]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Improve the autoscrolling for the rubberband selection
authorPeter Penz <peter.penz19@gmail.com>
Sat, 27 Aug 2011 18:12:03 +0000 (20:12 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Sat, 27 Aug 2011 18:13:22 +0000 (20:13 +0200)
This modifications will also allow to do an autoscrolling in an
easy way for drag and drop operations (not fully implemented yet).

src/kitemviews/kitemlistcontainer.cpp
src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistview.cpp
src/kitemviews/kitemlistview.h

index ec759bdb32a26bcddb39c3b11c4c5b3e81789ed9..0d2637da633f658add93bf54c9e092dcf53ca6f2 100644 (file)
@@ -120,7 +120,14 @@ void KItemListContainer::scrollContentsBy(int dx, int dy)
         return;
     }
 
+    const QScrollBar* scrollBar = (view->scrollOrientation() == Qt::Vertical)
+                                  ? verticalScrollBar() : horizontalScrollBar();
     const qreal currentOffset = view->offset();
+    if (static_cast<int>(currentOffset) == scrollBar->value()) {
+        // The current offset is already synchronous to the scrollbar
+        return;
+    }
+
     qreal offsetDiff = (view->scrollOrientation() == Qt::Vertical) ? dy : dx;
 
     const bool animRunning = (m_smoothScrollingAnimation->state() == QAbstractAnimation::Running);
index ddae06c17c4f2fd27a50d7de5a1302bca39f674d..78c0a35946717e69b02121e2e966765cc23769b9 100644 (file)
@@ -306,6 +306,7 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const
         rubberBand->setEndPosition(startPos);
         rubberBand->setActive(true);
         connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged()));
+        m_view->setAutoScroll(true);
     }
 
     return false;
@@ -365,6 +366,7 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con
         disconnect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged()));
         rubberBand->setActive(false);
         m_oldSelection.clear();
+        m_view->setAutoScroll(false);
 
         if (rubberBand->startPosition() != rubberBand->endPosition()) {
             clearSelection = false;
index 3435e3f6531bda7d8b5fadf36c49c54e52494c7f..a35752a473ce3493c44e15cecfd9a0ddc32acff5 100644 (file)
@@ -43,7 +43,6 @@
 
 KItemListView::KItemListView(QGraphicsWidget* parent) :
     QGraphicsWidget(parent),
-    m_autoScrollMarginEnabled(false),
     m_grouped(false),
     m_activeTransactions(0),
     m_itemSize(),
@@ -62,8 +61,10 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
     m_layoutTimer(0),
     m_oldOffset(0),
     m_oldMaximumOffset(0),
+    m_skipAutoScrollForRubberBand(false),
     m_rubberBand(0),
-    m_mousePos()
+    m_mousePos(),
+    m_autoScrollTimer(0)
 {
     setAcceptHoverEvents(true);
 
@@ -193,6 +194,26 @@ QHash<QByteArray, int> KItemListView::visibleRoles() const
     return m_visibleRoles;
 }
 
+void KItemListView::setAutoScroll(bool enabled)
+{
+    if (enabled && !m_autoScrollTimer) {
+        m_autoScrollTimer = new QTimer(this);
+        m_autoScrollTimer->setInterval(1000 / 60); // 60 frames per second
+        m_autoScrollTimer->setSingleShot(false);
+        connect(m_autoScrollTimer, SIGNAL(timeout()), this, SLOT(triggerAutoScrolling()));
+        m_autoScrollTimer->start();
+    } else if (!enabled && m_autoScrollTimer) {
+        delete m_autoScrollTimer;
+        m_autoScrollTimer = 0;
+    }
+
+}
+
+bool KItemListView::autoScroll() const
+{
+    return m_autoScrollTimer != 0;
+}
+
 KItemListController* KItemListView::controller() const
 {
     return m_controller;
@@ -463,6 +484,10 @@ void KItemListView::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
 {
     m_mousePos = transform().map(event->pos());
     QGraphicsWidget::mouseMoveEvent(event);
+
+    if (m_autoScrollTimer && !m_autoScrollTimer->isActive()) {
+        m_autoScrollTimer->start();
+    }
 }
 
 void KItemListView::dragEnterEvent(QGraphicsSceneDragDropEvent* event)
@@ -755,29 +780,21 @@ void KItemListView::slotLayoutTimerFinished()
     doLayout(Animation, 0, 0);
 }
 
-void KItemListView::slotRubberBandStartPosChanged()
+void KItemListView::slotRubberBandPosChanged()
 {
     update();
 }
 
-void KItemListView::slotRubberBandEndPosChanged()
-{
-    // The autoscrolling is triggered asynchronously otherwise it
-    // might be possible to have an endless recursion: The autoscrolling
-    // might adjust the position which might result in updating the
-    // rubberband end-position.
-    QTimer::singleShot(0, this, SLOT(triggerAutoScrolling()));
-    update();
-}
-
 void KItemListView::slotRubberBandActivationChanged(bool active)
 {
     if (active) {
-        connect(m_rubberBand, SIGNAL(startPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandStartPosChanged()));
-        connect(m_rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandEndPosChanged()));
+        connect(m_rubberBand, SIGNAL(startPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandPosChanged()));
+        connect(m_rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandPosChanged()));
+        m_skipAutoScrollForRubberBand = true;
     } else {
-        disconnect(m_rubberBand, SIGNAL(startPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandStartPosChanged()));
-        disconnect(m_rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandEndPosChanged()));
+        disconnect(m_rubberBand, SIGNAL(startPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandPosChanged()));
+        disconnect(m_rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandPosChanged()));
+        m_skipAutoScrollForRubberBand = false;
     }
 
     update();
@@ -785,6 +802,10 @@ void KItemListView::slotRubberBandActivationChanged(bool active)
 
 void KItemListView::triggerAutoScrolling()
 {
+    if (!m_autoScrollTimer) {
+        return;
+    }
+
     int pos = 0;
     int visibleSize = 0;
     if (scrollOrientation() == Qt::Vertical) {
@@ -797,13 +818,17 @@ void KItemListView::triggerAutoScrolling()
 
     const int inc = calculateAutoScrollingIncrement(pos, visibleSize);
     if (inc == 0) {
-        // The mouse position is not above an autoscroll margin
+        // The mouse position is not above an autoscroll margin (the autoscroll timer
+        // will be restarted in mouseMoveEvent())
+        m_autoScrollTimer->stop();
         return;
     }
 
-    if (m_rubberBand->isActive()) {
+    if (m_rubberBand->isActive() && m_skipAutoScrollForRubberBand) {
         // If a rubberband selection is ongoing the autoscrolling may only get triggered
-        // if the direction of the rubberband is similar to the autoscroll direction.
+        // if the direction of the rubberband is similar to the autoscroll direction. This
+        // prevents that starting to create a rubberband within the autoscroll margins starts
+        // an autoscrolling.
 
         const qreal minDiff = 4; // Ignore any autoscrolling if the rubberband is very small
         const qreal diff = (scrollOrientation() == Qt::Vertical)
@@ -812,11 +837,22 @@ void KItemListView::triggerAutoScrolling()
         if (qAbs(diff) < minDiff || (inc < 0 && diff > 0) || (inc > 0 && diff < 0)) {
             // The rubberband direction is different from the scroll direction (e.g. the rubberband has
             // been moved up although the autoscroll direction might be down)
+            m_autoScrollTimer->stop();
             return;
         }
     }
 
-    emit scrollTo(offset() + inc);
+    // As soon as the autoscrolling has been triggered at least once despite having an active rubberband,
+    // the autoscrolling may not get skipped anymore until a new rubberband is created
+    m_skipAutoScrollForRubberBand = false;
+
+    setOffset(offset() + inc);
+
+    if (!m_autoScrollTimer->isActive()) {
+       // Trigger the autoscroll timer which will periodically call
+       // triggerAutoScrolling()
+       m_autoScrollTimer->start();
+    }
 }
 
 void KItemListView::setController(KItemListController* controller)
@@ -1230,8 +1266,8 @@ int KItemListView::calculateAutoScrollingIncrement(int pos, int size)
     int inc = 0;
 
     const int minSpeed = 4;
-    const int maxSpeed = 768;
-    const int speedLimiter = 48;
+    const int maxSpeed = 128;
+    const int speedLimiter = 96;
     const int autoScrollBorder = 64;
 
     if (pos < autoScrollBorder) {
index 344221e40135850a5d09c542cfa573b1c69ccd45..9977e3639f8f3a3cedb807c1cb7888aa146d76f2 100644 (file)
@@ -89,6 +89,14 @@ public:
     void setVisibleRoles(const QHash<QByteArray, int>& roles);
     QHash<QByteArray, int> visibleRoles() const;
 
+    /**
+     * If set to true an automatic scrolling is done as soon as the
+     * mouse is moved near the borders of the view. Per default
+     * the automatic scrolling is turned off.
+     */
+    void setAutoScroll(bool enabled);
+    bool autoScroll() const;
+
     /**
      * @return Controller of the item-list. The controller gets
      *         initialized by KItemListController::setView() and will
@@ -124,6 +132,7 @@ public:
     void setStyleOption(const KItemListStyleOption& option);
     const KItemListStyleOption& styleOption() const;
 
+    /** @reimp */
     virtual void setGeometry(const QRectF& rect);
 
     int itemAt(const QPointF& pos) const;
@@ -207,13 +216,13 @@ private slots:
                                KItemListViewAnimation::AnimationType type);
     void slotLayoutTimerFinished();
 
-    void slotRubberBandStartPosChanged();
-    void slotRubberBandEndPosChanged();
+    void slotRubberBandPosChanged();
     void slotRubberBandActivationChanged(bool active);
 
     /**
-     * Emits the signal scrollTo() with the corresponding target offset if the current
-     * mouse position is above the autoscroll-margin.
+     * Triggers the autoscrolling if autoScroll() is enabled by checking the
+     * current mouse position. If the mouse position is within the autoscroll
+     * margins a timer will be started that periodically triggers the autoscrolling.
      */
     void triggerAutoScrolling();
 
@@ -289,7 +298,6 @@ private:
     static int calculateAutoScrollingIncrement(int pos, int size);
 
 private:
-    bool m_autoScrollMarginEnabled;
     bool m_grouped;
     int m_activeTransactions; // Counter for beginTransaction()/endTransaction()
 
@@ -314,9 +322,11 @@ private:
     qreal m_oldOffset;
     qreal m_oldMaximumOffset;
 
+    bool m_skipAutoScrollForRubberBand;
     KItemListRubberBand* m_rubberBand;
 
     QPointF m_mousePos;
+    QTimer* m_autoScrollTimer;
 
     friend class KItemListController;
 };