summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/filterwidget.cpp70
-rw-r--r--src/filterwidget.h41
-rw-r--r--src/modinfodialog.ui8
-rw-r--r--src/modinfodialogconflicts.cpp4
-rw-r--r--src/modinfodialogtextfiles.cpp13
-rw-r--r--src/modinfodialogtextfiles.h4
6 files changed, 123 insertions, 17 deletions
diff --git a/src/filterwidget.cpp b/src/filterwidget.cpp
index 82644658..1b9efd7c 100644
--- a/src/filterwidget.cpp
+++ b/src/filterwidget.cpp
@@ -1,12 +1,41 @@
#include "filterwidget.h"
#include "eventfilter.h"
-FilterWidget::FilterWidget()
- : m_edit(nullptr), m_eventFilter(nullptr), m_clear(nullptr)
+FilterWidgetProxyModel::FilterWidgetProxyModel(FilterWidget& fw, QWidget* parent)
+ : QSortFilterProxyModel(parent), m_filter(fw)
{
+ connect(&fw, &FilterWidget::changed, [&]{ invalidateFilter(); });
}
-void FilterWidget::set(QLineEdit* edit)
+bool FilterWidgetProxyModel::filterAcceptsRow(
+ int sourceRow, const QModelIndex& sourceParent) const
+{
+ const auto cols = sourceModel()->columnCount();
+
+ const auto m = m_filter.matches([&](auto&& what) {
+ for (int c=0; c<cols; ++c) {
+ QModelIndex index = sourceModel()->index(sourceRow, c, sourceParent);
+ const auto text = sourceModel()->data(index, Qt::DisplayRole).toString();
+
+ if (text.contains(what, Qt::CaseInsensitive)) {
+ return true;
+ }
+ }
+
+ return false;
+ });
+
+ return m;
+}
+
+
+FilterWidget::FilterWidget() :
+ m_edit(nullptr), m_list(nullptr), m_proxy(nullptr),
+ m_eventFilter(nullptr), m_clear(nullptr)
+{
+}
+
+void FilterWidget::setEdit(QLineEdit* edit)
{
unhook();
@@ -16,11 +45,22 @@ void FilterWidget::set(QLineEdit* edit)
return;
}
+ m_edit->setPlaceholderText(QObject::tr("Filter"));
+
createClear();
hookEvents();
clear();
}
+void FilterWidget::setList(QAbstractItemView* list)
+{
+ m_list = list;
+
+ m_proxy = new FilterWidgetProxyModel(*this);
+ m_proxy->setSourceModel(m_list->model());
+ m_list->setModel(m_proxy);
+}
+
void FilterWidget::clear()
{
if (!m_edit) {
@@ -30,6 +70,16 @@ void FilterWidget::clear()
m_edit->clear();
}
+QModelIndex FilterWidget::map(const QModelIndex& index)
+{
+ if (m_proxy) {
+ return m_proxy->mapToSource(index);
+ } else {
+ qCritical() << "FilterWidget::map() called, but proxy isn't set up";
+ return index;
+ }
+}
+
void FilterWidget::compile()
{
m_compiled.clear();
@@ -83,6 +133,14 @@ void FilterWidget::unhook()
if (m_edit) {
m_edit->removeEventFilter(m_eventFilter);
}
+
+ if (m_proxy && m_list) {
+ auto* model = m_proxy->sourceModel();
+ m_proxy->setSourceModel(nullptr);
+ delete m_proxy;
+
+ m_list->setModel(model);
+ }
}
void FilterWidget::createClear()
@@ -125,9 +183,11 @@ void FilterWidget::onTextChanged()
m_text = text;
compile();
- if (changed) {
- changed();
+ if (m_proxy) {
+ m_proxy->invalidateFilter();
}
+
+ emit changed();
}
}
diff --git a/src/filterwidget.h b/src/filterwidget.h
index 762d9b15..5b08c3ae 100644
--- a/src/filterwidget.h
+++ b/src/filterwidget.h
@@ -1,22 +1,55 @@
#ifndef FILTERWIDGET_H
#define FILTERWIDGET_H
+#include <QObject>
+#include <QLineEdit>
+#include <QToolButton>
+#include <QList>
+#include <QAbstractItemView>
+
class EventFilter;
+class FilterWidget;
-class FilterWidget
+class FilterWidgetProxyModel : public QSortFilterProxyModel
{
+ Q_OBJECT;
+
public:
- std::function<void ()> changed;
+ FilterWidgetProxyModel(FilterWidget& fw, QWidget* parent=nullptr);
+ using QSortFilterProxyModel::invalidateFilter;
+
+protected:
+ bool filterAcceptsRow(int row, const QModelIndex& parent) const override;
+
+private:
+ FilterWidget& m_filter;
+};
+
+
+class FilterWidget : public QObject
+{
+ Q_OBJECT;
+
+public:
+ using predFun = std::function<bool (const QString& what)>;
FilterWidget();
- void set(QLineEdit* edit);
+ void setEdit(QLineEdit* edit);
+ void setList(QAbstractItemView* list);
void clear();
- bool matches(std::function<bool (const QString& what)> pred) const;
+ QModelIndex map(const QModelIndex& index);
+
+ bool matches(predFun pred) const;
+
+signals:
+ void changed();
private:
QLineEdit* m_edit;
+ QAbstractItemView* m_list;
+ FilterWidgetProxyModel* m_proxy;
EventFilter* m_eventFilter;
QToolButton* m_clear;
QString m_text;
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui
index 9f4ae873..69e73da4 100644
--- a/src/modinfodialog.ui
+++ b/src/modinfodialog.ui
@@ -72,6 +72,9 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QLineEdit" name="textFileFilter"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="widget_7" native="true">
@@ -108,7 +111,7 @@
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="layoutWidget">
- <layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,0">
+ <layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,0,0">
<property name="spacing">
<number>6</number>
</property>
@@ -132,6 +135,9 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QLineEdit" name="iniFileFilter"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget1">
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index c053e64c..e631db30 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -999,8 +999,8 @@ AdvancedConflictsTab::AdvancedConflictsTab(
ui->conflictsAdvancedList, &QTreeView::customContextMenuRequested,
[&](const QPoint& p){ m_tab->showContextMenu(p, ui->conflictsAdvancedList); });
- m_filter.set(ui->conflictsAdvancedFilter);
- m_filter.changed = [&]{ update(); };
+ m_filter.setEdit(ui->conflictsAdvancedFilter);
+ QObject::connect(&m_filter, &FilterWidget::changed, [&]{ update(); });
}
void AdvancedConflictsTab::clear()
diff --git a/src/modinfodialogtextfiles.cpp b/src/modinfodialogtextfiles.cpp
index 675a4c79..2b5ab489 100644
--- a/src/modinfodialogtextfiles.cpp
+++ b/src/modinfodialogtextfiles.cpp
@@ -100,7 +100,7 @@ private:
GenericFilesTab::GenericFilesTab(
OrganizerCore& oc, PluginContainer& plugin,
QWidget* parent, Ui::ModInfoDialog* ui, int id,
- QListView* list, QSplitter* sp, TextEditor* e) :
+ QListView* list, QSplitter* sp, TextEditor* e, QLineEdit* filter) :
ModInfoDialogTab(oc, plugin, parent, ui, id),
m_list(list), m_editor(e), m_model(new FileListModel)
{
@@ -111,6 +111,9 @@ GenericFilesTab::GenericFilesTab(
sp->setStretchFactor(0, 0);
sp->setStretchFactor(1, 1);
+ m_filter.setEdit(filter);
+ m_filter.setList(m_list);
+
QObject::connect(
m_list->selectionModel(), &QItemSelectionModel::currentRowChanged,
[&](auto current, auto previous){ onSelection(current, previous); });
@@ -187,7 +190,7 @@ void GenericFilesTab::select(const QModelIndex& index)
}
m_editor->setEnabled(true);
- m_editor->load(m_model->fullPath(index));
+ m_editor->load(m_model->fullPath(m_filter.map(index)));
}
@@ -196,7 +199,8 @@ TextFilesTab::TextFilesTab(
QWidget* parent, Ui::ModInfoDialog* ui, int id)
: GenericFilesTab(
oc, plugin, parent, ui, id,
- ui->textFileList, ui->tabTextSplitter, ui->textFileEditor)
+ ui->textFileList, ui->tabTextSplitter,
+ ui->textFileEditor, ui->textFileFilter)
{
}
@@ -218,7 +222,8 @@ IniFilesTab::IniFilesTab(
QWidget* parent, Ui::ModInfoDialog* ui, int id)
: GenericFilesTab(
oc, plugin, parent, ui, id,
- ui->iniFileList, ui->tabIniSplitter, ui->iniFileEditor)
+ ui->iniFileList, ui->tabIniSplitter,
+ ui->iniFileEditor, ui->iniFileFilter)
{
}
diff --git a/src/modinfodialogtextfiles.h b/src/modinfodialogtextfiles.h
index d879c2bd..037c6bb3 100644
--- a/src/modinfodialogtextfiles.h
+++ b/src/modinfodialogtextfiles.h
@@ -2,6 +2,7 @@
#define MODINFODIALOGTEXTFILES_H
#include "modinfodialogtab.h"
+#include "filterwidget.h"
#include <QSplitter>
#include <QListView>
@@ -23,11 +24,12 @@ protected:
QListView* m_list;
TextEditor* m_editor;
FileListModel* m_model;
+ FilterWidget m_filter;
GenericFilesTab(
OrganizerCore& oc, PluginContainer& plugin,
QWidget* parent, Ui::ModInfoDialog* ui, int id,
- QListView* list, QSplitter* splitter, TextEditor* editor);
+ QListView* list, QSplitter* splitter, TextEditor* editor, QLineEdit* filter);
virtual bool wantsFile(const QString& rootPath, const QString& fullPath) const = 0;