aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp9
-rw-r--r--src/threadlistview.cpp33
-rw-r--r--src/threadlistview.h13
3 files changed, 53 insertions, 2 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 19373e3..e93898c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -962,8 +962,13 @@ void MainWindow::buildUi()
// the viewport and auto-scroll brought the clicked index fully into view.
m_threadView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- // Scrolling a whole card at a time rather than a fraction of one, so a
- // card is never left half above the top edge.
+ // Per PIXEL, so a touchpad moves the list continuously. Qt's default is
+ // per ITEM, which jumped several whole cards per wheel notch and quantised
+ // a touchpad's small deltas into card-sized jumps, so the eye lost track
+ // of how far the list had moved. The cost is that a card can rest half
+ // above the top edge. A wheel notch glides one step, which is one card;
+ // see ThreadListView::wheelEvent.
+ m_threadView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_threadView->verticalScrollBar()->setSingleStep(
CardLayout::heightFor(m_threadView->font()));
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();
+}
diff --git a/src/threadlistview.h b/src/threadlistview.h
index a509389..79db424 100644
--- a/src/threadlistview.h
+++ b/src/threadlistview.h
@@ -20,6 +20,8 @@
#include <QTreeView>
+class QPropertyAnimation;
+
/// The thread list.
///
/// It exists for ONE reason now: the expander is drawn by CardDelegate, and a
@@ -47,4 +49,15 @@ protected:
/// indicator underneath, also removed the style's hit area, so an expander
/// once painted correctly and did nothing at all.
void mousePressEvent(QMouseEvent *event) override;
+
+ /// A mouse wheel notch GLIDES one scrollbar step instead of jumping, so
+ /// the eye can follow how far the list moved. Notches arriving mid-glide
+ /// add to its target rather than restarting from where it has got to. A
+ /// touchpad's pixel deltas are already continuous and pass straight
+ /// through, as does any wheel with a modifier held.
+ void wheelEvent(QWheelEvent *event) override;
+
+private:
+ /// Created on the first notch, owned by the view.
+ QPropertyAnimation *m_glide = nullptr;
};