diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index e0e94d01fb..73fd776468 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -44,7 +44,8 @@ set(SRCS Config/Graphics/GraphicsWindow.cpp Config/Graphics/SoftwareRendererWidget.cpp Config/InfoWidget.cpp - Config/LoggerWidget.cpp + Config/LogConfigWidget.cpp + Config/LogWidget.cpp Config/Mapping/GCKeyboardEmu.cpp Config/Mapping/GCPadEmu.cpp Config/Mapping/GCPadWiiU.cpp diff --git a/Source/Core/DolphinQt2/Config/LogConfigWidget.cpp b/Source/Core/DolphinQt2/Config/LogConfigWidget.cpp new file mode 100644 index 0000000000..326eb50812 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/LogConfigWidget.cpp @@ -0,0 +1,198 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/LogConfigWidget.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "Common/FileUtil.h" +#include "Common/Logging/LogManager.h" +#include "Core/ConfigManager.h" +#include "DolphinQt2/Settings.h" + +LogConfigWidget::LogConfigWidget(QWidget* parent) : QDockWidget(parent) +{ + setWindowTitle(tr("Log Configuration")); + setHidden(!Settings::Instance().IsLogConfigVisible()); + setAllowedAreas(Qt::AllDockWidgetAreas); + + CreateWidgets(); + LoadSettings(); + ConnectWidgets(); +} + +LogConfigWidget::~LogConfigWidget() +{ + SaveSettings(); +} + +void LogConfigWidget::CreateWidgets() +{ + auto* layout = new QVBoxLayout; + + auto* verbosity = new QGroupBox(tr("Verbosity")); + auto* verbosity_layout = new QVBoxLayout; + verbosity->setLayout(verbosity_layout); + m_verbosity_notice = new QRadioButton(tr("Notice")); + m_verbosity_error = new QRadioButton(tr("Error")); + m_verbosity_warning = new QRadioButton(tr("Warning")); + m_verbosity_info = new QRadioButton(tr("Info")); + + auto* outputs = new QGroupBox(tr("Logger Outputs")); + auto* outputs_layout = new QVBoxLayout; + outputs->setLayout(outputs_layout); + m_out_file = new QCheckBox(tr("Write to File")); + m_out_console = new QCheckBox(tr("Write to Console")); + m_out_window = new QCheckBox(tr("Write to Window")); + + auto* types = new QGroupBox(tr("Log Types")); + auto* types_layout = new QVBoxLayout; + types->setLayout(types_layout); + m_types_toggle = new QPushButton(tr("Toggle All Log Types")); + m_types_list = new QListWidget; + + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) + { + QListWidgetItem* widget = new QListWidgetItem(QString::fromStdString( + LogManager::GetInstance()->GetFullName(static_cast(i)))); + widget->setCheckState(Qt::Unchecked); + m_types_list->addItem(widget); + } + + layout->addWidget(verbosity); + verbosity_layout->addWidget(m_verbosity_notice); + verbosity_layout->addWidget(m_verbosity_error); + verbosity_layout->addWidget(m_verbosity_warning); + verbosity_layout->addWidget(m_verbosity_info); + + layout->addWidget(outputs); + outputs_layout->addWidget(m_out_file); + outputs_layout->addWidget(m_out_console); + outputs_layout->addWidget(m_out_window); + + layout->addWidget(types); + types_layout->addWidget(m_types_toggle); + types_layout->addWidget(m_types_list); + + QWidget* widget = new QWidget; + widget->setLayout(layout); + + setWidget(widget); +} + +void LogConfigWidget::ConnectWidgets() +{ + // Configuration + connect(m_verbosity_notice, &QRadioButton::toggled, this, &LogConfigWidget::SaveSettings); + connect(m_verbosity_error, &QRadioButton::toggled, this, &LogConfigWidget::SaveSettings); + connect(m_verbosity_warning, &QRadioButton::toggled, this, &LogConfigWidget::SaveSettings); + connect(m_verbosity_info, &QRadioButton::toggled, this, &LogConfigWidget::SaveSettings); + + connect(m_out_file, &QCheckBox::toggled, this, &LogConfigWidget::SaveSettings); + connect(m_out_console, &QCheckBox::toggled, this, &LogConfigWidget::SaveSettings); + connect(m_out_window, &QCheckBox::toggled, this, &LogConfigWidget::SaveSettings); + + connect(m_types_toggle, &QPushButton::clicked, [this] { + m_all_enabled = !m_all_enabled; + + // Don't save every time we change an item + m_block_save = true; + + for (int i = 0; i < m_types_list->count(); i++) + m_types_list->item(i)->setCheckState(m_all_enabled ? Qt::Checked : Qt::Unchecked); + + m_block_save = false; + + SaveSettings(); + }); + + connect(m_types_list, &QListWidget::itemChanged, this, &LogConfigWidget::SaveSettings); + + connect(&Settings::Instance(), &Settings::LogConfigVisibilityChanged, this, + [this](bool visible) { setHidden(!visible); }); +} + +void LogConfigWidget::LoadSettings() +{ + auto* logmanager = LogManager::GetInstance(); + QSettings settings; + + restoreGeometry(settings.value(QStringLiteral("logconfigwidget/geometry")).toByteArray()); + setFloating(settings.value(QStringLiteral("logconfigwidget/floating")).toBool()); + + // Config - Verbosity + int verbosity = logmanager->GetLogLevel(); + m_verbosity_notice->setChecked(verbosity == 1); + m_verbosity_error->setChecked(verbosity == 2); + m_verbosity_warning->setChecked(verbosity == 3); + m_verbosity_info->setChecked(verbosity == 4); + + // Config - Outputs + m_out_file->setChecked(logmanager->IsListenerEnabled(LogListener::FILE_LISTENER)); + m_out_console->setChecked(logmanager->IsListenerEnabled(LogListener::CONSOLE_LISTENER)); + m_out_window->setChecked(logmanager->IsListenerEnabled(LogListener::LOG_WINDOW_LISTENER)); + + // Config - Log Types + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + { + bool log_enabled = LogManager::GetInstance()->IsEnabled(static_cast(i)); + + if (!log_enabled) + m_all_enabled = false; + + m_types_list->item(i)->setCheckState(log_enabled ? Qt::Checked : Qt::Unchecked); + } +} + +void LogConfigWidget::SaveSettings() +{ + if (m_block_save) + return; + + QSettings settings; + + settings.setValue(QStringLiteral("logconfigwidget/geometry"), saveGeometry()); + settings.setValue(QStringLiteral("logconfigwidget/floating"), isFloating()); + + // Config - Verbosity + int verbosity = 1; + + if (m_verbosity_notice->isChecked()) + verbosity = 1; + + if (m_verbosity_error->isChecked()) + verbosity = 2; + + if (m_verbosity_warning->isChecked()) + verbosity = 3; + + if (m_verbosity_info->isChecked()) + verbosity = 4; + + // Config - Verbosity + LogManager::GetInstance()->SetLogLevel(static_cast(verbosity)); + + // Config - Outputs + LogManager::GetInstance()->EnableListener(LogListener::FILE_LISTENER, m_out_file->isChecked()); + LogManager::GetInstance()->EnableListener(LogListener::CONSOLE_LISTENER, + m_out_console->isChecked()); + LogManager::GetInstance()->EnableListener(LogListener::LOG_WINDOW_LISTENER, + m_out_window->isChecked()); + // Config - Log Types + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + { + const auto type = static_cast(i); + bool enabled = m_types_list->item(i)->checkState() == Qt::Checked; + bool was_enabled = LogManager::GetInstance()->IsEnabled(type); + + if (enabled != was_enabled) + LogManager::GetInstance()->SetEnable(type, enabled); + } +} diff --git a/Source/Core/DolphinQt2/Config/LogConfigWidget.h b/Source/Core/DolphinQt2/Config/LogConfigWidget.h new file mode 100644 index 0000000000..94a0d241b6 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/LogConfigWidget.h @@ -0,0 +1,40 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class QCheckBox; +class QListWidget; +class QPushButton; +class QRadioButton; +class QVBoxLayout; + +class LogConfigWidget final : public QDockWidget +{ + Q_OBJECT +public: + explicit LogConfigWidget(QWidget* parent = nullptr); + ~LogConfigWidget(); + +private: + void CreateWidgets(); + void ConnectWidgets(); + void LoadSettings(); + void SaveSettings(); + + QRadioButton* m_verbosity_notice; + QRadioButton* m_verbosity_error; + QRadioButton* m_verbosity_warning; + QRadioButton* m_verbosity_info; + QCheckBox* m_out_file; + QCheckBox* m_out_console; + QCheckBox* m_out_window; + QPushButton* m_types_toggle; + QListWidget* m_types_list; + + bool m_all_enabled = true; + bool m_block_save = false; +}; diff --git a/Source/Core/DolphinQt2/Config/LogWidget.cpp b/Source/Core/DolphinQt2/Config/LogWidget.cpp new file mode 100644 index 0000000000..d31203371e --- /dev/null +++ b/Source/Core/DolphinQt2/Config/LogWidget.cpp @@ -0,0 +1,209 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/LogWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/FileUtil.h" +#include "Core/ConfigManager.h" +#include "DolphinQt2/Settings.h" + +// Delay in ms between calls of UpdateLog() +constexpr int UPDATE_LOG_DELAY = 100; +// Maximum lines to process at a time +constexpr int MAX_LOG_LINES = 200; +// Timestamp length +constexpr int TIMESTAMP_LENGTH = 10; + +LogWidget::LogWidget(QWidget* parent) : QDockWidget(parent), m_timer(new QTimer(this)) +{ + setWindowTitle(tr("Log")); + setHidden(!Settings::Instance().IsLogVisible()); + setAllowedAreas(Qt::AllDockWidgetAreas); + + CreateWidgets(); + LoadSettings(); + + ConnectWidgets(); + + connect(m_timer, &QTimer::timeout, this, &LogWidget::UpdateLog); + m_timer->start(UPDATE_LOG_DELAY); + + LogManager::GetInstance()->RegisterListener(LogListener::LOG_WINDOW_LISTENER, this); +} + +LogWidget::~LogWidget() +{ + SaveSettings(); + + LogManager::GetInstance()->RegisterListener(LogListener::LOG_WINDOW_LISTENER, nullptr); +} + +void LogWidget::UpdateLog() +{ + std::lock_guard lock(m_log_mutex); + + if (m_log_queue.empty()) + return; + + auto* vscroll = m_log_text->verticalScrollBar(); + auto* hscroll = m_log_text->horizontalScrollBar(); + + // If the vertical scrollbar is within 50 units of the maximum value, count it as being at the + // bottom + bool vscroll_bottom = vscroll->maximum() - vscroll->value() < 50; + + int old_horizontal = hscroll->value(); + int old_vertical = vscroll->value(); + + for (int i = 0; !m_log_queue.empty() && i < MAX_LOG_LINES; i++) + { + m_log_text->append(m_log_queue.front()); + m_log_queue.pop(); + } + + if (hscroll->value() != old_horizontal) + hscroll->setValue(old_horizontal); + + if (vscroll->value() != old_vertical) + { + if (vscroll_bottom) + vscroll->setValue(vscroll->maximum()); + else + vscroll->setValue(old_vertical); + } +} + +void LogWidget::UpdateFont() +{ + QFont f; + + switch (m_log_font->currentIndex()) + { + case 0: // Default font + break; + case 1: // Monospace font + f = QFont(QStringLiteral("Monospace")); + f.setStyleHint(QFont::TypeWriter); + break; + } + m_log_text->setFont(f); +} + +void LogWidget::CreateWidgets() +{ + // Log + m_tab_log = new QWidget; + m_log_text = new QTextEdit; + m_log_wrap = new QCheckBox(tr("Word Wrap")); + m_log_font = new QComboBox; + m_log_clear = new QPushButton(tr("Clear")); + + m_log_font->addItems({tr("Default Font"), tr("Monospaced Font")}); + + auto* log_layout = new QGridLayout; + m_tab_log->setLayout(log_layout); + log_layout->addWidget(m_log_wrap, 0, 0); + log_layout->addWidget(m_log_font, 0, 1); + log_layout->addWidget(m_log_clear, 0, 2); + log_layout->addWidget(m_log_text, 1, 0, 1, -1); + + QWidget* widget = new QWidget; + widget->setLayout(log_layout); + + setWidget(widget); + + m_log_text->setReadOnly(true); + + QPalette palette = m_log_text->palette(); + palette.setColor(QPalette::Base, Qt::black); + palette.setColor(QPalette::Text, Qt::white); + m_log_text->setPalette(palette); +} + +void LogWidget::ConnectWidgets() +{ + connect(m_log_clear, &QPushButton::clicked, m_log_text, &QTextEdit::clear); + connect(m_log_wrap, &QCheckBox::toggled, this, &LogWidget::SaveSettings); + connect(m_log_font, static_cast(&QComboBox::currentIndexChanged), this, + &LogWidget::SaveSettings); + connect(this, &QDockWidget::topLevelChanged, this, &LogWidget::SaveSettings); + connect(&Settings::Instance(), &Settings::LogVisibilityChanged, this, + [this](bool visible) { setHidden(!visible); }); +} + +void LogWidget::LoadSettings() +{ + QSettings settings; + + restoreGeometry(settings.value(QStringLiteral("logwidget/geometry")).toByteArray()); + setFloating(settings.value(QStringLiteral("logwidget/floating")).toBool()); + + // Log - Wrap Lines + m_log_wrap->setChecked(settings.value(QStringLiteral("logging/wraplines")).toBool()); + m_log_text->setLineWrapMode(m_log_wrap->isChecked() ? QTextEdit::WidgetWidth : QTextEdit::NoWrap); + + // Log - Font Selection + // Currently "Debugger Font" is not supported as there is no Qt Debugger, defaulting to Monospace + m_log_font->setCurrentIndex(std::min(settings.value(QStringLiteral("logging/font")).toInt(), 1)); + UpdateFont(); +} + +void LogWidget::SaveSettings() +{ + QSettings settings; + + settings.setValue(QStringLiteral("logwidget/geometry"), saveGeometry()); + settings.setValue(QStringLiteral("logwidget/floating"), isFloating()); + + // Log - Wrap Lines + settings.setValue(QStringLiteral("logging/wraplines"), m_log_wrap->isChecked()); + m_log_text->setLineWrapMode(m_log_wrap->isChecked() ? QTextEdit::WidgetWidth : QTextEdit::NoWrap); + + // Log - Font Selection + settings.setValue(QStringLiteral("logging/font"), m_log_font->currentIndex()); + UpdateFont(); +} + +void LogWidget::Log(LogTypes::LOG_LEVELS level, const char* text) +{ + std::lock_guard lock(m_log_mutex); + + const char* color = "white"; + + switch (level) + { + case LogTypes::LOG_LEVELS::LERROR: + color = "red"; + break; + case LogTypes::LOG_LEVELS::LWARNING: + color = "yellow"; + break; + case LogTypes::LOG_LEVELS::LNOTICE: + color = "green"; + break; + case LogTypes::LOG_LEVELS::LINFO: + color = "cyan"; + break; + case LogTypes::LOG_LEVELS::LDEBUG: + color = "lightgrey"; + break; + } + + m_log_queue.push(QStringLiteral("%1 %3") + .arg(QString::fromStdString(std::string(text).substr(0, TIMESTAMP_LENGTH)), + QString::fromStdString(color), + QString::fromStdString(std::string(text).substr(TIMESTAMP_LENGTH)))); +} diff --git a/Source/Core/DolphinQt2/Config/LoggerWidget.h b/Source/Core/DolphinQt2/Config/LogWidget.h similarity index 52% rename from Source/Core/DolphinQt2/Config/LoggerWidget.h rename to Source/Core/DolphinQt2/Config/LogWidget.h index 958dcbb8f4..193269d142 100644 --- a/Source/Core/DolphinQt2/Config/LoggerWidget.h +++ b/Source/Core/DolphinQt2/Config/LogWidget.h @@ -12,36 +12,27 @@ #include "Common/Logging/LogManager.h" class QCheckBox; -class QCloseEvent; class QComboBox; -class QListWidget; class QPushButton; -class QRadioButton; class QVBoxLayout; -class QTabWidget; class QTextEdit; class QTimer; -class LoggerWidget final : public QDockWidget, LogListener +class LogWidget final : public QDockWidget, LogListener { Q_OBJECT public: - explicit LoggerWidget(QWidget* parent = nullptr); - ~LoggerWidget(); - - bool eventFilter(QObject* object, QEvent* event) override; + explicit LogWidget(QWidget* parent = nullptr); + ~LogWidget(); private: void UpdateLog(); void UpdateFont(); void CreateWidgets(); void ConnectWidgets(); - void CreateMainLayout(); void LoadSettings(); void SaveSettings(); - void OnTabVisibilityChanged(); - void Log(LogTypes::LOG_LEVELS level, const char* text) override; // Log @@ -49,27 +40,11 @@ private: QComboBox* m_log_font; QPushButton* m_log_clear; QVBoxLayout* m_main_layout; - QTabWidget* m_tab_widget; QTextEdit* m_log_text; QWidget* m_tab_log; - // Configuration - QWidget* m_tab_config; - QRadioButton* m_verbosity_notice; - QRadioButton* m_verbosity_error; - QRadioButton* m_verbosity_warning; - QRadioButton* m_verbosity_info; - QCheckBox* m_out_file; - QCheckBox* m_out_console; - QCheckBox* m_out_window; - QPushButton* m_types_toggle; - QListWidget* m_types_list; - QTimer* m_timer; std::mutex m_log_mutex; std::queue m_log_queue; - - bool m_all_enabled = true; - bool m_block_save = false; }; diff --git a/Source/Core/DolphinQt2/Config/LoggerWidget.cpp b/Source/Core/DolphinQt2/Config/LoggerWidget.cpp deleted file mode 100644 index 00eb1ce7eb..0000000000 --- a/Source/Core/DolphinQt2/Config/LoggerWidget.cpp +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "DolphinQt2/Config/LoggerWidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Common/FileUtil.h" -#include "Core/ConfigManager.h" -#include "DolphinQt2/Settings.h" - -// Delay in ms between calls of UpdateLog() -constexpr int UPDATE_LOG_DELAY = 100; -// Maximum lines to process at a time -constexpr int MAX_LOG_LINES = 200; -// Timestamp length -constexpr int TIMESTAMP_LENGTH = 10; - -LoggerWidget::LoggerWidget(QWidget* parent) - : QDockWidget(tr("Logging"), parent), m_timer(new QTimer(this)) -{ - setAllowedAreas(Qt::AllDockWidgetAreas); - - CreateWidgets(); - CreateMainLayout(); - LoadSettings(); - - ConnectWidgets(); - OnTabVisibilityChanged(); - - LogManager::GetInstance()->RegisterListener(LogListener::LOG_WINDOW_LISTENER, this); - - connect(m_timer, &QTimer::timeout, this, &LoggerWidget::UpdateLog); - connect(&Settings::Instance(), &Settings::LogVisibilityChanged, this, - &LoggerWidget::OnTabVisibilityChanged); - connect(&Settings::Instance(), &Settings::LogConfigVisibilityChanged, this, - &LoggerWidget::OnTabVisibilityChanged); - - m_timer->start(UPDATE_LOG_DELAY); - - QSettings settings; - - restoreGeometry(settings.value(QStringLiteral("logging/geometry")).toByteArray()); - setFloating(settings.value(QStringLiteral("logging/floating")).toBool()); - - installEventFilter(this); -} - -LoggerWidget::~LoggerWidget() -{ - SaveSettings(); - - LogManager::GetInstance()->RegisterListener(LogListener::LOG_WINDOW_LISTENER, nullptr); -} - -void LoggerWidget::UpdateLog() -{ - std::lock_guard lock(m_log_mutex); - - if (m_log_queue.empty()) - return; - - auto* vscroll = m_log_text->verticalScrollBar(); - auto* hscroll = m_log_text->horizontalScrollBar(); - - // If the vertical scrollbar is within 50 units of the maximum value, count it as being at the - // bottom - bool vscroll_bottom = vscroll->maximum() - vscroll->value() < 50; - - int old_horizontal = hscroll->value(); - int old_vertical = vscroll->value(); - - for (int i = 0; !m_log_queue.empty() && i < MAX_LOG_LINES; i++) - { - m_log_text->append(m_log_queue.front()); - m_log_queue.pop(); - } - - if (hscroll->value() != old_horizontal) - hscroll->setValue(old_horizontal); - - if (vscroll->value() != old_vertical) - { - if (vscroll_bottom) - vscroll->setValue(vscroll->maximum()); - else - vscroll->setValue(old_vertical); - } -} - -void LoggerWidget::UpdateFont() -{ - QFont f; - - switch (m_log_font->currentIndex()) - { - case 0: // Default font - break; - case 1: // Monospace font - f = QFont(QStringLiteral("Monospace")); - f.setStyleHint(QFont::TypeWriter); - break; - } - m_log_text->setFont(f); -} - -void LoggerWidget::CreateWidgets() -{ - m_tab_widget = new QTabWidget; - - // Log - m_tab_log = new QWidget; - m_log_text = new QTextEdit; - m_log_wrap = new QCheckBox(tr("Word Wrap")); - m_log_font = new QComboBox; - m_log_clear = new QPushButton(tr("Clear")); - - m_log_font->addItems({tr("Default Font"), tr("Monospaced Font")}); - - auto* log_layout = new QGridLayout; - m_tab_log->setLayout(log_layout); - log_layout->addWidget(m_log_wrap, 0, 0); - log_layout->addWidget(m_log_font, 0, 1); - log_layout->addWidget(m_log_clear, 0, 2); - log_layout->addWidget(m_log_text, 1, 0, 1, -1); - - m_log_text->setReadOnly(true); - - QPalette palette = m_log_text->palette(); - palette.setColor(QPalette::Base, Qt::black); - palette.setColor(QPalette::Text, Qt::white); - m_log_text->setPalette(palette); - - // Configuration - m_tab_config = new QWidget(); - auto* config_layout = new QVBoxLayout; - m_tab_config->setLayout(config_layout); - - auto* config_verbosity = new QGroupBox(tr("Verbosity")); - auto* verbosity_layout = new QVBoxLayout; - config_verbosity->setLayout(verbosity_layout); - m_verbosity_notice = new QRadioButton(tr("Notice")); - m_verbosity_error = new QRadioButton(tr("Error")); - m_verbosity_warning = new QRadioButton(tr("Warning")); - m_verbosity_info = new QRadioButton(tr("Info")); - - auto* config_outputs = new QGroupBox(tr("Logger Outputs")); - auto* outputs_layout = new QVBoxLayout; - config_outputs->setLayout(outputs_layout); - m_out_file = new QCheckBox(tr("Write to File")); - m_out_console = new QCheckBox(tr("Write to Console")); - m_out_window = new QCheckBox(tr("Write to Window")); - - auto* config_types = new QGroupBox(tr("Log Types")); - auto* types_layout = new QVBoxLayout; - config_types->setLayout(types_layout); - m_types_toggle = new QPushButton(tr("Toggle All Log Types")); - m_types_list = new QListWidget; - - for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) - { - QListWidgetItem* widget = new QListWidgetItem(QString::fromStdString( - LogManager::GetInstance()->GetFullName(static_cast(i)))); - widget->setCheckState(Qt::Unchecked); - m_types_list->addItem(widget); - } - - config_layout->addWidget(config_verbosity); - verbosity_layout->addWidget(m_verbosity_notice); - verbosity_layout->addWidget(m_verbosity_error); - verbosity_layout->addWidget(m_verbosity_warning); - verbosity_layout->addWidget(m_verbosity_info); - - config_layout->addWidget(config_outputs); - outputs_layout->addWidget(m_out_file); - outputs_layout->addWidget(m_out_console); - outputs_layout->addWidget(m_out_window); - - config_layout->addWidget(config_types); - types_layout->addWidget(m_types_toggle); - types_layout->addWidget(m_types_list); -} - -void LoggerWidget::CreateMainLayout() -{ - QWidget* widget = new QWidget; - QVBoxLayout* layout = new QVBoxLayout; - - widget->setLayout(layout); - layout->addWidget(m_tab_widget); - - setWidget(widget); -} - -void LoggerWidget::ConnectWidgets() -{ - // Configuration - connect(m_verbosity_notice, &QRadioButton::toggled, this, &LoggerWidget::SaveSettings); - connect(m_verbosity_error, &QRadioButton::toggled, this, &LoggerWidget::SaveSettings); - connect(m_verbosity_warning, &QRadioButton::toggled, this, &LoggerWidget::SaveSettings); - connect(m_verbosity_info, &QRadioButton::toggled, this, &LoggerWidget::SaveSettings); - - connect(m_out_file, &QCheckBox::toggled, this, &LoggerWidget::SaveSettings); - connect(m_out_console, &QCheckBox::toggled, this, &LoggerWidget::SaveSettings); - connect(m_out_window, &QCheckBox::toggled, this, &LoggerWidget::SaveSettings); - - connect(m_types_toggle, &QPushButton::clicked, [this] { - m_all_enabled = !m_all_enabled; - - // Don't save every time we change an item - m_block_save = true; - - for (int i = 0; i < m_types_list->count(); i++) - m_types_list->item(i)->setCheckState(m_all_enabled ? Qt::Checked : Qt::Unchecked); - - m_block_save = false; - - SaveSettings(); - }); - - connect(m_types_list, &QListWidget::itemChanged, this, &LoggerWidget::SaveSettings); - - // Log - connect(m_log_clear, &QPushButton::clicked, m_log_text, &QTextEdit::clear); - connect(m_log_wrap, &QCheckBox::toggled, this, &LoggerWidget::SaveSettings); - connect(m_log_font, static_cast(&QComboBox::currentIndexChanged), this, - &LoggerWidget::SaveSettings); - - // Window tracking - connect(this, &QDockWidget::topLevelChanged, this, &LoggerWidget::SaveSettings); -} - -void LoggerWidget::LoadSettings() -{ - auto* logmanager = LogManager::GetInstance(); - QSettings settings; - - // Config - Verbosity - int verbosity = logmanager->GetLogLevel(); - m_verbosity_notice->setChecked(verbosity == 1); - m_verbosity_error->setChecked(verbosity == 2); - m_verbosity_warning->setChecked(verbosity == 3); - m_verbosity_info->setChecked(verbosity == 4); - - // Config - Outputs - m_out_file->setChecked(logmanager->IsListenerEnabled(LogListener::FILE_LISTENER)); - m_out_console->setChecked(logmanager->IsListenerEnabled(LogListener::CONSOLE_LISTENER)); - m_out_window->setChecked(logmanager->IsListenerEnabled(LogListener::LOG_WINDOW_LISTENER)); - - // Config - Log Types - for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) - { - bool log_enabled = LogManager::GetInstance()->IsEnabled(static_cast(i)); - - if (!log_enabled) - m_all_enabled = false; - - m_types_list->item(i)->setCheckState(log_enabled ? Qt::Checked : Qt::Unchecked); - } - - // Log - Wrap Lines - m_log_wrap->setChecked(settings.value(QStringLiteral("logging/wraplines")).toBool()); - m_log_text->setLineWrapMode(m_log_wrap->isChecked() ? QTextEdit::WidgetWidth : QTextEdit::NoWrap); - - // Log - Font Selection - // Currently "Debugger Font" is not supported as there is no Qt Debugger, defaulting to Monospace - m_log_font->setCurrentIndex(std::min(settings.value(QStringLiteral("logging/font")).toInt(), 1)); - UpdateFont(); -} - -void LoggerWidget::SaveSettings() -{ - if (m_block_save) - return; - - QSettings settings; - - // Config - Verbosity - int verbosity = 1; - - if (m_verbosity_notice->isChecked()) - verbosity = 1; - - if (m_verbosity_error->isChecked()) - verbosity = 2; - - if (m_verbosity_warning->isChecked()) - verbosity = 3; - - if (m_verbosity_info->isChecked()) - verbosity = 4; - - // Config - Verbosity - LogManager::GetInstance()->SetLogLevel(static_cast(verbosity)); - - // Config - Outputs - LogManager::GetInstance()->EnableListener(LogListener::FILE_LISTENER, m_out_file->isChecked()); - LogManager::GetInstance()->EnableListener(LogListener::CONSOLE_LISTENER, - m_out_console->isChecked()); - LogManager::GetInstance()->EnableListener(LogListener::LOG_WINDOW_LISTENER, - m_out_window->isChecked()); - // Config - Log Types - for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) - { - const auto type = static_cast(i); - bool enabled = m_types_list->item(i)->checkState() == Qt::Checked; - bool was_enabled = LogManager::GetInstance()->IsEnabled(type); - - if (enabled != was_enabled) - LogManager::GetInstance()->SetEnable(type, enabled); - } - - // Log - Wrap Lines - settings.setValue(QStringLiteral("logging/wraplines"), m_log_wrap->isChecked()); - m_log_text->setLineWrapMode(m_log_wrap->isChecked() ? QTextEdit::WidgetWidth : QTextEdit::NoWrap); - - // Log - Font Selection - settings.setValue(QStringLiteral("logging/font"), m_log_font->currentIndex()); - UpdateFont(); - - // Save window geometry - settings.setValue(QStringLiteral("logging/geometry"), saveGeometry()); - settings.setValue(QStringLiteral("logging/floating"), isFloating()); -} - -void LoggerWidget::OnTabVisibilityChanged() -{ - bool log_visible = Settings::Instance().IsLogVisible(); - bool config_visible = Settings::Instance().IsLogConfigVisible(); - - m_tab_widget->clear(); - - if (log_visible) - m_tab_widget->addTab(m_tab_log, tr("Log")); - - if (config_visible) - m_tab_widget->addTab(m_tab_config, tr("Configuration")); - - if (!log_visible && !config_visible) - hide(); - else - show(); -} - -void LoggerWidget::Log(LogTypes::LOG_LEVELS level, const char* text) -{ - std::lock_guard lock(m_log_mutex); - - const char* color = "white"; - - switch (level) - { - case LogTypes::LOG_LEVELS::LERROR: - color = "red"; - break; - case LogTypes::LOG_LEVELS::LWARNING: - color = "yellow"; - break; - case LogTypes::LOG_LEVELS::LNOTICE: - color = "green"; - break; - case LogTypes::LOG_LEVELS::LINFO: - color = "cyan"; - break; - case LogTypes::LOG_LEVELS::LDEBUG: - color = "lightgrey"; - break; - } - - m_log_queue.push(QStringLiteral("%1 %3") - .arg(QString::fromStdString(std::string(text).substr(0, TIMESTAMP_LENGTH)), - QString::fromStdString(color), - QString::fromStdString(std::string(text).substr(TIMESTAMP_LENGTH)))); -} - -bool LoggerWidget::eventFilter(QObject* object, QEvent* event) -{ - QSettings settings; - - if (event->type() == QEvent::Hide || event->type() == QEvent::Resize || - event->type() == QEvent::Move) - { - SaveSettings(); - } - - if (event->type() == QEvent::Close) - { - Settings::Instance().SetLogVisible(false); - Settings::Instance().SetLogConfigVisible(false); - } - - return false; -} diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 319d34c552..be07c59b2a 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -66,7 +66,8 @@ - + + @@ -134,7 +135,8 @@ - + + @@ -184,7 +186,8 @@ - + + @@ -223,6 +226,8 @@ + + diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index 0331104e01..96616fd3b2 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -41,7 +41,8 @@ #include "DolphinQt2/AboutDialog.h" #include "DolphinQt2/Config/ControllersWindow.h" #include "DolphinQt2/Config/Graphics/GraphicsWindow.h" -#include "DolphinQt2/Config/LoggerWidget.h" +#include "DolphinQt2/Config/LogConfigWidget.h" +#include "DolphinQt2/Config/LogWidget.h" #include "DolphinQt2/Config/Mapping/MappingWindow.h" #include "DolphinQt2/Config/SettingsWindow.h" #include "DolphinQt2/Host.h" @@ -147,7 +148,8 @@ void MainWindow::CreateComponents() m_controllers_window = new ControllersWindow(this); m_settings_window = new SettingsWindow(this); m_hotkey_window = new MappingWindow(this, 0); - m_logger_widget = new LoggerWidget(this); + m_log_widget = new LogWidget(this); + m_log_config_widget = new LogConfigWidget(this); connect(this, &MainWindow::EmulationStarted, m_settings_window, &SettingsWindow::EmulationStarted); @@ -310,7 +312,12 @@ void MainWindow::ConnectStack() m_stack->addWidget(m_game_list); setCentralWidget(m_stack); - addDockWidget(Qt::RightDockWidgetArea, m_logger_widget); + + setTabPosition(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea, QTabWidget::North); + addDockWidget(Qt::RightDockWidgetArea, m_log_widget); + addDockWidget(Qt::RightDockWidgetArea, m_log_config_widget); + + tabifyDockWidget(m_log_widget, m_log_config_widget); } void MainWindow::Open() diff --git a/Source/Core/DolphinQt2/MainWindow.h b/Source/Core/DolphinQt2/MainWindow.h index 154bd7b75a..a30c5699d5 100644 --- a/Source/Core/DolphinQt2/MainWindow.h +++ b/Source/Core/DolphinQt2/MainWindow.h @@ -18,7 +18,8 @@ struct BootParameters; class HotkeyScheduler; -class LoggerWidget; +class LogConfigWidget; +class LogWidget; class MappingWindow; class NetPlayClient; class NetPlayDialog; @@ -136,5 +137,6 @@ private: NetPlayDialog* m_netplay_dialog; NetPlaySetupDialog* m_netplay_setup_dialog; GraphicsWindow* m_graphics_window; - LoggerWidget* m_logger_widget; + LogWidget* m_log_widget; + LogConfigWidget* m_log_config_widget; };