summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Klotz <uklotz@mixxx.org>2020-10-18 11:59:36 +0200
committerUwe Klotz <uklotz@mixxx.org>2020-10-18 17:23:52 +0200
commit012d9bcafcbadf455fc7707d20c460acecfc6f31 (patch)
tree81dcacfe5d93cfc1a825a81839e86c6bdf4d8def
parent653b5559c2efa93b83ed020fb4a5eb1a4cfdf68c (diff)
Extract WSearchRelatedTracksMenu from WTrackMenu
-rw-r--r--CMakeLists.txt1
-rw-r--r--build/depends.py1
-rw-r--r--src/widget/wsearchrelatedtracksmenu.cpp179
-rw-r--r--src/widget/wsearchrelatedtracksmenu.h30
-rw-r--r--src/widget/wtrackmenu.cpp153
-rw-r--r--src/widget/wtrackmenu.h3
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{};