diff --git a/src/collection/collectionmodel.cpp b/src/collection/collectionmodel.cpp index e9b7c96a1..851a2b077 100644 --- a/src/collection/collectionmodel.cpp +++ b/src/collection/collectionmodel.cpp @@ -71,7 +71,6 @@ #include "covermanager/albumcoverloaderoptions.h" #include "covermanager/albumcoverloaderresult.h" #include "covermanager/albumcoverloader.h" -#include "constants/collectionsettings.h" using namespace std::chrono_literals; using namespace Qt::Literals::StringLiterals; @@ -209,7 +208,7 @@ void CollectionModel::ReloadSettings() { const bool show_pretty_covers = settings.value(CollectionSettings::kPrettyCovers, true).toBool(); const bool show_dividers= settings.value(CollectionSettings::kShowDividers, true).toBool(); const bool show_various_artists = settings.value(CollectionSettings::kVariousArtists, true).toBool(); - const bool sort_skips_articles = settings.value(CollectionSettings::kSortSkipsArticles, true).toBool(); + const CollectionSettings::SortBehaviour sort_behaviour = static_cast(settings.value(CollectionSettings::kSortBehaviour, static_cast(CollectionSettings::SortBehaviour::AsIs)).toInt()); use_disk_cache_ = settings.value(CollectionSettings::kSettingsDiskCacheEnable, false).toBool(); QPixmapCache::setCacheLimit(static_cast(MaximumCacheSize(&settings, CollectionSettings::kSettingsCacheSize, CollectionSettings::kSettingsCacheSizeUnit, CollectionSettings::kSettingsCacheSizeDefault) / 1024)); @@ -224,11 +223,11 @@ 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_skips_articles != options_current_.sort_skips_articles) { + sort_behaviour != options_current_.sort_behaviour) { 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_skips_articles = sort_skips_articles; + options_current_.sort_behaviour = sort_behaviour; ScheduleReset(); } @@ -696,7 +695,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_skips_articles)); + divider_key = DividerKey(group_by, song, SortText(group_by, song, options_active_.sort_behaviour)); if (!divider_key.isEmpty()) { if (!divider_nodes_.contains(divider_key)) { CreateDividerItem(divider_key, DividerDisplayText(group_by, divider_key), parent); @@ -709,8 +708,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); - item->sort_text = SortText(group_by, song, options_active_.sort_skips_articles); + item->display_text = DisplayText(group_by, song, options_active_.sort_behaviour); + item->sort_text = SortText(group_by, song, options_active_.sort_behaviour); if (!divider_key.isEmpty()) { item->sort_text.prepend(divider_key + QLatin1Char(' ')); } @@ -959,15 +958,15 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderR } -QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song) { +QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour &sort_behaviour) { switch (group_by) { case GroupBy::AlbumArtist: - return TextOrUnknown(song.effective_albumartist()); + return NameOrSortname(song.effective_albumartist(), song.albumartistsort(), sort_behaviour); case GroupBy::Artist: - return TextOrUnknown(song.artist()); + return NameOrSortname(song.artist(), song.artistsort(), sort_behaviour); case GroupBy::Album: - return TextOrUnknown(song.album()); + return NameOrSortname(song.album(), song.albumsort(), sort_behaviour); case GroupBy::AlbumDisc: return PrettyAlbumDisc(song.album(), song.disc()); case GroupBy::YearAlbum: @@ -987,9 +986,9 @@ QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song) { case GroupBy::Genre: return TextOrUnknown(song.genre()); case GroupBy::Composer: - return TextOrUnknown(song.composer()); + return NameOrSortname(song.composer(), song.composersort(), sort_behaviour); case GroupBy::Performer: - return TextOrUnknown(song.performer()); + return NameOrSortname(song.performer(), song.performersort(), sort_behaviour); case GroupBy::Grouping: return TextOrUnknown(song.grouping()); case GroupBy::FileType: @@ -1011,6 +1010,26 @@ QString CollectionModel::DisplayText(const GroupBy group_by, const Song &song) { } +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"); @@ -1065,15 +1084,15 @@ QString CollectionModel::PrettyFormat(const Song &song) { } -QString CollectionModel::SortText(const GroupBy group_by, const Song &song, const bool sort_skips_articles) { +QString CollectionModel::SortText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour &sort_behaviour) { switch (group_by) { case GroupBy::AlbumArtist: - return SortTextForArtist(song.effective_albumartist(), sort_skips_articles); + return SortTextForName(song.effective_albumartist(), song.albumartistsort(), sort_behaviour); case GroupBy::Artist: - return SortTextForArtist(song.artist(), sort_skips_articles); + return SortTextForName(song.artist(), song.artistsort(), sort_behaviour); case GroupBy::Album: - return SortText(song.album()); + return SortTextForName(song.album(), song.albumsort(), sort_behaviour); case GroupBy::AlbumDisc: return song.album() + SortTextForNumber(std::max(0, song.disc())); case GroupBy::YearAlbum: @@ -1091,13 +1110,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 SortTextForArtist(song.genre(), sort_skips_articles); + return SortTextForName(song.genre(), song.genre(), sort_behaviour); case GroupBy::Composer: - return SortTextForArtist(song.composer(), sort_skips_articles); + return SortTextForName(song.composer(), song.composersort(), sort_behaviour); case GroupBy::Performer: - return SortTextForArtist(song.performer(), sort_skips_articles); + return SortTextForName(song.performer(), song.performersort(), sort_behaviour); case GroupBy::Grouping: - return SortTextForArtist(song.grouping(), sort_skips_articles); + return SortTextForName(song.grouping(), song.grouping(), sort_behaviour); case GroupBy::FileType: return song.TextForFiletype(); case GroupBy::Format: @@ -1132,21 +1151,43 @@ QString CollectionModel::SortText(QString text) { } -QString CollectionModel::SortTextForArtist(QString artist, const bool skip_articles) { +QString CollectionModel::SortTextSkipArticles(QString name) { - artist = SortText(artist); + name = SortText(name); - if (skip_articles) { - for (const auto &i : Song::kArticles) { - if (artist.startsWith(i)) { - qint64 ilen = i.length(); - artist = artist.right(artist.length() - ilen) + ", "_L1 + i.left(ilen - 1); - break; - } + 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 artist; + 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; } diff --git a/src/collection/collectionmodel.h b/src/collection/collectionmodel.h index 1242a4fc0..dc4cd7e87 100644 --- a/src/collection/collectionmodel.h +++ b/src/collection/collectionmodel.h @@ -52,6 +52,7 @@ #include "collectionmodelupdate.h" #include "collectionfilteroptions.h" #include "collectionitem.h" +#include "constants/collectionsettings.h" class QTimer; class Settings; @@ -129,14 +130,14 @@ class CollectionModel : public SimpleTreeModel { show_dividers(true), show_pretty_covers(true), show_various_artists(true), - sort_skips_articles(true), + sort_behaviour(CollectionSettings::SortBehaviour::SkipArticles), separate_albums_by_grouping(false) {} Grouping group_by; bool show_dividers; bool show_pretty_covers; bool show_various_artists; - bool sort_skips_articles; + CollectionSettings::SortBehaviour sort_behaviour; bool separate_albums_by_grouping; CollectionFilterOptions filter_options; }; @@ -176,17 +177,19 @@ 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); + 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); 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 bool sort_skips_articles); + QString SortText(const GroupBy group_by, const Song &song, const CollectionSettings::SortBehaviour &sort_behaviour); static QString SortText(QString text); + static QString SortTextForName(const QString &name, const QString &sort_name, const CollectionSettings::SortBehaviour &sort_behaviour); static QString SortTextForNumber(const int number); - static QString SortTextForArtist(QString artist, const bool skip_articles); + static QString SortTextSkipArticles(QString name); static QString SortTextForSong(const Song &song); static QString SortTextForYear(const int year); static QString SortTextForBitrate(const int bitrate); diff --git a/src/constants/collectionsettings.h b/src/constants/collectionsettings.h index 94f89c7e3..9b15a5e45 100644 --- a/src/constants/collectionsettings.h +++ b/src/constants/collectionsettings.h @@ -28,7 +28,7 @@ constexpr char kAutoOpen[] = "auto_open"; constexpr char kShowDividers[] = "show_dividers"; constexpr char kPrettyCovers[] = "pretty_covers"; constexpr char kVariousArtists[] = "various_artists"; -constexpr char kSortSkipsArticles[] = "sort_skips_articles"; +constexpr char kSortBehaviour[] = "sort_behaviour"; constexpr char kStartupScan[] = "startup_scan"; constexpr char kMonitor[] = "monitor"; constexpr char kSongTracking[] = "song_tracking"; @@ -50,6 +50,13 @@ 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/settings/collectionsettingspage.cpp b/src/settings/collectionsettingspage.cpp index 729e0e5f9..88d3cae99 100644 --- a/src/settings/collectionsettingspage.cpp +++ b/src/settings/collectionsettingspage.cpp @@ -87,6 +87,11 @@ CollectionSettingsPage::CollectionSettingsPage(SettingsDialog *dialog, 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)); @@ -152,7 +157,7 @@ void CollectionSettingsPage::Load() { 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_->sort_skips_articles->setChecked(s.value(kSortSkipsArticles, 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()); @@ -196,7 +201,8 @@ void CollectionSettingsPage::Save() { s.setValue(kShowDividers, ui_->show_dividers->isChecked()); s.setValue(kPrettyCovers, ui_->pretty_covers->isChecked()); s.setValue(kVariousArtists, ui_->various_artists->isChecked()); - s.setValue(kSortSkipsArticles, ui_->sort_skips_articles->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()); diff --git a/src/settings/collectionsettingspage.ui b/src/settings/collectionsettingspage.ui index 5810a429d..e49ef6327 100644 --- a/src/settings/collectionsettingspage.ui +++ b/src/settings/collectionsettingspage.ui @@ -6,8 +6,8 @@ 0 0 - 565 - 1003 + 604 + 1035 @@ -235,11 +235,37 @@ If there are no matches then it will use the largest image in the directory. + + + + + + + When sorting names like "The Beatles"... + + - - - Skip leading articles ("the", "a", "an") when sorting artist names - + + + + 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 + + @@ -525,7 +551,7 @@ If there are no matches then it will use the largest image in the directory.show_dividers pretty_covers various_artists - sort_skips_articles + combobox_sort spinbox_cache_size combobox_cache_size checkbox_disk_cache diff --git a/src/streaming/streamingsearchmodel.cpp b/src/streaming/streamingsearchmodel.cpp index 37676d4a7..8ae932b98 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::SortTextForArtist(s.effective_albumartist(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.effective_albumartist()); } has_artist_icon = true; break; @@ -109,14 +109,14 @@ QStandardItem *StreamingSearchModel::BuildContainers(const Song &s, QStandardIte } else { display_text = CollectionModel::TextOrUnknown(s.artist()); - sort_text = CollectionModel::SortTextForArtist(s.artist(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.artist()); } has_artist_icon = true; break; case CollectionModel::GroupBy::Album: display_text = CollectionModel::TextOrUnknown(s.album()); - sort_text = CollectionModel::SortTextForArtist(s.album(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.album()); 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::SortTextForArtist(display_text, true); + sort_text = CollectionModel::SortTextSkipArticles(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::SortTextForArtist(s.genre(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.genre()); has_album_icon = true; break; case CollectionModel::GroupBy::Composer: display_text = CollectionModel::TextOrUnknown(s.composer()); - sort_text = CollectionModel::SortTextForArtist(s.composer(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.composer()); has_album_icon = true; break; case CollectionModel::GroupBy::Performer: display_text = CollectionModel::TextOrUnknown(s.performer()); - sort_text = CollectionModel::SortTextForArtist(s.performer(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.performer()); has_album_icon = true; break; case CollectionModel::GroupBy::Grouping: display_text = CollectionModel::TextOrUnknown(s.grouping()); - sort_text = CollectionModel::SortTextForArtist(s.grouping(), true); + sort_text = CollectionModel::SortTextSkipArticles(s.grouping()); has_album_icon = true; break;