diff options
Diffstat (limited to 'src/osd/modules/debugger/qt/windowqt.cpp')
-rw-r--r-- | src/osd/modules/debugger/qt/windowqt.cpp | 264 |
1 files changed, 195 insertions, 69 deletions
diff --git a/src/osd/modules/debugger/qt/windowqt.cpp b/src/osd/modules/debugger/qt/windowqt.cpp index dda9ee64dc7..294871e6d22 100644 --- a/src/osd/modules/debugger/qt/windowqt.cpp +++ b/src/osd/modules/debugger/qt/windowqt.cpp @@ -1,104 +1,114 @@ // license:BSD-3-Clause // copyright-holders:Andrew Gardner #include "emu.h" -#include <QtWidgets/QMenu> -#include <QtWidgets/QMenuBar> - #include "windowqt.h" -#include "logwindow.h" -#include "dasmwindow.h" -#include "memorywindow.h" + #include "breakpointswindow.h" +#include "dasmwindow.h" #include "deviceswindow.h" +#include "logwindow.h" +#include "memorywindow.h" +#include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" -bool WindowQt::s_refreshAll = false; -bool WindowQt::s_hideAll = false; +#include "util/xmlfile.h" +#include <QtWidgets/QMenu> +#include <QtWidgets/QMenuBar> + + +namespace osd::debugger::qt { // Since all debug windows are intended to be top-level, this inherited // constructor is always called with a nullptr parent. The passed-in parent widget, // however, is often used to place each child window & the code to do this can // be found in most of the inherited classes. -WindowQt::WindowQt(running_machine* machine, QWidget* parent) : +WindowQt::WindowQt(DebuggerQt &debugger, QWidget *parent) : QMainWindow(parent), - m_machine(machine) + m_debugger(debugger), + m_machine(debugger.machine()) { setAttribute(Qt::WA_DeleteOnClose, true); + // Subscribe to signals + connect(&debugger, &DebuggerQt::exitDebugger, this, &WindowQt::debuggerExit); + connect(&debugger, &DebuggerQt::hideAllWindows, this, &WindowQt::hide); + connect(&debugger, &DebuggerQt::showAllWindows, this, &WindowQt::show); + connect(&debugger, &DebuggerQt::saveConfiguration, this, &WindowQt::saveConfiguration); + // The Debug menu bar - QAction* debugActOpenMemory = new QAction("New &Memory Window", this); + QAction *debugActOpenMemory = new QAction("New &Memory Window", this); debugActOpenMemory->setShortcut(QKeySequence("Ctrl+M")); connect(debugActOpenMemory, &QAction::triggered, this, &WindowQt::debugActOpenMemory); - QAction* debugActOpenDasm = new QAction("New &Dasm Window", this); + QAction *debugActOpenDasm = new QAction("New &Disassembly Window", this); debugActOpenDasm->setShortcut(QKeySequence("Ctrl+D")); connect(debugActOpenDasm, &QAction::triggered, this, &WindowQt::debugActOpenDasm); - QAction* debugActOpenLog = new QAction("New &Log Window", this); + QAction *debugActOpenLog = new QAction("New Error &Log Window", this); debugActOpenLog->setShortcut(QKeySequence("Ctrl+L")); connect(debugActOpenLog, &QAction::triggered, this, &WindowQt::debugActOpenLog); - QAction* debugActOpenPoints = new QAction("New &Break|Watchpoints Window", this); + QAction *debugActOpenPoints = new QAction("New (&Break|Watch)points Window", this); debugActOpenPoints->setShortcut(QKeySequence("Ctrl+B")); connect(debugActOpenPoints, &QAction::triggered, this, &WindowQt::debugActOpenPoints); - QAction* debugActOpenDevices = new QAction("New D&evices Window", this); - debugActOpenDevices->setShortcut(QKeySequence("Shift+Ctrl+D")); + QAction *debugActOpenDevices = new QAction("New D&evices Window", this); connect(debugActOpenDevices, &QAction::triggered, this, &WindowQt::debugActOpenDevices); - QAction* dbgActRun = new QAction("Run", this); + QAction *dbgActRun = new QAction("Run", this); dbgActRun->setShortcut(Qt::Key_F5); connect(dbgActRun, &QAction::triggered, this, &WindowQt::debugActRun); - QAction* dbgActRunAndHide = new QAction("Run And Hide Debugger", this); + QAction *dbgActRunAndHide = new QAction("Run And Hide Debugger", this); dbgActRunAndHide->setShortcut(Qt::Key_F12); connect(dbgActRunAndHide, &QAction::triggered, this, &WindowQt::debugActRunAndHide); - QAction* dbgActRunToNextCpu = new QAction("Run to Next CPU", this); + QAction *dbgActRunToNextCpu = new QAction("Run to Next CPU", this); dbgActRunToNextCpu->setShortcut(Qt::Key_F6); connect(dbgActRunToNextCpu, &QAction::triggered, this, &WindowQt::debugActRunToNextCpu); - QAction* dbgActRunNextInt = new QAction("Run to Next Interrupt on This CPU", this); + QAction *dbgActRunNextInt = new QAction("Run to Next Interrupt on This CPU", this); dbgActRunNextInt->setShortcut(Qt::Key_F7); connect(dbgActRunNextInt, &QAction::triggered, this, &WindowQt::debugActRunNextInt); - QAction* dbgActRunNextVBlank = new QAction("Run to Next VBlank", this); + QAction *dbgActRunNextVBlank = new QAction("Run to Next VBlank", this); dbgActRunNextVBlank->setShortcut(Qt::Key_F8); connect(dbgActRunNextVBlank, &QAction::triggered, this, &WindowQt::debugActRunNextVBlank); - QAction* dbgActStepInto = new QAction("Step Into", this); + QAction *dbgActStepInto = new QAction("Step Into", this); dbgActStepInto->setShortcut(Qt::Key_F11); connect(dbgActStepInto, &QAction::triggered, this, &WindowQt::debugActStepInto); - QAction* dbgActStepOver = new QAction("Step Over", this); + QAction *dbgActStepOver = new QAction("Step Over", this); dbgActStepOver->setShortcut(Qt::Key_F10); connect(dbgActStepOver, &QAction::triggered, this, &WindowQt::debugActStepOver); - QAction* dbgActStepOut = new QAction("Step Out", this); + QAction *dbgActStepOut = new QAction("Step Out", this); dbgActStepOut->setShortcut(QKeySequence("Shift+F11")); connect(dbgActStepOut, &QAction::triggered, this, &WindowQt::debugActStepOut); - QAction* dbgActSoftReset = new QAction("Soft Reset", this); + QAction *dbgActSoftReset = new QAction("Soft Reset", this); dbgActSoftReset->setShortcut(Qt::Key_F3); connect(dbgActSoftReset, &QAction::triggered, this, &WindowQt::debugActSoftReset); - QAction* dbgActHardReset = new QAction("Hard Reset", this); + QAction *dbgActHardReset = new QAction("Hard Reset", this); dbgActHardReset->setShortcut(QKeySequence("Shift+F3")); connect(dbgActHardReset, &QAction::triggered, this, &WindowQt::debugActHardReset); - QAction* dbgActClose = new QAction("Close &Window", this); + QAction *dbgActClose = new QAction("Close &Window", this); dbgActClose->setShortcut(QKeySequence::Close); connect(dbgActClose, &QAction::triggered, this, &WindowQt::debugActClose); - QAction* dbgActQuit = new QAction("&Quit", this); + QAction *dbgActQuit = new QAction("&Quit", this); dbgActQuit->setShortcut(QKeySequence::Quit); connect(dbgActQuit, &QAction::triggered, this, &WindowQt::debugActQuit); // Construct the menu - QMenu* debugMenu = menuBar()->addMenu("&Debug"); + QMenu *debugMenu = menuBar()->addMenu("&Debug"); debugMenu->addAction(debugActOpenMemory); debugMenu->addAction(debugActOpenDasm); debugMenu->addAction(debugActOpenLog); @@ -127,9 +137,10 @@ WindowQt::~WindowQt() { } + void WindowQt::debugActOpenMemory() { - MemoryWindow* foo = new MemoryWindow(m_machine, this); + MemoryWindow *foo = new MemoryWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -139,7 +150,7 @@ void WindowQt::debugActOpenMemory() void WindowQt::debugActOpenDasm() { - DasmWindow* foo = new DasmWindow(m_machine, this); + DasmWindow *foo = new DasmWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -149,7 +160,7 @@ void WindowQt::debugActOpenDasm() void WindowQt::debugActOpenLog() { - LogWindow* foo = new LogWindow(m_machine, this); + LogWindow *foo = new LogWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -159,7 +170,7 @@ void WindowQt::debugActOpenLog() void WindowQt::debugActOpenPoints() { - BreakpointsWindow* foo = new BreakpointsWindow(m_machine, this); + BreakpointsWindow *foo = new BreakpointsWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -169,7 +180,7 @@ void WindowQt::debugActOpenPoints() void WindowQt::debugActOpenDevices() { - DevicesWindow* foo = new DevicesWindow(m_machine, this); + DevicesWindow *foo = new DevicesWindow(m_debugger, this); // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon // foo->setWindowFlags(Qt::Dialog); // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint); @@ -179,54 +190,54 @@ void WindowQt::debugActOpenDevices() void WindowQt::debugActRun() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); + m_machine.debugger().console().get_visible_cpu()->debug()->go(); } void WindowQt::debugActRunAndHide() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go(); - hideAll(); + m_machine.debugger().console().get_visible_cpu()->debug()->go(); + m_debugger.hideAll(); } void WindowQt::debugActRunToNextCpu() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + m_machine.debugger().console().get_visible_cpu()->debug()->go_next_device(); } void WindowQt::debugActRunNextInt() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + m_machine.debugger().console().get_visible_cpu()->debug()->go_interrupt(); } void WindowQt::debugActRunNextVBlank() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + m_machine.debugger().console().get_visible_cpu()->debug()->go_vblank(); } void WindowQt::debugActStepInto() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step(); } void WindowQt::debugActStepOver() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step_over(); } void WindowQt::debugActStepOut() { - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step_out(); } void WindowQt::debugActSoftReset() { - m_machine->schedule_soft_reset(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->single_step(); + m_machine.schedule_soft_reset(); + m_machine.debugger().console().get_visible_cpu()->debug()->single_step(); } void WindowQt::debugActHardReset() { - m_machine->schedule_hard_reset(); + m_machine.schedule_hard_reset(); } void WindowQt::debugActClose() @@ -236,43 +247,158 @@ void WindowQt::debugActClose() void WindowQt::debugActQuit() { - m_machine->schedule_exit(); + m_machine.schedule_exit(); +} + +void WindowQt::debuggerExit() +{ + // this isn't called from a Qt event loop, so close() will leak the window object + delete this; +} + + +void WindowQt::restoreConfiguration(util::xml::data_node const &node) +{ + QPoint p(geometry().topLeft()); + p.setX(node.get_attribute_int(ATTR_WINDOW_POSITION_X, p.x())); + p.setY(node.get_attribute_int(ATTR_WINDOW_POSITION_Y, p.y())); + + QSize s(size()); + s.setWidth(node.get_attribute_int(ATTR_WINDOW_WIDTH, s.width())); + s.setHeight(node.get_attribute_int(ATTR_WINDOW_HEIGHT, s.height())); + + // TODO: sanity checks, restrict to screen area + + setGeometry(p.x(), p.y(), s.width(), s.height()); +} + + +void WindowQt::saveConfiguration(util::xml::data_node &parentnode) +{ + util::xml::data_node *const node = parentnode.add_child(NODE_WINDOW, nullptr); + if (node) + saveConfigurationToNode(*node); } -//========================================================================= -// WindowQtConfig -//========================================================================= -void WindowQtConfig::buildFromQWidget(QWidget* widget) +void WindowQt::saveConfigurationToNode(util::xml::data_node &node) { - m_position.setX(widget->geometry().topLeft().x()); - m_position.setY(widget->geometry().topLeft().y()); - m_size.setX(widget->size().width()); - m_size.setY(widget->size().height()); + node.set_attribute_int(ATTR_WINDOW_POSITION_X, geometry().topLeft().x()); + node.set_attribute_int(ATTR_WINDOW_POSITION_Y, geometry().topLeft().y()); + node.set_attribute_int(ATTR_WINDOW_WIDTH, size().width()); + node.set_attribute_int(ATTR_WINDOW_HEIGHT, size().height()); } -void WindowQtConfig::applyToQWidget(QWidget* widget) +CommandHistory::CommandHistory() : + m_history(), + m_current(), + m_position(-1) { - widget->setGeometry(m_position.x(), m_position.y(), m_size.x(), m_size.y()); } -void WindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const +CommandHistory::~CommandHistory() { - node.set_attribute_int("type", m_type); - node.set_attribute_int("position_x", m_position.x()); - node.set_attribute_int("position_y", m_position.y()); - node.set_attribute_int("size_x", m_size.x()); - node.set_attribute_int("size_y", m_size.y()); } -void WindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node) +void CommandHistory::add(QString const &entry) { - m_size.setX(node.get_attribute_int("size_x", m_size.x())); - m_size.setY(node.get_attribute_int("size_y", m_size.y())); - m_position.setX(node.get_attribute_int("position_x", m_position.x())); - m_position.setY(node.get_attribute_int("position_y", m_position.y())); - m_type = (WindowQtConfig::WindowType)node.get_attribute_int("type", m_type); + if (m_history.empty() || (m_history.front() != entry)) + { + while (m_history.size() >= CAPACITY) + m_history.pop_back(); + m_history.push_front(entry); + } + m_position = 0; } + + +QString const *CommandHistory::previous(QString const ¤t) +{ + if ((m_position + 1) < m_history.size()) + { + if (0 > m_position) + m_current = std::make_unique<QString>(current); + return &m_history[++m_position]; + } + else + { + return nullptr; + } +} + + +QString const *CommandHistory::next(QString const ¤t) +{ + if (0 < m_position) + { + return &m_history[--m_position]; + } + else if (!m_position && m_current && (m_history.front() != *m_current)) + { + --m_position; + return m_current.get(); + } + else + { + return nullptr; + } +} + + +void CommandHistory::edit() +{ + if (!m_position) + --m_position; +} + + +void CommandHistory::reset() +{ + m_position = -1; + m_current.reset(); +} + + +void CommandHistory::clear() +{ + m_position = -1; + m_current.reset(); + m_history.clear(); +} + + +void CommandHistory::restoreConfigurationFromNode(util::xml::data_node const &node) +{ + clear(); + util::xml::data_node const *const historynode = node.get_child(NODE_WINDOW_HISTORY); + if (historynode) + { + util::xml::data_node const *itemnode = historynode->get_child(NODE_HISTORY_ITEM); + while (itemnode) + { + if (itemnode->get_value() && *itemnode->get_value()) + { + while (m_history.size() >= CAPACITY) + m_history.pop_back(); + m_history.push_front(QString::fromUtf8(itemnode->get_value())); + } + itemnode = itemnode->get_next_sibling(NODE_HISTORY_ITEM); + } + } +} + + +void CommandHistory::saveConfigurationToNode(util::xml::data_node &node) +{ + util::xml::data_node *const historynode = node.add_child(NODE_WINDOW_HISTORY, nullptr); + if (historynode) + { + for (auto it = m_history.crbegin(); m_history.crend() != it; ++it) + historynode->add_child(NODE_HISTORY_ITEM, it->toUtf8().data()); + } +} + +} // namespace osd::debugger::qt |