aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-03 16:31:34 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:53:39 +0200
commite36115208f588ea90483b7da93378bbb71155cce (patch)
tree1e071cbf364619d96f67fb44d426fe9f6207bc2b /src
parent0364f7d48813a350e9c02d78e652f6b58c31abec (diff)
downloadqtmaildir-e36115208f588ea90483b7da93378bbb71155cce.tar.gz
qtmaildir-e36115208f588ea90483b7da93378bbb71155cce.zip
feat: choose the startup query by name
The app opened whichever saved query sorted first alphabetically, which is not a choice anyone made: [queries] is read through childKeys(), so savedQueries().first() means "Flagged" before "Inbox" before "Unread" rather than anything the user expressed. [general] startup_query names the entry to open and defaults to Unread, so a fresh install comes up on the unified unread list. Saved-query button order is untouched and stays alphabetical. A name matching no saved query falls back to the first one rather than starting with an empty view. That is reported as a problem only when the user actually wrote the name; the built-in default naming a query they never created is not something they got wrong, and warning about it would fire on every launch of a config that has no Unread entry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src')
-rw-r--r--src/config.cpp36
-rw-r--r--src/config.h18
-rw-r--r--src/mainwindow.cpp8
3 files changed, 60 insertions, 2 deletions
diff --git a/src/config.cpp b/src/config.cpp
index a2caaee..e92c7f3 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -66,6 +66,14 @@ void Config::load(const QString &path)
// is a problem, since the user asked for something and is not getting it.
// The range check lives in MessageView::clampZoom(), the one place that
// knows what the web view can render.
+ // Empty is treated as unset rather than as "a query named nothing".
+ const QString startup =
+ settings.value(QStringLiteral("startup_query")).toString().trimmed();
+ if (!startup.isEmpty()) {
+ m_startupQuery = startup;
+ m_startupQueryWasSet = true;
+ }
+
const QVariant zoom = settings.value(QStringLiteral("message_zoom"));
if (zoom.isValid()) {
bool ok = false;
@@ -149,6 +157,34 @@ void Config::load(const QString &path)
for (const QString &name : settings.childKeys())
m_savedQueries.append({ name, settings.value(name).toString() });
settings.endGroup();
+
+ // Checked here rather than where startup_query is read: [queries] is not
+ // parsed until now. Only a name the user actually wrote is worth a
+ // problem; the built-in default naming a query they never created is not
+ // something they got wrong.
+ if (m_startupQueryWasSet && !m_savedQueries.isEmpty()
+ && startupSavedQuery().name.compare(m_startupQuery,
+ Qt::CaseInsensitive) != 0) {
+ addProblem(QStringLiteral("Startup query '%1' is not a saved query; "
+ "opening '%2' instead.")
+ .arg(m_startupQuery, startupSavedQuery().name));
+ }
+}
+
+SavedQuery Config::startupSavedQuery() const
+{
+ if (m_savedQueries.isEmpty())
+ return {};
+
+ for (const SavedQuery &query : m_savedQueries) {
+ if (query.name.compare(m_startupQuery, Qt::CaseInsensitive) == 0)
+ return query;
+ }
+
+ // Named a query that does not exist. Not worth a warning: the default is
+ // a name the user never wrote, so an install with no [queries] Unread
+ // entry would warn on every launch about a key it never set.
+ return m_savedQueries.first();
}
Account Config::account(const QString &key) const
diff --git a/src/config.h b/src/config.h
index 8089d67..f3f1706 100644
--- a/src/config.h
+++ b/src/config.h
@@ -78,6 +78,18 @@ public:
/// Optional alternate notmuch config file. Empty means "let notmuch decide".
QString notmuchConfig() const { return m_notmuchConfig; }
+ /// The saved query to open at startup, by name. Falls back to "Unread"
+ /// when unset, and to the first saved query when no query by that name
+ /// exists: [queries] is read through childKeys(), which sorts
+ /// alphabetically, so "first" would otherwise mean whatever happens to
+ /// sort first rather than anything the user chose.
+ QString startupQuery() const { return m_startupQuery; }
+
+ /// The saved query startupQuery() names, or the first one when it names
+ /// nothing that exists. A default-constructed SavedQuery when there are
+ /// none at all.
+ SavedQuery startupSavedQuery() const;
+
/// Starting message-pane zoom for a profile with no saved UI state. Once
/// the user zooms, the state file remembers that instead, so this is only
/// ever the default. Clamped by MessageView::clampZoom() on use.
@@ -107,6 +119,12 @@ private:
QString m_syncCommand;
QString m_notmuchConfig;
qreal m_messageZoom = 1.0;
+ QString m_startupQuery = QStringLiteral("Unread");
+
+ /// Whether startup_query came from the config rather than being the
+ /// built-in default. Only a name the user wrote is worth reporting when
+ /// it matches no saved query.
+ bool m_startupQueryWasSet = false;
QStringList m_warnings;
QStringList m_problems;
};
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index c4955b6..2a79988 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -171,8 +171,12 @@ MainWindow::MainWindow(const Config &config, QWidget *parent)
// modifier shortcuts such as Ctrl+Q still work there, which the old
// filter blocked.
- if (!m_config.savedQueries().isEmpty()) {
- m_queryEdit->setText(m_config.savedQueries().first().query);
+ // Not savedQueries().first(): [queries] is read through childKeys(), which
+ // sorts alphabetically, so "first" means whatever happens to sort first
+ // rather than anything the user chose. Config resolves the name.
+ const SavedQuery startup = m_config.startupSavedQuery();
+ if (!startup.query.isEmpty()) {
+ m_queryEdit->setText(startup.query);
runCurrentQuery();
}
}