]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistcontroller.cpp
Implement basic keyboard navigation in Icons and Compact View
[dolphin.git] / src / kitemviews / kitemlistcontroller.cpp
index 91fb8680657675f8b5e96a67d71d67d8fc61f459..af93715cf2d50c6b8c5dd869874c54bda3066c52 100644 (file)
@@ -119,8 +119,92 @@ bool KItemListController::hideEvent(QHideEvent* event)
 
 bool KItemListController::keyPressEvent(QKeyEvent* event)
 {
-    Q_UNUSED(event);
-    return false;
+    const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
+    const bool controlPressed = event->modifiers() & Qt::ControlModifier;
+    const bool shiftOrControlPressed = shiftPressed || controlPressed;
+
+    int index = m_selectionManager->currentItem();
+
+    switch (event->key()) {
+    case Qt::Key_Home:
+        index = 0;
+        break;
+
+    case Qt::Key_End:
+        index = m_model->count() - 1;
+        break;
+
+    case Qt::Key_Up:
+        if (m_view->scrollOrientation() == Qt::Horizontal) {
+            if (index > 0) {
+                index--;
+            }
+        }
+        else {
+            // TODO: Move to the previous row
+        }
+        break;
+
+    case Qt::Key_Down:
+        if (m_view->scrollOrientation() == Qt::Horizontal) {
+            if (index < m_model->count() - 1) {
+                index++;
+            }
+        }
+        else {
+            // TODO: Move to the next row
+        }
+        break;
+
+    case Qt::Key_Left:
+        if (m_view->scrollOrientation() == Qt::Vertical) {
+            if (index > 0) {
+                index--;
+            }
+        }
+        else {
+            // TODO: Move to the previous column
+        }
+        break;
+
+    case Qt::Key_Right:
+        if (m_view->scrollOrientation() == Qt::Vertical) {
+            if (index < m_model->count() - 1) {
+                index++;
+            }
+        }
+        else {
+            // TODO: Move to the next column
+        }
+        break;
+
+    case Qt::Key_Space:
+        if (controlPressed) {
+            m_selectionManager->endAnchoredSelection();
+            m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle);
+            m_selectionManager->beginAnchoredSelection(index);
+        }
+     default:
+        break;
+    }
+
+    if (m_selectionManager->currentItem() != index) {
+        if (controlPressed) {
+            m_selectionManager->endAnchoredSelection();
+        }
+
+        m_selectionManager->setCurrentItem(index);
+
+        if (!shiftOrControlPressed || m_selectionBehavior == SingleSelection) {
+            m_selectionManager->clearSelection();
+            m_selectionManager->setSelected(index, 1);
+        }
+
+        if (!shiftPressed) {
+            m_selectionManager->beginAnchoredSelection(index);
+        }
+    }
+    return true;
 }
 
 bool KItemListController::inputMethodEvent(QInputMethodEvent* event)
@@ -131,10 +215,56 @@ bool KItemListController::inputMethodEvent(QInputMethodEvent* event)
 
 bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
 {
-    Q_UNUSED(event);
-    Q_UNUSED(transform);
     const QPointF pos = transform.map(event->pos());
     m_pressedIndex = m_view->itemAt(pos);
+
+    if (m_view->isAboveExpansionToggle(m_pressedIndex, pos)) {
+        return true;
+    }
+
+    const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
+    const bool controlPressed = event->modifiers() & Qt::ControlModifier;
+    const bool shiftOrControlPressed = shiftPressed || controlPressed;
+
+    if (!shiftOrControlPressed || m_selectionBehavior == SingleSelection) {
+        m_selectionManager->clearSelection();
+    }
+
+    if (!shiftPressed) {
+        // Finish the anchored selection before the current index is changed
+        m_selectionManager->endAnchoredSelection();
+    }
+
+    if (m_pressedIndex >= 0) {
+        m_selectionManager->setCurrentItem(m_pressedIndex);
+
+        switch (m_selectionBehavior) {
+        case NoSelection:
+            return true;
+        case SingleSelection:
+            m_selectionManager->setSelected(m_pressedIndex);
+            return true;
+        case MultiSelection:
+            if (controlPressed) {
+                m_selectionManager->setSelected(m_pressedIndex, 1, KItemListSelectionManager::Toggle);
+                m_selectionManager->beginAnchoredSelection(m_pressedIndex);
+            }
+            else {
+                if (shiftPressed && m_selectionManager->isAnchoredSelectionActive()) {
+                    // The anchored selection is continued automatically by calling
+                    // m_selectionManager->setCurrentItem(m_pressedIndex), see above -> nothing more to do here
+                    return true;
+                }
+
+                // Select the pressed item and start a new anchored selection
+                m_selectionManager->setSelected(m_pressedIndex, 1, KItemListSelectionManager::Select);
+                m_selectionManager->beginAnchoredSelection(m_pressedIndex);
+            }
+        }
+
+        return true;
+    }
+
     return false;
 }
 
@@ -150,18 +280,27 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con
     if (m_view) {
         const QPointF pos = transform.map(event->pos());
         const int index = m_view->itemAt(pos);
+        const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier;
+
         if (index >= 0 && index == m_pressedIndex) {
+            // The release event is done above the same item as the press event
             bool emitItemClicked = true;
             if (event->button() & Qt::LeftButton) {
                 if (m_view->isAboveExpansionToggle(index, pos)) {
                     emit itemExpansionToggleClicked(index);
                     emitItemClicked = false;
                 }
+                else if (shiftOrControlPressed) {
+                    // The mouse click should only update the selection, not trigger the item
+                    emitItemClicked = false;
+                }
             }
 
             if (emitItemClicked) {
                 emit itemClicked(index, event->button());
             }
+        } else if (!shiftOrControlPressed) {
+            m_selectionManager->clearSelection();
         }
     }
 
@@ -213,8 +352,49 @@ bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const
 
 bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
 {
-    Q_UNUSED(event);
+    // The implementation assumes that only one item can get hovered no matter
+    // whether they overlap or not.
+
     Q_UNUSED(transform);
+    if (!m_model || !m_view) {
+        return false;
+    }
+
+    // Search the previously hovered item that might get unhovered
+    KItemListWidget* unhoveredWidget = 0;
+    foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
+        if (widget->isHovered()) {
+            unhoveredWidget = widget;
+            break;
+        }
+    }
+
+    // Search the currently hovered item
+    KItemListWidget* hoveredWidget = 0;
+    foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
+        const QPointF mappedPos = widget->mapFromItem(m_view, event->pos());
+
+        const bool hovered = widget->contains(mappedPos) &&
+                             !widget->expansionToggleRect().contains(mappedPos) &&
+                             !widget->selectionToggleRect().contains(mappedPos);
+        if (hovered) {
+            hoveredWidget = widget;
+            break;
+        }
+    }
+
+    if (unhoveredWidget != hoveredWidget) {
+        if (unhoveredWidget) {
+            unhoveredWidget->setHovered(false);
+            emit itemUnhovered(unhoveredWidget->index());
+        }
+
+        if (hoveredWidget) {
+            hoveredWidget->setHovered(true);
+            emit itemHovered(hoveredWidget->index());
+        }
+    }
+
     return false;
 }
 
@@ -222,6 +402,17 @@ bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const
 {
     Q_UNUSED(event);
     Q_UNUSED(transform);
+
+    if (!m_model || !m_view) {
+        return false;
+    }
+
+    foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) {
+        if (widget->isHovered()) {
+            widget->setHovered(false);
+            emit itemUnhovered(widget->index());
+        }
+    }
     return false;
 }
 
@@ -246,9 +437,6 @@ bool KItemListController::processEvent(QEvent* event, const QTransform& transfor
     }
 
     switch (event->type()) {
-//  case QEvent::FocusIn:
-//  case QEvent::FocusOut:
-//      return focusEvent(static_cast<QFocusEvent*>(event));
     case QEvent::KeyPress:
         return keyPressEvent(static_cast<QKeyEvent*>(event));
     case QEvent::InputMethod: