mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 03:16:10 +00:00
PE-Bear like interface is supported in the Section Widget (#916)
* basic layout prototyping done * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * Initial commit for the current seek point indicator * WIP * A bit of refactoring * Indicator moves along with the ratio of the address in the section * Done with this feature for now. Need to fix redrawing the graph issue * Prevent the duplicated drawings of the items on the graphics scene * Quite a bit of refactoring * Refactoring done. * Add Header * Added a bit more features and also some refactoring * Everything should be done now for the comments * Indicator should move along with the seeks
This commit is contained in:
parent
5a62bd6dc7
commit
54ea5f014e
@ -1,9 +1,14 @@
|
|||||||
#include "SectionsWidget.h"
|
#include <QGraphicsTextItem>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
#include "SectionsWidget.h"
|
||||||
#include "CutterTreeView.h"
|
#include "CutterTreeView.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "QuickFilterView.h"
|
#include "QuickFilterView.h"
|
||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
|
#include "common/Configuration.h"
|
||||||
|
|
||||||
SectionsModel::SectionsModel(QList<SectionDescription> *sections, QObject *parent)
|
SectionsModel::SectionsModel(QList<SectionDescription> *sections, QObject *parent)
|
||||||
: QAbstractListModel(parent),
|
: QAbstractListModel(parent),
|
||||||
@ -48,11 +53,11 @@ QVariant SectionsModel::data(const QModelIndex &index, int role) const
|
|||||||
case SectionsModel::NameColumn:
|
case SectionsModel::NameColumn:
|
||||||
return section.name;
|
return section.name;
|
||||||
case SectionsModel::SizeColumn:
|
case SectionsModel::SizeColumn:
|
||||||
return section.size;
|
return section.vsize;
|
||||||
case SectionsModel::AddressColumn:
|
case SectionsModel::AddressColumn:
|
||||||
return RAddressString(section.vaddr);
|
return RAddressString(section.vaddr);
|
||||||
case SectionsModel::EndAddressColumn:
|
case SectionsModel::EndAddressColumn:
|
||||||
return RAddressString(section.vaddr + section.size);
|
return RAddressString(section.vaddr + section.vsize);
|
||||||
case SectionsModel::EntropyColumn:
|
case SectionsModel::EntropyColumn:
|
||||||
return section.entropy;
|
return section.entropy;
|
||||||
default:
|
default:
|
||||||
@ -77,7 +82,7 @@ QVariant SectionsModel::headerData(int section, Qt::Orientation, int role) const
|
|||||||
case SectionsModel::NameColumn:
|
case SectionsModel::NameColumn:
|
||||||
return tr("Name");
|
return tr("Name");
|
||||||
case SectionsModel::SizeColumn:
|
case SectionsModel::SizeColumn:
|
||||||
return tr("Size");
|
return tr("Virtual Size");
|
||||||
case SectionsModel::AddressColumn:
|
case SectionsModel::AddressColumn:
|
||||||
return tr("Address");
|
return tr("Address");
|
||||||
case SectionsModel::EndAddressColumn:
|
case SectionsModel::EndAddressColumn:
|
||||||
@ -109,10 +114,13 @@ bool SectionsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &ri
|
|||||||
case SectionsModel::NameColumn:
|
case SectionsModel::NameColumn:
|
||||||
return leftSection.name < rightSection.name;
|
return leftSection.name < rightSection.name;
|
||||||
case SectionsModel::SizeColumn:
|
case SectionsModel::SizeColumn:
|
||||||
return leftSection.size < rightSection.size;
|
return leftSection.vsize < rightSection.vsize;
|
||||||
case SectionsModel::AddressColumn:
|
case SectionsModel::AddressColumn:
|
||||||
case SectionsModel::EndAddressColumn:
|
case SectionsModel::EndAddressColumn:
|
||||||
return leftSection.vaddr < rightSection.vaddr;
|
if (leftSection.vaddr != rightSection.vaddr) {
|
||||||
|
return leftSection.vaddr < rightSection.vaddr;
|
||||||
|
}
|
||||||
|
return leftSection.vsize < rightSection.vsize;
|
||||||
case SectionsModel::EntropyColumn:
|
case SectionsModel::EntropyColumn:
|
||||||
return leftSection.entropy < rightSection.entropy;
|
return leftSection.entropy < rightSection.entropy;
|
||||||
|
|
||||||
@ -163,13 +171,35 @@ SectionsWidget::SectionsWidget(MainWindow *main, QAction *action) :
|
|||||||
connect(quickFilterView, SIGNAL(filterTextChanged(const QString &)), proxyModel,
|
connect(quickFilterView, SIGNAL(filterTextChanged(const QString &)), proxyModel,
|
||||||
SLOT(setFilterWildcard(const QString &)));
|
SLOT(setFilterWildcard(const QString &)));
|
||||||
connect(quickFilterView, SIGNAL(filterClosed()), sectionsTable, SLOT(setFocus()));
|
connect(quickFilterView, SIGNAL(filterClosed()), sectionsTable, SLOT(setFocus()));
|
||||||
|
|
||||||
dockWidgetContents = new QWidget(this);
|
dockWidgetContents = new QWidget(this);
|
||||||
QVBoxLayout *layout = new QVBoxLayout();
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
layout->addWidget(sectionsTable);
|
layout->addWidget(sectionsTable);
|
||||||
layout->addWidget(quickFilterView);
|
layout->addWidget(quickFilterView);
|
||||||
|
rawAddrDock = new SectionAddrDock(sectionsModel, SectionAddrDock::Raw, this);
|
||||||
|
virtualAddrDock = new SectionAddrDock(sectionsModel, SectionAddrDock::Virtual, this);
|
||||||
|
|
||||||
|
QWidget *addrDockWidget = new QWidget();
|
||||||
|
QHBoxLayout *addrDockLayout = new QHBoxLayout();
|
||||||
|
addrDockLayout->addWidget(rawAddrDock);
|
||||||
|
addrDockLayout->addWidget(virtualAddrDock);
|
||||||
|
addrDockWidget->setLayout(addrDockLayout);
|
||||||
|
layout->addWidget(addrDockWidget);
|
||||||
|
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
dockWidgetContents->setLayout(layout);
|
dockWidgetContents->setLayout(layout);
|
||||||
setWidget(dockWidgetContents);
|
setWidget(dockWidgetContents);
|
||||||
|
|
||||||
|
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
|
||||||
|
if (visibility) {
|
||||||
|
refreshSections();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(onSectionsSeekChanged(RVA)));
|
||||||
|
|
||||||
|
indicatorWidth = 600;
|
||||||
|
indicatorHeight = 5;
|
||||||
|
indicatorParamPosY = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionsWidget::~SectionsWidget() {}
|
SectionsWidget::~SectionsWidget() {}
|
||||||
@ -181,6 +211,11 @@ void SectionsWidget::refreshSections()
|
|||||||
sectionsModel->endResetModel();
|
sectionsModel->endResetModel();
|
||||||
|
|
||||||
qhelpers::adjustColumns(sectionsTable, SectionsModel::ColumnCount, 0);
|
qhelpers::adjustColumns(sectionsTable, SectionsModel::ColumnCount, 0);
|
||||||
|
rawAddrDock->show();
|
||||||
|
virtualAddrDock->show();
|
||||||
|
rawAddrDock->updateDock();
|
||||||
|
virtualAddrDock->updateDock();
|
||||||
|
drawIndicatorOnAddrDocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SectionsWidget::onSectionsDoubleClicked(const QModelIndex &index)
|
void SectionsWidget::onSectionsDoubleClicked(const QModelIndex &index)
|
||||||
@ -191,3 +226,141 @@ void SectionsWidget::onSectionsDoubleClicked(const QModelIndex &index)
|
|||||||
auto section = index.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
auto section = index.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
||||||
Core()->seek(section.vaddr);
|
Core()->seek(section.vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SectionsWidget::onSectionsSeekChanged(RVA addr)
|
||||||
|
{
|
||||||
|
Q_UNUSED(addr);
|
||||||
|
rawAddrDock->updateDock();
|
||||||
|
virtualAddrDock->updateDock();
|
||||||
|
drawIndicatorOnAddrDocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SectionsWidget::drawIndicatorOnAddrDocks()
|
||||||
|
{
|
||||||
|
RVA offset = Core()->getOffset();
|
||||||
|
for (int i = 0; i != virtualAddrDock->proxyModel->rowCount(); i++) {
|
||||||
|
QModelIndex idx = virtualAddrDock->proxyModel->index(i, 0);
|
||||||
|
RVA vaddr = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().vaddr;
|
||||||
|
int vsize = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().vsize;
|
||||||
|
RVA end = vaddr + vsize;
|
||||||
|
if (offset < end) {
|
||||||
|
QString name = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().name;
|
||||||
|
float ratio = 0;
|
||||||
|
if (vsize > 0 && offset > vaddr) {
|
||||||
|
ratio = (float)(offset - vaddr) / (float)vsize;
|
||||||
|
}
|
||||||
|
updateIndicator(rawAddrDock, name, ratio);
|
||||||
|
updateIndicator(virtualAddrDock, name, ratio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SectionsWidget::updateIndicator(SectionAddrDock *targetDock, QString name, float ratio)
|
||||||
|
{
|
||||||
|
RVA offset = Core()->getOffset();
|
||||||
|
float padding = targetDock->nameHeightMap[name] * ratio;
|
||||||
|
int y = targetDock->namePosYMap[name] + (int)padding;
|
||||||
|
QColor color = targetDock->indicatorColor;
|
||||||
|
QGraphicsRectItem *indicator = new QGraphicsRectItem(QRectF(0, y, indicatorWidth, indicatorHeight));
|
||||||
|
indicator->setBrush(QBrush(color));
|
||||||
|
targetDock->graphicsScene->addItem(indicator);
|
||||||
|
|
||||||
|
targetDock->addTextItem(color, QPoint(targetDock->rectOffset + targetDock->rectWidth, y - indicatorParamPosY), name);
|
||||||
|
targetDock->addTextItem(color, QPoint(0, y - indicatorParamPosY), QString("0x%1").arg(offset, 0, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
SectionAddrDock::SectionAddrDock(SectionsModel *model, AddrType type, QWidget *parent) :
|
||||||
|
QDockWidget(parent),
|
||||||
|
header(new QLabel),
|
||||||
|
graphicsScene(new QGraphicsScene),
|
||||||
|
graphicsView(new QGraphicsView)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case SectionAddrDock::Raw:
|
||||||
|
header->setText(tr("Raw"));
|
||||||
|
break;
|
||||||
|
case SectionAddrDock::Virtual:
|
||||||
|
header->setText(tr("Virtual"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphicsView->setScene(graphicsScene);
|
||||||
|
setWidget(graphicsView);
|
||||||
|
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||||
|
proxyModel = new SectionsProxyModel(model, this);
|
||||||
|
addrType = type;
|
||||||
|
|
||||||
|
QWidget *w = new QWidget();
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(header);
|
||||||
|
layout->addWidget(graphicsView);
|
||||||
|
w->setLayout(layout);
|
||||||
|
setWidget(w);
|
||||||
|
|
||||||
|
heightThreshold = 30;
|
||||||
|
rectOffset = 100;
|
||||||
|
rectWidth = 400;
|
||||||
|
indicatorColor = ConfigColor("gui.navbar.err");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SectionAddrDock::updateDock()
|
||||||
|
{
|
||||||
|
setFeatures(QDockWidget::DockWidgetClosable);
|
||||||
|
|
||||||
|
graphicsScene->clear();
|
||||||
|
|
||||||
|
header->setStyleSheet(QString("color:%1;").arg(ConfigColor("gui.dataoffset").name()));
|
||||||
|
const QBrush bg = QBrush(ConfigColor("gui.background"));
|
||||||
|
graphicsScene->setBackgroundBrush(bg);
|
||||||
|
|
||||||
|
int y = 0;
|
||||||
|
proxyModel->sort(2, Qt::AscendingOrder);
|
||||||
|
for (int i = 0; i < proxyModel->rowCount(); i++) {
|
||||||
|
QModelIndex idx = proxyModel->index(i, 0);
|
||||||
|
RVA addr;
|
||||||
|
int size;
|
||||||
|
switch (addrType) {
|
||||||
|
case SectionAddrDock::Raw:
|
||||||
|
addr = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().paddr;
|
||||||
|
size = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().size;
|
||||||
|
break;
|
||||||
|
case SectionAddrDock::Virtual:
|
||||||
|
addr = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().vaddr;
|
||||||
|
size = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().vsize;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString name = idx.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>().name;
|
||||||
|
if (size < heightThreshold) {
|
||||||
|
size = heightThreshold;
|
||||||
|
} else {
|
||||||
|
size /= heightThreshold;
|
||||||
|
size = std::max(size, heightThreshold);
|
||||||
|
}
|
||||||
|
QGraphicsRectItem *rect = new QGraphicsRectItem(rectOffset, y, rectWidth, size);
|
||||||
|
rect->setBrush(QBrush(idx.data(Qt::DecorationRole).value<QColor>()));
|
||||||
|
graphicsScene->addItem(rect);
|
||||||
|
|
||||||
|
addTextItem(ConfigColor("gui.dataoffset"), QPoint(0, y), QString("0x%1").arg(addr, 0, 16));
|
||||||
|
addTextItem(ConfigColor("gui.dataoffset"), QPoint(rectOffset, y), QString::number(size));
|
||||||
|
addTextItem(ConfigColor("gui.dataoffset"), QPoint(rectOffset + rectWidth, y), name);
|
||||||
|
|
||||||
|
namePosYMap[name] = y;
|
||||||
|
nameHeightMap[name] = size;
|
||||||
|
|
||||||
|
y += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SectionAddrDock::addTextItem(QColor color, QPoint pos, QString string)
|
||||||
|
{
|
||||||
|
QGraphicsTextItem *text = new QGraphicsTextItem;
|
||||||
|
text->setDefaultTextColor(color);
|
||||||
|
text->setPos(pos);
|
||||||
|
text->setPlainText(string);
|
||||||
|
graphicsScene->addItem(text);
|
||||||
|
}
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
#define SECTIONSWIDGET_H
|
#define SECTIONSWIDGET_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
#include "Cutter.h"
|
#include "Cutter.h"
|
||||||
#include "CutterDockWidget.h"
|
#include "CutterDockWidget.h"
|
||||||
@ -13,7 +17,10 @@ class CutterTreeView;
|
|||||||
class QAbstractItemView;
|
class QAbstractItemView;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class SectionsWidget;
|
class SectionsWidget;
|
||||||
|
class SectionAddrDock;
|
||||||
class QuickFilterView;
|
class QuickFilterView;
|
||||||
|
class QGraphicsView;
|
||||||
|
class QGraphicsRectItem;
|
||||||
|
|
||||||
class SectionsModel : public QAbstractListModel
|
class SectionsModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
@ -59,14 +66,51 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void refreshSections();
|
void refreshSections();
|
||||||
void onSectionsDoubleClicked(const QModelIndex &index);
|
void onSectionsDoubleClicked(const QModelIndex &index);
|
||||||
|
void onSectionsSeekChanged(RVA addr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<SectionDescription> sections;
|
QList<SectionDescription> sections;
|
||||||
SectionsModel *sectionsModel;
|
SectionsModel *sectionsModel;
|
||||||
|
SectionsProxyModel *proxyModel;
|
||||||
CutterTreeView *sectionsTable;
|
CutterTreeView *sectionsTable;
|
||||||
MainWindow *main;
|
MainWindow *main;
|
||||||
QWidget *dockWidgetContents;
|
QWidget *dockWidgetContents;
|
||||||
QuickFilterView *quickFilterView;
|
QuickFilterView *quickFilterView;
|
||||||
|
|
||||||
|
SectionAddrDock *rawAddrDock;
|
||||||
|
SectionAddrDock *virtualAddrDock;
|
||||||
|
|
||||||
|
int indicatorWidth;
|
||||||
|
int indicatorHeight;
|
||||||
|
int indicatorParamPosY;
|
||||||
|
void drawIndicatorOnAddrDocks();
|
||||||
|
void updateIndicator(SectionAddrDock *targetDock, QString name, float ratio);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SectionAddrDock : public QDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum AddrType { Raw = 0, Virtual };
|
||||||
|
int heightThreshold;
|
||||||
|
int rectOffset;
|
||||||
|
int rectWidth;
|
||||||
|
QColor indicatorColor;
|
||||||
|
explicit SectionAddrDock(SectionsModel *model, AddrType type, QWidget *parent = nullptr);
|
||||||
|
QLabel *header;
|
||||||
|
QGraphicsScene *graphicsScene;
|
||||||
|
SectionsProxyModel *proxyModel;
|
||||||
|
AddrType addrType;
|
||||||
|
QHash<QString, int> namePosYMap;
|
||||||
|
QHash<QString, int> nameHeightMap;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void updateDock();
|
||||||
|
void addTextItem(QColor color, QPoint pos, QString string);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QGraphicsView *graphicsView;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SECTIONSWIDGET_H
|
#endif // SECTIONSWIDGET_H
|
||||||
|
Loading…
Reference in New Issue
Block a user