aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-18 15:46:24 +0200
committerDanilo M. <danix@danix.xyz>2026-09-18 15:46:24 +0200
commit2401dc251a24aada7fb0d95093d7129279551ef3 (patch)
treee8f0a70cf0ab58c917dd903dd25f0b80068fdef8
parent06586027b0f328ba0aa4b2c6c3c77471d72aac52 (diff)
downloadqtmaildir-2401dc251a24aada7fb0d95093d7129279551ef3.tar.gz
qtmaildir-2401dc251a24aada7fb0d95093d7129279551ef3.zip
feat: load the contact store once and feed both consumers
MainWindow reads contactsDir() once while building its UI, holds the result in m_contacts, and hands it to the query bar's completer right after that is constructed and to every ComposeWindow as it opens. An empty contactsDir() skips the call, so a machine with no address book pays nothing and warns about nothing. The directory is not watched: a restart picks up a vdirsyncer update, and a QFileSystemWatcher would be a live-index feature nobody asked for. No action is added, so none of the five places in "Adding an action is FIVE places" applies: there is no name in KeyMap::knownActions(), no default binding, no icon-table entry and no menu entry to add.
-rw-r--r--src/mainwindow.cpp16
-rw-r--r--src/mainwindow.h14
2 files changed, 30 insertions, 0 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 2443ead..4c37a83 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -770,6 +770,17 @@ void MainWindow::buildUi()
m_queryEdit->installEventFilter(this);
m_queryCompleter = new QueryCompleter(m_queryEdit, m_config, this);
+ // The address book, read once for the whole session. A vdirsyncer
+ // directory is a handful of small vCards, so the parse is paid at startup
+ // rather than per keystroke, and a restart is the refresh route: watching
+ // the directory would be a live-index feature nobody asked for. An empty
+ // contactsDir() is the feature switched off, so the loader is not even
+ // called, and no warning is raised for a machine with no address book.
+ if (!m_config.contactsDir().isEmpty()) {
+ m_contacts = ContactStore::loadDirectory(m_config.contactsDir());
+ m_queryCompleter->setContacts(m_contacts);
+ }
+
m_markReadTimer = new QTimer(this);
// Named so a test can observe whether it is armed without the window
// having to expose the timer or the decision that armed it.
@@ -1254,6 +1265,11 @@ void MainWindow::openComposer(const ComposeContext &context)
composer->setAttribute(Qt::WA_DeleteOnClose);
m_composers.append(QPointer<ComposeWindow>(composer));
+ // The same list the query bar offers, from the once-per-session load. The
+ // composer builds its own model over it, so a recipient field completes on
+ // the address book the query bar completes from.
+ composer->setContacts(m_contacts);
+
// Compaction, and ONLY compaction. The QPointer above is what keeps
// composersBlockingQuit() safe against a destroyed window, since it nulls
// on destruction; this drops the entry so the list does not accumulate
diff --git a/src/mainwindow.h b/src/mainwindow.h
index c3395c9..4fb19e4 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -48,6 +48,10 @@
// asserted through it without reaching into the delegate.
#include "businesssenders.h"
+// Held by value, like the business-senders list above: the parsed contact list
+// is a member, so its size must be known here.
+#include "contactstore.h"
+
class QAction;
class QLineEdit;
class QMenu;
@@ -1836,6 +1840,16 @@ private:
/// completer does not yet offer, without a round trip.
QStringList m_knownTags;
+ /// The address book, loaded ONCE when the window is built and handed to
+ /// both consumers: the query-bar completer and every composer.
+ ///
+ /// Held here so the list is read from disk a single time per session. A
+ /// vdirsyncer directory can change while the application runs, but a
+ /// QFileSystemWatcher would be speculative: a restart picks up the new
+ /// file, and the store is 117 files of two fields, not a live index.
+ /// Empty when contactsDir() is unset, which is the feature being off.
+ QList<Contact> m_contacts;
+
quint64 m_generation = 0;
/// True once the running query has reported its total, so the model holds