From 601339d86fbe97db566e61f2053eb5b88a6fce46 Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Ghildiyal Date: Fri, 1 Feb 2019 21:41:50 +0530 Subject: [PATCH] Added some of the features mentioned in the Types Widget Project. (#1153) * Added filter widget to types widget * Added filter capibility in types widget * Added comments and refactored some code * Corrected some details --- src/Cutter.cpp | 82 ++++++++++++++++++++++++++++++++++++- src/Cutter.h | 31 ++++++++++++++ src/widgets/TypesWidget.cpp | 66 +++++++++++++++++++++++++++-- src/widgets/TypesWidget.h | 14 ++++++- src/widgets/TypesWidget.ui | 25 +++++++++++ 5 files changed, 213 insertions(+), 5 deletions(-) diff --git a/src/Cutter.cpp b/src/Cutter.cpp index e407e3da..e7a4e947 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -2004,12 +2004,24 @@ QList CutterCore::getAllVTables() } QList CutterCore::getAllTypes() +{ + QList ret; + + ret.append(getAllPrimitiveTypes()); + ret.append(getAllUnions()); + ret.append(getAllStructs()); + ret.append(getAllEnums()); + ret.append(getAllTypedefs()); + + return ret; +} + +QList CutterCore::getAllPrimitiveTypes() { CORE_LOCK(); QList ret; QJsonArray typesArray = cmdj("tj").array(); - for (const QJsonValue &value : typesArray) { QJsonObject typeObject = value.toObject(); @@ -2018,7 +2030,75 @@ QList CutterCore::getAllTypes() exp.type = typeObject[RJsonKey::type].toString(); exp.size = typeObject[RJsonKey::size].toVariant().toULongLong(); exp.format = typeObject[RJsonKey::format].toString(); + exp.category = tr("Primitive"); + ret << exp; + } + return ret; +} + +QList CutterCore::getAllUnions() +{ + CORE_LOCK(); + QList ret; + + QJsonArray typesArray = cmdj("tuj").array(); + for (auto value: typesArray) { + TypeDescription exp; + exp.type = value.toString(); + exp.size = 0; + exp.category = tr("Union"); + ret << exp; + } + + return ret; +} + +QList CutterCore::getAllStructs() +{ + CORE_LOCK(); + QList ret; + + QJsonArray typesArray = cmdj("tsj").array(); + for (auto value: typesArray) { + TypeDescription exp; + exp.type = value.toString(); + exp.size = 0; + exp.category = tr("Struct"); + ret << exp; + } + + return ret; +} + +QList CutterCore::getAllEnums() +{ + CORE_LOCK(); + QList ret; + + QJsonObject typesObject = cmdj("tej").object(); + for (QString key: typesObject.keys()) { + TypeDescription exp; + exp.type = key; + exp.size = 0; + exp.category = tr("Enum"); + ret << exp; + } + + return ret; +} + +QList CutterCore::getAllTypedefs() +{ + CORE_LOCK(); + QList ret; + + QJsonObject typesObject = cmdj("ttj").object(); + for (QString key: typesObject.keys()) { + TypeDescription exp; + exp.type = key; + exp.size = 0; + exp.category = tr("Typedef"); ret << exp; } diff --git a/src/Cutter.h b/src/Cutter.h index 333c1150..99b5f723 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -133,6 +133,7 @@ struct TypeDescription { QString type; int size; QString format; + QString category; }; struct SearchDescription { @@ -606,7 +607,37 @@ public: QList getAllClassesFromFlags(); QList getAllResources(); QList getAllVTables(); + + /*! + * \return all loaded types + */ QList getAllTypes(); + + /*! + * \return all loaded primitive types + */ + QList getAllPrimitiveTypes(); + + /*! + * \return all loaded unions + */ + QList getAllUnions(); + + /*! + * \return all loaded structs + */ + QList getAllStructs(); + + /*! + * \return all loaded enums + */ + QList getAllEnums(); + + /*! + * \return all loaded typedefs + */ + QList getAllTypedefs(); + QList getMemoryMap(); QList getAllSearch(QString search_for, QString space); BlockStatistics getBlockStatistics(unsigned int blocksCount); diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index 487ba4d0..7428e747 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -32,9 +32,11 @@ QVariant TypesModel::data(const QModelIndex &index, int role) const case TYPE: return exp.type; case SIZE: - return exp.size; + return exp.category == tr("Primitive") ? exp.size : QVariant(); case FORMAT: return exp.format; + case CATEGORY: + return exp.category; default: return QVariant(); } @@ -56,6 +58,8 @@ QVariant TypesModel::headerData(int section, Qt::Orientation, int role) const return tr("Size"); case FORMAT: return tr("Format"); + case CATEGORY: + return tr("Category"); default: return QVariant(); } @@ -75,7 +79,11 @@ bool TypesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &par { QModelIndex index = sourceModel()->index(row, 0, parent); TypeDescription exp = index.data(TypesModel::TypeDescriptionRole).value(); - return exp.type.contains(filterRegExp()); + if (selectedCategory.isEmpty()) { + return exp.type.contains(filterRegExp()); + } else { + return selectedCategory == exp.category && exp.type.contains(filterRegExp()); + } } bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const @@ -90,6 +98,8 @@ bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIn return left_exp.size < right_exp.size; case TypesModel::FORMAT: return left_exp.format < right_exp.format; + case TypesModel::CATEGORY: + return left_exp.category < right_exp.category; default: break; } @@ -101,9 +111,14 @@ bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIn TypesWidget::TypesWidget(MainWindow *main, QAction *action) : CutterDockWidget(main, action), - ui(new Ui::TypesWidget) + ui(new Ui::TypesWidget), + tree(new CutterTreeWidget(this)) { ui->setupUi(this); + ui->quickFilterView->setLabelText(tr("Category")); + + // Add status bar which displays the count + tree->addStatusBar(ui->verticalLayout); types_model = new TypesModel(&types, this); types_proxy_model = new TypesSortFilterProxyModel(types_model, this); @@ -112,7 +127,31 @@ TypesWidget::TypesWidget(MainWindow *main, QAction *action) : setScrollMode(); + connect(ui->quickFilterView, SIGNAL(filterTextChanged(const QString &)), types_proxy_model, + SLOT(setFilterWildcard(const QString &))); + + connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this, [this] { + tree->showItemsNumber(types_proxy_model->rowCount()); + }); + + QShortcut *searchShortcut = new QShortcut(QKeySequence::Find, this); + connect(searchShortcut, &QShortcut::activated, ui->quickFilterView, &ComboQuickFilterView::showFilter); + searchShortcut->setContext(Qt::WidgetWithChildrenShortcut); + + QShortcut *clearShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this); + connect(clearShortcut, &QShortcut::activated, ui->quickFilterView, &ComboQuickFilterView::clearFilter); + clearShortcut->setContext(Qt::WidgetWithChildrenShortcut); + connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshTypes())); + + connect( + ui->quickFilterView->comboBox(), &QComboBox::currentTextChanged, this, + [this]() { + types_proxy_model->selectedCategory = ui->quickFilterView->comboBox()->currentData().toString(); + types_proxy_model->setFilterRegExp(types_proxy_model->filterRegExp()); + tree->showItemsNumber(types_proxy_model->rowCount()); + } + ); } TypesWidget::~TypesWidget() {} @@ -123,9 +162,30 @@ void TypesWidget::refreshTypes() types = Core()->getAllTypes(); types_model->endResetModel(); + QStringList categories; + for (TypeDescription exp: types) { + categories << exp.category; + } + categories.removeDuplicates(); + refreshCategoryCombo(categories); + qhelpers::adjustColumns(ui->typesTreeView, 3, 0); } +void TypesWidget::refreshCategoryCombo(const QStringList &categories) +{ + QComboBox *combo = ui->quickFilterView->comboBox(); + + combo->clear(); + combo->addItem(tr("(All)")); + + for (const QString &category : categories) { + combo->addItem(category, category); + } + + types_proxy_model->selectedCategory.clear(); +} + void TypesWidget::setScrollMode() { qhelpers::setVerticalScrollMode(ui->typesTreeView); diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index 3f4d8e06..b73bf06e 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -5,6 +5,7 @@ #include "Cutter.h" #include "CutterDockWidget.h" +#include "CutterTreeWidget.h" #include #include @@ -32,7 +33,7 @@ private: QList *types; public: - enum Columns { TYPE = 0, SIZE, FORMAT, COUNT }; + enum Columns { TYPE = 0, SIZE, FORMAT, CATEGORY, COUNT }; static const int TypeDescriptionRole = Qt::UserRole; TypesModel(QList *types, QObject *parent = nullptr); @@ -50,12 +51,16 @@ class TypesSortFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT + friend TypesWidget; + public: TypesSortFilterProxyModel(TypesModel *source_model, QObject *parent = nullptr); protected: bool filterAcceptsRow(int row, const QModelIndex &parent) const override; bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + + QString selectedCategory; }; @@ -77,8 +82,15 @@ private: TypesModel *types_model; TypesSortFilterProxyModel *types_proxy_model; QList types; + CutterTreeWidget *tree; void setScrollMode(); + + /*! + * \brief Sets the contents of the ComboBox to the supplied contents + * \param categories The list of categories which has to be added to the ComboBox + */ + void refreshCategoryCombo(const QStringList &categories); }; diff --git a/src/widgets/TypesWidget.ui b/src/widgets/TypesWidget.ui index f97b969d..b7ce9b69 100644 --- a/src/widgets/TypesWidget.ui +++ b/src/widgets/TypesWidget.ui @@ -15,6 +15,9 @@ + + 0 + 0 @@ -29,6 +32,12 @@ + + + 0 + 0 + + CutterTreeView::item { @@ -50,6 +59,16 @@ + + + + + 0 + 0 + + + + @@ -60,6 +79,12 @@
widgets/CutterTreeView.h
1 + + ComboQuickFilterView + QWidget +
widgets/ComboQuickFilterView.h
+ 1 +