summaryrefslogtreecommitdiffstats
path: root/src/mainwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainwindow.cpp')
-rw-r--r--src/mainwindow.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 3d7add2..7ece2f3 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1753,6 +1753,12 @@ void MainWindow::buildSavedQueryRow(QWidget *parent, QVBoxLayout *layout)
auto *box = new QHBoxLayout(row);
box->setContentsMargins(0, 0, 0, 0);
+ // Cleared first: the row is rebuilt wholesale on every saved-query edit, so
+ // the buttons this hash points at are deleted and re-created. Keeping the
+ // old entries would leave dangling pointers that findChild() cannot save us
+ // from, since nothing looks them up by name.
+ m_filterButtons.clear();
+
// The built-in filters come first, in their own fixed order, and they are
// not saved queries: they are shipped, they are not in queries.json, and
// the user cannot edit or delete them (item 93). They are what the row is
@@ -1804,8 +1810,22 @@ void MainWindow::buildSavedQueryRow(QWidget *parent, QVBoxLayout *layout)
// of control than it is.
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ // Checkable so the style draws its own "this is the current view" look,
+ // which is why no colour is chosen here: a hand-picked highlight would
+ // have to be picked twice, once per theme, and would still be wrong
+ // under a third.
+ //
+ // Not auto-exclusive and never toggled by the click itself. The check
+ // state is derived from the query bar in updateFilterButtons(), so a
+ // button that runs a filter and then has its query edited away does not
+ // stay lit. Letting the click set it would make the highlight a record
+ // of what was pressed rather than of what is shown.
+ button->setCheckable(true);
+ button->setFocusPolicy(Qt::NoFocus);
+
connect(button, &QToolButton::clicked, this,
[this, filter]() { runFilter(filter); });
+ m_filterButtons.insert(filter.generated, button);
box->addWidget(button);
}
@@ -1886,6 +1906,22 @@ void MainWindow::buildSavedQueryRow(QWidget *parent, QVBoxLayout *layout)
// query with no pinned ones still needs the row for its menu.
if (contentCount == 0 && unpinned.isEmpty())
row->hide();
+
+ // Connected HERE rather than beside the query bar's other handlers, which
+ // run in registerActions() before this row exists. Both connections are
+ // owned by `row`, so a rebuild disconnects them with the widgets they
+ // update and cannot leave a second copy behind firing at deleted buttons.
+ //
+ // textChanged rather than editingFinished: the highlight has to clear while
+ // the user types, not once they leave the field.
+ connect(m_queryEdit, &QLineEdit::textChanged, row,
+ [this]() { updateFilterButtons(); });
+ // The account is the other half of a filter's resolved query, so switching
+ // account re-resolves it and the highlight has to be recomputed against the
+ // new scope rather than assumed to survive.
+ connect(m_accountBox, &QComboBox::currentIndexChanged, row,
+ [this]() { updateFilterButtons(); });
+ updateFilterButtons();
}
void MainWindow::addSavedQueryActions(QWidget *target, const SavedQuery &saved)
@@ -2048,6 +2084,33 @@ void MainWindow::runFilter(const SavedQuery &filter)
AccountScope::AlreadyScoped);
}
+void MainWindow::updateFilterButtons()
+{
+ const QString current = m_queryEdit->text().trimmed();
+ const QString accountKey = m_accountBox->currentData().toString();
+
+ for (auto it = m_filterButtons.constBegin();
+ it != m_filterButtons.constEnd(); ++it) {
+ const SavedQuery filter = Config::builtinFilter(it.key());
+ const QString resolved = m_config.resolvedQuery(filter, accountKey);
+
+ // An unresolvable filter must never match, or every filter would light
+ // up on an empty query bar. matchNothingQuery() is a real query string
+ // and would compare equal to itself.
+ const bool matches = !current.isEmpty()
+ && resolved != Config::matchNothingQuery()
+ && resolved == current;
+
+ // Blocked, because setChecked() on a checkable QToolButton emits
+ // toggled() and this runs from the query bar's own textChanged: a
+ // handler that ran runFilter() would re-enter the query path on every
+ // keystroke. Nothing connects toggled() today, so this is a guard
+ // against the obvious next edit rather than a fix for a live bug.
+ const QSignalBlocker blocker(it.value());
+ it.value()->setChecked(matches);
+ }
+}
+
void MainWindow::saveCurrentQuery()
{
const QString query = m_queryEdit->text().trimmed();