mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
CodeWidget: Change address bar into a combobox that can save addresses. Add a button to save an address to the combobox.
This commit is contained in:
parent
2719a5673e
commit
b403a23085
@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
#include <QKeyEvent>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
@ -35,10 +37,29 @@
|
|||||||
#include "DolphinQt/Resources.h"
|
#include "DolphinQt/Resources.h"
|
||||||
#include "DolphinQt/Settings.h"
|
#include "DolphinQt/Settings.h"
|
||||||
|
|
||||||
|
constexpr int MAX_SEARCH_ITEMS = 16;
|
||||||
|
|
||||||
static const QString BOX_SPLITTER_STYLESHEET = QStringLiteral(
|
static const QString BOX_SPLITTER_STYLESHEET = QStringLiteral(
|
||||||
"QSplitter::handle { border-top: 1px dashed black; width: 1px; margin-left: 10px; "
|
"QSplitter::handle { border-top: 1px dashed black; width: 1px; margin-left: 10px; "
|
||||||
"margin-right: 10px; }");
|
"margin-right: 10px; }");
|
||||||
|
|
||||||
|
bool DeleteAddressEventFilter::eventFilter(QObject* object, QEvent* event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::KeyPress)
|
||||||
|
{
|
||||||
|
QKeyEvent* key_event = static_cast<QKeyEvent*>(event);
|
||||||
|
if (key_event->key() == Qt::Key_Delete)
|
||||||
|
{
|
||||||
|
const int row = m_combo_box->view()->currentIndex().row();
|
||||||
|
if (row != m_combo_box->count() - 1)
|
||||||
|
m_combo_box->removeItem(row);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CodeWidget::CodeWidget(QWidget* parent)
|
CodeWidget::CodeWidget(QWidget* parent)
|
||||||
: QDockWidget(parent), m_system(Core::System::GetInstance()),
|
: QDockWidget(parent), m_system(Core::System::GetInstance()),
|
||||||
m_ppc_symbol_db(m_system.GetPPCSymbolDB())
|
m_ppc_symbol_db(m_system.GetPPCSymbolDB())
|
||||||
@ -109,8 +130,23 @@ void CodeWidget::CreateWidgets()
|
|||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
|
|
||||||
auto* top_layout = new QHBoxLayout;
|
auto* top_layout = new QHBoxLayout;
|
||||||
m_search_address = new QLineEdit;
|
m_search_address = new QComboBox;
|
||||||
m_search_address->setPlaceholderText(tr("Search Address"));
|
m_search_address->view()->installEventFilter(new DeleteAddressEventFilter(m_search_address));
|
||||||
|
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->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||||
|
// "Clear all" is always at the bottom of the ComboBox and cannot be in the search field.
|
||||||
|
m_search_address->addItem(tr("Clear all"));
|
||||||
|
m_search_address->setCurrentIndex(-1);
|
||||||
|
|
||||||
|
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."));
|
||||||
|
|
||||||
m_lock_btn = new QToolButton();
|
m_lock_btn = new QToolButton();
|
||||||
m_lock_btn->setIcon(Resources::GetThemeIcon("pause"));
|
m_lock_btn->setIcon(Resources::GetThemeIcon("pause"));
|
||||||
@ -120,6 +156,7 @@ void CodeWidget::CreateWidgets()
|
|||||||
m_branch_watch = new QPushButton(tr("Branch Watch"));
|
m_branch_watch = new QPushButton(tr("Branch Watch"));
|
||||||
|
|
||||||
top_layout->addWidget(m_search_address);
|
top_layout->addWidget(m_search_address);
|
||||||
|
top_layout->addWidget(m_save_address_btn);
|
||||||
top_layout->addWidget(m_lock_btn);
|
top_layout->addWidget(m_lock_btn);
|
||||||
top_layout->addWidget(m_branch_watch);
|
top_layout->addWidget(m_branch_watch);
|
||||||
|
|
||||||
@ -199,10 +236,11 @@ void CodeWidget::ConnectWidgets()
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(m_search_address, &QLineEdit::textChanged, this, &CodeWidget::OnSearchAddress);
|
connect(m_search_address, &QComboBox::currentTextChanged, this, &CodeWidget::OnSearchAddress);
|
||||||
connect(m_search_address, &QLineEdit::returnPressed, 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_lock_btn, &QPushButton::toggled, m_code_view, &CodeViewWidget::OnLockAddress);
|
||||||
connect(m_search_symbols, &QLineEdit::textChanged, this, &CodeWidget::OnSearchSymbols);
|
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] {
|
connect(m_search_calls, &QLineEdit::textChanged, this, [this] {
|
||||||
if (const Common::Symbol* symbol = m_ppc_symbol_db.GetSymbolFromAddr(m_code_view->GetAddress()))
|
if (const Common::Symbol* symbol = m_ppc_symbol_db.GetSymbolFromAddr(m_code_view->GetAddress()))
|
||||||
UpdateFunctionCalls(symbol);
|
UpdateFunctionCalls(symbol);
|
||||||
@ -259,21 +297,69 @@ void CodeWidget::OnPPCSymbolsChanged()
|
|||||||
UpdateFunctionCallers(symbol);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAX_SEARCH_ITEMS - 2 is that index of the oldest address, -1 is the clear text option.
|
||||||
|
if (m_search_address->count() == MAX_SEARCH_ITEMS)
|
||||||
|
m_search_address->removeItem(MAX_SEARCH_ITEMS - 2);
|
||||||
|
|
||||||
|
m_search_address->insertItem(0, QString::fromStdString(text), addr);
|
||||||
|
}
|
||||||
|
|
||||||
void CodeWidget::ActivateSearchAddress()
|
void CodeWidget::ActivateSearchAddress()
|
||||||
{
|
{
|
||||||
m_search_address->setFocus();
|
m_search_address->setFocus();
|
||||||
m_search_address->selectAll();
|
m_search_address->lineEdit()->selectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeWidget::OnSearchAddress()
|
void CodeWidget::OnSearchAddress()
|
||||||
{
|
{
|
||||||
|
// If "Clear all" is selected
|
||||||
|
if (m_search_address->currentIndex() == m_search_address->count() - 1)
|
||||||
|
{
|
||||||
|
m_search_address->blockSignals(true);
|
||||||
|
m_search_address->clear();
|
||||||
|
m_search_address->addItem(tr("Clear all"));
|
||||||
|
m_search_address->setCurrentIndex(-1);
|
||||||
|
m_search_address->blockSignals(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool good = true;
|
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;
|
QPalette palette;
|
||||||
QFont font;
|
QFont font;
|
||||||
|
|
||||||
if (!good && !m_search_address->text().isEmpty())
|
if (!good && !m_search_address->currentText().isEmpty())
|
||||||
{
|
{
|
||||||
font.setBold(true);
|
font.setBold(true);
|
||||||
palette.setColor(QPalette::Text, Qt::red);
|
palette.setColor(QPalette::Text, Qt::red);
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
@ -11,6 +12,7 @@
|
|||||||
|
|
||||||
class BranchWatchDialog;
|
class BranchWatchDialog;
|
||||||
class QCloseEvent;
|
class QCloseEvent;
|
||||||
|
class QComboBox;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QShowEvent;
|
class QShowEvent;
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
@ -29,6 +31,21 @@ class System;
|
|||||||
}
|
}
|
||||||
class PPCSymbolDB;
|
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
|
class CodeWidget : public QDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -65,6 +82,7 @@ private:
|
|||||||
void UpdateNotes();
|
void UpdateNotes();
|
||||||
|
|
||||||
void OnPPCSymbolsChanged();
|
void OnPPCSymbolsChanged();
|
||||||
|
void OnSaveAddress();
|
||||||
void OnSearchAddress();
|
void OnSearchAddress();
|
||||||
void OnSearchSymbols();
|
void OnSearchSymbols();
|
||||||
void OnSelectSymbol();
|
void OnSelectSymbol();
|
||||||
@ -80,7 +98,8 @@ private:
|
|||||||
PPCSymbolDB& m_ppc_symbol_db;
|
PPCSymbolDB& m_ppc_symbol_db;
|
||||||
|
|
||||||
BranchWatchDialog* m_branch_watch_dialog = nullptr;
|
BranchWatchDialog* m_branch_watch_dialog = nullptr;
|
||||||
QLineEdit* m_search_address;
|
QComboBox* m_search_address;
|
||||||
|
QToolButton* m_save_address_btn;
|
||||||
QToolButton* m_lock_btn;
|
QToolButton* m_lock_btn;
|
||||||
QPushButton* m_branch_watch;
|
QPushButton* m_branch_watch;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user