]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistcontroller.cpp
Allow custom sorting of details-view columns
[dolphin.git] / src / kitemviews / kitemlistcontroller.cpp
index fedbe61a90ddff63d4b8241229693c66d471bac2..239cf2e6c4b3c2d33bb46921e487e8b95d7155ac 100644 (file)
@@ -1,5 +1,6 @@
 /***************************************************************************
  *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2012 by Frank Reininghaus <frank78ac@googlemail.com>    *
  *                                                                         *
  *   Based on the Itemviews NG project from Trolltech Labs:                *
  *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
@@ -201,8 +202,9 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
         default:            break;
         }
     }
-    
-    const bool selectSingleItem = itemCount == 1 &&
+
+    const bool selectSingleItem = m_selectionBehavior != NoSelection &&
+                                  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);
@@ -215,10 +217,14 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
     switch (key) {
     case Qt::Key_Home:
         index = 0;
+        m_keyboardAnchorIndex = index;
+        m_keyboardAnchorPos = keyboardAnchorPos(index);
         break;
 
     case Qt::Key_End:
         index = itemCount - 1;
+        m_keyboardAnchorIndex = index;
+        m_keyboardAnchorPos = keyboardAnchorPos(index);
         break;
 
     case Qt::Key_Left:
@@ -239,12 +245,68 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
 
     case Qt::Key_Up:
         updateKeyboardAnchor();
-        index = previousRowIndex();
+        index = previousRowIndex(index);
         break;
 
     case Qt::Key_Down:
         updateKeyboardAnchor();
-        index = nextRowIndex();
+        index = nextRowIndex(index);
+        break;
+
+    case Qt::Key_PageUp:
+        if (m_view->scrollOrientation() == Qt::Horizontal) {
+            // The new current index should correspond to the first item in the current column.
+            int newIndex = qMax(index - 1, 0);
+            while (newIndex != index && m_view->itemRect(newIndex).topLeft().y() < m_view->itemRect(index).topLeft().y()) {
+                index = newIndex;
+                newIndex = qMax(index - 1, 0);
+            }
+            m_keyboardAnchorIndex = index;
+            m_keyboardAnchorPos = keyboardAnchorPos(index);
+        } else {
+            const qreal currentItemBottom = m_view->itemRect(index).bottomLeft().y();
+            const qreal height = m_view->geometry().height();
+
+            // The new current item should be the first item in the current
+            // column whose itemRect's top coordinate is larger than targetY.
+            const qreal targetY = currentItemBottom - height;
+
+            updateKeyboardAnchor();
+            int newIndex = previousRowIndex(index);
+            do {
+                index = newIndex;
+                updateKeyboardAnchor();
+                newIndex = previousRowIndex(index);
+            } while (m_view->itemRect(newIndex).topLeft().y() > targetY && newIndex != index);
+        }
+        break;
+
+    case Qt::Key_PageDown:
+        if (m_view->scrollOrientation() == Qt::Horizontal) {
+            // The new current index should correspond to the last item in the current column.
+            int newIndex = qMin(index + 1, m_model->count() - 1);
+            while (newIndex != index && m_view->itemRect(newIndex).topLeft().y() > m_view->itemRect(index).topLeft().y()) {
+                index = newIndex;
+                newIndex = qMin(index + 1, m_model->count() - 1);
+            }
+            m_keyboardAnchorIndex = index;
+            m_keyboardAnchorPos = keyboardAnchorPos(index);
+        } else {
+            const qreal currentItemTop = m_view->itemRect(index).topLeft().y();
+            const qreal height = m_view->geometry().height();
+
+            // The new current item should be the last item in the current
+            // column whose itemRect's bottom coordinate is smaller than targetY.
+            const qreal targetY = currentItemTop + height;
+
+            updateKeyboardAnchor();
+            int newIndex = nextRowIndex(index);
+            do {
+                index = newIndex;
+                updateKeyboardAnchor();
+                newIndex = nextRowIndex(index);
+            } while (m_view->itemRect(newIndex).bottomLeft().y() < targetY && newIndex != index);
+        }
         break;
 
     case Qt::Key_Enter:
@@ -261,13 +323,15 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
     }
 
     case Qt::Key_Space:
-        if (controlPressed) {
-            m_selectionManager->endAnchoredSelection();
-            m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle);
-            m_selectionManager->beginAnchoredSelection(index);
-        } else {
-            const int current = m_selectionManager->currentItem();
-            m_selectionManager->setSelected(current);
+        if (m_selectionBehavior == MultiSelection) {
+            if (controlPressed) {
+                m_selectionManager->endAnchoredSelection();
+                m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle);
+                m_selectionManager->beginAnchoredSelection(index);
+            } else {
+                const int current = m_selectionManager->currentItem();
+                m_selectionManager->setSelected(current);
+            }
         }
         break;
 
@@ -300,19 +364,33 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
     }
 
     if (m_selectionManager->currentItem() != index) {
-        if (controlPressed) {
-            m_selectionManager->endAnchoredSelection();
-        }
-
-        m_selectionManager->setCurrentItem(index);
+        switch (m_selectionBehavior) {
+        case NoSelection:
+            m_selectionManager->setCurrentItem(index);
+            break;
 
-        if (!shiftOrControlPressed || m_selectionBehavior == SingleSelection) {
+        case SingleSelection:
+            m_selectionManager->setCurrentItem(index);
             m_selectionManager->clearSelection();
             m_selectionManager->setSelected(index, 1);
-        }
+            break;
 
-        if (!shiftPressed) {
-            m_selectionManager->beginAnchoredSelection(index);
+        case MultiSelection:
+            if (controlPressed) {
+                m_selectionManager->endAnchoredSelection();
+            }
+
+            m_selectionManager->setCurrentItem(index);
+
+            if (!shiftOrControlPressed) {
+                m_selectionManager->clearSelection();
+                m_selectionManager->setSelected(index, 1);
+            }
+
+            if (!shiftPressed) {
+                m_selectionManager->beginAnchoredSelection(index);
+            }
+            break;
         }
 
         m_view->scrollToItem(index);
@@ -414,7 +492,7 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const
                                 (!shiftOrControlPressed && !pressedItemAlreadySelected);
     if (clearSelection) {
         m_selectionManager->clearSelection();
-    } else if (pressedItemAlreadySelected && (event->buttons() & Qt::LeftButton)) {
+    } else if (pressedItemAlreadySelected && !shiftOrControlPressed && (event->buttons() & Qt::LeftButton)) {
         // The user might want to start dragging multiple items, but if he clicks the item
         // in order to trigger it instead, the other selected items must be deselected.
         // However, we do not know yet what the user is going to do.
@@ -653,6 +731,12 @@ bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent* event, con
 {
     Q_UNUSED(event);
     Q_UNUSED(transform);
+
+    KItemListWidget* widget = hoveredWidget();
+    if (widget) {
+        widget->setHovered(false);
+        emit itemUnhovered(widget->index());
+    }
     return false;
 }
 
@@ -994,24 +1078,23 @@ void KItemListController::updateKeyboardAnchor()
     }
 }
 
-int KItemListController::nextRowIndex() const
+int KItemListController::nextRowIndex(int index) const
 {
-    const int currentIndex = m_selectionManager->currentItem();
     if (m_keyboardAnchorIndex < 0) {
-        return currentIndex;
+        return index;
     }
 
     const int maxIndex = m_model->count() - 1;
-    if (currentIndex == maxIndex) {
-        return currentIndex;
+    if (index == maxIndex) {
+        return index;
     }
 
     // Calculate the index of the last column inside the row of the current index
-    int lastColumnIndex = currentIndex;
+    int lastColumnIndex = index;
     while (keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex)) {
         ++lastColumnIndex;
         if (lastColumnIndex >= maxIndex) {
-            return currentIndex;
+            return index;
         }
     }
 
@@ -1032,19 +1115,18 @@ int KItemListController::nextRowIndex() const
     return nextRowIndex;
 }
 
-int KItemListController::previousRowIndex() const
+int KItemListController::previousRowIndex(int index) const
 {
-    const int currentIndex = m_selectionManager->currentItem();
-    if (m_keyboardAnchorIndex < 0 || currentIndex == 0) {
-        return currentIndex;
+    if (m_keyboardAnchorIndex < 0 || index == 0) {
+        return index;
     }
 
     // Calculate the index of the first column inside the row of the current index
-    int firstColumnIndex = currentIndex;
+    int firstColumnIndex = index;
     while (keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex)) {
         --firstColumnIndex;
         if (firstColumnIndex <= 0) {
-            return currentIndex;
+            return index;
         }
     }