Debug toolbar (#521)
@ -754,6 +754,47 @@ QString CutterCore::getRegisterName(QString registerRole)
|
|||||||
void CutterCore::setRegister(QString regName, QString regValue)
|
void CutterCore::setRegister(QString regName, QString regValue)
|
||||||
{
|
{
|
||||||
cmd("dr " + regName + "=" + regValue);
|
cmd("dr " + regName + "=" + regValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::startDebug()
|
||||||
|
{
|
||||||
|
cmd("ood");
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::continueDebug()
|
||||||
|
{
|
||||||
|
cmd("dc");
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::continueUntilDebug(QString offset)
|
||||||
|
{
|
||||||
|
cmd("dcu " + offset);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::stepDebug()
|
||||||
|
{
|
||||||
|
cmd("ds");
|
||||||
|
QString programCounterValue = cmd("dr?`drn pc`").trimmed();
|
||||||
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::stepOverDebug()
|
||||||
|
{
|
||||||
|
cmd("dso");
|
||||||
|
QString programCounterValue = cmd("dr?`drn pc`").trimmed();
|
||||||
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::addBreakpoint(RVA addr)
|
||||||
|
{
|
||||||
|
cmd("db " + RAddressString(addr));
|
||||||
|
emit instructionChanged(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument CutterCore::getBacktrace()
|
QJsonDocument CutterCore::getBacktrace()
|
||||||
@ -761,6 +802,29 @@ QJsonDocument CutterCore::getBacktrace()
|
|||||||
return cmdj("dbtj");
|
return cmdj("dbtj");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<MemoryMapDescription> CutterCore::getMemoryMap()
|
||||||
|
{
|
||||||
|
QList<MemoryMapDescription> ret;
|
||||||
|
QJsonArray memoryMapArray = cmdj("dmj").array();
|
||||||
|
|
||||||
|
for (QJsonValue value : memoryMapArray) {
|
||||||
|
QJsonObject memMapObject = value.toObject();
|
||||||
|
|
||||||
|
MemoryMapDescription memMap;
|
||||||
|
|
||||||
|
memMap.name = memMapObject["name"].toString();
|
||||||
|
memMap.fileName = memMapObject["file"].toString();
|
||||||
|
memMap.addrStart = memMapObject["addr"].toVariant().toULongLong();
|
||||||
|
memMap.addrEnd = memMapObject["addr_end"].toVariant().toULongLong();
|
||||||
|
memMap.type = memMapObject["type"].toString();
|
||||||
|
memMap.permission = memMapObject["perm"].toString();
|
||||||
|
|
||||||
|
ret << memMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList CutterCore::getStats()
|
QStringList CutterCore::getStats()
|
||||||
{
|
{
|
||||||
QStringList stats;
|
QStringList stats;
|
||||||
|
21
src/Cutter.h
@ -294,6 +294,15 @@ struct BlockStatistics {
|
|||||||
QList<BlockDescription> blocks;
|
QList<BlockDescription> blocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MemoryMapDescription {
|
||||||
|
RVA addrStart;
|
||||||
|
RVA addrEnd;
|
||||||
|
QString name;
|
||||||
|
QString fileName;
|
||||||
|
QString type;
|
||||||
|
QString permission;
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
Q_DECLARE_METATYPE(ImportDescription)
|
Q_DECLARE_METATYPE(ImportDescription)
|
||||||
Q_DECLARE_METATYPE(ExportDescription)
|
Q_DECLARE_METATYPE(ExportDescription)
|
||||||
@ -322,6 +331,7 @@ Q_DECLARE_METATYPE(HeaderDescription)
|
|||||||
Q_DECLARE_METATYPE(ZignatureDescription)
|
Q_DECLARE_METATYPE(ZignatureDescription)
|
||||||
Q_DECLARE_METATYPE(SearchDescription)
|
Q_DECLARE_METATYPE(SearchDescription)
|
||||||
Q_DECLARE_METATYPE(SectionDescription)
|
Q_DECLARE_METATYPE(SectionDescription)
|
||||||
|
Q_DECLARE_METATYPE(MemoryMapDescription)
|
||||||
|
|
||||||
class CutterCore: public QObject
|
class CutterCore: public QObject
|
||||||
{
|
{
|
||||||
@ -450,12 +460,21 @@ public:
|
|||||||
ulong get_baddr();
|
ulong get_baddr();
|
||||||
QList<QList<QString>> get_exec_sections();
|
QList<QList<QString>> get_exec_sections();
|
||||||
QString getOffsetInfo(QString addr);
|
QString getOffsetInfo(QString addr);
|
||||||
|
|
||||||
|
// Debug
|
||||||
QJsonDocument getRegistersInfo();
|
QJsonDocument getRegistersInfo();
|
||||||
QJsonDocument getRegisterValues();
|
QJsonDocument getRegisterValues();
|
||||||
QString getRegisterName(QString registerRole);
|
QString getRegisterName(QString registerRole);
|
||||||
void setRegister(QString regName, QString regValue);
|
void setRegister(QString regName, QString regValue);
|
||||||
QJsonDocument getStack(int size = 0x40);
|
QJsonDocument getStack(int size = 0x40);
|
||||||
QJsonDocument getBacktrace();
|
QJsonDocument getBacktrace();
|
||||||
|
void startDebug();
|
||||||
|
void continueDebug();
|
||||||
|
void continueUntilDebug(QString offset);
|
||||||
|
void stepDebug();
|
||||||
|
void stepOverDebug();
|
||||||
|
void addBreakpoint(RVA offset);
|
||||||
|
|
||||||
RVA getOffsetJump(RVA addr);
|
RVA getOffsetJump(RVA addr);
|
||||||
QString getDecompiledCode(RVA addr);
|
QString getDecompiledCode(RVA addr);
|
||||||
QString getDecompiledCode(QString addr);
|
QString getDecompiledCode(QString addr);
|
||||||
@ -508,6 +527,7 @@ public:
|
|||||||
QList<ResourcesDescription> getAllResources();
|
QList<ResourcesDescription> getAllResources();
|
||||||
QList<VTableDescription> getAllVTables();
|
QList<VTableDescription> getAllVTables();
|
||||||
QList<TypeDescription> getAllTypes();
|
QList<TypeDescription> getAllTypes();
|
||||||
|
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);
|
||||||
|
|
||||||
@ -537,6 +557,7 @@ signals:
|
|||||||
void functionsChanged();
|
void functionsChanged();
|
||||||
void flagsChanged();
|
void flagsChanged();
|
||||||
void commentsChanged();
|
void commentsChanged();
|
||||||
|
void registersChanged();
|
||||||
void instructionChanged(RVA offset);
|
void instructionChanged(RVA offset);
|
||||||
|
|
||||||
void notesChanged(const QString ¬es);
|
void notesChanged(const QString ¬es);
|
||||||
|
@ -175,7 +175,9 @@ SOURCES += \
|
|||||||
dialogs/OpenFileDialog.cpp \
|
dialogs/OpenFileDialog.cpp \
|
||||||
utils/CommandTask.cpp \
|
utils/CommandTask.cpp \
|
||||||
utils/ProgressIndicator.cpp \
|
utils/ProgressIndicator.cpp \
|
||||||
utils/R2Task.cpp
|
utils/R2Task.cpp \
|
||||||
|
widgets/DebugToolbar.cpp \
|
||||||
|
widgets/MemoryMapWidget.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Cutter.h \
|
Cutter.h \
|
||||||
@ -262,7 +264,9 @@ HEADERS += \
|
|||||||
utils/CommandTask.h \
|
utils/CommandTask.h \
|
||||||
utils/ProgressIndicator.h \
|
utils/ProgressIndicator.h \
|
||||||
plugins/CutterPlugin.h \
|
plugins/CutterPlugin.h \
|
||||||
utils/R2Task.h
|
utils/R2Task.h \
|
||||||
|
widgets/DebugToolbar.h \
|
||||||
|
widgets/MemoryMapWidget.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
@ -310,7 +314,8 @@ FORMS += \
|
|||||||
widgets/StackWidget.ui \
|
widgets/StackWidget.ui \
|
||||||
widgets/RegistersWidget.ui \
|
widgets/RegistersWidget.ui \
|
||||||
widgets/BacktraceWidget.ui \
|
widgets/BacktraceWidget.ui \
|
||||||
dialogs/OpenFileDialog.ui
|
dialogs/OpenFileDialog.ui \
|
||||||
|
widgets/MemoryMapWidget.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc \
|
resources.qrc \
|
||||||
|
@ -73,6 +73,8 @@
|
|||||||
#include "widgets/JupyterWidget.h"
|
#include "widgets/JupyterWidget.h"
|
||||||
#include "widgets/HeadersWidget.h"
|
#include "widgets/HeadersWidget.h"
|
||||||
#include "widgets/ZignaturesWidget.h"
|
#include "widgets/ZignaturesWidget.h"
|
||||||
|
#include "widgets/DebugToolbar.h"
|
||||||
|
#include "widgets/MemoryMapWidget.h"
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
#include <QGraphicsEllipseItem>
|
#include <QGraphicsEllipseItem>
|
||||||
@ -124,9 +126,19 @@ void MainWindow::initUI()
|
|||||||
QWidget *spacer3 = new QWidget();
|
QWidget *spacer3 = new QWidget();
|
||||||
spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
spacer3->setMinimumSize(20, 20);
|
spacer3->setMinimumSize(20, 20);
|
||||||
spacer3->setMaximumWidth(300);
|
spacer3->setMaximumWidth(100);
|
||||||
ui->mainToolBar->addWidget(spacer3);
|
ui->mainToolBar->addWidget(spacer3);
|
||||||
|
|
||||||
|
QToolBar *debugToolbar = new DebugToolbar(this);
|
||||||
|
ui->mainToolBar->addWidget(debugToolbar);
|
||||||
|
|
||||||
|
// Sepparator between undo/redo and goto lineEdit
|
||||||
|
QWidget *spacer4 = new QWidget();
|
||||||
|
spacer4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
spacer4->setMinimumSize(20, 20);
|
||||||
|
spacer4->setMaximumWidth(100);
|
||||||
|
ui->mainToolBar->addWidget(spacer4);
|
||||||
|
|
||||||
// Omnibar LineEdit
|
// Omnibar LineEdit
|
||||||
this->omnibar = new Omnibar(this);
|
this->omnibar = new Omnibar(this);
|
||||||
ui->mainToolBar->addWidget(this->omnibar);
|
ui->mainToolBar->addWidget(this->omnibar);
|
||||||
@ -193,6 +205,7 @@ void MainWindow::initUI()
|
|||||||
stackDock = new StackWidget(this, ui->actionStack);
|
stackDock = new StackWidget(this, ui->actionStack);
|
||||||
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);
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
||||||
#else
|
#else
|
||||||
@ -531,6 +544,7 @@ 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);
|
||||||
|
splitDockWidget(stackDock, memoryMapDock, Qt::Vertical);
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
tabifyDockWidget(dashboardDock, jupyterDock);
|
tabifyDockWidget(dashboardDock, jupyterDock);
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,6 +222,7 @@ private:
|
|||||||
QDockWidget *stackDock = nullptr;
|
QDockWidget *stackDock = nullptr;
|
||||||
QDockWidget *registersDock = nullptr;
|
QDockWidget *registersDock = nullptr;
|
||||||
QDockWidget *backtraceDock = nullptr;
|
QDockWidget *backtraceDock = nullptr;
|
||||||
|
QDockWidget *memoryMapDock = nullptr;
|
||||||
NewFileDialog *newFileDialog = nullptr;
|
NewFileDialog *newFileDialog = nullptr;
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
JupyterWidget *jupyterDock = nullptr;
|
JupyterWidget *jupyterDock = nullptr;
|
||||||
|
@ -230,6 +230,7 @@ border-top: 0px;
|
|||||||
<addaction name="actionStack"/>
|
<addaction name="actionStack"/>
|
||||||
<addaction name="actionRegisters"/>
|
<addaction name="actionRegisters"/>
|
||||||
<addaction name="actionBacktrace"/>
|
<addaction name="actionBacktrace"/>
|
||||||
|
<addaction name="actionMemoryMap"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="addInfoWidgets">
|
<widget class="QMenu" name="addInfoWidgets">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -294,23 +295,6 @@ border-top: 0px;
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string notr="true">Main toolbar</string>
|
<string notr="true">Main toolbar</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">
|
|
||||||
QToolButton {
|
|
||||||
margin: 1px;
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-right: 2px;
|
|
||||||
padding: 2px;
|
|
||||||
padding-left: 7px;
|
|
||||||
padding-right: 7px;
|
|
||||||
border-radius: 6px;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
QToolButton:pressed {
|
|
||||||
background-color: palette(dark);
|
|
||||||
}
|
|
||||||
</string>
|
|
||||||
</property>
|
|
||||||
<property name="movable">
|
<property name="movable">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -457,7 +441,7 @@ background-color: palette(dark);
|
|||||||
<action name="actionBackward">
|
<action name="actionBackward">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="resources.qrc">
|
<iconset resource="resources.qrc">
|
||||||
<normaloff>:/img/icons/arrow_left.svg</normaloff>:/img/icons/arrow_left.svg</iconset>
|
<normaloff>:/img/icons/arrow_left_light.svg</normaloff>:/img/icons/arrow_left_light.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Back</string>
|
<string>Back</string>
|
||||||
@ -469,7 +453,7 @@ background-color: palette(dark);
|
|||||||
<action name="actionForward">
|
<action name="actionForward">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="resources.qrc">
|
<iconset resource="resources.qrc">
|
||||||
<normaloff>:/img/icons/arrow_right.svg</normaloff>:/img/icons/arrow_right.svg</iconset>
|
<normaloff>:/img/icons/arrow_right_light.svg</normaloff>:/img/icons/arrow_right_light.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Forward</string>
|
<string>Forward</string>
|
||||||
@ -1054,6 +1038,14 @@ background-color: palette(dark);
|
|||||||
<string>Backtrace</string>
|
<string>Backtrace</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionMemoryMap">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Memory map</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionClasses">
|
<action name="actionClasses">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
4
src/img/icons/arrow_left_light.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg style="enable-background:new 0 0 32 32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32px" width="32px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
|
||||||
|
<path d="m16 32l5.7-5.7-6.3-6.3h16v-8h-17l6.3-6.3-5-5.7-16 16 16 16z" fill="#aaacaf"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 418 B |
4
src/img/icons/arrow_right_light.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg style="enable-background:new 0 0 32 32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32px" width="32px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
|
||||||
|
<path d="m16 0l-5.7 5.7 6.3 6.3h-16v8h17l-6.3 6.3 5 6 16-16-16-16z" fill="#aaacaf"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 416 B |
4
src/img/icons/continue_until_main.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||||
|
<path d="M0 0v6l4-3-4-3z" transform="translate(0 1)" fill="#aaacaf"/>
|
||||||
|
<text x="4" y="4" font-family="Helvetica, Arial, sans-serif" font-size="5" stroke-width="1" stroke="#aaacaf" fill="#aaacaf" >M</text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 295 B |
5
src/img/icons/media-skip-forward_light.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||||
|
<g fill="#aaacaf">
|
||||||
|
<path d="M0 0v6l4-3-4-3zm4 3v3l4-3-4-3v3z" transform="translate(0 1)" fill="#aaacaf"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 205 B |
4
src/img/icons/play_light.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg style="enable-background:new 0 0 24 32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32px" width="24px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 32">
|
||||||
|
<polygon points="0 0 24 16 0 32" fill="#aaacaf"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 381 B |
3
src/img/icons/step_light.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||||
|
<path d="M0 0v6l5-3-5-3zm5 3v3h2v-6h-2v3z" transform="translate(0 1)" fill="#aaacaf"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 175 B |
4
src/img/icons/step_over_light.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||||
|
<path d="M0 0v6l5-3-5-3zm5 3v3h2v-6h-2v3z" transform="translate(0 1)" fill="#aaacaf"/>
|
||||||
|
<circle cx="3.5" cy="6.8" r="0.5" stroke="#aaacaf" stroke-width="1" fill="#aaacaf" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 263 B |
@ -41,7 +41,10 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
|
|||||||
actionSetBaseString(this),
|
actionSetBaseString(this),
|
||||||
actionSetBits16(this),
|
actionSetBits16(this),
|
||||||
actionSetBits32(this),
|
actionSetBits32(this),
|
||||||
actionSetBits64(this)
|
actionSetBits64(this),
|
||||||
|
actionContinueUntil(this),
|
||||||
|
actionAddBreakpoint(this),
|
||||||
|
actionSetPC(this)
|
||||||
{
|
{
|
||||||
createAction(&actionCopy, tr("Copy"), getCopySequence(), SLOT(on_actionCopy_triggered()));
|
createAction(&actionCopy, tr("Copy"), getCopySequence(), SLOT(on_actionCopy_triggered()));
|
||||||
copySeparator = addSeparator();
|
copySeparator = addSeparator();
|
||||||
@ -107,6 +110,17 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
|
|||||||
actionJmpReverse.setText(tr("Reverse Jump"));
|
actionJmpReverse.setText(tr("Reverse Jump"));
|
||||||
editMenu->addAction(&actionJmpReverse);
|
editMenu->addAction(&actionJmpReverse);
|
||||||
|
|
||||||
|
addSeparator();
|
||||||
|
debugMenu = new QMenu(tr("Debug"), this);
|
||||||
|
debugMenuAction = addMenu(debugMenu);
|
||||||
|
actionAddBreakpoint.setText(tr("Add breakpoint"));
|
||||||
|
debugMenu->addAction(&actionAddBreakpoint);
|
||||||
|
actionContinueUntil.setText(tr("Continue until line"));
|
||||||
|
debugMenu->addAction(&actionContinueUntil);
|
||||||
|
QString progCounterName = Core()->getRegisterName("PC");
|
||||||
|
actionSetPC.setText("Set " + progCounterName + " here");
|
||||||
|
debugMenu->addAction(&actionSetPC);
|
||||||
|
|
||||||
connect(&actionEditInstruction, SIGNAL(triggered(bool)), this,
|
connect(&actionEditInstruction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(on_actionEditInstruction_triggered()));
|
SLOT(on_actionEditInstruction_triggered()));
|
||||||
connect(&actionNopInstruction, SIGNAL(triggered(bool)), this,
|
connect(&actionNopInstruction, SIGNAL(triggered(bool)), this,
|
||||||
@ -134,6 +148,13 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
|
|||||||
connect(&actionSetBits32, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits32_triggered()));
|
connect(&actionSetBits32, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits32_triggered()));
|
||||||
connect(&actionSetBits64, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits64_triggered()));
|
connect(&actionSetBits64, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits64_triggered()));
|
||||||
|
|
||||||
|
connect(&actionAddBreakpoint, &QAction::triggered,
|
||||||
|
this, &DisassemblyContextMenu::on_actionAddBreakpoint_triggered);
|
||||||
|
connect(&actionContinueUntil, &QAction::triggered,
|
||||||
|
this, &DisassemblyContextMenu::on_actionContinueUntil_triggered);
|
||||||
|
connect(&actionSetPC, &QAction::triggered,
|
||||||
|
this, &DisassemblyContextMenu::on_actionSetPC_triggered);
|
||||||
|
|
||||||
connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSlot()));
|
connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSlot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,6 +237,10 @@ void DisassemblyContextMenu::aboutToShowSlot()
|
|||||||
// decide to show Reverse jmp option
|
// decide to show Reverse jmp option
|
||||||
showReverseJmpQuery();
|
showReverseJmpQuery();
|
||||||
|
|
||||||
|
// show debug options
|
||||||
|
// @TODO determine if we are being debugged and only show the menu in those cases
|
||||||
|
// maybe using dpt command
|
||||||
|
debugMenuAction->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence DisassemblyContextMenu::getCopySequence() const
|
QKeySequence DisassemblyContextMenu::getCopySequence() const
|
||||||
@ -325,6 +350,22 @@ void DisassemblyContextMenu::on_actionCopyAddr_triggered()
|
|||||||
clipboard->setText(RAddressString(offset));
|
clipboard->setText(RAddressString(offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisassemblyContextMenu::on_actionAddBreakpoint_triggered()
|
||||||
|
{
|
||||||
|
Core()->addBreakpoint(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisassemblyContextMenu::on_actionContinueUntil_triggered()
|
||||||
|
{
|
||||||
|
Core()->continueUntilDebug(RAddressString(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisassemblyContextMenu::on_actionSetPC_triggered()
|
||||||
|
{
|
||||||
|
QString progCounterName = Core()->getRegisterName("PC");
|
||||||
|
Core()->setRegister(progCounterName, RAddressString(offset));
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyContextMenu::on_actionAddComment_triggered()
|
void DisassemblyContextMenu::on_actionAddComment_triggered()
|
||||||
{
|
{
|
||||||
QString oldComment = Core()->cmd("CC." + RAddressString(offset));
|
QString oldComment = Core()->cmd("CC." + RAddressString(offset));
|
||||||
|
@ -55,6 +55,9 @@ private slots:
|
|||||||
void on_actionSetBits16_triggered();
|
void on_actionSetBits16_triggered();
|
||||||
void on_actionSetBits32_triggered();
|
void on_actionSetBits32_triggered();
|
||||||
void on_actionSetBits64_triggered();
|
void on_actionSetBits64_triggered();
|
||||||
|
void on_actionAddBreakpoint_triggered();
|
||||||
|
void on_actionContinueUntil_triggered();
|
||||||
|
void on_actionSetPC_triggered();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QKeySequence getCopySequence() const;
|
QKeySequence getCopySequence() const;
|
||||||
@ -111,6 +114,12 @@ private:
|
|||||||
QAction actionSetBits32;
|
QAction actionSetBits32;
|
||||||
QAction actionSetBits64;
|
QAction actionSetBits64;
|
||||||
|
|
||||||
|
QMenu *debugMenu;
|
||||||
|
QAction *debugMenuAction;
|
||||||
|
QAction actionContinueUntil;
|
||||||
|
QAction actionAddBreakpoint;
|
||||||
|
QAction actionSetPC;
|
||||||
|
|
||||||
// For creating anonymous entries (that are always visible)
|
// For creating anonymous entries (that are always visible)
|
||||||
void createAction(QString name, QKeySequence keySequence, const char *slot);
|
void createAction(QString name, QKeySequence keySequence, const char *slot);
|
||||||
void createAction(QAction *action, QString name, QKeySequence keySequence, const char *slot);
|
void createAction(QAction *action, QString name, QKeySequence keySequence, const char *slot);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file>img/icons/arrow_left.svg</file>
|
<file>img/icons/arrow_left_light.svg</file>
|
||||||
<file>img/icons/arrow_right.svg</file>
|
<file>img/icons/arrow_right_light.svg</file>
|
||||||
<file>img/icons/sidebar.svg</file>
|
<file>img/icons/sidebar.svg</file>
|
||||||
<file>img/icons/undo.svg</file>
|
<file>img/icons/undo.svg</file>
|
||||||
<file>img/icons/redo.svg</file>
|
<file>img/icons/redo.svg</file>
|
||||||
@ -17,6 +17,11 @@
|
|||||||
<file>img/icons/spin.svg</file>
|
<file>img/icons/spin.svg</file>
|
||||||
<file>img/icons/plus.svg</file>
|
<file>img/icons/plus.svg</file>
|
||||||
<file>img/icons/play.svg</file>
|
<file>img/icons/play.svg</file>
|
||||||
|
<file>img/icons/play_light.svg</file>
|
||||||
|
<file>img/icons/media-skip-forward_light.svg</file>
|
||||||
|
<file>img/icons/continue_until_main.svg</file>
|
||||||
|
<file>img/icons/step_light.svg</file>
|
||||||
|
<file>img/icons/step_over_light.svg</file>
|
||||||
<file>img/icons/cloud.svg</file>
|
<file>img/icons/cloud.svg</file>
|
||||||
<file>img/icons/down.svg</file>
|
<file>img/icons/down.svg</file>
|
||||||
<file>img/icons/down_white.svg</file>
|
<file>img/icons/down_white.svg</file>
|
||||||
|
39
src/widgets/DebugToolbar.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "DebugToolbar.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
DebugToolbar::DebugToolbar(MainWindow *main, QWidget *parent) :
|
||||||
|
QToolBar(parent),
|
||||||
|
main(main)
|
||||||
|
{
|
||||||
|
setObjectName("debugToolbar");
|
||||||
|
QIcon startIcon = QIcon(":/img/icons/play_light.svg");
|
||||||
|
QIcon continueIcon = QIcon(":/img/icons/media-skip-forward_light.svg");
|
||||||
|
QIcon continueUntilIcon = QIcon(":/img/icons/continue_until_main.svg");
|
||||||
|
QIcon stepIcon = QIcon(":/img/icons/step_light.svg");
|
||||||
|
QIcon stepOverIcon = QIcon(":/img/icons/step_over_light.svg");
|
||||||
|
|
||||||
|
QAction *actionStart = new QAction(startIcon, tr("Start debug"), parent);
|
||||||
|
QAction *actionContinue = new QAction(continueIcon, tr("Continue"), parent);
|
||||||
|
QAction *actionContinueUntilMain = new QAction(continueUntilIcon, tr("Continue until main"), parent);
|
||||||
|
QAction *actionStep = new QAction(stepIcon, tr("Step"), parent);
|
||||||
|
QAction *actionStepOver = new QAction(stepOverIcon, tr("Step over"), parent);
|
||||||
|
addAction(actionStart);
|
||||||
|
addAction(actionContinue);
|
||||||
|
addAction(actionContinueUntilMain);
|
||||||
|
addAction(actionStep);
|
||||||
|
addAction(actionStepOver);
|
||||||
|
|
||||||
|
connect(actionStep, &QAction::triggered, Core(), &CutterCore::stepDebug);
|
||||||
|
connect(actionStart, &QAction::triggered, Core(), &CutterCore::startDebug);
|
||||||
|
connect(actionStepOver, &QAction::triggered, Core(), &CutterCore::stepOverDebug);
|
||||||
|
connect(actionContinue, &QAction::triggered, Core(), &CutterCore::continueDebug);
|
||||||
|
connect(actionContinueUntilMain, &QAction::triggered, this, &DebugToolbar::continueUntilMain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugToolbar::continueUntilMain()
|
||||||
|
{
|
||||||
|
Core()->continueUntilDebug(tr("main"));
|
||||||
|
}
|
21
src/widgets/DebugToolbar.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QToolBar>
|
||||||
|
#include "Cutter.h"
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
|
class DebugToolbar : public QToolBar
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DebugToolbar(MainWindow *main, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MainWindow *main;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void continueUntilMain();
|
||||||
|
|
||||||
|
};
|
154
src/widgets/MemoryMapWidget.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include "MemoryMapWidget.h"
|
||||||
|
#include "ui_MemoryMapWidget.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "utils/Helpers.h"
|
||||||
|
|
||||||
|
MemoryMapModel::MemoryMapModel(QList<MemoryMapDescription> *memoryMaps, QObject *parent)
|
||||||
|
: QAbstractListModel(parent),
|
||||||
|
memoryMaps(memoryMaps)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int MemoryMapModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return memoryMaps->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int MemoryMapModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return MemoryMapModel::ColumnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant MemoryMapModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (index.row() >= memoryMaps->count())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
const MemoryMapDescription &memoryMap = memoryMaps->at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case AddrStartColumn:
|
||||||
|
return RAddressString(memoryMap.addrStart);
|
||||||
|
case AddrEndColumn:
|
||||||
|
return RAddressString(memoryMap.addrEnd);
|
||||||
|
case NameColumn:
|
||||||
|
return memoryMap.name;
|
||||||
|
case PermColumn:
|
||||||
|
return memoryMap.permission;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case MemoryDescriptionRole:
|
||||||
|
return QVariant::fromValue(memoryMap);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant MemoryMapModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (section) {
|
||||||
|
case AddrStartColumn:
|
||||||
|
return tr("Offset start");
|
||||||
|
case AddrEndColumn:
|
||||||
|
return tr("Offset end");
|
||||||
|
case NameColumn:
|
||||||
|
return tr("Name");
|
||||||
|
case PermColumn:
|
||||||
|
return tr("Permissions");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryMapModel::beginReloadMemoryMap()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryMapModel::endReloadMemoryMap()
|
||||||
|
{
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryProxyModel::MemoryProxyModel(MemoryMapModel *sourceModel, QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(sourceModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||||
|
MemoryMapDescription item = index.data(MemoryMapModel::MemoryDescriptionRole).value<MemoryMapDescription>();
|
||||||
|
return item.name.contains(filterRegExp());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
MemoryMapDescription leftMemMap = left.data(MemoryMapModel::MemoryDescriptionRole).value<MemoryMapDescription>();
|
||||||
|
MemoryMapDescription rightMemMap = right.data(MemoryMapModel::MemoryDescriptionRole).value<MemoryMapDescription>();
|
||||||
|
|
||||||
|
switch (left.column()) {
|
||||||
|
case MemoryMapModel::AddrStartColumn:
|
||||||
|
return leftMemMap.addrStart < rightMemMap.addrStart;
|
||||||
|
case MemoryMapModel::AddrEndColumn:
|
||||||
|
return leftMemMap.addrEnd < rightMemMap.addrEnd;
|
||||||
|
case MemoryMapModel::NameColumn:
|
||||||
|
return leftMemMap.name < rightMemMap.name;
|
||||||
|
case MemoryMapModel::PermColumn:
|
||||||
|
return leftMemMap.permission < rightMemMap.permission;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftMemMap.addrStart < rightMemMap.addrStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMapWidget::MemoryMapWidget(MainWindow *main, QAction *action) :
|
||||||
|
CutterDockWidget(main, action),
|
||||||
|
ui(new Ui::MemoryMapWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
memoryModel = new MemoryMapModel(&memoryMaps, this);
|
||||||
|
memoryProxyModel = new MemoryProxyModel(memoryModel, this);
|
||||||
|
ui->memoryTreeView->setModel(memoryProxyModel);
|
||||||
|
ui->memoryTreeView->sortByColumn(MemoryMapModel::AddrStartColumn, Qt::AscendingOrder);
|
||||||
|
|
||||||
|
setScrollMode();
|
||||||
|
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &MemoryMapWidget::refreshMemoryMap);
|
||||||
|
connect(Core(), &CutterCore::registersChanged, this, &MemoryMapWidget::refreshMemoryMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMapWidget::~MemoryMapWidget() {}
|
||||||
|
|
||||||
|
void MemoryMapWidget::refreshMemoryMap()
|
||||||
|
{
|
||||||
|
memoryModel->beginReloadMemoryMap();
|
||||||
|
memoryMaps = Core()->getMemoryMap();
|
||||||
|
memoryModel->endReloadMemoryMap();
|
||||||
|
|
||||||
|
ui->memoryTreeView->resizeColumnToContents(0);
|
||||||
|
ui->memoryTreeView->resizeColumnToContents(1);
|
||||||
|
ui->memoryTreeView->resizeColumnToContents(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryMapWidget::setScrollMode()
|
||||||
|
{
|
||||||
|
qhelpers::setVerticalScrollMode(ui->memoryTreeView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryMapWidget::on_memoryTreeView_doubleClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
MemoryMapDescription item = index.data(MemoryMapModel::MemoryDescriptionRole).value<MemoryMapDescription>();
|
||||||
|
Core()->seek(item.addrStart);
|
||||||
|
}
|
84
src/widgets/MemoryMapWidget.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidget;
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class MemoryMapWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
|
||||||
|
|
||||||
|
class MemoryMapModel: public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<MemoryMapDescription> *memoryMaps;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column { AddrStartColumn = 0, AddrEndColumn, NameColumn, PermColumn, ColumnCount };
|
||||||
|
enum Role { MemoryDescriptionRole = Qt::UserRole };
|
||||||
|
|
||||||
|
MemoryMapModel(QList<MemoryMapDescription> *memoryMaps, 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 beginReloadMemoryMap();
|
||||||
|
void endReloadMemoryMap();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MemoryProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryProxyModel(MemoryMapModel *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 MemoryMapWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MemoryMapWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
|
~MemoryMapWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_memoryTreeView_doubleClicked(const QModelIndex &index);
|
||||||
|
|
||||||
|
void refreshMemoryMap();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::MemoryMapWidget> ui;
|
||||||
|
|
||||||
|
MemoryMapModel *memoryModel;
|
||||||
|
MemoryProxyModel *memoryProxyModel;
|
||||||
|
QList<MemoryMapDescription> memoryMaps;
|
||||||
|
|
||||||
|
void setScrollMode();
|
||||||
|
};
|
58
src/widgets/MemoryMapWidget.ui
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MemoryMapWidget</class>
|
||||||
|
<widget class="QDockWidget" name="MemoryMapWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Memory Map</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="memoryTreeView">
|
||||||
|
<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>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -19,7 +19,7 @@ RegistersWidget::RegistersWidget(MainWindow *main, QAction *action) :
|
|||||||
|
|
||||||
ui->verticalLayout->addWidget(buttonSetRegisters);
|
ui->verticalLayout->addWidget(buttonSetRegisters);
|
||||||
connect(Core(), &CutterCore::refreshAll, this, &RegistersWidget::updateContents);
|
connect(Core(), &CutterCore::refreshAll, this, &RegistersWidget::updateContents);
|
||||||
connect(Core(), &CutterCore::seekChanged, this, &RegistersWidget::updateContents);
|
connect(Core(), &CutterCore::registersChanged, this, &RegistersWidget::updateContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegistersWidget::~RegistersWidget() {}
|
RegistersWidget::~RegistersWidget() {}
|
||||||
|