Warning, file /office/calligra/libs/widgetutils/KoKineticScroller.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2018 Emmet O'Neill <emmetoneill.pdx@gmail.com>
0003  * Copyright (C) 2018 Eoin O'Neill <eoinoneill1991@gmail.com>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include <KoKineticScroller.h>
0022 #include <QAbstractItemView>
0023 #include <ksharedconfig.h>
0024 #include <kconfiggroup.h>
0025 
0026 QScroller* KoKineticScroller::createPreconfiguredScroller(QAbstractScrollArea *scrollArea)
0027 {
0028     KConfigGroup config = KSharedConfig::openConfig()->group("KoKineticScroller");
0029     int sensitivity = config.readEntry("KineticScrollingSensitivity", 75);
0030     bool enabled = config.readEntry("KineticScrollingEnabled", true);
0031     bool hideScrollBars = config.readEntry("KineticScrollingHideScrollbar", false);
0032     float resistanceCoefficient = config.readEntry("KineticScrollingResistanceCoefficient", 10.0f);
0033     float dragVelocitySmoothFactor = config.readEntry("KineticScrollingDragVelocitySmoothingFactor", 1.0f);
0034     float minimumVelocity = config.readEntry("KineticScrollingMinimumVelocity", 0.0f);
0035     float axisLockThresh = config.readEntry("KineticScrollingAxisLockThreshold", 1.0f);
0036     float maximumClickThroughVelocity = config.readEntry("KineticScrollingMaxClickThroughVelocity", 0.0f);
0037     float flickAccelerationFactor = config.readEntry("KineticScrollingFlickAccelerationFactor", 1.5f);
0038     float overshootDragResistanceFactor = config.readEntry("KineticScrollingOvershotDragResistanceFactor", 0.1f);
0039     float overshootDragDistanceFactor = config.readEntry("KineticScrollingOvershootDragDistanceFactor", 0.3f);
0040     float overshootScrollDistanceFactor = config.readEntry("KineticScrollingOvershootScrollDistanceFactor", 0.1f);
0041     float overshootScrollTime = config.readEntry("KineticScrollingOvershootScrollTime", 0.4f);
0042     QScroller::ScrollerGestureType gestureType = getConfiguredGestureType();
0043 
0044     if (enabled && scrollArea) {
0045         if (hideScrollBars) {
0046             scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
0047             scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
0048         }
0049 
0050         QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(scrollArea);
0051         if (itemView) {
0052             itemView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
0053         }
0054 
0055         QScroller *scroller = QScroller::scroller(scrollArea);
0056         scroller->grabGesture(scrollArea, gestureType);
0057 
0058         QScrollerProperties properties;
0059 
0060         // DragStartDistance seems to be based on meter per second; though it's
0061         // not explicitly documented, other QScroller values are in that metric.
0062         // To start kinetic scrolling, with minimal sensitity, we expect a drag
0063         // of 10 mm, with minimum sensitity any > 0 mm.
0064         const float mm = 0.001f;
0065         const float resistance = 1.0f - (sensitivity / 100.0f);
0066         const float mousePressEventDelay = config.readEntry("KineticScrollingMousePressDelay", 1.0f - 0.75f * resistance);
0067 
0068         properties.setScrollMetric(QScrollerProperties::DragStartDistance, resistance * resistanceCoefficient * mm);
0069         properties.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor, dragVelocitySmoothFactor);
0070         properties.setScrollMetric(QScrollerProperties::MinimumVelocity, minimumVelocity);
0071         properties.setScrollMetric(QScrollerProperties::AxisLockThreshold, axisLockThresh);
0072         properties.setScrollMetric(QScrollerProperties::MaximumClickThroughVelocity, maximumClickThroughVelocity);
0073         properties.setScrollMetric(QScrollerProperties::MousePressEventDelay, mousePressEventDelay);
0074         properties.setScrollMetric(QScrollerProperties::AcceleratingFlickSpeedupFactor, flickAccelerationFactor);
0075 
0076         properties.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOn);
0077         properties.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, overshootDragResistanceFactor);
0078         properties.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, overshootDragDistanceFactor);
0079         properties.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, overshootScrollDistanceFactor);
0080         properties.setScrollMetric(QScrollerProperties::OvershootScrollTime, overshootScrollTime);
0081 
0082         scroller->setScrollerProperties(properties);
0083 
0084         return scroller;
0085     }
0086 
0087     return nullptr;
0088 }
0089 
0090 QScroller::ScrollerGestureType KoKineticScroller::getConfiguredGestureType()
0091 {
0092     KConfigGroup config = KSharedConfig::openConfig()->group("KoKineticScroller");
0093     int gesture = config.readEntry("KineticScrollingGesture", 0);
0094 
0095     switch (gesture) {
0096     case 0: {
0097         return QScroller::TouchGesture;
0098     }
0099     case 1: {
0100         return QScroller::LeftMouseButtonGesture;
0101     }
0102     case 2: {
0103         return QScroller::MiddleMouseButtonGesture;
0104     }
0105     case 3: {
0106         return QScroller::RightMouseButtonGesture;
0107     }
0108     default:
0109         return QScroller::MiddleMouseButtonGesture;
0110     }
0111 }
0112 
0113 void KoKineticScroller::updateCursor(QWidget *source, QScroller::State state)
0114 {
0115     if( state == QScroller::State::Pressed ) {
0116         source->setCursor(Qt::OpenHandCursor);
0117     } else if (state == QScroller::State::Dragging) {
0118         source->setCursor(Qt::ClosedHandCursor);
0119     } else {
0120         source->setCursor(Qt::ArrowCursor);
0121     }
0122 }