diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-03 16:31:34 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-03 16:31:34 +0200 |
| commit | 2c33529fb665cb54c31e54230fcb7b2491cf8565 (patch) | |
| tree | 87410a035212f0e8e5997722662803c17a3320d8 /src | |
| parent | 212048782be680e2f99341db6c6460e59c708e7c (diff) | |
| download | qtmaildir-feature/ui-state-persistence.tar.gz qtmaildir-feature/ui-state-persistence.zip | |
feat: choose the startup query by namefeature/ui-state-persistence
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.cpp | 36 | ||||
| -rw-r--r-- | src/config.h | 18 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 8 |
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 3e94249..3b7fc48 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(); } } |
