[DeckShare] Keep arrow-key navigation between flow items inside a scroll area

This commit is contained in:
Lukas Brübach 2026-09-19 07:23:56 +02:00
parent c6cebb0d2b
commit 4be2dd2f22
2 changed files with 32 additions and 6 deletions

View file

@ -81,10 +81,15 @@ FlowWidget::FlowWidget(QWidget *parent,
/**
* @brief Adds a widget to the flow layout within the FlowWidget.
*
* The widget is filtered for arrow-key events so keyboard navigation between
* the flow items keeps working even when the flow sits inside a QScrollArea,
* which swallows arrow keys before they can reach FlowWidget::keyPressEvent.
*
* @param widget_to_add The widget to add to the flow layout.
*/
void FlowWidget::addWidget(QWidget *widget_to_add) const
void FlowWidget::addWidget(QWidget *widget_to_add)
{
widget_to_add->installEventFilter(this);
flowLayout->addWidget(widget_to_add);
}
@ -179,6 +184,23 @@ QLayoutItem *FlowWidget::itemAt(int index) const
}
void FlowWidget::keyPressEvent(QKeyEvent *event)
{
if (moveFocus(event)) {
event->accept();
return;
}
QWidget::keyPressEvent(event);
}
bool FlowWidget::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::KeyPress && moveFocus(static_cast<QKeyEvent *>(event))) {
return true;
}
return QWidget::eventFilter(watched, event);
}
bool FlowWidget::moveFocus(QKeyEvent *event)
{
// Keyboard navigation between the flow items: arrow keys move focus just
// like clicking the sibling tiles would. Only items that can take keyboard
@ -186,8 +208,7 @@ void FlowWidget::keyPressEvent(QKeyEvent *event)
const bool moveForward = event->key() == Qt::Key_Right || event->key() == Qt::Key_Down;
const bool moveBackward = event->key() == Qt::Key_Left || event->key() == Qt::Key_Up;
if (!moveForward && !moveBackward) {
QWidget::keyPressEvent(event);
return;
return false;
}
QList<QWidget *> focusableItems;
@ -199,8 +220,7 @@ void FlowWidget::keyPressEvent(QKeyEvent *event)
}
if (focusableItems.isEmpty()) {
QWidget::keyPressEvent(event);
return;
return false;
}
int currentIndex = -1;
@ -220,6 +240,7 @@ void FlowWidget::keyPressEvent(QKeyEvent *event)
}
focusableItems.value(nextIndex)->setFocus();
event->accept();
return true;
}
int FlowWidget::count() const

View file

@ -29,7 +29,7 @@ public:
Qt::ScrollBarPolicy horizontalPolicy,
Qt::ScrollBarPolicy verticalPolicy);
void addWidget(QWidget *widget_to_add) const;
void addWidget(QWidget *widget_to_add);
void insertWidgetAtIndex(QWidget *toInsert, int index);
void removeWidget(QWidget *widgetToRemove) const;
void clearLayout();
@ -44,10 +44,15 @@ public slots:
void setSpacing(int hSpacing, int vSpacing);
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
/// @brief Moves keyboard focus to an adjacent flow item for an arrow-key event.
/// @return True when the event was an arrow key and was handled.
bool moveFocus(QKeyEvent *event);
Qt::Orientation flowDirection;
QHBoxLayout *mainLayout;
FlowLayout *flowLayout;