diff --git a/src/platform/qt/PopupManager.h b/src/platform/qt/PopupManager.h index 0c71bd088..e7ec6aed3 100644 --- a/src/platform/qt/PopupManager.h +++ b/src/platform/qt/PopupManager.h @@ -34,7 +34,8 @@ protected: class Private : public QSharedData { public: Private(PopupManagerBase* pub) : pub(pub) {} - Private(const Private& other) = default; + Private(const Private& other) = delete; + virtual ~Private() = default; PopupManagerBase* pub; bool isModal = false; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 5071b0cd3..e80409ad5 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -55,6 +55,7 @@ #include "ObjView.h" #include "PaletteView.h" #include "PlacementControl.h" +#include "PopupManager.h" #include "PrinterView.h" #include "ReportView.h" #include "ROMInfo.h" @@ -91,15 +92,34 @@ using namespace QGBA; +namespace QGBA { + +class WindowPopups { +public: + PopupManager logView; + PopupManager overrideView; + PopupManager sensorView; + PopupManager dolphinView; + PopupManager frameView; + PopupManager cheatsView; +#ifdef USE_FFMPEG + PopupManager videoView; + PopupManager gifView; +#endif + +}; + +} + Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWidget* parent) : QMainWindow(parent) , m_manager(manager) - , m_logView(new LogView(&m_log, this)) , m_screenWidget(new WindowBackground()) , m_config(config) , m_inputController(this) , m_shortcutController(new ShortcutController(this)) , m_playerId(playerId) + , m_popups(new WindowPopups) { setFocusPolicy(Qt::StrongFocus); setAcceptDrops(true); @@ -165,7 +185,6 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi } setLogo(); - connect(this, &Window::shutdown, m_logView, &QWidget::hide); connect(&m_fpsTimer, &QTimer::timeout, this, &Window::showFPS); connect(&m_focusCheck, &QTimer::timeout, this, &Window::focusCheck); connect(&m_inputController, &InputController::profileLoaded, m_shortcutController, &ShortcutController::loadProfile); @@ -192,13 +211,12 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi m_shortcutController->setConfigController(m_config); m_shortcutController->setActionMapper(&m_actions); + setupPopups(); setupMenu(menuBar()); setupOptions(); } Window::~Window() { - delete m_logView; - #ifdef USE_SQLITE3 delete m_libraryView; #endif @@ -572,67 +590,6 @@ void Window::startVideoLog() { } } -template -std::function Window::openTView(A... arg) { - return [=]() { - T* view = new T(arg...); - openView(view); - }; -} - -template -std::function Window::openTViewModal(A... arg) { - return [=]() { - T* view = new T(arg...); - view->setAttribute(Qt::WA_DeleteOnClose); - view->open(); - }; -} - -template -std::function Window::openControllerTView(A... arg) { - return [=]() { - T* view = new T(m_controller, arg...); - connect(m_controller.get(), &CoreController::stopping, view, &QWidget::close); - openView(view); - }; -} - -template -std::function Window::openNamedTView(QPointer* name, bool keepalive, A... arg) { - return [=]() { - if (!*name) { - *name = new T(arg...); - connect(this, &Window::shutdown, name->data(), &QWidget::close); - if (!keepalive) { - (*name)->setAttribute(Qt::WA_DeleteOnClose); - } - } - (*name)->show(); - (*name)->activateWindow(); - (*name)->raise(); - }; -} - -template -std::function Window::openNamedControllerTView(QPointer* name, bool keepalive, A... arg) { - return [=]() { - if (!*name) { - *name = new T(m_controller, arg...); - if (m_controller) { - connect(m_controller.get(), &CoreController::stopping, name->data(), &QWidget::close); - } - connect(this, &Window::shutdown, name->data(), &QWidget::close); - if (!keepalive) { - (*name)->setAttribute(Qt::WA_DeleteOnClose); - } - } - (*name)->show(); - (*name)->activateWindow(); - (*name)->raise(); - }; -} - #ifdef ENABLE_GDB_STUB void Window::gdbOpen() { if (!m_gdbController) { @@ -1304,6 +1261,16 @@ void Window::openStateWindow(LoadSave ls) { attachWidget(m_stateWindow); } +void Window::setupPopups() { + m_popups->logView.constructWith(&m_log, this).setKeepAlive(false); + m_popups->overrideView.withController(m_controller).constructWith(m_config, this); + // Why is SensorView keepalive? + m_popups->sensorView.withController(m_controller).constructWith(&m_inputController, this).setKeepAlive(true); + m_popups->dolphinView.constructWith(this).setKeepAlive(true); + m_popups->videoView.withController(m_controller).setKeepAlive(true); + m_popups->gifView.withController(m_controller).setKeepAlive(true); +} + void Window::setupMenu(QMenuBar* menubar) { installEventFilter(m_shortcutController); @@ -1327,7 +1294,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addSeparator("saves"); - m_actions.addAction(tr("Convert save game..."), "convertSave", openTViewModal(this), "saves"); + m_actions.addAction(tr("Convert save game..."), "convertSave", PopupManager(), "saves"); #ifdef M_CORE_GBA auto importShark = addGameAction(tr("Import GameShark Save..."), "importShark", this, &Window::importSharkport, "saves"); @@ -1365,7 +1332,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_platformActions.insert(mPLATFORM_GBA, scanCard); #endif - addGameAction(tr("ROM &info..."), "romInfo", openControllerTView(), "file"); + addGameAction(tr("ROM &info..."), "romInfo", PopupManager().withController(m_controller), "file"); m_actions.addMenu(tr("Recent"), "mru", "file"); m_actions.addSeparator("file"); @@ -1431,19 +1398,19 @@ void Window::setupMenu(QMenuBar* menubar) { m_multiWindow = m_actions.addAction(tr("New multiplayer window"), "multiWindow", GBAApp::app(), &GBAApp::newWindow, "file"); #ifdef M_CORE_GBA - auto dolphin = m_actions.addAction(tr("Connect to Dolphin..."), "connectDolphin", openNamedTView(&m_dolphinView, true, this), "file"); + auto dolphin = m_actions.addAction(tr("Connect to Dolphin..."), "connectDolphin", m_popups->dolphinView, "file"); m_platformActions.insert(mPLATFORM_GBA, dolphin); #endif m_actions.addSeparator("file"); - m_actions.addAction(tr("Report bug..."), "bugReport", openTViewModal(this), "file"); + m_actions.addAction(tr("Report bug..."), "bugReport", PopupManager(), "file"); #ifndef Q_OS_MAC m_actions.addSeparator("file"); #endif - m_actions.addAction(tr("About..."), "about", openTViewModal(this), "file")->setRole(Action::Role::ABOUT); + m_actions.addAction(tr("About..."), "about", PopupManager(), "file")->setRole(Action::Role::ABOUT); m_actions.addAction(tr("E&xit"), "quit", &QApplication::quit, "file", QKeySequence::Quit)->setRole(Action::Role::QUIT); m_actions.addMenu(tr("&Emulation"), "emu"); @@ -1558,7 +1525,7 @@ void Window::setupMenu(QMenuBar* menubar) { #endif #ifdef M_CORE_GBA - auto bcGate = addGameAction(tr("BattleChip Gate..."), "bcGate", openControllerTView(this), "emu"); + auto bcGate = addGameAction(tr("BattleChip Gate..."), "bcGate", PopupManager().withController(m_controller), "emu"); m_platformActions.insert(mPLATFORM_GBA, bcGate); #endif @@ -1712,28 +1679,27 @@ void Window::setupMenu(QMenuBar* menubar) { #endif #ifdef USE_FFMPEG - addGameAction(tr("Record A/V..."), "recordOutput", openNamedControllerTView(&m_videoView, true), "av"); - addGameAction(tr("Record GIF/WebP/APNG..."), "recordGIF", openNamedControllerTView(&m_gifView, true), "av"); + addGameAction(tr("Record A/V..."), "recordOutput", m_popups->videoView, "av"); + addGameAction(tr("Record GIF/WebP/APNG..."), "recordGIF", m_popups->gifView, "av"); #endif m_actions.addSeparator("av"); m_actions.addMenu(tr("Video layers"), "videoLayers", "av"); m_actions.addMenu(tr("Audio channels"), "audioChannels", "av"); - addGameAction(tr("Adjust layer placement..."), "placementControl", openControllerTView(), "av"); + addGameAction(tr("Adjust layer placement..."), "placementControl", PopupManager().withController(m_controller), "av"); m_actions.addMenu(tr("&Tools"), "tools"); - m_actions.addAction(tr("View &logs..."), "viewLogs", openNamedTView(&m_logView, true, &m_log, this), "tools"); - m_overrideView.withController(m_controller).constructWith(m_config, this); - m_actions.addAction(tr("Game &overrides..."), "overrideWindow", m_overrideView, "tools"); - m_actions.addAction(tr("Game Pak sensors..."), "sensorWindow", openNamedControllerTView(&m_sensorView, true, &m_inputController, this), "tools"); + m_actions.addAction(tr("View &logs..."), "viewLogs", m_popups->logView, "tools"); + m_actions.addAction(tr("Game &overrides..."), "overrideWindow", m_popups->overrideView, "tools"); + m_actions.addAction(tr("Game Pak sensors..."), "sensorWindow", m_popups->sensorView, "tools"); - addGameAction(tr("&Cheats..."), "cheatsWindow", openNamedControllerTView(&m_cheatsView, false), "tools"); + addGameAction(tr("&Cheats..."), "cheatsWindow", m_popups->cheatsView, "tools"); #ifdef ENABLE_SCRIPTING m_actions.addAction(tr("Scripting..."), "scripting", this, &Window::scriptingOpen, "tools"); #endif - m_actions.addAction(tr("Create forwarder..."), "createForwarder", openTViewModal(this), "tools"); + m_actions.addAction(tr("Create forwarder..."), "createForwarder", PopupManager(), "tools"); m_actions.addSeparator("tools"); m_actions.addAction(tr("Settings..."), "settings", this, &Window::openSettingsWindow, "tools")->setRole(Action::Role::SETTINGS); @@ -1752,14 +1718,14 @@ void Window::setupMenu(QMenuBar* menubar) { #endif m_actions.addMenu(tr("Game state views"), "stateViews", "tools"); - addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView(), "stateViews"); - addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView(), "stateViews"); - addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView(), "stateViews"); - addGameAction(tr("View &map..."), "mapWindow", openControllerTView(), "stateViews"); - addGameAction(tr("&Frame inspector..."), "frameWindow", openNamedControllerTView(&m_frameView, false), "stateViews"); - addGameAction(tr("View memory..."), "memoryView", openControllerTView(), "stateViews"); - addGameAction(tr("Search memory..."), "memorySearch", openControllerTView(), "stateViews"); - addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView(), "stateViews"); + addGameAction(tr("View &palette..."), "paletteWindow", PopupManager().withController(m_controller), "stateViews"); + addGameAction(tr("View &sprites..."), "spriteWindow", PopupManager().withController(m_controller), "stateViews"); + addGameAction(tr("View &tiles..."), "tileWindow", PopupManager().withController(m_controller), "stateViews"); + addGameAction(tr("View &map..."), "mapWindow", PopupManager().withController(m_controller), "stateViews"); + addGameAction(tr("&Frame inspector..."), "frameWindow", m_popups->frameView, "stateViews"); + addGameAction(tr("View memory..."), "memoryView", PopupManager().withController(m_controller), "stateViews"); + addGameAction(tr("Search memory..."), "memorySearch", PopupManager().withController(m_controller), "stateViews"); + addGameAction(tr("View &I/O registers..."), "ioViewer", PopupManager().withController(m_controller), "stateViews"); #ifdef ENABLE_DEBUGGERS addGameAction(tr("Log memory &accesses..."), "memoryAccessView", [this]() { @@ -2147,6 +2113,7 @@ void Window::setController(CoreController* controller, const QString& fname) { }); return; } + if (!fname.isEmpty()) { setWindowFilePath(fname); appendMRU(fname); @@ -2221,20 +2188,6 @@ void Window::setController(CoreController* controller, const QString& fname) { } #endif -#ifdef USE_FFMPEG - if (m_gifView) { - m_gifView->setController(m_controller); - } - - if (m_videoView) { - m_videoView->setController(m_controller); - } -#endif - - if (m_sensorView) { - m_sensorView->setController(m_controller); - } - if (!m_pendingPatch.isEmpty()) { m_controller->loadPatch(m_pendingPatch); m_pendingPatch = QString(); diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index b3a96895b..3ed4646e4 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -19,11 +19,11 @@ #include #include "ActionMapper.h" +#include "CoreConsumer.h" #include "InputController.h" #include "LoadSaveState.h" #include "LogController.h" #include "OverrideView.h" -#include "PopupManager.h" #include "SettingsView.h" #ifdef ENABLE_SCRIPTING #include "scripting/ScriptingController.h" @@ -32,24 +32,17 @@ namespace QGBA { class AudioProcessor; -class CheatsView; class ConfigController; class CoreController; class CoreManager; class DebuggerConsoleController; class Display; -class DolphinConnector; -class FrameView; class GDBController; -class GIFView; class LibraryController; -class LogView; -class OverrideView; -class SensorView; class ShaderSelector; class ShortcutController; -class VideoView; class WindowBackground; +class WindowPopups; class Window : public QMainWindow { Q_OBJECT @@ -167,6 +160,7 @@ private: static const int FPS_TIMER_INTERVAL = 2000; static const int MUST_RESTART_TIMEOUT = 10000; + void setupPopups(); void setupMenu(QMenuBar*); void setupOptions(); void openStateWindow(LoadSave); @@ -180,12 +174,6 @@ private: void ensureScripting(); - template std::function openTView(A... arg); - template std::function openTViewModal(A... arg); - template std::function openControllerTView(A... arg); - template std::function openNamedTView(QPointer*, bool keepalive, A... arg); - template std::function openNamedControllerTView(QPointer*, bool keepalive, A... arg); - std::shared_ptr addGameAction(const QString& visibleName, const QString& name, Action::Function action, const QString& menu = {}, const QKeySequence& = {}); template std::shared_ptr addGameAction(const QString& visibleName, const QString& name, T* obj, V (T::*action)(), const QString& menu = {}, const QKeySequence& = {}); template std::shared_ptr addGameAction(const QString& visibleName, const QString& name, V (CoreController::*action)(), const QString& menu = {}, const QKeySequence& = {}); @@ -213,7 +201,6 @@ private: QMap> m_frameSizes; LogController m_log{0}; - QPointer m_logView; #ifdef ENABLE_DEBUGGERS DebuggerConsoleController* m_console = nullptr; #endif @@ -247,16 +234,7 @@ private: bool m_multiActive = true; int m_playerId; - PopupManager m_overrideView; - QPointer m_sensorView; - QPointer m_dolphinView; - QPointer m_frameView; - QPointer m_cheatsView; - -#ifdef USE_FFMPEG - QPointer m_videoView; - QPointer m_gifView; -#endif + std::unique_ptr m_popups; #ifdef ENABLE_GDB_STUB GDBController* m_gdbController = nullptr;