diff options
author | 2022-09-20 04:22:51 +1000 | |
---|---|---|
committer | 2022-09-20 04:22:51 +1000 | |
commit | 76541e8c81f1a38707bd4d1c973f6e4f86478de5 (patch) | |
tree | cfb6ba0d92911763ae0fa56be563cf81612c7ab7 /src/osd/modules/debugger/debugqt.cpp | |
parent | 05d3b10a6c6223b7a384a4aa02ad9d55923d778d (diff) |
Debugger updates:
Made closing the Qt debugger console window hide all debugger windows
and run the emulated machine (debugger windows will be shown on next
user break or breakpoint hit). This matches the behaviour of the Win32
and Cocoa debuggers.
Made Qt debugger clean up its windows on exit rather than on subsequent
starts. This fixes GitHub #9789.
Made Qt debugger less reliant on global variables, and made code to save
and load configuration a bit less convoluted. It still needs more
refactoring on this front, but it's in slightly better shape now.
Made Qt debugger a bit less crashy on invalid configuration. Still
plenty of ways to crash it, but every little bit counts.
Made Qt debugger do less comparisons on menu item names and object
names - it might be possible to localise one day.
Moved all the C++ debugger implementations into namespaces. They're
using awfully generic class names, so it's about time.
Diffstat (limited to 'src/osd/modules/debugger/debugqt.cpp')
-rw-r--r-- | src/osd/modules/debugger/debugqt.cpp | 305 |
1 files changed, 127 insertions, 178 deletions
diff --git a/src/osd/modules/debugger/debugqt.cpp b/src/osd/modules/debugger/debugqt.cpp index cb09b08f0dc..9d87cfef5c8 100644 --- a/src/osd/modules/debugger/debugqt.cpp +++ b/src/osd/modules/debugger/debugqt.cpp @@ -35,39 +35,57 @@ #include "util/xmlfile.h" +#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) +extern int sdl_entered_debugger; +#elif defined(_WIN32) +void winwindow_update_cursor_state(running_machine &machine); +bool winwindow_qt_filter(void *message); +#endif + + +namespace { + class debug_qt : public osd_module, public debug_module #if defined(_WIN32) && !defined(SDLMAME_WIN32) , public QAbstractNativeEventFilter #endif { public: - debug_qt() : osd_module(OSD_DEBUG_PROVIDER, "qt"), debug_module(), m_machine(nullptr) + debug_qt() : + osd_module(OSD_DEBUG_PROVIDER, "qt"), + debug_module(), + m_machine(nullptr), + m_mainwindow(nullptr) { } virtual ~debug_qt() { } virtual int init(const osd_options &options) { return 0; } - virtual void exit() { } + virtual void exit(); virtual void init_debugger(running_machine &machine); virtual void wait_for_debugger(device_t &device, bool firststop); virtual void debugger_update(); #if defined(_WIN32) && !defined(SDLMAME_WIN32) - virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE; + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override + { + winwindow_qt_filter(message); + return false; + } #endif private: + void configuration_load(config_type which_type, config_level level, util::xml::data_node const *parentnode); void configuration_save(config_type which_type, util::xml::data_node *parentnode); - void gather_save_configurations(); + void load_window_configurations(util::xml::data_node const &parentnode); running_machine *m_machine; + osd::debugger::qt::MainWindow *m_mainwindow; util::xml::file::ptr m_config; }; -namespace { - //============================================================ // "Global" variables to make QT happy //============================================================ @@ -76,122 +94,21 @@ int qtArgc = 1; char qtArg0[] = "mame"; char *qtArgv[] = { qtArg0, nullptr }; -bool oneShot = true; -MainWindow *mainQtWindow = nullptr; - -//============================================================ -// XML configuration save/load -//============================================================ - -// Global variable used to feed the xml configuration callbacks -std::vector<std::unique_ptr<WindowQtConfig> > xmlConfigurations; - - -void xml_configuration_load(running_machine &machine, config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) -{ - // We only care about system configuration files - if ((cfg_type != config_type::SYSTEM) || !parentnode) - return; - - xmlConfigurations.clear(); - - // Configuration load - util::xml::data_node const *wnode = nullptr; - for (wnode = parentnode->get_child(osd::debugger::NODE_WINDOW); wnode; wnode = wnode->get_next_sibling(osd::debugger::NODE_WINDOW)) - { - switch (wnode->get_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, -1)) - { - case osd::debugger::WINDOW_TYPE_CONSOLE: xmlConfigurations.push_back(std::make_unique<MainWindowQtConfig>()); break; - case osd::debugger::WINDOW_TYPE_MEMORY_VIEWER: xmlConfigurations.push_back(std::make_unique<MemoryWindowQtConfig>()); break; - case osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: xmlConfigurations.push_back(std::make_unique<DasmWindowQtConfig>()); break; - case osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: xmlConfigurations.push_back(std::make_unique<LogWindowQtConfig>()); break; - case osd::debugger::WINDOW_TYPE_POINTS_VIEWER: xmlConfigurations.push_back(std::make_unique<BreakpointsWindowQtConfig>()); break; - case osd::debugger::WINDOW_TYPE_DEVICES_VIEWER: xmlConfigurations.push_back(std::make_unique<DevicesWindowQtConfig>()); break; - case osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: xmlConfigurations.push_back(std::make_unique<DeviceInformationWindowQtConfig>()); break; - default: continue; - } - xmlConfigurations.back()->recoverFromXmlNode(*wnode); - } -} - - -//============================================================ -// Utilities -//============================================================ - -void load_and_clear_main_window_config(std::vector<std::unique_ptr<WindowQtConfig> > &configList) -{ - for (int i = 0; i < configList.size(); i++) - { - WindowQtConfig &config = *configList[i]; - if (config.m_type == osd::debugger::WINDOW_TYPE_CONSOLE) - { - config.applyToQWidget(mainQtWindow); - configList.erase(configList.begin() + i); - break; - } - } -} - - -void setup_additional_startup_windows(running_machine &machine, std::vector<std::unique_ptr<WindowQtConfig> > &configList) -{ - for (int i = 0; i < configList.size(); i++) - { - WindowQtConfig &config = *configList[i]; - - WindowQt *foo = nullptr; - switch (config.m_type) - { - case osd::debugger::WINDOW_TYPE_MEMORY_VIEWER: - foo = new MemoryWindow(machine); break; - case osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: - foo = new DasmWindow(machine); break; - case osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: - foo = new LogWindow(machine); break; - case osd::debugger::WINDOW_TYPE_POINTS_VIEWER: - foo = new BreakpointsWindow(machine); break; - case osd::debugger::WINDOW_TYPE_DEVICES_VIEWER: - foo = new DevicesWindow(machine); break; - case osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: - foo = new DeviceInformationWindow(machine); break; - default: - break; - } - config.applyToQWidget(foo); - foo->show(); - } -} - - -void bring_main_window_to_front() -{ - foreach (QWidget *widget, QApplication::topLevelWidgets()) - { - if (dynamic_cast<MainWindow *>(widget)) - { - widget->activateWindow(); - widget->raise(); - } - } -} - -} // anonymous namespace - //============================================================ // Core functionality //============================================================ -#if defined(_WIN32) && !defined(SDLMAME_WIN32) -bool winwindow_qt_filter(void *message); - -bool debug_qt::nativeEventFilter(const QByteArray &eventType, void *message, long *) +void debug_qt::exit() { - winwindow_qt_filter(message); - return false; + // If you've done a hard reset, clear out existing widgets + if (m_mainwindow) + m_mainwindow->setExiting(); + QApplication::closeAllWindows(); + qApp->processEvents(QEventLoop::AllEvents, 1); + m_mainwindow = nullptr; } -#endif + void debug_qt::init_debugger(running_machine &machine) { @@ -203,23 +120,12 @@ void debug_qt::init_debugger(running_machine &machine) QAbstractEventDispatcher::instance()->installNativeEventFilter(this); #endif } - else - { - // If you've done a hard reset, clear out existing widgets & get ready for re-init - foreach (QWidget *widget, QApplication::topLevelWidgets()) - { - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - delete widget; - } - oneShot = true; - } m_machine = &machine; // Setup the configuration XML saving and loading machine.configuration().config_register("debugger", - configuration_manager::load_delegate(&xml_configuration_load, &machine), + configuration_manager::load_delegate(&debug_qt::configuration_load, this), configuration_manager::save_delegate(&debug_qt::configuration_save, this)); } @@ -228,12 +134,6 @@ void debug_qt::init_debugger(running_machine &machine) // Core functionality //============================================================ -#if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) -extern int sdl_entered_debugger; -#elif defined(_WIN32) -void winwindow_update_cursor_state(running_machine &machine); -#endif - void debug_qt::wait_for_debugger(device_t &device, bool firststop) { #if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) @@ -241,61 +141,55 @@ void debug_qt::wait_for_debugger(device_t &device, bool firststop) #endif // Dialog initialization - if (oneShot) + if (!m_mainwindow) { - mainQtWindow = new MainWindow(*m_machine); - load_and_clear_main_window_config(xmlConfigurations); - setup_additional_startup_windows(*m_machine, xmlConfigurations); - mainQtWindow->show(); - oneShot = false; + m_mainwindow = new osd::debugger::qt::MainWindow(*m_machine); + if (m_config) + { + load_window_configurations(*m_config->get_first_child()); + m_config.reset(); + } + m_mainwindow->show(); } // Ensure all top level widgets are visible & bring main window to front foreach (QWidget *widget, QApplication::topLevelWidgets()) { - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - widget->show(); + if (widget->isWindow() && (widget->windowType() == Qt::Window)) + widget->show(); } if (firststop) - bring_main_window_to_front(); + { + m_mainwindow->activateWindow(); + m_mainwindow->raise(); + } // Set the main window to display the proper cpu - mainQtWindow->setProcessor(&device); + m_mainwindow->setProcessor(&device); // Run our own QT event loop osd_sleep(osd_ticks_per_second() / 1000 * 50); qApp->processEvents(QEventLoop::AllEvents, 1); // Refresh everyone if requested - if (mainQtWindow->wantsRefresh()) + if (m_mainwindow->wantsRefresh()) { QWidgetList allWidgets = qApp->allWidgets(); for (int i = 0; i < allWidgets.length(); i++) allWidgets[i]->update(); - mainQtWindow->clearRefreshFlag(); + m_mainwindow->clearRefreshFlag(); } // Hide all top level widgets if requested - if (mainQtWindow->wantsHide()) + if (m_mainwindow->wantsHide()) { foreach (QWidget *widget, QApplication::topLevelWidgets()) { - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - widget->hide(); + if (widget->isWindow() && (widget->windowType() == Qt::Window)) + widget->hide(); } - mainQtWindow->clearHideFlag(); - } - - // Exit if the machine has been instructed to do so (scheduled event == exit || hard_reset) - if (m_machine->scheduled_event_pending()) - { - // Keep a list of windows we want to save. - // We need to do this here because by the time xml_configuration_save gets called - // all the QT windows are already gone. - gather_save_configurations(); + m_mainwindow->clearHideFlag(); } #if defined(_WIN32) && !defined(SDLMAME_WIN32) @@ -314,37 +208,92 @@ void debug_qt::debugger_update() } -void debug_qt::configuration_save(config_type which_type, util::xml::data_node *parentnode) +void debug_qt::configuration_load(config_type which_type, config_level level, util::xml::data_node const *parentnode) { - // We only save system configuration for now - if ((config_type::SYSTEM == which_type) && parentnode && m_config) + // We only care about system configuration files for now + if ((config_type::SYSTEM == which_type) && parentnode) { - for (util::xml::data_node const *node = m_config->get_first_child(); node; node = node->get_next_sibling()) - node->copy_into(*parentnode); - m_config.reset(); + if (m_mainwindow) + { + load_window_configurations(*parentnode); + } + else + { + m_config = util::xml::file::create(); + parentnode->copy_into(*m_config); + } } } -void debug_qt::gather_save_configurations() +void debug_qt::configuration_save(config_type which_type, util::xml::data_node *parentnode) { - m_config = util::xml::file::create(); - - // Loop over all the open windows - foreach (QWidget *widget, QApplication::topLevelWidgets()) + // We only save system configuration for now + if ((config_type::SYSTEM == which_type) && parentnode) { - if (!widget->isVisible()) - continue; + // Loop over all the open windows + for (QWidget *widget : QApplication::topLevelWidgets()) + { + if (!widget->isWindow() || (widget->windowType() != Qt::Window)) + continue; + + osd::debugger::qt::WindowQt *const win = dynamic_cast<osd::debugger::qt::WindowQt *>(widget); + if (win) + win->saveConfiguration(*parentnode); + } + } +} - if (!widget->isWindow() || widget->windowType() != Qt::Window) - continue; - WindowQt *const win = dynamic_cast<WindowQt *>(widget); - if (win) - win->saveConfiguration(*m_config); +void debug_qt::load_window_configurations(util::xml::data_node const &parentnode) +{ + for (util::xml::data_node const *wnode = parentnode.get_child(osd::debugger::NODE_WINDOW); wnode; wnode = wnode->get_next_sibling(osd::debugger::NODE_WINDOW)) + { + std::unique_ptr<osd::debugger::qt::WindowQtConfig> cfg; + osd::debugger::qt::WindowQt *win = nullptr; + switch (wnode->get_attribute_int(osd::debugger::ATTR_WINDOW_TYPE, -1)) + { + case osd::debugger::WINDOW_TYPE_CONSOLE: + cfg = std::make_unique<osd::debugger::qt::MainWindowQtConfig>(); + break; + case osd::debugger::WINDOW_TYPE_MEMORY_VIEWER: + cfg = std::make_unique<osd::debugger::qt::MemoryWindowQtConfig>(); + win = new osd::debugger::qt::MemoryWindow(*m_machine); + break; + case osd::debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: + cfg = std::make_unique<osd::debugger::qt::DasmWindowQtConfig>(); + win = new osd::debugger::qt::DasmWindow(*m_machine); + break; + case osd::debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: + cfg = std::make_unique<osd::debugger::qt::LogWindowQtConfig>(); + win = new osd::debugger::qt::LogWindow(*m_machine); + break; + case osd::debugger::WINDOW_TYPE_POINTS_VIEWER: + cfg = std::make_unique<osd::debugger::qt::BreakpointsWindowQtConfig>(); + win = new osd::debugger::qt::BreakpointsWindow(*m_machine); + break; + case osd::debugger::WINDOW_TYPE_DEVICES_VIEWER: + cfg = std::make_unique<osd::debugger::qt::DevicesWindowQtConfig>(); + win = new osd::debugger::qt::DevicesWindow(*m_machine); + break; + case osd::debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: + cfg = std::make_unique<osd::debugger::qt::DeviceInformationWindowQtConfig>(); + win = new osd::debugger::qt::DeviceInformationWindow(*m_machine); + break; + } + if (cfg) + { + cfg->recoverFromXmlNode(*wnode); + if (win) + cfg->applyToQWidget(win); + else if (osd::debugger::WINDOW_TYPE_CONSOLE == cfg->m_type) + cfg->applyToQWidget(m_mainwindow); + } } } +} // anonymous namespace + #else // USE_QTDEBUG MODULE_NOT_SUPPORTED(debug_qt, OSD_DEBUG_PROVIDER, "qt") |