[pim/mimetreeparser] src/quick: Add basic wheel interceptor
Claudio Cambra <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 8d2b3512eb2e5b9276b0f3f760274f5fa9abc912 by Claudio Cambra.
Committed on 16/08/2026 at 16:51.
Pushed by clau-cambra into branch 'master'.
Add basic wheel interceptor
a
M +4 -0 src/quick/CMakeLists.txt
A +88 -0 src/quick/wheelinterceptor.cpp [License: LGPL(v2.1+)]
A +35 -0 src/quick/wheelinterceptor.h [License: LGPL(v2.1+)]
https://invent.kde.org/pim/mimetreeparser/-/commit/8d2b3512eb2e5b9276b0f3f760274f5fa9abc912
diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt
index 0c8ae6e..86062a1 100644
--- a/src/quick/CMakeLists.txt
+++ b/src/quick/CMakeLists.txt
@@ -16,12 +16,16 @@ target_sources(
itinerarymodel.cpp
itinerarymodel.h
types.h
+ wheelinterceptor.h
+ wheelinterceptor.cpp
)
target_link_libraries(
mimetreeparser_plugin
PRIVATE
Qt::Qml
+ Qt::Quick
+ Qt::Gui
${DBUS_LIB}
KPim6::MimeTreeParserCore
KF6::KIOGui
diff --git a/src/quick/wheelinterceptor.cpp b/src/quick/wheelinterceptor.cpp
new file mode 100644
index 0000000..8be10fb
--- /dev/null
+++ b/src/quick/wheelinterceptor.cpp
@@ -0,0 +1,88 @@
+// SPDX-FileCopyrightText: 2025 Claudio Cambra <[email protected]>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include "wheelinterceptor.h"
+
+#include <QCoreApplication>
+#include <QGuiApplication>
+#include <QStyleHints>
+#include <QWheelEvent>
+
+WheelInterceptor::WheelInterceptor(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQuickItem *WheelInterceptor::source() const
+{
+ return m_source;
+}
+
+void WheelInterceptor::setSource(QQuickItem *source)
+{
+ if (m_source == source) {
+ return;
+ }
+ if (m_source) {
+ QCoreApplication::instance()->removeEventFilter(this);
+ }
+ m_source = source;
+ if (m_source) {
+ QCoreApplication::instance()->installEventFilter(this);
+ }
+ Q_EMIT sourceChanged();
+}
+
+QQuickItem *WheelInterceptor::target() const
+{
+ return m_target;
+}
+
+void WheelInterceptor::setTarget(QQuickItem *target)
+{
+ if (m_target == target) {
+ return;
+ }
+ m_target = target;
+ Q_EMIT targetChanged();
+}
+
+static QQuickItem *findTopmostFlickable(QQuickItem *item)
+{
+ QQuickItem *topmost = nullptr;
+ auto current = item;
+ while (current) {
+ if (current->inherits("QQuickFlickable")) {
+ topmost = current;
+ }
+ current = current->parentItem();
+ }
+ return topmost;
+}
+
+bool WheelInterceptor::eventFilter(QObject *obj, QEvent *event)
+{
+ Q_UNUSED(obj);
+ if (event->type() == QEvent::Wheel && m_source && m_target) {
+ auto wheelEvent = static_cast<QWheelEvent *>(event);
+ const auto localPos = m_source->mapFromGlobal(wheelEvent->globalPosition().toPoint());
+ if (m_source->contains(localPos)) {
+ auto flickable = findTopmostFlickable(m_source);
+ if (!flickable) {
+ flickable = findTopmostFlickable(m_target);
+ }
+ if (flickable) {
+ const auto viewH = flickable->height();
+ const auto contentH = flickable->property("contentHeight").toReal();
+ const auto currentY = flickable->property("contentY").toReal();
+ const auto maxScroll = qMax(0.0, contentH - viewH);
+ const auto delta = wheelEvent->angleDelta().y();
+ const auto scrollLines = QGuiApplication::styleHints()->wheelScrollLines();
+ const auto pixels = -(delta / 120.0) * scrollLines * 20.0;
+ flickable->setProperty("contentY", qBound(0.0, currentY + pixels, maxScroll));
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/quick/wheelinterceptor.h b/src/quick/wheelinterceptor.h
new file mode 100644
index 0000000..fa9006d
--- /dev/null
+++ b/src/quick/wheelinterceptor.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: 2025 Claudio Cambra <[email protected]>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#include <QObject>
+#include <QQuickItem>
+
+class WheelInterceptor : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QQuickItem *source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
+
+public:
+ explicit WheelInterceptor(QObject *parent = nullptr);
+
+ QQuickItem *source() const;
+ void setSource(QQuickItem *source);
+
+ QQuickItem *target() const;
+ void setTarget(QQuickItem *target);
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+Q_SIGNALS:
+ void sourceChanged();
+ void targetChanged();
+
+private:
+ QQuickItem *m_source = nullptr;
+ QQuickItem *m_target = nullptr;
+};