mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 19:06:10 +00:00
Add QuickFilter panel for ImportsWidget and ExportsWidget (#449)
This commit is contained in:
parent
5f9018f5b9
commit
09bfc9f3d0
@ -16,7 +16,7 @@ int ExportsModel::rowCount(const QModelIndex &) const
|
||||
|
||||
int ExportsModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return Columns::COUNT;
|
||||
return ExportsModel::ColumnCount;
|
||||
}
|
||||
|
||||
QVariant ExportsModel::data(const QModelIndex &index, int role) const
|
||||
@ -29,18 +29,18 @@ QVariant ExportsModel::data(const QModelIndex &index, int role) const
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column()) {
|
||||
case OFFSET:
|
||||
case ExportsModel::OffsetColumn:
|
||||
return RAddressString(exp.vaddr);
|
||||
case SIZE:
|
||||
case ExportsModel::SizeColumn:
|
||||
return RSizeString(exp.size);
|
||||
case TYPE:
|
||||
case ExportsModel::TypeColumn:
|
||||
return exp.type;
|
||||
case NAME:
|
||||
case ExportsModel::NameColumn:
|
||||
return exp.name;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
case ExportDescriptionRole:
|
||||
case ExportsModel::ExportDescriptionRole:
|
||||
return QVariant::fromValue(exp);
|
||||
default:
|
||||
return QVariant();
|
||||
@ -52,13 +52,13 @@ QVariant ExportsModel::headerData(int section, Qt::Orientation, int role) const
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (section) {
|
||||
case OFFSET:
|
||||
case ExportsModel::OffsetColumn:
|
||||
return tr("Address");
|
||||
case SIZE:
|
||||
case ExportsModel::SizeColumn:
|
||||
return tr("Size");
|
||||
case TYPE:
|
||||
case ExportsModel::TypeColumn:
|
||||
return tr("Type");
|
||||
case NAME:
|
||||
case ExportsModel::NameColumn:
|
||||
return tr("Name");
|
||||
default:
|
||||
return QVariant();
|
||||
@ -78,15 +78,13 @@ void ExportsModel::endReloadExports()
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ExportsSortFilterProxyModel::ExportsSortFilterProxyModel(ExportsModel *source_model,
|
||||
QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setSourceModel(source_model);
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool ExportsSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||
@ -104,17 +102,17 @@ bool ExportsSortFilterProxyModel::lessThan(const QModelIndex &left, const QModel
|
||||
ExportsModel::ExportDescriptionRole).value<ExportDescription>();
|
||||
|
||||
switch (left.column()) {
|
||||
case ExportsModel::SIZE:
|
||||
case ExportsModel::SizeColumn:
|
||||
if (left_exp.size != right_exp.size)
|
||||
return left_exp.size < right_exp.size;
|
||||
// fallthrough
|
||||
case ExportsModel::OFFSET:
|
||||
case ExportsModel::OffsetColumn:
|
||||
if (left_exp.vaddr != right_exp.vaddr)
|
||||
return left_exp.vaddr < right_exp.vaddr;
|
||||
// fallthrough
|
||||
case ExportsModel::NAME:
|
||||
case ExportsModel::NameColumn:
|
||||
return left_exp.name < right_exp.name;
|
||||
case ExportsModel::TYPE:
|
||||
case ExportsModel::TypeColumn:
|
||||
if (left_exp.type != right_exp.type)
|
||||
return left_exp.type < right_exp.type;
|
||||
default:
|
||||
@ -133,10 +131,24 @@ ExportsWidget::ExportsWidget(MainWindow *main, QAction *action) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
exports_model = new ExportsModel(&exports, this);
|
||||
exports_proxy_model = new ExportsSortFilterProxyModel(exports_model, this);
|
||||
ui->exportsTreeView->setModel(exports_proxy_model);
|
||||
ui->exportsTreeView->sortByColumn(ExportsModel::OFFSET, Qt::AscendingOrder);
|
||||
exportsModel = new ExportsModel(&exports, this);
|
||||
exportsProxyModel = new ExportsSortFilterProxyModel(exportsModel, this);
|
||||
ui->exportsTreeView->setModel(exportsProxyModel);
|
||||
ui->exportsTreeView->sortByColumn(ExportsModel::OffsetColumn, Qt::AscendingOrder);
|
||||
|
||||
// Ctrl-F to show/hide the filter entry
|
||||
QShortcut *searchShortcut = new QShortcut(QKeySequence::Find, this);
|
||||
connect(searchShortcut, &QShortcut::activated, ui->quickFilterView, &QuickFilterView::showFilter);
|
||||
searchShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||
|
||||
// Esc to clear the filter entry
|
||||
QShortcut *clearShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||
connect(clearShortcut, &QShortcut::activated, ui->quickFilterView, &QuickFilterView::clearFilter);
|
||||
clearShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||
|
||||
connect(ui->quickFilterView, SIGNAL(filterTextChanged(const QString &)),
|
||||
exportsProxyModel, SLOT(setFilterWildcard(const QString &)));
|
||||
connect(ui->quickFilterView, SIGNAL(filterClosed()), ui->exportsTreeView, SLOT(setFocus()));
|
||||
|
||||
setScrollMode();
|
||||
|
||||
@ -147,9 +159,9 @@ ExportsWidget::~ExportsWidget() {}
|
||||
|
||||
void ExportsWidget::refreshExports()
|
||||
{
|
||||
exports_model->beginReloadExports();
|
||||
exportsModel->beginReloadExports();
|
||||
exports = Core()->getAllExports();
|
||||
exports_model->endReloadExports();
|
||||
exportsModel->endReloadExports();
|
||||
|
||||
qhelpers::adjustColumns(ui->exportsTreeView, 3, 0);
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ private:
|
||||
QList<ExportDescription> *exports;
|
||||
|
||||
public:
|
||||
enum Columns { OFFSET = 0, SIZE, TYPE, NAME, COUNT };
|
||||
static const int ExportDescriptionRole = Qt::UserRole;
|
||||
enum Column { OffsetColumn = 0, SizeColumn, TypeColumn, NameColumn, ColumnCount };
|
||||
enum Role { ExportDescriptionRole = Qt::UserRole };
|
||||
|
||||
ExportsModel(QList<ExportDescription> *exports, QObject *parent = 0);
|
||||
|
||||
@ -76,8 +76,8 @@ private slots:
|
||||
private:
|
||||
std::unique_ptr<Ui::ExportsWidget> ui;
|
||||
|
||||
ExportsModel *exports_model;
|
||||
ExportsSortFilterProxyModel *exports_proxy_model;
|
||||
ExportsModel *exportsModel;
|
||||
ExportsSortFilterProxyModel *exportsProxyModel;
|
||||
QList<ExportDescription> exports;
|
||||
|
||||
void setScrollMode();
|
||||
|
@ -50,9 +50,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QuickFilterView" name="quickFilterView" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QuickFilterView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/QuickFilterView.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -20,36 +20,39 @@ int ImportsModel::rowCount(const QModelIndex &parent) const
|
||||
|
||||
int ImportsModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return COUNT;
|
||||
return ImportsModel::ColumnCount;
|
||||
}
|
||||
|
||||
QVariant ImportsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
const ImportDescription &import = imports->at(index.row());
|
||||
switch(role)
|
||||
switch (role)
|
||||
{
|
||||
case AddressRole:
|
||||
return import.plt;
|
||||
case Qt::ForegroundRole:
|
||||
if(index.column() < COUNT)
|
||||
if(banned.match(import.name).hasMatch())
|
||||
if (index.column() < ImportsModel::ColumnCount) {
|
||||
if (banned.match(import.name).hasMatch())
|
||||
return QColor(255, 129, 123);
|
||||
}
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case ADDRESS:
|
||||
case ImportsModel::AddressColumn:
|
||||
return RAddressString(import.plt);
|
||||
case TYPE:
|
||||
case ImportsModel::TypeColumn:
|
||||
return import.type;
|
||||
case SAFETY:
|
||||
case ImportsModel::SafetyColumn:
|
||||
return banned.match(import.name).hasMatch()? tr("Unsafe") : QStringLiteral("");
|
||||
case NAME:
|
||||
case ImportsModel::NameColumn:
|
||||
return import.name;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ImportsModel::ImportDescriptionRole:
|
||||
return QVariant::fromValue(import);
|
||||
case ImportsModel::AddressRole:
|
||||
return import.plt;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -62,13 +65,13 @@ QVariant ImportsModel::headerData(int section, Qt::Orientation, int role) const
|
||||
{
|
||||
switch(section)
|
||||
{
|
||||
case ADDRESS:
|
||||
case ImportsModel::AddressColumn:
|
||||
return tr("Address");
|
||||
case TYPE:
|
||||
case ImportsModel::TypeColumn:
|
||||
return tr("Type");
|
||||
case SAFETY:
|
||||
case ImportsModel::SafetyColumn:
|
||||
return tr("Safety");
|
||||
case NAME:
|
||||
case ImportsModel::NameColumn:
|
||||
return tr("Name");
|
||||
default:
|
||||
break;
|
||||
@ -87,6 +90,55 @@ void ImportsModel::endReload()
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
ImportsSortFilterProxyModel::ImportsSortFilterProxyModel(ImportsModel *sourceModel, QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setSourceModel(sourceModel);
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool ImportsSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||
{
|
||||
QModelIndex index;
|
||||
ImportDescription import;
|
||||
|
||||
index = sourceModel()->index(row, 0, parent);
|
||||
import = index.data(ImportsModel::ImportDescriptionRole).value<ImportDescription>();
|
||||
|
||||
return import.name.contains(filterRegExp());
|
||||
}
|
||||
|
||||
bool ImportsSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
ImportDescription leftImport;
|
||||
ImportDescription rightImport;
|
||||
|
||||
if (!left.isValid() || !right.isValid())
|
||||
return false;
|
||||
|
||||
if (left.parent().isValid() || right.parent().isValid())
|
||||
return false;
|
||||
|
||||
leftImport = left.data(ImportsModel::ImportDescriptionRole).value<ImportDescription>();
|
||||
rightImport = right.data(ImportsModel::ImportDescriptionRole).value<ImportDescription>();
|
||||
|
||||
switch (left.column()) {
|
||||
case ImportsModel::AddressColumn:
|
||||
return leftImport.plt < rightImport.plt;
|
||||
case ImportsModel::TypeColumn:
|
||||
return leftImport.type < rightImport.type;
|
||||
case ImportsModel::SafetyColumn:
|
||||
break;
|
||||
case ImportsModel::NameColumn:
|
||||
return leftImport.name < rightImport.name;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Imports Widget
|
||||
*/
|
||||
@ -94,12 +146,27 @@ void ImportsModel::endReload()
|
||||
ImportsWidget::ImportsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ui(new Ui::ImportsWidget),
|
||||
model(new ImportsModel(&imports, this))
|
||||
importsModel(new ImportsModel(&imports, this)),
|
||||
importsProxyModel(new ImportsSortFilterProxyModel(importsModel, this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->importsTreeView->setModel(model);
|
||||
ui->importsTreeView->sortByColumn(3, Qt::AscendingOrder);
|
||||
ui->importsTreeView->setModel(importsProxyModel);
|
||||
ui->importsTreeView->sortByColumn(ImportsModel::NameColumn, Qt::AscendingOrder);
|
||||
|
||||
// Ctrl-F to show/hide the filter entry
|
||||
QShortcut *searchShortcut = new QShortcut(QKeySequence::Find, this);
|
||||
connect(searchShortcut, &QShortcut::activated, ui->quickFilterView, &QuickFilterView::showFilter);
|
||||
searchShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||
|
||||
// Esc to clear the filter entry
|
||||
QShortcut *clearShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||
connect(clearShortcut, &QShortcut::activated, ui->quickFilterView, &QuickFilterView::clearFilter);
|
||||
clearShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||
|
||||
connect(ui->quickFilterView, SIGNAL(filterTextChanged(const QString &)),
|
||||
importsProxyModel, SLOT(setFilterWildcard(const QString &)));
|
||||
connect(ui->quickFilterView, SIGNAL(filterClosed()), ui->importsTreeView, SLOT(setFocus()));
|
||||
|
||||
setScrollMode();
|
||||
|
||||
@ -110,9 +177,9 @@ ImportsWidget::~ImportsWidget() {}
|
||||
|
||||
void ImportsWidget::refreshImports()
|
||||
{
|
||||
model->beginReload();
|
||||
importsModel->beginReload();
|
||||
imports = Core()->getAllImports();
|
||||
model->endReload();
|
||||
importsModel->endReload();
|
||||
qhelpers::adjustColumns(ui->importsTreeView, 4, 0);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QRegularExpression>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QTreeWidgetItem>
|
||||
@ -41,8 +42,8 @@ private:
|
||||
QList<ImportDescription> *imports;
|
||||
|
||||
public:
|
||||
enum COLUMNS {ADDRESS = 0, TYPE, SAFETY, NAME, COUNT};
|
||||
static const int AddressRole = Qt::UserRole;
|
||||
enum Column { AddressColumn = 0, TypeColumn, SafetyColumn, NameColumn, ColumnCount };
|
||||
enum Role { ImportDescriptionRole = Qt::UserRole, AddressRole };
|
||||
|
||||
ImportsModel(QList<ImportDescription> *imports, QObject *parent = nullptr);
|
||||
|
||||
@ -56,6 +57,18 @@ public:
|
||||
void endReload();
|
||||
};
|
||||
|
||||
class ImportsSortFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImportsSortFilterProxyModel(ImportsModel *sourceModel, QObject *parent = Q_NULLPTR);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
};
|
||||
|
||||
class ImportsWidget : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -71,7 +84,8 @@ private slots:
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::ImportsWidget> ui;
|
||||
ImportsModel* model;
|
||||
ImportsModel *importsModel;
|
||||
ImportsSortFilterProxyModel *importsProxyModel;
|
||||
QList<ImportDescription> imports;
|
||||
|
||||
void highlightUnsafe();
|
||||
|
@ -50,9 +50,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QuickFilterView" name="quickFilterView" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QuickFilterView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/QuickFilterView.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
Loading…
Reference in New Issue
Block a user