Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/common/CutterSearchable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <QObject>
#include <QAbstractScrollArea>
#include <QScrollBar>
#include <QSortFilterProxyModel>
#include <QRegularExpression>

void CutterSearchableHelper::setupConnections(QWidget *parent, SearchBarWidget *searchBar)
{
Expand Down Expand Up @@ -75,3 +77,39 @@ void CutterSearchableHelper::positionSearchBar(QWidget *parent, SearchBarWidget

searchBar->move(x, y);
}

void CutterSearchableHelper::applyFilter(QSortFilterProxyModel *proxyModel,
const QString &filterText, int options)
{
if (!proxyModel) {
return;
}

if (filterText.isEmpty()) {
proxyModel->setFilterFixedString(QString());
return;
}

QRegularExpression::PatternOptions patternOptions;
if (!(options & CaseSensitive)) {
patternOptions |= QRegularExpression::CaseInsensitiveOption;
}

if (options & RegExp) {
QRegularExpression regExp(filterText, patternOptions);
Comment thread
RealAhmedKhairi marked this conversation as resolved.
if (regExp.isValid()) {
proxyModel->setFilterRegularExpression(regExp);
}
} else if (options & WholeWords) {
QString pattern = QString("\\b%1\\b").arg(QRegularExpression::escape(filterText));
QRegularExpression regExp(pattern, patternOptions);
Comment thread
RealAhmedKhairi marked this conversation as resolved.
if (regExp.isValid()) {
proxyModel->setFilterRegularExpression(regExp);
}
} else {
proxyModel->setFilterCaseSensitivity((options & CaseSensitive)
? Qt::CaseSensitive
: Qt::CaseInsensitive);
proxyModel->setFilterWildcard(filterText);
}
}
12 changes: 11 additions & 1 deletion src/common/CutterSearchable.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define CUTTERSEARCHABLE_H

class QString;
class QSortFilterProxyModel;
class SearchBarWidget;
class QWidget;

Expand Down Expand Up @@ -79,6 +80,15 @@ void setupConnections(QWidget *parent, SearchBarWidget *bar);
*/
void positionSearchBar(QWidget *parent, SearchBarWidget *searchBar, QWidget *searchArea,
int hPadding, int vPadding);
};

/**
* @brief Applies filter options to a proxy model
* @param proxyModel The proxy model to filter
* @param filterText The text to filter by
* @param options Bitwise combination of SearchOption flags (CaseSensitive, WholeWords, RegExp)
*/
void applyFilter(QSortFilterProxyModel *proxyModel, const QString &filterText, int options);

} // namespace CutterSearchableHelper

#endif // CUTTERSEARCHABLE_H
7 changes: 5 additions & 2 deletions src/dialogs/TypesVariablesDialog.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "TypesVariablesDialog.h"
#include "ui_TypesVariablesDialog.h"
#include "common/CutterSearchable.h"

QString toString(VariableScope scope)
{
Expand Down Expand Up @@ -160,8 +161,10 @@ TypesVariablesDialog::TypesVariablesDialog(QWidget *parent, const QString &typeN

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

connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, proxyModel,
&TypesVariablesProxyModel::setFilterFixedString);
connect(ui->quickFilterView, &ComboQuickFilterView::filterChanged, this,
[this](const QString &text, int options) {
CutterSearchableHelper::applyFilter(proxyModel, text, options);
});
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this, updateCount);

connect(scopeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
Expand Down
45 changes: 44 additions & 1 deletion src/widgets/ComboQuickFilterView.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,44 @@
#include "ComboQuickFilterView.h"
#include "ui_ComboQuickFilterView.h"
#include "common/CutterSearchable.h"
#include <QMenu>

ComboQuickFilterView::ComboQuickFilterView(QWidget *parent)
: QWidget(parent), ui(new Ui::ComboQuickFilterView)
{
ui->setupUi(this);

QMenu *optionsMenu = new QMenu(this);
m_caseSensitiveAction = optionsMenu->addAction(tr("&Case Sensitive"));
m_caseSensitiveAction->setCheckable(true);

m_wholeWordsAction = optionsMenu->addAction(tr("Exact Match"));
m_wholeWordsAction->setCheckable(true);

m_regexAction = optionsMenu->addAction(tr("Regular Expression"));
m_regexAction->setCheckable(true);

auto emitFilterChanged = [this]() {
emit filterChanged(ui->lineEdit->text(), filterOptions());
emit filterTextChanged(ui->lineEdit->text());
};
connect(m_caseSensitiveAction, &QAction::triggered, this, emitFilterChanged);
connect(m_wholeWordsAction, &QAction::triggered, this, emitFilterChanged);
connect(m_regexAction, &QAction::triggered, this, emitFilterChanged);

QAction *optionsAction = new QAction(this);
optionsAction->setIcon(QIcon(":/img/icons/cog_light.svg"));
optionsAction->setMenu(optionsMenu);
ui->lineEdit->addAction(optionsAction, QLineEdit::LeadingPosition);

debounceTimer = new QTimer(this);
debounceTimer->setSingleShot(true);

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

connect(ui->lineEdit, &QLineEdit::textChanged, this, [this]() { debounceTimer->start(150); });
}
Expand Down Expand Up @@ -47,3 +75,18 @@ void ComboQuickFilterView::closeFilter()
hide();
emit filterClosed();
}

int ComboQuickFilterView::filterOptions() const
{
int options = 0;
if (m_caseSensitiveAction->isChecked()) {
options |= CaseSensitive;
}
if (m_wholeWordsAction->isChecked()) {
options |= WholeWords;
}
if (m_regexAction->isChecked()) {
options |= RegExp;
}
return options;
}
8 changes: 8 additions & 0 deletions src/widgets/ComboQuickFilterView.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QWidget>
#include <QComboBox>
#include <QTimer>
#include <QAction>

namespace Ui {
class ComboQuickFilterView;
Expand All @@ -29,11 +30,18 @@ public slots:

signals:
void filterTextChanged(const QString &text);
void filterChanged(const QString &text, int options);
void filterClosed();

private:
Ui::ComboQuickFilterView *ui;
QTimer *debounceTimer;

QAction *m_caseSensitiveAction;
QAction *m_wholeWordsAction;
QAction *m_regexAction;

int filterOptions() const;
};

#endif // COMBOQUICKFILTERVIEW_H
7 changes: 5 additions & 2 deletions src/widgets/GlobalsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ui_GlobalsWidget.h"
#include "core/MainWindow.h"
#include "common/Helpers.h"
#include "common/CutterSearchable.h"
#include "dialogs/GlobalVariableDialog.h"
#include "shortcuts/ShortcutManager.h"

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

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

connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this,
[this] { tree->showItemsNumber(globalsProxyModel->rowCount()); });
Expand Down
7 changes: 5 additions & 2 deletions src/widgets/ListDockWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ui_ListDockWidget.h"
#include "core/MainWindow.h"
#include "common/Helpers.h"
#include "common/CutterSearchable.h"
#include "shortcuts/ShortcutManager.h"

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

ui->treeView->setModel(objectFilterProxyModel);

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

Expand Down
7 changes: 5 additions & 2 deletions src/widgets/ProcessesWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ProcessesWidget.h"
#include "ui_ProcessesWidget.h"
#include "common/JsonModel.h"
#include "common/CutterSearchable.h"
#include "QuickFilterView.h"
#include <rz_debug.h>

Expand Down Expand Up @@ -49,8 +50,10 @@ ProcessesWidget::ProcessesWidget(MainWindow *main)

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

connect(ui->quickFilterView, &QuickFilterView::filterTextChanged, modelFilter,
&ProcessesFilterModel::setFilterWildcard);
connect(ui->quickFilterView, &QuickFilterView::filterChanged, this,
[this](const QString &text, int options) {
CutterSearchableHelper::applyFilter(modelFilter, text, options);
});
connect(Core(), &CutterCore::refreshAll, this, &ProcessesWidget::updateContents);
connect(Core(), &CutterCore::registersChanged, this, &ProcessesWidget::updateContents);
connect(Core(), &CutterCore::debugTaskStateChanged, this, &ProcessesWidget::updateContents);
Expand Down
46 changes: 44 additions & 2 deletions src/widgets/QuickFilterView.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,46 @@

#include "QuickFilterView.h"
#include "ui_QuickFilterView.h"
#include "common/CutterSearchable.h"
#include <QMenu>

QuickFilterView::QuickFilterView(QWidget *parent, bool defaultOn)
: QWidget(parent), ui(new Ui::QuickFilterView())
{
ui->setupUi(this);

QMenu *optionsMenu = new QMenu(this);
m_caseSensitiveAction = optionsMenu->addAction(tr("&Case Sensitive"));
m_caseSensitiveAction->setCheckable(true);

m_wholeWordsAction = optionsMenu->addAction(tr("Exact Match"));
m_wholeWordsAction->setCheckable(true);

m_regexAction = optionsMenu->addAction(tr("Regular Expression"));
m_regexAction->setCheckable(true);

auto emitFilterChanged = [this]() {
emit filterChanged(ui->filterLineEdit->text(), filterOptions());
emit filterTextChanged(ui->filterLineEdit->text());
};
connect(m_caseSensitiveAction, &QAction::triggered, this, emitFilterChanged);
connect(m_wholeWordsAction, &QAction::triggered, this, emitFilterChanged);
connect(m_regexAction, &QAction::triggered, this, emitFilterChanged);

QAction *optionsAction = new QAction(this);
optionsAction->setIcon(QIcon(":/img/icons/cog_light.svg"));
optionsAction->setMenu(optionsMenu);
ui->filterLineEdit->addAction(optionsAction, QLineEdit::LeadingPosition);

debounceTimer = new QTimer(this);
debounceTimer->setSingleShot(true);

connect(ui->closeFilterButton, &QAbstractButton::clicked, this, &QuickFilterView::closeFilter);

connect(debounceTimer, &QTimer::timeout, this,
[this]() { emit filterTextChanged(ui->filterLineEdit->text()); });
[this]() {
emit filterChanged(ui->filterLineEdit->text(), filterOptions());
emit filterTextChanged(ui->filterLineEdit->text());
});

connect(ui->filterLineEdit, &QLineEdit::textChanged, this,
[this]() { debounceTimer->start(150); });
Expand Down Expand Up @@ -46,3 +73,18 @@ void QuickFilterView::closeFilter()
hide();
emit filterClosed();
}

int QuickFilterView::filterOptions() const
{
int options = 0;
if (m_caseSensitiveAction->isChecked()) {
options |= CaseSensitive;
}
if (m_wholeWordsAction->isChecked()) {
options |= WholeWords;
}
if (m_regexAction->isChecked()) {
options |= RegExp;
}
return options;
Comment thread
RealAhmedKhairi marked this conversation as resolved.
}
9 changes: 8 additions & 1 deletion src/widgets/QuickFilterView.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

#ifndef QUICKFILTERVIEW_H
#define QUICKFILTERVIEW_H

Expand All @@ -8,6 +7,7 @@

#include <QWidget>
#include <QTimer>
#include <QAction>

namespace Ui {
class QuickFilterView;
Expand All @@ -28,11 +28,18 @@ public slots:

signals:
void filterTextChanged(const QString &text);
void filterChanged(const QString &text, int options);
void filterClosed();

private:
std::unique_ptr<Ui::QuickFilterView> ui;
QTimer *debounceTimer;

QAction *m_caseSensitiveAction;
QAction *m_wholeWordsAction;
QAction *m_regexAction;

int filterOptions() const;
};

#endif // QUICKFILTERVIEW_H
7 changes: 5 additions & 2 deletions src/widgets/RegisterRefsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ui_RegisterRefsWidget.h"
#include "core/MainWindow.h"
#include "common/Helpers.h"
#include "common/CutterSearchable.h"
#include "shortcuts/ShortcutManager.h"

#include <QJsonObject>
Expand Down Expand Up @@ -150,8 +151,10 @@ RegisterRefsWidget::RegisterRefsWidget(MainWindow *main)
&QuickFilterView::showFilter);
search_shortcut->setContext(Qt::WidgetWithChildrenShortcut);

connect(ui->quickFilterView, &QuickFilterView::filterTextChanged, registerRefProxyModel,
&QSortFilterProxyModel::setFilterWildcard);
connect(ui->quickFilterView, &QuickFilterView::filterChanged, this,
[this](const QString &text, int options) {
CutterSearchableHelper::applyFilter(registerRefProxyModel, text, options);
});
connect(ui->quickFilterView, &QuickFilterView::filterClosed, ui->registerRefTreeView,
[this]() { ui->registerRefTreeView->setFocus(); });
setScrollMode();
Expand Down
7 changes: 5 additions & 2 deletions src/widgets/StringsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ui_StringsWidget.h"
#include "core/MainWindow.h"
#include "common/Helpers.h"
#include "common/CutterSearchable.h"
#include "shortcuts/ShortcutManager.h"

#include <QClipboard>
Expand Down Expand Up @@ -182,8 +183,10 @@ StringsWidget::StringsWidget(MainWindow *main)
auto menu = ui->stringsTreeView->getItemContextMenu();
menu->addAction(ui->actionCopy_String);

connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, proxyModel,
&QSortFilterProxyModel::setFilterWildcard);
connect(ui->quickFilterView, &ComboQuickFilterView::filterChanged, this,
[this](const QString &text, int options) {
CutterSearchableHelper::applyFilter(proxyModel, text, options);
});

connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this,
[this] { tree->showItemsNumber(proxyModel->rowCount()); });
Expand Down
Loading
Loading