diff --git a/src/platform/qt/AudioDevice.cpp b/src/platform/qt/AudioDevice.cpp index c00071381..7565b6789 100644 --- a/src/platform/qt/AudioDevice.cpp +++ b/src/platform/qt/AudioDevice.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AudioDevice.h" +#include "GBAApp.h" #include "LogController.h" #include @@ -31,7 +32,7 @@ AudioDevice::~AudioDevice() { void AudioDevice::setFormat(const QAudioFormat& format) { if (!m_context || !mCoreThreadIsActive(m_context)) { - qInfo() << tr("Can't set format of context-less audio device"); + LOG(QT, INFO) << tr("Can't set format of context-less audio device"); return; } mCoreSyncLockAudio(&m_context->impl->sync); @@ -52,7 +53,7 @@ void AudioDevice::setInput(mCoreThread* input) { qint64 AudioDevice::readData(char* data, qint64 maxSize) { if (!m_context->core) { - qWarning() << tr("Audio device is missing its core"); + LOG(QT, WARN) << tr("Audio device is missing its core"); return 0; } @@ -80,7 +81,7 @@ qint64 AudioDevice::readData(char* data, qint64 maxSize) { } qint64 AudioDevice::writeData(const char*, qint64) { - qWarning() << tr("Writing data to read-only audio device"); + LOG(QT, WARN) << tr("Writing data to read-only audio device"); return 0; } diff --git a/src/platform/qt/AudioProcessorQt.cpp b/src/platform/qt/AudioProcessorQt.cpp index e9fcf3641..9f92eaa27 100644 --- a/src/platform/qt/AudioProcessorQt.cpp +++ b/src/platform/qt/AudioProcessorQt.cpp @@ -53,7 +53,7 @@ void AudioProcessorQt::stop() { bool AudioProcessorQt::start() { if (!input()) { - qWarning() << tr("Can't start an audio processor without input"); + LOG(QT, WARN) << tr("Can't start an audio processor without input"); return false; } @@ -78,7 +78,7 @@ bool AudioProcessorQt::start() { QAudioDevice device(QMediaDevices::defaultAudioOutput()); m_audioOutput = std::make_unique(device, format); - qInfo() << "Audio outputting to " << device.description(); + LOG(QT, INFO) << tr("Audio outputting to %1").arg(device.description()); connect(m_audioOutput.get(), &QAudioSink::stateChanged, this, [this](QAudio::State state) { if (state != QAudio::IdleState) { return; diff --git a/src/platform/qt/AudioProcessorSDL.cpp b/src/platform/qt/AudioProcessorSDL.cpp index 0be57b891..bfa9782d1 100644 --- a/src/platform/qt/AudioProcessorSDL.cpp +++ b/src/platform/qt/AudioProcessorSDL.cpp @@ -31,7 +31,7 @@ void AudioProcessorSDL::stop() { bool AudioProcessorSDL::start() { if (!input()) { - qWarning() << tr("Can't start an audio processor without input"); + LOG(QT, WARN) << tr("Can't start an audio processor without input"); return false; } diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 72a569fc3..7164e4e21 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -136,6 +136,7 @@ set(SOURCE_FILES InputProfile.cpp KeyEditor.cpp LoadSaveState.cpp + Log.cpp LogController.cpp LogConfigModel.cpp LogView.cpp @@ -309,6 +310,7 @@ if(ENABLE_SCRIPTING) scripting/ScriptingView.ui) set(TEST_QT_autoscript_SRC + Log.cpp test/autoscript.cpp scripting/AutorunScriptModel.cpp) endif() diff --git a/src/platform/qt/CheatsModel.cpp b/src/platform/qt/CheatsModel.cpp index 6e28df356..85528c1b6 100644 --- a/src/platform/qt/CheatsModel.cpp +++ b/src/platform/qt/CheatsModel.cpp @@ -208,7 +208,7 @@ void CheatsModel::endAppendRow() { void CheatsModel::loadFile(const QString& path) { VFile* vf = VFileDevice::open(path, O_RDONLY); if (!vf) { - qWarning() << tr("Failed to open cheats file: %1").arg(path); + LOG(QT, WARN) << tr("Failed to open cheats file: %1").arg(path); return; } beginResetModel(); diff --git a/src/platform/qt/CheatsView.cpp b/src/platform/qt/CheatsView.cpp index db0ce50c5..243987d6b 100644 --- a/src/platform/qt/CheatsView.cpp +++ b/src/platform/qt/CheatsView.cpp @@ -183,7 +183,7 @@ void CheatsView::enterCheat() { set->refresh(set, m_controller->cheatDevice()); } if (failure) { - qCritical() << tr("Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types."); + LOG(QT, ERROR) << tr("Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types."); } m_ui.codeEntry->clear(); } diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 1e4ff5138..55e743be1 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -824,7 +824,7 @@ void CoreController::loadSave(const QString& path, bool temporary) { m_resetActions.append([this, path, temporary]() { VFile* vf = VFileDevice::open(path, temporary ? O_RDONLY : O_RDWR); if (!vf) { - qCritical() << tr("Failed to open save file: %1").arg(path); + LOG(QT, ERROR) << tr("Failed to open save file: %1").arg(path); return; } @@ -882,7 +882,7 @@ void CoreController::loadPatch(const QString& patchPath) { void CoreController::replaceGame(const QString& path) { QFileInfo info(path); if (!info.isReadable()) { - qCritical() << tr("Failed to open game file: %1").arg(path); + LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path); return; } QString fname = info.canonicalFilePath(); @@ -912,7 +912,7 @@ void CoreController::yankPak() { break; #endif case mPLATFORM_NONE: - qCritical() << tr("Can't yank pack in unexpected platform!"); + LOG(QT, ERROR) << tr("Can't yank pack in unexpected platform!"); break; } } @@ -1027,7 +1027,7 @@ void CoreController::importSharkport(const QString& path) { } VFile* vf = VFileDevice::open(path, O_RDONLY); if (!vf) { - qCritical() << tr("Failed to open snapshot file for reading: %1").arg(path); + LOG(QT, ERROR) << tr("Failed to open snapshot file for reading: %1").arg(path); return; } Interrupter interrupter(this); @@ -1044,7 +1044,7 @@ void CoreController::exportSharkport(const QString& path) { } VFile* vf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC); if (!vf) { - qCritical() << tr("Failed to open snapshot file for writing: %1").arg(path); + LOG(QT, ERROR) << tr("Failed to open snapshot file for writing: %1").arg(path); return; } Interrupter interrupter(this); diff --git a/src/platform/qt/CoreManager.cpp b/src/platform/qt/CoreManager.cpp index 4abdcb8a1..385b3440b 100644 --- a/src/platform/qt/CoreManager.cpp +++ b/src/platform/qt/CoreManager.cpp @@ -49,7 +49,7 @@ CoreController* CoreManager::loadGame(const QString& path) { dir->close(dir); return loadGame(vf, fname, base); } else { - qCritical() << tr("Failed to open game file: %1").arg(path); + LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path); } return nullptr; } @@ -87,7 +87,7 @@ CoreController* CoreManager::loadGame(VFile* vf, const QString& path, const QStr mCore* core = mCoreFindVF(vf); if (!core) { vf->close(vf); - qCritical() << tr("Could not load game. Are you sure it's in the correct format?"); + LOG(QT, ERROR) << tr("Could not load game. Are you sure it's in the correct format?"); return nullptr; } @@ -114,7 +114,7 @@ CoreController* CoreManager::loadGame(VFile* vf, const QString& path, const QStr bytes = info.dir().canonicalPath().toUtf8(); mDirectorySetAttachBase(&core->dirs, VDirOpen(bytes.constData())); if (!mCoreAutoloadSave(core)) { - qCritical() << tr("Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows)."); + LOG(QT, ERROR) << tr("Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows)."); } mCoreAutoloadCheats(core); diff --git a/src/platform/qt/DebuggerConsoleController.cpp b/src/platform/qt/DebuggerConsoleController.cpp index 25bbe64cd..716c31639 100644 --- a/src/platform/qt/DebuggerConsoleController.cpp +++ b/src/platform/qt/DebuggerConsoleController.cpp @@ -173,7 +173,7 @@ void DebuggerConsoleController::historyLoad() { void DebuggerConsoleController::historySave() { QFile log(ConfigController::configDir() + "/cli_history.log"); if (!log.open(QIODevice::WriteOnly | QIODevice::Text)) { - qWarning() << tr("Could not open CLI history for writing"); + LOG(QT, WARN) << tr("Could not open CLI history for writing"); return; } for (const QString& line : m_history) { diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 8e5849dbf..00af3cb8d 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -310,7 +310,7 @@ bool DisplayGL::highestCompatible(QSurfaceFormat& format) { #ifdef BUILD_GL #if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) - qWarning() << tr("Failed to create an OpenGL 3 context, trying old-style..."); + LOG(QT, WARN) << tr("Failed to create an OpenGL 3 context, trying old-style..."); #endif if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { format.setVersion(1, 4); diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index 27d57e167..5c5d28f87 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -40,8 +40,6 @@ using namespace QGBA; static GBAApp* g_app = nullptr; -mLOG_DEFINE_CATEGORY(QT, "Qt", "platform.qt"); - GBAApp::GBAApp(int& argc, char* argv[], ConfigController* config) : QApplication(argc, argv) , m_configController(config) diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index 43848b183..23ba4f30c 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -25,10 +25,6 @@ struct NoIntroDB; -#include - -mLOG_DECLARE_CATEGORY(QT); - namespace QGBA { class ConfigController; diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index ef9ddee77..c3bf496da 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -60,7 +60,7 @@ void GIFView::startRecording() { } FFmpegEncoderSetLooping(&m_encoder, m_ui.loop->isChecked()); if (!FFmpegEncoderOpen(&m_encoder, m_filename.toUtf8().constData())) { - qCritical() << tr("Failed to open output file: %1").arg(m_filename); + LOG(QT, ERROR) << tr("Failed to open output file: %1").arg(m_filename); return; } m_ui.start->setEnabled(false); diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 4d7d7d8f7..30bdd0be2 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -724,9 +724,9 @@ void InputController::prepareCamFormat() { } } if (!goodFormatFound) { - qWarning() << "Could not find a valid camera format!"; + LOG(QT, WARN) << tr("Could not find a valid camera format!"); for (const auto& format : cameraFormats) { - qWarning() << "Camera supported format: " << QString::number(format); + LOG(QT, WARN) << tr("Camera supported format: %1").arg(format); } } m_camera->setViewfinderSettings(settings); @@ -745,7 +745,7 @@ void InputController::prepareCamFormat() { } } if (!goodFormatFound) { - qWarning() << "Could not find a valid camera format!"; + LOG(QT, WARN) << tr("Could not find a valid camera format!"); } m_camera->setCameraFormat(bestFormat); #endif diff --git a/src/platform/qt/Log.cpp b/src/platform/qt/Log.cpp new file mode 100644 index 000000000..f4b5db3b0 --- /dev/null +++ b/src/platform/qt/Log.cpp @@ -0,0 +1,78 @@ +/* Copyright (c) 2013-2025 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Log.h" + +#include + +mLOG_DEFINE_CATEGORY(QT, "Qt", "platform.qt"); + +using namespace QGBA; + +Log* Log::s_target = nullptr; + +Log::Stream Log::log(int level, int category) { + return Stream(s_target, level, category); +} + +void Log::setDefaultTarget(Log* target) { + s_target = target; +} + +Log::Log() { + // Nothing to do +} + +Log::~Log() { + if (s_target == this) { + s_target = nullptr; + } +} + +void Log::postLog(int level, int category, const QString& string) { + QLoggingCategory cat(mLogCategoryName(category)); + switch (level) { + case mLOG_DEBUG: + case mLOG_STUB: + qCDebug(cat).noquote() << string; + return; + case mLOG_INFO: + qCInfo(cat).noquote() << string; + return; + case mLOG_ERROR: + case mLOG_GAME_ERROR: + qCCritical(cat).noquote() << string; + return; + case mLOG_FATAL: + // qFatal doesn't have a stream API + qFatal("%s: %s", mLogCategoryName(category), qPrintable(string)); + return; + case mLOG_WARN: + default: + qCWarning(cat).noquote() << string; + return; + } +} + +Log::Stream::Stream(Log* target, int level, int category) + : m_level(level) + , m_category(category) + , m_log(target) +{ +} + +Log::Stream::~Stream() { + if (m_log) { + m_log->postLog(m_level, m_category, m_queue.join(" ")); + } else { + Log().postLog(m_level, m_category, m_queue.join(" ")); + } +} + +Log::Stream& Log::Stream::operator<<(const QString& string) { + m_queue.append(string); + return *this; +} diff --git a/src/platform/qt/Log.h b/src/platform/qt/Log.h new file mode 100644 index 000000000..78f3a9a3d --- /dev/null +++ b/src/platform/qt/Log.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2013-2025 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include + +#include + +mLOG_DECLARE_CATEGORY(QT); + +namespace QGBA { + +class LogController; + +class Log { +private: + class Stream { + public: + Stream(Log* target, int level, int category); + ~Stream(); + + Stream& operator<<(const QString&); + template + Stream& operator<<(const T& value) { + QString formatted; + QDebug dbg(&formatted); + dbg.noquote() << value; + *this << formatted; + return *this; + } + + private: + int m_level; + int m_category; + Log* m_log; + + QStringList m_queue; + }; + + static Log* s_target; + +public: + static Stream log(int level, int category); + static void setDefaultTarget(Log* target); + + Log(); + ~Log(); + + virtual void postLog(int level, int category, const QString& string); +}; + +} + +#define LOG(C, L) (QGBA::Log::log(mLOG_ ## L, _mLOG_CAT_ ## C)) diff --git a/src/platform/qt/LogController.cpp b/src/platform/qt/LogController.cpp index 5d2ec8dbf..098a947d5 100644 --- a/src/platform/qt/LogController.cpp +++ b/src/platform/qt/LogController.cpp @@ -5,17 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "LogController.h" +#include #include -#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) -#include -#endif #include "ConfigController.h" using namespace QGBA; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) -#define endl Qt::endl +#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) +namespace Qt { +using QTextStreamFunctions::endl; +} #endif LogController LogController::s_global(mLOG_ALL); @@ -55,7 +55,9 @@ LogController::LogController(int levels, QObject* parent) m_filter.defaultLevels = levels; s_qtCat = mLogCategoryById("platform.qt"); - if (this != &s_global) { + if (this == &s_global) { + setDefaultTarget(this); + } else { connect(&s_global, &LogController::logPosted, this, &LogController::postLog); connect(this, static_cast(&LogController::levelsSet), &s_global, static_cast(&LogController::setLevels)); connect(this, static_cast(&LogController::levelsEnabled), &s_global, static_cast(&LogController::enableLevels)); @@ -71,10 +73,6 @@ int LogController::levels(int category) const { return mLogFilterLevels(&m_filter, category); } -LogController::Stream LogController::operator()(int category, int level) { - return Stream(this, category, level); -} - void LogController::load(const ConfigController* config) { mLogFilterLoad(&m_filter, config->config()); if (!levels(mLogCategoryById("gba.bios"))) { @@ -96,7 +94,7 @@ void LogController::postLog(int level, int category, const QString& string) { if (!mLogFilterTest(&m_filter, category, static_cast(level))) { return; } - if (m_logToStdout || m_logToFile) { + if ((m_logToStdout || m_logToFile) && this == &s_global) { QString line = tr("[%1] %2: %3").arg(LogController::toString(level)).arg(mLogCategoryName(category)).arg(string); if (m_logToStdout) { @@ -196,19 +194,3 @@ QString LogController::toString(int level) { } return QString(); } - -LogController::Stream::Stream(LogController* controller, int level, int category) - : m_level(level) - , m_category(category) - , m_log(controller) -{ -} - -LogController::Stream::~Stream() { - m_log->postLog(m_level, m_category, m_queue.join(" ")); -} - -LogController::Stream& LogController::Stream::operator<<(const QString& string) { - m_queue.append(string); - return *this; -} diff --git a/src/platform/qt/LogController.h b/src/platform/qt/LogController.h index 2ab7962fb..40b9cb717 100644 --- a/src/platform/qt/LogController.h +++ b/src/platform/qt/LogController.h @@ -6,9 +6,12 @@ #pragma once #include "GBAApp.h" +#include "Log.h" #include +#include +#include #include #include #include @@ -18,25 +21,9 @@ namespace QGBA { class ConfigController; -class LogController : public QObject { +class LogController : public QObject, public Log { Q_OBJECT -private: - class Stream { - public: - Stream(LogController* controller, int level, int category); - ~Stream(); - - Stream& operator<<(const QString&); - - private: - int m_level; - int m_category; - LogController* m_log; - - QStringList m_queue; - }; - public: LogController(int levels, QObject* parent = nullptr); ~LogController(); @@ -45,8 +32,6 @@ public: int levels(int category) const; mLogFilter* filter() { return &m_filter; } - Stream operator()(int category, int level); - static LogController* global(); static QtMessageHandler installMessageHandler(); static QString toString(int level); @@ -65,7 +50,7 @@ signals: void levelsDisabled(int levels, int category); public slots: - void postLog(int level, int category, const QString& string); + void postLog(int level, int category, const QString& string) override; void setLevels(int levels); void enableLevels(int levels); void disableLevels(int levels); @@ -89,6 +74,4 @@ private: static int s_qtCat; }; -#define LOG(C, L) (*LogController::global())(mLOG_ ## L, _mLOG_CAT_ ## C) - } diff --git a/src/platform/qt/MemoryAccessLogController.cpp b/src/platform/qt/MemoryAccessLogController.cpp index d8b4cc00d..d62b2f8a5 100644 --- a/src/platform/qt/MemoryAccessLogController.cpp +++ b/src/platform/qt/MemoryAccessLogController.cpp @@ -114,7 +114,7 @@ void MemoryAccessLogController::load(bool loadExisting) { } VFile* vf = VFileDevice::open(m_path, flags); if (!vf) { - qCritical() << tr("Failed to open memory log file"); + LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } @@ -123,7 +123,7 @@ void MemoryAccessLogController::load(bool loadExisting) { m_controller->attachDebuggerModule(&m_logger.d); if (!mDebuggerAccessLoggerOpen(&m_logger, vf, flags)) { mDebuggerAccessLoggerDeinit(&m_logger); - qCritical() << tr("Failed to open memory log file"); + LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } emit loaded(true); diff --git a/src/platform/qt/MemoryDump.cpp b/src/platform/qt/MemoryDump.cpp index 01d228566..59cef31be 100644 --- a/src/platform/qt/MemoryDump.cpp +++ b/src/platform/qt/MemoryDump.cpp @@ -27,7 +27,7 @@ void MemoryDump::save() { } QFile outfile(filename); if (!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qWarning() << tr("Failed to open output file: %1").arg(filename); + LOG(QT, WARN) << tr("Failed to open output file: %1").arg(filename); return; } QByteArray out(serialize()); diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index 2ce02f644..ca264d4c1 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -219,7 +219,7 @@ void MemoryModel::save() { } QFile outfile(filename); if (!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qWarning() << tr("Failed to open output file: %1").arg(filename); + LOG(QT, WARN) << tr("Failed to open output file: %1").arg(filename); return; } QByteArray out(serialize()); @@ -233,7 +233,7 @@ void MemoryModel::load() { } QFile infile(filename); if (!infile.open(QIODevice::ReadOnly)) { - qWarning() << tr("Failed to open input file: %1").arg(filename); + LOG(QT, WARN) << tr("Failed to open input file: %1").arg(filename); return; } QByteArray bytestring(infile.readAll()); diff --git a/src/platform/qt/MultiplayerController.cpp b/src/platform/qt/MultiplayerController.cpp index bdcde615d..48f2334d0 100644 --- a/src/platform/qt/MultiplayerController.cpp +++ b/src/platform/qt/MultiplayerController.cpp @@ -310,7 +310,7 @@ bool MultiplayerController::attachGame(CoreController* controller) { break; } if (!player.saveId) { - qCritical() << "Couldn't find available save ID"; + LOG(QT, ERROR) << tr("Couldn't find available save ID"); player.saveId = 1; } } else if (saveId) { @@ -364,7 +364,7 @@ void MultiplayerController::detachGame(CoreController* controller) { interrupters.append(playerController); } if (pid < 0) { - qWarning() << tr("Trying to detach a multiplayer player that's not attached"); + LOG(QT, WARN) << tr("Trying to detach a multiplayer player that's not attached"); return; } switch (controller->platform()) { @@ -404,7 +404,7 @@ void MultiplayerController::detachGame(CoreController* controller) { QPair path(controller->path(), controller->baseDirectory()); Player& p = m_pids.find(pid).value(); if (!p.saveId) { - qWarning() << tr("Clearing invalid save ID"); + LOG(QT, WARN) << tr("Clearing invalid save ID"); } else { m_claimedSaves[path] &= ~(1 << (p.saveId - 1)); if (!m_claimedSaves[path]) { @@ -413,7 +413,7 @@ void MultiplayerController::detachGame(CoreController* controller) { } if (p.preferredId < 0) { - qWarning() << tr("Clearing invalid preferred ID"); + LOG(QT, WARN) << tr("Clearing invalid preferred ID"); } else { m_claimedIds &= ~(1 << p.preferredId); } @@ -434,7 +434,7 @@ int MultiplayerController::playerId(CoreController* controller) const { for (int i = 0; i < m_players.count(); ++i) { const Player* p = player(i); if (!p) { - qCritical() << tr("Trying to get player ID for a multiplayer player that's not attached"); + LOG(QT, ERROR) << tr("Trying to get player ID for a multiplayer player that's not attached"); return -1; } if (p->controller == controller) { @@ -448,7 +448,7 @@ int MultiplayerController::saveId(CoreController* controller) const { for (int i = 0; i < m_players.count(); ++i) { const Player* p = player(i); if (!p) { - qCritical() << tr("Trying to get save ID for a multiplayer player that's not attached"); + LOG(QT, ERROR) << tr("Trying to get save ID for a multiplayer player that's not attached"); return -1; } if (p->controller == controller) { diff --git a/src/platform/qt/PaletteView.cpp b/src/platform/qt/PaletteView.cpp index 896c561cf..de09c270a 100644 --- a/src/platform/qt/PaletteView.cpp +++ b/src/platform/qt/PaletteView.cpp @@ -139,7 +139,7 @@ void PaletteView::exportPalette(int start, int length) { } VFile* vf = VFileDevice::open(filename, O_WRONLY | O_CREAT | O_TRUNC); if (!vf) { - qCritical() << tr("Failed to open output palette file: %1").arg(filename); + LOG(QT, ERROR) << tr("Failed to open output palette file: %1").arg(filename); return; } if (filename.endsWith(".pal", Qt::CaseInsensitive)) { diff --git a/src/platform/qt/SaveConverter.cpp b/src/platform/qt/SaveConverter.cpp index a8047471c..3383e006e 100644 --- a/src/platform/qt/SaveConverter.cpp +++ b/src/platform/qt/SaveConverter.cpp @@ -656,7 +656,7 @@ QByteArray SaveConverter::AnnotatedSave::convertTo(const SaveConverter::Annotate } if (platform != target.platform) { - qCritical() << tr("Cannot convert save games between platforms"); + LOG(QT, ERROR) << tr("Cannot convert save games between platforms"); return {}; } diff --git a/src/platform/qt/VideoView.cpp b/src/platform/qt/VideoView.cpp index e81584ce4..356133bbb 100644 --- a/src/platform/qt/VideoView.cpp +++ b/src/platform/qt/VideoView.cpp @@ -223,7 +223,7 @@ void VideoView::startRecording() { return; } if (!FFmpegEncoderOpen(&m_encoder, m_filename.toUtf8().constData())) { - qCritical() << tr("Failed to open output video file: %1").arg(m_filename); + LOG(QT, ERROR) << tr("Failed to open output video file: %1").arg(m_filename); return; } m_ui.start->setEnabled(false); diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 049079b87..9e9926bc5 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1055,7 +1055,7 @@ void Window::reloadDisplayDriver() { } m_display = std::unique_ptr(Display::create(this)); if (!m_display) { - qCritical() << tr("Failed to create an appropriate display device, falling back to software display. " + LOG(QT, ERROR) << tr("Failed to create an appropriate display device, falling back to software display. " "Games may run slowly, especially with larger windows."); Display::setDriver(Display::Driver::QT); m_display = std::unique_ptr(Display::create(this)); @@ -1128,7 +1128,7 @@ void Window::reloadAudioDriver() { m_audioProcessor->setInput(m_controller); m_audioProcessor->configure(m_config); if (!m_audioProcessor->start()) { - qWarning() << "Failed to start audio processor"; + LOG(QT, WARN) << tr("Failed to start audio processor"); } } diff --git a/src/platform/qt/scripting/AutorunScriptModel.cpp b/src/platform/qt/scripting/AutorunScriptModel.cpp index 486e2f402..b7bd65fad 100644 --- a/src/platform/qt/scripting/AutorunScriptModel.cpp +++ b/src/platform/qt/scripting/AutorunScriptModel.cpp @@ -5,8 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "scripting/AutorunScriptModel.h" -#include -#include +#include "Log.h" QDataStream& operator<<(QDataStream& stream, const QGBA::AutorunScriptModel::ScriptInfo& object) { stream << QGBA::AutorunScriptModel::ScriptInfo::VERSION; @@ -16,6 +15,7 @@ QDataStream& operator<<(QDataStream& stream, const QGBA::AutorunScriptModel::Scr } QDataStream& operator>>(QDataStream& stream, QGBA::AutorunScriptModel::ScriptInfo& object) { + static bool displayedError = false; uint16_t version = 0; stream >> version; if (version == 1) { @@ -23,7 +23,13 @@ QDataStream& operator>>(QDataStream& stream, QGBA::AutorunScriptModel::ScriptInf stream >> filename; object.filename = QString::fromUtf8(filename); } else { - qCritical() << QGBA::AutorunScriptModel::tr("Could not load autorun script settings: unknown script info format %1").arg(version); + QString logMessage = QGBA::AutorunScriptModel::tr("Could not load autorun script settings: unknown script info format %1").arg(version); + if (displayedError) { + LOG(QT, WARN) << logMessage; + } else { + LOG(QT, ERROR) << logMessage; + displayedError = true; + } stream.setStatus(QDataStream::ReadCorruptData); return stream; }