diff --git a/libs/ui/dialogs/kis_dlg_preferences.h b/libs/ui/dialogs/kis_dlg_preferences.h --- a/libs/ui/dialogs/kis_dlg_preferences.h +++ b/libs/ui/dialogs/kis_dlg_preferences.h @@ -79,6 +79,9 @@ bool showCanvasMessages(); bool compressKra(); bool toolOptionsInDocker(); + int kineticScrollingGesture(); + int kineticScrollingSensitivity(); + bool kineticScrollingScrollbar(); bool switchSelectionCtrlAlt(); bool convertToImageColorspaceOnImport(); diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc --- a/libs/ui/dialogs/kis_dlg_preferences.cc +++ b/libs/ui/dialogs/kis_dlg_preferences.cc @@ -108,6 +108,10 @@ m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); + m_cmbKineticScrollingGesture->addItem(i18n("Disabled")); + m_cmbKineticScrollingGesture->addItem(i18n("On Touch Drag")); + m_cmbKineticScrollingGesture->addItem(i18n("On Click Drag")); + m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); @@ -143,6 +147,9 @@ m_chkSingleApplication->setChecked(kritarc.value("EnableSingleApplication", true).toBool()); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); + m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture()); + m_kineticScrollingSensitivity->setValue(cfg.kineticScrollingSensitivity()); + m_chkKineticScrollingScrollbar->setChecked(cfg.kineticScrollingScrollbar()); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas()); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport()); @@ -187,6 +194,9 @@ m_chkHiDPI->setChecked(true); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); + m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture(true)); + m_kineticScrollingSensitivity->setValue(cfg.kineticScrollingSensitivity(true)); + m_chkKineticScrollingScrollbar->setChecked(cfg.kineticScrollingScrollbar(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); @@ -258,6 +268,21 @@ return m_radioToolOptionsInDocker->isChecked(); } +int GeneralTab::kineticScrollingGesture() +{ + return m_cmbKineticScrollingGesture->currentIndex(); +} + +int GeneralTab::kineticScrollingSensitivity() +{ + return m_kineticScrollingSensitivity->value(); +} + +bool GeneralTab::kineticScrollingScrollbar() +{ + return m_chkKineticScrollingScrollbar->isChecked(); +} + bool GeneralTab::switchSelectionCtrlAlt() { return m_chkSwitchSelectionCtrlAlt->isChecked(); @@ -1168,6 +1193,9 @@ kritarc.setValue("EnableSingleApplication", dialog->m_general->m_chkSingleApplication->isChecked()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); + cfg.setKineticScrollingGesture(dialog->m_general->kineticScrollingGesture()); + cfg.setKineticScrollingSensitivity(dialog->m_general->kineticScrollingSensitivity()); + cfg.setKineticScrollingScrollbar(dialog->m_general->kineticScrollingScrollbar()); cfg.setSwitchSelectionCtrlAlt(dialog->m_general->switchSelectionCtrlAlt()); cfg.setDisableTouchOnCanvas(!dialog->m_general->chkEnableTouch->isChecked()); cfg.setConvertToImageColorspaceOnImport(dialog->m_general->convertToImageColorspaceOnImport()); diff --git a/libs/ui/forms/wdggeneralsettings.ui b/libs/ui/forms/wdggeneralsettings.ui --- a/libs/ui/forms/wdggeneralsettings.ui +++ b/libs/ui/forms/wdggeneralsettings.ui @@ -406,6 +406,64 @@ + + + + Kinetic Scrolling (needs restart) + + + + + + + + + + + Sensitivity (0-100): + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + 0 + + + 100 + + + 1 + + + 75 + + + + + + + + + Show Scrollbar + + + + + + diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h --- a/libs/ui/kis_config.h +++ b/libs/ui/kis_config.h @@ -493,6 +493,15 @@ bool toolOptionsInDocker(bool defaultValue = false) const; void setToolOptionsInDocker(bool inDocker); + int kineticScrollingGesture(bool defaultValue = false) const; + void setKineticScrollingGesture(int kineticScroll); + + int kineticScrollingSensitivity(bool defaultValue = false) const; + void setKineticScrollingSensitivity(int sensitivity); + + bool kineticScrollingScrollbar(bool defaultValue = false) const; + void setKineticScrollingScrollbar(bool scrollbar); + void setEnableOpenGLFramerateLogging(bool value) const; bool enableOpenGLFramerateLogging(bool defaultValue = false) const; diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc --- a/libs/ui/kis_config.cc +++ b/libs/ui/kis_config.cc @@ -1712,6 +1712,36 @@ m_cfg.writeEntry("ToolOptionsInDocker", inDocker); } +int KisConfig::kineticScrollingGesture(bool defaultValue) const +{ + return (defaultValue ? 0 : m_cfg.readEntry("KineticScrollingGesture", 0)); +} + +void KisConfig::setKineticScrollingGesture(int gesture) +{ + m_cfg.writeEntry("KineticScrollingGesture", gesture); +} + +int KisConfig::kineticScrollingSensitivity(bool defaultValue) const +{ + return (defaultValue ? 75 : m_cfg.readEntry("KineticScrollingSensitivity", 75)); +} + +void KisConfig::setKineticScrollingSensitivity(int sensitivity) +{ + m_cfg.writeEntry("KineticScrollingSensitivity", sensitivity); +} + +bool KisConfig::kineticScrollingScrollbar(bool defaultValue) const +{ + return (defaultValue ? true : m_cfg.readEntry("KineticScrollingScrollbar", true)); +} + +void KisConfig::setKineticScrollingScrollbar(bool scrollbar) +{ + m_cfg.writeEntry("KineticScrollingScrollbar", scrollbar); +} + const KoColorSpace* KisConfig::customColorSelectorColorSpace(bool defaultValue) const { const KoColorSpace *cs = 0; diff --git a/libs/ui/widgets/kis_preset_chooser.cpp b/libs/ui/widgets/kis_preset_chooser.cpp --- a/libs/ui/widgets/kis_preset_chooser.cpp +++ b/libs/ui/widgets/kis_preset_chooser.cpp @@ -29,6 +29,7 @@ #include #include +#include #include @@ -214,6 +215,11 @@ m_chooser->setSynced(true); layout->addWidget(m_chooser); + KisConfig cfg; + m_chooser->configureKineticScrolling(cfg.kineticScrollingGesture(), + cfg.kineticScrollingSensitivity(), + cfg.kineticScrollingScrollbar()); + connect(m_chooser, SIGNAL(resourceSelected(KoResource*)), this, SIGNAL(resourceSelected(KoResource*))); connect(m_chooser, SIGNAL(resourceClicked(KoResource*)), diff --git a/libs/widgets/KoResourceItemChooser.h b/libs/widgets/KoResourceItemChooser.h --- a/libs/widgets/KoResourceItemChooser.h +++ b/libs/widgets/KoResourceItemChooser.h @@ -27,6 +27,7 @@ #define KO_RESOURCE_ITEM_CHOOSER #include +#include #include "kritawidgets_export.h" @@ -110,6 +111,9 @@ bool eventFilter(QObject *object, QEvent *event) override; + /// sets up this chooser for kinetic (drag triggered) scrolling + void configureKineticScrolling(int gesture, int sensitivity, bool scrollbar); + Q_SIGNALS: /// Emitted when a resource was selected void resourceSelected(KoResource *resource); diff --git a/libs/widgets/KoResourceItemChooser.cpp b/libs/widgets/KoResourceItemChooser.cpp --- a/libs/widgets/KoResourceItemChooser.cpp +++ b/libs/widgets/KoResourceItemChooser.cpp @@ -533,6 +533,61 @@ return QObject::eventFilter(object, event); } +void KoResourceItemChooser::configureKineticScrolling(int gesture, int sensitivity, bool scrollbar) +{ + QScroller::ScrollerGestureType gestureType; + + switch (gesture) { + case 1: { + gestureType = QScroller::TouchGesture; + break; + } + case 2: { + gestureType = QScroller::LeftMouseButtonGesture; + break; + } + default: + return; + } + + KoResourceItemView *view = itemView(); + + view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + if (!scrollbar) { + view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + } + + QScroller *scroller = QScroller::scroller(view); + scroller->grabGesture(view, gestureType); + + QScrollerProperties sp; + + // DragStartDistance seems to be based on meter per second; though it's + // not explicitly documented, other QScroller values are in that metric. + + // To start kinetic scrolling, with minimal sensitity, we expect a drag + // of 10 mm, with minimum sensitity any > 0 mm. + + const float mm = 0.001f; // 1 millimeter + const float resistance = 1.0f - (sensitivity / 100.0f); + + sp.setScrollMetric(QScrollerProperties::DragStartDistance, resistance * 10.0f * mm); + sp.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor, 1.0f); + sp.setScrollMetric(QScrollerProperties::MinimumVelocity, 0.0f); + sp.setScrollMetric(QScrollerProperties::AxisLockThreshold, 1.0f); + sp.setScrollMetric(QScrollerProperties::MaximumClickThroughVelocity, 0.0f); + sp.setScrollMetric(QScrollerProperties::MousePressEventDelay, 1.0f - 0.75f * resistance); + sp.setScrollMetric(QScrollerProperties::AcceleratingFlickSpeedupFactor, 1.5f); + + sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOn); + sp.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.1); + sp.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.3); + sp.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.1); + sp.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.4); + + scroller->setScrollerProperties(sp); +} + void KoResourceItemChooser::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event);