mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +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");
|
||||
}
|
||||
|
||||
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 stats;
|
||||
|
@ -414,6 +414,11 @@ public:
|
||||
QList<QList<QString>> get_exec_sections();
|
||||
QString getOffsetInfo(QString addr);
|
||||
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);
|
||||
QString getDecompiledCode(RVA addr);
|
||||
QString getDecompiledCode(QString addr);
|
||||
|
@ -162,7 +162,10 @@ SOURCES += \
|
||||
dialogs/VersionInfoDialog.cpp \
|
||||
widgets/ZignaturesWidget.cpp \
|
||||
utils/AsyncTask.cpp \
|
||||
dialogs/AsyncTaskDialog.cpp
|
||||
dialogs/AsyncTaskDialog.cpp \
|
||||
widgets/StackWidget.cpp \
|
||||
widgets/RegistersWidget.cpp \
|
||||
widgets/BacktraceWidget.cpp
|
||||
|
||||
HEADERS += \
|
||||
Cutter.h \
|
||||
@ -239,7 +242,10 @@ HEADERS += \
|
||||
dialogs/VersionInfoDialog.h \
|
||||
widgets/ZignaturesWidget.h \
|
||||
utils/AsyncTask.h \
|
||||
dialogs/AsyncTaskDialog.h
|
||||
dialogs/AsyncTaskDialog.h \
|
||||
widgets/StackWidget.h \
|
||||
widgets/RegistersWidget.h \
|
||||
widgets/BacktraceWidget.h
|
||||
|
||||
FORMS += \
|
||||
dialogs/AboutDialog.ui \
|
||||
@ -283,7 +289,10 @@ FORMS += \
|
||||
dialogs/R2PluginsDialog.ui \
|
||||
dialogs/VersionInfoDialog.ui \
|
||||
widgets/ZignaturesWidget.ui \
|
||||
dialogs/AsyncTaskDialog.ui
|
||||
dialogs/AsyncTaskDialog.ui \
|
||||
widgets/StackWidget.ui \
|
||||
widgets/RegistersWidget.ui \
|
||||
widgets/BacktraceWidget.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc \
|
||||
|
@ -178,6 +178,9 @@ void MainWindow::initUI()
|
||||
commentsDock = new CommentsWidget(this, ui->actionComments);
|
||||
stringsDock = new StringsWidget(this, ui->actionStrings);
|
||||
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
|
||||
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
|
||||
#else
|
||||
@ -497,6 +500,11 @@ void MainWindow::restoreDocks()
|
||||
tabifyDockWidget(dashboardDock, classesDock);
|
||||
tabifyDockWidget(dashboardDock, resourcesDock);
|
||||
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
|
||||
tabifyDockWidget(dashboardDock, jupyterDock);
|
||||
#endif
|
||||
|
@ -6,6 +6,9 @@
|
||||
#include "Cutter.h" // only needed for ut64
|
||||
#include "widgets/DisassemblyWidget.h"
|
||||
#include "widgets/SidebarWidget.h"
|
||||
#include "widgets/StackWidget.h"
|
||||
#include "widgets/RegistersWidget.h"
|
||||
#include "widgets/BacktraceWidget.h"
|
||||
#include "widgets/HexdumpWidget.h"
|
||||
#include "widgets/PseudocodeWidget.h"
|
||||
#include "dialogs/NewFileDialog.h"
|
||||
@ -211,6 +214,9 @@ private:
|
||||
DisassemblerGraphView *graphView = nullptr;
|
||||
QDockWidget *asmDock = nullptr;
|
||||
QDockWidget *calcDock = nullptr;
|
||||
QDockWidget *stackDock = nullptr;
|
||||
QDockWidget *registersDock = nullptr;
|
||||
QDockWidget *backtraceDock = nullptr;
|
||||
NewFileDialog *newFileDialog = nullptr;
|
||||
#ifdef CUTTER_ENABLE_JUPYTER
|
||||
JupyterWidget *jupyterDock = nullptr;
|
||||
|
@ -223,6 +223,33 @@ border-top: 0px;
|
||||
<addaction name="actionUndoSeek"/>
|
||||
<addaction name="actionRedoSeek"/>
|
||||
</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">
|
||||
<property name="title">
|
||||
<string>Windows</string>
|
||||
@ -233,26 +260,14 @@ border-top: 0px;
|
||||
<addaction name="actionGraph"/>
|
||||
<addaction name="actionHexdump"/>
|
||||
<addaction name="actionPseudocode"/>
|
||||
<addaction name="actionFunctions"/>
|
||||
<addaction name="actionSidebar"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionEntrypoints"/>
|
||||
<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="actionStrings"/>
|
||||
<addaction name="actionSearch"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRelocs"/>
|
||||
<addaction name="actionStrings"/>
|
||||
<addaction name="actionFlags"/>
|
||||
<addaction name="actionSections"/>
|
||||
<addaction name="actionHeaders"/>
|
||||
<addaction name="actionZignatures"/>
|
||||
<addaction name="addInfoWidgets"/>
|
||||
<addaction name="addDebugWidgets"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionComments"/>
|
||||
<addaction name="actionConsole"/>
|
||||
@ -1015,6 +1030,30 @@ background-color: palette(dark);
|
||||
<string>Console</string>
|
||||
</property>
|
||||
</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">
|
||||
<property name="checkable">
|
||||
<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