diff --git a/src/gui/widgets/definition/definitionwidget.cpp b/src/gui/widgets/definition/definitionwidget.cpp index 75306e9..14adeed 100644 --- a/src/gui/widgets/definition/definitionwidget.cpp +++ b/src/gui/widgets/definition/definitionwidget.cpp @@ -50,6 +50,7 @@ DefinitionWidget::DefinitionWidget(bool showNavigation, QWidget *parent) initTheme(); initSearch(); initAudioSources(); + initShortcuts(); initSignals(); } @@ -211,6 +212,27 @@ void DefinitionWidget::initAudioSources() ); } +void DefinitionWidget::initShortcuts() +{ + m_shortcutSkipPrev = + new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Up), this); + m_shortcutSkipPrev->setContext(Qt::WidgetWithChildrenShortcut); + connect( + m_shortcutSkipPrev, &QShortcut::activated, + this, &DefinitionWidget::skipPrev, + Qt::QueuedConnection + ); + + m_shortcutSkipNext = + new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Down), this); + m_shortcutSkipNext->setContext(Qt::WidgetWithChildrenShortcut); + connect( + m_shortcutSkipNext, &QShortcut::activated, + this, &DefinitionWidget::skipNext, + Qt::QueuedConnection + ); +} + void DefinitionWidget::initSignals() { GlobalMediator *mediator = GlobalMediator::getGlobalMediator(); @@ -469,6 +491,8 @@ void DefinitionWidget::showKanji(QSharedPointer kanji) ); m_ui->scrollAreaContents->layout()->addWidget(kanjiWidget); m_ui->scrollArea->verticalScrollBar()->setValue(0); + + m_kanjiShown = true; } void DefinitionWidget::hideKanji() @@ -488,6 +512,8 @@ void DefinitionWidget::hideKanji() } QApplication::processEvents(); m_ui->scrollArea->verticalScrollBar()->setValue(m_savedScroll); + + m_kanjiShown = false; } /* End Kanji Helpers */ @@ -571,3 +597,66 @@ bool DefinitionWidget::positionChild(const QPoint &pos) #undef VERTICAL_OFFSET /* End Child Handlers */ +/* Begin Shortcut Helpers */ + +void DefinitionWidget::skipPrev() +{ + constexpr int ITER_SKIP = 2; + + if (m_kanjiShown) + { + return; + } + + int scrollY = m_ui->scrollArea->verticalScrollBar()->value(); + QLayout *scrollLayout = m_ui->scrollAreaContents->layout(); + int prevY = 0; + for (int i = 1; i < scrollLayout->count(); i += ITER_SKIP) + { + QWidget *widget = scrollLayout->itemAt(i)->widget(); + if (widget == nullptr) + { + break; + } + int currY = widget->mapToParent(QPoint(0, 0)).y(); + if (prevY <= scrollY && scrollY <= currY) + { + m_ui->scrollArea->verticalScrollBar()->setValue(prevY); + return; + } + prevY = currY; + } + + m_ui->scrollArea->verticalScrollBar()->setValue(prevY); +} + +void DefinitionWidget::skipNext() +{ + constexpr int ITER_SKIP = 2; + + if (m_kanjiShown) + { + return; + } + + int scrollY = m_ui->scrollArea->verticalScrollBar()->value(); + QLayout *scrollLayout = m_ui->scrollAreaContents->layout(); + int prevY = 0; + for (int i = 1; i < scrollLayout->count(); i += ITER_SKIP) + { + QWidget *widget = scrollLayout->itemAt(i)->widget(); + if (widget == nullptr) + { + break; + } + int currY = widget->mapToParent(QPoint(0, 0)).y(); + if (prevY <= scrollY && scrollY < currY) + { + m_ui->scrollArea->verticalScrollBar()->setValue(currY); + return; + } + prevY = currY; + } +} + +/* End Shortcut Helpers */ diff --git a/src/gui/widgets/definition/definitionwidget.h b/src/gui/widgets/definition/definitionwidget.h index b12cb7d..f6f20b6 100644 --- a/src/gui/widgets/definition/definitionwidget.h +++ b/src/gui/widgets/definition/definitionwidget.h @@ -24,6 +24,7 @@ #include #include +#include #include #include "definitionstate.h" @@ -100,6 +101,11 @@ private Q_SLOTS: */ void initAudioSources(); + /** + * Initializes keyboard shortcuts. + */ + void initShortcuts(); + /** * Initializes settings signals. */ @@ -157,6 +163,16 @@ private Q_SLOTS: */ bool positionChild(const QPoint &pos); + /** + * Skips to the previous entry in the scroll area. + */ + void skipPrev(); + + /** + * Skips to the next entry in the scroll area. + */ + void skipNext(); + protected: /** * Emits a signal that the Definition Widget has been hidden. @@ -217,11 +233,20 @@ private Q_SLOTS: */ int m_savedScroll = 0; + /* True if a subsearch kanji is shown, false otherwise */ + bool m_kanjiShown = false; + /* Current search ID. Used to prevent erroneous signals */ int m_searchId = 0; /* The child definition widget */ QPointer m_child = nullptr; + + /* Shortcut to skip to the previous entry */ + QShortcut *m_shortcutSkipPrev = nullptr; + + /* Shortcut to skip to the next entry */ + QShortcut *m_shortcutSkipNext = nullptr; }; #endif // DEFINITIONWIDGET_H diff --git a/src/gui/widgets/definition/definitionwidget.ui b/src/gui/widgets/definition/definitionwidget.ui index ca4efb7..6ce7262 100644 --- a/src/gui/widgets/definition/definitionwidget.ui +++ b/src/gui/widgets/definition/definitionwidget.ui @@ -16,6 +16,9 @@ 0 + + Qt::FocusPolicy::ClickFocus + Form @@ -26,7 +29,7 @@ - + Close @@ -75,13 +78,13 @@ - Qt::NoFocus + Qt::FocusPolicy::NoFocus - QFrame::StyledPanel + QFrame::Shape::StyledPanel - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff true @@ -91,7 +94,7 @@ 0 0 - 484 + 480 344 diff --git a/src/gui/widgets/definition/glossarylabel.cpp b/src/gui/widgets/definition/glossarylabel.cpp index df0a9a1..8ec812a 100644 --- a/src/gui/widgets/definition/glossarylabel.cpp +++ b/src/gui/widgets/definition/glossarylabel.cpp @@ -677,6 +677,12 @@ void GlossaryLabel::mousePressEvent(QMouseEvent *event) event->ignore(); } +void GlossaryLabel::keyPressEvent(QKeyEvent *event) +{ + QTextEdit::keyPressEvent(event); + event->ignore(); +} + /* End Event Handlers */ /* Begin Worker Implementation */ diff --git a/src/gui/widgets/definition/glossarylabel.h b/src/gui/widgets/definition/glossarylabel.h index 6e28b3b..42013b3 100644 --- a/src/gui/widgets/definition/glossarylabel.h +++ b/src/gui/widgets/definition/glossarylabel.h @@ -96,6 +96,12 @@ public Q_SLOTS: */ void mousePressEvent(QMouseEvent *event) override; + /** + * Ignore the key press event. + * @param event The key event. + */ + void keyPressEvent(QKeyEvent *event) override; + private Q_SLOTS: /** * Adjust the size of the label. diff --git a/src/gui/widgets/overlay/playeroverlay.cpp b/src/gui/widgets/overlay/playeroverlay.cpp index ed63bc6..9f95569 100644 --- a/src/gui/widgets/overlay/playeroverlay.cpp +++ b/src/gui/widgets/overlay/playeroverlay.cpp @@ -218,6 +218,15 @@ PlayerOverlay::PlayerOverlay(QWidget *parent) : QStackedLayout(parent) mediator, &GlobalMediator::definitionsShown, Qt::QueuedConnection ); + connect( + m_definition, + &DefinitionWidget::widgetShown, + m_definition, + [this] () { + m_definition->setFocus(Qt::FocusReason::PopupFocusReason); + }, + Qt::QueuedConnection + ); connect( m_definition, &DefinitionWidget::widgetHidden, &m_hideTimer, qOverload<>(&QTimer::start),