From 21f58a35bcc07da9bd84006a0602016b0a95e0f0 Mon Sep 17 00:00:00 2001 From: TryTwo Date: Wed, 26 Mar 2025 11:20:10 -0700 Subject: [PATCH] CodeWidget: Change address bar into a combobox that can save addresses. Add a button to save an address to the combobox. --- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 90 +++++++++++++++++-- Source/Core/DolphinQt/Debugger/CodeWidget.h | 21 ++++- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index a04f761cee..3c1f25b353 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -7,9 +7,11 @@ #include +#include #include #include #include +#include #include #include #include @@ -35,10 +37,33 @@ #include "DolphinQt/Resources.h" #include "DolphinQt/Settings.h" +constexpr int MAX_SEARCH_ITEMS = 16; + static const QString BOX_SPLITTER_STYLESHEET = QStringLiteral( "QSplitter::handle { border-top: 1px dashed black; width: 1px; margin-left: 10px; " "margin-right: 10px; }"); +bool DeleteAddressEventFilter::eventFilter(QObject* object, QEvent* event) +{ + if (event->type() == QEvent::KeyPress) + { + QKeyEvent* key_event = static_cast(event); + if (key_event->key() == Qt::Key_Delete && m_combo_box->view()->isVisible()) + { + const int row = m_combo_box->view()->currentIndex().row(); + m_combo_box->removeItem(row); + return true; + } + // Disable up/down key navigation when the ComboBox is closed. Alt/Shift up/down are still + // allowed. + if (key_event->key() == Qt::Key_Down || key_event->key() == Qt::Key_Up) + if (!m_combo_box->view()->isVisible() && key_event->modifiers() == Qt::NoModifier) + return true; + } + + return false; +} + CodeWidget::CodeWidget(QWidget* parent) : QDockWidget(parent), m_system(Core::System::GetInstance()), m_ppc_symbol_db(m_system.GetPPCSymbolDB()) @@ -109,8 +134,24 @@ void CodeWidget::CreateWidgets() layout->setSpacing(0); auto* top_layout = new QHBoxLayout; - m_search_address = new QLineEdit; - m_search_address->setPlaceholderText(tr("Search Address")); + m_search_address = new QComboBox; + auto* search_address_filter = new DeleteAddressEventFilter(m_search_address); + m_search_address->installEventFilter(search_address_filter); + m_search_address->view()->installEventFilter(search_address_filter); + m_search_address->setInsertPolicy(QComboBox::InsertAtTop); + m_search_address->setDuplicatesEnabled(false); + m_search_address->setEditable(true); + m_search_address->lineEdit()->setPlaceholderText(tr("Search address")); + m_search_address->setMaxVisibleItems(MAX_SEARCH_ITEMS); + m_search_address->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_search_address->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + + m_save_address_btn = new QToolButton(); + m_save_address_btn->setIcon(Resources::GetThemeIcon("debugger_save")); + // 24 is a standard button height. + m_save_address_btn->setMinimumSize(24, 24); + m_save_address_btn->setToolTip(tr("Save address to the address box dropdown. Highlight an " + "address and press Delete to clear it.")); m_lock_btn = new QToolButton(); m_lock_btn->setIcon(Resources::GetThemeIcon("pause")); @@ -120,6 +161,7 @@ void CodeWidget::CreateWidgets() m_branch_watch = new QPushButton(tr("Branch Watch")); top_layout->addWidget(m_search_address); + top_layout->addWidget(m_save_address_btn); top_layout->addWidget(m_lock_btn); top_layout->addWidget(m_branch_watch); @@ -199,10 +241,11 @@ void CodeWidget::ConnectWidgets() }); #endif - connect(m_search_address, &QLineEdit::textChanged, this, &CodeWidget::OnSearchAddress); - connect(m_search_address, &QLineEdit::returnPressed, this, &CodeWidget::OnSearchAddress); + connect(m_search_address, &QComboBox::currentTextChanged, this, &CodeWidget::OnSearchAddress); + connect(m_search_address, &QComboBox::activated, this, &CodeWidget::OnSearchAddress); connect(m_lock_btn, &QPushButton::toggled, m_code_view, &CodeViewWidget::OnLockAddress); connect(m_search_symbols, &QLineEdit::textChanged, this, &CodeWidget::OnSearchSymbols); + connect(m_save_address_btn, &QPushButton::pressed, this, &CodeWidget::OnSaveAddress); connect(m_search_calls, &QLineEdit::textChanged, this, [this] { if (const Common::Symbol* symbol = m_ppc_symbol_db.GetSymbolFromAddr(m_code_view->GetAddress())) UpdateFunctionCalls(symbol); @@ -259,21 +302,54 @@ void CodeWidget::OnPPCSymbolsChanged() UpdateFunctionCallers(symbol); } +void CodeWidget::OnSaveAddress() +{ + if (Core::GetState(m_system) != Core::State::Paused) + return; + + u32 addr = m_code_view->GetAddress(); + + Core::CPUThreadGuard guard(m_system); + + if (!PowerPC::MMU::HostIsRAMAddress(guard, addr)) + return; + + std::string instruction = m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); + std::replace(instruction.begin(), instruction.end(), '\t', ' '); + const std::string symbol = m_system.GetPowerPC().GetDebugInterface().GetDescription(addr); + + std::string text = fmt::format("{:08x} {}", addr, instruction); + if (symbol != " --- ") + text = fmt::format("{} -- {}", text, symbol); + + const int existing_entry = m_search_address->findData(addr); + if (existing_entry != -1) + { + m_search_address->setItemText(existing_entry, QString::fromStdString(text)); + return; + } + + m_search_address->insertItem(0, QString::fromStdString(text), addr); +} + void CodeWidget::ActivateSearchAddress() { m_search_address->setFocus(); - m_search_address->selectAll(); + m_search_address->lineEdit()->selectAll(); } void CodeWidget::OnSearchAddress() { bool good = true; - u32 address = m_search_address->text().toUInt(&good, 16); + u32 address = m_search_address->currentData().toUInt(&good); + + if (!good) + address = m_search_address->currentText().toUInt(&good, 16); QPalette palette; QFont font; - if (!good && !m_search_address->text().isEmpty()) + if (!good && !m_search_address->currentText().isEmpty()) { font.setBold(true); palette.setColor(QPalette::Text, Qt::red); diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.h b/Source/Core/DolphinQt/Debugger/CodeWidget.h index 76ada4f506..d7468cba83 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.h +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include @@ -11,6 +12,7 @@ class BranchWatchDialog; class QCloseEvent; +class QComboBox; class QLineEdit; class QShowEvent; class QSplitter; @@ -29,6 +31,21 @@ class System; } class PPCSymbolDB; +class DeleteAddressEventFilter final : public QObject +{ + Q_OBJECT +public: + explicit DeleteAddressEventFilter(QComboBox* combo_box) + : QObject(combo_box), m_combo_box(combo_box) + { + } + using QObject::QObject; + +private: + QComboBox* m_combo_box; + bool eventFilter(QObject* object, QEvent* event) override; +}; + class CodeWidget : public QDockWidget { Q_OBJECT @@ -65,6 +82,7 @@ private: void UpdateNotes(); void OnPPCSymbolsChanged(); + void OnSaveAddress(); void OnSearchAddress(); void OnSearchSymbols(); void OnSelectSymbol(); @@ -80,7 +98,8 @@ private: PPCSymbolDB& m_ppc_symbol_db; BranchWatchDialog* m_branch_watch_dialog = nullptr; - QLineEdit* m_search_address; + QComboBox* m_search_address; + QToolButton* m_save_address_btn; QToolButton* m_lock_btn; QPushButton* m_branch_watch;