From 4d90e502266dfb886e1d089fb26780d19a38e5a7 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 29 May 2019 09:45:30 -0400 Subject: added new filterwidget, will eventually get the operators functionality from the mod/pluging lists --- src/filterwidget.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/filterwidget.cpp (limited to 'src/filterwidget.cpp') diff --git a/src/filterwidget.cpp b/src/filterwidget.cpp new file mode 100644 index 00000000..39324bc6 --- /dev/null +++ b/src/filterwidget.cpp @@ -0,0 +1,88 @@ +#include "filterwidget.h" +#include "eventfilter.h" + +FilterWidget::FilterWidget() + : m_edit(nullptr), m_clear(nullptr), m_buddy(nullptr) +{ +} + +void FilterWidget::set(QLineEdit* edit) +{ + if (m_clear) { + delete m_clear; + m_clear = nullptr; + } + + m_edit = edit; + if (!m_edit) { + return; + } + + createClear(); + hookEvents(); +} + +void FilterWidget::clear() +{ + if (!m_edit) { + return; + } + + m_edit->clear(); +} + +void FilterWidget::createClear() +{ + m_clear = new QToolButton(m_edit); + + QPixmap pixmap(":/MO/gui/edit_clear"); + m_clear->setIcon(QIcon(pixmap)); + m_clear->setIconSize(pixmap.size()); + m_clear->setCursor(Qt::ArrowCursor); + m_clear->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + m_clear->hide(); + + QObject::connect(m_clear, &QToolButton::clicked, [&]{ clear(); }); + QObject::connect(m_edit, &QLineEdit::textChanged, [&]{ onTextChanged(); }); + + repositionClearButton(); +} + +void FilterWidget::hookEvents() +{ + auto* f = new EventFilter(m_edit, [&](auto* w, auto* e) { + if (e->type() == QEvent::Resize) { + onResized(); + } + + return false; + }); + + m_edit->installEventFilter(f); +} + +void FilterWidget::onTextChanged() +{ + m_clear->setVisible(!m_edit->text().isEmpty()); +} + +void FilterWidget::onResized() +{ + repositionClearButton(); +} + +void FilterWidget::repositionClearButton() +{ + if (!m_clear) { + return; + } + + const QSize sz = m_clear->sizeHint(); + const int frame = m_edit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + const auto r = m_edit->rect(); + + const auto x = r.right() - frame - sz.width(); + const auto y = (r.bottom() + 1 - sz.height()) / 2; + + m_clear->move(x, y); +} -- cgit v1.3.1 From 98b3be3e9bbca73640842f6dadaa159dcec04f7b Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 29 May 2019 10:08:46 -0400 Subject: removed buddy from FilterWidget, the intention was to hook a ctrl+f shortcut to it, but that won't work as a general solution, it would need to be on tabs for the modinfo dialog added a simple matches() that just searches for the string FilterWidget can cleanly unhook itself --- src/filterwidget.cpp | 40 +++++++++++++++++++++++++++++++++------- src/filterwidget.h | 12 +++++++++--- src/modinfodialog.cpp | 7 +++++++ 3 files changed, 49 insertions(+), 10 deletions(-) (limited to 'src/filterwidget.cpp') diff --git a/src/filterwidget.cpp b/src/filterwidget.cpp index 39324bc6..7c47980e 100644 --- a/src/filterwidget.cpp +++ b/src/filterwidget.cpp @@ -2,24 +2,23 @@ #include "eventfilter.h" FilterWidget::FilterWidget() - : m_edit(nullptr), m_clear(nullptr), m_buddy(nullptr) + : m_edit(nullptr), m_eventFilter(nullptr), m_clear(nullptr) { } void FilterWidget::set(QLineEdit* edit) { - if (m_clear) { - delete m_clear; - m_clear = nullptr; - } + unhook(); m_edit = edit; + if (!m_edit) { return; } createClear(); hookEvents(); + clear(); } void FilterWidget::clear() @@ -31,6 +30,23 @@ void FilterWidget::clear() m_edit->clear(); } +bool FilterWidget::matches(const QString& s) const +{ + return s.contains(m_text); +} + +void FilterWidget::unhook() +{ + if (m_clear) { + delete m_clear; + m_clear = nullptr; + } + + if (m_edit) { + m_edit->removeEventFilter(m_eventFilter); + } +} + void FilterWidget::createClear() { m_clear = new QToolButton(m_edit); @@ -50,7 +66,7 @@ void FilterWidget::createClear() void FilterWidget::hookEvents() { - auto* f = new EventFilter(m_edit, [&](auto* w, auto* e) { + m_eventFilter = new EventFilter(m_edit, [&](auto* w, auto* e) { if (e->type() == QEvent::Resize) { onResized(); } @@ -58,12 +74,22 @@ void FilterWidget::hookEvents() return false; }); - m_edit->installEventFilter(f); + m_edit->installEventFilter(m_eventFilter); } void FilterWidget::onTextChanged() { m_clear->setVisible(!m_edit->text().isEmpty()); + + const auto text = m_edit->text(); + + if (text != m_text) { + m_text = text; + + if (changed) { + changed(); + } + } } void FilterWidget::onResized() diff --git a/src/filterwidget.h b/src/filterwidget.h index 07e216f1..ca731dc1 100644 --- a/src/filterwidget.h +++ b/src/filterwidget.h @@ -1,21 +1,27 @@ #ifndef FILTERWIDGET_H #define FILTERWIDGET_H +class EventFilter; + class FilterWidget { public: + std::function changed; + FilterWidget(); void set(QLineEdit* edit); - void buddy(QWidget* w); - void clear(); + bool matches(const QString& s) const; + private: QLineEdit* m_edit; + EventFilter* m_eventFilter; QToolButton* m_clear; - QWidget* m_buddy; + QString m_text; + void unhook(); void createClear(); void hookEvents(); void repositionClearButton(); diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 1e933a74..0f18033a 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -454,6 +454,7 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo m_advancedConflictFilter.set(ui->conflictsAdvancedFilter); + m_advancedConflictFilter.changed = [&]{ refreshConflictLists(false, true); }; // left-elide the overwrites column so that the nearest are visible ui->conflictsAdvancedList->setItemDelegateForColumn( @@ -873,6 +874,12 @@ QTreeWidgetItem* ModInfoDialog::createAdvancedConflictItem( } } + if (!m_advancedConflictFilter.matches(before) && + !m_advancedConflictFilter.matches(relativeName) && + !m_advancedConflictFilter.matches(after)) { + return nullptr; + } + QTreeWidgetItem* item = new QTreeWidgetItem; item->setText(0, before); item->setText(1, relativeName); -- cgit v1.3.1 From 8efab8bf129b6f9928f478a429e20cf018e5e373 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 31 May 2019 10:54:36 -0400 Subject: FilterWidget takes a predicate to match strings copied the logic from modlistsortproxy so the basic boolean syntax in filters works --- src/filterwidget.cpp | 34 ++++++++++++++++++++++++++++++++-- src/filterwidget.h | 2 +- src/modinfodialog.cpp | 13 +++++++++---- 3 files changed, 42 insertions(+), 7 deletions(-) (limited to 'src/filterwidget.cpp') diff --git a/src/filterwidget.cpp b/src/filterwidget.cpp index 7c47980e..16a46b0e 100644 --- a/src/filterwidget.cpp +++ b/src/filterwidget.cpp @@ -30,9 +30,39 @@ void FilterWidget::clear() m_edit->clear(); } -bool FilterWidget::matches(const QString& s) const +bool FilterWidget::matches(std::function pred) const { - return s.contains(m_text); + const QStringList ORList = [&] { + QString filterCopy = QString(m_text); + filterCopy.replace("||", ";").replace("OR", ";").replace("|", ";"); + return filterCopy.split(";", QString::SkipEmptyParts); + }(); + + if (ORList.isEmpty() || !pred) { + return true; + } + + // split in ORSegments that internally use AND logic + for (auto& ORSegment : ORList) { + QStringList ANDKeywords = ORSegment.split(" ", QString::SkipEmptyParts); + bool segmentGood = true; + + // check each word in the segment for match, each word needs to be matched + // but it doesn't matter where. + for (auto& currentKeyword : ANDKeywords) { + if (!pred(currentKeyword)) { + segmentGood = false; + } + } + + if (segmentGood) { + // the last AND loop didn't break so the ORSegments is true so mod + // matches filter + return true; + } + } + + return false; } void FilterWidget::unhook() diff --git a/src/filterwidget.h b/src/filterwidget.h index ca731dc1..4fee5983 100644 --- a/src/filterwidget.h +++ b/src/filterwidget.h @@ -13,7 +13,7 @@ public: void set(QLineEdit* edit); void clear(); - bool matches(const QString& s) const; + bool matches(std::function pred) const; private: QLineEdit* m_edit; diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 0f18033a..4852150f 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -874,10 +874,15 @@ QTreeWidgetItem* ModInfoDialog::createAdvancedConflictItem( } } - if (!m_advancedConflictFilter.matches(before) && - !m_advancedConflictFilter.matches(relativeName) && - !m_advancedConflictFilter.matches(after)) { - return nullptr; + bool matched = m_advancedConflictFilter.matches([&](auto&& what) { + return + before.contains(what, Qt::CaseInsensitive) || + relativeName.contains(what, Qt::CaseInsensitive) || + after.contains(what, Qt::CaseInsensitive); + }); + + if (!matched) { + return nullptr; } QTreeWidgetItem* item = new QTreeWidgetItem; -- cgit v1.3.1