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
This commit is contained in:
Gaurav Kumar Ghildiyal 2019-02-01 21:41:50 +05:30 committed by Itay Cohen
parent f5709830b9
commit 601339d86f
5 changed files with 213 additions and 5 deletions

View File

@ -2004,12 +2004,24 @@ QList<VTableDescription> CutterCore::getAllVTables()
}
QList<TypeDescription> CutterCore::getAllTypes()
{
QList<TypeDescription> ret;
ret.append(getAllPrimitiveTypes());
ret.append(getAllUnions());
ret.append(getAllStructs());
ret.append(getAllEnums());
ret.append(getAllTypedefs());
return ret;
}
QList<TypeDescription> CutterCore::getAllPrimitiveTypes()
{
CORE_LOCK();
QList<TypeDescription> ret;
QJsonArray typesArray = cmdj("tj").array();
for (const QJsonValue &value : typesArray) {
QJsonObject typeObject = value.toObject();
@ -2018,7 +2030,75 @@ QList<TypeDescription> 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<TypeDescription> CutterCore::getAllUnions()
{
CORE_LOCK();
QList<TypeDescription> 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<TypeDescription> CutterCore::getAllStructs()
{
CORE_LOCK();
QList<TypeDescription> 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<TypeDescription> CutterCore::getAllEnums()
{
CORE_LOCK();
QList<TypeDescription> 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<TypeDescription> CutterCore::getAllTypedefs()
{
CORE_LOCK();
QList<TypeDescription> 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;
}

View File

@ -133,6 +133,7 @@ struct TypeDescription {
QString type;
int size;
QString format;
QString category;
};
struct SearchDescription {
@ -606,7 +607,37 @@ public:
QList<ClassDescription> getAllClassesFromFlags();
QList<ResourcesDescription> getAllResources();
QList<VTableDescription> getAllVTables();
/*!
* \return all loaded types
*/
QList<TypeDescription> getAllTypes();
/*!
* \return all loaded primitive types
*/
QList<TypeDescription> getAllPrimitiveTypes();
/*!
* \return all loaded unions
*/
QList<TypeDescription> getAllUnions();
/*!
* \return all loaded structs
*/
QList<TypeDescription> getAllStructs();
/*!
* \return all loaded enums
*/
QList<TypeDescription> getAllEnums();
/*!
* \return all loaded typedefs
*/
QList<TypeDescription> getAllTypedefs();
QList<MemoryMapDescription> getMemoryMap();
QList<SearchDescription> getAllSearch(QString search_for, QString space);
BlockStatistics getBlockStatistics(unsigned int blocksCount);

View File

@ -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<TypeDescription>();
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);

View File

@ -5,6 +5,7 @@
#include "Cutter.h"
#include "CutterDockWidget.h"
#include "CutterTreeWidget.h"
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
@ -32,7 +33,7 @@ private:
QList<TypeDescription> *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<TypeDescription> *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<TypeDescription> 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);
};

View File

@ -15,6 +15,9 @@
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
@ -29,6 +32,12 @@
</property>
<item>
<widget class="CutterTreeView" name="typesTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">CutterTreeView::item
{
@ -50,6 +59,16 @@
</property>
</widget>
</item>
<item>
<widget class="ComboQuickFilterView" name="quickFilterView" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
@ -60,6 +79,12 @@
<header>widgets/CutterTreeView.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ComboQuickFilterView</class>
<extends>QWidget</extends>
<header>widgets/ComboQuickFilterView.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>