mirror of
https://invent.kde.org/system/dolphin
synced 2024-09-19 16:31:21 +00:00
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
This commit is contained in:
parent
4dc5714016
commit
118fe89449
|
@ -50,7 +50,9 @@ KItemListController::KItemListController(QObject* parent) :
|
||||||
m_pressedIndex(-1),
|
m_pressedIndex(-1),
|
||||||
m_pressedMousePos(),
|
m_pressedMousePos(),
|
||||||
m_autoActivationTimer(0),
|
m_autoActivationTimer(0),
|
||||||
m_oldSelection()
|
m_oldSelection(),
|
||||||
|
m_keyboardAnchorIndex(-1),
|
||||||
|
m_keyboardAnchorXPos(0)
|
||||||
{
|
{
|
||||||
connect(m_keyboardManager, SIGNAL(changeCurrentItem(QString,bool)),
|
connect(m_keyboardManager, SIGNAL(changeCurrentItem(QString,bool)),
|
||||||
this, SLOT(slotChangeCurrentItem(QString,bool)));
|
this, SLOT(slotChangeCurrentItem(QString,bool)));
|
||||||
|
@ -175,7 +177,6 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
|
||||||
const bool shiftOrControlPressed = shiftPressed || controlPressed;
|
const bool shiftOrControlPressed = shiftPressed || controlPressed;
|
||||||
|
|
||||||
const int itemCount = m_model->count();
|
const int itemCount = m_model->count();
|
||||||
const int itemsPerRow = m_view->itemsPerOffset();
|
|
||||||
|
|
||||||
// For horizontal scroll orientation, transform
|
// For horizontal scroll orientation, transform
|
||||||
// the arrow keys to simplify the event handling.
|
// the arrow keys to simplify the event handling.
|
||||||
|
@ -210,37 +211,28 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
|
||||||
|
|
||||||
case Qt::Key_Left:
|
case Qt::Key_Left:
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
index--;
|
--index;
|
||||||
|
m_keyboardAnchorIndex = index;
|
||||||
|
m_keyboardAnchorXPos = keyboardAnchorPos(index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Right:
|
case Qt::Key_Right:
|
||||||
if (index < itemCount - 1) {
|
if (index < itemCount - 1) {
|
||||||
index++;
|
++index;
|
||||||
|
m_keyboardAnchorIndex = index;
|
||||||
|
m_keyboardAnchorXPos = keyboardAnchorPos(index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
if (index >= itemsPerRow) {
|
updateKeyboardAnchor();
|
||||||
index -= itemsPerRow;
|
index = previousRowIndex();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Down:
|
case Qt::Key_Down:
|
||||||
if (index + itemsPerRow < itemCount) {
|
updateKeyboardAnchor();
|
||||||
// We are not in the last row yet.
|
index = nextRowIndex();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
|
@ -955,4 +947,97 @@ KItemListWidget* KItemListController::widgetForPos(const QPointF& pos) const
|
||||||
return 0;
|
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"
|
#include "kitemlistcontroller.moc"
|
||||||
|
|
|
@ -220,6 +220,34 @@ private:
|
||||||
*/
|
*/
|
||||||
KItemListWidget* widgetForPos(const QPointF& pos) const;
|
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:
|
private:
|
||||||
bool m_selectionTogglePressed;
|
bool m_selectionTogglePressed;
|
||||||
SelectionBehavior m_selectionBehavior;
|
SelectionBehavior m_selectionBehavior;
|
||||||
|
@ -235,10 +263,27 @@ private:
|
||||||
/**
|
/**
|
||||||
* When starting a rubberband selection during a Shift- or Control-key has been
|
* 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
|
* 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.
|
* rubberband gets activated.
|
||||||
*/
|
*/
|
||||||
QSet<int> m_oldSelection;
|
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
|
#endif
|
||||||
|
|
|
@ -485,11 +485,6 @@ void KItemListView::scrollToItem(int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int KItemListView::itemsPerOffset() const
|
|
||||||
{
|
|
||||||
return m_layouter->itemsPerOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KItemListView::beginTransaction()
|
void KItemListView::beginTransaction()
|
||||||
{
|
{
|
||||||
++m_activeTransactions;
|
++m_activeTransactions;
|
||||||
|
|
|
@ -202,15 +202,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void scrollToItem(int index);
|
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 beginTransaction();
|
||||||
void endTransaction();
|
void endTransaction();
|
||||||
bool isTransactionActive() const;
|
bool isTransactionActive() const;
|
||||||
|
|
|
@ -253,11 +253,6 @@ int KItemListViewLayouter::maximumVisibleItems() const
|
||||||
return rows * m_columnCount;
|
return rows * m_columnCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KItemListViewLayouter::itemsPerOffset() const
|
|
||||||
{
|
|
||||||
return m_columnCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
|
bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
|
||||||
{
|
{
|
||||||
const_cast<KItemListViewLayouter*>(this)->doLayout();
|
const_cast<KItemListViewLayouter*>(this)->doLayout();
|
||||||
|
|
|
@ -107,13 +107,6 @@ public:
|
||||||
*/
|
*/
|
||||||
int maximumVisibleItems() const;
|
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
|
* @return True if the item with the index \p itemIndex
|
||||||
* is the first item within a group.
|
* is the first item within a group.
|
||||||
|
|
Loading…
Reference in a new issue