diff options
| author | Al <gabriel.cortesi@outlook.com> | 2019-06-01 09:54:09 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-06-01 09:54:09 +0200 |
| commit | f00314442b9c3c28e846c64da3c3f776e50656de (patch) | |
| tree | 371f52175eaa83db0b3b354b95d382bd7080ca38 /src/filterwidget.cpp | |
| parent | 41f8da011d1df7a368e3fb73f972cee1f4efd0c0 (diff) | |
| parent | d2eb890f2b9df13c402db6adeaafa7e3f4a7d736 (diff) | |
Merge pull request #740 from isanae/new-conflict-list
New conflict list, new "go to" conflict menu item
Diffstat (limited to 'src/filterwidget.cpp')
| -rw-r--r-- | src/filterwidget.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/filterwidget.cpp b/src/filterwidget.cpp new file mode 100644 index 00000000..16a46b0e --- /dev/null +++ b/src/filterwidget.cpp @@ -0,0 +1,144 @@ +#include "filterwidget.h" +#include "eventfilter.h" + +FilterWidget::FilterWidget() + : m_edit(nullptr), m_eventFilter(nullptr), m_clear(nullptr) +{ +} + +void FilterWidget::set(QLineEdit* edit) +{ + unhook(); + + m_edit = edit; + + if (!m_edit) { + return; + } + + createClear(); + hookEvents(); + clear(); +} + +void FilterWidget::clear() +{ + if (!m_edit) { + return; + } + + m_edit->clear(); +} + +bool FilterWidget::matches(std::function<bool (const QString& what)> pred) const +{ + 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() +{ + 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); + + 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() +{ + m_eventFilter = new EventFilter(m_edit, [&](auto* w, auto* e) { + if (e->type() == QEvent::Resize) { + onResized(); + } + + return false; + }); + + 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() +{ + 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); +} |
