From 71e0e6e411dc5448f563311023e5e72daac71b1f Mon Sep 17 00:00:00 2001 From: emeric Date: Wed, 1 May 2024 11:27:08 +0200 Subject: [PATCH] Factorized sort mode, now using a more compact dropdown menu --- approot/artists.xml | 49 +++--- approot/explore.xml | 15 ++ approot/releases.xml | 23 +-- approot/search.xml | 6 +- approot/tracks.xml | 23 +-- src/libs/database/impl/TrackArtistLink.cpp | 14 -- .../include/database/TrackArtistLink.hpp | 1 - src/lms/CMakeLists.txt | 2 + src/lms/ui/explore/ArtistListHelpers.cpp | 58 +------ src/lms/ui/explore/ArtistListHelpers.hpp | 1 - src/lms/ui/explore/ArtistsView.cpp | 43 ++--- src/lms/ui/explore/ArtistsView.hpp | 38 ++--- src/lms/ui/explore/Explore.cpp | 153 +++++++++--------- src/lms/ui/explore/Explore.hpp | 27 ++-- src/lms/ui/explore/ReleasesView.cpp | 26 +-- src/lms/ui/explore/ReleasesView.hpp | 41 +++-- src/lms/ui/explore/SearchView.cpp | 13 +- src/lms/ui/explore/SearchView.hpp | 2 - src/lms/ui/explore/SortModeSelector.cpp | 59 +++++++ src/lms/ui/explore/SortModeSelector.hpp | 40 +++++ .../explore/TrackArtistLinkTypeSelector.cpp | 64 ++++++++ .../explore/TrackArtistLinkTypeSelector.hpp | 42 +++++ src/lms/ui/explore/TracksView.cpp | 24 +-- src/lms/ui/explore/TracksView.hpp | 41 +++-- 24 files changed, 425 insertions(+), 380 deletions(-) create mode 100644 src/lms/ui/explore/SortModeSelector.cpp create mode 100644 src/lms/ui/explore/SortModeSelector.hpp create mode 100644 src/lms/ui/explore/TrackArtistLinkTypeSelector.cpp create mode 100644 src/lms/ui/explore/TrackArtistLinkTypeSelector.hpp diff --git a/approot/artists.xml b/approot/artists.xml index a0fd6409..abdc4730 100644 --- a/approot/artists.xml +++ b/approot/artists.xml @@ -3,32 +3,9 @@ -
- -
-
- ${link-type class="form-select"} -
-
+
+ ${link-type} + ${sort-mode}
${artists} @@ -42,4 +19,24 @@ ${loading-indicator} + + + + diff --git a/approot/explore.xml b/approot/explore.xml index 342621dc..f6ce0857 100644 --- a/approot/explore.xml +++ b/approot/explore.xml @@ -52,5 +52,20 @@
+ + + diff --git a/approot/releases.xml b/approot/releases.xml index c66f3577..347ea624 100644 --- a/approot/releases.xml +++ b/approot/releases.xml @@ -3,27 +3,7 @@ -
- +
${play-btn class="btn btn-primary"}
+ ${sort-mode}
${releases} diff --git a/approot/search.xml b/approot/search.xml index cb417139..25709a2d 100644 --- a/approot/search.xml +++ b/approot/search.xml @@ -20,10 +20,8 @@ -
-
- ${link-type class="form-select"} -
+
+ ${link-type}
${artists} diff --git a/approot/tracks.xml b/approot/tracks.xml index e18aa162..21a84f0c 100644 --- a/approot/tracks.xml +++ b/approot/tracks.xml @@ -4,27 +4,7 @@ -
- +
${play-btn class="btn btn-primary"}
+ ${sort-mode}
${tracks} diff --git a/src/libs/database/impl/TrackArtistLink.cpp b/src/libs/database/impl/TrackArtistLink.cpp index 81ebe025..06e2056e 100644 --- a/src/libs/database/impl/TrackArtistLink.cpp +++ b/src/libs/database/impl/TrackArtistLink.cpp @@ -105,20 +105,6 @@ namespace lms::db }); } - core::EnumSet TrackArtistLink::findUsedTypes(Session& session) - { - session.checkReadTransaction(); - - const auto query{ session.getDboSession()->query("SELECT DISTINCT type from track_artist_link") }; - - core::EnumSet res; - utils::forEachQueryResult(query, [&](TrackArtistLinkType linkType) - { - res.insert(linkType); - }); - return res; - } - core::EnumSet TrackArtistLink::findUsedTypes(Session& session, ArtistId artistId) { session.checkReadTransaction(); diff --git a/src/libs/database/include/database/TrackArtistLink.hpp b/src/libs/database/include/database/TrackArtistLink.hpp index 216fbf33..dafae759 100644 --- a/src/libs/database/include/database/TrackArtistLink.hpp +++ b/src/libs/database/include/database/TrackArtistLink.hpp @@ -66,7 +66,6 @@ namespace lms::db static void find(Session& session, const FindParameters& parameters, const std::function&); static pointer find(Session& session, TrackArtistLinkId linkId); static pointer create(Session& session, ObjectPtr track, ObjectPtr artist, TrackArtistLinkType type, std::string_view subType = {}); - static core::EnumSet findUsedTypes(Session& session); static core::EnumSet findUsedTypes(Session& session, ArtistId _artist); ObjectPtr getTrack() const { return _track; } diff --git a/src/lms/CMakeLists.txt b/src/lms/CMakeLists.txt index 2a877826..03f00b0e 100644 --- a/src/lms/CMakeLists.txt +++ b/src/lms/CMakeLists.txt @@ -43,6 +43,8 @@ add_executable(lms ui/explore/ReleaseView.cpp ui/explore/ReleaseTypes.cpp ui/explore/SearchView.cpp + ui/explore/SortModeSelector.cpp + ui/explore/TrackArtistLinkTypeSelector.cpp ui/explore/TrackCollector.cpp ui/explore/TrackListHelpers.cpp ui/explore/TrackListView.cpp diff --git a/src/lms/ui/explore/ArtistListHelpers.cpp b/src/lms/ui/explore/ArtistListHelpers.cpp index 4adcf775..cd501789 100644 --- a/src/lms/ui/explore/ArtistListHelpers.cpp +++ b/src/lms/ui/explore/ArtistListHelpers.cpp @@ -18,62 +18,18 @@ */ #include "ArtistListHelpers.hpp" -#include - #include "database/Artist.hpp" #include "database/Session.hpp" -#include "database/TrackArtistLink.hpp" -#include "core/EnumSet.hpp" #include "LmsApplication.hpp" #include "Utils.hpp" namespace lms::ui::ArtistListHelpers { - std::unique_ptr - createEntry(const db::ObjectPtr& artist) - { - auto res {std::make_unique(Wt::WString::tr("Lms.Explore.Artists.template.entry"))}; - res->bindWidget("name", utils::createArtistAnchor(artist)); - - return res; - } - - std::unique_ptr - createArtistLinkTypesModel() - { - using namespace db; - - std::unique_ptr linkTypesModel {std::make_unique()}; - - core::EnumSet usedLinkTypes; - { - auto transaction {LmsApp->getDbSession().createReadTransaction()}; - usedLinkTypes = TrackArtistLink::findUsedTypes(LmsApp->getDbSession()); - } - - auto addTypeIfUsed {[&](TrackArtistLinkType linkType, std::string_view stringKey) - { - if (!usedLinkTypes.contains(linkType)) - return; - - linkTypesModel->add(Wt::WString::trn(std::string {stringKey}, 2), linkType); - }}; - - // add default one first (none) - linkTypesModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-all"), std::nullopt); - - // TODO: sort by translated strings - addTypeIfUsed(TrackArtistLinkType::Artist, "Lms.Explore.Artists.linktype-artist"); - addTypeIfUsed(TrackArtistLinkType::ReleaseArtist, "Lms.Explore.Artists.linktype-releaseartist"); - addTypeIfUsed(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer"); - addTypeIfUsed(TrackArtistLinkType::Conductor, "Lms.Explore.Artists.linktype-conductor"); - addTypeIfUsed(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist"); - addTypeIfUsed(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer"); - addTypeIfUsed(TrackArtistLinkType::Performer, "Lms.Explore.Artists.linktype-performer"); - addTypeIfUsed(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer"); - addTypeIfUsed(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer"); - - return linkTypesModel; - } -} + std::unique_ptr createEntry(const db::ObjectPtr& artist) + { + auto res{ std::make_unique(Wt::WString::tr("Lms.Explore.Artists.template.entry")) }; + res->bindWidget("name", utils::createArtistAnchor(artist)); + return res; + } +} \ No newline at end of file diff --git a/src/lms/ui/explore/ArtistListHelpers.hpp b/src/lms/ui/explore/ArtistListHelpers.hpp index 37c168bf..ca9164ba 100644 --- a/src/lms/ui/explore/ArtistListHelpers.hpp +++ b/src/lms/ui/explore/ArtistListHelpers.hpp @@ -39,7 +39,6 @@ namespace lms::ui namespace ArtistListHelpers { std::unique_ptr createEntry(const db::ObjectPtr& artist); - std::unique_ptr createArtistLinkTypesModel(); } } diff --git a/src/lms/ui/explore/ArtistsView.cpp b/src/lms/ui/explore/ArtistsView.cpp index 589b9966..9c0197b1 100644 --- a/src/lms/ui/explore/ArtistsView.cpp +++ b/src/lms/ui/explore/ArtistsView.cpp @@ -21,15 +21,17 @@ #include +#include "core/ILogger.hpp" #include "database/Artist.hpp" #include "database/Session.hpp" #include "database/TrackArtistLink.hpp" -#include "core/ILogger.hpp" #include "common/InfiniteScrollingContainer.hpp" #include "ArtistListHelpers.hpp" #include "Filters.hpp" #include "LmsApplication.hpp" +#include "SortModeSelector.hpp" +#include "TrackArtistLinkTypeSelector.hpp" namespace lms::ui { @@ -37,49 +39,22 @@ namespace lms::ui Artists::Artists(Filters& filters) : Wt::WTemplate{ Wt::WString::tr("Lms.Explore.Artists.template") } - , _artistCollector{ filters, _defaultMode, _maxCount } + , _artistCollector{ filters, _defaultSortMode, _maxCount } { addFunction("tr", &Wt::WTemplate::Functions::tr); - auto bindMenuItem{ [this](const std::string& var, const Wt::WString& title, ArtistCollector::Mode mode) - { - auto* menuItem {bindNew(var, title)}; - menuItem->clicked().connect([=, this] + SortModeSelector* sortModeSelector{ bindNew("sort-mode", _defaultSortMode) }; + sortModeSelector->sortModeChanged.connect([this](ArtistCollector::Mode sortMode) { - refreshView(mode); - _currentActiveItem->removeStyleClass("active"); - menuItem->addStyleClass("active"); - _currentActiveItem = menuItem; + refreshView(sortMode); }); - if (mode == _defaultMode) + TrackArtistLinkTypeSelector* linkTypeSelector{ bindNew("link-type", _defaultLinkType) }; + linkTypeSelector->linkTypeChanged.connect([this](std::optional linkType) { - _currentActiveItem = menuItem; - _currentActiveItem->addStyleClass("active"); - } - } }; - - bindMenuItem("random", Wt::WString::tr("Lms.Explore.random"), ArtistCollector::Mode::Random); - bindMenuItem("starred", Wt::WString::tr("Lms.Explore.starred"), ArtistCollector::Mode::Starred); - bindMenuItem("recently-played", Wt::WString::tr("Lms.Explore.recently-played"), ArtistCollector::Mode::RecentlyPlayed); - bindMenuItem("most-played", Wt::WString::tr("Lms.Explore.most-played"), ArtistCollector::Mode::MostPlayed); - bindMenuItem("recently-added", Wt::WString::tr("Lms.Explore.recently-added"), ArtistCollector::Mode::RecentlyAdded); - bindMenuItem("all", Wt::WString::tr("Lms.Explore.all"), ArtistCollector::Mode::All); - - _linkType = bindNew("link-type"); - _linkType->setModel(ArtistListHelpers::createArtistLinkTypesModel()); - _linkType->changed().connect([this] - { - const std::optional linkType{ static_cast(_linkType->model().get())->getValue(_linkType->currentIndex()) }; refreshView(linkType); }); - LmsApp->getScannerEvents().scanComplete.connect(this, [this](const scanner::ScanStats& stats) - { - if (stats.nbChanges()) - _linkType->setModel(ArtistListHelpers::createArtistLinkTypesModel()); - }); - _container = bindNew("artists", Wt::WString::tr("Lms.Explore.Artists.template.container")); _container->onRequestElements.connect([this] { diff --git a/src/lms/ui/explore/ArtistsView.hpp b/src/lms/ui/explore/ArtistsView.hpp index f3230ff2..2d4c0843 100644 --- a/src/lms/ui/explore/ArtistsView.hpp +++ b/src/lms/ui/explore/ArtistsView.hpp @@ -30,28 +30,28 @@ namespace lms::ui { - class Filters; - class InfiniteScrollingContainer; + class Filters; + class InfiniteScrollingContainer; - class Artists : public Wt::WTemplate - { - public: - Artists(Filters& filters); + class Artists : public Wt::WTemplate + { + public: + Artists(Filters& filters); - private: - void refreshView(); - void refreshView(ArtistCollector::Mode mode); - void refreshView(std::optional linkType); - void addSome(); + private: + void refreshView(); + void refreshView(ArtistCollector::Mode mode); + void refreshView(std::optional linkType); + void addSome(); - static constexpr std::size_t _batchSize {30}; - static constexpr std::size_t _maxCount {8000}; + static constexpr std::size_t _batchSize{ 30 }; + static constexpr std::size_t _maxCount{ 8000 }; - Wt::WWidget* _currentActiveItem {}; - InfiniteScrollingContainer* _container {}; - ArtistCollector _artistCollector; - Wt::WComboBox* _linkType {}; - static constexpr ArtistCollector::Mode _defaultMode {ArtistCollector::Mode::Random}; - }; + Wt::WWidget* _currentLinkTypeActiveItem{}; + InfiniteScrollingContainer* _container{}; + ArtistCollector _artistCollector; + static constexpr ArtistCollector::Mode _defaultSortMode{ ArtistCollector::Mode::Random }; + static constexpr std::optional _defaultLinkType; + }; } // namespace lms::ui diff --git a/src/lms/ui/explore/Explore.cpp b/src/lms/ui/explore/Explore.cpp index 682a9d2c..bae923fc 100644 --- a/src/lms/ui/explore/Explore.cpp +++ b/src/lms/ui/explore/Explore.cpp @@ -32,97 +32,94 @@ #include "TrackListsView.hpp" #include "TracksView.hpp" -namespace lms::ui { +namespace lms::ui +{ + namespace + { + void handleContentsPathChange(Wt::WStackedWidget* stack) + { + enum Idx + { + IdxArtists = 0, + IdxArtist, + IdxTrackLists, + IdxTrackList, + IdxReleases, + IdxRelease, + IdxSearch, + IdxTracks, + }; - namespace { + static const std::map indexes = + { + { "/artists", IdxArtists }, + { "/artist", IdxArtist }, + { "/tracklists", IdxTrackLists }, + { "/tracklist", IdxTrackList }, + { "/releases", IdxReleases }, + { "/release", IdxRelease }, + { "/search", IdxSearch }, + { "/tracks", IdxTracks }, + }; - void - handleContentsPathChange(Wt::WStackedWidget* stack) - { - enum Idx - { - IdxArtists = 0, - IdxArtist, - IdxTrackLists, - IdxTrackList, - IdxReleases, - IdxRelease, - IdxSearch, - IdxTracks, - }; + for (const auto& index : indexes) + { + if (wApp->internalPathMatches(index.first)) + { + stack->setCurrentIndex(index.second); + return; + } + } + } - static const std::map indexes = - { - { "/artists", IdxArtists }, - { "/artist", IdxArtist }, - { "/tracklists", IdxTrackLists }, - { "/tracklist", IdxTrackList }, - { "/releases", IdxReleases }, - { "/release", IdxRelease }, - { "/search", IdxSearch }, - { "/tracks", IdxTracks }, - }; + } // namespace - for (const auto& index : indexes) - { - if (wApp->internalPathMatches(index.first)) - { - stack->setCurrentIndex(index.second); - return; - } - } - } + Explore::Explore(Filters& filters, PlayQueue& playQueue) + : Wt::WTemplate{ Wt::WString::tr("Lms.Explore.template") } + , _playQueueController{ filters, playQueue } + { + addFunction("tr", &Functions::tr); - } // namespace + // Contents + Wt::WStackedWidget* contentsStack{ bindNew("contents") }; + contentsStack->setOverflow(Wt::Overflow::Visible); // wt makes it hidden by default - Explore::Explore(Filters& filters, PlayQueue& playQueue) - : Wt::WTemplate {Wt::WString::tr("Lms.Explore.template")} - , _playQueueController {filters, playQueue} - { - addFunction("tr", &Functions::tr); + // same order as enum Idx + auto artists = std::make_unique(filters); + contentsStack->addWidget(std::move(artists)); - // Contents - Wt::WStackedWidget* contentsStack {bindNew("contents")}; - contentsStack->setOverflow(Wt::Overflow::Visible); // wt makes it hidden by default + auto artist = std::make_unique(filters, _playQueueController); + contentsStack->addWidget(std::move(artist)); - // same order as enum Idx - auto artists = std::make_unique(filters); - contentsStack->addWidget(std::move(artists)); + auto trackLists{ std::make_unique(filters) }; + auto trackList{ std::make_unique(filters, _playQueueController) }; + trackList->trackListDeleted.connect(trackLists.get(), &TrackLists::onTrackListDeleted); + contentsStack->addWidget(std::move(trackLists)); + contentsStack->addWidget(std::move(trackList)); - auto artist = std::make_unique(filters, _playQueueController); - contentsStack->addWidget(std::move(artist)); + auto releases = std::make_unique(filters, _playQueueController); + contentsStack->addWidget(std::move(releases)); - auto trackLists {std::make_unique(filters)}; - auto trackList {std::make_unique(filters, _playQueueController)}; - trackList->trackListDeleted.connect(trackLists.get(), &TrackLists::onTrackListDeleted); - contentsStack->addWidget(std::move(trackLists)); - contentsStack->addWidget(std::move(trackList)); + auto release = std::make_unique(filters, _playQueueController); + contentsStack->addWidget(std::move(release)); - auto releases = std::make_unique(filters, _playQueueController); - contentsStack->addWidget(std::move(releases)); + auto search = std::make_unique(filters, _playQueueController); + _search = search.get(); + contentsStack->addWidget(std::move(search)); - auto release = std::make_unique(filters, _playQueueController); - contentsStack->addWidget(std::move(release)); + auto tracks = std::make_unique(filters, _playQueueController); + contentsStack->addWidget(std::move(tracks)); - auto search = std::make_unique(filters, _playQueueController); - _search = search.get(); - contentsStack->addWidget(std::move(search)); + wApp->internalPathChanged().connect(this, [contentsStack] + { + handleContentsPathChange(contentsStack); + }); - auto tracks = std::make_unique(filters, _playQueueController); - contentsStack->addWidget(std::move(tracks)); - - wApp->internalPathChanged().connect(this, [=] - { - handleContentsPathChange(contentsStack); - }); - - handleContentsPathChange(contentsStack); - } - - void - Explore::search(const Wt::WString& searchText) - { - _search->refreshView(searchText); - } + handleContentsPathChange(contentsStack); + } + void Explore::search(const Wt::WString& searchText) + { + _search->refreshView(searchText); + } } // namespace lms::ui diff --git a/src/lms/ui/explore/Explore.hpp b/src/lms/ui/explore/Explore.hpp index 1f6ef350..ced70b41 100644 --- a/src/lms/ui/explore/Explore.hpp +++ b/src/lms/ui/explore/Explore.hpp @@ -20,25 +20,26 @@ #pragma once #include + #include "PlayQueueController.hpp" namespace lms::ui { - class Filters; - class SearchView; - class PlayQueue; + class Filters; + class SearchView; + class PlayQueue; - class Explore : public Wt::WTemplate - { - public: - Explore(Filters& filters, PlayQueue& playQueue); + class Explore : public Wt::WTemplate + { + public: + Explore(Filters& filters, PlayQueue& playQueue); - void search(const Wt::WString& searchText); - PlayQueueController& getPlayQueueController() { return _playQueueController; } + void search(const Wt::WString& searchText); + PlayQueueController& getPlayQueueController() { return _playQueueController; } - private: - PlayQueueController _playQueueController; - SearchView* _search {}; - }; + private: + PlayQueueController _playQueueController; + SearchView* _search{}; + }; } // namespace lms::ui diff --git a/src/lms/ui/explore/ReleasesView.cpp b/src/lms/ui/explore/ReleasesView.cpp index 82055427..592e7588 100644 --- a/src/lms/ui/explore/ReleasesView.cpp +++ b/src/lms/ui/explore/ReleasesView.cpp @@ -30,6 +30,7 @@ #include "explore/PlayQueueController.hpp" #include "explore/ReleaseHelpers.hpp" #include "LmsApplication.hpp" +#include "SortModeSelector.hpp" namespace lms::ui { @@ -43,31 +44,12 @@ namespace lms::ui addFunction("tr", &Wt::WTemplate::Functions::tr); addFunction("id", &Wt::WTemplate::Functions::id); - auto bindMenuItem{ [this](const std::string& var, const Wt::WString& title, ReleaseCollector::Mode mode) - { - auto* menuItem {bindNew(var, title)}; - menuItem->clicked().connect([this, mode, menuItem] + SortModeSelector* sortMode{ bindNew("sort-mode", _defaultMode) }; + sortMode->sortModeChanged.connect([this](ReleaseCollector::Mode sortMode) { - refreshView(mode); - _currentActiveItem->removeStyleClass("active"); - menuItem->addStyleClass("active"); - _currentActiveItem = menuItem; + refreshView(sortMode); }); - if (mode == _defaultMode) - { - _currentActiveItem = menuItem; - _currentActiveItem->addStyleClass("active"); - } - } }; - - bindMenuItem("random", Wt::WString::tr("Lms.Explore.random"), ReleaseCollector::Mode::Random); - bindMenuItem("starred", Wt::WString::tr("Lms.Explore.starred"), ReleaseCollector::Mode::Starred); - bindMenuItem("recently-played", Wt::WString::tr("Lms.Explore.recently-played"), ReleaseCollector::Mode::RecentlyPlayed); - bindMenuItem("most-played", Wt::WString::tr("Lms.Explore.most-played"), ReleaseCollector::Mode::MostPlayed); - bindMenuItem("recently-added", Wt::WString::tr("Lms.Explore.recently-added"), ReleaseCollector::Mode::RecentlyAdded); - bindMenuItem("all", Wt::WString::tr("Lms.Explore.all"), ReleaseCollector::Mode::All); - Wt::WPushButton* playBtn{ bindNew("play-btn", Wt::WString::tr("Lms.Explore.play"), Wt::TextFormat::XHTML) }; playBtn->clicked().connect([this] { diff --git a/src/lms/ui/explore/ReleasesView.hpp b/src/lms/ui/explore/ReleasesView.hpp index d10dac59..555db842 100644 --- a/src/lms/ui/explore/ReleasesView.hpp +++ b/src/lms/ui/explore/ReleasesView.hpp @@ -26,31 +26,30 @@ namespace lms::ui { - class Filters; - class InfiniteScrollingContainer; - class PlayQueueController; + class Filters; + class InfiniteScrollingContainer; + class PlayQueueController; - class Releases : public Template - { - public: - Releases(Filters& filters, PlayQueueController& playQueueController); + class Releases : public Template + { + public: + Releases(Filters& filters, PlayQueueController& playQueueController); - private: - void refreshView(); - void refreshView(ReleaseCollector::Mode mode); + private: + void refreshView(); + void refreshView(ReleaseCollector::Mode mode); - void addSome(); - std::vector getAllReleases(); + void addSome(); + std::vector getAllReleases(); - static constexpr std::size_t _maxItemsPerLine {6}; - static constexpr std::size_t _batchSize {_maxItemsPerLine}; - static constexpr std::size_t _maxCount {_maxItemsPerLine * 500}; + static constexpr std::size_t _maxItemsPerLine{ 6 }; + static constexpr std::size_t _batchSize{ _maxItemsPerLine }; + static constexpr std::size_t _maxCount{ _maxItemsPerLine * 500 }; - PlayQueueController& _playQueueController; - Wt::WWidget* _currentActiveItem {}; - InfiniteScrollingContainer* _container {}; - ReleaseCollector _releaseCollector; - static constexpr ReleaseCollector::Mode _defaultMode {ReleaseCollector::Mode::Random}; - }; + PlayQueueController& _playQueueController; + InfiniteScrollingContainer* _container{}; + ReleaseCollector _releaseCollector; + static constexpr ReleaseCollector::Mode _defaultMode{ ReleaseCollector::Mode::Random }; + }; } // namespace lms::ui diff --git a/src/lms/ui/explore/SearchView.cpp b/src/lms/ui/explore/SearchView.cpp index aed56f86..508c4322 100644 --- a/src/lms/ui/explore/SearchView.cpp +++ b/src/lms/ui/explore/SearchView.cpp @@ -31,6 +31,7 @@ #include "Filters.hpp" #include "LmsApplication.hpp" #include "ReleaseHelpers.hpp" +#include "TrackArtistLinkTypeSelector.hpp" #include "TrackListHelpers.hpp" namespace lms::ui @@ -58,11 +59,9 @@ namespace lms::ui { Wt::WTemplate* artistResults{ _stack->addNew(Wt::WString::tr("Lms.Explore.Search.template.artists")) }; - _artistLinkType = artistResults->bindNew("link-type"); - _artistLinkType->setModel(ArtistListHelpers::createArtistLinkTypesModel()); - _artistLinkType->changed().connect([this] + TrackArtistLinkTypeSelector* linkTypeSelector{ artistResults->bindNew("link-type", std::nullopt)}; + linkTypeSelector->linkTypeChanged.connect([this](std::optional linkType) { - const std::optional linkType{ static_cast(_artistLinkType->model().get())->getValue(_artistLinkType->currentIndex()) }; refreshView(linkType); }); @@ -101,12 +100,6 @@ namespace lms::ui { refreshView(); }); - - LmsApp->getScannerEvents().scanComplete.connect(this, [this](const scanner::ScanStats& stats) - { - if (stats.nbChanges()) - _artistLinkType->setModel(ArtistListHelpers::createArtistLinkTypesModel()); - }); } std::size_t SearchView::getBatchSize(Mode mode) const diff --git a/src/lms/ui/explore/SearchView.hpp b/src/lms/ui/explore/SearchView.hpp index 89d2d0fd..5a44e3b9 100644 --- a/src/lms/ui/explore/SearchView.hpp +++ b/src/lms/ui/explore/SearchView.hpp @@ -85,8 +85,6 @@ namespace lms::ui InfiniteScrollingContainer* _artists{}; InfiniteScrollingContainer* _releases{}; InfiniteScrollingContainer* _tracks{}; - - Wt::WComboBox* _artistLinkType{}; }; } // namespace lms::ui diff --git a/src/lms/ui/explore/SortModeSelector.cpp b/src/lms/ui/explore/SortModeSelector.cpp new file mode 100644 index 00000000..545fc28a --- /dev/null +++ b/src/lms/ui/explore/SortModeSelector.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "SortModeSelector.hpp" + +#include + +namespace lms::ui +{ + SortModeSelector::SortModeSelector(DatabaseCollectorBase::Mode defaultMode) + : Wt::WTemplate{ Wt::WString::tr("Lms.Explore.template.sort-mode-selector") } + { + auto* sortMode{ bindNew("sort-mode") }; + + auto bindMenuItem{ [this, sortMode, defaultMode](const std::string& var, const Wt::WString& title, DatabaseCollectorBase::Mode mode) + { + auto* menuItem {bindNew(var, title)}; + menuItem->clicked().connect([this, mode, menuItem, sortMode, title] + { + _currentActiveItem->removeStyleClass("active"); + menuItem->addStyleClass("active"); + _currentActiveItem = menuItem; + sortMode->setText(title); + + sortModeChanged.emit(mode); + }); + + if (mode == defaultMode) + { + _currentActiveItem = menuItem; + _currentActiveItem->addStyleClass("active"); + sortMode->setText(title); + } + } }; + + bindMenuItem("random", Wt::WString::tr("Lms.Explore.random"), DatabaseCollectorBase::Mode::Random); + bindMenuItem("starred", Wt::WString::tr("Lms.Explore.starred"), DatabaseCollectorBase::Mode::Starred); + bindMenuItem("recently-played", Wt::WString::tr("Lms.Explore.recently-played"), DatabaseCollectorBase::Mode::RecentlyPlayed); + bindMenuItem("most-played", Wt::WString::tr("Lms.Explore.most-played"), DatabaseCollectorBase::Mode::MostPlayed); + bindMenuItem("recently-added", Wt::WString::tr("Lms.Explore.recently-added"), DatabaseCollectorBase::Mode::RecentlyAdded); + bindMenuItem("all", Wt::WString::tr("Lms.Explore.all"), DatabaseCollectorBase::Mode::All); + } +} // namespace lms::ui diff --git a/src/lms/ui/explore/SortModeSelector.hpp b/src/lms/ui/explore/SortModeSelector.hpp new file mode 100644 index 00000000..b32af35f --- /dev/null +++ b/src/lms/ui/explore/SortModeSelector.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include +#include + +#include "DatabaseCollectorBase.hpp" + +namespace lms::ui +{ + class SortModeSelector : public Wt::WTemplate + { + public: + SortModeSelector(DatabaseCollectorBase::Mode defaultMode); + + Wt::Signal sortModeChanged; + + private: + Wt::WWidget* _currentActiveItem{}; + }; +} // namespace lms::ui + diff --git a/src/lms/ui/explore/TrackArtistLinkTypeSelector.cpp b/src/lms/ui/explore/TrackArtistLinkTypeSelector.cpp new file mode 100644 index 00000000..2202fd41 --- /dev/null +++ b/src/lms/ui/explore/TrackArtistLinkTypeSelector.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "TrackArtistLinkTypeSelector.hpp" + +#include + +namespace lms::ui +{ + TrackArtistLinkTypeSelector::TrackArtistLinkTypeSelector(std::optional defaultLinkType) + : Wt::WTemplate{ Wt::WString::tr("Lms.Explore.Artists.template.track-artist-link-type-selector") } + { + Wt::WText* linkTypeTxt{ bindNew("link-type") }; + + auto bindMenuItem{ [this, linkTypeTxt, defaultLinkType](const std::string& var, const Wt::WString& title, std::optional linkType) + { + auto* menuItem{ bindNew(var, title) }; + menuItem->clicked().connect([=] + { + _currentActiveItem->removeStyleClass("active"); + menuItem->addStyleClass("active"); + _currentActiveItem = menuItem; + linkTypeTxt->setText(title); + + linkTypeChanged.emit(linkType); + }); + + if (linkType == defaultLinkType) + { + _currentActiveItem = menuItem; + _currentActiveItem->addStyleClass("active"); + linkTypeTxt->setText(title); + } + } }; + + bindMenuItem("link-type-all", Wt::WString::tr("Lms.Explore.Artists.linktype-all"), std::nullopt); + bindMenuItem("link-type-artist", Wt::WString::trn("Lms.Explore.Artists.linktype-artist", 2), db::TrackArtistLinkType::Artist); + bindMenuItem("link-type-releaseartist", Wt::WString::trn("Lms.Explore.Artists.linktype-releaseartist", 2), db::TrackArtistLinkType::ReleaseArtist); + bindMenuItem("link-type-composer", Wt::WString::trn("Lms.Explore.Artists.linktype-composer", 2), db::TrackArtistLinkType::Composer); + bindMenuItem("link-type-conductor", Wt::WString::trn("Lms.Explore.Artists.linktype-conductor", 2), db::TrackArtistLinkType::Conductor); + bindMenuItem("link-type-lyricist", Wt::WString::trn("Lms.Explore.Artists.linktype-lyricist", 2), db::TrackArtistLinkType::Lyricist); + bindMenuItem("link-type-mixer", Wt::WString::trn("Lms.Explore.Artists.linktype-mixer", 2), db::TrackArtistLinkType::Mixer); + bindMenuItem("link-type-performer", Wt::WString::trn("Lms.Explore.Artists.linktype-performer", 2), db::TrackArtistLinkType::Performer); + bindMenuItem("link-type-producer", Wt::WString::trn("Lms.Explore.Artists.linktype-producer", 2), db::TrackArtistLinkType::Producer); + bindMenuItem("link-type-remixer", Wt::WString::trn("Lms.Explore.Artists.linktype-remixer", 2), db::TrackArtistLinkType::Remixer); + } +} // namespace lms::ui + diff --git a/src/lms/ui/explore/TrackArtistLinkTypeSelector.hpp b/src/lms/ui/explore/TrackArtistLinkTypeSelector.hpp new file mode 100644 index 00000000..fbea71c0 --- /dev/null +++ b/src/lms/ui/explore/TrackArtistLinkTypeSelector.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include + +#include +#include + +#include "database/Types.hpp" + +namespace lms::ui +{ + class TrackArtistLinkTypeSelector : public Wt::WTemplate + { + public: + TrackArtistLinkTypeSelector(std::optional defaultLinkType); + + Wt::Signal> linkTypeChanged; + + private: + Wt::WWidget* _currentActiveItem{}; + }; +} // namespace lms::ui + diff --git a/src/lms/ui/explore/TracksView.cpp b/src/lms/ui/explore/TracksView.cpp index 9274951a..018f5d42 100644 --- a/src/lms/ui/explore/TracksView.cpp +++ b/src/lms/ui/explore/TracksView.cpp @@ -30,6 +30,7 @@ #include "explore/PlayQueueController.hpp" #include "explore/TrackListHelpers.hpp" #include "LmsApplication.hpp" +#include "SortModeSelector.hpp" namespace lms::ui { @@ -44,31 +45,12 @@ namespace lms::ui addFunction("tr", &Wt::WTemplate::Functions::tr); addFunction("id", &Wt::WTemplate::Functions::id); - auto bindMenuItem{ [this](const std::string& var, const Wt::WString& title, TrackCollector::Mode mode) - { - auto* menuItem {bindNew(var, title)}; - menuItem->clicked().connect([this, mode, menuItem] + SortModeSelector* sortMode{ bindNew("sort-mode", _defaultMode) }; + sortMode->sortModeChanged.connect([this](TrackCollector::Mode mode) { refreshView(mode); - _currentActiveItem->removeStyleClass("active"); - menuItem->addStyleClass("active"); - _currentActiveItem = menuItem; }); - if (mode == _defaultMode) - { - _currentActiveItem = menuItem; - _currentActiveItem->addStyleClass("active"); - } - } }; - - bindMenuItem("random", Wt::WString::tr("Lms.Explore.random"), TrackCollector::Mode::Random); - bindMenuItem("starred", Wt::WString::tr("Lms.Explore.starred"), TrackCollector::Mode::Starred); - bindMenuItem("recently-played", Wt::WString::tr("Lms.Explore.recently-played"), TrackCollector::Mode::RecentlyPlayed); - bindMenuItem("most-played", Wt::WString::tr("Lms.Explore.most-played"), TrackCollector::Mode::MostPlayed); - bindMenuItem("recently-added", Wt::WString::tr("Lms.Explore.recently-added"), TrackCollector::Mode::RecentlyAdded); - bindMenuItem("all", Wt::WString::tr("Lms.Explore.all"), TrackCollector::Mode::All); - bindNew("play-btn", Wt::WString::tr("Lms.Explore.play"), Wt::TextFormat::XHTML) ->clicked().connect([this] { diff --git a/src/lms/ui/explore/TracksView.hpp b/src/lms/ui/explore/TracksView.hpp index 26ef324e..748467b0 100644 --- a/src/lms/ui/explore/TracksView.hpp +++ b/src/lms/ui/explore/TracksView.hpp @@ -26,31 +26,30 @@ namespace lms::ui { - class Filters; - class InfiniteScrollingContainer; - class PlayQueueController; + class Filters; + class InfiniteScrollingContainer; + class PlayQueueController; - class Tracks : public Template - { - public: - Tracks(Filters& filters, PlayQueueController& playQueueController); + class Tracks : public Template + { + public: + Tracks(Filters& filters, PlayQueueController& playQueueController); - private: - void refreshView(); - void refreshView(TrackCollector::Mode mode); - void addSome(); + private: + void refreshView(); + void refreshView(TrackCollector::Mode mode); + void addSome(); - std::vector getAllTracks(); + std::vector getAllTracks(); - static constexpr TrackCollector::Mode _defaultMode {TrackCollector::Mode::Random}; - static constexpr std::size_t _batchSize {6}; - static constexpr std::size_t _maxCount {8000}; + static constexpr TrackCollector::Mode _defaultMode{ TrackCollector::Mode::Random }; + static constexpr std::size_t _batchSize{ 6 }; + static constexpr std::size_t _maxCount{ 8000 }; - Filters& _filters; - PlayQueueController& _playQueueController; - Wt::WWidget* _currentActiveItem {}; - InfiniteScrollingContainer* _container {}; - TrackCollector _trackCollector; - }; + Filters& _filters; + PlayQueueController& _playQueueController; + InfiniteScrollingContainer* _container{}; + TrackCollector _trackCollector; + }; } // namespace lms::ui