mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-20 05:05:40 -04:00
Qt: Add log window
This commit is contained in:
@ -111,6 +111,8 @@ set(SRCS
|
||||
inputbindingdialog.ui
|
||||
inputbindingwidgets.cpp
|
||||
inputbindingwidgets.h
|
||||
logwindow.cpp
|
||||
logwindow.h
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
mainwindow.ui
|
||||
|
@ -30,6 +30,7 @@
|
||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||
<ClCompile Include="inputbindingdialog.cpp" />
|
||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||
<ClCompile Include="logwindow.cpp" />
|
||||
<ClCompile Include="memoryviewwidget.cpp" />
|
||||
<ClCompile Include="displaywidget.cpp" />
|
||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||
@ -86,6 +87,7 @@
|
||||
<QtMoc Include="colorpickerbutton.h" />
|
||||
<ClInclude Include="controllersettingwidgetbinder.h" />
|
||||
<QtMoc Include="memoryviewwidget.h" />
|
||||
<QtMoc Include="logwindow.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="settingwidgetbinder.h" />
|
||||
@ -258,6 +260,7 @@
|
||||
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_inputbindingdialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_logwindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_memorycardsettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_memorycardeditordialog.cpp" />
|
||||
@ -388,4 +391,4 @@
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="..\..\dep\msvc\vsprops\Targets.props" />
|
||||
<Import Project="..\..\dep\msvc\vsprops\QtCompile.targets" />
|
||||
</Project>
|
||||
</Project>
|
@ -93,6 +93,9 @@
|
||||
<ClCompile Include="$(IntDir)moc_colorpickerbutton.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="setupwizarddialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_setupwizarddialog.cpp" />
|
||||
<ClCompile Include="logwindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_logwindow.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="qtutils.h" />
|
||||
@ -154,6 +157,7 @@
|
||||
<QtMoc Include="coverdownloaddialog.h" />
|
||||
<QtMoc Include="colorpickerbutton.h" />
|
||||
<QtMoc Include="setupwizarddialog.h" />
|
||||
<QtMoc Include="logwindow.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUi Include="consolesettingswidget.ui" />
|
||||
@ -262,4 +266,4 @@
|
||||
<Filter>translations</Filter>
|
||||
</QtTs>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
356
src/duckstation-qt/logwindow.cpp
Normal file
356
src/duckstation-qt/logwindow.cpp
Normal file
@ -0,0 +1,356 @@
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "logwindow.h"
|
||||
#include "mainwindow.h"
|
||||
#include "qthost.h"
|
||||
#include "settingwidgetbinder.h"
|
||||
|
||||
#include "util/host.h"
|
||||
|
||||
#include <QtCore/QLatin1StringView>
|
||||
#include <QtCore/QUtf8StringView>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QScrollBar>
|
||||
|
||||
LogWindow* g_log_window;
|
||||
|
||||
LogWindow::LogWindow(bool attach_to_main)
|
||||
: QMainWindow(), m_filter_names(Settings::GetLogFilters()), m_attached_to_main_window(attach_to_main)
|
||||
{
|
||||
// TODO: probably should save the size..
|
||||
resize(700, 400);
|
||||
|
||||
createUi();
|
||||
|
||||
Log::RegisterCallback(&LogWindow::logCallback, this);
|
||||
}
|
||||
|
||||
LogWindow::~LogWindow()
|
||||
{
|
||||
Log::UnregisterCallback(&LogWindow::logCallback, this);
|
||||
}
|
||||
|
||||
void LogWindow::updateSettings()
|
||||
{
|
||||
const bool new_enabled = Host::GetBaseBoolSettingValue("Logging", "LogToWindow", false);
|
||||
const bool attach_to_main = Host::GetBaseBoolSettingValue("Logging", "AttachLogWindowToMainWindow", true);
|
||||
const bool curr_enabled = (g_log_window != nullptr);
|
||||
if (new_enabled == curr_enabled)
|
||||
{
|
||||
if (g_log_window->m_attached_to_main_window != attach_to_main)
|
||||
{
|
||||
g_log_window->m_attached_to_main_window = attach_to_main;
|
||||
if (attach_to_main)
|
||||
g_log_window->reattachToMainWindow();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_enabled)
|
||||
{
|
||||
g_log_window = new LogWindow(attach_to_main);
|
||||
if (attach_to_main && g_main_window && g_main_window->isVisible())
|
||||
g_log_window->reattachToMainWindow();
|
||||
|
||||
g_log_window->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete g_log_window;
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::reattachToMainWindow()
|
||||
{
|
||||
// Skip when maximized.
|
||||
if (g_main_window->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen))
|
||||
return;
|
||||
|
||||
resize(width(), g_main_window->height());
|
||||
|
||||
const QPoint new_pos = g_main_window->pos() + QPoint(g_main_window->width() + 10, 0);
|
||||
if (pos() != new_pos)
|
||||
move(new_pos);
|
||||
}
|
||||
|
||||
void LogWindow::updateWindowTitle()
|
||||
{
|
||||
QString title;
|
||||
|
||||
const QString& serial = QtHost::GetCurrentGameSerial();
|
||||
|
||||
if (QtHost::IsSystemValid() && !serial.isEmpty())
|
||||
{
|
||||
const QFileInfo fi(QtHost::GetCurrentGamePath());
|
||||
title = tr("Log Window - %1 [%2]").arg(serial).arg(fi.fileName());
|
||||
}
|
||||
else
|
||||
{
|
||||
title = tr("Log Window");
|
||||
}
|
||||
|
||||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
void LogWindow::createUi()
|
||||
{
|
||||
QIcon icon;
|
||||
icon.addFile(QString::fromUtf8(":/icons/duck.png"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
setWindowIcon(icon);
|
||||
updateWindowTitle();
|
||||
|
||||
QAction* action;
|
||||
|
||||
QMenuBar* menu = new QMenuBar(this);
|
||||
setMenuBar(menu);
|
||||
|
||||
QMenu* log_menu = menu->addMenu("&Log");
|
||||
action = log_menu->addAction(tr("&Clear"));
|
||||
connect(action, &QAction::triggered, this, &LogWindow::onClearTriggered);
|
||||
action = log_menu->addAction(tr("&Save..."));
|
||||
connect(action, &QAction::triggered, this, &LogWindow::onSaveTriggered);
|
||||
|
||||
log_menu->addSeparator();
|
||||
|
||||
action = log_menu->addAction(tr("Cl&ose"));
|
||||
connect(action, &QAction::triggered, this, &LogWindow::close);
|
||||
|
||||
QMenu* settings_menu = menu->addMenu(tr("&Settings"));
|
||||
|
||||
action = settings_menu->addAction(tr("Log To &System Console"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "LogToConsole", false);
|
||||
|
||||
action = settings_menu->addAction(tr("Log To &Debug Console"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "LogToDebug", false);
|
||||
|
||||
action = settings_menu->addAction(tr("Log To &File"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "LogToFile", false);
|
||||
|
||||
settings_menu->addSeparator();
|
||||
|
||||
action = settings_menu->addAction(tr("Attach To &Main Window"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "AttachLogWindowToMainWindow", true);
|
||||
|
||||
action = settings_menu->addAction(tr("Show &Timestamps"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "LogTimestamps", true);
|
||||
|
||||
settings_menu->addSeparator();
|
||||
|
||||
m_level_menu = settings_menu->addMenu(tr("&Log Level"));
|
||||
for (u32 i = 0; i < static_cast<u32>(LOGLEVEL_COUNT); i++)
|
||||
{
|
||||
action = m_level_menu->addAction(QString::fromUtf8(Settings::GetLogLevelDisplayName(static_cast<LOGLEVEL>(i))));
|
||||
action->setCheckable(true);
|
||||
connect(action, &QAction::triggered, this, [this, i]() { setLogLevel(static_cast<LOGLEVEL>(i)); });
|
||||
}
|
||||
updateLogLevelUi();
|
||||
|
||||
QMenu* filters_menu = menu->addMenu(tr("&Filters"));
|
||||
populateFilters(filters_menu);
|
||||
|
||||
m_text = new QPlainTextEdit(this);
|
||||
m_text->setReadOnly(true);
|
||||
m_text->setUndoRedoEnabled(false);
|
||||
m_text->setTextInteractionFlags(Qt::TextSelectableByKeyboard);
|
||||
m_text->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
|
||||
#ifndef _WIN32
|
||||
QFont font("Monospace");
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
#else
|
||||
QFont font("Consolas");
|
||||
font.setPointSize(10);
|
||||
#endif
|
||||
m_text->setFont(font);
|
||||
|
||||
setCentralWidget(m_text);
|
||||
}
|
||||
|
||||
void LogWindow::updateLogLevelUi()
|
||||
{
|
||||
const u32 level = Settings::ParseLogLevelName(Host::GetBaseStringSettingValue("Logging", "LogLevel", "").c_str())
|
||||
.value_or(Settings::DEFAULT_LOG_LEVEL);
|
||||
|
||||
const QList<QAction*> actions = m_level_menu->actions();
|
||||
for (u32 i = 0; i < actions.size(); i++)
|
||||
actions[i]->setChecked(i == level);
|
||||
}
|
||||
|
||||
void LogWindow::setLogLevel(LOGLEVEL level)
|
||||
{
|
||||
Host::SetBaseStringSettingValue("Logging", "LogLevel", Settings::GetLogLevelName(level));
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->applySettings(false);
|
||||
}
|
||||
|
||||
void LogWindow::populateFilters(QMenu* filter_menu)
|
||||
{
|
||||
const std::string filters = Host::GetBaseStringSettingValue("Logging", "LogFilter", "");
|
||||
for (size_t i = 0; i < m_filter_names.size(); i++)
|
||||
{
|
||||
const char* filter = m_filter_names[i];
|
||||
const bool is_currently_filtered = (filters.find(filter) == std::string::npos);
|
||||
QAction* action = filter_menu->addAction(QString::fromUtf8(filter));
|
||||
action->setCheckable(action);
|
||||
action->setChecked(is_currently_filtered);
|
||||
connect(action, &QAction::triggered, this, [this, i](bool checked) { setChannelFiltered(i, !checked); });
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::setChannelFiltered(size_t index, bool enabled)
|
||||
{
|
||||
const char* filter = m_filter_names[index];
|
||||
const size_t filter_len = std::strlen(filter);
|
||||
|
||||
std::string filters = Host::GetBaseStringSettingValue("Logging", "LogFilter", "");
|
||||
const std::string::size_type pos = filters.find(filter);
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
if (pos == std::string::npos)
|
||||
return;
|
||||
|
||||
const size_t erase_count =
|
||||
filter_len + (((pos + filter_len) < filters.length() && filters[pos + filter_len] == ' ') ? 1 : 0);
|
||||
filters.erase(pos, erase_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos != std::string::npos)
|
||||
return;
|
||||
|
||||
if (!filters.empty() && filters.back() != ' ')
|
||||
filters.push_back(' ');
|
||||
filters.append(filter);
|
||||
}
|
||||
|
||||
Host::SetBaseStringSettingValue("Logging", "LogFilter", filters.c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->applySettings(false);
|
||||
}
|
||||
|
||||
void LogWindow::onClearTriggered()
|
||||
{
|
||||
m_text->clear();
|
||||
}
|
||||
|
||||
void LogWindow::onSaveTriggered()
|
||||
{
|
||||
const QString path = QFileDialog::getSaveFileName(this, tr("Select Log File"), QString(), tr("Log Files (*.txt)"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to open file for writing."));
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(m_text->toPlainText().toUtf8());
|
||||
file.close();
|
||||
|
||||
appendMessage(QLatin1StringView("LogWindow"), LOGLEVEL_INFO, tr("Log was written to %1.\n").arg(path));
|
||||
}
|
||||
|
||||
void LogWindow::logCallback(void* pUserParam, const char* channelName, const char* functionName, LOGLEVEL level,
|
||||
std::string_view message)
|
||||
{
|
||||
LogWindow* this_ptr = static_cast<LogWindow*>(pUserParam);
|
||||
|
||||
// TODO: Split message based on lines.
|
||||
// I don't like the memory allocations here either...
|
||||
|
||||
QString qmessage;
|
||||
qmessage.reserve(message.length() + 1);
|
||||
qmessage.append(QUtf8StringView(message.data(), message.length()));
|
||||
qmessage.append(QChar('\n'));
|
||||
|
||||
const QLatin1StringView qchannel((level <= LOGLEVEL_PERF) ? functionName : channelName);
|
||||
|
||||
if (g_emu_thread->isOnUIThread())
|
||||
{
|
||||
this_ptr->appendMessage(qchannel, level, qmessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(this_ptr, "appendMessage", Qt::QueuedConnection,
|
||||
Q_ARG(const QLatin1StringView&, qchannel), Q_ARG(quint32, static_cast<u32>(level)),
|
||||
Q_ARG(const QString&, qmessage));
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::appendMessage(const QLatin1StringView& channel, quint32 level, const QString& message)
|
||||
{
|
||||
QTextCursor temp_cursor = m_text->textCursor();
|
||||
QScrollBar* scrollbar = m_text->verticalScrollBar();
|
||||
const bool cursor_at_end = temp_cursor.atEnd();
|
||||
const bool scroll_at_end = scrollbar->sliderPosition() == scrollbar->maximum();
|
||||
|
||||
temp_cursor.movePosition(QTextCursor::End);
|
||||
|
||||
{
|
||||
static constexpr const QChar level_characters[LOGLEVEL_COUNT] = {'X', 'E', 'W', 'P', 'I', 'V', 'D', 'R', 'B', 'T'};
|
||||
static constexpr const QColor level_colors[LOGLEVEL_COUNT] = {
|
||||
QColor(255, 255, 255), // NONE
|
||||
QColor(0xE7, 0x48, 0x56), // ERROR, Red Intensity
|
||||
QColor(0xF9, 0xF1, 0xA5), // WARNING, Yellow Intensity
|
||||
QColor(0xB4, 0x00, 0x9E), // PERF, Purple Intensity
|
||||
QColor(0xF2, 0xF2, 0xF2), // INFO, White Intensity
|
||||
QColor(0x16, 0xC6, 0x0C), // VERBOSE, Green Intensity
|
||||
QColor(0xCC, 0xCC, 0xCC), // DEV, White
|
||||
QColor(0x61, 0xD6, 0xD6), // PROFILE, Cyan Intensity
|
||||
QColor(0x13, 0xA1, 0x0E), // DEBUG, Green
|
||||
QColor(0x00, 0x37, 0xDA), // TRACE, Blue
|
||||
};
|
||||
static constexpr const QColor timestamp_color = QColor(0xcc, 0xcc, 0xcc);
|
||||
static constexpr const QColor channel_color = QColor(0xf2, 0xf2, 0xf2);
|
||||
|
||||
QTextCharFormat format = temp_cursor.charFormat();
|
||||
|
||||
if (g_settings.log_timestamps)
|
||||
{
|
||||
const float message_time = Log::GetCurrentMessageTime();
|
||||
const QString qtimestamp = QStringLiteral("[%1] ").arg(message_time, 10, 'f', 4);
|
||||
format.setForeground(QBrush(timestamp_color));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(qtimestamp);
|
||||
}
|
||||
|
||||
const QString qchannel = (level <= LOGLEVEL_PERF) ?
|
||||
QStringLiteral("%1(%2): ").arg(level_characters[level]).arg(channel) :
|
||||
QStringLiteral("%1/%2: ").arg(level_characters[level]).arg(channel);
|
||||
format.setForeground(QBrush(channel_color));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(qchannel);
|
||||
|
||||
// message has \n already
|
||||
format.setForeground(QBrush(level_colors[level]));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(message);
|
||||
}
|
||||
|
||||
if (cursor_at_end)
|
||||
{
|
||||
if (scroll_at_end)
|
||||
{
|
||||
m_text->setTextCursor(temp_cursor);
|
||||
scrollbar->setSliderPosition(scrollbar->maximum());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't let changing the cursor affect the scroll bar...
|
||||
const int pos = scrollbar->sliderPosition();
|
||||
m_text->setTextCursor(temp_cursor);
|
||||
scrollbar->setSliderPosition(pos);
|
||||
}
|
||||
}
|
||||
}
|
50
src/duckstation-qt/logwindow.h
Normal file
50
src/duckstation-qt/logwindow.h
Normal file
@ -0,0 +1,50 @@
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/log.h"
|
||||
|
||||
#include <span>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QPlainTextEdit>
|
||||
|
||||
class LogWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LogWindow(bool attach_to_main);
|
||||
~LogWindow();
|
||||
|
||||
static void updateSettings();
|
||||
|
||||
ALWAYS_INLINE bool isAttachedToMainWindow() const { return m_attached_to_main_window; }
|
||||
void reattachToMainWindow();
|
||||
|
||||
void updateWindowTitle();
|
||||
|
||||
private:
|
||||
void createUi();
|
||||
void updateLogLevelUi();
|
||||
void setLogLevel(LOGLEVEL level);
|
||||
void populateFilters(QMenu* filter_menu);
|
||||
void setChannelFiltered(size_t index, bool state);
|
||||
|
||||
static void logCallback(void* pUserParam, const char* channelName, const char* functionName, LOGLEVEL level,
|
||||
std::string_view message);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onClearTriggered();
|
||||
void onSaveTriggered();
|
||||
void appendMessage(const QLatin1StringView& channel, quint32 level, const QString& message);
|
||||
|
||||
private:
|
||||
QPlainTextEdit* m_text;
|
||||
QMenu* m_level_menu;
|
||||
std::span<const char*> m_filter_names;
|
||||
|
||||
bool m_attached_to_main_window = true;
|
||||
};
|
||||
|
||||
extern LogWindow* g_log_window;
|
@ -12,6 +12,7 @@
|
||||
#include "gamelistsettingswidget.h"
|
||||
#include "gamelistwidget.h"
|
||||
#include "generalsettingswidget.h"
|
||||
#include "logwindow.h"
|
||||
#include "memorycardeditordialog.h"
|
||||
#include "qthost.h"
|
||||
#include "qtutils.h"
|
||||
@ -83,6 +84,9 @@ static bool s_use_central_widget = false;
|
||||
// UI thread VM validity.
|
||||
static bool s_system_valid = false;
|
||||
static bool s_system_paused = false;
|
||||
static QString s_current_game_title;
|
||||
static QString s_current_game_serial;
|
||||
static QString s_current_game_path;
|
||||
|
||||
bool QtHost::IsSystemPaused()
|
||||
{
|
||||
@ -94,6 +98,21 @@ bool QtHost::IsSystemValid()
|
||||
return s_system_valid;
|
||||
}
|
||||
|
||||
const QString& QtHost::GetCurrentGameTitle()
|
||||
{
|
||||
return s_current_game_title;
|
||||
}
|
||||
|
||||
const QString& QtHost::GetCurrentGameSerial()
|
||||
{
|
||||
return s_current_game_serial;
|
||||
}
|
||||
|
||||
const QString& QtHost::GetCurrentGamePath()
|
||||
{
|
||||
return s_current_game_path;
|
||||
}
|
||||
|
||||
MainWindow::MainWindow() : QMainWindow(nullptr)
|
||||
{
|
||||
Assert(!g_main_window);
|
||||
@ -102,6 +121,8 @@ MainWindow::MainWindow() : QMainWindow(nullptr)
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
s_use_central_widget = DisplayContainer::isRunningOnWayland();
|
||||
#endif
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@ -596,12 +617,11 @@ void MainWindow::onSystemDestroyed()
|
||||
|
||||
void MainWindow::onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title)
|
||||
{
|
||||
m_current_game_path = filename;
|
||||
m_current_game_title = game_title;
|
||||
m_current_game_serial = game_serial;
|
||||
s_current_game_path = filename;
|
||||
s_current_game_title = game_title;
|
||||
s_current_game_serial = game_serial;
|
||||
|
||||
updateWindowTitle();
|
||||
// updateSaveStateMenus(path, serial, crc);
|
||||
}
|
||||
|
||||
void MainWindow::onApplicationStateChanged(Qt::ApplicationState state)
|
||||
@ -934,7 +954,7 @@ void MainWindow::populateChangeDiscSubImageMenu(QMenu* menu, QActionGroup* actio
|
||||
QAction* action = action_group->addAction(QString::fromStdString(title));
|
||||
QString path = QString::fromStdString(glentry->path);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(path == m_current_game_path);
|
||||
action->setChecked(path == s_current_game_path);
|
||||
connect(action, &QAction::triggered, [path = std::move(path)]() { g_emu_thread->changeDisc(path); });
|
||||
menu->addAction(action);
|
||||
}
|
||||
@ -1165,12 +1185,12 @@ void MainWindow::onChangeDiscMenuAboutToHide()
|
||||
|
||||
void MainWindow::onLoadStateMenuAboutToShow()
|
||||
{
|
||||
populateLoadStateMenu(m_current_game_serial.toUtf8().constData(), m_ui.menuLoadState);
|
||||
populateLoadStateMenu(s_current_game_serial.toUtf8().constData(), m_ui.menuLoadState);
|
||||
}
|
||||
|
||||
void MainWindow::onSaveStateMenuAboutToShow()
|
||||
{
|
||||
populateSaveStateMenu(m_current_game_serial.toUtf8().constData(), m_ui.menuSaveState);
|
||||
populateSaveStateMenu(s_current_game_serial.toUtf8().constData(), m_ui.menuSaveState);
|
||||
}
|
||||
|
||||
void MainWindow::onCheatsMenuAboutToShow()
|
||||
@ -1742,9 +1762,9 @@ void MainWindow::updateWindowTitle()
|
||||
{
|
||||
QString suffix(QtHost::GetAppConfigSuffix());
|
||||
QString main_title(QtHost::GetAppNameAndVersion() + suffix);
|
||||
QString display_title(m_current_game_title + suffix);
|
||||
QString display_title(s_current_game_title + suffix);
|
||||
|
||||
if (!s_system_valid || m_current_game_title.isEmpty())
|
||||
if (!s_system_valid || s_current_game_title.isEmpty())
|
||||
display_title = main_title;
|
||||
else if (isRenderingToMain())
|
||||
main_title = display_title;
|
||||
@ -1759,6 +1779,9 @@ void MainWindow::updateWindowTitle()
|
||||
if (container->windowTitle() != display_title)
|
||||
container->setWindowTitle(display_title);
|
||||
}
|
||||
|
||||
if (g_log_window)
|
||||
g_log_window->updateWindowTitle();
|
||||
}
|
||||
|
||||
void MainWindow::updateWindowState(bool force_visible)
|
||||
@ -2474,6 +2497,22 @@ void MainWindow::dropEvent(QDropEvent* event)
|
||||
startFileOrChangeDisc(qfilename);
|
||||
}
|
||||
|
||||
void MainWindow::moveEvent(QMoveEvent* event)
|
||||
{
|
||||
QMainWindow::moveEvent(event);
|
||||
|
||||
if (g_log_window && g_log_window->isAttachedToMainWindow())
|
||||
g_log_window->reattachToMainWindow();
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QMainWindow::resizeEvent(event);
|
||||
|
||||
if (g_log_window && g_log_window->isAttachedToMainWindow())
|
||||
g_log_window->reattachToMainWindow();
|
||||
}
|
||||
|
||||
void MainWindow::startupUpdateCheck()
|
||||
{
|
||||
if (!Host::GetBaseBoolSettingValue("AutoUpdater", "CheckAtStartup", true))
|
||||
@ -2510,7 +2549,7 @@ bool MainWindow::requestShutdown(bool allow_confirm /* = true */, bool allow_sav
|
||||
return true;
|
||||
|
||||
// If we don't have a serial, we can't save state.
|
||||
allow_save_to_state &= !m_current_game_serial.isEmpty();
|
||||
allow_save_to_state &= !s_current_game_serial.isEmpty();
|
||||
save_state &= allow_save_to_state;
|
||||
|
||||
// Only confirm on UI thread because we need to display a msgbox.
|
||||
@ -2574,6 +2613,7 @@ void MainWindow::checkForSettingChanges()
|
||||
m_display_widget->updateRelativeMode(s_system_valid && !s_system_paused);
|
||||
#endif
|
||||
|
||||
LogWindow::updateSettings();
|
||||
updateWindowState();
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,6 @@ public:
|
||||
/// Sets application theme according to settings.
|
||||
static void updateApplicationTheme();
|
||||
|
||||
/// Initializes the window. Call once at startup.
|
||||
void initialize();
|
||||
|
||||
/// Performs update check if enabled in settings.
|
||||
void startupUpdateCheck();
|
||||
|
||||
@ -186,6 +183,8 @@ protected:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
void moveEvent(QMoveEvent* event) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
#ifdef _WIN32
|
||||
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
|
||||
@ -194,6 +193,10 @@ protected:
|
||||
private:
|
||||
static void setStyleFromSettings();
|
||||
static void setIconThemeFromSettings();
|
||||
|
||||
/// Initializes the window. Call once at startup.
|
||||
void initialize();
|
||||
|
||||
void setupAdditionalUi();
|
||||
void connectSignals();
|
||||
|
||||
@ -285,10 +288,6 @@ private:
|
||||
CheatManagerDialog* m_cheat_manager_dialog = nullptr;
|
||||
DebuggerWindow* m_debugger_window = nullptr;
|
||||
|
||||
QString m_current_game_path;
|
||||
QString m_current_game_title;
|
||||
QString m_current_game_serial;
|
||||
|
||||
bool m_was_paused_by_focus_loss = false;
|
||||
bool m_open_debugger_on_start = false;
|
||||
bool m_relative_mouse_mode = false;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "qthost.h"
|
||||
#include "autoupdaterdialog.h"
|
||||
#include "displaywidget.h"
|
||||
#include "logwindow.h"
|
||||
#include "mainwindow.h"
|
||||
#include "qtprogresscallback.h"
|
||||
#include "qtutils.h"
|
||||
@ -201,7 +202,7 @@ bool QtHost::InitializeConfig(std::string settings_filename)
|
||||
if (!Log::IsConsoleOutputEnabled() &&
|
||||
s_base_settings_interface->GetBoolValue("Logging", "LogToConsole", Settings::DEFAULT_LOG_TO_CONSOLE))
|
||||
{
|
||||
Log::SetConsoleOutputParams(true, nullptr, LOGLEVEL_NONE);
|
||||
Log::SetConsoleOutputParams(true, s_base_settings_interface->GetBoolValue("Logging", "LogTimestamps", true));
|
||||
}
|
||||
|
||||
// TEMPORARY: Migrate controller settings to new interface.
|
||||
@ -2028,6 +2029,9 @@ int main(int argc, char* argv[])
|
||||
// Set theme before creating any windows.
|
||||
MainWindow::updateApplicationTheme();
|
||||
|
||||
// Start logging early.
|
||||
LogWindow::updateSettings();
|
||||
|
||||
// Start up the CPU thread.
|
||||
QtHost::HookSignals();
|
||||
EmuThread::start();
|
||||
@ -2043,7 +2047,6 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Create all window objects, the emuthread might still be starting up at this point.
|
||||
main_window = new MainWindow();
|
||||
main_window->initialize();
|
||||
|
||||
// When running in batch mode, ensure game list is loaded, but don't scan for any new files.
|
||||
if (!s_batch_mode)
|
||||
|
@ -87,6 +87,7 @@ public:
|
||||
static void stop();
|
||||
|
||||
ALWAYS_INLINE bool isOnThread() const { return QThread::currentThread() == this; }
|
||||
ALWAYS_INLINE bool isOnUIThread() const { return QThread::currentThread() == m_ui_thread; }
|
||||
|
||||
ALWAYS_INLINE QEventLoop* getEventLoop() const { return m_event_loop; }
|
||||
|
||||
@ -276,4 +277,9 @@ void QueueSettingsSave();
|
||||
/// VM state, safe to access on UI thread.
|
||||
bool IsSystemValid();
|
||||
bool IsSystemPaused();
|
||||
|
||||
/// Accessors for game information.
|
||||
const QString& GetCurrentGameTitle();
|
||||
const QString& GetCurrentGameSerial();
|
||||
const QString& GetCurrentGamePath();
|
||||
} // namespace QtHost
|
||||
|
Reference in New Issue
Block a user