summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/debugger/debugqt.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2022-09-20 04:22:51 +1000
committer Vas Crabb <vas@vastheman.com>2022-09-20 04:22:51 +1000
commit76541e8c81f1a38707bd4d1c973f6e4f86478de5 (patch)
treecfb6ba0d92911763ae0fa56be563cf81612c7ab7 /src/osd/modules/debugger/debugqt.cpp
parent05d3b10a6c6223b7a384a4aa02ad9d55923d778d (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.cpp305
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")