Clayton Groeneveld пре 5 година
родитељ
комит
040e445617
8 измењених фајлова са 217 додато и 20 уклоњено
  1. 4 2
      UI/CMakeLists.txt
  2. 2 0
      UI/data/locale/en-US.ini
  3. 11 0
      UI/forms/OBSBasic.ui
  4. 145 0
      UI/log-viewer.cpp
  5. 24 0
      UI/log-viewer.hpp
  6. 19 6
      UI/obs-app.cpp
  7. 9 12
      UI/window-basic-main.cpp
  8. 3 0
      UI/window-basic-main.hpp

+ 4 - 2
UI/CMakeLists.txt

@@ -244,7 +244,8 @@ set(obs_SOURCES
 	source-label.cpp
 	remote-text.cpp
 	audio-encoders.cpp
-	qt-wrappers.cpp)
+	qt-wrappers.cpp
+	log-viewer.cpp)
 
 set(obs_HEADERS
 	${obs_PLATFORM_HEADERS}
@@ -308,7 +309,8 @@ set(obs_HEADERS
 	remote-text.hpp
 	audio-encoders.hpp
 	qt-wrappers.hpp
-	clickable-label.hpp)
+	clickable-label.hpp
+	log-viewer.hpp)
 
 set(obs_importers_HEADERS
 	importers/importers.hpp)

+ 2 - 0
UI/data/locale/en-US.ini

@@ -94,6 +94,8 @@ Windowed="Windowed"
 Percent="Percent"
 AspectRatio="Aspect Ratio <b>%1:%2</b>"
 LockVolume="Lock Volume"
+LogViewer="Log Viewer"
+ShowOnStartup="Show on startup"
 
 # warning if program already open
 AlreadyRunning.Title="OBS is already running"

+ 11 - 0
UI/forms/OBSBasic.ui

@@ -1768,6 +1768,17 @@
     <string>Basic.MainMenu.View.SourceIcons</string>
    </property>
   </action>
+  <action name="toggleLog">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>LogViewer</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>

+ 145 - 0
UI/log-viewer.cpp

@@ -0,0 +1,145 @@
+#include <QFile>
+#include <QTextStream>
+#include <QScrollBar>
+#include <QFont>
+#include <QFontDatabase>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QLayout>
+#include <string>
+
+#include "log-viewer.hpp"
+#include "qt-wrappers.hpp"
+
+OBSLogViewer::OBSLogViewer(QWidget *parent) : QDialog(parent)
+{
+	setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+	QVBoxLayout *layout = new QVBoxLayout();
+	layout->setContentsMargins(0, 0, 0, 0);
+
+	const QFont fixedFont =
+		QFontDatabase::systemFont(QFontDatabase::FixedFont);
+
+	textArea = new QTextEdit();
+	textArea->setReadOnly(true);
+	textArea->setFont(fixedFont);
+
+	QHBoxLayout *buttonLayout = new QHBoxLayout();
+	QPushButton *clearButton = new QPushButton(QTStr("Clear"));
+	connect(clearButton, &QPushButton::clicked, this,
+		&OBSLogViewer::ClearText);
+	QPushButton *closeButton = new QPushButton(QTStr("Close"));
+	connect(closeButton, &QPushButton::clicked, this, &QDialog::hide);
+
+	QCheckBox *showStartup = new QCheckBox(QTStr("ShowOnStartup"));
+	showStartup->setChecked(ShowOnStartup());
+	connect(showStartup, SIGNAL(toggled(bool)), this,
+		SLOT(ToggleShowStartup(bool)));
+
+	buttonLayout->addSpacing(10);
+	buttonLayout->addWidget(showStartup);
+	buttonLayout->addStretch();
+	buttonLayout->addWidget(clearButton);
+	buttonLayout->addWidget(closeButton);
+	buttonLayout->addSpacing(10);
+	buttonLayout->setContentsMargins(0, 0, 0, 4);
+
+	layout->addWidget(textArea);
+	layout->addLayout(buttonLayout);
+	setLayout(layout);
+
+	setWindowTitle(QTStr("LogViewer"));
+	resize(800, 300);
+
+	const char *geom = config_get_string(App()->GlobalConfig(), "LogViewer",
+					     "geometry");
+
+	if (geom != nullptr) {
+		QByteArray ba = QByteArray::fromBase64(QByteArray(geom));
+		restoreGeometry(ba);
+	}
+
+	InitLog();
+}
+
+OBSLogViewer::~OBSLogViewer()
+{
+	config_set_string(App()->GlobalConfig(), "LogViewer", "geometry",
+			  saveGeometry().toBase64().constData());
+}
+
+void OBSLogViewer::ToggleShowStartup(bool checked)
+{
+	config_set_bool(App()->GlobalConfig(), "LogViewer", "ShowLogStartup",
+			checked);
+}
+
+bool OBSLogViewer::ShowOnStartup()
+{
+	return config_get_bool(App()->GlobalConfig(), "LogViewer",
+			       "ShowLogStartup");
+}
+
+extern QPointer<OBSLogViewer> obsLogViewer;
+
+void OBSLogViewer::InitLog()
+{
+	char logDir[512];
+	std::string path;
+
+	if (GetConfigPath(logDir, sizeof(logDir), "obs-studio/logs")) {
+		path += logDir;
+		path += "/";
+		path += App()->GetCurrentLog();
+	}
+
+	QFile file(QT_UTF8(path.c_str()));
+
+	if (file.open(QIODevice::ReadOnly)) {
+		QTextStream in(&file);
+
+		while (!in.atEnd()) {
+			QString line = in.readLine();
+			AddLine(LOG_INFO, line);
+		}
+
+		file.close();
+	}
+
+	obsLogViewer = this;
+}
+
+void OBSLogViewer::AddLine(int type, const QString &str)
+{
+	QString msg = str.toHtmlEscaped();
+
+	switch (type) {
+	case LOG_WARNING:
+		msg = QStringLiteral("<font color=\"#c08000\">") + msg +
+		      QStringLiteral("</font>");
+		break;
+	case LOG_ERROR:
+		msg = QStringLiteral("<font color=\"#c00000\">") + msg +
+		      QStringLiteral("</font>");
+		break;
+	}
+
+	QScrollBar *scroll = textArea->verticalScrollBar();
+	bool bottomScrolled = scroll->value() >= scroll->maximum() - 10;
+
+	if (bottomScrolled)
+		scroll->setValue(scroll->maximum());
+
+	QTextCursor newCursor = textArea->textCursor();
+	newCursor.movePosition(QTextCursor::End);
+	newCursor.insertHtml(msg + QStringLiteral("<br>"));
+
+	if (bottomScrolled)
+		scroll->setValue(scroll->maximum());
+}
+
+void OBSLogViewer::ClearText()
+{
+	textArea->clear();
+}

+ 24 - 0
UI/log-viewer.hpp

@@ -0,0 +1,24 @@
+#pragma once
+
+#include <QDialog>
+#include <QTextEdit>
+#include "obs-app.hpp"
+
+class OBSLogViewer : public QDialog {
+	Q_OBJECT
+
+	QPointer<QTextEdit> textArea;
+
+	void InitLog();
+
+private slots:
+	void AddLine(int type, const QString &text);
+	void ClearText();
+	void ToggleShowStartup(bool checked);
+
+public:
+	OBSLogViewer(QWidget *parent = 0);
+	~OBSLogViewer();
+
+	bool ShowOnStartup();
+};

+ 19 - 6
UI/obs-app.cpp

@@ -38,6 +38,7 @@
 
 #include "qt-wrappers.hpp"
 #include "obs-app.hpp"
+#include "log-viewer.hpp"
 #include "window-basic-main.hpp"
 #include "window-basic-settings.hpp"
 #include "crash-report.hpp"
@@ -89,6 +90,8 @@ string remuxFilename;
 
 bool restart = false;
 
+QPointer<OBSLogViewer> obsLogViewer;
+
 // GPU hint exports for AMD/NVIDIA laptops
 #ifdef _MSC_VER
 extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 1;
@@ -250,12 +253,22 @@ string CurrentDateTimeString()
 }
 
 static inline void LogString(fstream &logFile, const char *timeString,
-			     char *str)
+			     char *str, int log_level)
 {
-	logFile << timeString << str << endl;
+	string msg;
+	msg += timeString;
+	msg += str;
+
+	logFile << msg << endl;
+
+	if (!!obsLogViewer)
+		QMetaObject::invokeMethod(obsLogViewer.data(), "AddLine",
+					  Qt::QueuedConnection,
+					  Q_ARG(int, log_level),
+					  Q_ARG(QString, QString(msg.c_str())));
 }
 
-static inline void LogStringChunk(fstream &logFile, char *str)
+static inline void LogStringChunk(fstream &logFile, char *str, int log_level)
 {
 	char *nextLine = str;
 	string timeString = CurrentTimeString();
@@ -272,12 +285,12 @@ static inline void LogStringChunk(fstream &logFile, char *str)
 			nextLine[0] = 0;
 		}
 
-		LogString(logFile, timeString.c_str(), str);
+		LogString(logFile, timeString.c_str(), str, log_level);
 		nextLine++;
 		str = nextLine;
 	}
 
-	LogString(logFile, timeString.c_str(), str);
+	LogString(logFile, timeString.c_str(), str, log_level);
 }
 
 #define MAX_REPEATED_LINES 30
@@ -368,7 +381,7 @@ static void do_log(int log_level, const char *msg, va_list args, void *param)
 	if (log_level <= LOG_INFO || log_verbose) {
 		if (too_many_repeated_entries(logFile, msg, str))
 			return;
-		LogStringChunk(logFile, str);
+		LogStringChunk(logFile, str, log_level);
 	}
 
 #if defined(_WIN32) && defined(OBS_DEBUGBREAK_ON_ERROR)

+ 9 - 12
UI/window-basic-main.cpp

@@ -190,6 +190,9 @@ extern void RegisterRestreamAuth();
 OBSBasic::OBSBasic(QWidget *parent)
 	: OBSMainWindow(parent), ui(new Ui::OBSBasic)
 {
+	/* setup log viewer */
+	logView = new OBSLogViewer();
+
 	qRegisterMetaTypeStreamOperators<SignalContainer<OBSScene>>(
 		"SignalContainer<OBSScene>");
 
@@ -377,6 +380,7 @@ OBSBasic::OBSBasic(QWidget *parent)
 	}
 
 	QPoint curSize(width(), height());
+
 	QPoint statsDockSize(statsDock->width(), statsDock->height());
 	QPoint statsDockPos = curSize / 2 - statsDockSize / 2;
 	QPoint newPos = curPos + statsDockPos;
@@ -1926,6 +1930,9 @@ void OBSBasic::OnFirstLoad()
 #endif
 
 	Auth::Load();
+
+	if (logView && logView->ShowOnStartup())
+		logView->show();
 }
 
 void OBSBasic::DeferredSysTrayLoad(int requeueCount)
@@ -2398,6 +2405,7 @@ OBSBasic::~OBSBasic()
 		updateCheckThread->wait();
 
 	delete screenshotData;
+	delete logView;
 	delete multiviewProjectorMenu;
 	delete previewProjector;
 	delete studioProgramProjector;
@@ -5183,18 +5191,7 @@ void OBSBasic::on_actionUploadLastLog_triggered()
 
 void OBSBasic::on_actionViewCurrentLog_triggered()
 {
-	char logDir[512];
-	if (GetConfigPath(logDir, sizeof(logDir), "obs-studio/logs") <= 0)
-		return;
-
-	const char *log = App()->GetCurrentLog();
-
-	string path = logDir;
-	path += "/";
-	path += log;
-
-	QUrl url = QUrl::fromLocalFile(QT_UTF8(path.c_str()));
-	QDesktopServices::openUrl(url);
+	logView->setVisible(!logView->isVisible());
 }
 
 void OBSBasic::on_actionShowCrashLogs_triggered()

+ 3 - 0
UI/window-basic-main.hpp

@@ -34,6 +34,7 @@
 #include "window-projector.hpp"
 #include "window-basic-about.hpp"
 #include "auth-base.hpp"
+#include "log-viewer.hpp"
 
 #include <obs-frontend-internal.hpp>
 
@@ -210,6 +211,8 @@ private:
 	QPointer<QDockWidget> statsDock;
 	QPointer<OBSAbout> about;
 
+	OBSLogViewer *logView;
+
 	QPointer<QTimer> cpuUsageTimer;
 	QPointer<QTimer> diskFullTimer;