diff --git a/src/collection/collectionmodel.cpp b/src/collection/collectionmodel.cpp index afe3eec23..a626c9e4a 100644 --- a/src/collection/collectionmodel.cpp +++ b/src/collection/collectionmodel.cpp @@ -1,6 +1,6 @@ /* * Strawberry Music Player - * Copyright 2018-2024, Jonas Kvinge + * Copyright 2018-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,6 +54,7 @@ #include "includes/scoped_ptr.h" #include "includes/shared_ptr.h" +#include "constants/collectionsettings.h" #include "core/logging.h" #include "core/standardpaths.h" #include "core/database.h" @@ -76,6 +77,7 @@ using namespace std::chrono_literals; using namespace Qt::Literals::StringLiterals; const int CollectionModel::kPrettyCoverSize = 32; + namespace { constexpr char kPixmapDiskCacheDir[] = "pixmapcache"; constexpr char kVariousArtists[] = QT_TR_NOOP("Various artists"); @@ -206,9 +208,10 @@ void CollectionModel::ReloadSettings() { Settings settings; settings.beginGroup(CollectionSettings::kSettingsGroup); const bool show_pretty_covers = settings.value(CollectionSettings::kPrettyCovers, true).toBool(); - const bool show_dividers= settings.value(CollectionSettings::kShowDividers, true).toBool(); + const bool show_dividers = settings.value(CollectionSettings::kShowDividers, true).toBool(); const bool show_various_artists = settings.value(CollectionSettings::kVariousArtists, true).toBool(); - const CollectionSettings::SortBehaviour sort_behaviour = static_cast(settings.value(CollectionSettings::kSortBehaviour, static_cast(CollectionSettings::SortBehaviour::AsIs)).toInt()); + const bool sort_skip_articles_for_artists = settings.value(CollectionSettings::kSkipArticlesForArtists, true).toBool(); + const bool sort_skip_articles_for_albums = settings.value(CollectionSettings::kSkipArticlesForAlbums, false).toBool(); use_disk_cache_ = settings.value(CollectionSettings::kSettingsDiskCacheEnable, false).toBool(); QPixmapCache::setCacheLimit(static_cast(MaximumCacheSize(&settings, CollectionSettings::kSettingsCacheSize, CollectionSettings::kSettingsCacheSizeUnit, CollectionSettings::kSettingsCacheSizeDefault) / 1024)); @@ -223,11 +226,13 @@ void CollectionModel::ReloadSettings() { if (show_pretty_covers != options_current_.show_pretty_covers || show_dividers != options_current_.show_dividers || show_various_artists != options_current_.show_various_artists || - sort_behaviour != options_current_.sort_behaviour) { + sort_skip_articles_for_artists != options_current_.sort_skip_articles_for_artists || + sort_skip_articles_for_albums != options_current_.sort_skip_articles_for_albums) { options_current_.show_pretty_covers = show_pretty_covers; options_current_.show_dividers = show_dividers; options_current_.show_various_artists = show_various_artists; - options_current_.sort_behaviour = sort_behaviour; + options_current_.sort_skip_articles_for_artists = sort_skip_articles_for_artists; + options_current_.sort_skip_articles_for_albums = sort_skip_articles_for_albums; ScheduleReset(); } @@ -695,7 +700,7 @@ CollectionItem *CollectionModel::CreateContainerItem(const GroupBy group_by, con QString divider_key; if (options_active_.show_dividers && container_level == 0) { - divider_key = DividerKey(group_by, song, SortText(group_by, song, options_active_.sort_behaviour)); + divider_key = DividerKey(group_by, song, SortText(group_by, song, options_active_.sort_skip_articles_for_artists, options_active_.sort_skip_articles_for_albums)); if (!divider_key.isEmpty()) { if (!divider_nodes_.contains(divider_key)) { CreateDividerItem(divider_key, DividerDisplayText(group_by, divider_key), parent); @@ -708,8 +713,8 @@ CollectionItem *CollectionModel::CreateContainerItem(const GroupBy group_by, con CollectionItem *item = new CollectionItem(CollectionItem::Type::Container, parent); item->container_level = container_level; item->container_key = container_key; - item->display_text = DisplayText(group_by, song, options_active_.sort_behaviour); - item->sort_text = SortText(group_by, song, options_active_.sort_behaviour); + item->display_text = DisplayText(group_by, song); + item->sort_text = SortText(group_by, song, options_active_.sort_skip_articles_for_artists, options_active_.sort_skip_articles_for_albums); if (!divider_key.isEmpty()) { item->sort_text.prepend(divider_key + QLatin1Char(' ')); } @@ -958,15 +963,15 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderR } -QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour sort_behaviour) { +QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song) { switch (group_by) { case GroupBy::AlbumArtist: - return NameOrSortname(song.effective_albumartist(), song.albumartistsort(), sort_behaviour); + return TextOrUnknown(song.effective_albumartist()); case GroupBy::Artist: - return NameOrSortname(song.artist(), song.artistsort(), sort_behaviour); + return TextOrUnknown(song.artist()); case GroupBy::Album: - return NameOrSortname(song.album(), song.albumsort(), sort_behaviour); + return TextOrUnknown(song.album()); case GroupBy::AlbumDisc: return PrettyAlbumDisc(song.album(), song.disc()); case GroupBy::YearAlbum: @@ -986,9 +991,9 @@ QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song, c case GroupBy::Genre: return TextOrUnknown(song.genre()); case GroupBy::Composer: - return NameOrSortname(song.composer(), song.composersort(), sort_behaviour); + return TextOrUnknown(song.composer()); case GroupBy::Performer: - return NameOrSortname(song.performer(), song.performersort(), sort_behaviour); + return TextOrUnknown(song.performer()); case GroupBy::Grouping: return TextOrUnknown(song.grouping()); case GroupBy::FileType: @@ -1010,26 +1015,6 @@ QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song, c } -QString CollectionModel::NameOrSortname(const QString &name, const QString &sort_name, const CollectionSettings::SortBehaviour sort_behaviour) { - - QString str; - - switch (sort_behaviour) { - using namespace CollectionSettings; - case SortBehaviour::AsIs: - case SortBehaviour::SkipArticles: - case SortBehaviour::UseSortTagForSort: - str = name; - break; - case SortBehaviour::UseSortTagForDisplayAndSort: - str = sort_name; - break; - } - - return TextOrUnknown(str); - -} - QString CollectionModel::TextOrUnknown(const QString &text) { if (text.isEmpty()) return tr("Unknown"); @@ -1084,25 +1069,25 @@ QString CollectionModel::PrettyFormat(const Song &song) { } -QString CollectionModel::SortText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour sort_behaviour) { +QString CollectionModel::SortText(const GroupBy group_by, const Song &song, const bool sort_skip_articles_for_artists, const bool sort_skip_articles_for_albums) { switch (group_by) { case GroupBy::AlbumArtist: - return SortTextForName(song.effective_albumartist(), song.albumartistsort(), sort_behaviour); + return SortTextForName(song.effective_albumartist_with_sort(), sort_skip_articles_for_artists); case GroupBy::Artist: - return SortTextForName(song.artist(), song.artistsort(), sort_behaviour); + return SortTextForName(song.effective_artistsort(), sort_skip_articles_for_artists); case GroupBy::Album: - return SortTextForName(song.album(), song.albumsort(), sort_behaviour); + return SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums); case GroupBy::AlbumDisc: - return song.album() + SortTextForNumber(std::max(0, song.disc())); + return SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc())); case GroupBy::YearAlbum: - return SortTextForNumber(std::max(0, song.year())) + song.grouping() + song.album(); + return SortTextForNumber(std::max(0, song.year())) + song.grouping() + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums); case GroupBy::YearAlbumDisc: - return SortTextForNumber(std::max(0, song.year())) + song.album() + SortTextForNumber(std::max(0, song.disc())); + return SortTextForNumber(std::max(0, song.year())) + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc())); case GroupBy::OriginalYearAlbum: - return SortTextForNumber(std::max(0, song.effective_originalyear())) + song.grouping() + song.album(); + return SortTextForNumber(std::max(0, song.effective_originalyear())) + song.grouping() + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums); case GroupBy::OriginalYearAlbumDisc: - return SortTextForNumber(std::max(0, song.effective_originalyear())) + song.album() + SortTextForNumber(std::max(0, song.disc())); + return SortTextForNumber(std::max(0, song.effective_originalyear())) + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc())); case GroupBy::Disc: return SortTextForNumber(std::max(0, song.disc())); case GroupBy::Year: @@ -1110,13 +1095,13 @@ QString CollectionModel::SortText(const GroupBy group_by, const Song &song, cons case GroupBy::OriginalYear: return SortTextForNumber(std::max(0, song.effective_originalyear())) + QLatin1Char(' '); case GroupBy::Genre: - return SortTextForName(song.genre(), song.genre(), sort_behaviour); + return SortText(song.genre()); case GroupBy::Composer: - return SortTextForName(song.composer(), song.composersort(), sort_behaviour); + return SortTextForName(song.effective_composersort(), sort_skip_articles_for_artists); case GroupBy::Performer: - return SortTextForName(song.performer(), song.performersort(), sort_behaviour); + return SortTextForName(song.effective_performersort(), sort_skip_articles_for_artists); case GroupBy::Grouping: - return SortTextForName(song.grouping(), song.grouping(), sort_behaviour); + return SortText(song.grouping()); case GroupBy::FileType: return song.TextForFiletype(); case GroupBy::Format: @@ -1151,43 +1136,9 @@ QString CollectionModel::SortText(QString text) { } -QString CollectionModel::SortTextSkipArticles(QString name) { +QString CollectionModel::SortTextForName(const QString &name, const bool sort_skip_articles) { - name = SortText(name); - - for (const auto &i : Song::kArticles) { - if (name.startsWith(i)) { - qint64 ilen = i.length(); - name = name.right(name.length() - ilen) + ", "_L1 + i.left(ilen - 1); - break; - } - } - - return name; - -} - -QString CollectionModel::SortTextForName(const QString &name, const QString &sort_name, const CollectionSettings::SortBehaviour sort_behaviour) { - - QString str; - - switch (sort_behaviour) { - using namespace CollectionSettings; - case SortBehaviour::AsIs: - str = SortText(name); - break; - case SortBehaviour::SkipArticles: - str = SortTextSkipArticles(name); - break; - case SortBehaviour::UseSortTagForSort: - str = SortText(sort_name); - break; - case SortBehaviour::UseSortTagForDisplayAndSort: - str = SortText(sort_name); - break; - } - - return str; + return sort_skip_articles ? SkipArticles(SortText(name)) : SortText(name); } @@ -1218,6 +1169,20 @@ QString CollectionModel::SortTextForBitrate(const int bitrate) { } +QString CollectionModel::SkipArticles(QString name) { + + for (const auto &i : Song::kArticles) { + if (name.startsWith(i)) { + qint64 ilen = i.length(); + name = name.right(name.length() - ilen) + ", "_L1 + i.left(ilen - 1); + break; + } + } + + return name; + +} + bool CollectionModel::IsSongTitleDataChanged(const Song &song1, const Song &song2) { return song1.url() != song2.url() || diff --git a/src/collection/collectionmodel.h b/src/collection/collectionmodel.h index 61914b7ac..ab98ed28e 100644 --- a/src/collection/collectionmodel.h +++ b/src/collection/collectionmodel.h @@ -1,6 +1,6 @@ /* * Strawberry Music Player - * Copyright 2018-2024, Jonas Kvinge + * Copyright 2018-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,7 +52,6 @@ #include "collectionmodelupdate.h" #include "collectionfilteroptions.h" #include "collectionitem.h" -#include "constants/collectionsettings.h" class QTimer; class Settings; @@ -130,14 +129,16 @@ class CollectionModel : public SimpleTreeModel { show_dividers(true), show_pretty_covers(true), show_various_artists(true), - sort_behaviour(CollectionSettings::SortBehaviour::SkipArticles), + sort_skip_articles_for_artists(false), + sort_skip_articles_for_albums(false), separate_albums_by_grouping(false) {} Grouping group_by; bool show_dividers; bool show_pretty_covers; bool show_various_artists; - CollectionSettings::SortBehaviour sort_behaviour; + bool sort_skip_articles_for_artists; + bool sort_skip_articles_for_albums; bool separate_albums_by_grouping; CollectionFilterOptions filter_options; }; @@ -177,22 +178,21 @@ class CollectionModel : public SimpleTreeModel { QMimeData *mimeData(const QModelIndexList &indexes) const override; // Utility functions for manipulating text - static QString DisplayText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour sort_behaviour); - static QString NameOrSortname(const QString &name, const QString &sort_name, const CollectionSettings::SortBehaviour sort_behaviour); + QString DisplayText(const GroupBy group_by, const Song &song); static QString TextOrUnknown(const QString &text); static QString PrettyYearAlbum(const int year, const QString &album); static QString PrettyAlbumDisc(const QString &album, const int disc); static QString PrettyYearAlbumDisc(const int year, const QString &album, const int disc); static QString PrettyDisc(const int disc); static QString PrettyFormat(const Song &song); - QString SortText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour sort_behaviour); + QString SortText(const GroupBy group_by, const Song &song, const bool sort_skip_articles_for_artists, const bool sort_skip_articles_for_albums); static QString SortText(QString text); - static QString SortTextForName(const QString &name, const QString &sort_name, const CollectionSettings::SortBehaviour sort_behaviour); + static QString SortTextForName(const QString &name, const bool sort_skip_articles); static QString SortTextForNumber(const int number); - static QString SortTextSkipArticles(QString name); static QString SortTextForSong(const Song &song); static QString SortTextForYear(const int year); static QString SortTextForBitrate(const int bitrate); + static QString SkipArticles(QString name); static bool IsSongTitleDataChanged(const Song &song1, const Song &song2); QString ContainerKey(const GroupBy group_by, const Song &song, bool &has_unique_album_identifier) const; diff --git a/src/constants/collectionsettings.h b/src/constants/collectionsettings.h index 9b15a5e45..b7495d0f8 100644 --- a/src/constants/collectionsettings.h +++ b/src/constants/collectionsettings.h @@ -1,6 +1,6 @@ /* * Strawberry Music Player -* Copyright 2024, Jonas Kvinge +* Copyright 2024-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,18 +24,20 @@ namespace CollectionSettings { constexpr char kSettingsGroup[] = "Collection"; +constexpr char kStartupScan[] = "startup_scan"; +constexpr char kMonitor[] = "monitor"; +constexpr char kSongTracking[] = "song_tracking"; +constexpr char kMarkSongsUnavailable[] = "mark_songs_unavailable"; +constexpr char kSongENUR128LoudnessAnalysis[] = "song_ebur128_loudness_analysis"; +constexpr char kExpireUnavailableSongs[] = "expire_unavailable_songs"; +constexpr char kCoverArtPatterns[] = "cover_art_patterns"; constexpr char kAutoOpen[] = "auto_open"; constexpr char kShowDividers[] = "show_dividers"; constexpr char kPrettyCovers[] = "pretty_covers"; constexpr char kVariousArtists[] = "various_artists"; -constexpr char kSortBehaviour[] = "sort_behaviour"; -constexpr char kStartupScan[] = "startup_scan"; -constexpr char kMonitor[] = "monitor"; -constexpr char kSongTracking[] = "song_tracking"; -constexpr char kSongENUR128LoudnessAnalysis[] = "song_ebur128_loudness_analysis"; -constexpr char kMarkSongsUnavailable[] = "mark_songs_unavailable"; -constexpr char kExpireUnavailableSongs[] = "expire_unavailable_songs"; -constexpr char kCoverArtPatterns[] = "cover_art_patterns"; +constexpr char kSkipArticlesForArtists[] = "skip_articles_for_artists"; +constexpr char kSkipArticlesForAlbums[] = "skip_articles_for_albums"; +constexpr char kShowSortText[] = "show_sort_text"; constexpr char kSettingsCacheSize[] = "cache_size"; constexpr char kSettingsCacheSizeUnit[] = "cache_size_unit"; constexpr char kSettingsDiskCacheEnable[] = "disk_cache_enable"; @@ -50,13 +52,6 @@ constexpr char kOverwriteRating[] = "overwrite_rating"; constexpr char kDeleteFiles[] = "delete_files"; constexpr char kLastPath[] = "last_path"; -enum class SortBehaviour { - AsIs = 1, - SkipArticles = 2, - UseSortTagForSort = 3, - UseSortTagForDisplayAndSort = 4 -}; - enum class CacheSizeUnit { KB, MB, diff --git a/src/core/song.cpp b/src/core/song.cpp index 699e137e8..59b509e2c 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -2,7 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome - * Copyright 2018-2024, Jonas Kvinge + * Copyright 2018-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -349,11 +349,6 @@ struct Song::Private : public QSharedData { bool init_from_file_; // Whether this song was loaded from a file using taglib. bool suspicious_tags_; // Whether our encoding guesser thinks these tags might be incorrectly encoded. - QString title_sortable_; - QString album_sortable_; - QString artist_sortable_; - QString albumartist_sortable_; - QUrl stream_url_; // Temporary stream URL set by the URL handler. }; @@ -529,23 +524,18 @@ QString *Song::mutable_musicbrainz_work_id() { return &d->musicbrainz_work_id_; bool Song::init_from_file() const { return d->init_from_file_; } -const QString &Song::title_sortable() const { return d->title_sortable_; } -const QString &Song::album_sortable() const { return d->album_sortable_; } -const QString &Song::artist_sortable() const { return d->artist_sortable_; } -const QString &Song::albumartist_sortable() const { return d->albumartist_sortable_; } - const QUrl &Song::stream_url() const { return d->stream_url_; } void Song::set_id(const int id) { d->id_ = id; } void Song::set_valid(const bool v) { d->valid_ = v; } -void Song::set_title(const QString &v) { d->title_sortable_ = sortable(v); d->title_ = v; } +void Song::set_title(const QString &v) { d->title_ = v; } void Song::set_titlesort(const QString &v) { d->titlesort_ = v; } -void Song::set_album(const QString &v) { d->album_sortable_ = sortable(v); d->album_ = v; } +void Song::set_album(const QString &v) { d->album_ = v; } void Song::set_albumsort(const QString &v) { d->albumsort_ = v; } -void Song::set_artist(const QString &v) { d->artist_sortable_ = sortable(v); d->artist_ = v; } +void Song::set_artist(const QString &v) { d->artist_ = v; } void Song::set_artistsort(const QString &v) { d->artistsort_ = v; } -void Song::set_albumartist(const QString &v) { d->albumartist_sortable_ = sortable(v); d->albumartist_ = v; } +void Song::set_albumartist(const QString &v) { d->albumartist_ = v; } void Song::set_albumartistsort(const QString &v) { d->albumartistsort_ = v; } void Song::set_track(const int v) { d->track_ = v; } void Song::set_disc(const int v) { d->disc_ = v; } @@ -624,44 +614,13 @@ void Song::set_init_from_file(const bool v) { d->init_from_file_ = v; } void Song::set_stream_url(const QUrl &v) { d->stream_url_ = v; } -void Song::set_title(const TagLib::String &v) { - - const QString title = TagLibStringToQString(v); - d->title_sortable_ = sortable(title); - d->title_ = title; - -} - +void Song::set_title(const TagLib::String &v) { d->title_ = TagLibStringToQString(v); } void Song::set_titlesort(const TagLib::String &v) { d->titlesort_ = TagLibStringToQString(v); } - -void Song::set_album(const TagLib::String &v) { - - const QString album = TagLibStringToQString(v); - d->album_sortable_ = sortable(album); - d->album_ = album; - -} - +void Song::set_album(const TagLib::String &v) { d->album_ = TagLibStringToQString(v); } void Song::set_albumsort(const TagLib::String &v) { d->albumsort_ = TagLibStringToQString(v); } - -void Song::set_artist(const TagLib::String &v) { - - const QString artist = TagLibStringToQString(v); - d->artist_sortable_ = sortable(artist); - d->artist_ = artist; - -} - +void Song::set_artist(const TagLib::String &v) { d->artist_ = TagLibStringToQString(v); } void Song::set_artistsort(const TagLib::String &v) { d->artistsort_ = TagLibStringToQString(v); } - -void Song::set_albumartist(const TagLib::String &v) { - - const QString albumartist = TagLibStringToQString(v); - d->albumartist_sortable_ = sortable(albumartist); - d->albumartist_ = albumartist; - -} - +void Song::set_albumartist(const TagLib::String &v) { d->albumartist_ = TagLibStringToQString(v); } void Song::set_albumartistsort(const TagLib::String &v) { d->albumartistsort_ = TagLibStringToQString(v); } void Song::set_genre(const TagLib::String &v) { d->genre_ = TagLibStringToQString(v); } void Song::set_composer(const TagLib::String &v) { d->composer_ = TagLibStringToQString(v); } @@ -688,12 +647,17 @@ void Song::set_musicbrainz_release_group_id(const TagLib::String &v) { d->musicb void Song::set_musicbrainz_work_id(const TagLib::String &v) { d->musicbrainz_work_id_ = TagLibStringToQString(v).remove(u' ').replace(u';', u'/'); } const QUrl &Song::effective_url() const { return !d->stream_url_.isEmpty() && d->stream_url_.isValid() ? d->stream_url_ : d->url_; } +const QString &Song::effective_titlesort() const { return d->titlesort_.isEmpty() ? d->title_ : d->titlesort_; } const QString &Song::effective_albumartist() const { return d->albumartist_.isEmpty() ? d->artist_ : d->albumartist_; } -const QString &Song::effective_albumartist_sortable() const { return d->albumartist_.isEmpty() ? d->artist_sortable_ : d->albumartist_sortable_; } +const QString &Song::effective_albumartistsort_only() const { return d->albumartistsort_.isEmpty() ? d->albumartist_ : d->albumartistsort_; } +const QString &Song::effective_albumartist_with_sort() const { return effective_albumartistsort_only().isEmpty() ? effective_artistsort() : effective_albumartistsort_only(); } +const QString &Song::effective_artistsort() const { return d->artistsort_.isEmpty() ? d->artist_ : d->artistsort_; } const QString &Song::effective_album() const { return d->album_.isEmpty() ? d->title_ : d->album_; } +const QString &Song::effective_albumsort() const { return d->albumsort_.isEmpty() ? d->album_ : d->albumsort_; } +const QString &Song::effective_composersort() const { return d->composersort_.isEmpty() ? d->composer_ : d->composersort_; } +const QString &Song::effective_performersort() const { return d->performersort_.isEmpty() ? d->performer_ : d->performersort_; } int Song::effective_originalyear() const { return d->originalyear_ < 0 ? d->year_ : d->originalyear_; } -const QString &Song::playlist_albumartist() const { return is_compilation() ? d->albumartist_ : effective_albumartist(); } -const QString &Song::playlist_albumartist_sortable() const { return is_compilation() ? d->albumartist_sortable_ : effective_albumartist_sortable(); } +const QString &Song::playlist_albumartist() const { return is_compilation() ? effective_albumartistsort_only() : effective_albumartist_with_sort(); } bool Song::is_metadata_good() const { return !d->url_.isEmpty() && !d->artist_.isEmpty() && !d->title_.isEmpty(); } bool Song::is_local_collection_song() const { return d->source_ == Source::Collection; } @@ -853,21 +817,6 @@ bool Song::save_embedded_cover_supported(const FileType filetype) { } -QString Song::sortable(const QString &v) { - - QString copy = v.toLower(); - - for (const auto &i : kArticles) { - if (copy.startsWith(i)) { - qint64 ilen = i.length(); - return copy.right(copy.length() - ilen) + u", "_s + copy.left(ilen - 1); - } - } - - return copy; - -} - int Song::ColumnIndex(const QString &field) { return static_cast(kRowIdColumns.indexOf(field)); diff --git a/src/core/song.h b/src/core/song.h index 2cdd0c88f..0e225a0c9 100644 --- a/src/core/song.h +++ b/src/core/song.h @@ -2,7 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome - * Copyright 2018-2024, Jonas Kvinge + * Copyright 2018-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -256,11 +256,6 @@ class Song { bool init_from_file() const; - const QString &title_sortable() const; - const QString &album_sortable() const; - const QString &artist_sortable() const; - const QString &albumartist_sortable() const; - const QUrl &stream_url() const; // Setters @@ -385,12 +380,17 @@ class Song { void set_musicbrainz_work_id(const TagLib::String &v); const QUrl &effective_url() const; + const QString &effective_titlesort() const; const QString &effective_albumartist() const; - const QString &effective_albumartist_sortable() const; + const QString &effective_albumartistsort_only() const; + const QString &effective_albumartist_with_sort() const; + const QString &effective_artistsort() const; const QString &effective_album() const; + const QString &effective_albumsort() const; + const QString &effective_composersort() const; + const QString &effective_performersort() const; int effective_originalyear() const; const QString &playlist_albumartist() const; - const QString &playlist_albumartist_sortable() const; bool is_metadata_good() const; bool is_local_collection_song() const; @@ -555,9 +555,6 @@ class Song { private: struct Private; - - static QString sortable(const QString &v); - QSharedDataPointer d; }; diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index 039f3c01c..da0d513a9 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -378,12 +378,12 @@ QVariant Playlist::data(const QModelIndex &idx, const int role) const { case Column::DateCreated: return song.ctime(); case Column::Comment: - if (role == Qt::DisplayRole) return song.comment().simplified(); + if (role == Qt::DisplayRole) return song.comment().simplified(); return song.comment(); case Column::EBUR128IntegratedLoudness: return song.ebur128_integrated_loudness_lufs().has_value() ? song.ebur128_integrated_loudness_lufs().value() : QVariant(); - case Column::EBUR128LoudnessRange: return song.ebur128_loudness_range_lu().has_value() ? song.ebur128_loudness_range_lu().value() : QVariant(); + case Column::EBUR128LoudnessRange: return song.ebur128_loudness_range_lu().has_value() ? song.ebur128_loudness_range_lu().value() : QVariant(); case Column::Source: return QVariant::fromValue(song.source()); @@ -1346,118 +1346,126 @@ QMimeData *Playlist::mimeData(const QModelIndexList &indexes) const { } +namespace { + +inline bool CompareStr(const QString &a, const QString &b) { + return QString::localeAwareCompare(a.toLower(), b.toLower()) < 0; +} + +template +inline bool CompareVal(const T &a, const T &b) { + return a < b; +} + +} // namespace + bool Playlist::CompareItems(const Column column, const Qt::SortOrder order, PlaylistItemPtr _a, PlaylistItemPtr _b) { - PlaylistItemPtr a = order == Qt::AscendingOrder ? _a : _b; - PlaylistItemPtr b = order == Qt::AscendingOrder ? _b : _a; + PlaylistItemPtr a = (order == Qt::AscendingOrder) ? _a : _b; + PlaylistItemPtr b = (order == Qt::AscendingOrder) ? _b : _a; -#define cmp(field) return a->EffectiveMetadata().field() < b->EffectiveMetadata().field() -#define strcmp(field) return QString::localeAwareCompare(a->EffectiveMetadata().field().toLower(), b->EffectiveMetadata().field().toLower()) < 0; + const auto &ma = a->EffectiveMetadata(); + const auto &mb = b->EffectiveMetadata(); switch (column) { - case Column::Title: strcmp(title_sortable); - case Column::TitleSort: strcmp(titlesort); - case Column::Artist: strcmp(artist_sortable); - case Column::ArtistSort: strcmp(artistsort); - case Column::Album: strcmp(album_sortable); - case Column::AlbumSort: strcmp(albumsort); - case Column::Length: cmp(length_nanosec); - case Column::Track: cmp(track); - case Column::Disc: cmp(disc); - case Column::Year: cmp(year); - case Column::OriginalYear: cmp(effective_originalyear); - case Column::Genre: strcmp(genre); - case Column::AlbumArtist: strcmp(playlist_albumartist_sortable); - case Column::AlbumArtistSort: strcmp(albumartistsort); - case Column::Composer: strcmp(composer); - case Column::ComposerSort: strcmp(composersort); - case Column::Performer: strcmp(performer); - case Column::PerformerSort: strcmp(performersort); - case Column::Grouping: strcmp(grouping); + case Column::Title: return CompareStr(ma.effective_titlesort(), mb.effective_titlesort()); + case Column::TitleSort: return CompareStr(ma.titlesort(), mb.titlesort()); + case Column::Artist: return CompareStr(ma.effective_artistsort(), mb.effective_artistsort()); + case Column::ArtistSort: return CompareStr(ma.artistsort(), mb.artistsort()); + case Column::Album: return CompareStr(ma.effective_albumsort(), mb.effective_albumsort()); + case Column::AlbumSort: return CompareStr(ma.albumsort(), mb.albumsort()); + case Column::Length: return CompareVal(ma.length_nanosec(), mb.length_nanosec()); + case Column::Track: return CompareVal(ma.track(), mb.track()); + case Column::Disc: return CompareVal(ma.disc(), mb.disc()); + case Column::Year: return CompareVal(ma.year(), mb.year()); + case Column::OriginalYear: return CompareVal(ma.effective_originalyear(), mb.effective_originalyear()); + case Column::Genre: return CompareStr(ma.genre(), mb.genre()); + case Column::AlbumArtist: return CompareStr(ma.playlist_albumartist(), mb.playlist_albumartist()); + case Column::AlbumArtistSort: return CompareStr(ma.albumartistsort(), mb.albumartistsort()); + case Column::Composer: return CompareStr(ma.effective_composersort(), mb.effective_composersort()); + case Column::ComposerSort: return CompareStr(ma.composersort(), mb.composersort()); + case Column::Performer: return CompareStr(ma.effective_performersort(), mb.effective_performersort()); + case Column::PerformerSort: return CompareStr(ma.performersort(), mb.performersort()); + case Column::Grouping: return CompareStr(ma.grouping(), mb.grouping()); - case Column::PlayCount: cmp(playcount); - case Column::SkipCount: cmp(skipcount); - case Column::LastPlayed: cmp(lastplayed); + case Column::PlayCount: return CompareVal(ma.playcount(), mb.playcount()); + case Column::SkipCount: return CompareVal(ma.skipcount(), mb.skipcount()); + case Column::LastPlayed: return CompareVal(ma.lastplayed(), mb.lastplayed()); - case Column::Bitrate: cmp(bitrate); - case Column::Samplerate: cmp(samplerate); - case Column::Bitdepth: cmp(bitdepth); - case Column::URL: - return QString::localeAwareCompare(a->OriginalUrl().path(), b->OriginalUrl().path()) < 0; - case Column::BaseFilename: cmp(basefilename); - case Column::Filesize: cmp(filesize); - case Column::Filetype: cmp(filetype); - case Column::DateModified: cmp(mtime); - case Column::DateCreated: cmp(ctime); + case Column::Bitrate: return CompareVal(ma.bitrate(), mb.bitrate()); + case Column::Samplerate: return CompareVal(ma.samplerate(), mb.samplerate()); + case Column::Bitdepth: return CompareVal(ma.bitdepth(), mb.bitdepth()); + case Column::URL: return CompareStr(a->OriginalUrl().path(), b->OriginalUrl().path()); + case Column::BaseFilename: return CompareVal(ma.basefilename(), mb.basefilename()); + case Column::Filesize: return CompareVal(ma.filesize(), mb.filesize()); + case Column::Filetype: return CompareVal(ma.filetype(), mb.filetype()); + case Column::DateModified: return CompareVal(ma.mtime(), mb.mtime()); + case Column::DateCreated: return CompareVal(ma.ctime(), mb.ctime()); - case Column::Comment: strcmp(comment); - case Column::Source: cmp(source); + case Column::Comment: return CompareStr(ma.comment(), mb.comment()); + case Column::Source: return CompareVal(ma.source(), mb.source()); - case Column::Rating: cmp(rating); + case Column::Rating: return CompareVal(ma.rating(), mb.rating()); - case Column::HasCUE: cmp(has_cue); + case Column::HasCUE: return CompareVal(ma.has_cue(), mb.has_cue()); - case Column::EBUR128IntegratedLoudness: cmp(ebur128_integrated_loudness_lufs); - case Column::EBUR128LoudnessRange: cmp(ebur128_loudness_range_lu); + case Column::EBUR128IntegratedLoudness: return CompareVal(ma.ebur128_integrated_loudness_lufs(), mb.ebur128_integrated_loudness_lufs()); + case Column::EBUR128LoudnessRange: return CompareVal(ma.ebur128_loudness_range_lu(), mb.ebur128_loudness_range_lu()); case Column::Mood: case Column::ColumnCount: break; } -#undef cmp -#undef strcmp - return false; - } QString Playlist::column_name(const Column column) { switch (column) { - case Column::Title: return tr("Title"); - case Column::TitleSort: return tr("Title Sort"); - case Column::Artist: return tr("Artist"); - case Column::ArtistSort: return tr("Artist Sort"); - case Column::Album: return tr("Album"); - case Column::AlbumSort: return tr("Album Sort"); - case Column::Track: return tr("Track"); - case Column::Disc: return tr("Disc"); - case Column::Length: return tr("Length"); - case Column::Year: return tr("Year"); - case Column::OriginalYear: return tr("Original Year"); - case Column::Genre: return tr("Genre"); - case Column::AlbumArtist: return tr("Album Artist"); - case Column::AlbumArtistSort: return tr("Album Artist Sort"); - case Column::Composer: return tr("Composer"); - case Column::ComposerSort: return tr("Composer Sort"); - case Column::Performer: return tr("Performer"); - case Column::PerformerSort: return tr("Performer Sort"); - case Column::Grouping: return tr("Grouping"); + case Column::Title: return tr("Title"); + case Column::TitleSort: return tr("Title Sort"); + case Column::Artist: return tr("Artist"); + case Column::ArtistSort: return tr("Artist Sort"); + case Column::Album: return tr("Album"); + case Column::AlbumSort: return tr("Album Sort"); + case Column::Track: return tr("Track"); + case Column::Disc: return tr("Disc"); + case Column::Length: return tr("Length"); + case Column::Year: return tr("Year"); + case Column::OriginalYear: return tr("Original Year"); + case Column::Genre: return tr("Genre"); + case Column::AlbumArtist: return tr("Album Artist"); + case Column::AlbumArtistSort: return tr("Album Artist Sort"); + case Column::Composer: return tr("Composer"); + case Column::ComposerSort: return tr("Composer Sort"); + case Column::Performer: return tr("Performer"); + case Column::PerformerSort: return tr("Performer Sort"); + case Column::Grouping: return tr("Grouping"); - case Column::PlayCount: return tr("Play Count"); - case Column::SkipCount: return tr("Skip Count"); - case Column::LastPlayed: return tr("Last Played"); + case Column::PlayCount: return tr("Play Count"); + case Column::SkipCount: return tr("Skip Count"); + case Column::LastPlayed: return tr("Last Played"); - case Column::Samplerate: return tr("Sample Rate"); - case Column::Bitdepth: return tr("Bit Depth"); - case Column::Bitrate: return tr("Bitrate"); + case Column::Samplerate: return tr("Sample Rate"); + case Column::Bitdepth: return tr("Bit Depth"); + case Column::Bitrate: return tr("Bitrate"); - case Column::URL: return tr("URL"); - case Column::BaseFilename: return tr("File Name (without path)"); - case Column::Filesize: return tr("File Size"); - case Column::Filetype: return tr("File Type"); - case Column::DateModified: return tr("Date Modified"); - case Column::DateCreated: return tr("Date Created"); + case Column::URL: return tr("URL"); + case Column::BaseFilename: return tr("File Name (without path)"); + case Column::Filesize: return tr("File Size"); + case Column::Filetype: return tr("File Type"); + case Column::DateModified: return tr("Date Modified"); + case Column::DateCreated: return tr("Date Created"); - case Column::Comment: return tr("Comment"); - case Column::Source: return tr("Source"); - case Column::Mood: return tr("Mood"); - case Column::Rating: return tr("Rating"); - case Column::HasCUE: return tr("CUE"); + case Column::Comment: return tr("Comment"); + case Column::Source: return tr("Source"); + case Column::Mood: return tr("Mood"); + case Column::Rating: return tr("Rating"); + case Column::HasCUE: return tr("CUE"); case Column::EBUR128IntegratedLoudness: return tr("Integrated Loudness"); - case Column::EBUR128LoudnessRange: return tr("Loudness Range"); + case Column::EBUR128LoudnessRange: return tr("Loudness Range"); case Column::ColumnCount: break; diff --git a/src/settings/collectionsettingspage.cpp b/src/settings/collectionsettingspage.cpp index 88d3cae99..fdb5720da 100644 --- a/src/settings/collectionsettingspage.cpp +++ b/src/settings/collectionsettingspage.cpp @@ -2,7 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome - * Copyright 2018-2024, Jonas Kvinge + * Copyright 2018-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -83,15 +83,9 @@ CollectionSettingsPage::CollectionSettingsPage(SettingsDialog *dialog, ui_->setupUi(this); ui_->list->setItemDelegate(new NativeSeparatorsDelegate(this)); - // Icons setWindowIcon(IconLoader::Load(u"library-music"_s, true, 0, 32)); ui_->add_directory->setIcon(IconLoader::Load(u"document-open-folder"_s)); - ui_->combobox_sort->setItemData(0, static_cast(SortBehaviour::AsIs)); - ui_->combobox_sort->setItemData(1, static_cast(SortBehaviour::SkipArticles)); - ui_->combobox_sort->setItemData(2, static_cast(SortBehaviour::UseSortTagForSort)); - ui_->combobox_sort->setItemData(3, static_cast(SortBehaviour::UseSortTagForDisplayAndSort)); - ui_->combobox_cache_size->addItem(u"KB"_s, static_cast(CacheSizeUnit::KB)); ui_->combobox_cache_size->addItem(u"MB"_s, static_cast(CacheSizeUnit::MB)); @@ -153,21 +147,24 @@ void CollectionSettingsPage::Load() { Settings s; s.beginGroup(kSettingsGroup); - ui_->auto_open->setChecked(s.value(kAutoOpen, true).toBool()); - ui_->show_dividers->setChecked(s.value(kShowDividers, true).toBool()); - ui_->pretty_covers->setChecked(s.value(kPrettyCovers, true).toBool()); - ui_->various_artists->setChecked(s.value(kVariousArtists, true).toBool()); - ui_->combobox_sort->setCurrentIndex(ui_->combobox_sort->findData(s.value(kSortBehaviour, static_cast(SortBehaviour::SkipArticles)).toInt())); + ui_->startup_scan->setChecked(s.value(kStartupScan, true).toBool()); ui_->monitor->setChecked(s.value(kMonitor, true).toBool()); ui_->song_tracking->setChecked(s.value(kSongTracking, false).toBool()); - ui_->song_ebur128_loudness_analysis->setChecked(s.value(kSongENUR128LoudnessAnalysis, false).toBool()); ui_->mark_songs_unavailable->setChecked(ui_->song_tracking->isChecked() ? true : s.value(kMarkSongsUnavailable, true).toBool()); + ui_->song_ebur128_loudness_analysis->setChecked(s.value(kSongENUR128LoudnessAnalysis, false).toBool()); ui_->expire_unavailable_songs_days->setValue(s.value(kExpireUnavailableSongs, 60).toInt()); QStringList filters = s.value(kCoverArtPatterns, QStringList() << u"front"_s << u"cover"_s).toStringList(); ui_->cover_art_patterns->setText(filters.join(u',')); + ui_->auto_open->setChecked(s.value(kAutoOpen, true).toBool()); + ui_->show_dividers->setChecked(s.value(kShowDividers, true).toBool()); + ui_->pretty_covers->setChecked(s.value(kPrettyCovers, true).toBool()); + ui_->various_artists->setChecked(s.value(kVariousArtists, true).toBool()); + ui_->checkbox_skip_articles_for_artists->setChecked(s.value(kSkipArticlesForArtists, true).toBool()); + ui_->checkbox_skip_articles_for_albums->setChecked(s.value(kSkipArticlesForAlbums, false).toBool()); + ui_->spinbox_cache_size->setValue(s.value(kSettingsCacheSize, kSettingsCacheSizeDefault).toInt()); ui_->combobox_cache_size->setCurrentIndex(ui_->combobox_cache_size->findData(s.value(kSettingsCacheSizeUnit, static_cast(CacheSizeUnit::MB)).toInt())); ui_->checkbox_disk_cache->setChecked(s.value(kSettingsDiskCacheEnable, false).toBool()); @@ -197,24 +194,23 @@ void CollectionSettingsPage::Save() { Settings s; s.beginGroup(kSettingsGroup); + + s.setValue(kStartupScan, ui_->startup_scan->isChecked()); + s.setValue(kMonitor, ui_->monitor->isChecked()); + s.setValue(kSongTracking, ui_->song_tracking->isChecked()); + s.setValue(kMarkSongsUnavailable, ui_->song_tracking->isChecked() ? true : ui_->mark_songs_unavailable->isChecked()); + s.setValue(kSongENUR128LoudnessAnalysis, ui_->song_ebur128_loudness_analysis->isChecked()); + s.setValue(kExpireUnavailableSongs, ui_->expire_unavailable_songs_days->value()); + + const QString filter_text = ui_->cover_art_patterns->text(); + s.setValue(kCoverArtPatterns, filter_text.split(u',', Qt::SkipEmptyParts)); + s.setValue(kAutoOpen, ui_->auto_open->isChecked()); s.setValue(kShowDividers, ui_->show_dividers->isChecked()); s.setValue(kPrettyCovers, ui_->pretty_covers->isChecked()); s.setValue(kVariousArtists, ui_->various_artists->isChecked()); - const SortBehaviour menu_sort = static_cast(ui_->combobox_sort->currentData().toInt()); - s.setValue(kSortBehaviour, static_cast(menu_sort)); - s.setValue(kStartupScan, ui_->startup_scan->isChecked()); - s.setValue(kMonitor, ui_->monitor->isChecked()); - s.setValue(kSongTracking, ui_->song_tracking->isChecked()); - s.setValue(kSongENUR128LoudnessAnalysis, ui_->song_ebur128_loudness_analysis->isChecked()); - s.setValue(kMarkSongsUnavailable, ui_->song_tracking->isChecked() ? true : ui_->mark_songs_unavailable->isChecked()); - s.setValue(kExpireUnavailableSongs, ui_->expire_unavailable_songs_days->value()); - - QString filter_text = ui_->cover_art_patterns->text(); - - const QStringList filters = filter_text.split(u',', Qt::SkipEmptyParts); - - s.setValue(kCoverArtPatterns, filters); + s.setValue(kSkipArticlesForArtists, ui_->checkbox_skip_articles_for_artists->isChecked()); + s.setValue(kSkipArticlesForAlbums, ui_->checkbox_skip_articles_for_albums->isChecked()); s.setValue(kSettingsCacheSize, ui_->spinbox_cache_size->value()); s.setValue(kSettingsCacheSizeUnit, ui_->combobox_cache_size->currentData().toInt()); diff --git a/src/settings/collectionsettingspage.h b/src/settings/collectionsettingspage.h index 2ccec4b6d..efd3d9ec0 100644 --- a/src/settings/collectionsettingspage.h +++ b/src/settings/collectionsettingspage.h @@ -2,7 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome - * Copyright 2018-2024, Jonas Kvinge + * Copyright 2018-2025, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/settings/collectionsettingspage.ui b/src/settings/collectionsettingspage.ui index e49ef6327..6a7e689fd 100644 --- a/src/settings/collectionsettingspage.ui +++ b/src/settings/collectionsettingspage.ui @@ -7,7 +7,7 @@ 0 0 604 - 1035 + 1112 @@ -235,37 +235,18 @@ If there are no matches then it will use the largest image in the directory. - - - - - - - When sorting names like "The Beatles"... - - - - - - Sort and show name as is - - - - - Skip articles "The, A, An" for sorting but show name as is - - - - - Use sort tag for sorting and show name as is - - - - - Use sort tag for sorting and display - - + + + Skip leading articles ("the", "a", "an") when sorting artists, composers and performers + + + + + + + Skip leading articles ("the", "a", "an") when sorting albums + @@ -551,7 +532,8 @@ If there are no matches then it will use the largest image in the directory.show_dividers pretty_covers various_artists - combobox_sort + checkbox_skip_articles_for_artists + checkbox_skip_articles_for_albums spinbox_cache_size combobox_cache_size checkbox_disk_cache diff --git a/src/streaming/streamingsearchmodel.cpp b/src/streaming/streamingsearchmodel.cpp index 8ae932b98..439e5e6d7 100644 --- a/src/streaming/streamingsearchmodel.cpp +++ b/src/streaming/streamingsearchmodel.cpp @@ -97,7 +97,7 @@ QStandardItem *StreamingSearchModel::BuildContainers(const Song &s, QStandardIte } else { display_text = CollectionModel::TextOrUnknown(s.effective_albumartist()); - sort_text = CollectionModel::SortTextSkipArticles(s.effective_albumartist()); + sort_text = CollectionModel::SortTextForName(s.effective_albumartist_with_sort(), true); } has_artist_icon = true; break; @@ -109,60 +109,60 @@ QStandardItem *StreamingSearchModel::BuildContainers(const Song &s, QStandardIte } else { display_text = CollectionModel::TextOrUnknown(s.artist()); - sort_text = CollectionModel::SortTextSkipArticles(s.artist()); + sort_text = CollectionModel::SortTextForName(s.effective_artistsort(), true); } has_artist_icon = true; break; case CollectionModel::GroupBy::Album: display_text = CollectionModel::TextOrUnknown(s.album()); - sort_text = CollectionModel::SortTextSkipArticles(s.album()); + sort_text = CollectionModel::SortTextForName(s.effective_albumsort(), false); unique_tag = s.album_id(); has_album_icon = true; break; case CollectionModel::GroupBy::AlbumDisc:{ - int disc = qMax(0, s.disc()); + const int disc = std::max(0, s.disc()); display_text = CollectionModel::PrettyAlbumDisc(s.album(), disc); - sort_text = s.album() + CollectionModel::SortTextForNumber(disc); + sort_text = CollectionModel::SortTextForName(s.effective_albumsort(), false) + CollectionModel::SortTextForNumber(disc); unique_tag = s.album_id(); has_album_icon = true; break; } case CollectionModel::GroupBy::YearAlbum:{ - int year = qMax(0, s.year()); + const int year = std::max(0, s.year()); display_text = CollectionModel::PrettyYearAlbum(year, s.album()); - sort_text = CollectionModel::SortTextForNumber(year) + s.album(); + sort_text = CollectionModel::SortTextForNumber(year) + CollectionModel::SortTextForName(s.effective_albumsort(), false); unique_tag = s.album_id(); has_album_icon = true; break; } case CollectionModel::GroupBy::YearAlbumDisc:{ - int year = qMax(0, s.year()); - int disc = qMax(0, s.disc()); + const int year = std::max(0, s.year()); + const int disc = std::max(0, s.disc()); display_text = CollectionModel::PrettyYearAlbumDisc(year, s.album(), disc); - sort_text = CollectionModel::SortTextForNumber(year) + s.album() + CollectionModel::SortTextForNumber(disc); + sort_text = CollectionModel::SortTextForNumber(year) + CollectionModel::SortTextForName(s.effective_albumsort(), false) + CollectionModel::SortTextForNumber(disc); unique_tag = s.album_id(); has_album_icon = true; break; } case CollectionModel::GroupBy::OriginalYearAlbum:{ - int year = qMax(0, s.effective_originalyear()); + const int year = std::max(0, s.effective_originalyear()); display_text = CollectionModel::PrettyYearAlbum(year, s.album()); - sort_text = CollectionModel::SortTextForNumber(year) + s.album(); + sort_text = CollectionModel::SortTextForNumber(year) + CollectionModel::SortTextForName(s.effective_albumsort(), false); unique_tag = s.album_id(); has_album_icon = true; break; } case CollectionModel::GroupBy::OriginalYearAlbumDisc:{ - const int year = qMax(0, s.effective_originalyear()); - const int disc = qMax(0, s.disc()); + const int year = std::max(0, s.effective_originalyear()); + const int disc = std::max(0, s.disc()); display_text = CollectionModel::PrettyYearAlbumDisc(year, s.album(), disc); - sort_text = CollectionModel::SortTextForNumber(year) + s.album() + CollectionModel::SortTextForNumber(disc); + sort_text = CollectionModel::SortTextForNumber(year) + CollectionModel::SortTextForName(s.effective_albumsort(), false) + CollectionModel::SortTextForNumber(disc); unique_tag = s.album_id(); has_album_icon = true; break; @@ -170,7 +170,7 @@ QStandardItem *StreamingSearchModel::BuildContainers(const Song &s, QStandardIte case CollectionModel::GroupBy::Disc: display_text = CollectionModel::PrettyDisc(s.disc()); - sort_text = CollectionModel::SortTextSkipArticles(display_text); + sort_text = CollectionModel::SortText(display_text); has_album_icon = true; break; @@ -190,25 +190,25 @@ QStandardItem *StreamingSearchModel::BuildContainers(const Song &s, QStandardIte case CollectionModel::GroupBy::Genre: display_text = CollectionModel::TextOrUnknown(s.genre()); - sort_text = CollectionModel::SortTextSkipArticles(s.genre()); + sort_text = CollectionModel::SortText(s.genre()); has_album_icon = true; break; case CollectionModel::GroupBy::Composer: display_text = CollectionModel::TextOrUnknown(s.composer()); - sort_text = CollectionModel::SortTextSkipArticles(s.composer()); + sort_text = CollectionModel::SortTextForName(s.composer(), true); has_album_icon = true; break; case CollectionModel::GroupBy::Performer: display_text = CollectionModel::TextOrUnknown(s.performer()); - sort_text = CollectionModel::SortTextSkipArticles(s.performer()); + sort_text = CollectionModel::SortTextForName(s.performer(), true); has_album_icon = true; break; case CollectionModel::GroupBy::Grouping: display_text = CollectionModel::TextOrUnknown(s.grouping()); - sort_text = CollectionModel::SortTextSkipArticles(s.grouping()); + sort_text = CollectionModel::SortText(s.grouping()); has_album_icon = true; break;