Merge pull request #2939 from cg2121/log-viewer

UI: Add log viewer window
master
Jim 2020-08-01 12:17:48 -07:00 committed by GitHub
commit 478f1de846
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 217 additions and 20 deletions

View File

@ -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)

View File

@ -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"

View File

@ -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
UI/log-viewer.cpp Normal file
View File

@ -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
UI/log-viewer.hpp Normal file
View File

@ -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();
};

View File

@ -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)

View File

@ -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()

View File

@ -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;