Skip to content
Snippets Groups Projects
Commit b5df860c authored by Peter Penz's avatar Peter Penz
Browse files

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
parent b0d8f01b
No related branches found
No related tags found
No related merge requests found
......@@ -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"
......@@ -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
......
......@@ -485,11 +485,6 @@ void KItemListView::scrollToItem(int index)
}
}
int KItemListView::itemsPerOffset() const
{
return m_layouter->itemsPerOffset();
}
void KItemListView::beginTransaction()
{
++m_activeTransactions;
......
......@@ -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;
......
......@@ -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();
......
......@@ -107,13 +107,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.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment