From 37d405d41d07609ba7fbaba9d90fc480f02d8e5d Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Sat, 25 May 2024 15:11:59 +0000 Subject: [PATCH 01/16] WSearchLineEdit: Correctly detect autocomplete vs. automatic "select all" on Enter/Return When the current text selection is due to the automatic selectAll() when focusing the text field, a subsequent Key_Enter should switch to the library view. Otherwise, it is due to an autocompletion and should trigger the search first. --- src/widget/wsearchlineedit.cpp | 22 +++++++++++++--------- src/widget/wsearchlineedit.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 1154fdf88e43..12deea7b9229 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -312,14 +312,11 @@ QString WSearchLineEdit::getSearchText() const { DEBUG_ASSERT(!currentText().isNull()); QString text = currentText(); QCompleter* pCompleter = completer(); - if (pCompleter && hasSelectedText()) { - if (text.startsWith(pCompleter->completionPrefix()) && - pCompleter->completionPrefix().size() == lineEdit()->cursorPosition()) { - // Search for the entered text until the user has accepted the - // completion by pressing Enter or changed/deselected the selected - // completion text with Right or Left key - return pCompleter->completionPrefix(); - } + if (pCompleter && hasCompletionAvailable()) { + // Search for the entered text until the user has accepted the + // completion by pressing Enter or changed/deselected the selected + // completion text with Right or Left key + return pCompleter->completionPrefix(); } return text; } else { @@ -402,7 +399,7 @@ void WSearchLineEdit::keyPressEvent(QKeyEvent* keyEvent) { if (slotClearSearchIfClearButtonHasFocus()) { return; } - if (hasSelectedText()) { + if (hasCompletionAvailable()) { QComboBox::keyPressEvent(keyEvent); slotTriggerSearch(); return; @@ -809,3 +806,10 @@ void WSearchLineEdit::slotSetFont(const QFont& font) { bool WSearchLineEdit::hasSelectedText() const { return lineEdit()->hasSelectedText(); } + +bool WSearchLineEdit::hasCompletionAvailable() const { + QCompleter* pCompleter = completer(); + return pCompleter && hasSelectedText() && + lineEdit()->text().startsWith(pCompleter->completionPrefix()) && + pCompleter->completionPrefix().size() == lineEdit()->cursorPosition(); +} diff --git a/src/widget/wsearchlineedit.h b/src/widget/wsearchlineedit.h index 45d2d7910ca2..61e8110a8df4 100644 --- a/src/widget/wsearchlineedit.h +++ b/src/widget/wsearchlineedit.h @@ -92,6 +92,7 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { void deleteSelectedListItem(); void triggerSearchDebounced(); bool hasSelectedText() const; + bool hasCompletionAvailable() const; inline int findCurrentTextIndex() { return findData(currentText(), Qt::DisplayRole); From e4b9309a993e5d8b962ff7acb84245a082a226b2 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 21 Aug 2024 12:38:48 +0000 Subject: [PATCH 02/16] WSearchLineEdit: Add Ctrl+Return as an alternative to Esc --- src/widget/wsearchlineedit.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 12deea7b9229..5ea0b5666dd5 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -241,7 +241,7 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { "Shows/hides the search history entries") + "\n" + tr("Delete or Backspace") + " " + tr("Delete query from history") + "\n" + - tr("Esc") + " " + tr("Exit search", "Exit search bar and leave focus")); + tr("Esc or Ctrl+Return") + " " + tr("Exit search", "Exit search bar and leave focus")); } void WSearchLineEdit::loadQueriesFromConfig() { @@ -399,6 +399,11 @@ void WSearchLineEdit::keyPressEvent(QKeyEvent* keyEvent) { if (slotClearSearchIfClearButtonHasFocus()) { return; } + if (keyEvent->modifiers() & Qt::ControlModifier) { + // Esc and Ctrl+Enter should have the same effect + emit setLibraryFocus(FocusWidget::TracksTable); + return; + } if (hasCompletionAvailable()) { QComboBox::keyPressEvent(keyEvent); slotTriggerSearch(); From cac9a01201c4751a89e28961796b796e7994e70b Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Thu, 23 May 2024 20:33:57 +0000 Subject: [PATCH 03/16] WSearchLineEdit: Update shortcut presentation in the search box tooltip ...so it uses the same format as the rest of the application. --- src/widget/wsearchlineedit.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 5ea0b5666dd5..ecfc0df530c2 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -227,21 +227,21 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Use operators like bpm:115-128, artist:BooFar, -year:1990") + "\n" + tr("For more information see User Manual > Mixxx Library") + "\n\n" + - tr("Shortcuts") + ": \n" + - tr("Ctrl+F") + " " + + tr("Shortcuts") + ":\n" + + tr("Ctrl+F") + ": " + tr("Focus", "Give search bar input focus") + "\n" + - tr("Return") + " " + + tr("Return") + ": " + tr("Trigger search before search-as-you-type timeout or" "jump to tracks view afterwards") + "\n" + - tr("Ctrl+Backspace") + " " + + tr("Ctrl+Backspace") + ": " + tr("Clear input", "Clear the search bar input field") + "\n" + - tr("Ctrl+Space") + " " + + tr("Ctrl+Space") + ": " + tr("Toggle search history", "Shows/hides the search history entries") + "\n" + - tr("Delete or Backspace") + " " + tr("Delete query from history") + "\n" + - tr("Esc or Ctrl+Return") + " " + tr("Exit search", "Exit search bar and leave focus")); + tr("Delete or Backspace") + ": " + tr("Delete query from history") + "\n" + + tr("Esc or Ctrl+Return") + ": " + tr("Exit search", "Exit search bar and leave focus")); } void WSearchLineEdit::loadQueriesFromConfig() { From 19dd37dd2c58d5a2ef52759ad6479213dbe5bb25 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Fri, 7 Jun 2024 12:03:19 +0000 Subject: [PATCH 04/16] WSearchLineEdit: Fix: Remove unsupported Ctrl+Backspace shortcut from tooltip The Ctrl+Backspace shortcut is a standard shortcut handled by QLineEdit and deletes the current word, but doesn't actually clear the search box if more than one word has been typed. This is different from the function of the clear button, which clears the whole search box. --- src/widget/wsearchlineedit.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index ecfc0df530c2..3d6352a66ff5 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -217,10 +217,7 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { setPalette(pal); m_clearButton->setToolTip(tr("Clear input") + "\n" + - tr("Clear the search bar input field") + "\n\n" + - - tr("Shortcut") + ": \n" + - tr("Ctrl+Backspace")); + tr("Clear the search bar input field")); setBaseTooltip(tr("Search", "noun") + "\n" + tr("Enter a string to search for") + "\n" + @@ -234,8 +231,6 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Trigger search before search-as-you-type timeout or" "jump to tracks view afterwards") + "\n" + - tr("Ctrl+Backspace") + ": " + - tr("Clear input", "Clear the search bar input field") + "\n" + tr("Ctrl+Space") + ": " + tr("Toggle search history", "Shows/hides the search history entries") + From b908e0f7070df01bd96267b106d6bb9845817053 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 21 Aug 2024 11:20:45 +0000 Subject: [PATCH 05/16] WSearchLineEdit: Fix: Add missing whitespace in tooltip text --- src/widget/wsearchlineedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 3d6352a66ff5..9b2766cb861c 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -228,7 +228,7 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Ctrl+F") + ": " + tr("Focus", "Give search bar input focus") + "\n" + tr("Return") + ": " + - tr("Trigger search before search-as-you-type timeout or" + tr("Trigger search before search-as-you-type timeout or " "jump to tracks view afterwards") + "\n" + tr("Ctrl+Space") + ": " + From 1637b3512799820ff889fe313e044882a0c2115a Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 21 Aug 2024 13:13:23 +0200 Subject: [PATCH 06/16] WSearchLineEdit: Order the shortcuts list in the tooltip by importance --- src/widget/wsearchlineedit.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 9b2766cb861c..589866c82087 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -224,19 +224,22 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Use operators like bpm:115-128, artist:BooFar, -year:1990") + "\n" + tr("For more information see User Manual > Mixxx Library") + "\n\n" + - tr("Shortcuts") + ":\n" + tr("Ctrl+F") + ": " + - tr("Focus", "Give search bar input focus") + "\n" + + tr("Focus", "Give search bar input focus") + "\n\n" + + tr("Additional Shortcuts When Focused:") + "\n" + tr("Return") + ": " + tr("Trigger search before search-as-you-type timeout or " "jump to tracks view afterwards") + "\n" + + tr("Esc or Ctrl+Return") + ": " + + tr("Exit search and jump to tracks view", "Exit search bar and leave focus") + "\n" + tr("Ctrl+Space") + ": " + tr("Toggle search history", "Shows/hides the search history entries") + "\n" + - tr("Delete or Backspace") + ": " + tr("Delete query from history") + "\n" + - tr("Esc or Ctrl+Return") + ": " + tr("Exit search", "Exit search bar and leave focus")); + tr("Delete or Backspace") + + " (" + tr("in search history") + "): " + + tr("Delete query from history")); } void WSearchLineEdit::loadQueriesFromConfig() { From 7e2949c3b55815142ed9ed05bf368cd94a46d8f3 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 21 Aug 2024 15:05:23 +0200 Subject: [PATCH 07/16] WSearchLineEdit: Use consistent wording ("jump to" vs. "focus") in tooltip --- src/widget/wsearchlineedit.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 589866c82087..6297fc96dd2f 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -229,11 +229,12 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Additional Shortcuts When Focused:") + "\n" + tr("Return") + ": " + tr("Trigger search before search-as-you-type timeout or " - "jump to tracks view afterwards") + + "focus tracks view afterwards") + "\n" + tr("Esc or Ctrl+Return") + ": " + - tr("Exit search and jump to tracks view", "Exit search bar and leave focus") + "\n" + - tr("Ctrl+Space") + ": " + + tr("Immediately trigger search and focus tracks view", + "Exit search bar and leave focus") + + "\n" + tr("Ctrl+Space") + ": " + tr("Toggle search history", "Shows/hides the search history entries") + "\n" + From 329fa0cfaf3c5473c7adc33d0cd84a78d3b58f4e Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 21 Aug 2024 11:50:40 +0000 Subject: [PATCH 08/16] WSearchLineEdit: Improve description text in search box tooltip --- src/widget/wsearchlineedit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 6297fc96dd2f..37ee90407aa8 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -220,9 +220,9 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Clear the search bar input field")); setBaseTooltip(tr("Search", "noun") + "\n" + - tr("Enter a string to search for") + "\n" + - tr("Use operators like bpm:115-128, artist:BooFar, -year:1990") + - "\n" + tr("For more information see User Manual > Mixxx Library") + + tr("Enter a string to search for.") + " " + + tr("Use operators like bpm:115-128, artist:BooFar, -year:1990.") + + "\n" + tr("See User Manual > Mixxx Library for more information.") + "\n\n" + tr("Ctrl+F") + ": " + tr("Focus", "Give search bar input focus") + "\n\n" + From b848daf137e01577d686b2c59991cfdc7dcafe20 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Fri, 3 May 2024 19:35:18 +0000 Subject: [PATCH 09/16] Library: Add LibraryFeature::selectAndActivate() --- src/library/library.cpp | 2 -- src/library/libraryfeature.cpp | 11 +++++++++++ src/library/libraryfeature.h | 4 ++++ src/library/mixxxlibraryfeature.cpp | 2 +- src/library/trackset/playlistfeature.cpp | 3 +-- src/library/trackset/setlogfeature.cpp | 9 ++------- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/library/library.cpp b/src/library/library.cpp index 21f82be564ea..54c4143a11f5 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -722,8 +722,6 @@ void Library::searchTracksInCollection(const QString& query) { return; } m_pMixxxLibraryFeature->searchAndActivate(query); - emit switchToView(m_sTrackViewName); - m_pSidebarModel->activateDefaultSelection(); } #ifdef __ENGINEPRIME__ diff --git a/src/library/libraryfeature.cpp b/src/library/libraryfeature.cpp index 51ad6ae3fac6..7c88fbf93bdc 100644 --- a/src/library/libraryfeature.cpp +++ b/src/library/libraryfeature.cpp @@ -32,6 +32,17 @@ LibraryFeature::LibraryFeature( } } +void LibraryFeature::selectAndActivate(const QModelIndex& index) { + if (index.isValid()) { + emit featureSelect(this, index); + activateChild(index); + } else { + // calling featureSelect with invalid index will select the root item + emit featureSelect(this, QModelIndex()); + activate(); + } +} + QStringList LibraryFeature::getPlaylistFiles(QFileDialog::FileMode mode) const { QString lastPlaylistDirectory = m_pConfig->getValue( ConfigKey("[Library]", "LastImportExportPlaylistDirectory"), diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index 61972192dcd0..dc4ae2fd9858 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -103,6 +103,10 @@ class LibraryFeature : public QObject { const UserSettingsPointer m_pConfig; public slots: + /// Pretend that the user has clicked on a tree item belonging + /// to this LibraryFeature by updating both the library view + /// and the sidebar selection. + void selectAndActivate(const QModelIndex& index = QModelIndex()); // called when you single click on the root item virtual void activate() = 0; // called when you single click on a child item, e.g., a concrete playlist or crate diff --git a/src/library/mixxxlibraryfeature.cpp b/src/library/mixxxlibraryfeature.cpp index 4ea52b1e6a1f..cee77807b7c3 100644 --- a/src/library/mixxxlibraryfeature.cpp +++ b/src/library/mixxxlibraryfeature.cpp @@ -173,7 +173,7 @@ void MixxxLibraryFeature::searchAndActivate(const QString& query) { return; } m_pLibraryTableModel->search(query); - activate(); + selectAndActivate(); } #ifdef __ENGINEPRIME__ diff --git a/src/library/trackset/playlistfeature.cpp b/src/library/trackset/playlistfeature.cpp index 1fc77890c04d..303b10f55938 100644 --- a/src/library/trackset/playlistfeature.cpp +++ b/src/library/trackset/playlistfeature.cpp @@ -307,8 +307,7 @@ void PlaylistFeature::slotPlaylistTableChanged(int playlistId) { // Else (root item was selected or for some reason no index could be created) // there's nothing to do: either no child was selected earlier, or the root // was selected and will remain selected after the child model was rebuilt. - activateChild(newIndex); - emit featureSelect(this, newIndex); + selectAndActivate(newIndex); } } diff --git a/src/library/trackset/setlogfeature.cpp b/src/library/trackset/setlogfeature.cpp index 7f7b8a01487c..d0a4cc2ae6fe 100644 --- a/src/library/trackset/setlogfeature.cpp +++ b/src/library/trackset/setlogfeature.cpp @@ -706,13 +706,8 @@ void SetlogFeature::slotPlaylistTableChanged(int playlistId) { newIndex = m_pSidebarModel->index(selectedYearIndexRow - 1, 0); } } - if (newIndex.isValid()) { - emit featureSelect(this, newIndex); - activateChild(newIndex); - } else if (rootWasSelected) { - // calling featureSelect with invalid index will select the root item - emit featureSelect(this, newIndex); - activate(); // to reload the new current playlist + if (newIndex.isValid() || rootWasSelected) { + selectAndActivate(newIndex); } } From 4d201ae7a4e353d25f2d3cebeebe95dd5f0f25b9 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Sat, 25 May 2024 15:41:24 +0200 Subject: [PATCH 10/16] Library: Add focusReason parameter to LibraryControl::setLibraryFocus --- src/library/librarycontrol.cpp | 12 +++++++----- src/library/librarycontrol.h | 5 +++-- src/widget/wlibrary.h | 3 ++- src/widget/wlibrarysidebar.h | 3 ++- src/widget/wsearchlineedit.cpp | 17 ++++++++++++++--- src/widget/wsearchlineedit.h | 5 ++++- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp index 0b69650eb51a..a57b664a31bc 100644 --- a/src/library/librarycontrol.cpp +++ b/src/library/librarycontrol.cpp @@ -908,15 +908,17 @@ FocusWidget LibraryControl::getFocusedWidget() { } } -void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget) { +void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget, Qt::FocusReason focusReason) { if (!QApplication::focusWindow()) { qInfo() << "No Mixxx window, popup or menu has focus." << "Don't attempt to focus a specific widget."; return; } - // ignore no-op - if (newFocusWidget == m_focusedWidget) { + // The search box wants to do special handling when the Ctrl+f is used + // while it is already focused. Non-shortcut cases should still be a + // no-op when a control is already focused. + if (newFocusWidget == m_focusedWidget && focusReason != Qt::ShortcutFocusReason) { return; } @@ -925,13 +927,13 @@ void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget) { VERIFY_OR_DEBUG_ASSERT(m_pSearchbox) { return; } - m_pSearchbox->setFocus(); + m_pSearchbox->handleSetFocus(focusReason); return; case FocusWidget::Sidebar: VERIFY_OR_DEBUG_ASSERT(m_pSidebarWidget) { return; } - m_pSidebarWidget->setFocus(); + m_pSidebarWidget->setFocus(focusReason); return; case FocusWidget::TracksTable: VERIFY_OR_DEBUG_ASSERT(m_pLibraryWidget) { diff --git a/src/library/librarycontrol.h b/src/library/librarycontrol.h index 65e21013ea45..35c9e36d40e6 100644 --- a/src/library/librarycontrol.h +++ b/src/library/librarycontrol.h @@ -44,8 +44,9 @@ class LibraryControl : public QObject { void bindLibraryWidget(WLibrary* pLibrary, KeyboardEventFilter* pKeyboard); void bindSidebarWidget(WLibrarySidebar* pLibrarySidebar); void bindSearchboxWidget(WSearchLineEdit* pSearchbox); - // Give the keyboard focus to one of the library widgets - void setLibraryFocus(FocusWidget newFocusWidget); + /// Give the keyboard focus to one of the library widgets + void setLibraryFocus(FocusWidget newFocusWidget, + Qt::FocusReason focusReason = Qt::OtherFocusReason); FocusWidget getFocusedWidget(); signals: diff --git a/src/widget/wlibrary.h b/src/widget/wlibrary.h index a017e9d823dd..c2ac12a3bcff 100644 --- a/src/widget/wlibrary.h +++ b/src/widget/wlibrary.h @@ -56,7 +56,8 @@ class WLibrary : public QStackedWidget, public WBaseWidget { } signals: - FocusWidget setLibraryFocus(FocusWidget newFocus); + FocusWidget setLibraryFocus(FocusWidget newFocus, + Qt::FocusReason focusReason = Qt::OtherFocusReason); public slots: // Show the view registered with the given name. Does nothing if the current diff --git a/src/widget/wlibrarysidebar.h b/src/widget/wlibrarysidebar.h index 4fa356e78b46..91d33befd709 100644 --- a/src/widget/wlibrarysidebar.h +++ b/src/widget/wlibrarysidebar.h @@ -37,7 +37,8 @@ class WLibrarySidebar : public QTreeView, public WBaseWidget { void rightClicked(const QPoint&, const QModelIndex&); void renameItem(const QModelIndex&); void deleteItem(const QModelIndex&); - FocusWidget setLibraryFocus(FocusWidget newFocus); + FocusWidget setLibraryFocus(FocusWidget newFocus, + Qt::FocusReason focusReason = Qt::OtherFocusReason); protected: bool event(QEvent* pEvent) override; diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 37ee90407aa8..03aaa252cd2d 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -791,10 +791,21 @@ void WSearchLineEdit::slotTextChanged(const QString& text) { } void WSearchLineEdit::slotSetShortcutFocus() { - if (hasFocus()) { + handleSetFocus(Qt::ShortcutFocusReason); +} + +void WSearchLineEdit::handleSetFocus(Qt::FocusReason focusReason) { + if (!hasFocus()) { + // selectAll will be called by setFocus - but only if hasFocus + // was false previously and focusReason is Tab, Backtab or Shortcut + setFocus(focusReason); + } else if (focusReason == Qt::TabFocusReason || + focusReason == Qt::BacktabFocusReason || + focusReason == Qt::ShortcutFocusReason) { + // If this widget already had focus (which can happen when the user + // presses the shortcut key while already in the searchbox), + // we need to manually simulate this behavior instead. lineEdit()->selectAll(); - } else { - setFocus(Qt::ShortcutFocusReason); } } diff --git a/src/widget/wsearchlineedit.h b/src/widget/wsearchlineedit.h index 61e8110a8df4..e621f6637d82 100644 --- a/src/widget/wsearchlineedit.h +++ b/src/widget/wsearchlineedit.h @@ -37,6 +37,8 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { void setup(const QDomNode& node, const SkinContext& context); + void handleSetFocus(Qt::FocusReason focusReason); + protected: void resizeEvent(QResizeEvent*) override; void focusInEvent(QFocusEvent*) override; @@ -47,7 +49,8 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { signals: void search(const QString& text); - FocusWidget setLibraryFocus(FocusWidget newFocusWidget); + FocusWidget setLibraryFocus(FocusWidget newFocusWidget, + Qt::FocusReason focusReason = Qt::OtherFocusReason); public slots: void slotSetFont(const QFont& font); From efaa911251a949210bf2863273b752c583397aaa Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 21 Aug 2024 13:03:31 +0200 Subject: [PATCH 11/16] Library: Fix: setLibraryFocus should work even if the window is not currently focused This scenario occurs e.g. when calling setLibraryFocus from a menu action. The popup window has already been closed when QAction::triggered occurs, but the main window has not yet gotten its focus back. As per the documentation of QWidget::setFocus(), when the containing window is not active, the focus change request is delayed until the window becomes active - which is exactly what we want in our case. --- src/library/librarycontrol.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp index a57b664a31bc..af05f574bcf6 100644 --- a/src/library/librarycontrol.cpp +++ b/src/library/librarycontrol.cpp @@ -909,12 +909,6 @@ FocusWidget LibraryControl::getFocusedWidget() { } void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget, Qt::FocusReason focusReason) { - if (!QApplication::focusWindow()) { - qInfo() << "No Mixxx window, popup or menu has focus." - << "Don't attempt to focus a specific widget."; - return; - } - // The search box wants to do special handling when the Ctrl+f is used // while it is already focused. Non-shortcut cases should still be a // no-op when a control is already focused. From f20fcb86b2b08285f42f594f0e38bc8073693c75 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Mon, 20 May 2024 13:02:47 +0000 Subject: [PATCH 12/16] Library: Add Ctrl+Shift+F shortcut to search the internal database --- src/library/library.cpp | 16 ++++++++++++++++ src/library/library.h | 6 ++++++ src/mixxxmainwindow.cpp | 10 ++++++++++ src/widget/wmainmenubar.cpp | 24 ++++++++++++++++++++++++ src/widget/wmainmenubar.h | 2 ++ src/widget/wsearchlineedit.cpp | 20 ++++++-------------- src/widget/wsearchlineedit.h | 1 - 7 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/library/library.cpp b/src/library/library.cpp index 54c4143a11f5..e0c13c72e189 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -717,6 +717,22 @@ void Library::setEditMetadataSelectedClick(bool enabled) { emit setSelectedClick(enabled); } +void Library::slotSearchInCurrentView() { + m_pLibraryControl->setLibraryFocus(FocusWidget::Searchbar, Qt::ShortcutFocusReason); +} + +void Library::slotSearchInAllTracks() { + searchTracksInCollection(); +} + +void Library::searchTracksInCollection() { + VERIFY_OR_DEBUG_ASSERT(m_pMixxxLibraryFeature) { + return; + } + m_pMixxxLibraryFeature->selectAndActivate(); + m_pLibraryControl->setLibraryFocus(FocusWidget::Searchbar, Qt::ShortcutFocusReason); +} + void Library::searchTracksInCollection(const QString& query) { VERIFY_OR_DEBUG_ASSERT(m_pMixxxLibraryFeature) { return; diff --git a/src/library/library.h b/src/library/library.h index e0190084eeba..0dbdbcfb3982 100644 --- a/src/library/library.h +++ b/src/library/library.h @@ -98,6 +98,10 @@ class Library: public QObject { void setRowHeight(int rowHeight); void setEditMetadataSelectedClick(bool enable); + /// Switches to the internal track collection view + /// and focuses the search box. + void searchTracksInCollection(); + /// Triggers a new search in the internal track collection /// and shows the results by switching the view. void searchTracksInCollection(const QString& query); @@ -119,6 +123,8 @@ class Library: public QObject { void slotRefreshLibraryModels(); void slotCreatePlaylist(); void slotCreateCrate(); + void slotSearchInCurrentView(); + void slotSearchInAllTracks(); void onSkinLoadFinished(); void slotSaveCurrentViewState() const; void slotRestoreCurrentViewState() const; diff --git a/src/mixxxmainwindow.cpp b/src/mixxxmainwindow.cpp index c5b44237bf97..a49802f72e58 100644 --- a/src/mixxxmainwindow.cpp +++ b/src/mixxxmainwindow.cpp @@ -935,6 +935,16 @@ void MixxxMainWindow::connectMenuBar() { } if (m_pCoreServices->getLibrary()) { + connect(m_pMenuBar, + &WMainMenuBar::searchInCurrentView, + m_pCoreServices->getLibrary().get(), + &Library::slotSearchInCurrentView, + Qt::UniqueConnection); + connect(m_pMenuBar, + &WMainMenuBar::searchInAllTracks, + m_pCoreServices->getLibrary().get(), + &Library::slotSearchInAllTracks, + Qt::UniqueConnection); connect(m_pMenuBar, &WMainMenuBar::createCrate, m_pCoreServices->getLibrary().get(), diff --git a/src/widget/wmainmenubar.cpp b/src/widget/wmainmenubar.cpp index 9fa9e2d91199..2df2e366e754 100644 --- a/src/widget/wmainmenubar.cpp +++ b/src/widget/wmainmenubar.cpp @@ -168,6 +168,30 @@ void WMainMenuBar::initialize() { pLibraryMenu->addSeparator(); + QString searchHereTitle = tr("Search in Current View..."); + QString searchHereText = tr("Search for tracks in the current library view"); + auto* pSearchHere = new QAction(searchHereTitle, this); + pSearchHere->setShortcut(QKeySequence(tr("Ctrl+f"))); + pSearchHere->setShortcutContext(Qt::ApplicationShortcut); + pSearchHere->setStatusTip(searchHereText); + pSearchHere->setWhatsThis(buildWhatsThis(searchHereTitle, searchHereText)); + connect(pSearchHere, &QAction::triggered, this, &WMainMenuBar::searchInCurrentView); + pLibraryMenu->addAction(pSearchHere); + + QString searchAllTitle = tr("Search in Tracks Library..."); + QString searchAllText = + tr("Search in the internal track collection under \"Tracks\" in " + "the library"); + auto* pSearchAll = new QAction(searchAllTitle, this); + pSearchAll->setShortcut(tr("Ctrl+Shift+F")); + pSearchAll->setShortcutContext(Qt::ApplicationShortcut); + pSearchAll->setStatusTip(searchAllText); + pSearchAll->setWhatsThis(buildWhatsThis(searchAllText, searchAllText)); + connect(pSearchAll, &QAction::triggered, this, &WMainMenuBar::searchInAllTracks); + pLibraryMenu->addAction(pSearchAll); + + pLibraryMenu->addSeparator(); + QString createPlaylistTitle = tr("Create &New Playlist"); QString createPlaylistText = tr("Create a new playlist"); auto* pLibraryCreatePlaylist = new QAction(createPlaylistTitle, this); diff --git a/src/widget/wmainmenubar.h b/src/widget/wmainmenubar.h index 98ec66c698f7..dd9fafadbcee 100644 --- a/src/widget/wmainmenubar.h +++ b/src/widget/wmainmenubar.h @@ -67,6 +67,8 @@ class WMainMenuBar : public QMenuBar { #ifdef __ENGINEPRIME__ void exportLibrary(); #endif + void searchInCurrentView(); + void searchInAllTracks(); void showAbout(); void showKeywheel(bool visible); void showPreferences(); diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 03aaa252cd2d..e74a8bdcd774 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -122,12 +122,6 @@ WSearchLineEdit::WSearchLineEdit(QWidget* pParent, UserSettingsPointer pConfig) this, &WSearchLineEdit::slotClearSearch); - QShortcut* setFocusShortcut = new QShortcut(QKeySequence(tr("Ctrl+F", "Search|Focus")), this); - connect(setFocusShortcut, - &QShortcut::activated, - this, - &WSearchLineEdit::slotSetShortcutFocus); - // Set up a timer to search after a few hundred milliseconds timeout. This // stops us from thrashing the database if you type really fast. m_debouncingTimer.setSingleShot(true); @@ -223,10 +217,12 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { tr("Enter a string to search for.") + " " + tr("Use operators like bpm:115-128, artist:BooFar, -year:1990.") + "\n" + tr("See User Manual > Mixxx Library for more information.") + - "\n\n" + - tr("Ctrl+F") + ": " + - tr("Focus", "Give search bar input focus") + "\n\n" + - tr("Additional Shortcuts When Focused:") + "\n" + + "\n\n" + tr("Ctrl+F") + ": " + + tr("Focus/Select All (Search in current view)", + "Give search bar input focus") + + "\n" + tr("Ctrl+Shift+F") + ": " + + tr("Focus/Select All (Search in \'Tracks\' library view)") + + "\n\n" + tr("Additional Shortcuts When Focused:") + "\n" + tr("Return") + ": " + tr("Trigger search before search-as-you-type timeout or " "focus tracks view afterwards") + @@ -790,10 +786,6 @@ void WSearchLineEdit::slotTextChanged(const QString& text) { m_saveTimer.start(kSaveTimeoutMillis); } -void WSearchLineEdit::slotSetShortcutFocus() { - handleSetFocus(Qt::ShortcutFocusReason); -} - void WSearchLineEdit::handleSetFocus(Qt::FocusReason focusReason) { if (!hasFocus()) { // selectAll will be called by setFocus - but only if hasFocus diff --git a/src/widget/wsearchlineedit.h b/src/widget/wsearchlineedit.h index e621f6637d82..fa7fefcd54f3 100644 --- a/src/widget/wsearchlineedit.h +++ b/src/widget/wsearchlineedit.h @@ -68,7 +68,6 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { void slotDeleteCurrentItem(); private slots: - void slotSetShortcutFocus(); void slotTextChanged(const QString& text); void slotIndexChanged(int index); From d42fdf3e4f101a2b25206f7b211e2d45fdc89fd7 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Fri, 7 Jun 2024 12:11:35 +0000 Subject: [PATCH 13/16] Library: Make search shortcuts configurable via keymap --- res/keyboard/cs_CZ.kbd.cfg | 2 ++ res/keyboard/da_DK.kbd.cfg | 2 ++ res/keyboard/de_CH.kbd.cfg | 2 ++ res/keyboard/de_DE.kbd.cfg | 2 ++ res/keyboard/el_GR.kbd.cfg | 2 ++ res/keyboard/en_US.kbd.cfg | 2 ++ res/keyboard/es_ES.kbd.cfg | 2 ++ res/keyboard/fi_FI.kbd.cfg | 2 ++ res/keyboard/fr_CH.kbd.cfg | 2 ++ res/keyboard/fr_FR.kbd.cfg | 2 ++ res/keyboard/it_IT.kbd.cfg | 2 ++ res/keyboard/ru_RU.kbd.cfg | 2 ++ src/widget/wmainmenubar.cpp | 8 ++++++-- src/widget/wsearchlineedit.cpp | 7 +++++-- src/widget/wsearchlineedit.h | 2 ++ 15 files changed, 37 insertions(+), 4 deletions(-) diff --git a/res/keyboard/cs_CZ.kbd.cfg b/res/keyboard/cs_CZ.kbd.cfg index 6af18ba2a3f0..23bf9f34e32b 100644 --- a/res/keyboard/cs_CZ.kbd.cfg +++ b/res/keyboard/cs_CZ.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/da_DK.kbd.cfg b/res/keyboard/da_DK.kbd.cfg index 323a0942d82a..0676d66b9afd 100644 --- a/res/keyboard/da_DK.kbd.cfg +++ b/res/keyboard/da_DK.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/de_CH.kbd.cfg b/res/keyboard/de_CH.kbd.cfg index 99ccb5361ec0..99d111609898 100644 --- a/res/keyboard/de_CH.kbd.cfg +++ b/res/keyboard/de_CH.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/de_DE.kbd.cfg b/res/keyboard/de_DE.kbd.cfg index 9fdb8e712b6e..6055dc8bdfca 100644 --- a/res/keyboard/de_DE.kbd.cfg +++ b/res/keyboard/de_DE.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/el_GR.kbd.cfg b/res/keyboard/el_GR.kbd.cfg index 140ce77cf7af..622e1ff97417 100644 --- a/res/keyboard/el_GR.kbd.cfg +++ b/res/keyboard/el_GR.kbd.cfg @@ -145,6 +145,8 @@ vinylcontrol_cueing Ctrl+Alt+Θ FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/en_US.kbd.cfg b/res/keyboard/en_US.kbd.cfg index 7fe10956a9fc..7d8c18a89a7a 100644 --- a/res/keyboard/en_US.kbd.cfg +++ b/res/keyboard/en_US.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/es_ES.kbd.cfg b/res/keyboard/es_ES.kbd.cfg index 72423c40319d..73d2f033c99e 100644 --- a/res/keyboard/es_ES.kbd.cfg +++ b/res/keyboard/es_ES.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/fi_FI.kbd.cfg b/res/keyboard/fi_FI.kbd.cfg index ea197ca1f3ad..36ec3d6cd98f 100644 --- a/res/keyboard/fi_FI.kbd.cfg +++ b/res/keyboard/fi_FI.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/fr_CH.kbd.cfg b/res/keyboard/fr_CH.kbd.cfg index d3831aeb8d0d..df828dd9467e 100644 --- a/res/keyboard/fr_CH.kbd.cfg +++ b/res/keyboard/fr_CH.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/fr_FR.kbd.cfg b/res/keyboard/fr_FR.kbd.cfg index eb1a5ba474a4..0c89dc3579d7 100644 --- a/res/keyboard/fr_FR.kbd.cfg +++ b/res/keyboard/fr_FR.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/it_IT.kbd.cfg b/res/keyboard/it_IT.kbd.cfg index 9ef866ec5713..4f6e69649634 100644 --- a/res/keyboard/it_IT.kbd.cfg +++ b/res/keyboard/it_IT.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+U FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/res/keyboard/ru_RU.kbd.cfg b/res/keyboard/ru_RU.kbd.cfg index beda6b6fa7b7..70672f10bb34 100644 --- a/res/keyboard/ru_RU.kbd.cfg +++ b/res/keyboard/ru_RU.kbd.cfg @@ -141,6 +141,8 @@ vinylcontrol_cueing Ctrl+Alt+Г FileMenu_LoadDeck1 Ctrl+o FileMenu_LoadDeck2 Ctrl+Shift+O FileMenu_Quit Ctrl+q +LibraryMenu_SearchInCurrentView Ctrl+f +LibraryMenu_SearchInAllTracks Ctrl+Shift+F LibraryMenu_NewPlaylist Ctrl+n LibraryMenu_NewCrate Ctrl+Shift+N ViewMenu_ShowSkinSettings Ctrl+1 diff --git a/src/widget/wmainmenubar.cpp b/src/widget/wmainmenubar.cpp index 2df2e366e754..aa376b5dfaca 100644 --- a/src/widget/wmainmenubar.cpp +++ b/src/widget/wmainmenubar.cpp @@ -171,7 +171,9 @@ void WMainMenuBar::initialize() { QString searchHereTitle = tr("Search in Current View..."); QString searchHereText = tr("Search for tracks in the current library view"); auto* pSearchHere = new QAction(searchHereTitle, this); - pSearchHere->setShortcut(QKeySequence(tr("Ctrl+f"))); + pSearchHere->setShortcut(QKeySequence(m_pKbdConfig->getValue( + ConfigKey("[KeyboardShortcuts]", "LibraryMenu_SearchInCurrentView"), + tr("Ctrl+f")))); pSearchHere->setShortcutContext(Qt::ApplicationShortcut); pSearchHere->setStatusTip(searchHereText); pSearchHere->setWhatsThis(buildWhatsThis(searchHereTitle, searchHereText)); @@ -183,7 +185,9 @@ void WMainMenuBar::initialize() { tr("Search in the internal track collection under \"Tracks\" in " "the library"); auto* pSearchAll = new QAction(searchAllTitle, this); - pSearchAll->setShortcut(tr("Ctrl+Shift+F")); + pSearchAll->setShortcut(QKeySequence(m_pKbdConfig->getValue( + ConfigKey("[KeyboardShortcuts]", "LibraryMenu_SearchInAllTracks"), + tr("Ctrl+Shift+F")))); pSearchAll->setShortcutContext(Qt::ApplicationShortcut); pSearchAll->setStatusTip(searchAllText); pSearchAll->setWhatsThis(buildWhatsThis(searchAllText, searchAllText)); diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index e74a8bdcd774..3afd0a489f4f 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -212,15 +212,18 @@ void WSearchLineEdit::setup(const QDomNode& node, const SkinContext& context) { m_clearButton->setToolTip(tr("Clear input") + "\n" + tr("Clear the search bar input field")); +} +void WSearchLineEdit::setupToolTip(const QString& searchInCurrentViewShortcut, + const QString& searchInAllTracksShortcut) { setBaseTooltip(tr("Search", "noun") + "\n" + tr("Enter a string to search for.") + " " + tr("Use operators like bpm:115-128, artist:BooFar, -year:1990.") + "\n" + tr("See User Manual > Mixxx Library for more information.") + - "\n\n" + tr("Ctrl+F") + ": " + + "\n\n" + searchInCurrentViewShortcut + ": " + tr("Focus/Select All (Search in current view)", "Give search bar input focus") + - "\n" + tr("Ctrl+Shift+F") + ": " + + "\n" + searchInAllTracksShortcut + ": " + tr("Focus/Select All (Search in \'Tracks\' library view)") + "\n\n" + tr("Additional Shortcuts When Focused:") + "\n" + tr("Return") + ": " + diff --git a/src/widget/wsearchlineedit.h b/src/widget/wsearchlineedit.h index fa7fefcd54f3..4094f081a944 100644 --- a/src/widget/wsearchlineedit.h +++ b/src/widget/wsearchlineedit.h @@ -36,6 +36,8 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { ~WSearchLineEdit(); void setup(const QDomNode& node, const SkinContext& context); + void setupToolTip(const QString& searchInCurrentViewShortcut, + const QString& searchInAllTracksShortcut); void handleSetFocus(Qt::FocusReason focusReason); From a922f0fc8ca886e07f9df70db9a0bf55c1747db2 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Thu, 22 Aug 2024 21:15:59 +0000 Subject: [PATCH 14/16] WSearchLineEdit: Fix: Invoke WSearchLineEdit::setupTooltip in LegacySkinParser --- src/skin/legacy/legacyskinparser.cpp | 24 ++++++++++++++++++++---- src/skin/legacy/legacyskinparser.h | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/skin/legacy/legacyskinparser.cpp b/src/skin/legacy/legacyskinparser.cpp index 5a4dfe5b9701..551eff842a41 100644 --- a/src/skin/legacy/legacyskinparser.cpp +++ b/src/skin/legacy/legacyskinparser.cpp @@ -1454,6 +1454,19 @@ QWidget* LegacySkinParser::parseSearchBox(const QDomElement& node) { commonWidgetSetup(node, pLineEditSearch, false); pLineEditSearch->setup(node, *m_pContext); + // Translate shortcuts to native text + QString searchInCurrentViewShortcut = + localizeShortcutKeys(m_pKeyboard->getKeyboardConfig()->getValue( + ConfigKey("[KeyboardShortcuts]", + "LibraryMenu_SearchInCurrentView"), + "Ctrl+f")); + QString searchInAllTracksShortcut = + localizeShortcutKeys(m_pKeyboard->getKeyboardConfig()->getValue( + ConfigKey("[KeyboardShortcuts]", + "LibraryMenu_SearchInAllTracks"), + "Ctrl+Shift+F")); + pLineEditSearch->setupToolTip(searchInCurrentViewShortcut, searchInAllTracksShortcut); + m_pLibrary->bindSearchboxWidget(pLineEditSearch); return pLineEditSearch; @@ -2504,9 +2517,6 @@ void LegacySkinParser::addShortcutToToolTip(WBaseWidget* pWidget, QString tooltip; - // translate shortcut to native text - QString nativeShortcut = QKeySequence(shortcut, QKeySequence::PortableText).toString(QKeySequence::NativeText); - tooltip += "\n"; tooltip += tr("Shortcut"); if (!cmd.isEmpty()) { @@ -2514,10 +2524,16 @@ void LegacySkinParser::addShortcutToToolTip(WBaseWidget* pWidget, tooltip += cmd; } tooltip += ": "; - tooltip += nativeShortcut; + tooltip += localizeShortcutKeys(shortcut); pWidget->appendBaseTooltip(tooltip); } +QString LegacySkinParser::localizeShortcutKeys(const QString& shortcut) { + // Translate shortcut to native text + return QKeySequence(shortcut, QKeySequence::PortableText) + .toString(QKeySequence::NativeText); +} + QString LegacySkinParser::parseLaunchImageStyle(const QDomNode& node) { return m_pContext->selectString(node, "LaunchImageStyle"); } diff --git a/src/skin/legacy/legacyskinparser.h b/src/skin/legacy/legacyskinparser.h index 11cb4639b713..e58533445b26 100644 --- a/src/skin/legacy/legacyskinparser.h +++ b/src/skin/legacy/legacyskinparser.h @@ -135,6 +135,7 @@ class LegacySkinParser : public QObject, public SkinParser { bool setupPosition=true); void setupConnections(const QDomNode& node, WBaseWidget* pWidget); void addShortcutToToolTip(WBaseWidget* pWidget, const QString& shortcut, const QString& cmd); + QString localizeShortcutKeys(const QString& shortcut); QString getLibraryStyle(const QDomNode& node); QString lookupNodeGroup(const QDomElement& node); From 408bb41841e8678e20a5797d90423e09120e6146 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Fri, 23 Aug 2024 11:21:02 +0000 Subject: [PATCH 15/16] WSearchLineEdit: Review: Rename WSearchLineEdit::handleSetFocus to setFocus --- src/library/librarycontrol.cpp | 2 +- src/widget/wsearchlineedit.cpp | 4 ++-- src/widget/wsearchlineedit.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp index af05f574bcf6..2fe96b70ad7e 100644 --- a/src/library/librarycontrol.cpp +++ b/src/library/librarycontrol.cpp @@ -921,7 +921,7 @@ void LibraryControl::setLibraryFocus(FocusWidget newFocusWidget, Qt::FocusReason VERIFY_OR_DEBUG_ASSERT(m_pSearchbox) { return; } - m_pSearchbox->handleSetFocus(focusReason); + m_pSearchbox->setFocus(focusReason); return; case FocusWidget::Sidebar: VERIFY_OR_DEBUG_ASSERT(m_pSidebarWidget) { diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index 3afd0a489f4f..bea36e403698 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -789,11 +789,11 @@ void WSearchLineEdit::slotTextChanged(const QString& text) { m_saveTimer.start(kSaveTimeoutMillis); } -void WSearchLineEdit::handleSetFocus(Qt::FocusReason focusReason) { +void WSearchLineEdit::setFocus(Qt::FocusReason focusReason) { if (!hasFocus()) { // selectAll will be called by setFocus - but only if hasFocus // was false previously and focusReason is Tab, Backtab or Shortcut - setFocus(focusReason); + QWidget::setFocus(focusReason); } else if (focusReason == Qt::TabFocusReason || focusReason == Qt::BacktabFocusReason || focusReason == Qt::ShortcutFocusReason) { diff --git a/src/widget/wsearchlineedit.h b/src/widget/wsearchlineedit.h index 4094f081a944..0a123d96bac7 100644 --- a/src/widget/wsearchlineedit.h +++ b/src/widget/wsearchlineedit.h @@ -39,7 +39,7 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { void setupToolTip(const QString& searchInCurrentViewShortcut, const QString& searchInAllTracksShortcut); - void handleSetFocus(Qt::FocusReason focusReason); + void setFocus(Qt::FocusReason focusReason); protected: void resizeEvent(QResizeEvent*) override; From de0e7f4bcd89f3d5e46358f36b782ac4c669ee9e Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Fri, 23 Aug 2024 11:21:53 +0000 Subject: [PATCH 16/16] WSearchLineEdit: Review: Simplify WSearchLineEdit::getSearchText --- src/widget/wsearchlineedit.cpp | 21 ++++++++++++++------- src/widget/wsearchlineedit.h | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/widget/wsearchlineedit.cpp b/src/widget/wsearchlineedit.cpp index bea36e403698..fbb728c70cb3 100644 --- a/src/widget/wsearchlineedit.cpp +++ b/src/widget/wsearchlineedit.cpp @@ -309,12 +309,12 @@ QString WSearchLineEdit::getSearchText() const { if (isEnabled()) { DEBUG_ASSERT(!currentText().isNull()); QString text = currentText(); - QCompleter* pCompleter = completer(); - if (pCompleter && hasCompletionAvailable()) { + QString completionPrefix; + if (hasCompletionAvailable(&completionPrefix)) { // Search for the entered text until the user has accepted the // completion by pressing Enter or changed/deselected the selected // completion text with Right or Left key - return pCompleter->completionPrefix(); + return completionPrefix; } return text; } else { @@ -817,9 +817,16 @@ bool WSearchLineEdit::hasSelectedText() const { return lineEdit()->hasSelectedText(); } -bool WSearchLineEdit::hasCompletionAvailable() const { +bool WSearchLineEdit::hasCompletionAvailable(QString* completionPrefix) const { QCompleter* pCompleter = completer(); - return pCompleter && hasSelectedText() && - lineEdit()->text().startsWith(pCompleter->completionPrefix()) && - pCompleter->completionPrefix().size() == lineEdit()->cursorPosition(); + QString prefix = pCompleter ? pCompleter->completionPrefix() : QString(); + if (!prefix.isEmpty() && hasSelectedText() && + lineEdit()->text().startsWith(prefix) && + prefix.size() == lineEdit()->cursorPosition()) { + if (completionPrefix) { + *completionPrefix = prefix; + } + return true; + } + return false; } diff --git a/src/widget/wsearchlineedit.h b/src/widget/wsearchlineedit.h index 0a123d96bac7..e56507294705 100644 --- a/src/widget/wsearchlineedit.h +++ b/src/widget/wsearchlineedit.h @@ -96,7 +96,7 @@ class WSearchLineEdit : public QComboBox, public WBaseWidget { void deleteSelectedListItem(); void triggerSearchDebounced(); bool hasSelectedText() const; - bool hasCompletionAvailable() const; + bool hasCompletionAvailable(QString* completionPrefix = nullptr) const; inline int findCurrentTextIndex() { return findData(currentText(), Qt::DisplayRole);