aboutsummaryrefslogtreecommitdiffstats
path: root/src/threadlistview.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-01 10:49:18 +0200
committerDanilo M. <danix@danix.xyz>2026-10-01 10:49:18 +0200
commit9ae9473acdb7cb3310c3028765cc4b30fedfce27 (patch)
tree438576dd9a5b9e4bfc060e3cd22310f3e03a6130 /src/threadlistview.cpp
parent107933409c9044a248ef483734176cbde03cc137 (diff)
downloadqtmaildir-9ae9473acdb7cb3310c3028765cc4b30fedfce27.tar.gz
qtmaildir-9ae9473acdb7cb3310c3028765cc4b30fedfce27.zip
feat: scroll the thread list smoothlyHEADmaster
The list scrolled per ITEM, Qt's default, so a wheel notch jumped several whole cards at once and a touchpad's small deltas were quantised into card-sized jumps. The eye lost track of how far the list had moved. The view now scrolls per pixel, so a touchpad moves it continuously, and ThreadListView::wheelEvent turns each wheel notch into a 160ms eased glide of exactly one card. Notches arriving mid-glide add to its target rather than restarting from where it has got to. Pixel deltas and modified wheels pass through to Qt unchanged. The cost of per-pixel scrolling is that a card can rest half above the top edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'src/threadlistview.cpp')
-rw-r--r--src/threadlistview.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/threadlistview.cpp b/src/threadlistview.cpp
index 019d7c9..b5176bf 100644
--- a/src/threadlistview.cpp
+++ b/src/threadlistview.cpp
@@ -22,6 +22,9 @@
#include "threadlistmodel.h"
#include <QMouseEvent>
+#include <QPropertyAnimation>
+#include <QScrollBar>
+#include <QWheelEvent>
void ThreadListView::mousePressEvent(QMouseEvent *event)
{
@@ -53,3 +56,33 @@ void ThreadListView::mousePressEvent(QMouseEvent *event)
QTreeView::mousePressEvent(event);
}
+
+void ThreadListView::wheelEvent(QWheelEvent *event)
+{
+ const int notches = event->angleDelta().y() / QWheelEvent::DefaultDeltasPerStep;
+ if (!event->pixelDelta().isNull() || event->modifiers() != Qt::NoModifier
+ || notches == 0) {
+ // ponytail: a high-resolution wheel sending less than one notch per
+ // event falls through to the plain per-pixel scroll, unanimated.
+ QTreeView::wheelEvent(event);
+ return;
+ }
+
+ QScrollBar *bar = verticalScrollBar();
+ if (!m_glide) {
+ m_glide = new QPropertyAnimation(bar, "value", this);
+ m_glide->setDuration(160);
+ m_glide->setEasingCurve(QEasingCurve::OutCubic);
+ }
+
+ const bool gliding = m_glide->state() == QAbstractAnimation::Running;
+ const int from = gliding ? m_glide->endValue().toInt() : bar->value();
+ const int to = qBound(bar->minimum(), from - notches * bar->singleStep(),
+ bar->maximum());
+
+ m_glide->stop();
+ m_glide->setStartValue(bar->value());
+ m_glide->setEndValue(to);
+ m_glide->start();
+ event->accept();
+}