diff --git a/src/library/autodj/dlgautodj.cpp b/src/library/autodj/dlgautodj.cpp index de66efb902b5..9c2819bae4bd 100644 --- a/src/library/autodj/dlgautodj.cpp +++ b/src/library/autodj/dlgautodj.cpp @@ -349,8 +349,9 @@ void DlgAutoDJ::slotTransitionModeChanged(int newIndex) { m_pAutoDJProcessor->setTransitionMode( static_cast( fadeModeCombobox->itemData(newIndex).toInt())); - // Move focus to tracks table to immediately allow keyboard shortcuts again. - setFocus(); + // Clicking on a transition mode item moves keyboard focus to the list widget. + // Move focus back to the previously focused library widget. + ControlObject::set(ConfigKey("[Library]", "refocus_prev_widget"), 1); } void DlgAutoDJ::slotRepeatPlaylistChanged(int checkState) { @@ -394,12 +395,13 @@ void DlgAutoDJ::setFocus() { } void DlgAutoDJ::keyPressEvent(QKeyEvent* pEvent) { - // Return, Enter and Escape key move focus to the AutoDJ queue to immediately - // allow keyboard shortcuts again. + // If we receive key events either the mode selector or the spinbox are focused. + // Return, Enter and Escape move focus back to the previously focused + // library widget in order to immediately allow keyboard shortcuts again. if (pEvent->key() == Qt::Key_Return || pEvent->key() == Qt::Key_Enter || pEvent->key() == Qt::Key_Escape) { - setFocus(); + ControlObject::set(ConfigKey("[Library]", "refocus_prev_widget"), 1); return; } return QWidget::keyPressEvent(pEvent); diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp index 6c8d297efa36..4110c5d70a73 100644 --- a/src/library/librarycontrol.cpp +++ b/src/library/librarycontrol.cpp @@ -57,7 +57,8 @@ void LoadToGroupController::slotLoadToGroupAndPlay(double v) { LibraryControl::LibraryControl(Library* pLibrary) : QObject(pLibrary), m_pLibrary(pLibrary), - m_pFocusedWidget(FocusWidget::None), + m_focusedWidget(FocusWidget::None), + m_prevFocusedWidget(FocusWidget::None), m_pLibraryWidget(nullptr), m_pSidebarWidget(nullptr), m_pSearchbox(nullptr), @@ -172,6 +173,17 @@ LibraryControl::LibraryControl(Library* pLibrary) }); #endif + // Pure trigger control. Alternative for signal/slot since widgets that want + // to call refocusPrevLibraryWidget() are cumbersome to connect to. + // This CO is never actually set or read so the value just needs to be not 0 + m_pRefocusPrevWidgetCO = std::make_unique( + ConfigKey("[Library]", "refocus_prev_widget")); + m_pRefocusPrevWidgetCO->setButtonMode(ControlPushButton::TRIGGER); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + m_pRefocusPrevWidgetCO->connectValueChangeRequest(this, + &LibraryControl::refocusPrevLibraryWidget); +#endif + // Control to "goto" the currently selected item in focused widget (context dependent) m_pGoToItem = std::make_unique(ConfigKey("[Library]", "GoToItem")); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -411,7 +423,7 @@ LibraryControl::LibraryControl(Library* pLibrary) connect(app, &QApplication::focusChanged, this, - &LibraryControl::updateFocusedWidgetControls); + &LibraryControl::slotFocusedWidgetChanged); // Also update controls if the window focus changed. // Even though any new menu window has focus and will receive keypress events // it does NOT have a focused widget before the first click or keypress. @@ -628,7 +640,7 @@ void LibraryControl::slotMoveVertical(double v) { return; } - switch (m_pFocusedWidget) { + switch (m_focusedWidget) { case FocusWidget::Sidebar: { int i = static_cast(v); slotSelectSidebarItem(i); @@ -747,11 +759,8 @@ void LibraryControl::emitKeyEvent(QKeyEvent&& event) { return; } - switch (m_pFocusedWidget) { - case FocusWidget::None: + if (m_focusedWidget == FocusWidget::None) { return setLibraryFocus(FocusWidget::TracksTable); - default: - break; } // Send the event pointer to the currently focused widget @@ -818,7 +827,7 @@ void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget) { } // ignore no-op - if (newFocusWidget == m_pFocusedWidget) { + if (newFocusWidget == m_focusedWidget) { return; } @@ -850,13 +859,32 @@ void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget) { // to update [Library],focused_widget } +void LibraryControl::slotFocusedWidgetChanged(QWidget* oldW, QWidget* newW) { + Q_UNUSED(newW); + + // If one of the library widgets had focus store it so we can return to it, + // for example when we finish editing a WBeatSizeSpinBox. + if (m_pSearchbox && oldW == m_pSearchbox) { + m_prevFocusedWidget = FocusWidget::Searchbar; + } else if (m_pSidebarWidget && oldW == m_pSidebarWidget) { + m_prevFocusedWidget = FocusWidget::Sidebar; + } else if (m_pLibraryWidget && oldW == m_pLibraryWidget->currentWidget()) { + m_prevFocusedWidget = FocusWidget::TracksTable; + } + updateFocusedWidgetControls(); +} + void LibraryControl::updateFocusedWidgetControls() { - m_pFocusedWidget = getFocusedWidget(); + m_focusedWidget = getFocusedWidget(); // Update "[Library], focused_widget" control - double newVal = static_cast(m_pFocusedWidget); + double newVal = static_cast(m_focusedWidget); m_pFocusedWidgetCO->setAndConfirm(newVal); } +void LibraryControl::refocusPrevLibraryWidget() { + setLibraryFocus(m_prevFocusedWidget); +} + void LibraryControl::slotSelectSidebarItem(double v) { if (!m_pSidebarWidget) { return; @@ -895,7 +923,7 @@ void LibraryControl::slotGoToItem(double v) { return; } - switch (m_pFocusedWidget) { + switch (m_focusedWidget) { case FocusWidget::Sidebar: // Focus the library if this is a leaf node in the tree // Note that Tracks and AutoDJ always return 'false': diff --git a/src/library/librarycontrol.h b/src/library/librarycontrol.h index 6c8b44976247..f4680a9d1de8 100644 --- a/src/library/librarycontrol.h +++ b/src/library/librarycontrol.h @@ -62,8 +62,10 @@ class LibraryControl : public QObject { void sidebarWidgetDeleted(); void searchboxWidgetDeleted(); - // Update m_pFocusedWidget and m_pFocusedWidgetCO + // Update m_focusedWidget and m_pFocusedWidgetCO + void slotFocusedWidgetChanged(QWidget* oldW, QWidget* newW); void updateFocusedWidgetControls(); + void refocusPrevLibraryWidget(); void slotMoveUp(double); void slotMoveDown(double); @@ -134,7 +136,9 @@ class LibraryControl : public QObject { std::unique_ptr m_pMoveFocusBackward; std::unique_ptr m_pMoveFocus; std::unique_ptr m_pFocusedWidgetCO; - FocusWidget m_pFocusedWidget; + FocusWidget m_focusedWidget; + std::unique_ptr m_pRefocusPrevWidgetCO; + FocusWidget m_prevFocusedWidget; // Control to choose the currently selected item in focused widget (double click) std::unique_ptr m_pGoToItem; diff --git a/src/widget/wbeatspinbox.cpp b/src/widget/wbeatspinbox.cpp index 9e8986a81305..099679f45ecf 100644 --- a/src/widget/wbeatspinbox.cpp +++ b/src/widget/wbeatspinbox.cpp @@ -286,15 +286,13 @@ bool WBeatSpinBox::event(QEvent* pEvent) { } void WBeatSpinBox::keyPressEvent(QKeyEvent* pEvent) { - // By default, Return & Enter keys apply current value. - // Here, Return, Enter and Escape apply and move focus to tracks table. - // TODO(ronso0) switch to previously focused (library?) widget instead + // By default, Return & Enter keys apply the current value. + // Additionally, move focus back to the previously focused library widget. if (pEvent->key() == Qt::Key_Return || pEvent->key() == Qt::Key_Enter || pEvent->key() == Qt::Key_Escape) { QDoubleSpinBox::keyPressEvent(pEvent); - ControlObject::set(ConfigKey("[Library]", "focused_widget"), - static_cast(FocusWidget::TracksTable)); + ControlObject::set(ConfigKey("[Library]", "refocus_prev_widget"), 1); return; } return QDoubleSpinBox::keyPressEvent(pEvent); diff --git a/src/widget/weffectchainpresetselector.cpp b/src/widget/weffectchainpresetselector.cpp index 16de08a10158..f8a0a924e54b 100644 --- a/src/widget/weffectchainpresetselector.cpp +++ b/src/widget/weffectchainpresetselector.cpp @@ -90,11 +90,9 @@ void WEffectChainPresetSelector::populate() { void WEffectChainPresetSelector::slotEffectChainPresetSelected(int index) { m_pChain->loadChainPreset( m_pChainPresetManager->getPreset(currentData().toString())); - // After selecting an effect move focus to the tracks table in order - // to immediately allow keyboard shortcuts again. - // TODO(ronso0) switch to previously focused (library?) widget instead - ControlObject::set(ConfigKey("[Library]", "focused_widget"), - static_cast(FocusWidget::TracksTable)); + // Clicking a chain item moves keyboard focus to the list view. + // Move focus back to the previously focused library widget. + ControlObject::set(ConfigKey("[Library]", "refocus_prev_widget"), 1); } void WEffectChainPresetSelector::slotChainPresetChanged(const QString& name) { diff --git a/src/widget/weffectselector.cpp b/src/widget/weffectselector.cpp index c6a3a80c22c2..ab1e21170a05 100644 --- a/src/widget/weffectselector.cpp +++ b/src/widget/weffectselector.cpp @@ -89,11 +89,9 @@ void WEffectSelector::slotEffectSelected(int newIndex) { m_pEffectSlot->loadEffectWithDefaults(pManifest); setBaseTooltip(itemData(newIndex, Qt::ToolTipRole).toString()); - // After selecting an effect send Shift+Tab to move focus to tracks table - // in order to immediately allow keyboard shortcuts again. - // TODO(ronso0) switch to previously focused (library?) widget instead - ControlObject::set(ConfigKey("[Library]", "focused_widget"), - static_cast(FocusWidget::TracksTable)); + // Clicking an effect item moves keyboard focus to the list view. + // Move focus back to the previously focused library widget. + ControlObject::set(ConfigKey("[Library]", "refocus_prev_widget"), 1); } void WEffectSelector::slotEffectUpdated() {