diff --git a/approot/messages.xml b/approot/messages.xml
index 9673b06a..04bc9e86 100644
--- a/approot/messages.xml
+++ b/approot/messages.xml
@@ -192,6 +192,7 @@
Recently modified
Recently played
Release information
+Release type
Albums
Search
Star
diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml
index 54920f49..6b082834 100644
--- a/approot/messages_fr.xml
+++ b/approot/messages_fr.xml
@@ -192,6 +192,7 @@
Modifiés récemment
Joués récemment
Informations sur l'album
+Type de publication
Albums
Rechercher
Ajouter aux favoris
diff --git a/approot/messages_it.xml b/approot/messages_it.xml
index c7ee2ebd..63fdce7e 100644
--- a/approot/messages_it.xml
+++ b/approot/messages_it.xml
@@ -192,6 +192,7 @@
Modificati di recente
Riprodotti di recente
Informazioni sull'album
+Tipo di pubblicazione
Album
Ricerca
Aggiungi ai preferiti
diff --git a/approot/messages_pl.xml b/approot/messages_pl.xml
index 6bb2b14d..305e4a30 100644
--- a/approot/messages_pl.xml
+++ b/approot/messages_pl.xml
@@ -209,6 +209,7 @@
Ostatnio zmienione
Ostatnio odtwarzane
Informacje o wydaniu
+Typ wydania
Albumy
Szukaj
Wyróżnij
diff --git a/approot/messages_zh.xml b/approot/messages_zh.xml
index 8f0640fc..5193f55f 100644
--- a/approot/messages_zh.xml
+++ b/approot/messages_zh.xml
@@ -192,6 +192,7 @@
最近更改
最近播放
+
专辑
搜索
收藏
diff --git a/src/libs/database/impl/Artist.cpp b/src/libs/database/impl/Artist.cpp
index 7bec17cf..7a61591a 100644
--- a/src/libs/database/impl/Artist.cpp
+++ b/src/libs/database/impl/Artist.cpp
@@ -51,7 +51,8 @@ namespace lms::db
|| params.release.isValid()
|| params.filters.clusters.size() == 1
|| params.filters.mediaLibrary.isValid()
- || params.filters.label.isValid())
+ || params.filters.label.isValid()
+ || params.filters.releaseType.isValid())
{
query.join("track_artist_link t_a_l ON t_a_l.artist_id = a.id");
}
@@ -61,7 +62,8 @@ namespace lms::db
|| params.writtenAfter.isValid()
|| params.release.isValid()
|| params.filters.mediaLibrary.isValid()
- || params.filters.label.isValid())
+ || params.filters.label.isValid()
+ || params.filters.releaseType.isValid())
{
query.join("track t ON t.id = t_a_l.track_id");
@@ -79,6 +81,12 @@ namespace lms::db
query.join("release_label r_l ON r_l.release_id = t.release_id");
query.where("r_l.label_id = ?").bind(params.filters.label);
}
+
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
}
if (params.linkType)
diff --git a/src/libs/database/impl/Listen.cpp b/src/libs/database/impl/Listen.cpp
index 6704496f..be05082a 100644
--- a/src/libs/database/impl/Listen.cpp
+++ b/src/libs/database/impl/Listen.cpp
@@ -42,18 +42,26 @@ namespace lms::db
assert(!params.artist.isValid()); // poor check
- if (params.filters.mediaLibrary.isValid() || params.filters.label.isValid())
+ if (params.filters.mediaLibrary.isValid()
+ || params.filters.label.isValid()
+ || params.filters.releaseType.isValid())
{
query.join("track t ON t.id = t_a_l.track_id");
- }
- if (params.filters.mediaLibrary.isValid())
- query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
+ if (params.filters.mediaLibrary.isValid())
+ query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
- if (params.filters.label.isValid())
- {
- query.join("release_label r_l ON t.release_id = r_l.release_id");
- query.where("r_l.label_id = ?").bind(params.filters.label);
+ if (params.filters.label.isValid())
+ {
+ query.join("release_label r_l ON r_l.release_id = t.release_id");
+ query.where("r_l.label_id = ?").bind(params.filters.label);
+ }
+
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
}
if (params.linkType)
@@ -127,6 +135,12 @@ namespace lms::db
query.where("r_l.label_id = ?").bind(params.filters.label);
}
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = r.id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
+
if (!params.filters.clusters.empty())
{
std::ostringstream oss;
@@ -180,6 +194,12 @@ namespace lms::db
query.where("r_l.label_id = ?").bind(params.filters.label);
}
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
+
if (!params.filters.clusters.empty())
{
std::ostringstream oss;
diff --git a/src/libs/database/impl/Release.cpp b/src/libs/database/impl/Release.cpp
index 37648cf5..add8377a 100644
--- a/src/libs/database/impl/Release.cpp
+++ b/src/libs/database/impl/Release.cpp
@@ -83,6 +83,12 @@ namespace lms::db
query.where("r_l.label_id = ?").bind(params.filters.label);
}
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = r.id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
+
if (params.directory.isValid())
query.where("t.directory_id = ?").bind(params.directory);
@@ -401,6 +407,24 @@ namespace lms::db
return utils::fetchQuerySingleResult(session.getDboSession()->query>("SELECT r_t from release_type r_t").where("r_t.name = ?").bind(name));
}
+ void ReleaseType::find(Session& session, ReleaseTypeSortMethod sortMethod, std::function func)
+ {
+ session.checkReadTransaction();
+
+ auto query{ session.getDboSession()->find() };
+ switch (sortMethod)
+ {
+ case ReleaseTypeSortMethod::None:
+ break;
+ case ReleaseTypeSortMethod::Name:
+ query.orderBy("name COLLATE NOCASE");
+ }
+
+ utils::forEachQueryResult(query, [&](const ReleaseType::pointer& releaseType) {
+ func(releaseType);
+ });
+ }
+
RangeResults ReleaseType::findOrphanIds(Session& session, std::optional range)
{
session.checkReadTransaction();
diff --git a/src/libs/database/impl/Session.cpp b/src/libs/database/impl/Session.cpp
index 39d3dd0a..0340736b 100644
--- a/src/libs/database/impl/Session.cpp
+++ b/src/libs/database/impl/Session.cpp
@@ -238,7 +238,9 @@ namespace lms::db
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_mbid_idx ON release(mbid)");
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_name_idx ON release(name)");
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_name_nocase_idx ON release(name COLLATE NOCASE)");
- utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name)");
+
+ utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_id_idx ON release_type(id)");
+ utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name COLLATE NOCASE)");
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_id_idx ON track(id)");
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_absolute_path_idx ON track(absolute_file_path)");
diff --git a/src/libs/database/impl/Track.cpp b/src/libs/database/impl/Track.cpp
index 251dbef9..fae4863a 100644
--- a/src/libs/database/impl/Track.cpp
+++ b/src/libs/database/impl/Track.cpp
@@ -168,6 +168,12 @@ namespace lms::db
query.where("r_l.label_id = ?").bind(params.filters.label);
}
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
+
if (params.directory.isValid())
query.where("t.directory_id = ?").bind(params.directory);
diff --git a/src/libs/database/impl/TrackList.cpp b/src/libs/database/impl/TrackList.cpp
index e76bc7bb..9892d93c 100644
--- a/src/libs/database/impl/TrackList.cpp
+++ b/src/libs/database/impl/TrackList.cpp
@@ -54,7 +54,8 @@ namespace lms::db
query.where("t_l.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeLikeKeyword(keyword) + "%");
if (params.filters.mediaLibrary.isValid()
- || params.filters.label.isValid())
+ || params.filters.label.isValid()
+ || params.filters.releaseType.isValid())
{
query.join("track t ON t.id = t_l_e.track_id");
@@ -66,6 +67,12 @@ namespace lms::db
query.join("release_label r_l ON r_l.release_id = t.release_id");
query.where("r_l.label_id = ?").bind(params.filters.label);
}
+
+ if (params.filters.releaseType.isValid())
+ {
+ query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
+ query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
+ }
}
if (params.user.isValid())
diff --git a/src/libs/database/include/database/Filters.hpp b/src/libs/database/include/database/Filters.hpp
index ba4301af..84108568 100644
--- a/src/libs/database/include/database/Filters.hpp
+++ b/src/libs/database/include/database/Filters.hpp
@@ -24,6 +24,7 @@
#include "database/ClusterId.hpp"
#include "database/LabelId.hpp"
#include "database/MediaLibraryId.hpp"
+#include "database/ReleaseTypeId.hpp"
namespace lms::db
{
@@ -32,6 +33,7 @@ namespace lms::db
MediaLibraryId mediaLibrary; // tracks that belongs to this library
std::vector clusters; // tracks that belong to all these clusters
LabelId label; // tracks which release has this label
+ ReleaseTypeId releaseType; // tracks which release has this type
Filters& setClusters(std::span _clusters)
{
@@ -48,5 +50,10 @@ namespace lms::db
label = _label;
return *this;
}
+ Filters& setReleaseType(ReleaseTypeId _releaseType)
+ {
+ releaseType = _releaseType;
+ return *this;
+ }
};
} // namespace lms::db
\ No newline at end of file
diff --git a/src/libs/database/include/database/Release.hpp b/src/libs/database/include/database/Release.hpp
index 028c384d..9b28fcfc 100644
--- a/src/libs/database/include/database/Release.hpp
+++ b/src/libs/database/include/database/Release.hpp
@@ -124,6 +124,7 @@ namespace lms::db
static std::size_t getCount(Session& session);
static pointer find(Session& session, ReleaseTypeId id);
static pointer find(Session& session, std::string_view name);
+ static void find(Session& session, ReleaseTypeSortMethod sortMethod, std::function func);
static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt);
// Accessors
diff --git a/src/libs/database/include/database/Types.hpp b/src/libs/database/include/database/Types.hpp
index 9bde8def..e139062f 100644
--- a/src/libs/database/include/database/Types.hpp
+++ b/src/libs/database/include/database/Types.hpp
@@ -158,6 +158,12 @@ namespace lms::db
StarredDateDesc,
};
+ enum class ReleaseTypeSortMethod
+ {
+ None,
+ Name,
+ };
+
enum class TrackListSortMethod
{
None,
diff --git a/src/lms/ui/explore/Filters.cpp b/src/lms/ui/explore/Filters.cpp
index 78cb14b7..1f565c7e 100644
--- a/src/lms/ui/explore/Filters.cpp
+++ b/src/lms/ui/explore/Filters.cpp
@@ -30,6 +30,7 @@
#include "database/LabelId.hpp"
#include "database/MediaLibrary.hpp"
#include "database/Release.hpp"
+#include "database/ReleaseTypeId.hpp"
#include "database/Session.hpp"
#include "LmsApplication.hpp"
@@ -50,7 +51,11 @@ namespace lms::ui
{
};
- using TypeVariant = std::variant;
+ struct ReleaseTypeTag
+ {
+ };
+
+ using TypeVariant = std::variant;
using TypeModel = ValueStringModel;
std::unique_ptr createTypeModel()
@@ -66,11 +71,12 @@ namespace lms::ui
typeModel->add(Wt::WString::tr("Lms.Explore.media-library"), MediaLibraryTag{});
typeModel->add(Wt::WString::tr("Lms.Explore.label"), LabelTag{});
+ typeModel->add(Wt::WString::tr("Lms.Explore.release-type"), ReleaseTypeTag{});
return typeModel;
}
- using ValueVariant = std::variant;
+ using ValueVariant = std::variant;
using ValueModel = ValueStringModel;
std::unique_ptr createValueModel(TypeVariant type)
@@ -93,6 +99,12 @@ namespace lms::ui
valueModel->add(Wt::WString::fromUTF8(std::string{ label->getName() }), label->getId());
});
}
+ else if (std::holds_alternative(type))
+ {
+ db::ReleaseType::find(session, db::ReleaseTypeSortMethod::Name, [&](const db::ReleaseType::pointer& releaseType) {
+ valueModel->add(Wt::WString::fromUTF8(std::string{ releaseType->getName() }), releaseType->getId());
+ });
+ }
else if (const db::ClusterTypeId * clusterTypeId{ std::get_if(&type) })
{
db::Cluster::FindParameters params;
@@ -136,6 +148,11 @@ namespace lms::ui
set(*labelId);
state::writeValue("filters_label_id", labelId->getValue());
}
+ else if (const db::ReleaseTypeId * releaseTypeId{ std::get_if(&value) })
+ {
+ set(*releaseTypeId);
+ state::writeValue("filters_release_type_id", releaseTypeId->getValue());
+ }
else if (const db::ClusterId * clusterId{ std::get_if(&value) })
{
add(*clusterId);
@@ -176,8 +193,10 @@ namespace lms::ui
if (const std::optional mediaLibraryId{ state::readValue("filters_media_library_id") })
set(db::MediaLibraryId{ *mediaLibraryId });
- if (const std::optional mediaLibraryId{ state::readValue("filters_label_id") })
- set(db::LabelId{ *mediaLibraryId });
+ if (const std::optional labelId{ state::readValue("filters_label_id") })
+ set(db::LabelId{ *labelId });
+ if (const std::optional releaseTypeId{ state::readValue("filters_release_type_id") })
+ set(db::ReleaseTypeId{ *releaseTypeId });
}
void Filters::add(db::ClusterId clusterId)
@@ -272,6 +291,39 @@ namespace lms::ui
emitFilterAddedNotification();
}
+ void Filters::set(db::ReleaseTypeId releaseTypeId)
+ {
+ if (_releaseTypeFilter)
+ {
+ _filters->removeWidget(_releaseTypeFilter);
+ _releaseTypeFilter = nullptr;
+ _dbFilters.releaseType = db::ReleaseTypeId{};
+ }
+
+ std::string name;
+ {
+ auto transaction{ LmsApp->getDbSession().createReadTransaction() };
+
+ const auto releaseType{ db::ReleaseType::find(LmsApp->getDbSession(), releaseTypeId) };
+ if (!releaseType)
+ return;
+
+ name = releaseType->getName();
+ }
+
+ _dbFilters.releaseType = releaseTypeId;
+ _releaseTypeFilter = _filters->addWidget(utils::createFilter(Wt::WString::fromUTF8(name), Wt::WString::tr("Lms.Explore.release-type"), "bg-dark", true));
+ _releaseTypeFilter->clicked().connect(_releaseTypeFilter, [this] {
+ _filters->removeWidget(_releaseTypeFilter);
+ _dbFilters.releaseType = db::ReleaseTypeId{};
+ _releaseTypeFilter = nullptr;
+ _sigUpdated.emit();
+ state::writeValue("filters_release_type_id", std::nullopt);
+ });
+
+ emitFilterAddedNotification();
+ }
+
void Filters::emitFilterAddedNotification()
{
LmsApp->notifyMsg(Notification::Type::Info,
diff --git a/src/lms/ui/explore/Filters.hpp b/src/lms/ui/explore/Filters.hpp
index 98e9931b..1407c847 100644
--- a/src/lms/ui/explore/Filters.hpp
+++ b/src/lms/ui/explore/Filters.hpp
@@ -19,9 +19,6 @@
#pragma once
-#include
-#include
-
#include
#include
#include
@@ -45,11 +42,13 @@ namespace lms::ui
void showDialog();
void set(db::LabelId labelId);
void set(db::MediaLibraryId mediaLibraryId);
+ void set(db::ReleaseTypeId releaseTypeId);
void emitFilterAddedNotification();
Wt::WContainerWidget* _filters{};
Wt::WInteractWidget* _mediaLibraryFilter{};
Wt::WInteractWidget* _labelFilter{};
+ Wt::WInteractWidget* _releaseTypeFilter{};
Wt::Signal<> _sigUpdated;