aboutsummaryrefslogtreecommitdiffstats
path: root/src/composewindow.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-18 15:25:14 +0200
committerDanilo M. <danix@danix.xyz>2026-09-18 15:25:14 +0200
commit9d4fb5444438bdf188a6149a6667788dc3fc7bc0 (patch)
tree10d4a63f18334ed68d65805b78e16fe1b0dfe9a5 /src/composewindow.h
parent729fd1465718ef1da5f61452bcb7eb23d02c9c9a (diff)
downloadqtmaildir-9d4fb5444438bdf188a6149a6667788dc3fc7bc0.tar.gz
qtmaildir-9d4fb5444438bdf188a6149a6667788dc3fc7bc0.zip
feat: complete contacts in the composer recipients
One shared QCompleter serves To, Cc and Bcc, attached with setWidget and never setCompleter, which resets the prefix to the whole field and stops matching after the first comma. The prefix is the comma-delimited token under the cursor, set by hand from textEdited; accepting replaces only that token and leaves the rest of the field alone. Candidates match the name and the address case-insensitively. A display name containing a comma is quoted on insertion, and splitRecipients() is now quote-aware so the quoted name survives as one recipient. Contacts reach the composer through setContacts() rather than a fourth constructor argument, so every existing three-argument construction and test stays as it was. An empty list leaves the fields behaving exactly as before completion existed.
Diffstat (limited to 'src/composewindow.h')
-rw-r--r--src/composewindow.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/composewindow.h b/src/composewindow.h
index 09b47de..c4e5cb3 100644
--- a/src/composewindow.h
+++ b/src/composewindow.h
@@ -27,12 +27,17 @@
#include <memory>
#include "config.h"
+#include "contactstore.h"
#include "formattoolbar.h" // MarkdownFormat::Edit is used by value below, and
// a type nested in a namespace cannot be
// forward-declared from outside it.
#include "types.h"
class QAction;
+class QCompleter;
+class QEvent;
+class QModelIndex;
+class QStandardItemModel;
class QCheckBox;
class QSplitter;
class QComboBox;
@@ -114,6 +119,19 @@ public:
/// a second location, and the tests need to not read the real one.
void setSignatureDir(const QString &dir);
+ /// The address book the recipient fields complete from.
+ ///
+ /// MainWindow owns the load and calls this right after constructing the
+ /// window, because it already holds the list for its own account picker and
+ /// a composer must not read the store itself. Empty (the store off, or no
+ /// vdir) is the ordinary state and leaves the fields behaving exactly as
+ /// they did before completion existed: no candidates, no popup.
+ ///
+ /// A setter rather than a constructor parameter on purpose: the three-
+ /// argument constructor is used by every other test, and a fourth argument
+ /// would turn one load into forty edits.
+ void setContacts(const QList<Contact> &contacts);
+
/// Seeds the signature from config and fills the switch.
///
/// Public and called by the constructor rather than private, so a test can
@@ -220,9 +238,18 @@ protected:
/// The one place the registry is told, whichever route closes the window.
void closeEvent(QCloseEvent *event) override;
+ /// Re-points the shared contact completer at whichever recipient field just
+ /// took focus. One completer serves To, Cc and Bcc, and QCompleter anchors
+ /// its popup and its key handling to a single widget.
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
private:
void buildUi();
void buildFormatToolbar();
+ void buildContactCompleter();
+ void rebuildContactModel();
+ void completeRecipientToken(QLineEdit *field);
+ void acceptContactCompletion(const QModelIndex &index);
void seedFields();
/// Extracts a forwarded message's parts into m_forwardedParts and appends
@@ -325,6 +352,16 @@ private:
QPlainTextEdit *m_body = nullptr;
QToolButton *m_sendHtml = nullptr;
+ /// ONE completer over ONE model, shared by To, Cc and Bcc. Owned here and
+ /// parented to the window; the model's rows are the insertion strings, see
+ /// contactInsertionText() in the .cpp.
+ QCompleter *m_contactCompleter = nullptr;
+ QStandardItemModel *m_contactModel = nullptr;
+
+ /// The contacts MainWindow handed in, kept so setContacts() can rebuild the
+ /// model without reaching back for them.
+ QList<Contact> m_contacts;
+
/// Item 171. Strips remote content from the forwarded original, checked by
/// default. Only created for a Forward whose original carries remote
/// content, so an ordinary message gains no control.