Minor usability improvements for hex_viewer
This commit is contained in:
parent
0d2259a311
commit
5a7cbc4a7b
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ MiniHexDump::MiniHexDump(Navigation* navigation, Architecture* architecture, QWi
|
|||
: HexDump(architecture, parent)
|
||||
, mNavigation(navigation)
|
||||
{
|
||||
mUnderliningEnabled = false;
|
||||
mPointerUnderliningEnabled = false;
|
||||
mSelectionUnderliningEnabled = true;
|
||||
hexAsciiSlot();
|
||||
setupMenu();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue