]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphinviewautoscroller.cpp
use KAction::setShortcut() instead of QAction::setShortcut()
[dolphin.git] / src / dolphinviewautoscroller.cpp
index bbcf16ac3ef5bdca2c8506760ecb0391e1506df5..45896a5eb5cb353087bab4083b0aafaca714b894 100644 (file)
 #include "dolphinviewautoscroller.h"
 
 #include <QAbstractItemView>
-#include <QCoreApplication>
+#include <QApplication>
 #include <QCursor>
 #include <QEvent>
 #include <QMouseEvent>
 #include <QScrollBar>
 #include <QTimer>
+#include <math.h>
 
 DolphinViewAutoScroller::DolphinViewAutoScroller(QAbstractItemView* parent) :
     QObject(parent),
     m_rubberBandSelection(false),
-    m_scrollInc(0),
+    m_keyPressed(false),
+    m_initializedTimestamp(false),
+    m_horizontalScrollInc(0),
+    m_verticalScrollInc(0),
     m_itemView(parent),
-    m_timer()
+    m_timer(0),
+    m_timestamp()
 {
     m_itemView->setAutoScroll(false);
     m_itemView->viewport()->installEventFilter(this);
-    
+    m_itemView->installEventFilter(this);
+
     m_timer = new QTimer(this);
     m_timer->setSingleShot(false);
     m_timer->setInterval(1000 / 25); // 25 frames per second
@@ -47,36 +53,69 @@ DolphinViewAutoScroller::~DolphinViewAutoScroller()
 {
 }
 
+bool DolphinViewAutoScroller::isActive() const
+{
+    return m_timer->isActive();
+}
+
+void DolphinViewAutoScroller::handleCurrentIndexChange(const QModelIndex& current,
+                                                       const QModelIndex& previous)
+{
+    // When the autoscroller is inactive and a key has been pressed, it must be
+    // assured that the current item stays visible. The check whether the previous
+    // item is valid is important because of #197951. The keypress check is done
+    // because of #199833.
+    if (current.isValid() && (previous.isValid() || m_keyPressed) && !isActive()) {
+        m_itemView->scrollTo(current);
+    }
+}
+
 bool DolphinViewAutoScroller::eventFilter(QObject* watched, QEvent* event)
 {
     if (watched == m_itemView->viewport()) {
         switch (event->type()) {
         case QEvent::MouseButtonPress:
-            m_rubberBandSelection = true;
+            if (static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton) {
+                m_rubberBandSelection = true;
+            }
             break;
-            
+
         case QEvent::MouseMove:
             if (m_rubberBandSelection) {
                 triggerAutoScroll();
             }
             break;
-            
+
         case QEvent::MouseButtonRelease:
             m_rubberBandSelection = false;
             stopAutoScroll();
             break;
-            
+
         case QEvent::DragEnter:
         case QEvent::DragMove:
             m_rubberBandSelection = false;
             triggerAutoScroll();
             break;
-            
+
+        case QEvent::Drop:
         case QEvent::DragLeave:
             m_rubberBandSelection = false;
             stopAutoScroll();
             break;
-            
+
+        default:
+            break;
+        }
+    } else if (watched == m_itemView) {
+        switch (event->type()) {
+        case QEvent::KeyPress:
+            m_keyPressed = true;
+            break;
+
+        case QEvent::KeyRelease:
+            m_keyPressed = false;
+            break;
+
         default:
             break;
         }
@@ -87,26 +126,30 @@ bool DolphinViewAutoScroller::eventFilter(QObject* watched, QEvent* event)
 
 void DolphinViewAutoScroller::scrollViewport()
 {
+    if (m_timestamp.elapsed() < QApplication::startDragTime()) {
+        return;
+    }
+
     QScrollBar* verticalScrollBar = m_itemView->verticalScrollBar();
     if (verticalScrollBar != 0) {
         const int value = verticalScrollBar->value();
-        verticalScrollBar->setValue(value + m_scrollInc);
-        
+        verticalScrollBar->setValue(value + m_verticalScrollInc);
+
     }
     QScrollBar* horizontalScrollBar = m_itemView->horizontalScrollBar();
     if (horizontalScrollBar != 0) {
         const int value = horizontalScrollBar->value();
-        horizontalScrollBar->setValue(value + m_scrollInc);
-        
+        horizontalScrollBar->setValue(value + m_horizontalScrollInc);
+
     }
-    
+
     if (m_rubberBandSelection) {
         // The scrolling does not lead to an update of the rubberband
         // selection. Fake a mouse move event to let the QAbstractItemView
         // update the rubberband.
         QWidget* viewport = m_itemView->viewport();
         const QPoint pos = viewport->mapFromGlobal(QCursor::pos());
-        QMouseEvent event(QEvent::MouseMove, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+        QMouseEvent event(QEvent::MouseMove, pos, Qt::LeftButton, Qt::LeftButton, QApplication::keyboardModifiers());
         QCoreApplication::sendEvent(viewport, &event);
     }
 }
@@ -114,28 +157,33 @@ void DolphinViewAutoScroller::scrollViewport()
 void DolphinViewAutoScroller::triggerAutoScroll()
 {
     const bool verticalScrolling = (m_itemView->verticalScrollBar() != 0) &&
-                                    m_itemView->verticalScrollBar()->isVisible();
+                                   m_itemView->verticalScrollBar()->isVisible();
     const bool horizontalScrolling = (m_itemView->horizontalScrollBar() != 0) &&
                                      m_itemView->horizontalScrollBar()->isVisible();
     if (!verticalScrolling && !horizontalScrolling) {
         // no scrollbars are shown at all, so no autoscrolling is necessary
+        stopAutoScroll();
         return;
     }
-    
+
     QWidget* viewport = m_itemView->viewport();
     const QPoint pos = viewport->mapFromGlobal(QCursor::pos());
     if (verticalScrolling) {
-        calculateScrollIncrement(pos.y(), viewport->height());
+        m_verticalScrollInc = calculateScrollIncrement(pos.y(), viewport->height());
     }
     if (horizontalScrolling) {
-        calculateScrollIncrement(pos.x(), viewport->width());
+        m_horizontalScrollInc = calculateScrollIncrement(pos.x(), viewport->width());
     }
-    
+
     if (m_timer->isActive()) {
-        if (m_scrollInc == 0) {
-            m_timer->stop();
+        if ((m_horizontalScrollInc == 0) && (m_verticalScrollInc == 0)) {
+            stopAutoScroll();
+        }
+    } else if ((m_horizontalScrollInc != 0) || (m_verticalScrollInc != 0)) {
+        if (!m_initializedTimestamp) {
+            m_initializedTimestamp = true;
+            m_timestamp.start();
         }
-    } else if (m_scrollInc != 0) {
         m_timer->start();
     }
 }
@@ -143,29 +191,33 @@ void DolphinViewAutoScroller::triggerAutoScroll()
 void DolphinViewAutoScroller::stopAutoScroll()
 {
     m_timer->stop();
-    m_scrollInc = 0;
+    m_horizontalScrollInc = 0;
+    m_verticalScrollInc = 0;
+    m_initializedTimestamp = false;
 }
 
-void DolphinViewAutoScroller::calculateScrollIncrement(int cursorPos, int rangeSize)
+int DolphinViewAutoScroller::calculateScrollIncrement(int cursorPos, int rangeSize) const
 {
-    const int minSpeed = 2;
-    const int maxSpeed = 32;
-    const int speedLimiter = 8;
-    const int autoScrollBorder = 32;
-    
+    int inc = 0;
+
+    const int minSpeed = 4;
+    const int maxSpeed = 768;
+    const int speedLimiter = 48;
+    const int autoScrollBorder = 64;
+
     if (cursorPos < autoScrollBorder) {
-        m_scrollInc = -minSpeed + (cursorPos - autoScrollBorder) / speedLimiter;
-        if (m_scrollInc < -maxSpeed) {
-            m_scrollInc = -maxSpeed;
+        inc = -minSpeed + qAbs(cursorPos - autoScrollBorder) * (cursorPos - autoScrollBorder) / speedLimiter;
+        if (inc < -maxSpeed) {
+            inc = -maxSpeed;
         }
     } else if (cursorPos > rangeSize - autoScrollBorder) {
-        m_scrollInc = minSpeed + (cursorPos - rangeSize + autoScrollBorder) / speedLimiter;
-        if (m_scrollInc > maxSpeed) {
-            m_scrollInc = maxSpeed;
+        inc = minSpeed + qAbs(cursorPos - rangeSize + autoScrollBorder) * (cursorPos - rangeSize + autoScrollBorder) / speedLimiter;
+        if (inc > maxSpeed) {
+            inc = maxSpeed;
         }
-    } else {
-        m_scrollInc = 0;
     }
+
+    return inc;
 }
 
 #include "dolphinviewautoscroller.moc"