mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-24 05:45:27 +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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
CORE_LOCK();
|
||||
|
11
src/Cutter.h
11
src/Cutter.h
@ -189,6 +189,15 @@ struct SectionDescription {
|
||||
QString entropy;
|
||||
};
|
||||
|
||||
struct SegmentDescription {
|
||||
RVA vaddr;
|
||||
RVA paddr;
|
||||
RVA size;
|
||||
RVA vsize;
|
||||
QString name;
|
||||
QString perm;
|
||||
};
|
||||
|
||||
struct EntrypointDescription {
|
||||
RVA vaddr;
|
||||
RVA paddr;
|
||||
@ -350,6 +359,7 @@ Q_DECLARE_METATYPE(HeaderDescription)
|
||||
Q_DECLARE_METATYPE(ZignatureDescription)
|
||||
Q_DECLARE_METATYPE(SearchDescription)
|
||||
Q_DECLARE_METATYPE(SectionDescription)
|
||||
Q_DECLARE_METATYPE(SegmentDescription)
|
||||
Q_DECLARE_METATYPE(MemoryMapDescription)
|
||||
Q_DECLARE_METATYPE(BreakpointDescription)
|
||||
Q_DECLARE_METATYPE(ProcessDescription)
|
||||
@ -569,6 +579,7 @@ public:
|
||||
QList<FlagspaceDescription> getAllFlagspaces();
|
||||
QList<FlagDescription> getAllFlags(QString flagspace = NULL);
|
||||
QList<SectionDescription> getAllSections();
|
||||
QList<SegmentDescription> getAllSegments();
|
||||
QList<EntrypointDescription> getAllEntrypoint();
|
||||
QList<ClassDescription> getAllClassesFromBin();
|
||||
QList<ClassDescription> getAllClassesFromFlags();
|
||||
|
@ -138,6 +138,7 @@ SOURCES += \
|
||||
widgets/RelocsWidget.cpp \
|
||||
widgets/SdbDock.cpp \
|
||||
widgets/SectionsWidget.cpp \
|
||||
widgets/SegmentsWidget.cpp \
|
||||
widgets/Sidebar.cpp \
|
||||
widgets/StringsWidget.cpp \
|
||||
widgets/SymbolsWidget.cpp \
|
||||
@ -233,6 +234,7 @@ HEADERS += \
|
||||
widgets/RelocsWidget.h \
|
||||
widgets/SdbDock.h \
|
||||
widgets/SectionsWidget.h \
|
||||
widgets/SegmentsWidget.h \
|
||||
widgets/Sidebar.h \
|
||||
widgets/StringsWidget.h \
|
||||
widgets/SymbolsWidget.h \
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "widgets/GraphWidget.h"
|
||||
#include "widgets/FunctionsWidget.h"
|
||||
#include "widgets/SectionsWidget.h"
|
||||
#include "widgets/SegmentsWidget.h"
|
||||
#include "widgets/CommentsWidget.h"
|
||||
#include "widgets/ImportsWidget.h"
|
||||
#include "widgets/ExportsWidget.h"
|
||||
@ -201,6 +202,7 @@ void MainWindow::initUI()
|
||||
graphDock = new GraphWidget(this, ui->actionGraph);
|
||||
|
||||
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
||||
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
||||
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
||||
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
|
||||
importsDock = new ImportsWidget(this, ui->actionImports);
|
||||
@ -573,9 +575,11 @@ void MainWindow::restoreDocks()
|
||||
|
||||
// Console | Sections
|
||||
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
|
||||
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
|
||||
|
||||
// Tabs for center (must be applied after splitDockWidget())
|
||||
tabifyDockWidget(sectionsDock, commentsDock);
|
||||
tabifyDockWidget(segmentsDock, commentsDock);
|
||||
tabifyDockWidget(dashboardDock, disassemblyDock);
|
||||
tabifyDockWidget(dashboardDock, graphDock);
|
||||
tabifyDockWidget(dashboardDock, hexdumpDock);
|
||||
|
@ -38,6 +38,7 @@ class QLineEdit;
|
||||
class SdbDock;
|
||||
class QAction;
|
||||
class SectionsWidget;
|
||||
class SegmentsWidget;
|
||||
class ConsoleWidget;
|
||||
class EntrypointWidget;
|
||||
class DisassemblerGraphView;
|
||||
@ -215,6 +216,7 @@ private:
|
||||
QLineEdit *gotoEntry = nullptr;
|
||||
SdbDock *sdbDock = nullptr;
|
||||
SectionsWidget *sectionsDock = nullptr;
|
||||
SegmentsWidget *segmentsDock = nullptr;
|
||||
ZignaturesWidget *zignaturesDock = nullptr;
|
||||
ConsoleWidget *consoleDock = nullptr;
|
||||
ClassesWidget *classesDock = nullptr;
|
||||
|
@ -173,6 +173,7 @@ QToolTip {
|
||||
<addaction name="actionTypes"/>
|
||||
<addaction name="actionFlags"/>
|
||||
<addaction name="actionSections"/>
|
||||
<addaction name="actionSegments"/>
|
||||
<addaction name="actionHeaders"/>
|
||||
<addaction name="actionZignatures"/>
|
||||
<addaction name="actionRelocs"/>
|
||||
@ -452,6 +453,17 @@ QToolTip {
|
||||
<string>Show/Hide Sections panel</string>
|
||||
</property>
|
||||
</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">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "QuickFilterView.h"
|
||||
#include "ui_QuickFilterView.h"
|
||||
|
||||
QuickFilterView::QuickFilterView(QWidget *parent) :
|
||||
QuickFilterView::QuickFilterView(QWidget *parent, bool defaultOn) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::QuickFilterView())
|
||||
{
|
||||
@ -13,6 +13,10 @@ QuickFilterView::QuickFilterView(QWidget *parent) :
|
||||
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, [this](const QString & text) {
|
||||
emit filterTextChanged(text);
|
||||
});
|
||||
|
||||
if (!defaultOn) {
|
||||
closeFilter();
|
||||
}
|
||||
}
|
||||
|
||||
QuickFilterView::~QuickFilterView() {}
|
||||
|
@ -15,7 +15,7 @@ class QuickFilterView : public QWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QuickFilterView(QWidget *parent = nullptr);
|
||||
explicit QuickFilterView(QWidget *parent = nullptr, bool defaultOn = true);
|
||||
~QuickFilterView();
|
||||
|
||||
public slots:
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "SectionsWidget.h"
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "QuickFilterView.h"
|
||||
#include "common/Helpers.h"
|
||||
|
||||
SectionsModel::SectionsModel(QList<SectionDescription> *sections, QObject *parent)
|
||||
@ -81,7 +82,7 @@ QVariant SectionsModel::headerData(int section, Qt::Orientation, int role) const
|
||||
case SectionsModel::AddressColumn:
|
||||
return tr("Address");
|
||||
case SectionsModel::EndAddressColumn:
|
||||
return tr("EndAddress");
|
||||
return tr("End Address");
|
||||
case SectionsModel::EntropyColumn:
|
||||
return tr("Entropy");
|
||||
default:
|
||||
@ -135,19 +136,41 @@ SectionsWidget::SectionsWidget(MainWindow *main, QAction *action) :
|
||||
auto proxyModel = new SectionsProxyModel(sectionsModel, this);
|
||||
|
||||
sectionsTable->setModel(proxyModel);
|
||||
|
||||
sectionsTable->setIndentation(10);
|
||||
sectionsTable->setSortingEnabled(true);
|
||||
sectionsTable->sortByColumn(SectionsModel::NameColumn, Qt::AscendingOrder);
|
||||
|
||||
connect(sectionsTable, SIGNAL(doubleClicked(const QModelIndex &)),
|
||||
this, SLOT(onSectionsDoubleClicked(const QModelIndex &)));
|
||||
|
||||
setWidget(sectionsTable);
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
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() {}
|
||||
|
@ -13,6 +13,7 @@ class QTreeView;
|
||||
class QAbstractItemView;
|
||||
class MainWindow;
|
||||
class SectionsWidget;
|
||||
class QuickFilterView;
|
||||
|
||||
class SectionsModel : public QAbstractListModel
|
||||
{
|
||||
@ -64,6 +65,8 @@ private:
|
||||
SectionsModel *sectionsModel;
|
||||
QTreeView *sectionsTable;
|
||||
MainWindow *main;
|
||||
QWidget *dockWidgetContents;
|
||||
QuickFilterView *quickFilterView;
|
||||
};
|
||||
|
||||
#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