mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 03:16:10 +00:00
parent
2bfa3b7a3f
commit
fc94b896c4
@ -851,6 +851,57 @@ void CutterCore::addBreakpoint(RVA addr)
|
|||||||
{
|
{
|
||||||
cmd("db " + RAddressString(addr));
|
cmd("db " + RAddressString(addr));
|
||||||
emit instructionChanged(addr);
|
emit instructionChanged(addr);
|
||||||
|
emit breakpointsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::delBreakpoint(RVA addr)
|
||||||
|
{
|
||||||
|
cmd("db- " + RAddressString(addr));
|
||||||
|
emit instructionChanged(addr);
|
||||||
|
emit breakpointsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::delAllBreakpoints()
|
||||||
|
{
|
||||||
|
cmd("db-*");
|
||||||
|
emit breakpointsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::enableBreakpoint(RVA addr)
|
||||||
|
{
|
||||||
|
cmd("dbe " + RAddressString(addr));
|
||||||
|
emit instructionChanged(addr);
|
||||||
|
emit breakpointsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::disableBreakpoint(RVA addr)
|
||||||
|
{
|
||||||
|
cmd("dbd " + RAddressString(addr));
|
||||||
|
emit instructionChanged(addr);
|
||||||
|
emit breakpointsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<BreakpointDescription> CutterCore::getBreakpoints()
|
||||||
|
{
|
||||||
|
QList<BreakpointDescription> ret;
|
||||||
|
QJsonArray breakpointArray = cmdj("dbj").array();
|
||||||
|
|
||||||
|
for (QJsonValue value : breakpointArray) {
|
||||||
|
QJsonObject bpObject = value.toObject();
|
||||||
|
|
||||||
|
BreakpointDescription bp;
|
||||||
|
|
||||||
|
bp.addr = bpObject["addr"].toVariant().toULongLong();
|
||||||
|
bp.size = bpObject["size"].toVariant().toInt();
|
||||||
|
bp.permission = bpObject["prot"].toString();
|
||||||
|
bp.hw = bpObject["hw"].toBool();
|
||||||
|
bp.trace = bpObject["trace"].toBool();
|
||||||
|
bp.enabled = bpObject["enabled"].toBool();
|
||||||
|
|
||||||
|
ret << bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument CutterCore::getBacktrace()
|
QJsonDocument CutterCore::getBacktrace()
|
||||||
|
18
src/Cutter.h
18
src/Cutter.h
@ -303,6 +303,15 @@ struct MemoryMapDescription {
|
|||||||
QString permission;
|
QString permission;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BreakpointDescription {
|
||||||
|
RVA addr;
|
||||||
|
int size;
|
||||||
|
QString permission;
|
||||||
|
bool hw;
|
||||||
|
bool trace;
|
||||||
|
bool enabled;
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
Q_DECLARE_METATYPE(ImportDescription)
|
Q_DECLARE_METATYPE(ImportDescription)
|
||||||
Q_DECLARE_METATYPE(ExportDescription)
|
Q_DECLARE_METATYPE(ExportDescription)
|
||||||
@ -332,6 +341,7 @@ Q_DECLARE_METATYPE(ZignatureDescription)
|
|||||||
Q_DECLARE_METATYPE(SearchDescription)
|
Q_DECLARE_METATYPE(SearchDescription)
|
||||||
Q_DECLARE_METATYPE(SectionDescription)
|
Q_DECLARE_METATYPE(SectionDescription)
|
||||||
Q_DECLARE_METATYPE(MemoryMapDescription)
|
Q_DECLARE_METATYPE(MemoryMapDescription)
|
||||||
|
Q_DECLARE_METATYPE(BreakpointDescription)
|
||||||
|
|
||||||
class CutterCore: public QObject
|
class CutterCore: public QObject
|
||||||
{
|
{
|
||||||
@ -476,7 +486,11 @@ public:
|
|||||||
void continueUntilDebug(QString offset);
|
void continueUntilDebug(QString offset);
|
||||||
void stepDebug();
|
void stepDebug();
|
||||||
void stepOverDebug();
|
void stepOverDebug();
|
||||||
void addBreakpoint(RVA offset);
|
void addBreakpoint(RVA addr);
|
||||||
|
void delBreakpoint(RVA addr);
|
||||||
|
void delAllBreakpoints();
|
||||||
|
void enableBreakpoint(RVA addr);
|
||||||
|
void disableBreakpoint(RVA addr);
|
||||||
QString getActiveDebugPlugin();
|
QString getActiveDebugPlugin();
|
||||||
QStringList getDebugPlugins();
|
QStringList getDebugPlugins();
|
||||||
void setDebugPlugin(QString plugin);
|
void setDebugPlugin(QString plugin);
|
||||||
@ -536,6 +550,7 @@ public:
|
|||||||
QList<MemoryMapDescription> getMemoryMap();
|
QList<MemoryMapDescription> getMemoryMap();
|
||||||
QList<SearchDescription> getAllSearch(QString search_for, QString space);
|
QList<SearchDescription> getAllSearch(QString search_for, QString space);
|
||||||
BlockStatistics getBlockStatistics(unsigned int blocksCount);
|
BlockStatistics getBlockStatistics(unsigned int blocksCount);
|
||||||
|
QList<BreakpointDescription> getBreakpoints();
|
||||||
|
|
||||||
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
|
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
|
||||||
const QString &filterType = QString::null);
|
const QString &filterType = QString::null);
|
||||||
@ -565,6 +580,7 @@ signals:
|
|||||||
void commentsChanged();
|
void commentsChanged();
|
||||||
void registersChanged();
|
void registersChanged();
|
||||||
void instructionChanged(RVA offset);
|
void instructionChanged(RVA offset);
|
||||||
|
void breakpointsChanged();
|
||||||
|
|
||||||
void notesChanged(const QString ¬es);
|
void notesChanged(const QString ¬es);
|
||||||
void projectSaved(const QString &name);
|
void projectSaved(const QString &name);
|
||||||
|
@ -178,7 +178,8 @@ SOURCES += \
|
|||||||
utils/R2Task.cpp \
|
utils/R2Task.cpp \
|
||||||
widgets/DebugToolbar.cpp \
|
widgets/DebugToolbar.cpp \
|
||||||
widgets/MemoryMapWidget.cpp \
|
widgets/MemoryMapWidget.cpp \
|
||||||
dialogs/preferences/DebugOptionsWidget.cpp
|
dialogs/preferences/DebugOptionsWidget.cpp \
|
||||||
|
widgets/BreakpointWidget.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Cutter.h \
|
Cutter.h \
|
||||||
@ -268,7 +269,8 @@ HEADERS += \
|
|||||||
utils/R2Task.h \
|
utils/R2Task.h \
|
||||||
widgets/DebugToolbar.h \
|
widgets/DebugToolbar.h \
|
||||||
widgets/MemoryMapWidget.h \
|
widgets/MemoryMapWidget.h \
|
||||||
dialogs/preferences/DebugOptionsWidget.h
|
dialogs/preferences/DebugOptionsWidget.h \
|
||||||
|
widgets/BreakpointWidget.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
@ -319,7 +321,8 @@ FORMS += \
|
|||||||
dialogs/OpenFileDialog.ui \
|
dialogs/OpenFileDialog.ui \
|
||||||
widgets/MemoryMapWidget.ui \
|
widgets/MemoryMapWidget.ui \
|
||||||
widgets/MemoryMapWidget.ui \
|
widgets/MemoryMapWidget.ui \
|
||||||
dialogs/preferences/DebugOptionsWidget.ui
|
dialogs/preferences/DebugOptionsWidget.ui \
|
||||||
|
widgets/BreakpointWidget.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc \
|
resources.qrc \
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
#include "widgets/ZignaturesWidget.h"
|
#include "widgets/ZignaturesWidget.h"
|
||||||
#include "widgets/DebugToolbar.h"
|
#include "widgets/DebugToolbar.h"
|
||||||
#include "widgets/MemoryMapWidget.h"
|
#include "widgets/MemoryMapWidget.h"
|
||||||
|
#include "widgets/BreakpointWidget.h"
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
#include <QGraphicsEllipseItem>
|
#include <QGraphicsEllipseItem>
|
||||||
@ -206,6 +207,7 @@ void MainWindow::initUI()
|
|||||||
backtraceDock = new BacktraceWidget(this, ui->actionBacktrace);
|
backtraceDock = new BacktraceWidget(this, ui->actionBacktrace);
|
||||||
registersDock = new RegistersWidget(this, ui->actionRegisters);
|
registersDock = new RegistersWidget(this, ui->actionRegisters);
|
||||||
memoryMapDock = new MemoryMapWidget(this, ui->actionMemoryMap);
|
memoryMapDock = new MemoryMapWidget(this, ui->actionMemoryMap);
|
||||||
|
breakpointDock = new BreakpointWidget(this, ui->actionBreakpoint);
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
||||||
#else
|
#else
|
||||||
@ -545,8 +547,9 @@ void MainWindow::restoreDocks()
|
|||||||
addExtraWidget(stackDock);
|
addExtraWidget(stackDock);
|
||||||
splitDockWidget(stackDock, registersDock, Qt::Vertical);
|
splitDockWidget(stackDock, registersDock, Qt::Vertical);
|
||||||
splitDockWidget(stackDock, backtraceDock, Qt::Vertical);
|
splitDockWidget(stackDock, backtraceDock, Qt::Vertical);
|
||||||
// MemoryMap widget goes in the center tabs
|
// MemoryMap/Breakpoint widget goes in the center tabs
|
||||||
tabifyDockWidget(dashboardDock, memoryMapDock);
|
tabifyDockWidget(dashboardDock, memoryMapDock);
|
||||||
|
tabifyDockWidget(dashboardDock, breakpointDock);
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
tabifyDockWidget(dashboardDock, jupyterDock);
|
tabifyDockWidget(dashboardDock, jupyterDock);
|
||||||
#endif
|
#endif
|
||||||
@ -629,7 +632,8 @@ void MainWindow::showDebugDocks()
|
|||||||
stackDock,
|
stackDock,
|
||||||
registersDock,
|
registersDock,
|
||||||
backtraceDock,
|
backtraceDock,
|
||||||
memoryMapDock
|
memoryMapDock,
|
||||||
|
breakpointDock
|
||||||
};
|
};
|
||||||
for (auto w : dockWidgets) {
|
for (auto w : dockWidgets) {
|
||||||
if (debugDocks.contains(w)) {
|
if (debugDocks.contains(w)) {
|
||||||
|
@ -226,6 +226,7 @@ private:
|
|||||||
QDockWidget *backtraceDock = nullptr;
|
QDockWidget *backtraceDock = nullptr;
|
||||||
QDockWidget *memoryMapDock = nullptr;
|
QDockWidget *memoryMapDock = nullptr;
|
||||||
NewFileDialog *newFileDialog = nullptr;
|
NewFileDialog *newFileDialog = nullptr;
|
||||||
|
QDockWidget *breakpointDock = nullptr;
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
JupyterWidget *jupyterDock = nullptr;
|
JupyterWidget *jupyterDock = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
@ -231,6 +231,7 @@ border-top: 0px;
|
|||||||
<addaction name="actionRegisters"/>
|
<addaction name="actionRegisters"/>
|
||||||
<addaction name="actionBacktrace"/>
|
<addaction name="actionBacktrace"/>
|
||||||
<addaction name="actionMemoryMap"/>
|
<addaction name="actionMemoryMap"/>
|
||||||
|
<addaction name="actionBreakpoint"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="addInfoWidgets">
|
<widget class="QMenu" name="addInfoWidgets">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -1046,6 +1047,14 @@ border-top: 0px;
|
|||||||
<string>Memory map</string>
|
<string>Memory map</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionBreakpoint">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Breakpoints</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionClasses">
|
<action name="actionClasses">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
197
src/widgets/BreakpointWidget.cpp
Normal file
197
src/widgets/BreakpointWidget.cpp
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#include "BreakpointWidget.h"
|
||||||
|
#include "ui_BreakpointWidget.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "utils/Helpers.h"
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
BreakpointModel::BreakpointModel(QList<BreakpointDescription> *breakpoints, QObject *parent)
|
||||||
|
: QAbstractListModel(parent),
|
||||||
|
breakpoints(breakpoints)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int BreakpointModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return breakpoints->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BreakpointModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return BreakpointModel::ColumnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant BreakpointModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (index.row() >= breakpoints->count())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
const BreakpointDescription &breakpoint = breakpoints->at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case AddrColumn:
|
||||||
|
return RAddressString(breakpoint.addr);
|
||||||
|
case PermColumn:
|
||||||
|
return breakpoint.permission;
|
||||||
|
case HwColumn:
|
||||||
|
return breakpoint.hw;
|
||||||
|
case TraceColumn:
|
||||||
|
return breakpoint.trace;
|
||||||
|
case EnabledColumn:
|
||||||
|
return breakpoint.enabled;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case BreakpointDescriptionRole:
|
||||||
|
return QVariant::fromValue(breakpoint);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant BreakpointModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (section) {
|
||||||
|
case AddrColumn:
|
||||||
|
return tr("Offset");
|
||||||
|
case PermColumn:
|
||||||
|
return tr("Permissions");
|
||||||
|
case HwColumn:
|
||||||
|
return tr("Hardware bp");
|
||||||
|
case TraceColumn:
|
||||||
|
return tr("Tracing");
|
||||||
|
case EnabledColumn:
|
||||||
|
return tr("Active");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointModel::beginReloadBreakpoint()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointModel::endReloadBreakpoint()
|
||||||
|
{
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakpointProxyModel::BreakpointProxyModel(BreakpointModel *sourceModel, QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(sourceModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BreakpointProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||||
|
BreakpointDescription item = index.data(BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
|
return item.permission.contains(filterRegExp());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BreakpointProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
BreakpointDescription leftBreakpt = left.data(BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
|
BreakpointDescription rightBreakpt = right.data(BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
|
|
||||||
|
switch (left.column()) {
|
||||||
|
case BreakpointModel::AddrColumn:
|
||||||
|
return leftBreakpt.addr < rightBreakpt.addr;
|
||||||
|
case BreakpointModel::HwColumn:
|
||||||
|
return leftBreakpt.hw < rightBreakpt.hw;
|
||||||
|
case BreakpointModel::PermColumn:
|
||||||
|
return leftBreakpt.permission < rightBreakpt.permission;
|
||||||
|
case BreakpointModel::EnabledColumn:
|
||||||
|
return leftBreakpt.enabled < rightBreakpt.enabled;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftBreakpt.addr < rightBreakpt.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakpointWidget::BreakpointWidget(MainWindow *main, QAction *action) :
|
||||||
|
CutterDockWidget(main, action),
|
||||||
|
ui(new Ui::BreakpointWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
breakpointModel = new BreakpointModel(&breakpoints, this);
|
||||||
|
breakpointProxyModel = new BreakpointProxyModel(breakpointModel, this);
|
||||||
|
ui->breakpointTreeView->setModel(breakpointProxyModel);
|
||||||
|
ui->breakpointTreeView->sortByColumn(BreakpointModel::AddrColumn, Qt::AscendingOrder);
|
||||||
|
|
||||||
|
setScrollMode();
|
||||||
|
actionDelBreakpoint = new QAction(tr("Delete breakpoint"));
|
||||||
|
actionToggleBreakpoint = new QAction(tr("Toggle breakpoint"));
|
||||||
|
connect(actionDelBreakpoint, &QAction::triggered, this, &BreakpointWidget::delBreakpoint);
|
||||||
|
connect(actionToggleBreakpoint, &QAction::triggered, this, &BreakpointWidget::toggleBreakpoint);
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &BreakpointWidget::refreshBreakpoint);
|
||||||
|
connect(Core(), &CutterCore::breakpointsChanged, this, &BreakpointWidget::refreshBreakpoint);
|
||||||
|
connect(ui->delAllBreakpoints, &QAbstractButton::clicked, Core(), &CutterCore::delAllBreakpoints);
|
||||||
|
ui->breakpointTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(ui->breakpointTreeView, SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||||
|
this, SLOT(showBreakpointContextMenu(const QPoint &)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakpointWidget::~BreakpointWidget() {}
|
||||||
|
|
||||||
|
void BreakpointWidget::refreshBreakpoint()
|
||||||
|
{
|
||||||
|
breakpointModel->beginReloadBreakpoint();
|
||||||
|
breakpoints = Core()->getBreakpoints();
|
||||||
|
breakpointModel->endReloadBreakpoint();
|
||||||
|
|
||||||
|
ui->breakpointTreeView->resizeColumnToContents(0);
|
||||||
|
ui->breakpointTreeView->resizeColumnToContents(1);
|
||||||
|
ui->breakpointTreeView->resizeColumnToContents(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointWidget::setScrollMode()
|
||||||
|
{
|
||||||
|
qhelpers::setVerticalScrollMode(ui->breakpointTreeView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointWidget::on_breakpointTreeView_doubleClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
BreakpointDescription item = index.data(BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
|
Core()->seek(item.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointWidget::showBreakpointContextMenu(const QPoint &pt)
|
||||||
|
{
|
||||||
|
QMenu *menu = new QMenu(ui->breakpointTreeView);
|
||||||
|
menu->clear();
|
||||||
|
menu->addAction(actionDelBreakpoint);
|
||||||
|
menu->addAction(actionToggleBreakpoint);
|
||||||
|
|
||||||
|
menu->exec(ui->breakpointTreeView->mapToGlobal(pt));
|
||||||
|
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointWidget::delBreakpoint()
|
||||||
|
{
|
||||||
|
BreakpointDescription bp = ui->breakpointTreeView->selectionModel()->currentIndex().data(
|
||||||
|
BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
|
Core()->delBreakpoint(bp.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointWidget::toggleBreakpoint()
|
||||||
|
{
|
||||||
|
BreakpointDescription bp = ui->breakpointTreeView->selectionModel()->currentIndex().data(
|
||||||
|
BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
|
if (bp.enabled) {
|
||||||
|
Core()->disableBreakpoint(bp.addr);
|
||||||
|
} else {
|
||||||
|
Core()->enableBreakpoint(bp.addr);
|
||||||
|
}
|
||||||
|
}
|
89
src/widgets/BreakpointWidget.h
Normal file
89
src/widgets/BreakpointWidget.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidget;
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class BreakpointWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
|
||||||
|
|
||||||
|
class BreakpointModel: public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<BreakpointDescription> *breakpoints;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column { AddrColumn = 0, PermColumn, HwColumn, TraceColumn, EnabledColumn, ColumnCount };
|
||||||
|
enum Role { BreakpointDescriptionRole = Qt::UserRole };
|
||||||
|
|
||||||
|
BreakpointModel(QList<BreakpointDescription> *breakpoints, QObject *parent = 0);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
void beginReloadBreakpoint();
|
||||||
|
void endReloadBreakpoint();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BreakpointProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BreakpointProxyModel(BreakpointModel *sourceModel, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
|
||||||
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BreakpointWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BreakpointWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
|
~BreakpointWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_breakpointTreeView_doubleClicked(const QModelIndex &index);
|
||||||
|
void showBreakpointContextMenu(const QPoint &pt);
|
||||||
|
void delBreakpoint();
|
||||||
|
void toggleBreakpoint();
|
||||||
|
|
||||||
|
void refreshBreakpoint();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::BreakpointWidget> ui;
|
||||||
|
|
||||||
|
BreakpointModel *breakpointModel;
|
||||||
|
BreakpointProxyModel *breakpointProxyModel;
|
||||||
|
QList<BreakpointDescription> breakpoints;
|
||||||
|
QAction *actionDelBreakpoint = nullptr;
|
||||||
|
QAction *actionToggleBreakpoint = nullptr;
|
||||||
|
|
||||||
|
void setScrollMode();
|
||||||
|
};
|
65
src/widgets/BreakpointWidget.ui
Normal file
65
src/widgets/BreakpointWidget.ui
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BreakpointWidget</class>
|
||||||
|
<widget class="QDockWidget" name="BreakpointWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Breakpoints</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="breakpointTreeView">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QTreeView::item
|
||||||
|
{
|
||||||
|
padding-top: 1px;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="indentation">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="delAllBreakpoints">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete all breakpoints</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue
Block a user