aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/busyindicator.cpp65
-rw-r--r--src/busyindicator.h53
-rw-r--r--src/mainwindow.cpp18
-rw-r--r--src/mainwindow.h4
5 files changed, 129 insertions, 12 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 197366d..b63ff3e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,6 +6,7 @@ add_library(qtmaildir_lib STATIC
htmlbuilder.cpp
cidschemehandler.cpp
cardlayout.cpp
+ busyindicator.cpp
marks.cpp
carddelegate.cpp
notmuchworker.cpp
diff --git a/src/busyindicator.cpp b/src/busyindicator.cpp
new file mode 100644
index 0000000..0ccc719
--- /dev/null
+++ b/src/busyindicator.cpp
@@ -0,0 +1,65 @@
+/*
+ * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs
+ * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "busyindicator.h"
+
+BusyIndicator::BusyIndicator(QWidget *parent)
+ : QProgressBar(parent)
+{
+ // Starts indeterminate and hidden, which is what both consumers want
+ // before anything is happening. A caller that wants a fraction calls
+ // setProgress() and never sees this range.
+ setRange(0, 0);
+
+ // The percentage would be meaningless in the indeterminate mode and is
+ // redundant beside the phase text in the determinate one, where the popup
+ // says what is being waited for.
+ setTextVisible(false);
+ hide();
+}
+
+void BusyIndicator::setBusy(bool busy)
+{
+ setRange(0, 0);
+ setVisible(busy);
+}
+
+void BusyIndicator::setProgress(int value, int total)
+{
+ if (total <= 0) {
+ // Not an empty determinate bar: setRange(0, 0) IS the indeterminate
+ // range, so falling through here would hand the caller an animating
+ // bar while it believed it had shown a fraction.
+ setBusy(true);
+ return;
+ }
+
+ setRange(0, total);
+ setValue(qBound(0, value, total));
+ show();
+}
+
+bool BusyIndicator::isBusy() const
+{
+ return isVisible();
+}
+
+bool BusyIndicator::isDeterminate() const
+{
+ return maximum() > minimum();
+}
diff --git a/src/busyindicator.h b/src/busyindicator.h
new file mode 100644
index 0000000..14ad6ee
--- /dev/null
+++ b/src/busyindicator.h
@@ -0,0 +1,53 @@
+/*
+ * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs
+ * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <QProgressBar>
+
+// A progress bar that carries both of the modes this application needs, so the
+// two places that show one do not each configure a bare QProgressBar. The
+// status bar's sync indicator is indeterminate, because mbsync reports no
+// percentage; the composer's send popup drains a determinate bar through its
+// undo countdown and then switches THE SAME widget to indeterminate when the
+// command starts. That switch is why one class exists rather than two.
+//
+// Deliberately no label. MainWindow's status text is m_statusLabel, which is
+// the window's and carries far more than this widget's state, and the send
+// popup's phase text belongs to the popup. A label here would be a third
+// owner of status text.
+class BusyIndicator : public QProgressBar
+{
+ Q_OBJECT
+
+public:
+ explicit BusyIndicator(QWidget *parent = nullptr);
+
+ // Indeterminate: an animating bar meaning "working, duration unknown".
+ // setRange(0, 0) is what Qt reads as indeterminate, and a bar left in that
+ // range shows no fraction however many times setValue() is called.
+ void setBusy(bool busy);
+
+ // Determinate: a real fraction. Passing a total of 0 or less would be a
+ // silent request for the indeterminate range, so it is treated as busy
+ // instead of quietly drawing an empty bar forever.
+ void setProgress(int value, int total);
+
+ bool isBusy() const;
+ bool isDeterminate() const;
+};
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 58c82ca..dc416ca 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -36,7 +36,6 @@
#include <QMenuBar>
#include <QMessageBox>
#include <QPlainTextEdit>
-#include <QProgressBar>
#include <QPushButton>
#include <QSettings>
#include <QSplitter>
@@ -54,6 +53,7 @@
#include "notmuchworker.h"
#include "querycompleter.h"
#include "carddelegate.h"
+#include "busyindicator.h"
#include "cardlayout.h"
#include "searchterm.h"
#include "tagchip.h"
@@ -504,16 +504,14 @@ void MainWindow::buildUi()
m_pendingLabel->hide();
statusBar()->addPermanentWidget(m_pendingLabel);
- // Indeterminate: setRange(0, 0). A sync has no measurable progress, since
- // mbsync reports no percentage and the script's output is unstructured, so
- // a bar filling left to right would be inventing a fraction. This one
- // animates to say "working, duration unknown".
- m_syncProgress = new QProgressBar(this);
+ // Indeterminate, which BusyIndicator starts in: a sync has no measurable
+ // progress, since mbsync reports no percentage and the script's output is
+ // unstructured, so a bar filling left to right would be inventing a
+ // fraction. This one animates to say "working, duration unknown". The
+ // determinate half of the widget is the composer's, not this one's.
+ m_syncProgress = new BusyIndicator(this);
m_syncProgress->setObjectName(QStringLiteral("syncProgress"));
- m_syncProgress->setRange(0, 0);
- m_syncProgress->setTextVisible(false);
m_syncProgress->setMaximumWidth(120);
- m_syncProgress->hide();
statusBar()->addPermanentWidget(m_syncProgress);
// Query row.
@@ -3677,7 +3675,7 @@ void MainWindow::updateSyncControls()
// local run ending would re-enable it while cron still holds the lock.
const bool busy = m_localSyncBusy || m_externalSyncBusy;
- m_syncProgress->setVisible(busy);
+ m_syncProgress->setBusy(busy);
// Disabled rather than left clickable: MailSync::start() already refuses a
// second run and the script exits 75 when another holds the lock, but a
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 5b1621f..8e483d2 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -52,11 +52,11 @@ class QPushButton;
class QComboBox;
class QPlainTextEdit;
class QSplitter;
-class QProgressBar;
class QTimer;
class QToolButton;
class QVBoxLayout;
+class BusyIndicator;
class ThreadListModel;
class MessageView;
class MailSync;
@@ -1074,7 +1074,7 @@ private:
QLabel *m_pendingLabel = nullptr;
/// Indeterminate, shown only while a sync runs. See setSyncBusy().
- QProgressBar *m_syncProgress = nullptr;
+ BusyIndicator *m_syncProgress = nullptr;
/// The last counts the worker answered, one per placeholderLines() entry.
/// Empty until the first reply, which renders the pane without its helper