mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 03:16:10 +00:00
Refactor SectionsWidget to use Model/View archictecture (#475)
This commit is contained in:
parent
fd829986af
commit
a30ac22056
@ -275,6 +275,7 @@ Q_DECLARE_METATYPE(ResourcesDescription)
|
||||
Q_DECLARE_METATYPE(VTableDescription)
|
||||
Q_DECLARE_METATYPE(TypeDescription)
|
||||
Q_DECLARE_METATYPE(SearchDescription)
|
||||
Q_DECLARE_METATYPE(SectionDescription)
|
||||
|
||||
class CutterCore: public QObject
|
||||
{
|
||||
|
@ -120,7 +120,6 @@ SOURCES += \
|
||||
widgets/PieView.cpp \
|
||||
widgets/RelocsWidget.cpp \
|
||||
widgets/SdbDock.cpp \
|
||||
widgets/SectionsDock.cpp \
|
||||
widgets/SectionsWidget.cpp \
|
||||
widgets/Sidebar.cpp \
|
||||
widgets/StringsWidget.cpp \
|
||||
@ -192,7 +191,6 @@ HEADERS += \
|
||||
widgets/PieView.h \
|
||||
widgets/RelocsWidget.h \
|
||||
widgets/SdbDock.h \
|
||||
widgets/SectionsDock.h \
|
||||
widgets/SectionsWidget.h \
|
||||
widgets/Sidebar.h \
|
||||
widgets/StringsWidget.h \
|
||||
@ -252,7 +250,7 @@ FORMS += \
|
||||
widgets/ImportsWidget.ui \
|
||||
widgets/SdbDock.ui \
|
||||
widgets/RelocsWidget.ui \
|
||||
widgets/SectionsDock.ui \
|
||||
widgets/SectionsWidget.ui \
|
||||
widgets/Sidebar.ui \
|
||||
widgets/StringsWidget.ui \
|
||||
widgets/SymbolsWidget.ui \
|
||||
|
@ -53,7 +53,6 @@
|
||||
#include "widgets/SearchWidget.h"
|
||||
#include "widgets/SymbolsWidget.h"
|
||||
#include "widgets/StringsWidget.h"
|
||||
#include "widgets/SectionsDock.h"
|
||||
#include "widgets/RelocsWidget.h"
|
||||
#include "widgets/FlagsWidget.h"
|
||||
#include "widgets/VisualNavbar.h"
|
||||
@ -163,7 +162,7 @@ void MainWindow::initUI()
|
||||
// Hide centralWidget as we do not need it
|
||||
ui->centralWidget->hide();
|
||||
|
||||
sectionsDock = new SectionsDock(this, ui->actionSections);
|
||||
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
||||
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
||||
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
|
||||
importsDock = new ImportsWidget(this, ui->actionImports);
|
||||
|
@ -32,7 +32,7 @@ class Dashboard;
|
||||
class QLineEdit;
|
||||
class SdbDock;
|
||||
class QAction;
|
||||
class SectionsDock;
|
||||
class SectionsWidget;
|
||||
class ConsoleWidget;
|
||||
class EntrypointWidget;
|
||||
class DisassemblerGraphView;
|
||||
@ -188,7 +188,7 @@ private:
|
||||
Dashboard *dashboardDock = nullptr;
|
||||
QLineEdit *gotoEntry = nullptr;
|
||||
SdbDock *sdbDock = nullptr;
|
||||
SectionsDock *sectionsDock = nullptr;
|
||||
SectionsWidget *sectionsDock = nullptr;
|
||||
ConsoleWidget *consoleDock = nullptr;
|
||||
ClassesWidget *classesDock = nullptr;
|
||||
ResourcesWidget *resourcesDock = nullptr;
|
||||
|
@ -121,8 +121,6 @@ bool ExportsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
return leftExp.vaddr < rightExp.vaddr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExportsWidget::ExportsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ui(new Ui::ExportsWidget)
|
||||
|
@ -16,12 +16,7 @@ namespace Ui {
|
||||
class ExportsWidget;
|
||||
}
|
||||
|
||||
|
||||
class MainWindow;
|
||||
class QTreeWidgetItem;
|
||||
|
||||
|
||||
class ExportsModel: public QAbstractListModel
|
||||
class ExportsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -44,8 +39,6 @@ public:
|
||||
void endReloadExports();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ExportsProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -58,8 +51,6 @@ protected:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ExportsWidget : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -83,5 +74,4 @@ private:
|
||||
void setScrollMode();
|
||||
};
|
||||
|
||||
|
||||
#endif // EXPORTSWIDGET_H
|
||||
|
@ -1,71 +0,0 @@
|
||||
#include "SectionsDock.h"
|
||||
#include "ui_SectionsDock.h"
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "widgets/SectionsWidget.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
|
||||
|
||||
SectionsDock::SectionsDock(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ui(new Ui::SectionsDock),
|
||||
main(main)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
this->sectionsWidget = new SectionsWidget(this->main);
|
||||
this->setWidget(this->sectionsWidget);
|
||||
this->sectionsWidget->setContentsMargins(0, 0, 0, 5);
|
||||
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||
this, SLOT(showSectionsContextMenu(const QPoint &)));
|
||||
}
|
||||
|
||||
SectionsDock::~SectionsDock() {}
|
||||
|
||||
void SectionsDock::showSectionsContextMenu(const QPoint &pt)
|
||||
{
|
||||
// Set functions popup menu
|
||||
QMenu *menu = new QMenu(this);
|
||||
menu->clear();
|
||||
menu->addAction(ui->actionHorizontal);
|
||||
menu->addAction(ui->actionVertical);
|
||||
|
||||
if (this->sectionsWidget->orientation() == 1) {
|
||||
ui->actionHorizontal->setChecked(true);
|
||||
ui->actionVertical->setChecked(false);
|
||||
} else {
|
||||
ui->actionVertical->setChecked(true);
|
||||
ui->actionHorizontal->setChecked(false);
|
||||
}
|
||||
|
||||
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
menu->exec(this->mapToGlobal(pt));
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void SectionsDock::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
if (main->responsive && isVisible()) {
|
||||
if (event->size().width() >= event->size().height()) {
|
||||
// Set horizontal view (list)
|
||||
this->on_actionHorizontal_triggered();
|
||||
} else {
|
||||
// Set vertical view (Tree)
|
||||
this->on_actionVertical_triggered();
|
||||
}
|
||||
}
|
||||
QWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
void SectionsDock::on_actionVertical_triggered()
|
||||
{
|
||||
this->sectionsWidget->setOrientation(Qt::Vertical);
|
||||
}
|
||||
|
||||
void SectionsDock::on_actionHorizontal_triggered()
|
||||
{
|
||||
this->sectionsWidget->setOrientation(Qt::Horizontal);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#ifndef SECTIONSDOCK_H
|
||||
#define SECTIONSDOCK_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "CutterDockWidget.h"
|
||||
|
||||
class MainWindow;
|
||||
class SectionsWidget;
|
||||
|
||||
namespace Ui {
|
||||
class SectionsDock;
|
||||
}
|
||||
|
||||
class SectionsDock : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SectionsDock(MainWindow *main, QAction *action = nullptr);
|
||||
~SectionsDock();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private slots:
|
||||
|
||||
void showSectionsContextMenu(const QPoint &pt);
|
||||
|
||||
void on_actionVertical_triggered();
|
||||
|
||||
void on_actionHorizontal_triggered();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::SectionsDock> ui;
|
||||
MainWindow *main;
|
||||
SectionsWidget *sectionsWidget;
|
||||
};
|
||||
|
||||
#endif // SECTIONSDOCK_H
|
@ -1,73 +1,32 @@
|
||||
#include "widgets/SectionsWidget.h"
|
||||
#include "widgets/PieView.h"
|
||||
#include <QMenu>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include "SectionsWidget.h"
|
||||
#include "ui_SectionsWidget.h"
|
||||
#include "PieView.h"
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "utils/Helpers.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QTreeWidget>
|
||||
|
||||
SectionsWidget::SectionsWidget(MainWindow *main, QWidget *parent) :
|
||||
QSplitter(main),
|
||||
main(main)
|
||||
SectionsModel::SectionsModel(QList<SectionDescription> *sections, QObject *parent)
|
||||
: QAbstractListModel(parent),
|
||||
sections(sections)
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
setupViews();
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
connect(this->tree, SIGNAL(doubleClicked(const QModelIndex &)), this,
|
||||
SLOT(onSectionsDoubleClicked(const QModelIndex &)));
|
||||
|
||||
tree->sortByColumn(0, Qt::AscendingOrder);
|
||||
|
||||
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshSections()));
|
||||
}
|
||||
|
||||
void SectionsWidget::refreshSections()
|
||||
int SectionsModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
tree->clear();
|
||||
|
||||
int row = 0;
|
||||
for (auto section : Core()->getAllSections()) {
|
||||
fillSections(row++, section);
|
||||
}
|
||||
|
||||
qhelpers::adjustColumns(tree, 0);
|
||||
return sections->count();
|
||||
}
|
||||
|
||||
void SectionsWidget::setupViews()
|
||||
int SectionsModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
// Table view
|
||||
this->tree = new QTreeWidget;
|
||||
this->tree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
this->tree->setIndentation(10);
|
||||
|
||||
// Setup TreeWidget
|
||||
this->tree->setColumnCount(4);
|
||||
QList<QString> headers;
|
||||
headers << tr("Name") << tr("Size") << tr("Address") << tr("End Address");
|
||||
this->tree->setHeaderLabels(headers);
|
||||
|
||||
this->tree->setFrameShape(QFrame::NoFrame);
|
||||
this->tree->setSortingEnabled(true);
|
||||
|
||||
pieChart = new PieView;
|
||||
pieChart->setFrameShape(QFrame::NoFrame);
|
||||
pieChart->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
this->addWidget(this->tree);
|
||||
this->addWidget(pieChart);
|
||||
this->setStretchFactor(0, 4);
|
||||
|
||||
//this->tree->setModel(model);
|
||||
pieChart->setModel(this->tree->model());
|
||||
|
||||
QItemSelectionModel *selectionModel = new QItemSelectionModel(this->tree->model());
|
||||
this->tree->setSelectionModel(selectionModel);
|
||||
pieChart->setSelectionModel(selectionModel);
|
||||
return SectionsModel::ColumnCount;
|
||||
}
|
||||
|
||||
void SectionsWidget::fillSections(int row, const SectionDescription §ion)
|
||||
QVariant SectionsModel::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
|
||||
@ -83,14 +42,200 @@ void SectionsWidget::fillSections(int row, const SectionDescription §ion)
|
||||
QColor("#95A5A6") //COBCRETE
|
||||
};
|
||||
|
||||
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
||||
tempItem->setText(0, section.name);
|
||||
tempItem->setData(1, Qt::DisplayRole, section.size);
|
||||
tempItem->setTextAlignment(1, Qt::AlignRight | Qt::AlignVCenter);
|
||||
tempItem->setText(2, RAddressString(section.vaddr));
|
||||
tempItem->setText(3, RAddressString(section.vaddr + section.vsize));
|
||||
tempItem->setData(0, Qt::DecorationRole, colors[row % colors.size()]);
|
||||
this->tree->insertTopLevelItem(0, tempItem);
|
||||
if (index.row() >= sections->count())
|
||||
return QVariant();
|
||||
|
||||
const SectionDescription §ion = sections->at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column()) {
|
||||
case SectionsModel::NameColumn:
|
||||
return section.name;
|
||||
case SectionsModel::SizeColumn:
|
||||
return section.size;
|
||||
case SectionsModel::AddressColumn:
|
||||
return RAddressString(section.vaddr);
|
||||
case SectionsModel::EndAddressColumn:
|
||||
return RAddressString(section.vaddr + section.size);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
if (index.column() == 0)
|
||||
return colors[index.row() % colors.size()];
|
||||
return QVariant();
|
||||
case SectionsModel::SectionDescriptionRole:
|
||||
return QVariant::fromValue(section);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant SectionsModel::headerData(int section, Qt::Orientation, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (section) {
|
||||
case SectionsModel::NameColumn:
|
||||
return tr("Name");
|
||||
case SectionsModel::SizeColumn:
|
||||
return tr("Size");
|
||||
case SectionsModel::AddressColumn:
|
||||
return tr("Address");
|
||||
case SectionsModel::EndAddressColumn:
|
||||
return tr("EndAddress");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void SectionsModel::beginReloadSections()
|
||||
{
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void SectionsModel::endReloadSections()
|
||||
{
|
||||
endResetModel();
|
||||
// Update PieChart
|
||||
emit dataChanged(QModelIndex(), QModelIndex());
|
||||
}
|
||||
|
||||
SectionsProxyModel::SectionsProxyModel(SectionsModel *sourceModel, QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setSourceModel(sourceModel);
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
connect(sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
|
||||
this, SLOT(onSourceModelDataChanged(QModelIndex,QModelIndex,QVector<int>)));
|
||||
}
|
||||
|
||||
void SectionsProxyModel::onSourceModelDataChanged(const QModelIndex &topLeft,
|
||||
const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles)
|
||||
{
|
||||
// Pass the signal further to update PieChart
|
||||
emit dataChanged(topLeft, bottomRight, roles);
|
||||
}
|
||||
|
||||
bool SectionsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
auto leftSection = left.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
||||
auto rightSection = right.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
||||
|
||||
switch (left.column()) {
|
||||
case SectionsModel::NameColumn:
|
||||
return leftSection.name < rightSection.name;
|
||||
case SectionsModel::SizeColumn:
|
||||
return leftSection.size < rightSection.size;
|
||||
case SectionsModel::AddressColumn:
|
||||
case SectionsModel::EndAddressColumn:
|
||||
return leftSection.vaddr < rightSection.vaddr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SectionsWidget::SectionsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ui(new Ui::SectionsWidget),
|
||||
main(main)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
sectionsModel = new SectionsModel(§ions, this);
|
||||
sectionsProxyModel = new SectionsProxyModel(sectionsModel, this);
|
||||
|
||||
setupViews();
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||
this, SLOT(showSectionsContextMenu(const QPoint &)));
|
||||
|
||||
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshSections()));
|
||||
}
|
||||
|
||||
SectionsWidget::~SectionsWidget() {}
|
||||
|
||||
void SectionsWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
if (main->responsive && isVisible()) {
|
||||
if (event->size().width() >= event->size().height()) {
|
||||
on_actionHorizontal_triggered();
|
||||
} else {
|
||||
on_actionVertical_triggered();
|
||||
}
|
||||
}
|
||||
QWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
void SectionsWidget::showSectionsContextMenu(const QPoint &pt)
|
||||
{
|
||||
// Set functions popup menu
|
||||
QMenu *menu = new QMenu(this);
|
||||
menu->clear();
|
||||
menu->addAction(ui->actionHorizontal);
|
||||
menu->addAction(ui->actionVertical);
|
||||
|
||||
if (splitter->orientation() == 1) {
|
||||
ui->actionHorizontal->setChecked(true);
|
||||
ui->actionVertical->setChecked(false);
|
||||
} else {
|
||||
ui->actionVertical->setChecked(true);
|
||||
ui->actionHorizontal->setChecked(false);
|
||||
}
|
||||
|
||||
menu->exec(mapToGlobal(pt));
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void SectionsWidget::refreshSections()
|
||||
{
|
||||
sectionsModel->beginReloadSections();
|
||||
sections = Core()->getAllSections();
|
||||
sectionsModel->endReloadSections();
|
||||
|
||||
qhelpers::adjustColumns(sectionsTable, SectionsModel::ColumnCount, 0);
|
||||
}
|
||||
|
||||
void SectionsWidget::setupViews()
|
||||
{
|
||||
splitter = new QSplitter;
|
||||
sectionsTable = new QTreeView;
|
||||
sectionsPieChart = new PieView;
|
||||
|
||||
splitter->addWidget(sectionsTable);
|
||||
splitter->addWidget(sectionsPieChart);
|
||||
//splitter->setStretchFactor(0, 4);
|
||||
|
||||
sectionsTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
sectionsTable->setIndentation(10);
|
||||
sectionsTable->setFrameShape(QFrame::NoFrame);
|
||||
sectionsTable->setSortingEnabled(true);
|
||||
sectionsTable->sortByColumn(SectionsModel::NameColumn, Qt::AscendingOrder);
|
||||
connect(sectionsTable, SIGNAL(doubleClicked(const QModelIndex &)),
|
||||
this, SLOT(onSectionsDoubleClicked(const QModelIndex &)));
|
||||
|
||||
sectionsPieChart->setFrameShape(QFrame::NoFrame);
|
||||
sectionsPieChart->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
||||
sectionsTable->setModel(sectionsProxyModel);
|
||||
sectionsPieChart->setModel(sectionsProxyModel);
|
||||
|
||||
QItemSelectionModel *selectionModel = new QItemSelectionModel(sectionsProxyModel);
|
||||
sectionsTable->setSelectionModel(selectionModel);
|
||||
sectionsPieChart->setSelectionModel(selectionModel);
|
||||
|
||||
setWidget(splitter);
|
||||
}
|
||||
|
||||
void SectionsWidget::onSectionsDoubleClicked(const QModelIndex &index)
|
||||
@ -98,7 +243,16 @@ void SectionsWidget::onSectionsDoubleClicked(const QModelIndex &index)
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
QTreeWidgetItem *section = tree->topLevelItem(index.row());
|
||||
auto addr = section->text(2);
|
||||
Core()->seek(addr);
|
||||
auto section = index.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
||||
Core()->seek(section.vaddr);
|
||||
}
|
||||
|
||||
void SectionsWidget::on_actionVertical_triggered()
|
||||
{
|
||||
splitter->setOrientation(Qt::Vertical);
|
||||
}
|
||||
|
||||
void SectionsWidget::on_actionHorizontal_triggered()
|
||||
{
|
||||
splitter->setOrientation(Qt::Horizontal);
|
||||
}
|
||||
|
@ -1,41 +1,92 @@
|
||||
#ifndef SECTIONSWIDGET_H
|
||||
#define SECTIONSWIDGET_H
|
||||
|
||||
#include <QSplitter>
|
||||
#include <memory>
|
||||
|
||||
class MainWindow;
|
||||
class QTreeWidget;
|
||||
class QAbstractItemModel;
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "CutterDockWidget.h"
|
||||
|
||||
class QSplitter;
|
||||
class QTreeView;
|
||||
class QAbstractItemView;
|
||||
class QItemSelectionModel;
|
||||
|
||||
struct SectionDescription;
|
||||
class QResizeEvent;
|
||||
class MainWindow;
|
||||
|
||||
namespace Ui {
|
||||
class SectionsWidget;
|
||||
}
|
||||
|
||||
class SectionsWidget : public QSplitter
|
||||
class SectionsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QList<SectionDescription> *sections;
|
||||
|
||||
public:
|
||||
enum Column { NameColumn = 0, SizeColumn, AddressColumn, EndAddressColumn, ColumnCount };
|
||||
enum Role { SectionDescriptionRole = Qt::UserRole };
|
||||
|
||||
SectionsModel(QList<SectionDescription> *sections, QObject *parent = Q_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 section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
void beginReloadSections();
|
||||
void endReloadSections();
|
||||
};
|
||||
|
||||
class SectionsProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SectionsWidget(MainWindow *main, QWidget *parent = 0);
|
||||
SectionsProxyModel(SectionsModel *sourceModel, QObject *parent = Q_NULLPTR);
|
||||
|
||||
private slots:
|
||||
void onSourceModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
|
||||
const QVector<int>& roles);
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
};
|
||||
|
||||
class SectionsWidget : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SectionsWidget(MainWindow *main, QAction *action = Q_NULLPTR);
|
||||
~SectionsWidget();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void refreshSections();
|
||||
|
||||
void showSectionsContextMenu(const QPoint &pt);
|
||||
void on_actionVertical_triggered();
|
||||
void on_actionHorizontal_triggered();
|
||||
void onSectionsDoubleClicked(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
QAbstractItemView *pieChart;
|
||||
QItemSelectionModel *selectionModel;
|
||||
MainWindow *main;
|
||||
QTreeWidget *tree;
|
||||
std::unique_ptr<Ui::SectionsWidget> ui;
|
||||
|
||||
QList<SectionDescription> sections;
|
||||
SectionsModel *sectionsModel;
|
||||
SectionsProxyModel *sectionsProxyModel;
|
||||
QSplitter *splitter;
|
||||
QTreeView *sectionsTable;
|
||||
QAbstractItemView *sectionsPieChart;
|
||||
MainWindow *main;
|
||||
|
||||
void setupViews();
|
||||
|
||||
void fillSections(int row, const SectionDescription §ion);
|
||||
};
|
||||
|
||||
#endif // SECTIONSWIDGET_H
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SectionsDock</class>
|
||||
<widget class="QDockWidget" name="SectionsDock">
|
||||
<class>SectionsWidget</class>
|
||||
<widget class="QDockWidget" name="SectionsWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@ -13,7 +13,6 @@
|
||||
<property name="windowTitle">
|
||||
<string>Sections</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents"/>
|
||||
<action name="actionVertical">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
Loading…
Reference in New Issue
Block a user