Added breakpoint list

Added a list widget that displays all the currently active breakpoints. You can rename each one for convenience, delete them in bulk, or double click to jump to that address.
This commit is contained in:
MRG95 2017-10-22 03:34:36 -04:00 committed by kd-11
parent 09a0d046f4
commit c1f08ce58d
2 changed files with 115 additions and 4 deletions

View file

@ -4,6 +4,7 @@
#include <QApplication>
#include <QFontDatabase>
#include <QCompleter>
#include <QMenu>
constexpr auto qstr = QString::fromStdString;
extern bool user_asked_for_frame_capture;
@ -22,6 +23,10 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
QHBoxLayout* hbox_b_main = new QHBoxLayout();
m_list = new debugger_list(this);
m_breakpoints_list = new QListWidget(this);
m_breakpoints_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_breakpoints_list->setContextMenuPolicy(Qt::CustomContextMenu);
m_breakpoints_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_choice_units = new QComboBox(this);
m_choice_units->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_choice_units->setMaxVisibleItems(30);
@ -33,6 +38,11 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
m_choice_units->completer()->setMaxVisibleItems(30);
m_choice_units->completer()->setFilterMode(Qt::MatchContains);
m_breakpoints_list_delete = new QAction("Delete", m_breakpoints_list);
m_breakpoints_list_delete->setShortcut(Qt::Key_Delete);
m_breakpoints_list_delete->setShortcutContext(Qt::WidgetShortcut);
m_breakpoints_list->addAction(m_breakpoints_list_delete);
m_go_to_addr = new QPushButton(tr("Go To Address"), this);
m_go_to_pc = new QPushButton(tr("Go To PC"), this);
m_btn_capture = new QPushButton(tr("Capture"), this);
@ -58,9 +68,15 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
m_list->setFont(m_mono);
m_regs->setFont(m_mono);
m_right_splitter = new QSplitter(this);
m_right_splitter->setOrientation(Qt::Vertical);
m_right_splitter->addWidget(m_regs);
m_right_splitter->addWidget(m_breakpoints_list);
m_right_splitter->setStretchFactor(0, 1);
m_splitter = new QSplitter(this);
m_splitter->addWidget(m_list);
m_splitter->addWidget(m_regs);
m_splitter->addWidget(m_right_splitter);
QHBoxLayout* hbox_w_list = new QHBoxLayout();
hbox_w_list->addWidget(m_splitter);
@ -117,6 +133,10 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
connect(m_choice_units, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &debugger_frame::OnSelectUnit);
connect(this, &QDockWidget::visibilityChanged, this, &debugger_frame::EnableUpdateTimer);
connect(m_breakpoints_list, &QListWidget::itemDoubleClicked, this, &debugger_frame::OnBreakpointList_doubleClicked);
connect(m_breakpoints_list, &QListWidget::customContextMenuRequested, this, &debugger_frame::OnBreakpointList_rightClicked);
connect(m_breakpoints_list_delete, &QAction::triggered, this, &debugger_frame::OnBreakpointList_delete);
m_list->ShowAddr(CentrePc(m_list->m_pc));
UpdateUnitList();
}
@ -473,9 +493,56 @@ void debugger_frame::EnableButtons(bool enable)
void debugger_frame::ClearBreakpoints()
{
//This is required to actually delete the breakpoints, not just visually.
for (std::map<u32, bool>::iterator it = g_breakpoints.begin(); it != g_breakpoints.end(); it++)
m_list->RemoveBreakPoint(it->first, false);
g_breakpoints.clear();
}
void debugger_frame::OnBreakpointList_doubleClicked()
{
m_list->ShowAddr(CentrePc(m_breakpoints_list->currentItem()->data(Qt::UserRole).value<u32>()));
m_list->setCurrentRow(16);
}
void debugger_frame::OnBreakpointList_rightClicked(const QPoint &pos)
{
if (m_breakpoints_list->itemAt(pos) == NULL)
return;
QMenu* menu = new QMenu();
if (m_breakpoints_list->selectedItems().count() == 1)
{
menu->addAction("Rename");
menu->addSeparator();
}
menu->addAction(m_breakpoints_list_delete);
QAction* selectedItem = menu->exec(QCursor::pos());
if (selectedItem != NULL)
{
if (selectedItem->text() == "Rename")
{
QListWidgetItem* currentItem = m_breakpoints_list->selectedItems().at(0);
currentItem->setFlags(currentItem->flags() | Qt::ItemIsEditable);
m_breakpoints_list->editItem(currentItem);
}
}
}
void debugger_frame::OnBreakpointList_delete()
{
int selectedCount = m_breakpoints_list->selectedItems().count();
for (int i = selectedCount - 1; i >= 0; i--)
{
m_list->RemoveBreakPoint(m_breakpoints_list->item(i)->data(Qt::UserRole).value<u32>());
}
}
debugger_list::debugger_list(debugger_frame* parent) : QListWidget(parent)
{
m_pc = 0;
@ -543,12 +610,47 @@ void debugger_list::AddBreakPoint(u32 pc)
{
g_breakpoints.emplace(pc, false);
ppu_breakpoint(pc);
const auto cpu = m_debugFrame->cpu.lock();
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
m_debugFrame->m_disasm->offset = (u8*)vm::base(cpu_offset);
m_debugFrame->m_disasm->disasm(m_debugFrame->m_disasm->dump_pc = pc);
QString breakpointItemText = qstr(m_debugFrame->m_disasm->last_opcode);
breakpointItemText.remove(10, 13);
QListWidgetItem* breakpointItem = new QListWidgetItem(breakpointItemText);
breakpointItem->setTextColor(m_text_color_bp);
breakpointItem->setBackgroundColor(m_color_bp);
QVariant pcVariant;
pcVariant.setValue(pc);
breakpointItem->setData(Qt::UserRole, pcVariant);
m_debugFrame->m_breakpoints_list->addItem(breakpointItem);
}
void debugger_list::RemoveBreakPoint(u32 pc)
void debugger_list::RemoveBreakPoint(u32 pc, bool eraseFromMap)
{
g_breakpoints.erase(pc);
if(eraseFromMap)
g_breakpoints.erase(pc);
ppu_breakpoint(pc);
int breakpointsListCount = m_debugFrame->m_breakpoints_list->count();
for (int i = 0; i < breakpointsListCount; i++)
{
QListWidgetItem* currentItem = m_debugFrame->m_breakpoints_list->item(i);
if (currentItem->data(Qt::UserRole).value<u32>() == pc)
{
delete m_debugFrame->m_breakpoints_list->takeItem(i);
break;
}
}
ShowAddr(m_pc - (m_item_count) * 4);
}
void debugger_list::keyPressEvent(QKeyEvent* event)

View file

@ -36,6 +36,7 @@ class debugger_frame : public QDockWidget
Q_OBJECT
debugger_list* m_list;
QSplitter* m_right_splitter;
QFont m_mono;
QTextEdit* m_regs;
QPushButton* m_go_to_addr;
@ -61,8 +62,11 @@ class debugger_frame : public QDockWidget
std::shared_ptr<gui_settings> xgui_settings;
QAction* m_breakpoints_list_delete;
public:
std::unique_ptr<CPUDisAsm> m_disasm;
QListWidget* m_breakpoints_list;
std::weak_ptr<cpu_thread> cpu;
public:
@ -93,6 +97,9 @@ Q_SIGNALS:
public Q_SLOTS:
void DoStep();
private Q_SLOTS:
void OnBreakpointList_doubleClicked();
void OnBreakpointList_rightClicked(const QPoint &pos);
void OnBreakpointList_delete();
void OnSelectUnit();
void Show_Val();
void Show_PC();
@ -117,11 +124,11 @@ public:
public:
debugger_list(debugger_frame* parent);
void ShowAddr(u32 addr);
void RemoveBreakPoint(u32 pc, bool eraseFromMap = true);
private:
bool IsBreakPoint(u32 pc);
void AddBreakPoint(u32 pc);
void RemoveBreakPoint(u32 pc);
protected:
void keyPressEvent(QKeyEvent* event);
@ -129,3 +136,5 @@ protected:
void wheelEvent(QWheelEvent* event);
void resizeEvent(QResizeEvent* event);
};
Q_DECLARE_METATYPE(u32);