diff options
author | Uwe Klotz <uklotz@mixxx.org> | 2020-10-18 11:59:36 +0200 |
---|---|---|
committer | Uwe Klotz <uklotz@mixxx.org> | 2020-10-18 17:23:52 +0200 |
commit | 012d9bcafcbadf455fc7707d20c460acecfc6f31 (patch) | |
tree | 81dcacfe5d93cfc1a825a81839e86c6bdf4d8def | |
parent | 653b5559c2efa93b83ed020fb4a5eb1a4cfdf68c (diff) |
Extract WSearchRelatedTracksMenu from WTrackMenu
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | build/depends.py | 1 | ||||
-rw-r--r-- | src/widget/wsearchrelatedtracksmenu.cpp | 179 | ||||
-rw-r--r-- | src/widget/wsearchrelatedtracksmenu.h | 30 | ||||
-rw-r--r-- | src/widget/wtrackmenu.cpp | 153 | ||||
-rw-r--r-- | src/widget/wtrackmenu.h | 3 |
6 files changed, 222 insertions, 145 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ccfbb72072..c0a44c18e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -902,6 +902,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/widget/wpushbutton.cpp src/widget/wrecordingduration.cpp src/widget/wsearchlineedit.cpp + src/widget/wsearchrelatedtracksmenu.cpp src/widget/wsingletoncontainer.cpp src/widget/wsizeawarestack.cpp src/widget/wskincolor.cpp diff --git a/build/depends.py b/build/depends.py index dc8e83e477..a735ce93a3 100644 --- a/build/depends.py +++ b/build/depends.py @@ -980,6 +980,7 @@ class MixxxCore(Feature): "src/widget/wspinny.cpp", "src/widget/wskincolor.cpp", "src/widget/wsearchlineedit.cpp", + "src/widget/wsearchrelatedtracksmenu.cpp", "src/widget/wpixmapstore.cpp", "src/widget/paintable.cpp", "src/widget/wimagestore.cpp", diff --git a/src/widget/wsearchrelatedtracksmenu.cpp b/src/widget/wsearchrelatedtracksmenu.cpp new file mode 100644 index 0000000000..8286fdf642 --- /dev/null +++ b/src/widget/wsearchrelatedtracksmenu.cpp @@ -0,0 +1,179 @@ +#include "widget/wsearchrelatedtracksmenu.h" + +#include "track/track.h" +#include "util/qt.h" + +WSearchRelatedTracksMenu::WSearchRelatedTracksMenu( + QWidget* parent) + : QMenu(tr("Search related Tracks"), parent) { +} + +void WSearchRelatedTracksMenu::addActionsForTrack( + const Track& track) { + bool addSeparator = false; + + // Musical property actions + const auto keyText = track.getKeyText(); + if (!keyText.isEmpty()) { + const auto keyTextDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(keyText); + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Harmonic keys for \"%1\"") + .arg(keyTextDisplay), + [this, keyText]() { + emit triggerSearch( + QStringLiteral("~key:\"") + + keyText + QChar('"')); + }); + } + const auto genre = track.getGenre(); + if (!genre.isEmpty()) { + const auto genreDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(genre); + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Genre \"%1\"") + .arg(genreDisplay), + [this, genre]() { + emit triggerSearch( + QStringLiteral("genre:\"") + + genre + QChar('"')); + }); + } + + // Artist actions + addSeparator = true; + auto primaryArtist = track.getArtist(); + auto secondaryArtist = track.getAlbumArtist(); + if (primaryArtist.isEmpty()) { + primaryArtist = secondaryArtist; + secondaryArtist = QString(); + } else { + if (!secondaryArtist.isEmpty() && + primaryArtist.contains(secondaryArtist)) { + // Use the shorter string as primary artist and the + // longer string as secondary artist + if (primaryArtist == secondaryArtist) { + secondaryArtist = QString(); + } else { + std::swap(primaryArtist, secondaryArtist); + } + } + } + DEBUG_ASSERT(!primaryArtist.isEmpty() || secondaryArtist.isEmpty()); + if (!primaryArtist.isEmpty()) { + const auto primaryArtistDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(primaryArtist); + const auto secondaryArtistDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(secondaryArtist); + // Search tracks with similar artist(s) + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Artist \"%1\"") + .arg(primaryArtistDisplay), + [this, primaryArtist]() { + emit triggerSearch( + QStringLiteral("artist:\"") + + primaryArtist + QChar('"')); + }); + if (!secondaryArtist.isEmpty()) { + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Artist \"%1\"") + .arg(secondaryArtistDisplay), + [this, secondaryArtist]() { + emit triggerSearch( + QStringLiteral("artist:\"") + + secondaryArtist + QChar('"')); + }); + } + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Album artist \"%1\"") + .arg(primaryArtistDisplay), + [this, primaryArtist]() { + emit triggerSearch( + QStringLiteral("album_artist:\"") + + primaryArtist + QChar('"')); + }); + if (!secondaryArtist.isEmpty()) { + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Album artist \"%1\"") + .arg(secondaryArtistDisplay), + [this, secondaryArtist]() { + emit triggerSearch( + QStringLiteral( + "album_artist:\"") + + secondaryArtist + QChar('"')); + }); + } + } + const auto composer = track.getComposer(); + if (!composer.isEmpty()) { + const auto composerDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(composer); + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Composer \"%1\"") + .arg(composerDisplay), + [this, composer]() { + emit triggerSearch( + QStringLiteral("composer:\"") + + composer + QChar('"')); + }); + } + + // Title actions + addSeparator = true; + const auto title = track.getTitle(); + if (!title.isEmpty()) { + const auto titleDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(title); + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Title \"%1\"") + .arg(titleDisplay), + [this, title]() { + emit triggerSearch( + QStringLiteral("title:\"") + + title + QChar('"')); + }); + } + const auto album = track.getAlbum(); + if (!album.isEmpty()) { + const auto albumDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(album); + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Album \"%1\"") + .arg(albumDisplay), + [this, album]() { + emit triggerSearch( + QStringLiteral("album:\"") + + album + QChar('"')); + }); + } + + // File system actions + addSeparator = true; + const auto locationPath = track.getFileInfo().directory(); + if (!locationPath.isEmpty()) { + const auto locationPathDisplay = + mixxx::escapeTextPropertyWithoutShortcuts(locationPath); + if (addSeparator) { + this->addSeparator(); + addSeparator = false; + } + addSeparator = addSeparatorBeforeAction(addSeparator); + addAction( + tr("Folder \"%1\"") + .arg(locationPathDisplay), + [this, locationPath]() { + emit triggerSearch( + QStringLiteral("location:\"") + + locationPath + QChar('"')); + }); + } +} diff --git a/src/widget/wsearchrelatedtracksmenu.h b/src/widget/wsearchrelatedtracksmenu.h new file mode 100644 index 0000000000..99c8f18399 --- /dev/null +++ b/src/widget/wsearchrelatedtracksmenu.h @@ -0,0 +1,30 @@ +#pragma once + +#include <QMenu> + +class Track; + +class WSearchRelatedTracksMenu : public QMenu { + Q_OBJECT + public: + explicit WSearchRelatedTracksMenu( + QWidget* parent = nullptr); + ~WSearchRelatedTracksMenu() override = default; + + void addActionsForTrack( + const Track& track); + + signals: + void triggerSearch( + const QString& searchQuery); + + private: + bool addSeparatorBeforeAction( + bool addSeparator) { + if (addSeparator) { + this->addSeparator(); + } + // Reset flag + return false; + } +}; diff --git a/src/widget/wtrackmenu.cpp b/src/widget/wtrackmenu.cpp index 526a235726..5b1f9c320c 100644 --- a/src/widget/wtrackmenu.cpp +++ b/src/widget/wtrackmenu.cpp @@ -31,6 +31,7 @@ #include "widget/wcolorpickeraction.h" #include "widget/wcoverartlabel.h" #include "widget/wcoverartmenu.h" +#include "widget/wsearchrelatedtracksmenu.h" #include "widget/wskincolor.h" #include "widget/wstarrating.h" #include "widget/wwidget.h" @@ -144,160 +145,24 @@ void WTrackMenu::createMenus() { // TODO: Create a new subclass of QMenu? DEBUG_ASSERT(!m_pSearchRelatedMenu); m_pSearchRelatedMenu = - make_parented<QMenu>(tr("Search related Tracks"), this); + make_parented<WSearchRelatedTracksMenu>(this); connect(m_pSearchRelatedMenu, &QMenu::aboutToShow, this, [this] { m_pSearchRelatedMenu->clear(); - m_pSearchRelatedMenu->setEnabled(false); const auto pTrack = getFirstTrackPointer(); - if (!pTrack) { - return; - } - const auto musicalKey = pTrack->getKeyText(); - if (!musicalKey.isEmpty()) { - const auto musicalKeyText = - mixxx::escapeTextPropertyWithoutShortcuts(musicalKey); - m_pSearchRelatedMenu->addAction( - tr("Harmonic keys for \"%1\"") - .arg(musicalKeyText), - [this, musicalKey]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("~key:\"") + - musicalKey + QChar('"')); - }); - } - const auto genre = pTrack->getGenre(); - if (!genre.isEmpty()) { - const auto genreText = - mixxx::escapeTextPropertyWithoutShortcuts(genre); - m_pSearchRelatedMenu->addAction( - tr("Genre \"%1\"") - .arg(genreText), - [this, genre]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("genre:\"") + - genre + QChar('"')); - }); - } - const auto title = pTrack->getTitle(); - if (!title.isEmpty()) { - const auto titleText = - mixxx::escapeTextPropertyWithoutShortcuts(title); - m_pSearchRelatedMenu->addAction( - tr("Title \"%1\"") - .arg(titleText), - [this, title]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("title:\"") + - title + QChar('"')); - }); - } - auto primaryArtist = pTrack->getArtist(); - auto secondaryArtist = pTrack->getAlbumArtist(); - if (primaryArtist.isEmpty()) { - primaryArtist = secondaryArtist; - secondaryArtist = QString(); - } else { - if (!secondaryArtist.isEmpty() && - primaryArtist.contains(secondaryArtist)) { - // Use the shorter string as primary artist and the - // longer string as secondary artist - if (primaryArtist == secondaryArtist) { - secondaryArtist = QString(); - } else { - std::swap(primaryArtist, secondaryArtist); - } - } - } - DEBUG_ASSERT(!primaryArtist.isEmpty() || secondaryArtist.isEmpty()); - if (!primaryArtist.isEmpty()) { - const auto primaryArtistText = - mixxx::escapeTextPropertyWithoutShortcuts(primaryArtist); - const auto secondaryArtistText = - mixxx::escapeTextPropertyWithoutShortcuts(secondaryArtist); - // Search tracks with similar artist(s) - m_pSearchRelatedMenu->addAction( - tr("Artist \"%1\"") - .arg(primaryArtistText), - [this, primaryArtist]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("artist:\"") + - primaryArtist + QChar('"')); - }); - if (!secondaryArtist.isEmpty()) { - m_pSearchRelatedMenu->addAction( - tr("Artist \"%1\"") - .arg(secondaryArtistText), - [this, secondaryArtist]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("artist:\"") + - secondaryArtist + QChar('"')); - }); - } - m_pSearchRelatedMenu->addAction( - tr("Album artist \"%1\"") - .arg(primaryArtistText), - [this, primaryArtist]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("album_artist:\"") + - primaryArtist + QChar('"')); - }); - if (!secondaryArtist.isEmpty()) { - m_pSearchRelatedMenu->addAction( - tr("Album artist \"%1\"") - .arg(secondaryArtistText), - [this, secondaryArtist]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral( - "album_artist:\"") + - secondaryArtist + QChar('"')); - }); - } - } - const auto albumTitle = pTrack->getAlbum(); - if (!albumTitle.isEmpty()) { - const auto albumTitleText = - mixxx::escapeTextPropertyWithoutShortcuts(albumTitle); - m_pSearchRelatedMenu->addAction( - tr("Album \"%1\"") - .arg(albumTitleText), - [this, albumTitle]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("album:\"") + - albumTitle + QChar('"')); - }); - } - const auto composer = pTrack->getComposer(); - if (!composer.isEmpty()) { - const auto composerText = - mixxx::escapeTextPropertyWithoutShortcuts(composer); - m_pSearchRelatedMenu->addAction( - tr("Composer \"%1\"") - .arg(composerText), - [this, composer]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("composer:\"") + - composer + QChar('"')); - }); - } - const auto locationPath = pTrack->getFileInfo().directory(); - if (!locationPath.isEmpty()) { - const auto locationPathText = - mixxx::escapeTextPropertyWithoutShortcuts(locationPath); - m_pSearchRelatedMenu->addAction( - tr("Folder \"%1\"") - .arg(locationPathText), - [this, locationPath]() { - m_pLibrary->searchTracksInCollection( - QStringLiteral("location:\"") + - locationPath + QChar('"')); - }); + if (pTrack) { + m_pSearchRelatedMenu->addActionsForTrack(*pTrack); } m_pSearchRelatedMenu->setEnabled( !m_pSearchRelatedMenu->isEmpty()); }); + connect(m_pSearchRelatedMenu, + &WSearchRelatedTracksMenu::triggerSearch, + [this](const QString& searchQuery) { + m_pLibrary->searchTracksInCollection(searchQuery); + }); } } diff --git a/src/widget/wtrackmenu.h b/src/widget/wtrackmenu.h index 1a16730738..1234627bde 100644 --- a/src/widget/wtrackmenu.h +++ b/src/widget/wtrackmenu.h @@ -21,6 +21,7 @@ class Library; class TrackModel; class WColorPickerAction; class WCoverArtMenu; +class WSearchRelatedTracksMenu; /// A context menu for track(s). /// Can be used with individual track type widgets based on TrackPointer @@ -198,7 +199,7 @@ class WTrackMenu : public QMenu { QMenu* m_pBPMMenu{}; QMenu* m_pColorMenu{}; WCoverArtMenu* m_pCoverMenu{}; - parented_ptr<QMenu> m_pSearchRelatedMenu; + parented_ptr<WSearchRelatedTracksMenu> m_pSearchRelatedMenu; // Reload Track Metadata Action: QAction* m_pImportMetadataFromFileAct{}; |