Skip to content

Commit 772df1e

Browse files
Add filter options menu to QuickFilterView (#2230)
1 parent d8a8964 commit 772df1e

16 files changed

Lines changed: 185 additions & 22 deletions

build-output.txt

232 KB
Binary file not shown.

src/common/CutterSearchable.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <QObject>
66
#include <QAbstractScrollArea>
77
#include <QScrollBar>
8+
#include <QSortFilterProxyModel>
9+
#include <QRegularExpression>
810

911
void CutterSearchableHelper::setupConnections(QWidget *parent, SearchBarWidget *searchBar)
1012
{
@@ -75,3 +77,35 @@ void CutterSearchableHelper::positionSearchBar(QWidget *parent, SearchBarWidget
7577

7678
searchBar->move(x, y);
7779
}
80+
81+
void CutterSearchableHelper::applyFilter(QSortFilterProxyModel *proxyModel,
82+
const QString &filterText, int options)
83+
{
84+
if (!proxyModel) {
85+
return;
86+
}
87+
88+
if (filterText.isEmpty()) {
89+
proxyModel->setFilterFixedString(QString());
90+
return;
91+
}
92+
93+
QRegularExpression::PatternOptions patternOptions;
94+
if (!(options & CaseSensitive)) {
95+
patternOptions |= QRegularExpression::CaseInsensitiveOption;
96+
}
97+
98+
if (options & RegExp) {
99+
QRegularExpression regExp(filterText, patternOptions);
100+
proxyModel->setFilterRegularExpression(regExp);
101+
} else if (options & WholeWords) {
102+
QString pattern = QString("\\b%1\\b").arg(QRegularExpression::escape(filterText));
103+
QRegularExpression regExp(pattern, patternOptions);
104+
proxyModel->setFilterRegularExpression(regExp);
105+
} else {
106+
proxyModel->setFilterCaseSensitivity((options & CaseSensitive)
107+
? Qt::CaseSensitive
108+
: Qt::CaseInsensitive);
109+
proxyModel->setFilterWildcard(filterText);
110+
}
111+
}

src/common/CutterSearchable.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define CUTTERSEARCHABLE_H
33

44
class QString;
5+
class QSortFilterProxyModel;
56
class SearchBarWidget;
67
class QWidget;
78

@@ -79,6 +80,15 @@ void setupConnections(QWidget *parent, SearchBarWidget *bar);
7980
*/
8081
void positionSearchBar(QWidget *parent, SearchBarWidget *searchBar, QWidget *searchArea,
8182
int hPadding, int vPadding);
82-
};
83+
84+
/**
85+
* @brief Applies filter options to a proxy model
86+
* @param proxyModel The proxy model to filter
87+
* @param filterText The text to filter by
88+
* @param options Bitwise combination of SearchOption flags (CaseSensitive, WholeWords, RegExp)
89+
*/
90+
void applyFilter(QSortFilterProxyModel *proxyModel, const QString &filterText, int options);
91+
92+
} // namespace CutterSearchableHelper
8393

8494
#endif // CUTTERSEARCHABLE_H

src/dialogs/TypesVariablesDialog.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "TypesVariablesDialog.h"
22
#include "ui_TypesVariablesDialog.h"
3+
#include "common/CutterSearchable.h"
34

45
QString toString(VariableScope scope)
56
{
@@ -160,8 +161,10 @@ TypesVariablesDialog::TypesVariablesDialog(QWidget *parent, const QString &typeN
160161

161162
auto updateCount = [this]() { tree->showItemsNumber(proxyModel->rowCount()); };
162163

163-
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, proxyModel,
164-
&TypesVariablesProxyModel::setFilterFixedString);
164+
connect(ui->quickFilterView, &ComboQuickFilterView::filterChanged, this,
165+
[this](const QString &text, int options) {
166+
CutterSearchableHelper::applyFilter(proxyModel, text, options);
167+
});
165168
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this, updateCount);
166169

167170
connect(scopeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,

src/widgets/ComboQuickFilterView.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,40 @@
11
#include "ComboQuickFilterView.h"
22
#include "ui_ComboQuickFilterView.h"
3+
#include "common/CutterSearchable.h"
4+
#include <QMenu>
35

46
ComboQuickFilterView::ComboQuickFilterView(QWidget *parent)
57
: QWidget(parent), ui(new Ui::ComboQuickFilterView)
68
{
79
ui->setupUi(this);
810

11+
QMenu *optionsMenu = new QMenu(this);
12+
m_caseSensitiveAction = optionsMenu->addAction(tr("&Case Sensitive"));
13+
m_caseSensitiveAction->setCheckable(true);
14+
15+
m_wholeWordsAction = optionsMenu->addAction(tr("Exact Match"));
16+
m_wholeWordsAction->setCheckable(true);
17+
18+
m_regexAction = optionsMenu->addAction(tr("Regular Expression"));
19+
m_regexAction->setCheckable(true);
20+
21+
auto emitFilterChanged = [this]() {
22+
emit filterChanged(ui->lineEdit->text(), filterOptions());
23+
};
24+
connect(m_caseSensitiveAction, &QAction::triggered, this, emitFilterChanged);
25+
connect(m_wholeWordsAction, &QAction::triggered, this, emitFilterChanged);
26+
connect(m_regexAction, &QAction::triggered, this, emitFilterChanged);
27+
28+
QAction *optionsAction = new QAction(this);
29+
optionsAction->setIcon(QIcon(":/img/icons/cog_light.svg"));
30+
optionsAction->setMenu(optionsMenu);
31+
ui->lineEdit->addAction(optionsAction, QLineEdit::LeadingPosition);
32+
933
debounceTimer = new QTimer(this);
1034
debounceTimer->setSingleShot(true);
1135

1236
connect(debounceTimer, &QTimer::timeout, this,
13-
[this]() { emit filterTextChanged(ui->lineEdit->text()); });
37+
[this]() { emit filterChanged(ui->lineEdit->text(), filterOptions()); });
1438

1539
connect(ui->lineEdit, &QLineEdit::textChanged, this, [this]() { debounceTimer->start(150); });
1640
}
@@ -47,3 +71,18 @@ void ComboQuickFilterView::closeFilter()
4771
hide();
4872
emit filterClosed();
4973
}
74+
75+
int ComboQuickFilterView::filterOptions() const
76+
{
77+
int options = 0;
78+
if (m_caseSensitiveAction->isChecked()) {
79+
options |= CaseSensitive;
80+
}
81+
if (m_wholeWordsAction->isChecked()) {
82+
options |= WholeWords;
83+
}
84+
if (m_regexAction->isChecked()) {
85+
options |= RegExp;
86+
}
87+
return options;
88+
}

src/widgets/ComboQuickFilterView.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <QWidget>
77
#include <QComboBox>
88
#include <QTimer>
9+
#include <QAction>
910

1011
namespace Ui {
1112
class ComboQuickFilterView;
@@ -29,11 +30,18 @@ public slots:
2930

3031
signals:
3132
void filterTextChanged(const QString &text);
33+
void filterChanged(const QString &text, int options);
3234
void filterClosed();
3335

3436
private:
3537
Ui::ComboQuickFilterView *ui;
3638
QTimer *debounceTimer;
39+
40+
QAction *m_caseSensitiveAction;
41+
QAction *m_wholeWordsAction;
42+
QAction *m_regexAction;
43+
44+
int filterOptions() const;
3745
};
3846

3947
#endif // COMBOQUICKFILTERVIEW_H

src/widgets/GlobalsWidget.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "ui_GlobalsWidget.h"
33
#include "core/MainWindow.h"
44
#include "common/Helpers.h"
5+
#include "common/CutterSearchable.h"
56
#include "dialogs/GlobalVariableDialog.h"
67
#include "shortcuts/ShortcutManager.h"
78

@@ -170,8 +171,10 @@ GlobalsWidget::GlobalsWidget(MainWindow *main)
170171
// Setup custom context menu
171172
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
172173

173-
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, globalsProxyModel,
174-
&QSortFilterProxyModel::setFilterWildcard);
174+
connect(ui->quickFilterView, &ComboQuickFilterView::filterChanged, this,
175+
[this](const QString &text, int options) {
176+
CutterSearchableHelper::applyFilter(globalsProxyModel, text, options);
177+
});
175178

176179
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this,
177180
[this] { tree->showItemsNumber(globalsProxyModel->rowCount()); });

src/widgets/ListDockWidget.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "ui_ListDockWidget.h"
33
#include "core/MainWindow.h"
44
#include "common/Helpers.h"
5+
#include "common/CutterSearchable.h"
56
#include "shortcuts/ShortcutManager.h"
67

78
#include <QMenu>
@@ -57,8 +58,10 @@ void ListDockWidget::setModels(AddressableFilterProxyModel *objectFilterProxyMod
5758

5859
ui->treeView->setModel(objectFilterProxyModel);
5960

60-
connect(ui->quickFilterView, &QuickFilterView::filterTextChanged, objectFilterProxyModel,
61-
&QSortFilterProxyModel::setFilterWildcard);
61+
connect(ui->quickFilterView, &QuickFilterView::filterChanged, this,
62+
[=](const QString &text, int options) {
63+
CutterSearchableHelper::applyFilter(objectFilterProxyModel, text, options);
64+
});
6265
connect(ui->quickFilterView, &QuickFilterView::filterClosed, ui->treeView,
6366
static_cast<void (QWidget::*)()>(&QWidget::setFocus));
6467

src/widgets/ProcessesWidget.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "ProcessesWidget.h"
33
#include "ui_ProcessesWidget.h"
44
#include "common/JsonModel.h"
5+
#include "common/CutterSearchable.h"
56
#include "QuickFilterView.h"
67
#include <rz_debug.h>
78

@@ -49,8 +50,10 @@ ProcessesWidget::ProcessesWidget(MainWindow *main)
4950

5051
refreshDeferrer = createRefreshDeferrer([this]() { updateContents(); });
5152

52-
connect(ui->quickFilterView, &QuickFilterView::filterTextChanged, modelFilter,
53-
&ProcessesFilterModel::setFilterWildcard);
53+
connect(ui->quickFilterView, &QuickFilterView::filterChanged, this,
54+
[this](const QString &text, int options) {
55+
CutterSearchableHelper::applyFilter(modelFilter, text, options);
56+
});
5457
connect(Core(), &CutterCore::refreshAll, this, &ProcessesWidget::updateContents);
5558
connect(Core(), &CutterCore::registersChanged, this, &ProcessesWidget::updateContents);
5659
connect(Core(), &CutterCore::debugTaskStateChanged, this, &ProcessesWidget::updateContents);

src/widgets/QuickFilterView.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,35 @@
1-
21
#include "QuickFilterView.h"
32
#include "ui_QuickFilterView.h"
3+
#include "common/CutterSearchable.h"
4+
#include <QMenu>
45

56
QuickFilterView::QuickFilterView(QWidget *parent, bool defaultOn)
67
: QWidget(parent), ui(new Ui::QuickFilterView())
78
{
89
ui->setupUi(this);
910

11+
QMenu *optionsMenu = new QMenu(this);
12+
m_caseSensitiveAction = optionsMenu->addAction(tr("&Case Sensitive"));
13+
m_caseSensitiveAction->setCheckable(true);
14+
15+
m_wholeWordsAction = optionsMenu->addAction(tr("Exact Match"));
16+
m_wholeWordsAction->setCheckable(true);
17+
18+
m_regexAction = optionsMenu->addAction(tr("Regular Expression"));
19+
m_regexAction->setCheckable(true);
20+
21+
auto emitFilterChanged = [this]() {
22+
emit filterChanged(ui->filterLineEdit->text(), filterOptions());
23+
};
24+
connect(m_caseSensitiveAction, &QAction::triggered, this, emitFilterChanged);
25+
connect(m_wholeWordsAction, &QAction::triggered, this, emitFilterChanged);
26+
connect(m_regexAction, &QAction::triggered, this, emitFilterChanged);
27+
28+
QAction *optionsAction = new QAction(this);
29+
optionsAction->setIcon(QIcon(":/img/icons/cog_light.svg"));
30+
optionsAction->setMenu(optionsMenu);
31+
ui->filterLineEdit->addAction(optionsAction, QLineEdit::LeadingPosition);
32+
1033
debounceTimer = new QTimer(this);
1134
debounceTimer->setSingleShot(true);
1235

@@ -46,3 +69,18 @@ void QuickFilterView::closeFilter()
4669
hide();
4770
emit filterClosed();
4871
}
72+
73+
int QuickFilterView::filterOptions() const
74+
{
75+
int options = 0;
76+
if (m_caseSensitiveAction->isChecked()) {
77+
options |= CaseSensitive;
78+
}
79+
if (m_wholeWordsAction->isChecked()) {
80+
options |= WholeWords;
81+
}
82+
if (m_regexAction->isChecked()) {
83+
options |= RegExp;
84+
}
85+
return options;
86+
}

0 commit comments

Comments
 (0)