diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -16,6 +16,7 @@ endif () set(kritaui_LIB_SRCS + ../widgets/KisKineticScroller.cpp canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp @@ -205,6 +206,7 @@ tool/strokes/KisMaskingBrushCompositeOpFactory.cpp tool/strokes/move_stroke_strategy.cpp + widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp diff --git a/libs/ui/KisNodeView.h b/libs/ui/KisNodeView.h --- a/libs/ui/KisNodeView.h +++ b/libs/ui/KisNodeView.h @@ -21,6 +21,7 @@ #define KIS_DOCUMENT_SECTION_VIEW_H #include +#include #include "kritaui_export.h" class QStyleOptionViewItem; @@ -149,6 +150,7 @@ public Q_SLOTS: /// called with a theme change to refresh icon colors void slotUpdateIcons(); + void slotScrollerStateChanged(QScroller::State state); protected Q_SLOTS: void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override; diff --git a/libs/ui/KisNodeView.cpp b/libs/ui/KisNodeView.cpp --- a/libs/ui/KisNodeView.cpp +++ b/libs/ui/KisNodeView.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include "kis_node_view_color_scheme.h" @@ -99,8 +101,14 @@ setDragEnabled(true); setDragDropMode(QAbstractItemView::DragDrop); setAcceptDrops(true); - setDropIndicatorShown(true); + + { + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); + if( scroller ) + connect(scroller, SIGNAL(stateChanged(QScroller::State)), + this, SLOT(slotScrollerStateChanged(QScroller::State))); + } } KisNodeView::~KisNodeView() @@ -571,3 +579,7 @@ { d->delegate.slotUpdateIcon(); } + +void KisNodeView::slotScrollerStateChanged(QScroller::State state){ + KisKineticScroller::updateCursor(this, state); +} 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 @@ -86,9 +86,10 @@ bool showCanvasMessages(); bool compressKra(); bool toolOptionsInDocker(); + bool kineticScrollingEnabled(); int kineticScrollingGesture(); int kineticScrollingSensitivity(); - bool kineticScrollingScrollbar(); + bool kineticScrollingHiddenScrollbars(); 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 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -154,13 +155,17 @@ m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas()); - m_cmbKineticScrollingGesture->addItem(i18n("Disabled")); + m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled()); + m_cmbKineticScrollingGesture->addItem(i18n("On Touch Drag")); m_cmbKineticScrollingGesture->addItem(i18n("On Click Drag")); + m_cmbKineticScrollingGesture->addItem(i18n("On Middle-Click Drag")); m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture()); - m_kineticScrollingSensitivity->setValue(cfg.kineticScrollingSensitivity()); - m_chkKineticScrollingScrollbar->setChecked(cfg.kineticScrollingScrollbar()); + m_kineticScrollingSensitivitySlider->setRange(0, 100); + m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity()); + m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars()); + // // Miscellaneous @@ -236,9 +241,10 @@ m_chkHiDPI->setChecked(true); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); + m_groupBoxKineticScrollingSettings->setChecked(cfg.kineticScrollingEnabled(true)); m_cmbKineticScrollingGesture->setCurrentIndex(cfg.kineticScrollingGesture(true)); - m_kineticScrollingSensitivity->setValue(cfg.kineticScrollingSensitivity(true)); - m_chkKineticScrollingScrollbar->setChecked(cfg.kineticScrollingScrollbar(true)); + m_kineticScrollingSensitivitySlider->setValue(cfg.kineticScrollingSensitivity(true)); + m_chkKineticScrollingHideScrollbars->setChecked(cfg.kineticScrollingHiddenScrollbars(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); @@ -317,6 +323,11 @@ return m_radioToolOptionsInDocker->isChecked(); } +bool GeneralTab::kineticScrollingEnabled() +{ + return m_groupBoxKineticScrollingSettings->isChecked(); +} + int GeneralTab::kineticScrollingGesture() { return m_cmbKineticScrollingGesture->currentIndex(); @@ -324,12 +335,12 @@ int GeneralTab::kineticScrollingSensitivity() { - return m_kineticScrollingSensitivity->value(); + return m_kineticScrollingSensitivitySlider->value(); } -bool GeneralTab::kineticScrollingScrollbar() +bool GeneralTab::kineticScrollingHiddenScrollbars() { - return m_chkKineticScrollingScrollbar->isChecked(); + return m_chkKineticScrollingHideScrollbars->isChecked(); } bool GeneralTab::switchSelectionCtrlAlt() @@ -1320,9 +1331,12 @@ kritarc.setValue("EnableSingleApplication", dialog->m_general->m_chkSingleApplication->isChecked()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); + + cfg.setKineticScrollingEnabled(dialog->m_general->kineticScrollingEnabled()); cfg.setKineticScrollingGesture(dialog->m_general->kineticScrollingGesture()); cfg.setKineticScrollingSensitivity(dialog->m_general->kineticScrollingSensitivity()); - cfg.setKineticScrollingScrollbar(dialog->m_general->kineticScrollingScrollbar()); + cfg.setKineticScrollingHideScrollbars(dialog->m_general->kineticScrollingHiddenScrollbars()); + 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 @@ -26,7 +26,7 @@ - 0 + 2 @@ -424,10 +424,25 @@ - + + + true + + + Enabling kinetic scrolling allows you to scroll Krita's user interface panels and dockers using various mouse or touch gestures anywhere inside the scrollable area. + Kinetic Scrolling (needs restart) + + false + + + true + + + true + @@ -437,44 +452,25 @@ - Sensitivity (0-100): + Sensitivity: - - - - 0 - 0 - - - - - 50 - 0 - - - - 0 - - - 100 - - - 1 - - - 75 - - + - + + + true + - Show Scrollbar + Hide Scrollbars + + + false @@ -796,6 +792,11 @@ QPushButton
kis_color_button.h
+ + KisSliderSpinBox + QWidget +
kis_slider_spin_box.h
+
@@ -804,6 +805,16 @@ toggled(bool) m_autosaveSpinBox setEnabled(bool) + + + 20 + 20 + + + 20 + 20 + + 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 @@ -509,14 +509,17 @@ bool toolOptionsInDocker(bool defaultValue = false) const; void setToolOptionsInDocker(bool inDocker); + bool kineticScrollingEnabled(bool defaultValue = false) const; + void setKineticScrollingEnabled(bool enabled); + 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); + bool kineticScrollingHiddenScrollbars(bool defaultValue = false) const; + void setKineticScrollingHideScrollbars(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 @@ -1724,9 +1724,19 @@ m_cfg.writeEntry("ToolOptionsInDocker", inDocker); } +bool KisConfig::kineticScrollingEnabled(bool defaultValue) const +{ + return (defaultValue ? true : m_cfg.readEntry("KineticScrollingEnabled", true)); +} + +void KisConfig::setKineticScrollingEnabled(bool value) +{ + m_cfg.writeEntry("KineticScrollingEnabled", value); +} + int KisConfig::kineticScrollingGesture(bool defaultValue) const { - return (defaultValue ? 0 : m_cfg.readEntry("KineticScrollingGesture", 0)); + return (defaultValue ? 2 : m_cfg.readEntry("KineticScrollingGesture", 2)); } void KisConfig::setKineticScrollingGesture(int gesture) @@ -1744,14 +1754,14 @@ m_cfg.writeEntry("KineticScrollingSensitivity", sensitivity); } -bool KisConfig::kineticScrollingScrollbar(bool defaultValue) const +bool KisConfig::kineticScrollingHiddenScrollbars(bool defaultValue) const { - return (defaultValue ? true : m_cfg.readEntry("KineticScrollingScrollbar", true)); + return (defaultValue ? false : m_cfg.readEntry("KineticScrollingHideScrollbar", false)); } -void KisConfig::setKineticScrollingScrollbar(bool scrollbar) +void KisConfig::setKineticScrollingHideScrollbars(bool scrollbar) { - m_cfg.writeEntry("KineticScrollingScrollbar", scrollbar); + m_cfg.writeEntry("KineticScrollingHideScrollbar", scrollbar); } const KoColorSpace* KisConfig::customColorSelectorColorSpace(bool defaultValue) const diff --git a/libs/ui/widgets/kis_categorized_list_view.h b/libs/ui/widgets/kis_categorized_list_view.h --- a/libs/ui/widgets/kis_categorized_list_view.h +++ b/libs/ui/widgets/kis_categorized_list_view.h @@ -22,7 +22,7 @@ #include #include #include - +#include class KRITAUI_EXPORT KisCategorizedListView: public QListView { @@ -49,6 +49,7 @@ void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; + void slotScrollerStateChange(QScroller::State state); private: void updateRows(int begin, int end); diff --git a/libs/ui/widgets/kis_categorized_list_view.cpp b/libs/ui/widgets/kis_categorized_list_view.cpp --- a/libs/ui/widgets/kis_categorized_list_view.cpp +++ b/libs/ui/widgets/kis_categorized_list_view.cpp @@ -26,11 +26,18 @@ #include #include #include "kis_debug.h" +#include KisCategorizedListView::KisCategorizedListView(QWidget* parent): QListView(parent) { connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(slotIndexChanged(QModelIndex))); + + { + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); + if (scroller) + connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); + } } KisCategorizedListView::~KisCategorizedListView() @@ -167,5 +174,10 @@ QListView::mouseReleaseEvent(event); } +void KisCategorizedListView::slotScrollerStateChange(QScroller::State state) +{ + KisKineticScroller::updateCursor(this, state); +} + diff --git a/libs/ui/widgets/kis_gradient_chooser.cc b/libs/ui/widgets/kis_gradient_chooser.cc --- a/libs/ui/widgets/kis_gradient_chooser.cc +++ b/libs/ui/widgets/kis_gradient_chooser.cc @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -119,11 +121,6 @@ mainLayout->addWidget(m_itemChooser, 10); mainLayout->addWidget(buttonWidget); - KisConfig cfg(true); - m_itemChooser->configureKineticScrolling(cfg.kineticScrollingGesture(), - cfg.kineticScrollingSensitivity(), - cfg.kineticScrollingScrollbar()); - slotUpdateIcons(); setLayout(mainLayout); } diff --git a/libs/ui/widgets/kis_pattern_chooser.cc b/libs/ui/widgets/kis_pattern_chooser.cc --- a/libs/ui/widgets/kis_pattern_chooser.cc +++ b/libs/ui/widgets/kis_pattern_chooser.cc @@ -65,11 +65,6 @@ mainLayout->addWidget(m_lblName); mainLayout->addWidget(m_itemChooser, 10); - KisConfig cfg(true); - m_itemChooser->configureKineticScrolling(cfg.kineticScrollingGesture(), - cfg.kineticScrollingSensitivity(), - cfg.kineticScrollingScrollbar()); - setLayout(mainLayout); } diff --git a/libs/ui/widgets/kis_preset_chooser.h b/libs/ui/widgets/kis_preset_chooser.h --- a/libs/ui/widgets/kis_preset_chooser.h +++ b/libs/ui/widgets/kis_preset_chooser.h @@ -21,6 +21,7 @@ #define KIS_ITEM_CHOOSER_H_ #include +#include #include #include @@ -76,6 +77,8 @@ /// saves the icon size for the presets. called by the horizontal slider release event. void saveIconSize(); + void slotScrollerStateChanged(QScroller::State state); + private Q_SLOTS: void notifyConfigChanged(); 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 @@ -31,7 +31,7 @@ #include #include - +#include #include #include @@ -216,11 +216,12 @@ m_chooser->setSynced(true); layout->addWidget(m_chooser); - KisConfig cfg(true); - m_chooser->configureKineticScrolling(cfg.kineticScrollingGesture(), - cfg.kineticScrollingSensitivity(), - cfg.kineticScrollingScrollbar()); - + { + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this->itemChooser()->itemView()); + if(scroller) + connect(scroller, SIGNAL(stateChanged(QScroller::State)), + this, SLOT(slotScrollerStateChanged(QScroller::State))); + } connect(m_chooser, SIGNAL(resourceSelected(KoResource*)), this, SIGNAL(resourceSelected(KoResource*))); connect(m_chooser, SIGNAL(resourceClicked(KoResource*)), @@ -359,3 +360,8 @@ KisConfig cfg(false); cfg.setPresetIconSize(iconSize()); } + +void KisPresetChooser::slotScrollerStateChanged(QScroller::State state) +{ + KisKineticScroller::updateCursor(this, state); +} diff --git a/libs/ui/widgets/kis_workspace_chooser.cpp b/libs/ui/widgets/kis_workspace_chooser.cpp --- a/libs/ui/widgets/kis_workspace_chooser.cpp +++ b/libs/ui/widgets/kis_workspace_chooser.cpp @@ -27,10 +27,12 @@ #include #include #include +#include #include #include +#include #include #include @@ -75,9 +77,7 @@ painter->fillRect(option.rect, option.palette.base()); } - painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, workspace->name()); - } KisWorkspaceChooser::KisWorkspaceChooser(KisViewManager * view, QWidget* parent): QWidget(parent), m_view(view) @@ -120,11 +120,6 @@ widgets.itemChooser->showTaggingBar(false); widgets.saveButton = new QPushButton(i18n("Save")); - KisConfig cfg(true); - widgets.itemChooser->configureKineticScrolling(cfg.kineticScrollingGesture(), - cfg.kineticScrollingSensitivity(), - cfg.kineticScrollingScrollbar()); - widgets.nameEdit = new QLineEdit(this); widgets.nameEdit->setPlaceholderText(i18n("Insert name")); widgets.nameEdit->setClearButtonEnabled(true); diff --git a/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt --- a/libs/widgets/CMakeLists.txt +++ b/libs/widgets/CMakeLists.txt @@ -55,6 +55,8 @@ KoToolBoxDocker.cpp KoToolBoxFactory.cpp KoToolDocker.cpp + + KisKineticScroller.cpp KisPaletteModel.cpp kis_palette_delegate.cpp diff --git a/libs/widgets/KisColorsetChooser.cpp b/libs/widgets/KisColorsetChooser.cpp --- a/libs/widgets/KisColorsetChooser.cpp +++ b/libs/widgets/KisColorsetChooser.cpp @@ -28,10 +28,13 @@ #include #include +#include #include #include #include #include +#include + #include #include @@ -93,11 +96,6 @@ connect(m_itemChooser, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*))); - KConfigGroup cfg = KSharedConfig::openConfig()->group(""); - m_itemChooser->configureKineticScrolling(cfg.readEntry("KineticScrollingGesture", 0), - cfg.readEntry("KineticScrollingSensitivity", 75), - cfg.readEntry("KineticScrollingScrollbar", true)); - QPushButton* saveButton = new QPushButton(i18n("Save")); connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSave())); diff --git a/libs/widgets/KisKineticScroller.h b/libs/widgets/KisKineticScroller.h new file mode 100644 --- /dev/null +++ b/libs/widgets/KisKineticScroller.h @@ -0,0 +1,38 @@ +/* This file is part of the KDE project + * Copyright (C) 2018 Emmet O'Neill + * Copyright (C) 2018 Eoin O'Neill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef KISKINECTICSCROLLER_H +#define KISKINECTICSCROLLER_H +#include + +class QAbstractScrollArea; + +/* This is a convenience namespace for setting up global kinetic scrolling + * with consistent settings across various UI elements within Krita. */ + +namespace KisKineticScroller { +QScroller* createPreconfiguredScroller(QAbstractScrollArea *target); + +QScroller::ScrollerGestureType getConfiguredGestureType(); + +void updateCursor(QWidget *source, QScroller::State state); +} + +#endif // KISKINECTICSCROLLER_H diff --git a/libs/widgets/KisKineticScroller.cpp b/libs/widgets/KisKineticScroller.cpp new file mode 100644 --- /dev/null +++ b/libs/widgets/KisKineticScroller.cpp @@ -0,0 +1,108 @@ +/* This file is part of the KDE project + * Copyright (C) 2018 Emmet O'Neill + * Copyright (C) 2018 Eoin O'Neill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +QScroller* KisKineticScroller::createPreconfiguredScroller(QAbstractScrollArea *scrollArea) { + KConfigGroup config = KSharedConfig::openConfig()->group(""); + int sensitivity = config.readEntry("KineticScrollingSensitivity", 75); + bool enabled = config.readEntry("KineticScrollingEnabled", false); + bool hideScrollBars = config.readEntry("KineticScrollingHideScrollbar", false); + QScroller::ScrollerGestureType gestureType = getConfiguredGestureType(); + + if(enabled && scrollArea){ + if(hideScrollBars){ + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); + } + + QAbstractItemView *itemView = qobject_cast(scrollArea); + if(itemView){ + itemView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + } + + QScroller *scroller = QScroller::scroller(scrollArea); + scroller->grabGesture(scrollArea, gestureType); + + QScrollerProperties properties; + + // 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; + const float resistance = 1.0f - (sensitivity / 100.0f); + + properties.setScrollMetric(QScrollerProperties::DragStartDistance, resistance * 10.0f * mm); + properties.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor, 1.0f); + properties.setScrollMetric(QScrollerProperties::MinimumVelocity, 0.0f); + properties.setScrollMetric(QScrollerProperties::AxisLockThreshold, 1.0f); + properties.setScrollMetric(QScrollerProperties::MaximumClickThroughVelocity, 0.0f); + properties.setScrollMetric(QScrollerProperties::MousePressEventDelay, 1.0f - 0.75f * resistance); + properties.setScrollMetric(QScrollerProperties::AcceleratingFlickSpeedupFactor, 1.5f); + + properties.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOn); + properties.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.1); + properties.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.3); + properties.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.1); + properties.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.4); + + scroller->setScrollerProperties(properties); + + return scroller; + } + + return nullptr; +} + +QScroller::ScrollerGestureType KisKineticScroller::getConfiguredGestureType() { + KConfigGroup config = KSharedConfig::openConfig()->group(""); + int gesture = config.readEntry("KineticScrollingGesture", 0); + + switch (gesture) { + case 0: { + return QScroller::TouchGesture; + } + case 1: { + return QScroller::LeftMouseButtonGesture; + } + case 2: { + return QScroller::MiddleMouseButtonGesture; + } + case 3: { + return QScroller::RightMouseButtonGesture; + } + default: + return QScroller::MiddleMouseButtonGesture; + } +} + +void KisKineticScroller::updateCursor(QWidget *source, QScroller::State state) { + if( state == QScroller::State::Pressed ) { + source->setCursor(Qt::OpenHandCursor); + } else if (state == QScroller::State::Dragging) { + source->setCursor(Qt::ClosedHandCursor); + } else { + source->setCursor(Qt::ArrowCursor); + } +} diff --git a/libs/widgets/KoResourceItemChooser.h b/libs/widgets/KoResourceItemChooser.h --- a/libs/widgets/KoResourceItemChooser.h +++ b/libs/widgets/KoResourceItemChooser.h @@ -112,9 +112,6 @@ 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 @@ -546,61 +546,6 @@ 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); diff --git a/libs/widgets/KoResourceItemView.h b/libs/widgets/KoResourceItemView.h --- a/libs/widgets/KoResourceItemView.h +++ b/libs/widgets/KoResourceItemView.h @@ -23,6 +23,8 @@ #include #include +#include +#include class QEvent; class QModelIndex; @@ -55,6 +57,7 @@ private Q_SLOTS: void slotItemClicked(const QModelIndex &index); + void slotScrollerStateChange(QScroller::State state){ KisKineticScroller::updateCursor(this, state); } private: KoIconToolTip m_tip; diff --git a/libs/widgets/KoResourceItemView.cpp b/libs/widgets/KoResourceItemView.cpp --- a/libs/widgets/KoResourceItemView.cpp +++ b/libs/widgets/KoResourceItemView.cpp @@ -19,7 +19,9 @@ */ #include "KoResourceItemView.h" +#include #include +#include #include #include @@ -28,6 +30,10 @@ : KoTableView(parent) { connect(this, SIGNAL(clicked(QModelIndex)), SLOT(slotItemClicked(QModelIndex))); + + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); + if(scroller) + connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); } bool KoResourceItemView::viewportEvent(QEvent *event) diff --git a/libs/widgets/KoTableView.h b/libs/widgets/KoTableView.h --- a/libs/widgets/KoTableView.h +++ b/libs/widgets/KoTableView.h @@ -20,8 +20,10 @@ #define KOTABLEVIEW_H #include +#include #include "kritawidgets_export.h" +#include class QEvent; class QModelIndex; @@ -53,6 +55,9 @@ void updateView(); +public Q_SLOTS: + void slotScrollerStateChange(QScroller::State state){ KisKineticScroller::updateCursor(this, state); } + Q_SIGNALS: void sigSizeChanged(); diff --git a/libs/widgets/KoTableView.cpp b/libs/widgets/KoTableView.cpp --- a/libs/widgets/KoTableView.cpp +++ b/libs/widgets/KoTableView.cpp @@ -30,6 +30,10 @@ verticalHeader()->setDefaultSectionSize(20); setContextMenuPolicy(Qt::DefaultContextMenu); setViewMode(FIXED_COLUMNS); + + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); + if(scroller) + connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); } void KoTableView::resizeEvent(QResizeEvent *event) diff --git a/libs/widgets/KoToolBoxScrollArea_p.h b/libs/widgets/KoToolBoxScrollArea_p.h --- a/libs/widgets/KoToolBoxScrollArea_p.h +++ b/libs/widgets/KoToolBoxScrollArea_p.h @@ -28,6 +28,7 @@ #include #include #include +#include class KoToolBoxScrollArea : public QScrollArea { @@ -56,17 +57,21 @@ m_scrollNext->setFocusPolicy(Qt::NoFocus); connect(m_scrollNext, &QToolButton::clicked, this, &KoToolBoxScrollArea::doScrollNext); - QScroller::grabGesture(viewport(), QScroller::LeftMouseButtonGesture); - QScroller *scroller = QScroller::scroller(viewport()); - QScrollerProperties sp = scroller->scrollerProperties(); + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); + if(!scroller){ + QScroller::grabGesture(viewport(), QScroller::MiddleMouseButtonGesture); + QScroller *scroller = QScroller::scroller(viewport()); + QScrollerProperties sp = scroller->scrollerProperties(); - sp.setScrollMetric(QScrollerProperties::MaximumVelocity, 0.0); - sp.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.1); - sp.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.1); - sp.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.0); - sp.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.4); + sp.setScrollMetric(QScrollerProperties::MaximumVelocity, 0.0); + sp.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.1); + sp.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.1); + sp.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.0); + sp.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.4); - scroller->setScrollerProperties(sp); + scroller->setScrollerProperties(sp); + } + connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); } void setOrientation(Qt::Orientation orientation) @@ -147,6 +152,8 @@ } } + void slotScrollerStateChange(QScroller::State state){ KisKineticScroller::updateCursor(this, state); } + private: int scrollButtonWidth() const { diff --git a/libs/widgets/KoToolDocker.h b/libs/widgets/KoToolDocker.h --- a/libs/widgets/KoToolDocker.h +++ b/libs/widgets/KoToolDocker.h @@ -23,6 +23,8 @@ #include #include +#include +#include class QWidget; @@ -50,6 +52,7 @@ * Update the option widgets to the argument one, removing the currently set widget. */ void setOptionWidgets(const QList > &optionWidgetList); + void slotScrollerStateChange(QScroller::State state); /** * Returns whether the docker has an optionwidget attached diff --git a/libs/widgets/KoToolDocker.cpp b/libs/widgets/KoToolDocker.cpp --- a/libs/widgets/KoToolDocker.cpp +++ b/libs/widgets/KoToolDocker.cpp @@ -33,11 +33,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -182,6 +184,11 @@ d->scrollArea->setWidgetResizable(true); d->scrollArea->setFocusPolicy(Qt::NoFocus); + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(d->scrollArea); + if( scroller ) { + connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); + } + setWidget(d->scrollArea); } @@ -200,6 +207,11 @@ d->recreateLayout(optionWidgetList); } +void KoToolDocker::slotScrollerStateChange(QScroller::State state) +{ + KisKineticScroller::updateCursor(d->scrollArea, state); +} + void KoToolDocker::resetWidgets() { d->resetWidgets(); diff --git a/libs/widgets/kis_palette_view.cpp b/libs/widgets/kis_palette_view.cpp --- a/libs/widgets/kis_palette_view.cpp +++ b/libs/widgets/kis_palette_view.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include #include "kis_palette_delegate.h" diff --git a/plugins/dockers/animation/CMakeLists.txt b/plugins/dockers/animation/CMakeLists.txt --- a/plugins/dockers/animation/CMakeLists.txt +++ b/plugins/dockers/animation/CMakeLists.txt @@ -3,6 +3,7 @@ endif() set(KRITA_ANIMATIONDOCKER_SOURCES + ../../../libs/widgets/KisKineticScroller.cpp animation_dockers.cpp animation_docker.cpp timeline_docker.cpp diff --git a/plugins/dockers/animation/timeline_frames_view.h b/plugins/dockers/animation/timeline_frames_view.h --- a/plugins/dockers/animation/timeline_frames_view.h +++ b/plugins/dockers/animation/timeline_frames_view.h @@ -22,6 +22,7 @@ #include #include +#include #include "kis_action_manager.h" #include "kritaanimationdocker_export.h" @@ -136,6 +137,9 @@ void slotUpdateAudioActions(); void slotAudioVolumeChanged(int value); + // DragScroll + void slotScrollerStateChanged(QScroller::State state); + private: void setFramesPerSecond(int fps); diff --git a/plugins/dockers/animation/timeline_frames_view.cpp b/plugins/dockers/animation/timeline_frames_view.cpp --- a/plugins/dockers/animation/timeline_frames_view.cpp +++ b/plugins/dockers/animation/timeline_frames_view.cpp @@ -29,12 +29,14 @@ #include #include #include +#include #include #include #include #include #include "KSharedConfig" +#include "KisKineticScroller.h" #include "kis_zoom_button.h" #include "kis_icon_utils.h" @@ -270,6 +272,13 @@ setFramesPerSecond(12); setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + { + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); + if( scroller ) + connect(scroller, SIGNAL(stateChanged(QScroller::State)), + this, SLOT(slotScrollerStateChanged(QScroller::State))); + } + connect(&m_d->selectionChangedCompressor, SIGNAL(timeout()), SLOT(slotSelectionChanged())); connect(&m_d->selectionChangedCompressor, SIGNAL(timeout()), @@ -552,6 +561,10 @@ m_d->model->setLastVisibleFrame(calculatedIndex); } +void TimelineFramesView::slotScrollerStateChanged( QScroller::State state ) { + KisKineticScroller::updateCursor(this, state); +} + void TimelineFramesView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { QTableView::currentChanged(current, previous); diff --git a/plugins/dockers/compositiondocker/CMakeLists.txt b/plugins/dockers/compositiondocker/CMakeLists.txt --- a/plugins/dockers/compositiondocker/CMakeLists.txt +++ b/plugins/dockers/compositiondocker/CMakeLists.txt @@ -1,4 +1,4 @@ -set(KRITA_COMPOSITIONDOCKER_SOURCES compositionmodel.cpp compositiondocker.cpp compositiondocker_dock.cpp ) +set(KRITA_COMPOSITIONDOCKER_SOURCES ../../../libs/widgets/KisKineticScroller.cpp compositionmodel.cpp compositiondocker.cpp compositiondocker_dock.cpp ) ki18n_wrap_ui(KRITA_COMPOSITIONDOCKER_SOURCES wdgcompositiondocker.ui diff --git a/plugins/dockers/compositiondocker/compositiondocker_dock.cpp b/plugins/dockers/compositiondocker/compositiondocker_dock.cpp --- a/plugins/dockers/compositiondocker/compositiondocker_dock.cpp +++ b/plugins/dockers/compositiondocker/compositiondocker_dock.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,6 @@ saveButton->setToolTip(i18n("New Composition")); exportButton->setToolTip(i18n("Export Composition")); - setWidget(widget); connect( compositionView, SIGNAL(doubleClicked(QModelIndex)), @@ -79,6 +79,7 @@ connect( exportButton, SIGNAL(clicked(bool)), this, SLOT(exportClicked())); saveNameEdit->setPlaceholderText(i18n("Insert Name")); + QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(compositionView); } diff --git a/plugins/dockers/historydocker/KisUndoView.cpp b/plugins/dockers/historydocker/KisUndoView.cpp --- a/plugins/dockers/historydocker/KisUndoView.cpp +++ b/plugins/dockers/historydocker/KisUndoView.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include "kis_double_parse_spin_box.h" #include "kis_int_parse_spin_box.h" @@ -130,6 +131,7 @@ , d(new KisUndoViewPrivate) { d->init(this); + } /*! diff --git a/plugins/paintops/libpaintop/CMakeLists.txt b/plugins/paintops/libpaintop/CMakeLists.txt --- a/plugins/paintops/libpaintop/CMakeLists.txt +++ b/plugins/paintops/libpaintop/CMakeLists.txt @@ -1,4 +1,5 @@ set(kritalibpaintop_LIB_SRCS + ../../../libs/widgets/KisKineticScroller.cpp kis_airbrush_option_widget.cpp kis_auto_brush_widget.cpp kis_spacing_selection_widget.cpp diff --git a/plugins/paintops/libpaintop/kis_brush_chooser.h b/plugins/paintops/libpaintop/kis_brush_chooser.h --- a/plugins/paintops/libpaintop/kis_brush_chooser.h +++ b/plugins/paintops/libpaintop/kis_brush_chooser.h @@ -20,6 +20,7 @@ #include #include +#include #include "kritapaintop_export.h" #include "ui_wdgpredefinedbrushchooser.h" diff --git a/plugins/paintops/libpaintop/kis_brush_chooser.cpp b/plugins/paintops/libpaintop/kis_brush_chooser.cpp --- a/plugins/paintops/libpaintop/kis_brush_chooser.cpp +++ b/plugins/paintops/libpaintop/kis_brush_chooser.cpp @@ -36,7 +36,9 @@ #include #include #include +#include +#include #include #include @@ -118,7 +120,6 @@ QObject::connect(brushSizeSpinBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetItemSize(qreal))); - brushRotationSpinBox->setRange(0, 360, 0); brushRotationSpinBox->setValue(0); brushRotationSpinBox->setSuffix(QChar(Qt::Key_degree)); @@ -127,10 +128,8 @@ brushSpacingSelectionWidget->setSpacing(true, 1.0); connect(brushSpacingSelectionWidget, SIGNAL(sigSpacingChanged()), SLOT(slotSpacingChanged())); - QObject::connect(useColorAsMaskCheckbox, SIGNAL(toggled(bool)), this, SLOT(slotSetItemUseColorAsMask(bool))); - KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer(); QSharedPointer adapter(new KisBrushResourceServerAdapter(rServer)); @@ -147,23 +146,14 @@ m_itemChooser->setMinimumHeight(150); m_itemChooser->showButtons(false); // turn the import and delete buttons since we want control over them - KisConfig cfg(true); - m_itemChooser->configureKineticScrolling(cfg.kineticScrollingGesture(), - cfg.kineticScrollingSensitivity(), - cfg.kineticScrollingScrollbar()); - - addPresetButton->setIcon(KisIconUtils::loadIcon("list-add")); deleteBrushTipButton->setIcon(KisIconUtils::loadIcon("trash-empty")); - - connect(addPresetButton, SIGNAL(clicked(bool)), this, SLOT(slotImportNewBrushResource())); connect(deleteBrushTipButton, SIGNAL(clicked(bool)), this, SLOT(slotDeleteBrushResource())); presetsLayout->addWidget(m_itemChooser); - connect(m_itemChooser, SIGNAL(resourceSelected(KoResource *)), this, SLOT(updateBrushTip(KoResource *))); stampButton->setIcon(KisIconUtils::loadIcon("list-add")); @@ -173,7 +163,6 @@ clipboardButton->setIcon(KisIconUtils::loadIcon("list-add")); clipboardButton->setToolTip(i18n("Creates a brush tip from the image in the clipboard.")); - connect(stampButton, SIGNAL(clicked()), this, SLOT(slotOpenStampBrush())); connect(clipboardButton, SIGNAL(clicked()), SLOT(slotOpenClipboardBrush())); @@ -352,7 +341,6 @@ brushTypeString = i18n("Animated Image"); } - QString brushDetailsText = QString("%1 (%2 x %3) %4") .arg(brushTypeString) .arg(m_brush->width()) @@ -370,7 +358,6 @@ m_brush->setUserEffectiveSize(brushSizeSpinBox->value()); } - brushSpacingSelectionWidget->setSpacing(m_brush->autoSpacingActive(), m_brush->autoSpacingActive() ? m_brush->autoSpacingCoeff() : m_brush->spacing()); @@ -378,7 +365,6 @@ brushRotationSpinBox->setValue(m_brush->angle() * 180 / M_PI); brushSizeSpinBox->setValue(m_brush->width() * m_brush->scale()); - // useColorAsMask support is only in gimp brush so far KisGbrBrush *gimpBrush = dynamic_cast(m_brush.data()); if (gimpBrush) {