From: Peter Penz Date: Thu, 1 Sep 2011 21:08:22 +0000 (+0200) Subject: Improve autoscrolling X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/d2a3510cc372685ad491a0b653587bf569a132aa?ds=sidebyside Improve autoscrolling - Start autoscrolling when doing a dragging - Start autoscrolling with a small delay --- diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 09c7d8d46..025249a34 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -38,7 +38,6 @@ KItemListController::KItemListController(QObject* parent) : QObject(parent), - m_dragging(false), m_selectionBehavior(NoSelection), m_model(0), m_view(0), @@ -271,7 +270,6 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return false; } - m_dragging = false; m_pressedMousePos = transform.map(event->pos()); m_pressedIndex = m_view->itemAt(m_pressedMousePos); @@ -362,13 +360,13 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const if (m_pressedIndex >= 0) { // Check whether a dragging should be started - if (!m_dragging && (event->buttons() & Qt::LeftButton)) { + if (event->buttons() & Qt::LeftButton) { const QPointF pos = transform.map(event->pos()); const qreal minDragDiff = 4; const bool hasMinDragDiff = qAbs(pos.x() - m_pressedMousePos.x()) >= minDragDiff || qAbs(pos.y() - m_pressedMousePos.y()) >= minDragDiff; - if (hasMinDragDiff && startDragging()) { - m_dragging = true; + if (hasMinDragDiff) { + startDragging(); } } } else { @@ -401,7 +399,7 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier; - bool clearSelection = !shiftOrControlPressed && !m_dragging && event->button() != Qt::RightButton; + bool clearSelection = !shiftOrControlPressed && event->button() != Qt::RightButton; KItemListRubberBand* rubberBand = m_view->rubberBand(); if (rubberBand->isActive()) { @@ -449,7 +447,6 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con m_selectionManager->clearSelection(); } - m_dragging = false; m_pressedMousePos = QPointF(); m_pressedIndex = -1; return false; @@ -494,8 +491,6 @@ bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QT { Q_UNUSED(event); Q_UNUSED(transform); - - m_dragging = false; return false; } @@ -737,16 +732,16 @@ void KItemListController::slotRubberBandChanged() } } -bool KItemListController::startDragging() +void KItemListController::startDragging() { if (!m_view || !m_model) { - return false; + return; } const QSet selectedItems = m_selectionManager->selectedItems(); QMimeData* data = m_model->createMimeData(selectedItems); if (!data) { - return false; + return; } // The created drag object will be owned and deleted @@ -758,7 +753,6 @@ bool KItemListController::startDragging() drag->setPixmap(pixmap); drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction); - return true; } #include "kitemlistcontroller.moc" diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index 4ce5b804b..8ac2b554b 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -138,14 +138,11 @@ private slots: private: /** - * Creates a QDrag object to start a drag-operation. - * @return True if the QDrag object has been created. If false is returned - * there is no implementation available for KItemModelBase::createMimeData(). + * Creates a QDrag object and initiates a drag-operation. */ - bool startDragging(); + void startDragging(); private: - bool m_dragging; SelectionBehavior m_selectionBehavior; KItemModelBase* m_model; KItemListView* m_view; diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index a35752a47..2a7b0e4cd 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -41,6 +41,15 @@ #include #include +namespace { + // Time in ms until reaching the autoscroll margin triggers + // an initial autoscrolling + const int InitialAutoScrollDelay = 700; + + // Delay in ms for triggering the next autoscroll + const int RepeatingAutoScrollDelay = 1000 / 60; +} + KItemListView::KItemListView(QGraphicsWidget* parent) : QGraphicsWidget(parent), m_grouped(false), @@ -64,6 +73,7 @@ KItemListView::KItemListView(QGraphicsWidget* parent) : m_skipAutoScrollForRubberBand(false), m_rubberBand(0), m_mousePos(), + m_autoScrollIncrement(0), m_autoScrollTimer(0) { setAcceptHoverEvents(true); @@ -198,10 +208,9 @@ 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(); + m_autoScrollTimer->start(InitialAutoScrollDelay); } else if (!enabled && m_autoScrollTimer) { delete m_autoScrollTimer; m_autoScrollTimer = 0; @@ -482,17 +491,40 @@ void KItemListView::mousePressEvent(QGraphicsSceneMouseEvent* event) void KItemListView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { - m_mousePos = transform().map(event->pos()); QGraphicsWidget::mouseMoveEvent(event); + m_mousePos = transform().map(event->pos()); if (m_autoScrollTimer && !m_autoScrollTimer->isActive()) { - m_autoScrollTimer->start(); + m_autoScrollTimer->start(InitialAutoScrollDelay); } } void KItemListView::dragEnterEvent(QGraphicsSceneDragDropEvent* event) { event->setAccepted(true); + setAutoScroll(true); +} + +void KItemListView::dragMoveEvent(QGraphicsSceneDragDropEvent *event) +{ + QGraphicsWidget::dragMoveEvent(event); + + m_mousePos = transform().map(event->pos()); + if (m_autoScrollTimer && !m_autoScrollTimer->isActive()) { + m_autoScrollTimer->start(InitialAutoScrollDelay); + } +} + +void KItemListView::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) +{ + QGraphicsWidget::dragLeaveEvent(event); + setAutoScroll(false); +} + +void KItemListView::dropEvent(QGraphicsSceneDragDropEvent* event) +{ + QGraphicsWidget::dropEvent(event); + setAutoScroll(false); } QList KItemListView::visibleItemListWidgets() const @@ -816,8 +848,12 @@ void KItemListView::triggerAutoScrolling() visibleSize = size().width(); } - const int inc = calculateAutoScrollingIncrement(pos, visibleSize); - if (inc == 0) { + if (m_autoScrollTimer->interval() == InitialAutoScrollDelay) { + m_autoScrollIncrement = 0; + } + + m_autoScrollIncrement = calculateAutoScrollingIncrement(pos, visibleSize, m_autoScrollIncrement); + if (m_autoScrollIncrement == 0) { // The mouse position is not above an autoscroll margin (the autoscroll timer // will be restarted in mouseMoveEvent()) m_autoScrollTimer->stop(); @@ -834,7 +870,7 @@ void KItemListView::triggerAutoScrolling() const qreal diff = (scrollOrientation() == Qt::Vertical) ? m_rubberBand->endPosition().y() - m_rubberBand->startPosition().y() : m_rubberBand->endPosition().x() - m_rubberBand->startPosition().x(); - if (qAbs(diff) < minDiff || (inc < 0 && diff > 0) || (inc > 0 && diff < 0)) { + if (qAbs(diff) < minDiff || (m_autoScrollIncrement < 0 && diff > 0) || (m_autoScrollIncrement > 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(); @@ -846,13 +882,11 @@ void KItemListView::triggerAutoScrolling() // the autoscrolling may not get skipped anymore until a new rubberband is created m_skipAutoScrollForRubberBand = false; - setOffset(offset() + inc); + setOffset(offset() + m_autoScrollIncrement); - if (!m_autoScrollTimer->isActive()) { - // Trigger the autoscroll timer which will periodically call - // triggerAutoScrolling() - m_autoScrollTimer->start(); - } + // Trigger the autoscroll timer which will periodically call + // triggerAutoScrolling() + m_autoScrollTimer->start(RepeatingAutoScrollDelay); } void KItemListView::setController(KItemListController* controller) @@ -1261,7 +1295,7 @@ void KItemListView::updateWidgetProperties(KItemListWidget* widget, int index) widget->setData(m_model->data(index)); } -int KItemListView::calculateAutoScrollingIncrement(int pos, int size) +int KItemListView::calculateAutoScrollingIncrement(int pos, int range, int oldInc) { int inc = 0; @@ -1270,16 +1304,18 @@ int KItemListView::calculateAutoScrollingIncrement(int pos, int size) const int speedLimiter = 96; const int autoScrollBorder = 64; + // Limit the increment that is allowed to be added in comparison to 'oldInc'. + // This assures that the autoscrolling speed grows gradually. + const int incLimiter = 1; + if (pos < autoScrollBorder) { inc = -minSpeed + qAbs(pos - autoScrollBorder) * (pos - autoScrollBorder) / speedLimiter; - if (inc < -maxSpeed) { - inc = -maxSpeed; - } - } else if (pos > size - autoScrollBorder) { - inc = minSpeed + qAbs(pos - size + autoScrollBorder) * (pos - size + autoScrollBorder) / speedLimiter; - if (inc > maxSpeed) { - inc = maxSpeed; - } + inc = qMax(inc, -maxSpeed); + inc = qMax(inc, oldInc - incLimiter); + } else if (pos > range - autoScrollBorder) { + inc = minSpeed + qAbs(pos - range + autoScrollBorder) * (pos - range + autoScrollBorder) / speedLimiter; + inc = qMin(inc, maxSpeed); + inc = qMin(inc, oldInc + incLimiter); } return inc; diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 9977e3639..55a5c3344 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -200,6 +200,9 @@ protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event); virtual void dragEnterEvent(QGraphicsSceneDragDropEvent* event); + virtual void dragMoveEvent(QGraphicsSceneDragDropEvent* event); + virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent* event); + virtual void dropEvent(QGraphicsSceneDragDropEvent* event); QList visibleItemListWidgets() const; @@ -290,12 +293,16 @@ private: void updateWidgetProperties(KItemListWidget* widget, int index); /** - * Helper function for triggerAutoScrolling(). Returns the scroll increment - * that should be added to the offset() based on the available size \a size - * and the current mouse position \a pos. As soon as \a pos is inside - * the autoscroll-margin a value != 0 will be returned. + * Helper function for triggerAutoScrolling(). + * @param pos Logical position of the mouse relative to the range. + * @param range Range of the visible area. + * @param oldInc Previous increment. Is used to assure that the increment + * increases only gradually. + * @return Scroll increment that should be added to the offset(). + * As soon as \a pos is inside the autoscroll-margin a + * value != 0 will be returned. */ - static int calculateAutoScrollingIncrement(int pos, int size); + static int calculateAutoScrollingIncrement(int pos, int range, int oldInc); private: bool m_grouped; @@ -326,6 +333,7 @@ private: KItemListRubberBand* m_rubberBand; QPointF m_mousePos; + int m_autoScrollIncrement; QTimer* m_autoScrollTimer; friend class KItemListController;