/****************************************************************************** Copyright (C) 2025 by Taylor Giampaolo This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ******************************************************************************/ #include #include #include FlowFrame::FlowFrame(QWidget *parent) : QFrame(parent) { layout = new FlowLayout(this); setLayout(layout); } void FlowFrame::keyPressEvent(QKeyEvent *event) { QWidget *focused = focusWidget(); if (!focused) { return; } int index = -1; for (int i = 0; i < layout->count(); ++i) { if (!layout->itemAt(i)->widget()) { continue; } auto focusProxy = layout->itemAt(i)->widget()->focusProxy(); if (layout->itemAt(i)->widget() == focused || focusProxy == focused) { if (focusProxy == focused) { focused = layout->itemAt(i)->widget(); } index = i; break; } } if (index == -1) { return; } const QRect focusedRect = focused->geometry(); QWidget *nextFocus = nullptr; switch (event->key()) { case Qt::Key_Right: case Qt::Key_Down: case Qt::Key_Left: case Qt::Key_Up: { // Find next widget in the given direction int bestDistance = INT_MAX; for (int i = 0; i < layout->count(); ++i) { if (i == index) { continue; } QWidget *widget = layout->itemAt(i)->widget(); const QRect rect = widget->geometry(); bool isCandidate = false; int distance = INT_MAX; switch (event->key()) { case Qt::Key_Right: if (rect.left() > focusedRect.right()) { distance = (rect.left() - focusedRect.right()) + qAbs(rect.center().y() - focusedRect.center().y()); isCandidate = true; } break; case Qt::Key_Left: if (rect.right() < focusedRect.left()) { distance = (focusedRect.left() - rect.right()) + qAbs(rect.center().y() - focusedRect.center().y()); isCandidate = true; } break; case Qt::Key_Down: if (rect.top() > focusedRect.bottom()) { distance = (rect.top() - focusedRect.bottom()) + qAbs(rect.center().x() - focusedRect.center().x()); isCandidate = true; } break; case Qt::Key_Up: if (rect.bottom() < focusedRect.top()) { distance = (focusedRect.top() - rect.bottom()) + qAbs(rect.center().x() - focusedRect.center().x()); isCandidate = true; } break; } if (isCandidate && distance < bestDistance) { bestDistance = distance; nextFocus = widget; } } break; } default: QWidget::keyPressEvent(event); return; } if (nextFocus) { nextFocus->setFocus(); QWidget *scrollParent = nextFocus->parentWidget(); while (scrollParent) { QScrollArea *scrollArea = qobject_cast(scrollParent); if (scrollArea) { scrollArea->ensureWidgetVisible(nextFocus, 20, 20); break; } scrollParent = scrollParent->parentWidget(); } } }