┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2011-12-26 22:16:32 +0100
committerPeter Penz <[email protected]>2011-12-26 22:22:50 +0100
commit118fe89449a6e94065a0b30748f4f854b2fbeb27 (patch)
tree7907ffd0445cb97dcd391987be95eb43f3920178
parent4dc571401662e6f8ac8c90aa2d74c071c9d73076 (diff)
Fix keyboard issues when groups are enabled
When groups are enabled in Dolphin the key-up and key-down keys did not behave consistent in comparison to traditional views or like done in editors. CCBUG: 261995 CCBUG: 262038
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp127
-rw-r--r--src/kitemviews/kitemlistcontroller.h47
-rw-r--r--src/kitemviews/kitemlistview.cpp5
-rw-r--r--src/kitemviews/kitemlistview.h9
-rw-r--r--src/kitemviews/kitemlistviewlayouter.cpp5
-rw-r--r--src/kitemviews/kitemlistviewlayouter_p.h7
6 files changed, 152 insertions, 48 deletions
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
index 8577bf863..0cf62f8e0 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_keyboardAnchorXPos(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.
@@ -210,37 +211,28 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
case Qt::Key_Left:
if (index > 0) {
- index--;
+ --index;
+ m_keyboardAnchorIndex = index;
+ m_keyboardAnchorXPos = keyboardAnchorPos(index);
}
break;
case Qt::Key_Right:
if (index < itemCount - 1) {
- index++;
+ ++index;
+ m_keyboardAnchorIndex = index;
+ m_keyboardAnchorXPos = 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:
@@ -955,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_keyboardAnchorXPos;
+ if (!validAnchor) {
+ const int index = m_selectionManager->currentItem();
+ m_keyboardAnchorIndex = index;
+ m_keyboardAnchorXPos = 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_keyboardAnchorXPos - keyboardAnchorPos(nextRowIndex));
+ while (searchIndex < maxIndex && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex)) {
+ ++searchIndex;
+ const qreal searchDiff = qAbs(m_keyboardAnchorXPos - 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_keyboardAnchorXPos - keyboardAnchorPos(previousRowIndex));
+ while (searchIndex > 0 && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex)) {
+ --searchIndex;
+ const qreal searchDiff = qAbs(m_keyboardAnchorXPos - 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"
diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h
index e0e8b0a9b..b2c7d65b2 100644
--- a/src/kitemviews/kitemlistcontroller.h
+++ b/src/kitemviews/kitemlistcontroller.h
@@ -220,6 +220,34 @@ private:
*/
KItemListWidget* widgetForPos(const QPointF& pos) const;
+ /**
+ * Updates m_keyboardAnchorIndex and m_keyboardAnchorPos. If no anchor is
+ * set, it will be adjusted to the current item. If it is set it will be
+ * checked whether it is still valid, otherwise it will be reset to the
+ * current item.
+ */
+ void updateKeyboardAnchor();
+
+ /**
+ * @return Index for the next row based on the current index.
+ * If there is no next row the current index will be returned.
+ */
+ int nextRowIndex() const;
+
+ /**
+ * @return Index for the previous row based on the current index.
+ * If there is no previous row the current index will be returned.
+ */
+ int previousRowIndex() const;
+
+ /**
+ * Helper method for updateKeyboardAnchor(), previousRowIndex() and nextRowIndex().
+ * @return The position of the keyboard anchor for the item with the index \a index.
+ * If a horizontal scrolling is used the y-position of the item will be returned,
+ * for the vertical scrolling the x-position will be returned.
+ */
+ qreal keyboardAnchorPos(int index) const;
+
private:
bool m_selectionTogglePressed;
SelectionBehavior m_selectionBehavior;
@@ -235,10 +263,27 @@ private:
/**
* When starting a rubberband selection during a Shift- or Control-key has been
* pressed the current selection should never be deleted. To be able to restore
- * the current selection it is remembered in m_oldSelection before
+ * the current selection it is remembered in m_oldSelection before the
* rubberband gets activated.
*/
QSet<int> m_oldSelection;
+
+ /**
+ * Assuming a view is given with a vertical scroll-orientation, grouped items and
+ * a maximum of 4 columns:
+ *
+ * 1 2 3 4
+ * 5 6 7
+ * 8 9 10 11
+ * 12 13 14
+ *
+ * If the current index is on 4 and key-down is pressed, then item 7 gets the current
+ * item. Now when pressing key-down again item 11 should get the current item and not
+ * item 10. This makes it necessary to keep track of the requested column to have a
+ * similar behavior like in a text editor:
+ */
+ int m_keyboardAnchorIndex;
+ qreal m_keyboardAnchorXPos;
};
#endif
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
index 42445dcfe..be03606ce 100644
--- a/src/kitemviews/kitemlistview.cpp
+++ b/src/kitemviews/kitemlistview.cpp
@@ -485,11 +485,6 @@ void KItemListView::scrollToItem(int index)
}
}
-int KItemListView::itemsPerOffset() const
-{
- return m_layouter->itemsPerOffset();
-}
-
void KItemListView::beginTransaction()
{
++m_activeTransactions;
diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h
index 90f753087..d44a08c02 100644
--- a/src/kitemviews/kitemlistview.h
+++ b/src/kitemviews/kitemlistview.h
@@ -202,15 +202,6 @@ public:
*/
void scrollToItem(int index);
- /**
- * @return The number of items that can be shown in parallel for one offset.
- * Assuming the scrolldirection is vertical then a value of 4 means
- * that 4 columns for items are available. Assuming the scrolldirection
- * is horizontal then a value of 4 means that 4 lines for items are
- * available.
- */
- int itemsPerOffset() const;
-
void beginTransaction();
void endTransaction();
bool isTransactionActive() const;
diff --git a/src/kitemviews/kitemlistviewlayouter.cpp b/src/kitemviews/kitemlistviewlayouter.cpp
index 8dbbb372a..b486a390b 100644
--- a/src/kitemviews/kitemlistviewlayouter.cpp
+++ b/src/kitemviews/kitemlistviewlayouter.cpp
@@ -253,11 +253,6 @@ int KItemListViewLayouter::maximumVisibleItems() const
return rows * m_columnCount;
}
-int KItemListViewLayouter::itemsPerOffset() const
-{
- return m_columnCount;
-}
-
bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
{
const_cast<KItemListViewLayouter*>(this)->doLayout();
diff --git a/src/kitemviews/kitemlistviewlayouter_p.h b/src/kitemviews/kitemlistviewlayouter_p.h
index 109528c63..3d2f10906 100644
--- a/src/kitemviews/kitemlistviewlayouter_p.h
+++ b/src/kitemviews/kitemlistviewlayouter_p.h
@@ -108,13 +108,6 @@ public:
int maximumVisibleItems() const;
/**
- * @return Maximum number of items that can be shown in the same row
- * (= vertical scrolldirection) or same column
- * (= horizontal scrolldirection).
- */
- int itemsPerOffset() const;
-
- /**
* @return True if the item with the index \p itemIndex
* is the first item within a group.
*/