aboutsummaryrefslogtreecommitdiffstats
path: root/src/notmuchworker.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-18 12:12:49 +0200
committerDanilo M. <danix@danix.xyz>2026-08-18 12:12:49 +0200
commitec8c2d7492b479846270f702541a26be5643a376 (patch)
treef743e215e177a9c5dfb49394a6d9bdcaa1dd498b /src/notmuchworker.h
parenta089820aba3bc51884ad880b9e3cf689eda7361d (diff)
downloadqtmaildir-ec8c2d7492b479846270f702541a26be5643a376.tar.gz
qtmaildir-ec8c2d7492b479846270f702541a26be5643a376.zip
feat(worker): resolve whole threads to their messages, ids and paths
Delete thread MOVES every message now, and a move needs message ids and file paths that the UI does not hold: a thread the user never expanded has no nodes in the model for its replies, so those live only in the database. resolveThreadMessages() answers with both, in one combined query, for the same reason applyTagsToThreads() resolves threads here rather than in the UI: a query per thread reopens the same Xapian cursor once per selected row. Paths come back RELATIVE to the database root, matching ThreadSummary::firstMessagePath, because the UI knows accounts only by their maildir, itself a database-relative prefix. Without them the caller would know which messages to move and not where any of them belongs. Tags come back too, because Restore reads a message's `deleted-from:` tag to decide where to send it and an unexpanded thread's messages have no node to read tags from. They are joined by a TAB, not a space. A notmuch tag may absolutely contain a space: the folder "Inbox/SlackBuilds users" produces `deleted-from:Inbox/SlackBuilds users`, and splitting that on spaces truncated the folder to "Inbox/SlackBuilds". Restore then moved the messages into a folder of that name, CREATING it, so real messages ended up in a directory mbsync does not sync and read as missing. Under `Create Both` that folder can propagate to the mail server. A tab cannot appear in a tag, since notmuch's own dump format is line-based and whitespace-delimited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/notmuchworker.h')
-rw-r--r--src/notmuchworker.h27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/notmuchworker.h b/src/notmuchworker.h
index d1bec59..dfd4303 100644
--- a/src/notmuchworker.h
+++ b/src/notmuchworker.h
@@ -143,6 +143,21 @@ public slots:
const QStringList &remove,
const QString &description);
+ /// Resolves whole threads to the message ids and file paths they contain.
+ ///
+ /// Delete thread MOVES every message, and a move needs message ids, which
+ /// the UI does not hold for a thread it never expanded. The resolution
+ /// happens here for the same reason applyTagsToThreads() does it here:
+ /// the database handle lives on this thread, and one combined query beats
+ /// reopening the cursor per thread.
+ ///
+ /// Paths come back beside the ids because the destination is per ACCOUNT
+ /// and the UI resolves an account from a message's path. Without them the
+ /// caller would know which messages to move and not where any of them
+ /// belongs.
+ void resolveThreadMessages(const QStringList &threadIds,
+ const QString &requestTag);
+
/// Every tag in the database, sorted. Feeds query bar completion, which
/// cannot offer tag names it has no way to enumerate. Called at startup,
/// after a sync, and after a tag mutation introduces an unknown tag.
@@ -222,6 +237,18 @@ signals:
/// from here can be passed straight back to move a message home.
void messagesMovedFrom(const QMap<QString, QString> &originByMessageId,
const QString &destFolder);
+ /// The answer to resolveThreadMessages(), as parallel lists: `messageIds`
+ /// and the database-relative `paths` of the same messages, in the same
+ /// order. `requestTag` is echoed back so a caller can tell which request
+ /// this answers.
+ /// `tags` carries each message's tags joined by a space, in the same
+ /// order. Needed because Restore reads a message's `deleted-from:` tag to
+ /// decide where to send it, and an unexpanded thread's messages have no
+ /// node in the model to read tags from.
+ void threadMessagesResolved(const QStringList &messageIds,
+ const QStringList &paths,
+ const QStringList &tags,
+ const QString &requestTag);
void allTagsReady(const QStringList &tags, quint64 generation);
/// One entry per requested query, in the order they were asked for. A query