mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-24 22:05:25 +00:00
Segments implemented (#851)
* Segments implemented * Not util anymore but common * Fixed the strings to be shown as the headers better * Quick Filter functionality is supported on both Section and Segment Widget * QuickFilter should basically be on but for some widgets, they should be off
This commit is contained in:
parent
d3572b9eb5
commit
ac64bbface
@ -1652,6 +1652,33 @@ QList<SectionDescription> CutterCore::getAllSections()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<SegmentDescription> CutterCore::getAllSegments()
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
QList<SegmentDescription> ret;
|
||||||
|
|
||||||
|
QJsonArray segments = cmdj("iSSj").array();
|
||||||
|
|
||||||
|
for (QJsonValue value : segments) {
|
||||||
|
QJsonObject segmentObject = value.toObject();
|
||||||
|
|
||||||
|
QString name = segmentObject["name"].toString();
|
||||||
|
if (name.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SegmentDescription segment;
|
||||||
|
segment.name = name;
|
||||||
|
segment.vaddr = segmentObject["vaddr"].toVariant().toULongLong();
|
||||||
|
segment.paddr = segmentObject["paddr"].toVariant().toULongLong();
|
||||||
|
segment.size = segmentObject["size"].toVariant().toULongLong();
|
||||||
|
segment.vsize = segmentObject["vsize"].toVariant().toULongLong();
|
||||||
|
segment.perm = segmentObject["perm"].toString();
|
||||||
|
|
||||||
|
ret << segment;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
QList<EntrypointDescription> CutterCore::getAllEntrypoint()
|
QList<EntrypointDescription> CutterCore::getAllEntrypoint()
|
||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
|
11
src/Cutter.h
11
src/Cutter.h
@ -189,6 +189,15 @@ struct SectionDescription {
|
|||||||
QString entropy;
|
QString entropy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SegmentDescription {
|
||||||
|
RVA vaddr;
|
||||||
|
RVA paddr;
|
||||||
|
RVA size;
|
||||||
|
RVA vsize;
|
||||||
|
QString name;
|
||||||
|
QString perm;
|
||||||
|
};
|
||||||
|
|
||||||
struct EntrypointDescription {
|
struct EntrypointDescription {
|
||||||
RVA vaddr;
|
RVA vaddr;
|
||||||
RVA paddr;
|
RVA paddr;
|
||||||
@ -350,6 +359,7 @@ Q_DECLARE_METATYPE(HeaderDescription)
|
|||||||
Q_DECLARE_METATYPE(ZignatureDescription)
|
Q_DECLARE_METATYPE(ZignatureDescription)
|
||||||
Q_DECLARE_METATYPE(SearchDescription)
|
Q_DECLARE_METATYPE(SearchDescription)
|
||||||
Q_DECLARE_METATYPE(SectionDescription)
|
Q_DECLARE_METATYPE(SectionDescription)
|
||||||
|
Q_DECLARE_METATYPE(SegmentDescription)
|
||||||
Q_DECLARE_METATYPE(MemoryMapDescription)
|
Q_DECLARE_METATYPE(MemoryMapDescription)
|
||||||
Q_DECLARE_METATYPE(BreakpointDescription)
|
Q_DECLARE_METATYPE(BreakpointDescription)
|
||||||
Q_DECLARE_METATYPE(ProcessDescription)
|
Q_DECLARE_METATYPE(ProcessDescription)
|
||||||
@ -569,6 +579,7 @@ public:
|
|||||||
QList<FlagspaceDescription> getAllFlagspaces();
|
QList<FlagspaceDescription> getAllFlagspaces();
|
||||||
QList<FlagDescription> getAllFlags(QString flagspace = NULL);
|
QList<FlagDescription> getAllFlags(QString flagspace = NULL);
|
||||||
QList<SectionDescription> getAllSections();
|
QList<SectionDescription> getAllSections();
|
||||||
|
QList<SegmentDescription> getAllSegments();
|
||||||
QList<EntrypointDescription> getAllEntrypoint();
|
QList<EntrypointDescription> getAllEntrypoint();
|
||||||
QList<ClassDescription> getAllClassesFromBin();
|
QList<ClassDescription> getAllClassesFromBin();
|
||||||
QList<ClassDescription> getAllClassesFromFlags();
|
QList<ClassDescription> getAllClassesFromFlags();
|
||||||
|
@ -138,6 +138,7 @@ SOURCES += \
|
|||||||
widgets/RelocsWidget.cpp \
|
widgets/RelocsWidget.cpp \
|
||||||
widgets/SdbDock.cpp \
|
widgets/SdbDock.cpp \
|
||||||
widgets/SectionsWidget.cpp \
|
widgets/SectionsWidget.cpp \
|
||||||
|
widgets/SegmentsWidget.cpp \
|
||||||
widgets/Sidebar.cpp \
|
widgets/Sidebar.cpp \
|
||||||
widgets/StringsWidget.cpp \
|
widgets/StringsWidget.cpp \
|
||||||
widgets/SymbolsWidget.cpp \
|
widgets/SymbolsWidget.cpp \
|
||||||
@ -233,6 +234,7 @@ HEADERS += \
|
|||||||
widgets/RelocsWidget.h \
|
widgets/RelocsWidget.h \
|
||||||
widgets/SdbDock.h \
|
widgets/SdbDock.h \
|
||||||
widgets/SectionsWidget.h \
|
widgets/SectionsWidget.h \
|
||||||
|
widgets/SegmentsWidget.h \
|
||||||
widgets/Sidebar.h \
|
widgets/Sidebar.h \
|
||||||
widgets/StringsWidget.h \
|
widgets/StringsWidget.h \
|
||||||
widgets/SymbolsWidget.h \
|
widgets/SymbolsWidget.h \
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#include "widgets/GraphWidget.h"
|
#include "widgets/GraphWidget.h"
|
||||||
#include "widgets/FunctionsWidget.h"
|
#include "widgets/FunctionsWidget.h"
|
||||||
#include "widgets/SectionsWidget.h"
|
#include "widgets/SectionsWidget.h"
|
||||||
|
#include "widgets/SegmentsWidget.h"
|
||||||
#include "widgets/CommentsWidget.h"
|
#include "widgets/CommentsWidget.h"
|
||||||
#include "widgets/ImportsWidget.h"
|
#include "widgets/ImportsWidget.h"
|
||||||
#include "widgets/ExportsWidget.h"
|
#include "widgets/ExportsWidget.h"
|
||||||
@ -201,6 +202,7 @@ void MainWindow::initUI()
|
|||||||
graphDock = new GraphWidget(this, ui->actionGraph);
|
graphDock = new GraphWidget(this, ui->actionGraph);
|
||||||
|
|
||||||
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
||||||
|
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
||||||
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
||||||
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
|
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
|
||||||
importsDock = new ImportsWidget(this, ui->actionImports);
|
importsDock = new ImportsWidget(this, ui->actionImports);
|
||||||
@ -573,9 +575,11 @@ void MainWindow::restoreDocks()
|
|||||||
|
|
||||||
// Console | Sections
|
// Console | Sections
|
||||||
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
|
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
|
||||||
|
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
|
||||||
|
|
||||||
// Tabs for center (must be applied after splitDockWidget())
|
// Tabs for center (must be applied after splitDockWidget())
|
||||||
tabifyDockWidget(sectionsDock, commentsDock);
|
tabifyDockWidget(sectionsDock, commentsDock);
|
||||||
|
tabifyDockWidget(segmentsDock, commentsDock);
|
||||||
tabifyDockWidget(dashboardDock, disassemblyDock);
|
tabifyDockWidget(dashboardDock, disassemblyDock);
|
||||||
tabifyDockWidget(dashboardDock, graphDock);
|
tabifyDockWidget(dashboardDock, graphDock);
|
||||||
tabifyDockWidget(dashboardDock, hexdumpDock);
|
tabifyDockWidget(dashboardDock, hexdumpDock);
|
||||||
|
@ -38,6 +38,7 @@ class QLineEdit;
|
|||||||
class SdbDock;
|
class SdbDock;
|
||||||
class QAction;
|
class QAction;
|
||||||
class SectionsWidget;
|
class SectionsWidget;
|
||||||
|
class SegmentsWidget;
|
||||||
class ConsoleWidget;
|
class ConsoleWidget;
|
||||||
class EntrypointWidget;
|
class EntrypointWidget;
|
||||||
class DisassemblerGraphView;
|
class DisassemblerGraphView;
|
||||||
@ -215,6 +216,7 @@ private:
|
|||||||
QLineEdit *gotoEntry = nullptr;
|
QLineEdit *gotoEntry = nullptr;
|
||||||
SdbDock *sdbDock = nullptr;
|
SdbDock *sdbDock = nullptr;
|
||||||
SectionsWidget *sectionsDock = nullptr;
|
SectionsWidget *sectionsDock = nullptr;
|
||||||
|
SegmentsWidget *segmentsDock = nullptr;
|
||||||
ZignaturesWidget *zignaturesDock = nullptr;
|
ZignaturesWidget *zignaturesDock = nullptr;
|
||||||
ConsoleWidget *consoleDock = nullptr;
|
ConsoleWidget *consoleDock = nullptr;
|
||||||
ClassesWidget *classesDock = nullptr;
|
ClassesWidget *classesDock = nullptr;
|
||||||
|
@ -173,6 +173,7 @@ QToolTip {
|
|||||||
<addaction name="actionTypes"/>
|
<addaction name="actionTypes"/>
|
||||||
<addaction name="actionFlags"/>
|
<addaction name="actionFlags"/>
|
||||||
<addaction name="actionSections"/>
|
<addaction name="actionSections"/>
|
||||||
|
<addaction name="actionSegments"/>
|
||||||
<addaction name="actionHeaders"/>
|
<addaction name="actionHeaders"/>
|
||||||
<addaction name="actionZignatures"/>
|
<addaction name="actionZignatures"/>
|
||||||
<addaction name="actionRelocs"/>
|
<addaction name="actionRelocs"/>
|
||||||
@ -452,6 +453,17 @@ QToolTip {
|
|||||||
<string>Show/Hide Sections panel</string>
|
<string>Show/Hide Sections panel</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionSegments">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Segments</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Show/Hide Segments panel</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionFunctions">
|
<action name="actionFunctions">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "QuickFilterView.h"
|
#include "QuickFilterView.h"
|
||||||
#include "ui_QuickFilterView.h"
|
#include "ui_QuickFilterView.h"
|
||||||
|
|
||||||
QuickFilterView::QuickFilterView(QWidget *parent) :
|
QuickFilterView::QuickFilterView(QWidget *parent, bool defaultOn) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::QuickFilterView())
|
ui(new Ui::QuickFilterView())
|
||||||
{
|
{
|
||||||
@ -13,6 +13,10 @@ QuickFilterView::QuickFilterView(QWidget *parent) :
|
|||||||
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, [this](const QString & text) {
|
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, [this](const QString & text) {
|
||||||
emit filterTextChanged(text);
|
emit filterTextChanged(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!defaultOn) {
|
||||||
|
closeFilter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuickFilterView::~QuickFilterView() {}
|
QuickFilterView::~QuickFilterView() {}
|
||||||
|
@ -15,7 +15,7 @@ class QuickFilterView : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QuickFilterView(QWidget *parent = nullptr);
|
explicit QuickFilterView(QWidget *parent = nullptr, bool defaultOn = true);
|
||||||
~QuickFilterView();
|
~QuickFilterView();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "SectionsWidget.h"
|
#include "SectionsWidget.h"
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "QuickFilterView.h"
|
||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
|
|
||||||
SectionsModel::SectionsModel(QList<SectionDescription> *sections, QObject *parent)
|
SectionsModel::SectionsModel(QList<SectionDescription> *sections, QObject *parent)
|
||||||
@ -81,7 +82,7 @@ QVariant SectionsModel::headerData(int section, Qt::Orientation, int role) const
|
|||||||
case SectionsModel::AddressColumn:
|
case SectionsModel::AddressColumn:
|
||||||
return tr("Address");
|
return tr("Address");
|
||||||
case SectionsModel::EndAddressColumn:
|
case SectionsModel::EndAddressColumn:
|
||||||
return tr("EndAddress");
|
return tr("End Address");
|
||||||
case SectionsModel::EntropyColumn:
|
case SectionsModel::EntropyColumn:
|
||||||
return tr("Entropy");
|
return tr("Entropy");
|
||||||
default:
|
default:
|
||||||
@ -135,19 +136,41 @@ SectionsWidget::SectionsWidget(MainWindow *main, QAction *action) :
|
|||||||
auto proxyModel = new SectionsProxyModel(sectionsModel, this);
|
auto proxyModel = new SectionsProxyModel(sectionsModel, this);
|
||||||
|
|
||||||
sectionsTable->setModel(proxyModel);
|
sectionsTable->setModel(proxyModel);
|
||||||
|
|
||||||
sectionsTable->setIndentation(10);
|
sectionsTable->setIndentation(10);
|
||||||
sectionsTable->setSortingEnabled(true);
|
sectionsTable->setSortingEnabled(true);
|
||||||
sectionsTable->sortByColumn(SectionsModel::NameColumn, Qt::AscendingOrder);
|
sectionsTable->sortByColumn(SectionsModel::NameColumn, Qt::AscendingOrder);
|
||||||
|
|
||||||
connect(sectionsTable, SIGNAL(doubleClicked(const QModelIndex &)),
|
connect(sectionsTable, SIGNAL(doubleClicked(const QModelIndex &)),
|
||||||
this, SLOT(onSectionsDoubleClicked(const QModelIndex &)));
|
this, SLOT(onSectionsDoubleClicked(const QModelIndex &)));
|
||||||
|
|
||||||
setWidget(sectionsTable);
|
|
||||||
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
|
||||||
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshSections()));
|
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshSections()));
|
||||||
|
quickFilterView = new QuickFilterView(this, false);
|
||||||
|
quickFilterView->setObjectName(QStringLiteral("quickFilterView"));
|
||||||
|
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||||
|
sizePolicy1.setHorizontalStretch(0);
|
||||||
|
sizePolicy1.setVerticalStretch(0);
|
||||||
|
sizePolicy1.setHeightForWidth(quickFilterView->sizePolicy().hasHeightForWidth());
|
||||||
|
quickFilterView->setSizePolicy(sizePolicy1);
|
||||||
|
|
||||||
|
QShortcut *search_shortcut = new QShortcut(QKeySequence::Find, this);
|
||||||
|
connect(search_shortcut, &QShortcut::activated, quickFilterView, &QuickFilterView::showFilter);
|
||||||
|
search_shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
|
||||||
|
QShortcut *clear_shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
|
connect(clear_shortcut, &QShortcut::activated, quickFilterView, &QuickFilterView::clearFilter);
|
||||||
|
clear_shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
|
||||||
|
connect(quickFilterView, SIGNAL(filterTextChanged(const QString &)), proxyModel,
|
||||||
|
SLOT(setFilterWildcard(const QString &)));
|
||||||
|
connect(quickFilterView, SIGNAL(filterClosed()), sectionsTable, SLOT(setFocus()));
|
||||||
|
dockWidgetContents = new QWidget(this);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(sectionsTable);
|
||||||
|
layout->addWidget(quickFilterView);
|
||||||
|
layout->setMargin(0);
|
||||||
|
dockWidgetContents->setLayout(layout);
|
||||||
|
setWidget(dockWidgetContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionsWidget::~SectionsWidget() {}
|
SectionsWidget::~SectionsWidget() {}
|
||||||
|
@ -13,6 +13,7 @@ class QTreeView;
|
|||||||
class QAbstractItemView;
|
class QAbstractItemView;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class SectionsWidget;
|
class SectionsWidget;
|
||||||
|
class QuickFilterView;
|
||||||
|
|
||||||
class SectionsModel : public QAbstractListModel
|
class SectionsModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
@ -64,6 +65,8 @@ private:
|
|||||||
SectionsModel *sectionsModel;
|
SectionsModel *sectionsModel;
|
||||||
QTreeView *sectionsTable;
|
QTreeView *sectionsTable;
|
||||||
MainWindow *main;
|
MainWindow *main;
|
||||||
|
QWidget *dockWidgetContents;
|
||||||
|
QuickFilterView *quickFilterView;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SECTIONSWIDGET_H
|
#endif // SECTIONSWIDGET_H
|
||||||
|
191
src/widgets/SegmentsWidget.cpp
Normal file
191
src/widgets/SegmentsWidget.cpp
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
#include "SegmentsWidget.h"
|
||||||
|
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "QuickFilterView.h"
|
||||||
|
#include "common/Helpers.h"
|
||||||
|
|
||||||
|
SegmentsModel::SegmentsModel(QList<SegmentDescription> *segments, QObject *parent)
|
||||||
|
: QAbstractListModel(parent),
|
||||||
|
segments(segments)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SegmentsModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return segments->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SegmentsModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return SegmentsModel::ColumnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SegmentsModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
// TODO: create unique colors, e. g. use HSV color space and rotate in H for 360/size
|
||||||
|
static const QList<QColor> colors = { QColor("#1ABC9C"), //TURQUOISE
|
||||||
|
QColor("#2ECC71"), //EMERALD
|
||||||
|
QColor("#3498DB"), //PETER RIVER
|
||||||
|
QColor("#9B59B6"), //AMETHYST
|
||||||
|
QColor("#34495E"), //WET ASPHALT
|
||||||
|
QColor("#F1C40F"), //SUN FLOWER
|
||||||
|
QColor("#E67E22"), //CARROT
|
||||||
|
QColor("#E74C3C"), //ALIZARIN
|
||||||
|
QColor("#ECF0F1"), //CLOUDS
|
||||||
|
QColor("#BDC3C7"), //SILVER
|
||||||
|
QColor("#95A5A6") //COBCRETE
|
||||||
|
};
|
||||||
|
|
||||||
|
if (index.row() >= segments->count())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
const SegmentDescription &segment = segments->at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case SegmentsModel::NameColumn:
|
||||||
|
return segment.name;
|
||||||
|
case SegmentsModel::SizeColumn:
|
||||||
|
return segment.size;
|
||||||
|
case SegmentsModel::AddressColumn:
|
||||||
|
return RAddressString(segment.vaddr);
|
||||||
|
case SegmentsModel::EndAddressColumn:
|
||||||
|
return RAddressString(segment.vaddr + segment.size);
|
||||||
|
case SegmentsModel::PermColumn:
|
||||||
|
return segment.perm;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case Qt::DecorationRole:
|
||||||
|
if (index.column() == 0)
|
||||||
|
return colors[index.row() % colors.size()];
|
||||||
|
return QVariant();
|
||||||
|
case SegmentsModel::SegmentDescriptionRole:
|
||||||
|
return QVariant::fromValue(segment);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SegmentsModel::headerData(int segment, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (segment) {
|
||||||
|
case SegmentsModel::NameColumn:
|
||||||
|
return tr("Name");
|
||||||
|
case SegmentsModel::SizeColumn:
|
||||||
|
return tr("Size");
|
||||||
|
case SegmentsModel::AddressColumn:
|
||||||
|
return tr("Address");
|
||||||
|
case SegmentsModel::EndAddressColumn:
|
||||||
|
return tr("End Address");
|
||||||
|
case SegmentsModel::PermColumn:
|
||||||
|
return tr("Permissions");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentsProxyModel::SegmentsProxyModel(SegmentsModel *sourceModel, QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(sourceModel);
|
||||||
|
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
auto leftSegment = left.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
|
||||||
|
auto rightSegment = right.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
|
||||||
|
switch (left.column()) {
|
||||||
|
case SegmentsModel::NameColumn:
|
||||||
|
return leftSegment.name < rightSegment.name;
|
||||||
|
case SegmentsModel::SizeColumn:
|
||||||
|
return leftSegment.size < rightSegment.size;
|
||||||
|
case SegmentsModel::AddressColumn:
|
||||||
|
case SegmentsModel::EndAddressColumn:
|
||||||
|
return leftSegment.vaddr < rightSegment.vaddr;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentsWidget::SegmentsWidget(MainWindow *main, QAction *action) :
|
||||||
|
CutterDockWidget(main, action),
|
||||||
|
main(main)
|
||||||
|
{
|
||||||
|
|
||||||
|
setObjectName("SegmentsWidget");
|
||||||
|
setWindowTitle(QStringLiteral("Segments"));
|
||||||
|
|
||||||
|
segmentsTable = new QTreeView;
|
||||||
|
segmentsModel = new SegmentsModel(&segments, this);
|
||||||
|
auto proxyModel = new SegmentsProxyModel(segmentsModel, this);
|
||||||
|
|
||||||
|
segmentsTable->setModel(proxyModel);
|
||||||
|
segmentsTable->setIndentation(10);
|
||||||
|
segmentsTable->setSortingEnabled(true);
|
||||||
|
segmentsTable->sortByColumn(SegmentsModel::NameColumn, Qt::AscendingOrder);
|
||||||
|
|
||||||
|
connect(segmentsTable, SIGNAL(doubleClicked(const QModelIndex &)),
|
||||||
|
this, SLOT(onSegmentsDoubleClicked(const QModelIndex &)));
|
||||||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshSegments()));
|
||||||
|
|
||||||
|
quickFilterView = new QuickFilterView(this, false);
|
||||||
|
quickFilterView->setObjectName(QStringLiteral("quickFilterView"));
|
||||||
|
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||||
|
sizePolicy1.setHorizontalStretch(0);
|
||||||
|
sizePolicy1.setVerticalStretch(0);
|
||||||
|
sizePolicy1.setHeightForWidth(quickFilterView->sizePolicy().hasHeightForWidth());
|
||||||
|
quickFilterView->setSizePolicy(sizePolicy1);
|
||||||
|
|
||||||
|
QShortcut *search_shortcut = new QShortcut(QKeySequence::Find, this);
|
||||||
|
connect(search_shortcut, &QShortcut::activated, quickFilterView, &QuickFilterView::showFilter);
|
||||||
|
search_shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
|
||||||
|
QShortcut *clear_shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
|
connect(clear_shortcut, &QShortcut::activated, quickFilterView, &QuickFilterView::clearFilter);
|
||||||
|
clear_shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
|
||||||
|
connect(quickFilterView, SIGNAL(filterTextChanged(const QString &)), proxyModel,
|
||||||
|
SLOT(setFilterWildcard(const QString &)));
|
||||||
|
connect(quickFilterView, SIGNAL(filterClosed()), segmentsTable, SLOT(setFocus()));
|
||||||
|
|
||||||
|
dockWidgetContents = new QWidget(this);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(segmentsTable);
|
||||||
|
layout->addWidget(quickFilterView);
|
||||||
|
layout->setMargin(0);
|
||||||
|
dockWidgetContents->setLayout(layout);
|
||||||
|
setWidget(dockWidgetContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentsWidget::~SegmentsWidget() {}
|
||||||
|
|
||||||
|
void SegmentsWidget::refreshSegments()
|
||||||
|
{
|
||||||
|
segmentsModel->beginResetModel();
|
||||||
|
segments = Core()->getAllSegments();
|
||||||
|
segmentsModel->endResetModel();
|
||||||
|
|
||||||
|
qhelpers::adjustColumns(segmentsTable, SegmentsModel::ColumnCount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentsWidget::onSegmentsDoubleClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto segment = index.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
|
||||||
|
Core()->seek(segment.vaddr);
|
||||||
|
}
|
72
src/widgets/SegmentsWidget.h
Normal file
72
src/widgets/SegmentsWidget.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef SEGMENTSWIDGET_H
|
||||||
|
#define SEGMENTSWIDGET_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
|
||||||
|
class QTreeView;
|
||||||
|
class QAbstractItemView;
|
||||||
|
class MainWindow;
|
||||||
|
class SegmentsWidget;
|
||||||
|
class QuickFilterView;
|
||||||
|
|
||||||
|
class SegmentsModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend SegmentsWidget;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<SegmentDescription> *segments;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column { NameColumn = 0, SizeColumn, AddressColumn, EndAddressColumn, PermColumn, ColumnCount };
|
||||||
|
enum Role { SegmentDescriptionRole = Qt::UserRole };
|
||||||
|
|
||||||
|
SegmentsModel(QList<SegmentDescription> *segments, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
QVariant headerData(int segment, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SegmentsProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SegmentsProxyModel(SegmentsModel *sourceModel, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SegmentsWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SegmentsWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
|
~SegmentsWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void refreshSegments();
|
||||||
|
void onSegmentsDoubleClicked(const QModelIndex &index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<SegmentDescription> segments;
|
||||||
|
SegmentsModel *segmentsModel;
|
||||||
|
QTreeView *segmentsTable;
|
||||||
|
MainWindow *main;
|
||||||
|
QWidget *dockWidgetContents;
|
||||||
|
QuickFilterView *quickFilterView;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SEGMENTSWIDGET_H
|
Loading…
Reference in New Issue
Block a user