X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/dbfba7dfedc979469ec2be072c63d0dfcf7970ee..c8d8556950005dfd96ebdb41d2f43ad90356367c:/src/kitemviews/kitemlistcontroller.cpp diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 2ff8068ab..026c245f5 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -50,7 +50,9 @@ KItemListController::KItemListController(QObject* parent) : m_pressedIndex(-1), m_pressedMousePos(), m_autoActivationTimer(0), - m_oldSelection() + m_oldSelection(), + m_keyboardAnchorIndex(-1), + m_keyboardAnchorPos(0) { connect(m_keyboardManager, SIGNAL(changeCurrentItem(QString,bool)), this, SLOT(slotChangeCurrentItem(QString,bool))); @@ -175,7 +177,6 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) const bool shiftOrControlPressed = shiftPressed || controlPressed; const int itemCount = m_model->count(); - const int itemsPerRow = m_view->itemsPerOffset(); // For horizontal scroll orientation, transform // the arrow keys to simplify the event handling. @@ -188,6 +189,16 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) default: break; } } + + const bool selectSingleItem = itemCount == 1 && + (key == Qt::Key_Home || key == Qt::Key_End || + key == Qt::Key_Up || key == Qt::Key_Down || + key == Qt::Key_Left || key == Qt::Key_Right); + if (selectSingleItem) { + const int current = m_selectionManager->currentItem(); + m_selectionManager->setSelected(current); + return true; + } switch (key) { case Qt::Key_Home: @@ -200,37 +211,28 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) case Qt::Key_Left: if (index > 0) { - index--; + --index; + m_keyboardAnchorIndex = index; + m_keyboardAnchorPos = keyboardAnchorPos(index); } break; case Qt::Key_Right: if (index < itemCount - 1) { - index++; + ++index; + m_keyboardAnchorIndex = index; + m_keyboardAnchorPos = keyboardAnchorPos(index); } break; case Qt::Key_Up: - if (index >= itemsPerRow) { - index -= itemsPerRow; - } + updateKeyboardAnchor(); + index = previousRowIndex(); break; case Qt::Key_Down: - if (index + itemsPerRow < itemCount) { - // We are not in the last row yet. - index += itemsPerRow; - } else { - // We are either in the last row already, or we are in the second-last row, - // and there is no item below the current item. - // In the latter case, we jump to the very last item. - const int currentColumn = index % itemsPerRow; - const int lastItemColumn = (itemCount - 1) % itemsPerRow; - const bool inLastRow = currentColumn < lastItemColumn; - if (!inLastRow) { - index = itemCount - 1; - } - } + updateKeyboardAnchor(); + index = nextRowIndex(); break; case Qt::Key_Enter: @@ -252,7 +254,8 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle); m_selectionManager->beginAnchoredSelection(index); } else { - m_keyboardManager->addKeys(event->text()); + const int current = m_selectionManager->currentItem(); + m_selectionManager->setSelected(current); } break; @@ -361,6 +364,9 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const m_pressedMousePos = transform.map(event->pos()); m_pressedIndex = m_view->itemAt(m_pressedMousePos); + if (m_pressedIndex >= 0) { + emit itemPressed(m_pressedIndex, event->button()); + } if (m_view->isAboveExpansionToggle(m_pressedIndex, m_pressedMousePos)) { m_selectionManager->setCurrentItem(m_pressedIndex); @@ -527,6 +533,10 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con return false; } + if (m_pressedIndex >= 0) { + emit itemReleased(m_pressedIndex, event->button()); + } + const bool isAboveSelectionToggle = m_view->isAboveSelectionToggle(m_pressedIndex, m_pressedMousePos); if (isAboveSelectionToggle) { m_selectionTogglePressed = false; @@ -904,7 +914,7 @@ void KItemListController::startDragging() const QPixmap pixmap = m_view->createDragPixmap(selectedItems); drag->setPixmap(pixmap); - drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction); + drag->exec(Qt::CopyAction); } KItemListWidget* KItemListController::hoveredWidget() const @@ -937,4 +947,97 @@ KItemListWidget* KItemListController::widgetForPos(const QPointF& pos) const return 0; } +void KItemListController::updateKeyboardAnchor() +{ + const bool validAnchor = m_keyboardAnchorIndex >= 0 && + m_keyboardAnchorIndex < m_model->count() && + keyboardAnchorPos(m_keyboardAnchorIndex) == m_keyboardAnchorPos; + if (!validAnchor) { + const int index = m_selectionManager->currentItem(); + m_keyboardAnchorIndex = index; + m_keyboardAnchorPos = keyboardAnchorPos(index); + } +} + +int KItemListController::nextRowIndex() const +{ + const int currentIndex = m_selectionManager->currentItem(); + if (m_keyboardAnchorIndex < 0) { + return currentIndex; + } + + const int maxIndex = m_model->count() - 1; + if (currentIndex == maxIndex) { + return currentIndex; + } + + // Calculate the index of the last column inside the row of the current index + int lastColumnIndex = currentIndex; + while (keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex)) { + ++lastColumnIndex; + if (lastColumnIndex >= maxIndex) { + return currentIndex; + } + } + + // Based on the last column index go to the next row and calculate the nearest index + // that is below the current index + int nextRowIndex = lastColumnIndex + 1; + int searchIndex = nextRowIndex; + qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(nextRowIndex)); + while (searchIndex < maxIndex && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex)) { + ++searchIndex; + const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex)); + if (searchDiff < minDiff) { + minDiff = searchDiff; + nextRowIndex = searchIndex; + } + } + + return nextRowIndex; +} + +int KItemListController::previousRowIndex() const +{ + const int currentIndex = m_selectionManager->currentItem(); + if (m_keyboardAnchorIndex < 0 || currentIndex == 0) { + return currentIndex; + } + + // Calculate the index of the first column inside the row of the current index + int firstColumnIndex = currentIndex; + while (keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex)) { + --firstColumnIndex; + if (firstColumnIndex <= 0) { + return currentIndex; + } + } + + // Based on the first column index go to the previous row and calculate the nearest index + // that is above the current index + int previousRowIndex = firstColumnIndex - 1; + int searchIndex = previousRowIndex; + qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(previousRowIndex)); + while (searchIndex > 0 && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex)) { + --searchIndex; + const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex)); + if (searchDiff < minDiff) { + minDiff = searchDiff; + previousRowIndex = searchIndex; + } + } + + return previousRowIndex; +} + +qreal KItemListController::keyboardAnchorPos(int index) const +{ + const QRectF itemRect = m_view->itemRect(index); + if (!itemRect.isEmpty()) { + return (m_view->scrollOrientation() == Qt::Vertical) ? itemRect.x() : itemRect.y(); + } + + return 0; +} + #include "kitemlistcontroller.moc"