1
0
Fork 0

Minor usability improvements for hex_viewer

This commit is contained in:
Duncan Ogilvie 2025-06-15 15:00:58 +02:00
parent 0d2259a311
commit 5a7cbc4a7b
6 changed files with 61 additions and 17 deletions

View File

@ -10,6 +10,18 @@ DataTable::DataTable(QWidget *parent)
mTypes.emplace_back(name, std::move(fn));
};
type("Address", [this](duint start, duint end) {
auto size = end - start + 1;
if(size > 1)
{
return QString("0x%1 - 0x%2 (0x%3 bytes)").arg(ToHexString(start)).arg(ToHexString(end)).arg(ToHexString(size));
}
else
{
return "0x" + ToHexString(start);
}
});
type("Binary (u8)", [this](duint start, duint end) {
uint8_t data = 0;
read(&data, start, sizeof(data));

View File

@ -166,7 +166,7 @@ void MainWindow::setupNavigation()
{
case Navigation::Dump:
qDebug() << "Dump at: " << address;
mHexDump->printDumpAt(address);
gotoHexDump(address, 1);
break;
default:
qDebug() << "Unknown window: " << window;
@ -211,6 +211,7 @@ void MainWindow::setupWidgets()
{
mDataTable->selectionChanged(mHexDump->getSelectionStart(), mHexDump->getSelectionEnd());
});
connect(mStructWidget, &StructWidget::selectionUpdated, this, &MainWindow::gotoHexDump);
auto hl = new QHBoxLayout();
//hl->addSpacing()
@ -232,13 +233,13 @@ void MainWindow::setupWidgets()
auto codeSplitter = new QSplitter(Qt::Vertical, this);
codeSplitter->addWidget(codeWidget);
codeSplitter->addWidget(mLogBrowser);
codeSplitter->addWidget(mStructWidget);
codeSplitter->setStretchFactor(0, 80);
codeSplitter->setStretchFactor(0, 20);
mStructTabs = new QTabWidget(this);
mStructTabs->addTab(mDataTable, "Data");
mStructTabs->addTab(mStructWidget, "Struct");
mStructTabs->addTab(mDataTable, "Inspector");
mStructTabs->addTab(mLogBrowser, "Console");
auto hexSplitter = new QSplitter(Qt::Vertical, this);
hexSplitter->addWidget(mHexDump);
@ -312,6 +313,27 @@ void MainWindow::evalError(const EvalError & error)
}
}
void MainWindow::gotoHexDump(duint address, duint size)
{
duint viewStart = mHexDump->getTableOffset() * mHexDump->getBytePerRowCount();
duint viewSize = mHexDump->getViewableRowsCount() * mHexDump->getBytePerRowCount();
duint viewEnd = viewStart + viewSize;
duint alignedAddress = address - address % 16;
// Make sure the address is in view
if(address < viewStart || address >= viewEnd)
{
mHexDump->printDumpAt(alignedAddress, false, false, true);
}
// Go to the aligned address and then set the selection
mHexDump->printDumpAt(alignedAddress, true, false, false);
mHexDump->setSingleSelection(address);
if(size > 1)
{
mHexDump->expandSelectionUpTo(address + size - 1);
}
mHexDump->updateViewport();
}
void MainWindow::onLogAnchorClicked(const QUrl & url)
{
if(url.scheme() == "navigate")
@ -382,10 +404,7 @@ void MainWindow::onButtonRunPressed()
mCodeEditor->setErrorLine(-1);
auto status = PatternRun(&args);
emit Bridge::getBridge()->typeUpdateWidget();
if(status == PatternSuccess)
{
mStructTabs->setCurrentIndex(1);
}
mStructTabs->setCurrentIndex(1);
}

View File

@ -30,6 +30,7 @@ public:
private slots:
void onButtonRunPressed();
void onLogAnchorClicked(const QUrl & url);
void gotoHexDump(duint address, duint size);
void on_action_Load_file_triggered();

View File

@ -6,7 +6,8 @@ MiniHexDump::MiniHexDump(Navigation* navigation, Architecture* architecture, QWi
: HexDump(architecture, parent)
, mNavigation(navigation)
{
mUnderliningEnabled = false;
mPointerUnderliningEnabled = false;
mSelectionUnderliningEnabled = true;
hexAsciiSlot();
setupMenu();
}

View File

@ -10,6 +10,10 @@
#include "MiscUtil.h"
#include "RichTextItemDelegate.h"
#define hasSelection !!ui->treeWidget->selectedItems().count()
#define selectedItem ui->treeWidget->selectedItems()[0]
#define selectedType selectedItem->data(0, Qt::UserRole).value<TypeDescriptor>().type
struct TypeDescriptor
{
TYPEDESCRIPTOR type = {};
@ -34,6 +38,14 @@ StructWidget::StructWidget(QWidget* parent) :
fontsUpdatedSlot();
setupColumns();
setupContextMenu();
connect(ui->treeWidget, &QTreeWidget::itemSelectionChanged, [this]()
{
if(hasSelection)
{
emit selectionUpdated(selectedType.addr + selectedType.offset, selectedType.sizeBits / 8);
}
});
}
StructWidget::~StructWidget()
@ -113,9 +125,9 @@ void StructWidget::typeAddNode(void* parent, const TYPEDESCRIPTOR* type, void**
text[ColOffset] = "+0x" + ToHexString(dtype.type.offset);
text[ColField] = dtype.name;
if(dtype.type.offset == 0 && true)
text[ColAddress] = QString("<u>%1</u>").arg(ToPtrString(dtype.type.addr + dtype.type.offset));
text[ColAddress] = QString("<u>%1</u>").arg(ToHexString(dtype.type.addr + dtype.type.offset));
else
text[ColAddress] = ToPtrString(dtype.type.addr + dtype.type.offset);
text[ColAddress] = ToHexString(dtype.type.addr + dtype.type.offset);
text[ColSize] = "0x" + ToHexString(dtype.type.sizeBits / 8);
text[ColValue] = ""; // NOTE: filled in later
QTreeWidgetItem* item = parent ? new QTreeWidgetItem((QTreeWidgetItem*)parent, text) : new QTreeWidgetItem(ui->treeWidget, text);
@ -142,7 +154,7 @@ void StructWidget::typeUpdateWidget()
type.type.name = name.constData();
auto addr = type.type.addr + type.type.offset;
item->setText(ColAddress, ToPtrString(addr));
item->setText(ColAddress, ToHexString(addr));
QString valueStr;
if(type.type.callback) //use the provided callback
@ -191,7 +203,7 @@ void StructWidget::setupColumns()
auto charWidth = ui->treeWidget->fontMetrics().horizontalAdvance(' ');
ui->treeWidget->setColumnWidth(ColField, 4 + charWidth * 35);
ui->treeWidget->setColumnWidth(ColOffset, 6 + charWidth * 7);
ui->treeWidget->setColumnWidth(ColAddress, 6 + charWidth * 16);
ui->treeWidget->setColumnWidth(ColAddress, 6 + charWidth * 8);
ui->treeWidget->setColumnWidth(ColSize, 4 + charWidth * 6);
// NOTE: Trick to display the expander icons in the second column
@ -199,10 +211,6 @@ void StructWidget::setupColumns()
// ui->treeWidget->header()->moveSection(ColField, ColOffset);
}
#define hasSelection !!ui->treeWidget->selectedItems().count()
#define selectedItem ui->treeWidget->selectedItems()[0]
#define selectedType selectedItem->data(0, Qt::UserRole).value<TypeDescriptor>().type
void StructWidget::setupContextMenu()
{
auto makeAction = [this](const QIcon & icon, const QString & text, const char* slot)

View File

@ -31,6 +31,9 @@ public slots:
void typeUpdateWidget();
void dbgStateChangedSlot(DBGSTATE state);
signals:
void selectionUpdated(duint address, duint size);
private:
Ui::StructWidget* ui;
MenuBuilder* mMenuBuilder;