X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/aa5ffc8d89170b8e381f10ec846b07c1d81ec4e7..8dd3b9d3be28ab5b3faa851919cc794e3a338154:/src/dolphinviewautoscroller.cpp diff --git a/src/dolphinviewautoscroller.cpp b/src/dolphinviewautoscroller.cpp index fbce803b8..45896a5eb 100644 --- a/src/dolphinviewautoscroller.cpp +++ b/src/dolphinviewautoscroller.cpp @@ -20,24 +20,29 @@ #include "dolphinviewautoscroller.h" #include -#include +#include #include #include #include #include #include +#include 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 @@ -48,6 +53,23 @@ 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()) { @@ -57,111 +79,111 @@ bool DolphinViewAutoScroller::eventFilter(QObject* watched, QEvent* event) 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) && (event->type() == QEvent::KeyPress)) { - switch (static_cast(event)->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_PageUp: - case Qt::Key_PageDown: - case Qt::Key_Home: - case Qt::Key_End: - QMetaObject::invokeMethod(this, "scrollToCurrentIndex", Qt::QueuedConnection); + } else if (watched == m_itemView) { + switch (event->type()) { + case QEvent::KeyPress: + m_keyPressed = true; + break; + + case QEvent::KeyRelease: + m_keyPressed = false; break; + default: break; } - } - + } return QObject::eventFilter(watched, 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); } } -void DolphinViewAutoScroller::scrollToCurrentIndex() -{ - const QModelIndex index = m_itemView->currentIndex(); - m_itemView->scrollTo(index); -} - 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(); } } @@ -169,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"