summaryrefslogtreecommitdiffstats
path: root/src/mailsync.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-03 09:01:32 +0200
committerDanilo M. <danix@danix.xyz>2026-08-03 09:01:32 +0200
commit376323043a6b7a02e23cd9b6232bc25ec5fc1ce6 (patch)
tree4140c48b8c1b493c2998bd094dca76613f0d2917 /src/mailsync.h
parentc6c1011222361b446fb3cdee1ad324fe54931abc (diff)
downloadqtmaildir-376323043a6b7a02e23cd9b6232bc25ec5fc1ce6.tar.gz
qtmaildir-376323043a6b7a02e23cd9b6232bc25ec5fc1ce6.zip
feat: add MailSync process wrapper
Runs the configured sync script through QProcess, merging stdout and stderr into one log so a failing mbsync run has something to show. The script is never run through a shell: the command is a config value, and splitCommand keeps its arguments literal. Two fixes against the drafted version: - start() no longer calls waitForStarted(). It blocked the UI thread for up to five seconds, which contradicts the spec's requirement that the UI stay usable during sync, and it swallowed launch failures into a bare false return. A missing script now surfaces asynchronously through errorOccurred as finished(false, -1) with an explanatory log line, so the spinner cannot hang with nothing to explain it. - Removed a double-emit guard I had added on the assumption that QProcess follows errorOccurred(FailedToStart) with finished(). Verified it does not: FailedToStart is emitted instead of finished, never before it. The guard was dead state and the comment justifying it was wrong. Also corrects the sync interval throughout: the user's cron runs every 10 minutes, not hourly. The shorter interval strengthens the flock rationale rather than weakening it, since collisions with a manual sync are that much more likely. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/mailsync.h')
-rw-r--r--src/mailsync.h44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/mailsync.h b/src/mailsync.h
new file mode 100644
index 0000000..af4acbc
--- /dev/null
+++ b/src/mailsync.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <QObject>
+#include <QProcess>
+#include <QString>
+
+/// Runs the configured external sync command.
+///
+/// qtmaildir deliberately does not implement sync itself. The existing script
+/// holds a flock that is the shared mutex between the user's cron sync, which
+/// runs every 10 minutes, and any manual sync; running the script joins that
+/// mutex, whereas a built-in implementation would sit outside it and could run
+/// mbsync concurrently with cron, corrupting Maildir UID state.
+class MailSync : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MailSync(const QString &command, QObject *parent = nullptr);
+
+ /// False when no command is configured; the UI disables its Sync button.
+ bool isAvailable() const { return !m_command.isEmpty(); }
+ bool isRunning() const;
+
+ /// Returns false if unavailable or already running. A true return means the
+ /// process was handed to the event loop, not that it launched successfully:
+ /// a missing binary surfaces asynchronously through finished(false, ...).
+ bool start();
+
+ QString log() const { return m_log; }
+
+signals:
+ void started();
+ void outputReceived(const QString &chunk);
+ void finished(bool success, int exitCode);
+
+private:
+ void handleReadyRead();
+ void handleFinished(int exitCode, QProcess::ExitStatus status);
+ void handleError(QProcess::ProcessError error);
+
+ QString m_command;
+ QProcess m_process;
+ QString m_log;
+};