mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 10:58:51 +00:00
Added widget to view register values (#509)
* Added backtrace info * Make stack printing arch agnostic * Split into registers/stack/backtrace widgets * hide table idxs in stacktable * backtrace table header has register name instead of generic PC/SP * imports cleanup * add sorting to stack table * add Qheaderview import * Added button to set registers * added color to recently changed register * reorganized Windows tab and added stacking to debug widgets
This commit is contained in:
parent
14cfe74324
commit
e8b024042b
@ -689,6 +689,31 @@ QJsonDocument CutterCore::getSignatureInfo()
|
|||||||
return cmdj("iCj");
|
return cmdj("iCj");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonDocument CutterCore::getStack(int size)
|
||||||
|
{
|
||||||
|
return cmdj("pxrj " + QString::number(size) + " @ r:SP");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument CutterCore::getRegisterValues()
|
||||||
|
{
|
||||||
|
return cmdj("drj");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CutterCore::getRegisterName(QString registerRole)
|
||||||
|
{
|
||||||
|
return cmd("drn " + registerRole).trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::setRegister(QString regName, QString regValue)
|
||||||
|
{
|
||||||
|
cmd("dr " + regName + "=" + regValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument CutterCore::getBacktrace()
|
||||||
|
{
|
||||||
|
return cmdj("dbtj");
|
||||||
|
}
|
||||||
|
|
||||||
QStringList CutterCore::getStats()
|
QStringList CutterCore::getStats()
|
||||||
{
|
{
|
||||||
QStringList stats;
|
QStringList stats;
|
||||||
|
@ -414,6 +414,11 @@ public:
|
|||||||
QList<QList<QString>> get_exec_sections();
|
QList<QList<QString>> get_exec_sections();
|
||||||
QString getOffsetInfo(QString addr);
|
QString getOffsetInfo(QString addr);
|
||||||
QJsonDocument getRegistersInfo();
|
QJsonDocument getRegistersInfo();
|
||||||
|
QJsonDocument getRegisterValues();
|
||||||
|
QString getRegisterName(QString registerRole);
|
||||||
|
void setRegister(QString regName, QString regValue);
|
||||||
|
QJsonDocument getStack(int size = 0x40);
|
||||||
|
QJsonDocument getBacktrace();
|
||||||
RVA getOffsetJump(RVA addr);
|
RVA getOffsetJump(RVA addr);
|
||||||
QString getDecompiledCode(RVA addr);
|
QString getDecompiledCode(RVA addr);
|
||||||
QString getDecompiledCode(QString addr);
|
QString getDecompiledCode(QString addr);
|
||||||
|
@ -162,7 +162,10 @@ SOURCES += \
|
|||||||
dialogs/VersionInfoDialog.cpp \
|
dialogs/VersionInfoDialog.cpp \
|
||||||
widgets/ZignaturesWidget.cpp \
|
widgets/ZignaturesWidget.cpp \
|
||||||
utils/AsyncTask.cpp \
|
utils/AsyncTask.cpp \
|
||||||
dialogs/AsyncTaskDialog.cpp
|
dialogs/AsyncTaskDialog.cpp \
|
||||||
|
widgets/StackWidget.cpp \
|
||||||
|
widgets/RegistersWidget.cpp \
|
||||||
|
widgets/BacktraceWidget.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Cutter.h \
|
Cutter.h \
|
||||||
@ -239,7 +242,10 @@ HEADERS += \
|
|||||||
dialogs/VersionInfoDialog.h \
|
dialogs/VersionInfoDialog.h \
|
||||||
widgets/ZignaturesWidget.h \
|
widgets/ZignaturesWidget.h \
|
||||||
utils/AsyncTask.h \
|
utils/AsyncTask.h \
|
||||||
dialogs/AsyncTaskDialog.h
|
dialogs/AsyncTaskDialog.h \
|
||||||
|
widgets/StackWidget.h \
|
||||||
|
widgets/RegistersWidget.h \
|
||||||
|
widgets/BacktraceWidget.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
@ -283,7 +289,10 @@ FORMS += \
|
|||||||
dialogs/R2PluginsDialog.ui \
|
dialogs/R2PluginsDialog.ui \
|
||||||
dialogs/VersionInfoDialog.ui \
|
dialogs/VersionInfoDialog.ui \
|
||||||
widgets/ZignaturesWidget.ui \
|
widgets/ZignaturesWidget.ui \
|
||||||
dialogs/AsyncTaskDialog.ui
|
dialogs/AsyncTaskDialog.ui \
|
||||||
|
widgets/StackWidget.ui \
|
||||||
|
widgets/RegistersWidget.ui \
|
||||||
|
widgets/BacktraceWidget.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc \
|
resources.qrc \
|
||||||
|
@ -178,6 +178,9 @@ void MainWindow::initUI()
|
|||||||
commentsDock = new CommentsWidget(this, ui->actionComments);
|
commentsDock = new CommentsWidget(this, ui->actionComments);
|
||||||
stringsDock = new StringsWidget(this, ui->actionStrings);
|
stringsDock = new StringsWidget(this, ui->actionStrings);
|
||||||
flagsDock = new FlagsWidget(this, ui->actionFlags);
|
flagsDock = new FlagsWidget(this, ui->actionFlags);
|
||||||
|
stackDock = new StackWidget(this, ui->actionStack);
|
||||||
|
backtraceDock = new BacktraceWidget(this, ui->actionBacktrace);
|
||||||
|
registersDock = new RegistersWidget(this, ui->actionRegisters);
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
||||||
#else
|
#else
|
||||||
@ -497,6 +500,11 @@ void MainWindow::restoreDocks()
|
|||||||
tabifyDockWidget(dashboardDock, classesDock);
|
tabifyDockWidget(dashboardDock, classesDock);
|
||||||
tabifyDockWidget(dashboardDock, resourcesDock);
|
tabifyDockWidget(dashboardDock, resourcesDock);
|
||||||
tabifyDockWidget(dashboardDock, vTablesDock);
|
tabifyDockWidget(dashboardDock, vTablesDock);
|
||||||
|
|
||||||
|
// Add Stack, Registers and Backtrace vertically stacked
|
||||||
|
addExtraWidget(stackDock);
|
||||||
|
splitDockWidget(stackDock, registersDock, Qt::Vertical);
|
||||||
|
splitDockWidget(stackDock, backtraceDock, Qt::Vertical);
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
tabifyDockWidget(dashboardDock, jupyterDock);
|
tabifyDockWidget(dashboardDock, jupyterDock);
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
#include "Cutter.h" // only needed for ut64
|
#include "Cutter.h" // only needed for ut64
|
||||||
#include "widgets/DisassemblyWidget.h"
|
#include "widgets/DisassemblyWidget.h"
|
||||||
#include "widgets/SidebarWidget.h"
|
#include "widgets/SidebarWidget.h"
|
||||||
|
#include "widgets/StackWidget.h"
|
||||||
|
#include "widgets/RegistersWidget.h"
|
||||||
|
#include "widgets/BacktraceWidget.h"
|
||||||
#include "widgets/HexdumpWidget.h"
|
#include "widgets/HexdumpWidget.h"
|
||||||
#include "widgets/PseudocodeWidget.h"
|
#include "widgets/PseudocodeWidget.h"
|
||||||
#include "dialogs/NewFileDialog.h"
|
#include "dialogs/NewFileDialog.h"
|
||||||
@ -211,6 +214,9 @@ private:
|
|||||||
DisassemblerGraphView *graphView = nullptr;
|
DisassemblerGraphView *graphView = nullptr;
|
||||||
QDockWidget *asmDock = nullptr;
|
QDockWidget *asmDock = nullptr;
|
||||||
QDockWidget *calcDock = nullptr;
|
QDockWidget *calcDock = nullptr;
|
||||||
|
QDockWidget *stackDock = nullptr;
|
||||||
|
QDockWidget *registersDock = nullptr;
|
||||||
|
QDockWidget *backtraceDock = nullptr;
|
||||||
NewFileDialog *newFileDialog = nullptr;
|
NewFileDialog *newFileDialog = nullptr;
|
||||||
#ifdef CUTTER_ENABLE_JUPYTER
|
#ifdef CUTTER_ENABLE_JUPYTER
|
||||||
JupyterWidget *jupyterDock = nullptr;
|
JupyterWidget *jupyterDock = nullptr;
|
||||||
|
@ -223,6 +223,33 @@ border-top: 0px;
|
|||||||
<addaction name="actionUndoSeek"/>
|
<addaction name="actionUndoSeek"/>
|
||||||
<addaction name="actionRedoSeek"/>
|
<addaction name="actionRedoSeek"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="addDebugWidgets">
|
||||||
|
<property name="title">
|
||||||
|
<string>Debug...</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionStack"/>
|
||||||
|
<addaction name="actionRegisters"/>
|
||||||
|
<addaction name="actionBacktrace"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="addInfoWidgets">
|
||||||
|
<property name="title">
|
||||||
|
<string>Info...</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionEntrypoints"/>
|
||||||
|
<addaction name="actionClasses"/>
|
||||||
|
<addaction name="actionImports"/>
|
||||||
|
<addaction name="actionExports"/>
|
||||||
|
<addaction name="actionSymbols"/>
|
||||||
|
<addaction name="actionSDBBrowser"/>
|
||||||
|
<addaction name="actionResources"/>
|
||||||
|
<addaction name="actionVTables"/>
|
||||||
|
<addaction name="actionTypes"/>
|
||||||
|
<addaction name="actionFlags"/>
|
||||||
|
<addaction name="actionSections"/>
|
||||||
|
<addaction name="actionHeaders"/>
|
||||||
|
<addaction name="actionZignatures"/>
|
||||||
|
<addaction name="actionRelocs"/>
|
||||||
|
</widget>
|
||||||
<widget class="QMenu" name="menuWindows">
|
<widget class="QMenu" name="menuWindows">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Windows</string>
|
<string>Windows</string>
|
||||||
@ -233,26 +260,14 @@ border-top: 0px;
|
|||||||
<addaction name="actionGraph"/>
|
<addaction name="actionGraph"/>
|
||||||
<addaction name="actionHexdump"/>
|
<addaction name="actionHexdump"/>
|
||||||
<addaction name="actionPseudocode"/>
|
<addaction name="actionPseudocode"/>
|
||||||
|
<addaction name="actionFunctions"/>
|
||||||
<addaction name="actionSidebar"/>
|
<addaction name="actionSidebar"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionEntrypoints"/>
|
<addaction name="actionStrings"/>
|
||||||
<addaction name="actionFunctions"/>
|
|
||||||
<addaction name="actionClasses"/>
|
|
||||||
<addaction name="actionImports"/>
|
|
||||||
<addaction name="actionExports"/>
|
|
||||||
<addaction name="actionSymbols"/>
|
|
||||||
<addaction name="actionSDBBrowser"/>
|
|
||||||
<addaction name="actionResources"/>
|
|
||||||
<addaction name="actionVTables"/>
|
|
||||||
<addaction name="actionTypes"/>
|
|
||||||
<addaction name="actionSearch"/>
|
<addaction name="actionSearch"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionRelocs"/>
|
<addaction name="addInfoWidgets"/>
|
||||||
<addaction name="actionStrings"/>
|
<addaction name="addDebugWidgets"/>
|
||||||
<addaction name="actionFlags"/>
|
|
||||||
<addaction name="actionSections"/>
|
|
||||||
<addaction name="actionHeaders"/>
|
|
||||||
<addaction name="actionZignatures"/>
|
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionComments"/>
|
<addaction name="actionComments"/>
|
||||||
<addaction name="actionConsole"/>
|
<addaction name="actionConsole"/>
|
||||||
@ -1015,6 +1030,30 @@ background-color: palette(dark);
|
|||||||
<string>Console</string>
|
<string>Console</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionStack">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Stack</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionRegisters">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Registers</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionBacktrace">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Backtrace</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionClasses">
|
<action name="actionClasses">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
63
src/widgets/BacktraceWidget.cpp
Normal file
63
src/widgets/BacktraceWidget.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "BacktraceWidget.h"
|
||||||
|
#include "ui_BacktraceWidget.h"
|
||||||
|
#include "utils/JsonModel.h"
|
||||||
|
|
||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
BacktraceWidget::BacktraceWidget(MainWindow *main, QAction *action) :
|
||||||
|
CutterDockWidget(main, action),
|
||||||
|
ui(new Ui::BacktraceWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// setup backtrace model
|
||||||
|
QString PC = Core()->getRegisterName("PC");
|
||||||
|
QString SP = Core()->getRegisterName("SP");
|
||||||
|
modelBacktrace->setHorizontalHeaderItem(0, new QStandardItem(PC));
|
||||||
|
modelBacktrace->setHorizontalHeaderItem(1, new QStandardItem(SP));
|
||||||
|
modelBacktrace->setHorizontalHeaderItem(2, new QStandardItem(tr("Frame Size")));
|
||||||
|
modelBacktrace->setHorizontalHeaderItem(3, new QStandardItem(tr("Func Name")));
|
||||||
|
modelBacktrace->setHorizontalHeaderItem(4, new QStandardItem(tr("Description")));
|
||||||
|
viewBacktrace->setStyleSheet("QTableView {font-family: mono}");
|
||||||
|
viewBacktrace->setModel(modelBacktrace);
|
||||||
|
ui->verticalLayout->addWidget(viewBacktrace);
|
||||||
|
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &BacktraceWidget::updateContents);
|
||||||
|
connect(Core(), &CutterCore::seekChanged, this, &BacktraceWidget::updateContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
BacktraceWidget::~BacktraceWidget() {}
|
||||||
|
|
||||||
|
void BacktraceWidget::updateContents()
|
||||||
|
{
|
||||||
|
setBacktraceGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BacktraceWidget::setBacktraceGrid()
|
||||||
|
{
|
||||||
|
QJsonArray backtraceValues = Core()->getBacktrace().array();
|
||||||
|
int i = 0;
|
||||||
|
for (QJsonValueRef value : backtraceValues) {
|
||||||
|
QJsonObject backtraceItem = value.toObject();
|
||||||
|
QString progCounter = RAddressString(backtraceItem["pc"].toVariant().toULongLong());
|
||||||
|
QString stackPointer = RAddressString(backtraceItem["sp"].toVariant().toULongLong());
|
||||||
|
int frameSize = backtraceItem["frame_size"].toInt();
|
||||||
|
QString funcName = backtraceItem["fname"].toString();
|
||||||
|
QString desc = backtraceItem["desc"].toString();
|
||||||
|
|
||||||
|
QStandardItem *rowPC = new QStandardItem(progCounter);
|
||||||
|
QStandardItem *rowSP = new QStandardItem(stackPointer);
|
||||||
|
QStandardItem *rowFrameSize = new QStandardItem(frameSize);
|
||||||
|
QStandardItem *rowFuncName = new QStandardItem(funcName);
|
||||||
|
QStandardItem *rowDesc = new QStandardItem(desc);
|
||||||
|
|
||||||
|
modelBacktrace->setItem(i, 0, rowPC);
|
||||||
|
modelBacktrace->setItem(i, 1, rowSP);
|
||||||
|
modelBacktrace->setItem(i, 2, rowFrameSize);
|
||||||
|
modelBacktrace->setItem(i, 3, rowFuncName);
|
||||||
|
modelBacktrace->setItem(i, 4, rowDesc);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
viewBacktrace->setModel(modelBacktrace);
|
||||||
|
viewBacktrace->resizeColumnsToContents();;
|
||||||
|
}
|
33
src/widgets/BacktraceWidget.h
Normal file
33
src/widgets/BacktraceWidget.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <memory>
|
||||||
|
#include <QStandardItem>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BacktraceWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BacktraceWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BacktraceWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
|
~BacktraceWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateContents();
|
||||||
|
void setBacktraceGrid();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::BacktraceWidget> ui;
|
||||||
|
QStandardItemModel *modelBacktrace = new QStandardItemModel(1, 5, this);
|
||||||
|
QTableView *viewBacktrace = new QTableView;
|
||||||
|
};
|
35
src/widgets/BacktraceWidget.ui
Normal file
35
src/widgets/BacktraceWidget.ui
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BacktraceWidget</class>
|
||||||
|
<widget class="QDockWidget" name="BacktraceWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>463</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Backtrace</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
103
src/widgets/RegistersWidget.cpp
Normal file
103
src/widgets/RegistersWidget.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "RegistersWidget.h"
|
||||||
|
#include "ui_RegistersWidget.h"
|
||||||
|
#include "utils/JsonModel.h"
|
||||||
|
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "QPushButton"
|
||||||
|
|
||||||
|
RegistersWidget::RegistersWidget(MainWindow *main, QAction *action) :
|
||||||
|
CutterDockWidget(main, action),
|
||||||
|
ui(new Ui::RegistersWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// setup register layout
|
||||||
|
ui->verticalLayout->addLayout(registerLayout);
|
||||||
|
|
||||||
|
buttonSetRegisters = new QPushButton("Set registers", this);
|
||||||
|
connect(buttonSetRegisters, &QPushButton::clicked, this, &RegistersWidget::handleButton);
|
||||||
|
|
||||||
|
ui->verticalLayout->addWidget(buttonSetRegisters);
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &RegistersWidget::updateContents);
|
||||||
|
connect(Core(), &CutterCore::seekChanged, this, &RegistersWidget::updateContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegistersWidget::~RegistersWidget() {}
|
||||||
|
|
||||||
|
void RegistersWidget::updateContents()
|
||||||
|
{
|
||||||
|
setRegisterGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistersWidget::handleButton()
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
int i = 0;
|
||||||
|
int col = 0;
|
||||||
|
for (j = 0; j<registerLen; j++) {
|
||||||
|
QWidget *regName = registerLayout->itemAtPosition(i, col)->widget();
|
||||||
|
QWidget *regValue = registerLayout->itemAtPosition(i, col + 1)->widget();
|
||||||
|
QLabel *regLabel = qobject_cast<QLabel *>(regName);
|
||||||
|
QLineEdit *regLine = qobject_cast<QLineEdit *>(regValue);
|
||||||
|
QString regNameString = regLabel->text();
|
||||||
|
QString regValueString = regLine->text();
|
||||||
|
Core()->setRegister(regNameString, regValueString);
|
||||||
|
i++;
|
||||||
|
if (i >= registerLen/numCols + 1) {
|
||||||
|
i = 0;
|
||||||
|
col += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setRegisterGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistersWidget::setRegisterGrid()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int col = 0;
|
||||||
|
QString regValue;
|
||||||
|
QLabel *registerLabel;
|
||||||
|
QLineEdit *registerEditValue;
|
||||||
|
QJsonObject registerValues = Core()->getRegisterValues().object();
|
||||||
|
QStringList registerNames = registerValues.keys();
|
||||||
|
registerLen = registerNames.size();
|
||||||
|
for (const QString &key : registerNames) {
|
||||||
|
regValue = RAddressString(registerValues[key].toVariant().toULongLong());
|
||||||
|
// check if we already filled this grid space with label/value
|
||||||
|
if (!registerLayout->itemAtPosition(i, col)) {
|
||||||
|
registerLabel = new QLabel;
|
||||||
|
registerLabel->setStyleSheet("font-weight: bold; font-family: mono");
|
||||||
|
registerEditValue = new QLineEdit;
|
||||||
|
QFont font = registerEditValue->font();
|
||||||
|
font.setWeight(QFont::Monospace);
|
||||||
|
registerEditValue->setFont(font);
|
||||||
|
// add label and register value to grid
|
||||||
|
registerLayout->addWidget(registerLabel, i, col);
|
||||||
|
registerLayout->addWidget(registerEditValue, i, col + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QWidget *regNameWidget = registerLayout->itemAtPosition(i, col)->widget();
|
||||||
|
QWidget *regValueWidget = registerLayout->itemAtPosition(i, col + 1)->widget();
|
||||||
|
registerLabel = qobject_cast<QLabel *>(regNameWidget);
|
||||||
|
registerEditValue = qobject_cast<QLineEdit *>(regValueWidget);
|
||||||
|
}
|
||||||
|
// decide to highlight QLine Box in case of change of register value
|
||||||
|
if (regValue != registerEditValue->text() && registerEditValue->text() != 0) {
|
||||||
|
registerEditValue->setStyleSheet("QLineEdit {border: 1px solid green;} QLineEdit:hover { border: 1px solid #3daee9; color: #eff0f1;}");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// reset stylesheet
|
||||||
|
registerEditValue->setStyleSheet("");
|
||||||
|
}
|
||||||
|
// define register label and value
|
||||||
|
registerLabel->setText(key);
|
||||||
|
registerEditValue->setPlaceholderText(regValue);
|
||||||
|
registerEditValue->setText(regValue);
|
||||||
|
i++;
|
||||||
|
// decide if we should change column
|
||||||
|
if (i >= registerLen/numCols + 1) {
|
||||||
|
i = 0;
|
||||||
|
col += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
src/widgets/RegistersWidget.h
Normal file
37
src/widgets/RegistersWidget.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RegistersWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RegistersWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RegistersWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
|
~RegistersWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateContents();
|
||||||
|
void setRegisterGrid();
|
||||||
|
void handleButton();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::RegistersWidget> ui;
|
||||||
|
QGridLayout *registerLayout = new QGridLayout;
|
||||||
|
int numCols = 2;
|
||||||
|
int registerLen = 0;
|
||||||
|
QPushButton *buttonSetRegisters;
|
||||||
|
};
|
35
src/widgets/RegistersWidget.ui
Normal file
35
src/widgets/RegistersWidget.ui
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>RegistersWidget</class>
|
||||||
|
<widget class="QDockWidget" name="RegistersWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>463</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Registers</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
58
src/widgets/StackWidget.cpp
Normal file
58
src/widgets/StackWidget.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "StackWidget.h"
|
||||||
|
#include "ui_StackWidget.h"
|
||||||
|
#include "utils/JsonModel.h"
|
||||||
|
#include "utils/Helpers.h"
|
||||||
|
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "QHeaderView"
|
||||||
|
|
||||||
|
StackWidget::StackWidget(MainWindow *main, QAction *action) :
|
||||||
|
CutterDockWidget(main, action),
|
||||||
|
ui(new Ui::StackWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// setup stack model
|
||||||
|
modelStack->setHorizontalHeaderItem(0, new QStandardItem(tr("Offset")));
|
||||||
|
modelStack->setHorizontalHeaderItem(1, new QStandardItem(tr("Value")));
|
||||||
|
modelStack->setHorizontalHeaderItem(2, new QStandardItem(tr("Reference")));
|
||||||
|
viewStack->setStyleSheet("QTableView {font-family: mono}");
|
||||||
|
viewStack->setModel(modelStack);
|
||||||
|
viewStack->verticalHeader()->hide();
|
||||||
|
viewStack->setSortingEnabled(true);
|
||||||
|
ui->verticalLayout->addWidget(viewStack);
|
||||||
|
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &StackWidget::updateContents);
|
||||||
|
connect(Core(), &CutterCore::seekChanged, this, &StackWidget::updateContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackWidget::~StackWidget() {}
|
||||||
|
|
||||||
|
void StackWidget::updateContents()
|
||||||
|
{
|
||||||
|
setStackGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StackWidget::setStackGrid()
|
||||||
|
{
|
||||||
|
QJsonArray stackValues = Core()->getStack().array();
|
||||||
|
int i = 0;
|
||||||
|
for (QJsonValueRef value : stackValues) {
|
||||||
|
QJsonObject stackItem = value.toObject();
|
||||||
|
QString addr = RAddressString(stackItem["addr"].toVariant().toULongLong());
|
||||||
|
QString valueStack = RAddressString(stackItem["value"].toVariant().toULongLong());
|
||||||
|
QStandardItem *rowOffset = new QStandardItem(addr);
|
||||||
|
QStandardItem *rowValue = new QStandardItem(valueStack);
|
||||||
|
modelStack->setItem(i, 0, rowOffset);
|
||||||
|
modelStack->setItem(i, 1, rowValue);
|
||||||
|
QJsonValue refObject = stackItem["ref"];
|
||||||
|
if (!refObject.isUndefined()) { // check that the key exists
|
||||||
|
QString ref = refObject.toString();
|
||||||
|
QStandardItem *rowRef = new QStandardItem(ref);
|
||||||
|
modelStack->setItem(i, 2, rowRef);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
viewStack->setModel(modelStack);
|
||||||
|
viewStack->resizeColumnsToContents();;
|
||||||
|
}
|
33
src/widgets/StackWidget.h
Normal file
33
src/widgets/StackWidget.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <memory>
|
||||||
|
#include <QStandardItem>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class StackWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StackWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit StackWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
|
~StackWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateContents();
|
||||||
|
void setStackGrid();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::StackWidget> ui;
|
||||||
|
QTableView *viewStack = new QTableView;
|
||||||
|
QStandardItemModel *modelStack = new QStandardItemModel(1, 3, this);
|
||||||
|
};
|
35
src/widgets/StackWidget.ui
Normal file
35
src/widgets/StackWidget.ui
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>StackWidget</class>
|
||||||
|
<widget class="QDockWidget" name="StackWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>463</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Stack</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue
Block a user