CollectionModel: Make separating albums by grouping optional
Fixes #1018
This commit is contained in:
parent
c219995218
commit
6562258db5
|
@ -2,6 +2,7 @@
|
||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2019-2022, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -58,7 +59,12 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
ui_(new Ui_CollectionFilterWidget),
|
ui_(new Ui_CollectionFilterWidget),
|
||||||
model_(nullptr),
|
model_(nullptr),
|
||||||
group_by_dialog_(new GroupByDialog),
|
group_by_dialog_(new GroupByDialog(this)),
|
||||||
|
groupings_manager_(nullptr),
|
||||||
|
filter_age_menu_(nullptr),
|
||||||
|
group_by_menu_(nullptr),
|
||||||
|
collection_menu_(nullptr),
|
||||||
|
group_by_group_(nullptr),
|
||||||
filter_delay_(new QTimer(this)),
|
filter_delay_(new QTimer(this)),
|
||||||
filter_applies_to_model_(true),
|
filter_applies_to_model_(true),
|
||||||
delay_behaviour_(DelayedOnLargeLibraries) {
|
delay_behaviour_(DelayedOnLargeLibraries) {
|
||||||
|
@ -114,13 +120,8 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
|
||||||
filter_ages_[ui_->filter_age_three_months] = 60 * 60 * 24 * 30 * 3;
|
filter_ages_[ui_->filter_age_three_months] = 60 * 60 * 24 * 30 * 3;
|
||||||
filter_ages_[ui_->filter_age_year] = 60 * 60 * 24 * 365;
|
filter_ages_[ui_->filter_age_year] = 60 * 60 * 24 * 365;
|
||||||
|
|
||||||
// "Group by ..."
|
|
||||||
group_by_group_ = CreateGroupByActions(this);
|
|
||||||
|
|
||||||
group_by_menu_ = new QMenu(tr("Group by"), this);
|
group_by_menu_ = new QMenu(tr("Group by"), this);
|
||||||
group_by_menu_->addActions(group_by_group_->actions());
|
|
||||||
|
|
||||||
QObject::connect(group_by_group_, &QActionGroup::triggered, this, &CollectionFilterWidget::GroupByClicked);
|
|
||||||
QObject::connect(ui_->save_grouping, &QAction::triggered, this, &CollectionFilterWidget::SaveGroupBy);
|
QObject::connect(ui_->save_grouping, &QAction::triggered, this, &CollectionFilterWidget::SaveGroupBy);
|
||||||
QObject::connect(ui_->manage_groupings, &QAction::triggered, this, &CollectionFilterWidget::ShowGroupingManager);
|
QObject::connect(ui_->manage_groupings, &QAction::triggered, this, &CollectionFilterWidget::ShowGroupingManager);
|
||||||
|
|
||||||
|
@ -147,8 +148,8 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
|
||||||
|
|
||||||
if (model_) {
|
if (model_) {
|
||||||
QObject::disconnect(model_, nullptr, this, nullptr);
|
QObject::disconnect(model_, nullptr, this, nullptr);
|
||||||
QObject::disconnect(model_, nullptr, group_by_dialog_.get(), nullptr);
|
QObject::disconnect(model_, nullptr, group_by_dialog_, nullptr);
|
||||||
QObject::disconnect(group_by_dialog_.get(), nullptr, model_, nullptr);
|
QObject::disconnect(group_by_dialog_, nullptr, model_, nullptr);
|
||||||
QList<QAction*> filter_ages = filter_ages_.keys();
|
QList<QAction*> filter_ages = filter_ages_.keys();
|
||||||
for (QAction *action : filter_ages) {
|
for (QAction *action : filter_ages) {
|
||||||
QObject::disconnect(action, &QAction::triggered, model_, nullptr);
|
QObject::disconnect(action, &QAction::triggered, model_, nullptr);
|
||||||
|
@ -158,9 +159,9 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
|
||||||
model_ = model;
|
model_ = model;
|
||||||
|
|
||||||
// Connect signals
|
// Connect signals
|
||||||
QObject::connect(model_, &CollectionModel::GroupingChanged, group_by_dialog_.get(), &GroupByDialog::CollectionGroupingChanged);
|
QObject::connect(model_, &CollectionModel::GroupingChanged, group_by_dialog_, &GroupByDialog::CollectionGroupingChanged);
|
||||||
QObject::connect(model_, &CollectionModel::GroupingChanged, this, &CollectionFilterWidget::GroupingChanged);
|
QObject::connect(model_, &CollectionModel::GroupingChanged, this, &CollectionFilterWidget::GroupingChanged);
|
||||||
QObject::connect(group_by_dialog_.get(), &GroupByDialog::Accepted, model_, &CollectionModel::SetGroupBy);
|
QObject::connect(group_by_dialog_, &GroupByDialog::Accepted, model_, &CollectionModel::SetGroupBy);
|
||||||
|
|
||||||
QList<QAction*> filter_ages = filter_ages_.keys();
|
QList<QAction*> filter_ages = filter_ages_.keys();
|
||||||
for (QAction *action : filter_ages) {
|
for (QAction *action : filter_ages) {
|
||||||
|
@ -176,15 +177,31 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
|
||||||
if (s.contains(group_by_version())) version = s.value(group_by_version(), 0).toInt();
|
if (s.contains(group_by_version())) version = s.value(group_by_version(), 0).toInt();
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
model_->SetGroupBy(CollectionModel::Grouping(
|
model_->SetGroupBy(CollectionModel::Grouping(
|
||||||
CollectionModel::GroupBy(s.value(group_by(1), static_cast<int>(CollectionModel::GroupBy_AlbumArtist)).toInt()),
|
CollectionModel::GroupBy(s.value(group_by_key(1), static_cast<int>(CollectionModel::GroupBy_AlbumArtist)).toInt()),
|
||||||
CollectionModel::GroupBy(s.value(group_by(2), static_cast<int>(CollectionModel::GroupBy_AlbumDisc)).toInt()),
|
CollectionModel::GroupBy(s.value(group_by_key(2), static_cast<int>(CollectionModel::GroupBy_AlbumDisc)).toInt()),
|
||||||
CollectionModel::GroupBy(s.value(group_by(3), static_cast<int>(CollectionModel::GroupBy_None)).toInt())));
|
CollectionModel::GroupBy(s.value(group_by_key(3), static_cast<int>(CollectionModel::GroupBy_None)).toInt())), s.value(separate_albums_by_grouping_key(), false).toBool());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
model_->SetGroupBy(CollectionModel::Grouping(CollectionModel::GroupBy_AlbumArtist, CollectionModel::GroupBy_AlbumDisc, CollectionModel::GroupBy_None));
|
model_->SetGroupBy(CollectionModel::Grouping(CollectionModel::GroupBy_AlbumArtist, CollectionModel::GroupBy_AlbumDisc, CollectionModel::GroupBy_None), false);
|
||||||
}
|
}
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollectionFilterWidget::SetSettingsGroup(const QString &settings_group) {
|
||||||
|
|
||||||
|
settings_group_ = settings_group;
|
||||||
|
saved_groupings_settings_group_ = SavedGroupingManager::GetSavedGroupingsSettingsGroup(settings_group);
|
||||||
|
|
||||||
|
UpdateGroupByActions();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollectionFilterWidget::SetSettingsPrefix(const QString &prefix) {
|
||||||
|
|
||||||
|
settings_prefix_ = prefix;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionFilterWidget::ReloadSettings() {
|
void CollectionFilterWidget::ReloadSettings() {
|
||||||
|
@ -198,21 +215,10 @@ void CollectionFilterWidget::ReloadSettings() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CollectionFilterWidget::group_by() {
|
QString CollectionFilterWidget::group_by_version() const {
|
||||||
|
|
||||||
if (settings_prefix_.isEmpty()) {
|
if (settings_prefix_.isEmpty()) {
|
||||||
return QString("group_by");
|
return "group_by_version";
|
||||||
}
|
|
||||||
else {
|
|
||||||
return QString("%1_group_by").arg(settings_prefix_);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CollectionFilterWidget::group_by_version() {
|
|
||||||
|
|
||||||
if (settings_prefix_.isEmpty()) {
|
|
||||||
return QString("group_by_version");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return QString("%1_group_by_version").arg(settings_prefix_);
|
return QString("%1_group_by_version").arg(settings_prefix_);
|
||||||
|
@ -220,7 +226,29 @@ QString CollectionFilterWidget::group_by_version() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CollectionFilterWidget::group_by(const int number) { return group_by() + QString::number(number); }
|
QString CollectionFilterWidget::group_by_key() const {
|
||||||
|
|
||||||
|
if (settings_prefix_.isEmpty()) {
|
||||||
|
return "group_by";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QString("%1_group_by").arg(settings_prefix_);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CollectionFilterWidget::group_by_key(const int number) const { return group_by_key() + QString::number(number); }
|
||||||
|
|
||||||
|
QString CollectionFilterWidget::separate_albums_by_grouping_key() const {
|
||||||
|
|
||||||
|
if (settings_prefix_.isEmpty()) {
|
||||||
|
return "separate_albums_by_grouping";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QString("%1_separate_albums_by_grouping").arg(settings_prefix_);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionFilterWidget::UpdateGroupByActions() {
|
void CollectionFilterWidget::UpdateGroupByActions() {
|
||||||
|
|
||||||
|
@ -229,7 +257,7 @@ void CollectionFilterWidget::UpdateGroupByActions() {
|
||||||
delete group_by_group_;
|
delete group_by_group_;
|
||||||
}
|
}
|
||||||
|
|
||||||
group_by_group_ = CreateGroupByActions(this);
|
group_by_group_ = CreateGroupByActions(saved_groupings_settings_group_, this);
|
||||||
group_by_menu_->clear();
|
group_by_menu_->clear();
|
||||||
group_by_menu_->addActions(group_by_group_->actions());
|
group_by_menu_->addActions(group_by_group_->actions());
|
||||||
QObject::connect(group_by_group_, &QActionGroup::triggered, this, &CollectionFilterWidget::GroupByClicked);
|
QObject::connect(group_by_group_, &QActionGroup::triggered, this, &CollectionFilterWidget::GroupByClicked);
|
||||||
|
@ -239,8 +267,7 @@ void CollectionFilterWidget::UpdateGroupByActions() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QActionGroup *CollectionFilterWidget::CreateGroupByActions(const QString &saved_groupings_settings_group, QObject *parent) {
|
||||||
QActionGroup *CollectionFilterWidget::CreateGroupByActions(QObject *parent) {
|
|
||||||
|
|
||||||
QActionGroup *ret = new QActionGroup(parent);
|
QActionGroup *ret = new QActionGroup(parent);
|
||||||
|
|
||||||
|
@ -267,9 +294,9 @@ QActionGroup *CollectionFilterWidget::CreateGroupByActions(QObject *parent) {
|
||||||
sep1->setSeparator(true);
|
sep1->setSeparator(true);
|
||||||
ret->addAction(sep1);
|
ret->addAction(sep1);
|
||||||
|
|
||||||
// read saved groupings
|
// Read saved groupings
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(CollectionModel::kSavedGroupingsSettingsGroup);
|
s.beginGroup(saved_groupings_settings_group);
|
||||||
int version = s.value("version").toInt();
|
int version = s.value("version").toInt();
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
QStringList saved = s.childKeys();
|
QStringList saved = s.childKeys();
|
||||||
|
@ -316,20 +343,38 @@ QAction *CollectionFilterWidget::CreateGroupByAction(const QString &text, QObjec
|
||||||
|
|
||||||
void CollectionFilterWidget::SaveGroupBy() {
|
void CollectionFilterWidget::SaveGroupBy() {
|
||||||
|
|
||||||
QString text = QInputDialog::getText(this, tr("Grouping Name"), tr("Grouping name:"));
|
if (!model_) return;
|
||||||
if (!text.isEmpty() && model_) {
|
|
||||||
model_->SaveGrouping(text);
|
QString name = QInputDialog::getText(this, tr("Grouping Name"), tr("Grouping name:"));
|
||||||
UpdateGroupByActions();
|
if (name.isEmpty()) return;
|
||||||
|
|
||||||
|
qLog(Debug) << "Saving current grouping to" << name;
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
if (settings_group_.isEmpty() || settings_group_ == CollectionSettingsPage::kSettingsGroup) {
|
||||||
|
s.beginGroup(SavedGroupingManager::kSavedGroupingsSettingsGroup);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
s.beginGroup(QString(SavedGroupingManager::kSavedGroupingsSettingsGroup) + "_" + settings_group_);
|
||||||
|
}
|
||||||
|
QByteArray buffer;
|
||||||
|
QDataStream datastream(&buffer, QIODevice::WriteOnly);
|
||||||
|
datastream << model_->GetGroupBy();
|
||||||
|
s.setValue("version", "1");
|
||||||
|
s.setValue(name, buffer);
|
||||||
|
s.endGroup();
|
||||||
|
|
||||||
|
UpdateGroupByActions();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionFilterWidget::ShowGroupingManager() {
|
void CollectionFilterWidget::ShowGroupingManager() {
|
||||||
|
|
||||||
if (!groupings_manager_) {
|
if (!groupings_manager_) {
|
||||||
groupings_manager_ = std::make_unique<SavedGroupingManager>();
|
groupings_manager_ = new SavedGroupingManager(saved_groupings_settings_group_, this);
|
||||||
|
QObject::connect(groupings_manager_, &SavedGroupingManager::UpdateGroupByActions, this, &CollectionFilterWidget::UpdateGroupByActions);
|
||||||
}
|
}
|
||||||
groupings_manager_->SetFilter(this);
|
|
||||||
groupings_manager_->UpdateModel();
|
groupings_manager_->UpdateModel();
|
||||||
groupings_manager_->show();
|
groupings_manager_->show();
|
||||||
|
|
||||||
|
@ -362,20 +407,20 @@ void CollectionFilterWidget::GroupByClicked(QAction *action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionModel::Grouping g = action->property("group_by").value<CollectionModel::Grouping>();
|
CollectionModel::Grouping g = action->property("group_by").value<CollectionModel::Grouping>();
|
||||||
model_->SetGroupBy(g);
|
model_->SetGroupBy(g, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping g) {
|
void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping g, const bool separate_albums_by_grouping) {
|
||||||
|
|
||||||
if (!settings_group_.isEmpty()) {
|
if (!settings_group_.isEmpty()) {
|
||||||
// Save the settings
|
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(settings_group_);
|
s.beginGroup(settings_group_);
|
||||||
s.setValue(group_by_version(), 1);
|
s.setValue(group_by_version(), 1);
|
||||||
s.setValue(group_by(1), static_cast<int>(g[0]));
|
s.setValue(group_by_key(1), static_cast<int>(g[0]));
|
||||||
s.setValue(group_by(2), static_cast<int>(g[1]));
|
s.setValue(group_by_key(2), static_cast<int>(g[1]));
|
||||||
s.setValue(group_by(3), static_cast<int>(g[2]));
|
s.setValue(group_by_key(3), static_cast<int>(g[2]));
|
||||||
|
s.setValue(separate_albums_by_grouping_key(), separate_albums_by_grouping);
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +431,10 @@ void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping g)
|
||||||
|
|
||||||
void CollectionFilterWidget::CheckCurrentGrouping(const CollectionModel::Grouping g) {
|
void CollectionFilterWidget::CheckCurrentGrouping(const CollectionModel::Grouping g) {
|
||||||
|
|
||||||
|
if (!group_by_group_) {
|
||||||
|
UpdateGroupByActions();
|
||||||
|
}
|
||||||
|
|
||||||
for (QAction *action : group_by_group_->actions()) {
|
for (QAction *action : group_by_group_->actions()) {
|
||||||
if (action->property("group_by").isNull()) continue;
|
if (action->property("group_by").isNull()) continue;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2019-2022, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -60,9 +61,8 @@ class CollectionFilterWidget : public QWidget {
|
||||||
|
|
||||||
void Init(CollectionModel *model);
|
void Init(CollectionModel *model);
|
||||||
|
|
||||||
static QActionGroup *CreateGroupByActions(QObject *parent);
|
static QActionGroup *CreateGroupByActions(const QString &saved_groupings_settings_group, QObject *parent);
|
||||||
|
|
||||||
void UpdateGroupByActions();
|
|
||||||
void SetFilterHint(const QString &hint);
|
void SetFilterHint(const QString &hint);
|
||||||
void SetApplyFilterToCollection(bool filter_applies_to_model) { filter_applies_to_model_ = filter_applies_to_model; }
|
void SetApplyFilterToCollection(bool filter_applies_to_model) { filter_applies_to_model_ = filter_applies_to_model; }
|
||||||
void SetDelayBehaviour(DelayBehaviour behaviour) { delay_behaviour_ = behaviour; }
|
void SetDelayBehaviour(DelayBehaviour behaviour) { delay_behaviour_ = behaviour; }
|
||||||
|
@ -73,12 +73,13 @@ class CollectionFilterWidget : public QWidget {
|
||||||
QMenu *menu() const { return collection_menu_; }
|
QMenu *menu() const { return collection_menu_; }
|
||||||
void AddMenuAction(QAction *action);
|
void AddMenuAction(QAction *action);
|
||||||
|
|
||||||
void SetSettingsGroup(const QString &group) { settings_group_ = group; }
|
void SetSettingsGroup(const QString &group);
|
||||||
void SetSettingsPrefix(const QString &prefix) { settings_prefix_ = prefix; }
|
void SetSettingsPrefix(const QString &prefix);
|
||||||
|
|
||||||
QString group_by();
|
QString group_by_version() const;
|
||||||
QString group_by_version();
|
QString group_by_key() const;
|
||||||
QString group_by(const int number);
|
QString group_by_key(const int number) const;
|
||||||
|
QString separate_albums_by_grouping_key() const;
|
||||||
|
|
||||||
void ReloadSettings();
|
void ReloadSettings();
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ class CollectionFilterWidget : public QWidget {
|
||||||
void FocusSearchField();
|
void FocusSearchField();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void UpdateGroupByActions();
|
||||||
void SetQueryMode(QueryOptions::QueryMode query_mode);
|
void SetQueryMode(QueryOptions::QueryMode query_mode);
|
||||||
void FocusOnFilter(QKeyEvent *e);
|
void FocusOnFilter(QKeyEvent *e);
|
||||||
|
|
||||||
|
@ -99,7 +101,7 @@ class CollectionFilterWidget : public QWidget {
|
||||||
void keyReleaseEvent(QKeyEvent *e) override;
|
void keyReleaseEvent(QKeyEvent *e) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void GroupingChanged(const CollectionModel::Grouping g);
|
void GroupingChanged(const CollectionModel::Grouping g, const bool separate_albums_by_grouping);
|
||||||
void GroupByClicked(QAction *action);
|
void GroupByClicked(QAction *action);
|
||||||
void SaveGroupBy();
|
void SaveGroupBy();
|
||||||
void ShowGroupingManager();
|
void ShowGroupingManager();
|
||||||
|
@ -115,8 +117,8 @@ class CollectionFilterWidget : public QWidget {
|
||||||
Ui_CollectionFilterWidget *ui_;
|
Ui_CollectionFilterWidget *ui_;
|
||||||
CollectionModel *model_;
|
CollectionModel *model_;
|
||||||
|
|
||||||
std::unique_ptr<GroupByDialog> group_by_dialog_;
|
GroupByDialog *group_by_dialog_;
|
||||||
std::unique_ptr<SavedGroupingManager> groupings_manager_;
|
SavedGroupingManager *groupings_manager_;
|
||||||
|
|
||||||
QMenu *filter_age_menu_;
|
QMenu *filter_age_menu_;
|
||||||
QMenu *group_by_menu_;
|
QMenu *group_by_menu_;
|
||||||
|
@ -130,6 +132,7 @@ class CollectionFilterWidget : public QWidget {
|
||||||
DelayBehaviour delay_behaviour_;
|
DelayBehaviour delay_behaviour_;
|
||||||
|
|
||||||
QString settings_group_;
|
QString settings_group_;
|
||||||
|
QString saved_groupings_settings_group_;
|
||||||
QString settings_prefix_;
|
QString settings_prefix_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
@ -71,7 +72,6 @@
|
||||||
#include "covermanager/albumcoverloaderresult.h"
|
#include "covermanager/albumcoverloaderresult.h"
|
||||||
#include "settings/collectionsettingspage.h"
|
#include "settings/collectionsettingspage.h"
|
||||||
|
|
||||||
const char *CollectionModel::kSavedGroupingsSettingsGroup = "SavedGroupings";
|
|
||||||
const int CollectionModel::kPrettyCoverSize = 32;
|
const int CollectionModel::kPrettyCoverSize = 32;
|
||||||
const char *CollectionModel::kPixmapDiskCacheDir = "pixmapcache";
|
const char *CollectionModel::kPixmapDiskCacheDir = "pixmapcache";
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
||||||
total_song_count_(0),
|
total_song_count_(0),
|
||||||
total_artist_count_(0),
|
total_artist_count_(0),
|
||||||
total_album_count_(0),
|
total_album_count_(0),
|
||||||
|
separate_albums_by_grouping_(false),
|
||||||
artist_icon_(IconLoader::Load("folder-sound")),
|
artist_icon_(IconLoader::Load("folder-sound")),
|
||||||
album_icon_(IconLoader::Load("cdcase")),
|
album_icon_(IconLoader::Load("cdcase")),
|
||||||
init_task_id_(-1),
|
init_task_id_(-1),
|
||||||
|
@ -160,22 +161,6 @@ void CollectionModel::set_show_dividers(const bool show_dividers) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::SaveGrouping(const QString &name) {
|
|
||||||
|
|
||||||
qLog(Debug) << "Model, save to: " << name;
|
|
||||||
|
|
||||||
QByteArray buffer;
|
|
||||||
QDataStream ds(&buffer, QIODevice::WriteOnly);
|
|
||||||
ds << group_by_;
|
|
||||||
|
|
||||||
QSettings s;
|
|
||||||
s.beginGroup(kSavedGroupingsSettingsGroup);
|
|
||||||
s.setValue("version", "1");
|
|
||||||
s.setValue(name, buffer);
|
|
||||||
s.endGroup();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollectionModel::ReloadSettings() {
|
void CollectionModel::ReloadSettings() {
|
||||||
|
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
@ -239,13 +224,13 @@ void CollectionModel::SongsDiscovered(const SongList &songs) {
|
||||||
CollectionItem *container = root_;
|
CollectionItem *container = root_;
|
||||||
QString key;
|
QString key;
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
GroupBy type = group_by_[i];
|
GroupBy group_by = group_by_[i];
|
||||||
if (type == GroupBy_None) break;
|
if (group_by == GroupBy_None) break;
|
||||||
|
|
||||||
if (!key.isEmpty()) key.append("-");
|
if (!key.isEmpty()) key.append("-");
|
||||||
|
|
||||||
// Special case: if the song is a compilation and the current GroupBy level is Artists, then we want the Various Artists node :(
|
// Special case: if the song is a compilation and the current GroupBy level is Artists, then we want the Various Artists node :(
|
||||||
if (IsArtistGroupBy(type) && song.is_compilation()) {
|
if (IsArtistGroupBy(group_by) && song.is_compilation()) {
|
||||||
if (container->compilation_artist_node_ == nullptr) {
|
if (container->compilation_artist_node_ == nullptr) {
|
||||||
CreateCompilationArtistNode(true, container);
|
CreateCompilationArtistNode(true, container);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +239,7 @@ void CollectionModel::SongsDiscovered(const SongList &songs) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Otherwise find the proper container at this level based on the item's key
|
// Otherwise find the proper container at this level based on the item's key
|
||||||
key.append(ContainerKey(type, song));
|
key.append(ContainerKey(group_by, separate_albums_by_grouping_, song));
|
||||||
|
|
||||||
// Does it exist already?
|
// Does it exist already?
|
||||||
if (container_nodes_[i].contains(key)) {
|
if (container_nodes_[i].contains(key)) {
|
||||||
|
@ -262,7 +247,7 @@ void CollectionModel::SongsDiscovered(const SongList &songs) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Create the container
|
// Create the container
|
||||||
container = ItemFromSong(type, true, i == 0, container, song, i);
|
container = ItemFromSong(group_by, separate_albums_by_grouping_, true, i == 0, container, song, i);
|
||||||
container_nodes_[i].insert(key, container);
|
container_nodes_[i].insert(key, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +259,7 @@ void CollectionModel::SongsDiscovered(const SongList &songs) {
|
||||||
if (!container->lazy_loaded && use_lazy_loading_) continue;
|
if (!container->lazy_loaded && use_lazy_loading_) continue;
|
||||||
|
|
||||||
// We've gone all the way down to the deepest level and everything was already lazy loaded, so now we have to create the song in the container.
|
// We've gone all the way down to the deepest level and everything was already lazy loaded, so now we have to create the song in the container.
|
||||||
song_nodes_.insert(song.id(), ItemFromSong(GroupBy_None, true, false, container, song, -1));
|
song_nodes_.insert(song.id(), ItemFromSong(GroupBy_None, separate_albums_by_grouping_, true, false, container, song, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -311,11 +296,11 @@ CollectionItem *CollectionModel::CreateCompilationArtistNode(const bool signal,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CollectionModel::ContainerKey(const GroupBy type, const Song &song) {
|
QString CollectionModel::ContainerKey(const GroupBy group_by, const bool separate_albums_by_grouping, const Song &song) {
|
||||||
|
|
||||||
QString key;
|
QString key;
|
||||||
|
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:
|
case GroupBy_AlbumArtist:
|
||||||
key = TextOrUnknown(song.effective_albumartist());
|
key = TextOrUnknown(song.effective_albumartist());
|
||||||
break;
|
break;
|
||||||
|
@ -325,32 +310,32 @@ QString CollectionModel::ContainerKey(const GroupBy type, const Song &song) {
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:
|
||||||
key = TextOrUnknown(song.album());
|
key = TextOrUnknown(song.album());
|
||||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||||
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
|
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_AlbumDisc:
|
case GroupBy_AlbumDisc:
|
||||||
key = PrettyAlbumDisc(song.album(), song.disc());
|
key = PrettyAlbumDisc(song.album(), song.disc());
|
||||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||||
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
|
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_YearAlbum:
|
case GroupBy_YearAlbum:
|
||||||
key = PrettyYearAlbum(song.year(), song.album());
|
key = PrettyYearAlbum(song.year(), song.album());
|
||||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||||
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
|
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_YearAlbumDisc:
|
case GroupBy_YearAlbumDisc:
|
||||||
key = PrettyYearAlbumDisc(song.year(), song.album(), song.disc());
|
key = PrettyYearAlbumDisc(song.year(), song.album(), song.disc());
|
||||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||||
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
|
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_OriginalYearAlbum:
|
case GroupBy_OriginalYearAlbum:
|
||||||
key = PrettyYearAlbum(song.effective_originalyear(), song.album());
|
key = PrettyYearAlbum(song.effective_originalyear(), song.album());
|
||||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||||
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
|
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_OriginalYearAlbumDisc:
|
case GroupBy_OriginalYearAlbumDisc:
|
||||||
key = PrettyYearAlbumDisc(song.effective_originalyear(), song.album(), song.disc());
|
key = PrettyYearAlbumDisc(song.effective_originalyear(), song.album(), song.disc());
|
||||||
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
|
||||||
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
|
if (separate_albums_by_grouping && !song.grouping().isEmpty()) key.append("-" + song.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_Disc:
|
case GroupBy_Disc:
|
||||||
key = PrettyDisc(song.disc());
|
key = PrettyDisc(song.disc());
|
||||||
|
@ -408,13 +393,13 @@ QString CollectionModel::ContainerKey(const GroupBy type, const Song &song) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CollectionModel::DividerKey(const GroupBy type, CollectionItem *item) {
|
QString CollectionModel::DividerKey(const GroupBy group_by, CollectionItem *item) {
|
||||||
|
|
||||||
// Items which are to be grouped under the same divider must produce the same divider key. This will only get called for top-level items.
|
// Items which are to be grouped under the same divider must produce the same divider key. This will only get called for top-level items.
|
||||||
|
|
||||||
if (item->sort_text.isEmpty()) return QString();
|
if (item->sort_text.isEmpty()) return QString();
|
||||||
|
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:
|
case GroupBy_AlbumArtist:
|
||||||
case GroupBy_Artist:
|
case GroupBy_Artist:
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:
|
||||||
|
@ -461,16 +446,16 @@ QString CollectionModel::DividerKey(const GroupBy type, CollectionItem *item) {
|
||||||
case GroupByCount:
|
case GroupByCount:
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
qLog(Error) << "Unknown GroupBy type" << type << "for item" << item->display_text;
|
qLog(Error) << "Unknown GroupBy" << group_by << "for item" << item->display_text;
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CollectionModel::DividerDisplayText(const GroupBy type, const QString &key) {
|
QString CollectionModel::DividerDisplayText(const GroupBy group_by, const QString &key) {
|
||||||
|
|
||||||
// Pretty display text for the dividers.
|
// Pretty display text for the dividers.
|
||||||
|
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:
|
case GroupBy_AlbumArtist:
|
||||||
case GroupBy_Artist:
|
case GroupBy_Artist:
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:
|
||||||
|
@ -513,7 +498,7 @@ QString CollectionModel::DividerDisplayText(const GroupBy type, const QString &k
|
||||||
case GroupByCount:
|
case GroupByCount:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
qLog(Error) << "Unknown GroupBy type" << type << "for divider key" << key;
|
qLog(Error) << "Unknown GroupBy" << group_by << "for divider key" << key;
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -726,8 +711,8 @@ QVariant CollectionModel::data(const QModelIndex &idx, const int role) const {
|
||||||
if (use_pretty_covers_) {
|
if (use_pretty_covers_) {
|
||||||
bool is_album_node = false;
|
bool is_album_node = false;
|
||||||
if (role == Qt::DecorationRole && item->type == CollectionItem::Type_Container) {
|
if (role == Qt::DecorationRole && item->type == CollectionItem::Type_Container) {
|
||||||
GroupBy container_type = group_by_[item->container_level];
|
GroupBy container_group_by = group_by_[item->container_level];
|
||||||
is_album_node = IsAlbumGroupBy(container_type);
|
is_album_node = IsAlbumGroupBy(container_group_by);
|
||||||
}
|
}
|
||||||
if (is_album_node) {
|
if (is_album_node) {
|
||||||
// It has const behaviour some of the time - that's ok right?
|
// It has const behaviour some of the time - that's ok right?
|
||||||
|
@ -741,7 +726,7 @@ QVariant CollectionModel::data(const QModelIndex &idx, const int role) const {
|
||||||
|
|
||||||
QVariant CollectionModel::data(const CollectionItem *item, const int role) const {
|
QVariant CollectionModel::data(const CollectionItem *item, const int role) const {
|
||||||
|
|
||||||
GroupBy container_type = item->type == CollectionItem::Type_Container ? group_by_[item->container_level] : GroupBy_None;
|
GroupBy container_group_by = item->type == CollectionItem::Type_Container ? group_by_[item->container_level] : GroupBy_None;
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
|
@ -751,7 +736,7 @@ QVariant CollectionModel::data(const CollectionItem *item, const int role) const
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case CollectionItem::Type_Container:
|
case CollectionItem::Type_Container:
|
||||||
switch (container_type) {
|
switch (container_group_by) {
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:
|
||||||
case GroupBy_AlbumDisc:
|
case GroupBy_AlbumDisc:
|
||||||
case GroupBy_YearAlbum:
|
case GroupBy_YearAlbum:
|
||||||
|
@ -778,7 +763,7 @@ QVariant CollectionModel::data(const CollectionItem *item, const int role) const
|
||||||
return item->type == CollectionItem::Type_Divider;
|
return item->type == CollectionItem::Type_Divider;
|
||||||
|
|
||||||
case Role_ContainerType:
|
case Role_ContainerType:
|
||||||
return container_type;
|
return container_group_by;
|
||||||
|
|
||||||
case Role_Key:
|
case Role_Key:
|
||||||
return item->key;
|
return item->key;
|
||||||
|
@ -849,26 +834,26 @@ CollectionModel::QueryResult CollectionModel::RunQuery(CollectionItem *parent) {
|
||||||
|
|
||||||
// Information about what we want the children to be
|
// Information about what we want the children to be
|
||||||
int child_level = parent == root_ ? 0 : parent->container_level + 1;
|
int child_level = parent == root_ ? 0 : parent->container_level + 1;
|
||||||
GroupBy child_type = child_level >= 3 ? GroupBy_None : group_by_[child_level];
|
GroupBy child_group_by = child_level >= 3 ? GroupBy_None : group_by_[child_level];
|
||||||
|
|
||||||
// Initialize the query. child_type says what type of thing we want (artists, songs, etc.)
|
// Initialize the query. child_group_by says what type of thing we want (artists, songs, etc.)
|
||||||
|
|
||||||
{
|
{
|
||||||
QMutexLocker l(backend_->db()->Mutex());
|
QMutexLocker l(backend_->db()->Mutex());
|
||||||
QSqlDatabase db(backend_->db()->Connect());
|
QSqlDatabase db(backend_->db()->Connect());
|
||||||
|
|
||||||
CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_);
|
CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_);
|
||||||
InitQuery(child_type, &q);
|
InitQuery(child_group_by, separate_albums_by_grouping_, &q);
|
||||||
|
|
||||||
// Walk up through the item's parents adding filters as necessary
|
// Walk up through the item's parents adding filters as necessary
|
||||||
CollectionItem *p = parent;
|
CollectionItem *p = parent;
|
||||||
while (p && p->type == CollectionItem::Type_Container) {
|
while (p && p->type == CollectionItem::Type_Container) {
|
||||||
FilterQuery(group_by_[p->container_level], p, &q);
|
FilterQuery(group_by_[p->container_level], separate_albums_by_grouping_, p, &q);
|
||||||
p = p->parent;
|
p = p->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Artists GroupBy is special - we don't want compilation albums appearing
|
// Artists GroupBy is special - we don't want compilation albums appearing
|
||||||
if (IsArtistGroupBy(child_type)) {
|
if (IsArtistGroupBy(child_group_by)) {
|
||||||
// Add the special Various artists node
|
// Add the special Various artists node
|
||||||
if (show_various_artists_ && HasCompilations(db, q)) {
|
if (show_various_artists_ && HasCompilations(db, q)) {
|
||||||
result.create_va = true;
|
result.create_va = true;
|
||||||
|
@ -902,7 +887,7 @@ void CollectionModel::PostQuery(CollectionItem *parent, const CollectionModel::Q
|
||||||
|
|
||||||
// Information about what we want the children to be
|
// Information about what we want the children to be
|
||||||
int child_level = parent == root_ ? 0 : parent->container_level + 1;
|
int child_level = parent == root_ ? 0 : parent->container_level + 1;
|
||||||
GroupBy child_type = child_level >= 3 ? GroupBy_None : group_by_[child_level];
|
GroupBy child_group_by = child_level >= 3 ? GroupBy_None : group_by_[child_level];
|
||||||
|
|
||||||
if (result.create_va && parent->compilation_artist_node_ == nullptr) {
|
if (result.create_va && parent->compilation_artist_node_ == nullptr) {
|
||||||
CreateCompilationArtistNode(signal, parent);
|
CreateCompilationArtistNode(signal, parent);
|
||||||
|
@ -911,10 +896,10 @@ void CollectionModel::PostQuery(CollectionItem *parent, const CollectionModel::Q
|
||||||
// Step through the results
|
// Step through the results
|
||||||
for (const SqlRow &row : result.rows) {
|
for (const SqlRow &row : result.rows) {
|
||||||
// Create the item - it will get inserted into the model here
|
// Create the item - it will get inserted into the model here
|
||||||
CollectionItem *item = ItemFromQuery(child_type, signal, child_level == 0, parent, row, child_level);
|
CollectionItem *item = ItemFromQuery(child_group_by, separate_albums_by_grouping_, signal, child_level == 0, parent, row, child_level);
|
||||||
|
|
||||||
// Save a pointer to it for later
|
// Save a pointer to it for later
|
||||||
if (child_type == GroupBy_None) {
|
if (child_group_by == GroupBy_None) {
|
||||||
song_nodes_.insert(item->metadata.id(), item);
|
song_nodes_.insert(item->metadata.id(), item);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1002,34 +987,52 @@ void CollectionModel::Reset() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::InitQuery(const GroupBy type, CollectionQuery *q) {
|
void CollectionModel::InitQuery(const GroupBy group_by, const bool separate_albums_by_grouping, CollectionQuery *q) {
|
||||||
|
|
||||||
// Say what type of thing we want to get back from the database.
|
// Say what group_by of thing we want to get back from the database.
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:
|
case GroupBy_AlbumArtist:
|
||||||
q->SetColumnSpec("DISTINCT effective_albumartist");
|
q->SetColumnSpec("DISTINCT effective_albumartist");
|
||||||
break;
|
break;
|
||||||
case GroupBy_Artist:
|
case GroupBy_Artist:
|
||||||
q->SetColumnSpec("DISTINCT artist");
|
q->SetColumnSpec("DISTINCT artist");
|
||||||
break;
|
break;
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:{
|
||||||
q->SetColumnSpec("DISTINCT album, album_id, grouping");
|
QString query("DISTINCT album, album_id");
|
||||||
|
if (separate_albums_by_grouping) query.append(", grouping");
|
||||||
|
q->SetColumnSpec(query);
|
||||||
break;
|
break;
|
||||||
case GroupBy_AlbumDisc:
|
}
|
||||||
q->SetColumnSpec("DISTINCT album, album_id, disc, grouping");
|
case GroupBy_AlbumDisc:{
|
||||||
|
QString query("DISTINCT album, album_id, disc");
|
||||||
|
if (separate_albums_by_grouping) query.append(", grouping");
|
||||||
|
q->SetColumnSpec(query);
|
||||||
break;
|
break;
|
||||||
case GroupBy_YearAlbum:
|
}
|
||||||
q->SetColumnSpec("DISTINCT year, album, album_id, grouping");
|
case GroupBy_YearAlbum:{
|
||||||
|
QString query("DISTINCT year, album, album_id");
|
||||||
|
if (separate_albums_by_grouping) query.append(", grouping");
|
||||||
|
q->SetColumnSpec(query);
|
||||||
break;
|
break;
|
||||||
case GroupBy_YearAlbumDisc:
|
}
|
||||||
q->SetColumnSpec("DISTINCT year, album, album_id, disc, grouping");
|
case GroupBy_YearAlbumDisc:{
|
||||||
|
QString query("DISTINCT year, album, album_id, disc");
|
||||||
|
if (separate_albums_by_grouping) query.append(", grouping");
|
||||||
|
q->SetColumnSpec(query);
|
||||||
break;
|
break;
|
||||||
case GroupBy_OriginalYearAlbum:
|
}
|
||||||
q->SetColumnSpec("DISTINCT year, originalyear, album, album_id, grouping");
|
case GroupBy_OriginalYearAlbum:{
|
||||||
|
QString query("DISTINCT year, originalyear, album, album_id");
|
||||||
|
if (separate_albums_by_grouping) query.append(", grouping");
|
||||||
|
q->SetColumnSpec(query);
|
||||||
break;
|
break;
|
||||||
case GroupBy_OriginalYearAlbumDisc:
|
}
|
||||||
q->SetColumnSpec("DISTINCT year, originalyear, album, album_id, disc, grouping");
|
case GroupBy_OriginalYearAlbumDisc:{
|
||||||
|
QString query("DISTINCT year, originalyear, album, album_id, disc");
|
||||||
|
if (separate_albums_by_grouping) query.append(", grouping");
|
||||||
|
q->SetColumnSpec(query);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GroupBy_Disc:
|
case GroupBy_Disc:
|
||||||
q->SetColumnSpec("DISTINCT disc");
|
q->SetColumnSpec("DISTINCT disc");
|
||||||
break;
|
break;
|
||||||
|
@ -1074,11 +1077,11 @@ void CollectionModel::InitQuery(const GroupBy type, CollectionQuery *q) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, CollectionQuery *q) {
|
void CollectionModel::FilterQuery(const GroupBy group_by, const bool separate_albums_by_grouping, CollectionItem *item, CollectionQuery *q) {
|
||||||
|
|
||||||
// Say how we want the query to be filtered. This is done once for each parent going up the tree.
|
// Say how we want the query to be filtered. This is done once for each parent going up the tree.
|
||||||
|
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:
|
case GroupBy_AlbumArtist:
|
||||||
if (IsCompilationArtistNode(item)) {
|
if (IsCompilationArtistNode(item)) {
|
||||||
q->AddCompilationRequirement(true);
|
q->AddCompilationRequirement(true);
|
||||||
|
@ -1102,33 +1105,33 @@ void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, Coll
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:
|
||||||
q->AddWhere("album", item->metadata.album());
|
q->AddWhere("album", item->metadata.album());
|
||||||
q->AddWhere("album_id", item->metadata.album_id());
|
q->AddWhere("album_id", item->metadata.album_id());
|
||||||
q->AddWhere("grouping", item->metadata.grouping());
|
if (separate_albums_by_grouping) q->AddWhere("grouping", item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_AlbumDisc:
|
case GroupBy_AlbumDisc:
|
||||||
q->AddWhere("album", item->metadata.album());
|
q->AddWhere("album", item->metadata.album());
|
||||||
q->AddWhere("album_id", item->metadata.album_id());
|
q->AddWhere("album_id", item->metadata.album_id());
|
||||||
q->AddWhere("disc", item->metadata.disc());
|
q->AddWhere("disc", item->metadata.disc());
|
||||||
q->AddWhere("grouping", item->metadata.grouping());
|
if (separate_albums_by_grouping) q->AddWhere("grouping", item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_YearAlbum:
|
case GroupBy_YearAlbum:
|
||||||
q->AddWhere("year", item->metadata.year());
|
q->AddWhere("year", item->metadata.year());
|
||||||
q->AddWhere("album", item->metadata.album());
|
q->AddWhere("album", item->metadata.album());
|
||||||
q->AddWhere("album_id", item->metadata.album_id());
|
q->AddWhere("album_id", item->metadata.album_id());
|
||||||
q->AddWhere("grouping", item->metadata.grouping());
|
if (separate_albums_by_grouping) q->AddWhere("grouping", item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_YearAlbumDisc:
|
case GroupBy_YearAlbumDisc:
|
||||||
q->AddWhere("year", item->metadata.year());
|
q->AddWhere("year", item->metadata.year());
|
||||||
q->AddWhere("album", item->metadata.album());
|
q->AddWhere("album", item->metadata.album());
|
||||||
q->AddWhere("album_id", item->metadata.album_id());
|
q->AddWhere("album_id", item->metadata.album_id());
|
||||||
q->AddWhere("disc", item->metadata.disc());
|
q->AddWhere("disc", item->metadata.disc());
|
||||||
q->AddWhere("grouping", item->metadata.grouping());
|
if (separate_albums_by_grouping) q->AddWhere("grouping", item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_OriginalYearAlbum:
|
case GroupBy_OriginalYearAlbum:
|
||||||
q->AddWhere("year", item->metadata.year());
|
q->AddWhere("year", item->metadata.year());
|
||||||
q->AddWhere("originalyear", item->metadata.originalyear());
|
q->AddWhere("originalyear", item->metadata.originalyear());
|
||||||
q->AddWhere("album", item->metadata.album());
|
q->AddWhere("album", item->metadata.album());
|
||||||
q->AddWhere("album_id", item->metadata.album_id());
|
q->AddWhere("album_id", item->metadata.album_id());
|
||||||
q->AddWhere("grouping", item->metadata.grouping());
|
if (separate_albums_by_grouping) q->AddWhere("grouping", item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_OriginalYearAlbumDisc:
|
case GroupBy_OriginalYearAlbumDisc:
|
||||||
q->AddWhere("year", item->metadata.year());
|
q->AddWhere("year", item->metadata.year());
|
||||||
|
@ -1136,7 +1139,7 @@ void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, Coll
|
||||||
q->AddWhere("album", item->metadata.album());
|
q->AddWhere("album", item->metadata.album());
|
||||||
q->AddWhere("album_id", item->metadata.album_id());
|
q->AddWhere("album_id", item->metadata.album_id());
|
||||||
q->AddWhere("disc", item->metadata.disc());
|
q->AddWhere("disc", item->metadata.disc());
|
||||||
q->AddWhere("grouping", item->metadata.grouping());
|
if (separate_albums_by_grouping) q->AddWhere("grouping", item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
case GroupBy_Disc:
|
case GroupBy_Disc:
|
||||||
q->AddWhere("disc", item->metadata.disc());
|
q->AddWhere("disc", item->metadata.disc());
|
||||||
|
@ -1178,15 +1181,15 @@ void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, Coll
|
||||||
break;
|
break;
|
||||||
case GroupBy_None:
|
case GroupBy_None:
|
||||||
case GroupByCount:
|
case GroupByCount:
|
||||||
qLog(Error) << "Unknown GroupBy type" << type << "used in filter";
|
qLog(Error) << "Unknown GroupBy" << group_by << "used in filter";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionItem *CollectionModel::InitItem(const GroupBy type, const bool signal, CollectionItem *parent, const int container_level) {
|
CollectionItem *CollectionModel::InitItem(const GroupBy group_by, const bool signal, CollectionItem *parent, const int container_level) {
|
||||||
|
|
||||||
CollectionItem::Type item_type = type == GroupBy_None ? CollectionItem::Type_Song : CollectionItem::Type_Container;
|
CollectionItem::Type item_type = group_by == GroupBy_None ? CollectionItem::Type_Song : CollectionItem::Type_Container;
|
||||||
|
|
||||||
if (signal) beginInsertRows(ItemToIndex(parent), static_cast<int>(parent->children.count()), static_cast<int>(parent->children.count()));
|
if (signal) beginInsertRows(ItemToIndex(parent), static_cast<int>(parent->children.count()), static_cast<int>(parent->children.count()));
|
||||||
|
|
||||||
|
@ -1199,25 +1202,25 @@ CollectionItem *CollectionModel::InitItem(const GroupBy type, const bool signal,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const SqlRow &row, const int container_level) {
|
CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const bool separate_albums_by_grouping, const bool signal, const bool create_divider, CollectionItem *parent, const SqlRow &row, const int container_level) {
|
||||||
|
|
||||||
CollectionItem *item = InitItem(type, signal, parent, container_level);
|
CollectionItem *item = InitItem(group_by, signal, parent, container_level);
|
||||||
|
|
||||||
if (parent != root_ && !parent->key.isEmpty()) {
|
if (parent != root_ && !parent->key.isEmpty()) {
|
||||||
item->key = parent->key + "-";
|
item->key = parent->key + "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:{
|
case GroupBy_AlbumArtist:{
|
||||||
item->metadata.set_albumartist(row.value(0).toString());
|
item->metadata.set_albumartist(row.value(0).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.albumartist());
|
item->display_text = TextOrUnknown(item->metadata.albumartist());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.albumartist());
|
item->sort_text = SortTextForArtist(item->metadata.albumartist());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Artist:{
|
case GroupBy_Artist:{
|
||||||
item->metadata.set_artist(row.value(0).toString());
|
item->metadata.set_artist(row.value(0).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.artist());
|
item->display_text = TextOrUnknown(item->metadata.artist());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.artist());
|
item->sort_text = SortTextForArtist(item->metadata.artist());
|
||||||
break;
|
break;
|
||||||
|
@ -1226,7 +1229,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_album(row.value(0).toString());
|
item->metadata.set_album(row.value(0).toString());
|
||||||
item->metadata.set_album_id(row.value(1).toString());
|
item->metadata.set_album_id(row.value(1).toString());
|
||||||
item->metadata.set_grouping(row.value(2).toString());
|
item->metadata.set_grouping(row.value(2).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.album());
|
item->display_text = TextOrUnknown(item->metadata.album());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.album());
|
item->sort_text = SortTextForArtist(item->metadata.album());
|
||||||
break;
|
break;
|
||||||
|
@ -1236,7 +1239,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_album_id(row.value(1).toString());
|
item->metadata.set_album_id(row.value(1).toString());
|
||||||
item->metadata.set_disc(row.value(2).toInt());
|
item->metadata.set_disc(row.value(2).toInt());
|
||||||
item->metadata.set_grouping(row.value(3).toString());
|
item->metadata.set_grouping(row.value(3).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = PrettyAlbumDisc(item->metadata.album(), item->metadata.disc());
|
item->display_text = PrettyAlbumDisc(item->metadata.album(), item->metadata.disc());
|
||||||
item->sort_text = item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
|
item->sort_text = item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
|
||||||
break;
|
break;
|
||||||
|
@ -1246,7 +1249,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_album(row.value(1).toString());
|
item->metadata.set_album(row.value(1).toString());
|
||||||
item->metadata.set_album_id(row.value(2).toString());
|
item->metadata.set_album_id(row.value(2).toString());
|
||||||
item->metadata.set_grouping(row.value(3).toString());
|
item->metadata.set_grouping(row.value(3).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = PrettyYearAlbum(item->metadata.year(), item->metadata.album());
|
item->display_text = PrettyYearAlbum(item->metadata.year(), item->metadata.album());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, item->metadata.year())) + item->metadata.grouping() + item->metadata.album();
|
item->sort_text = SortTextForNumber(qMax(0, item->metadata.year())) + item->metadata.grouping() + item->metadata.album();
|
||||||
break;
|
break;
|
||||||
|
@ -1257,7 +1260,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_album_id(row.value(2).toString());
|
item->metadata.set_album_id(row.value(2).toString());
|
||||||
item->metadata.set_disc(row.value(3).toInt());
|
item->metadata.set_disc(row.value(3).toInt());
|
||||||
item->metadata.set_grouping(row.value(4).toString());
|
item->metadata.set_grouping(row.value(4).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = PrettyYearAlbumDisc(item->metadata.year(), item->metadata.album(), item->metadata.disc());
|
item->display_text = PrettyYearAlbumDisc(item->metadata.year(), item->metadata.album(), item->metadata.disc());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, item->metadata.year())) + item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
|
item->sort_text = SortTextForNumber(qMax(0, item->metadata.year())) + item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
|
||||||
break;
|
break;
|
||||||
|
@ -1268,7 +1271,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_album(row.value(2).toString());
|
item->metadata.set_album(row.value(2).toString());
|
||||||
item->metadata.set_album_id(row.value(3).toString());
|
item->metadata.set_album_id(row.value(3).toString());
|
||||||
item->metadata.set_grouping(row.value(4).toString());
|
item->metadata.set_grouping(row.value(4).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = PrettyYearAlbum(item->metadata.effective_originalyear(), item->metadata.album());
|
item->display_text = PrettyYearAlbum(item->metadata.effective_originalyear(), item->metadata.album());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, item->metadata.effective_originalyear())) + item->metadata.grouping() + item->metadata.album();
|
item->sort_text = SortTextForNumber(qMax(0, item->metadata.effective_originalyear())) + item->metadata.grouping() + item->metadata.album();
|
||||||
break;
|
break;
|
||||||
|
@ -1280,14 +1283,14 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_album_id(row.value(3).toString());
|
item->metadata.set_album_id(row.value(3).toString());
|
||||||
item->metadata.set_disc(row.value(4).toInt());
|
item->metadata.set_disc(row.value(4).toInt());
|
||||||
item->metadata.set_grouping(row.value(5).toString());
|
item->metadata.set_grouping(row.value(5).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = PrettyYearAlbumDisc(item->metadata.effective_originalyear(), item->metadata.album(), item->metadata.disc());
|
item->display_text = PrettyYearAlbumDisc(item->metadata.effective_originalyear(), item->metadata.album(), item->metadata.disc());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, item->metadata.effective_originalyear())) + item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
|
item->sort_text = SortTextForNumber(qMax(0, item->metadata.effective_originalyear())) + item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Disc:{
|
case GroupBy_Disc:{
|
||||||
item->metadata.set_disc(row.value(0).toInt());
|
item->metadata.set_disc(row.value(0).toInt());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
const int disc = qMax(0, row.value(0).toInt());
|
const int disc = qMax(0, row.value(0).toInt());
|
||||||
item->display_text = PrettyDisc(disc);
|
item->display_text = PrettyDisc(disc);
|
||||||
item->sort_text = SortTextForNumber(disc);
|
item->sort_text = SortTextForNumber(disc);
|
||||||
|
@ -1295,7 +1298,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
}
|
}
|
||||||
case GroupBy_Year:{
|
case GroupBy_Year:{
|
||||||
item->metadata.set_year(row.value(0).toInt());
|
item->metadata.set_year(row.value(0).toInt());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
const int year = qMax(0, item->metadata.year());
|
const int year = qMax(0, item->metadata.year());
|
||||||
item->display_text = QString::number(year);
|
item->display_text = QString::number(year);
|
||||||
item->sort_text = SortTextForNumber(year) + " ";
|
item->sort_text = SortTextForNumber(year) + " ";
|
||||||
|
@ -1303,7 +1306,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
}
|
}
|
||||||
case GroupBy_OriginalYear:{
|
case GroupBy_OriginalYear:{
|
||||||
item->metadata.set_originalyear(row.value(0).toInt());
|
item->metadata.set_originalyear(row.value(0).toInt());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
const int year = qMax(0, item->metadata.originalyear());
|
const int year = qMax(0, item->metadata.originalyear());
|
||||||
item->display_text = QString::number(year);
|
item->display_text = QString::number(year);
|
||||||
item->sort_text = SortTextForNumber(year) + " ";
|
item->sort_text = SortTextForNumber(year) + " ";
|
||||||
|
@ -1311,35 +1314,35 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
}
|
}
|
||||||
case GroupBy_Genre:{
|
case GroupBy_Genre:{
|
||||||
item->metadata.set_genre(row.value(0).toString());
|
item->metadata.set_genre(row.value(0).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.genre());
|
item->display_text = TextOrUnknown(item->metadata.genre());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.genre());
|
item->sort_text = SortTextForArtist(item->metadata.genre());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Composer:{
|
case GroupBy_Composer:{
|
||||||
item->metadata.set_composer(row.value(0).toString());
|
item->metadata.set_composer(row.value(0).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.composer());
|
item->display_text = TextOrUnknown(item->metadata.composer());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.composer());
|
item->sort_text = SortTextForArtist(item->metadata.composer());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Performer:{
|
case GroupBy_Performer:{
|
||||||
item->metadata.set_performer(row.value(0).toString());
|
item->metadata.set_performer(row.value(0).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.performer());
|
item->display_text = TextOrUnknown(item->metadata.performer());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.performer());
|
item->sort_text = SortTextForArtist(item->metadata.performer());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Grouping:{
|
case GroupBy_Grouping:{
|
||||||
item->metadata.set_grouping(row.value(0).toString());
|
item->metadata.set_grouping(row.value(0).toString());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = TextOrUnknown(item->metadata.grouping());
|
item->display_text = TextOrUnknown(item->metadata.grouping());
|
||||||
item->sort_text = SortTextForArtist(item->metadata.grouping());
|
item->sort_text = SortTextForArtist(item->metadata.grouping());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_FileType:{
|
case GroupBy_FileType:{
|
||||||
item->metadata.set_filetype(static_cast<Song::FileType>(row.value(0).toInt()));
|
item->metadata.set_filetype(static_cast<Song::FileType>(row.value(0).toInt()));
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
item->display_text = item->metadata.TextForFiletype();
|
item->display_text = item->metadata.TextForFiletype();
|
||||||
item->sort_text = item->metadata.TextForFiletype();
|
item->sort_text = item->metadata.TextForFiletype();
|
||||||
break;
|
break;
|
||||||
|
@ -1348,7 +1351,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
item->metadata.set_filetype(static_cast<Song::FileType>(row.value(0).toInt()));
|
item->metadata.set_filetype(static_cast<Song::FileType>(row.value(0).toInt()));
|
||||||
item->metadata.set_samplerate(row.value(1).toInt());
|
item->metadata.set_samplerate(row.value(1).toInt());
|
||||||
item->metadata.set_bitdepth(row.value(2).toInt());
|
item->metadata.set_bitdepth(row.value(2).toInt());
|
||||||
QString key = ContainerKey(type, item->metadata);
|
QString key = ContainerKey(group_by, separate_albums_by_grouping, item->metadata);
|
||||||
item->key.append(key);
|
item->key.append(key);
|
||||||
item->display_text = key;
|
item->display_text = key;
|
||||||
item->sort_text = key;
|
item->sort_text = key;
|
||||||
|
@ -1356,7 +1359,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
}
|
}
|
||||||
case GroupBy_Samplerate:{
|
case GroupBy_Samplerate:{
|
||||||
item->metadata.set_samplerate(row.value(0).toInt());
|
item->metadata.set_samplerate(row.value(0).toInt());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
const int samplerate = qMax(0, item->metadata.samplerate());
|
const int samplerate = qMax(0, item->metadata.samplerate());
|
||||||
item->display_text = QString::number(samplerate);
|
item->display_text = QString::number(samplerate);
|
||||||
item->sort_text = SortTextForNumber(samplerate) + " ";
|
item->sort_text = SortTextForNumber(samplerate) + " ";
|
||||||
|
@ -1364,7 +1367,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
}
|
}
|
||||||
case GroupBy_Bitdepth:{
|
case GroupBy_Bitdepth:{
|
||||||
item->metadata.set_bitdepth(row.value(0).toInt());
|
item->metadata.set_bitdepth(row.value(0).toInt());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
const int bitdepth = qMax(0, item->metadata.bitdepth());
|
const int bitdepth = qMax(0, item->metadata.bitdepth());
|
||||||
item->display_text = QString::number(bitdepth);
|
item->display_text = QString::number(bitdepth);
|
||||||
item->sort_text = SortTextForNumber(bitdepth) + " ";
|
item->sort_text = SortTextForNumber(bitdepth) + " ";
|
||||||
|
@ -1372,7 +1375,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
}
|
}
|
||||||
case GroupBy_Bitrate:{
|
case GroupBy_Bitrate:{
|
||||||
item->metadata.set_bitrate(row.value(0).toInt());
|
item->metadata.set_bitrate(row.value(0).toInt());
|
||||||
item->key.append(ContainerKey(type, item->metadata));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
|
||||||
const int bitrate = qMax(0, item->metadata.bitrate());
|
const int bitrate = qMax(0, item->metadata.bitrate());
|
||||||
item->display_text = QString::number(bitrate);
|
item->display_text = QString::number(bitrate);
|
||||||
item->sort_text = SortTextForNumber(bitrate) + " ";
|
item->sort_text = SortTextForNumber(bitrate) + " ";
|
||||||
|
@ -1392,31 +1395,31 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FinishItem(type, signal, create_divider, parent, item);
|
FinishItem(group_by, signal, create_divider, parent, item);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const Song &s, const int container_level) {
|
CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool separate_albums_by_grouping, const bool signal, const bool create_divider, CollectionItem *parent, const Song &s, const int container_level) {
|
||||||
|
|
||||||
CollectionItem *item = InitItem(type, signal, parent, container_level);
|
CollectionItem *item = InitItem(group_by, signal, parent, container_level);
|
||||||
|
|
||||||
if (parent != root_ && !parent->key.isEmpty()) {
|
if (parent != root_ && !parent->key.isEmpty()) {
|
||||||
item->key = parent->key + "-";
|
item->key = parent->key + "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (group_by) {
|
||||||
case GroupBy_AlbumArtist:{
|
case GroupBy_AlbumArtist:{
|
||||||
item->metadata.set_albumartist(s.effective_albumartist());
|
item->metadata.set_albumartist(s.effective_albumartist());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.effective_albumartist());
|
item->display_text = TextOrUnknown(s.effective_albumartist());
|
||||||
item->sort_text = SortTextForArtist(s.effective_albumartist());
|
item->sort_text = SortTextForArtist(s.effective_albumartist());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Artist:{
|
case GroupBy_Artist:{
|
||||||
item->metadata.set_artist(s.artist());
|
item->metadata.set_artist(s.artist());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.artist());
|
item->display_text = TextOrUnknown(s.artist());
|
||||||
item->sort_text = SortTextForArtist(s.artist());
|
item->sort_text = SortTextForArtist(s.artist());
|
||||||
break;
|
break;
|
||||||
|
@ -1425,7 +1428,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_album(s.album());
|
item->metadata.set_album(s.album());
|
||||||
item->metadata.set_album_id(s.album_id());
|
item->metadata.set_album_id(s.album_id());
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.album());
|
item->display_text = TextOrUnknown(s.album());
|
||||||
item->sort_text = SortTextForArtist(s.album());
|
item->sort_text = SortTextForArtist(s.album());
|
||||||
break;
|
break;
|
||||||
|
@ -1435,7 +1438,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_album_id(s.album_id());
|
item->metadata.set_album_id(s.album_id());
|
||||||
item->metadata.set_disc(s.disc());
|
item->metadata.set_disc(s.disc());
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = PrettyAlbumDisc(s.album(), s.disc());
|
item->display_text = PrettyAlbumDisc(s.album(), s.disc());
|
||||||
item->sort_text = s.album() + SortTextForNumber(qMax(0, s.disc()));
|
item->sort_text = s.album() + SortTextForNumber(qMax(0, s.disc()));
|
||||||
break;
|
break;
|
||||||
|
@ -1445,7 +1448,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_album(s.album());
|
item->metadata.set_album(s.album());
|
||||||
item->metadata.set_album_id(s.album_id());
|
item->metadata.set_album_id(s.album_id());
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = PrettyYearAlbum(s.year(), s.album());
|
item->display_text = PrettyYearAlbum(s.year(), s.album());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, s.year())) + s.grouping() + s.album();
|
item->sort_text = SortTextForNumber(qMax(0, s.year())) + s.grouping() + s.album();
|
||||||
break;
|
break;
|
||||||
|
@ -1456,7 +1459,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_album_id(s.album_id());
|
item->metadata.set_album_id(s.album_id());
|
||||||
item->metadata.set_disc(s.disc());
|
item->metadata.set_disc(s.disc());
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = PrettyYearAlbumDisc(s.year(), s.album(), s.disc());
|
item->display_text = PrettyYearAlbumDisc(s.year(), s.album(), s.disc());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, s.year())) + s.album() + SortTextForNumber(qMax(0, s.disc()));
|
item->sort_text = SortTextForNumber(qMax(0, s.year())) + s.album() + SortTextForNumber(qMax(0, s.disc()));
|
||||||
break;
|
break;
|
||||||
|
@ -1467,7 +1470,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_album(s.album());
|
item->metadata.set_album(s.album());
|
||||||
item->metadata.set_album_id(s.album_id());
|
item->metadata.set_album_id(s.album_id());
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = PrettyYearAlbum(s.effective_originalyear(), s.album());
|
item->display_text = PrettyYearAlbum(s.effective_originalyear(), s.album());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, s.effective_originalyear())) + s.grouping() + s.album();
|
item->sort_text = SortTextForNumber(qMax(0, s.effective_originalyear())) + s.grouping() + s.album();
|
||||||
break;
|
break;
|
||||||
|
@ -1479,14 +1482,14 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_album_id(s.album_id());
|
item->metadata.set_album_id(s.album_id());
|
||||||
item->metadata.set_disc(s.disc());
|
item->metadata.set_disc(s.disc());
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = PrettyYearAlbumDisc(s.effective_originalyear(), s.album(), s.disc());
|
item->display_text = PrettyYearAlbumDisc(s.effective_originalyear(), s.album(), s.disc());
|
||||||
item->sort_text = SortTextForNumber(qMax(0, s.effective_originalyear())) + s.album() + SortTextForNumber(qMax(0, s.disc()));
|
item->sort_text = SortTextForNumber(qMax(0, s.effective_originalyear())) + s.album() + SortTextForNumber(qMax(0, s.disc()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Disc:{
|
case GroupBy_Disc:{
|
||||||
item->metadata.set_disc(s.disc());
|
item->metadata.set_disc(s.disc());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
const int disc = qMax(0, s.disc());
|
const int disc = qMax(0, s.disc());
|
||||||
item->display_text = PrettyDisc(disc);
|
item->display_text = PrettyDisc(disc);
|
||||||
item->sort_text = SortTextForNumber(disc);
|
item->sort_text = SortTextForNumber(disc);
|
||||||
|
@ -1494,7 +1497,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
case GroupBy_Year:{
|
case GroupBy_Year:{
|
||||||
item->metadata.set_year(s.year());
|
item->metadata.set_year(s.year());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
const int year = qMax(0, s.year());
|
const int year = qMax(0, s.year());
|
||||||
item->display_text = QString::number(year);
|
item->display_text = QString::number(year);
|
||||||
item->sort_text = SortTextForNumber(year) + " ";
|
item->sort_text = SortTextForNumber(year) + " ";
|
||||||
|
@ -1502,7 +1505,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
case GroupBy_OriginalYear:{
|
case GroupBy_OriginalYear:{
|
||||||
item->metadata.set_originalyear(s.effective_originalyear());
|
item->metadata.set_originalyear(s.effective_originalyear());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
const int year = qMax(0, s.effective_originalyear());
|
const int year = qMax(0, s.effective_originalyear());
|
||||||
item->display_text = QString::number(year);
|
item->display_text = QString::number(year);
|
||||||
item->sort_text = SortTextForNumber(year) + " ";
|
item->sort_text = SortTextForNumber(year) + " ";
|
||||||
|
@ -1510,35 +1513,35 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
case GroupBy_Genre:{
|
case GroupBy_Genre:{
|
||||||
item->metadata.set_genre(s.genre());
|
item->metadata.set_genre(s.genre());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.genre());
|
item->display_text = TextOrUnknown(s.genre());
|
||||||
item->sort_text = SortTextForArtist(s.genre());
|
item->sort_text = SortTextForArtist(s.genre());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Composer:{
|
case GroupBy_Composer:{
|
||||||
item->metadata.set_composer(s.composer());
|
item->metadata.set_composer(s.composer());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.composer());
|
item->display_text = TextOrUnknown(s.composer());
|
||||||
item->sort_text = SortTextForArtist(s.composer());
|
item->sort_text = SortTextForArtist(s.composer());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Performer:{
|
case GroupBy_Performer:{
|
||||||
item->metadata.set_performer(s.performer());
|
item->metadata.set_performer(s.performer());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.performer());
|
item->display_text = TextOrUnknown(s.performer());
|
||||||
item->sort_text = SortTextForArtist(s.performer());
|
item->sort_text = SortTextForArtist(s.performer());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_Grouping:{
|
case GroupBy_Grouping:{
|
||||||
item->metadata.set_grouping(s.grouping());
|
item->metadata.set_grouping(s.grouping());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = TextOrUnknown(s.grouping());
|
item->display_text = TextOrUnknown(s.grouping());
|
||||||
item->sort_text = SortTextForArtist(s.grouping());
|
item->sort_text = SortTextForArtist(s.grouping());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroupBy_FileType:{
|
case GroupBy_FileType:{
|
||||||
item->metadata.set_filetype(s.filetype());
|
item->metadata.set_filetype(s.filetype());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
item->display_text = s.TextForFiletype();
|
item->display_text = s.TextForFiletype();
|
||||||
item->sort_text = s.TextForFiletype();
|
item->sort_text = s.TextForFiletype();
|
||||||
break;
|
break;
|
||||||
|
@ -1547,7 +1550,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
item->metadata.set_filetype(s.filetype());
|
item->metadata.set_filetype(s.filetype());
|
||||||
item->metadata.set_samplerate(s.samplerate());
|
item->metadata.set_samplerate(s.samplerate());
|
||||||
item->metadata.set_bitdepth(s.bitdepth());
|
item->metadata.set_bitdepth(s.bitdepth());
|
||||||
QString key = ContainerKey(type, s);
|
QString key = ContainerKey(group_by, separate_albums_by_grouping, s);
|
||||||
item->key.append(key);
|
item->key.append(key);
|
||||||
item->display_text = key;
|
item->display_text = key;
|
||||||
item->sort_text = key;
|
item->sort_text = key;
|
||||||
|
@ -1555,7 +1558,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
case GroupBy_Samplerate:{
|
case GroupBy_Samplerate:{
|
||||||
item->metadata.set_samplerate(s.samplerate());
|
item->metadata.set_samplerate(s.samplerate());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
const int samplerate = qMax(0, s.samplerate());
|
const int samplerate = qMax(0, s.samplerate());
|
||||||
item->display_text = QString::number(samplerate);
|
item->display_text = QString::number(samplerate);
|
||||||
item->sort_text = SortTextForNumber(samplerate) + " ";
|
item->sort_text = SortTextForNumber(samplerate) + " ";
|
||||||
|
@ -1563,7 +1566,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
case GroupBy_Bitdepth:{
|
case GroupBy_Bitdepth:{
|
||||||
item->metadata.set_bitdepth(s.bitdepth());
|
item->metadata.set_bitdepth(s.bitdepth());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
const int bitdepth = qMax(0, s.bitdepth());
|
const int bitdepth = qMax(0, s.bitdepth());
|
||||||
item->display_text = QString::number(bitdepth);
|
item->display_text = QString::number(bitdepth);
|
||||||
item->sort_text = SortTextForNumber(bitdepth) + " ";
|
item->sort_text = SortTextForNumber(bitdepth) + " ";
|
||||||
|
@ -1571,7 +1574,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
case GroupBy_Bitrate:{
|
case GroupBy_Bitrate:{
|
||||||
item->metadata.set_bitrate(s.bitrate());
|
item->metadata.set_bitrate(s.bitrate());
|
||||||
item->key.append(ContainerKey(type, s));
|
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
|
||||||
const int bitrate = qMax(0, s.bitrate());
|
const int bitrate = qMax(0, s.bitrate());
|
||||||
item->display_text = QString::number(bitrate);
|
item->display_text = QString::number(bitrate);
|
||||||
item->sort_text = SortTextForNumber(bitrate) + " ";
|
item->sort_text = SortTextForNumber(bitrate) + " ";
|
||||||
|
@ -1592,16 +1595,16 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FinishItem(type, signal, create_divider, parent, item);
|
FinishItem(group_by, signal, create_divider, parent, item);
|
||||||
if (s.url().scheme() == "cdda") item->lazy_loaded = true;
|
if (s.url().scheme() == "cdda") item->lazy_loaded = true;
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::FinishItem(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, CollectionItem *item) {
|
void CollectionModel::FinishItem(const GroupBy group_by, const bool signal, const bool create_divider, CollectionItem *parent, CollectionItem *item) {
|
||||||
|
|
||||||
if (type == GroupBy_None) item->lazy_loaded = true;
|
if (group_by == GroupBy_None) item->lazy_loaded = true;
|
||||||
|
|
||||||
if (signal) {
|
if (signal) {
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
@ -1609,7 +1612,7 @@ void CollectionModel::FinishItem(const GroupBy type, const bool signal, const bo
|
||||||
|
|
||||||
// Create the divider entry if we're supposed to
|
// Create the divider entry if we're supposed to
|
||||||
if (create_divider && show_dividers_) {
|
if (create_divider && show_dividers_) {
|
||||||
QString divider_key = DividerKey(type, item);
|
QString divider_key = DividerKey(group_by, item);
|
||||||
if (!divider_key.isEmpty()) {
|
if (!divider_key.isEmpty()) {
|
||||||
item->sort_text.prepend(divider_key + " ");
|
item->sort_text.prepend(divider_key + " ");
|
||||||
}
|
}
|
||||||
|
@ -1621,7 +1624,7 @@ void CollectionModel::FinishItem(const GroupBy type, const bool signal, const bo
|
||||||
|
|
||||||
CollectionItem *divider = new CollectionItem(CollectionItem::Type_Divider, root_);
|
CollectionItem *divider = new CollectionItem(CollectionItem::Type_Divider, root_);
|
||||||
divider->key = divider_key;
|
divider->key = divider_key;
|
||||||
divider->display_text = DividerDisplayText(type, divider_key);
|
divider->display_text = DividerDisplayText(group_by, divider_key);
|
||||||
divider->sort_text = divider_key + " ";
|
divider->sort_text = divider_key + " ";
|
||||||
divider->lazy_loaded = true;
|
divider->lazy_loaded = true;
|
||||||
|
|
||||||
|
@ -1875,12 +1878,15 @@ bool CollectionModel::canFetchMore(const QModelIndex &parent) const {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::SetGroupBy(const Grouping g) {
|
void CollectionModel::SetGroupBy(const Grouping g, const std::optional<bool> separate_albums_by_grouping) {
|
||||||
|
|
||||||
group_by_ = g;
|
group_by_ = g;
|
||||||
|
if (separate_albums_by_grouping) {
|
||||||
|
separate_albums_by_grouping_ = separate_albums_by_grouping.value();
|
||||||
|
}
|
||||||
|
|
||||||
ResetAsync();
|
ResetAsync();
|
||||||
emit GroupingChanged(g);
|
emit GroupingChanged(g, separate_albums_by_grouping_);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
@ -64,8 +66,6 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||||
explicit CollectionModel(CollectionBackend *backend, Application *app, QObject *parent = nullptr);
|
explicit CollectionModel(CollectionBackend *backend, Application *app, QObject *parent = nullptr);
|
||||||
~CollectionModel() override;
|
~CollectionModel() override;
|
||||||
|
|
||||||
static const char *kSavedGroupingsSettingsGroup;
|
|
||||||
|
|
||||||
static const int kPrettyCoverSize;
|
static const int kPrettyCoverSize;
|
||||||
static const char *kPixmapDiskCacheDir;
|
static const char *kPixmapDiskCacheDir;
|
||||||
|
|
||||||
|
@ -160,9 +160,6 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||||
// Whether or not to show letters heading in the collection view
|
// Whether or not to show letters heading in the collection view
|
||||||
void set_show_dividers(const bool show_dividers);
|
void set_show_dividers(const bool show_dividers);
|
||||||
|
|
||||||
// Save the current grouping
|
|
||||||
void SaveGrouping(const QString &name);
|
|
||||||
|
|
||||||
// Reload settings.
|
// Reload settings.
|
||||||
void ReloadSettings();
|
void ReloadSettings();
|
||||||
|
|
||||||
|
@ -195,15 +192,15 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||||
void ExpandAll(CollectionItem *item = nullptr) const;
|
void ExpandAll(CollectionItem *item = nullptr) const;
|
||||||
|
|
||||||
const CollectionModel::Grouping GetGroupBy() const { return group_by_; }
|
const CollectionModel::Grouping GetGroupBy() const { return group_by_; }
|
||||||
void SetGroupBy(const CollectionModel::Grouping g);
|
void SetGroupBy(const CollectionModel::Grouping g, const std::optional<bool> separate_albums_by_grouping);
|
||||||
|
|
||||||
static QString ContainerKey(const GroupBy type, const Song &song);
|
static QString ContainerKey(const GroupBy group_by, const bool separate_albums_by_grouping, const Song &song);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void TotalSongCountUpdated(int count);
|
void TotalSongCountUpdated(int count);
|
||||||
void TotalArtistCountUpdated(int count);
|
void TotalArtistCountUpdated(int count);
|
||||||
void TotalAlbumCountUpdated(int count);
|
void TotalAlbumCountUpdated(int count);
|
||||||
void GroupingChanged(CollectionModel::Grouping g);
|
void GroupingChanged(CollectionModel::Grouping g, bool separate_albums_by_grouping);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void SetFilterAge(const int age);
|
void SetFilterAge(const int age);
|
||||||
|
@ -247,22 +244,22 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||||
// Functions for working with queries and creating items.
|
// Functions for working with queries and creating items.
|
||||||
// When the model is reset or when a node is lazy-loaded the Collection constructs a database query to populate the items.
|
// When the model is reset or when a node is lazy-loaded the Collection constructs a database query to populate the items.
|
||||||
// Filters are added for each parent item, restricting the songs returned to a particular album or artist for example.
|
// Filters are added for each parent item, restricting the songs returned to a particular album or artist for example.
|
||||||
static void InitQuery(const GroupBy type, CollectionQuery *q);
|
static void InitQuery(const GroupBy group_by, const bool separate_albums_by_grouping, CollectionQuery *q);
|
||||||
static void FilterQuery(const GroupBy type, CollectionItem *item, CollectionQuery *q);
|
static void FilterQuery(const GroupBy group_by, const bool separate_albums_by_grouping, CollectionItem *item, CollectionQuery *q);
|
||||||
|
|
||||||
// Items can be created either from a query that's been run to populate a node, or by a spontaneous SongsDiscovered emission from the backend.
|
// Items can be created either from a query that's been run to populate a node, or by a spontaneous SongsDiscovered emission from the backend.
|
||||||
CollectionItem *ItemFromQuery(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const SqlRow &row, const int container_level);
|
CollectionItem *ItemFromQuery(const GroupBy group_by, const bool separate_albums_by_grouping, const bool signal, const bool create_divider, CollectionItem *parent, const SqlRow &row, const int container_level);
|
||||||
CollectionItem *ItemFromSong(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const Song &s, const int container_level);
|
CollectionItem *ItemFromSong(const GroupBy group_by, const bool separate_albums_by_grouping, const bool signal, const bool create_divider, CollectionItem *parent, const Song &s, const int container_level);
|
||||||
|
|
||||||
// The "Various Artists" node is an annoying special case.
|
// The "Various Artists" node is an annoying special case.
|
||||||
CollectionItem *CreateCompilationArtistNode(const bool signal, CollectionItem *parent);
|
CollectionItem *CreateCompilationArtistNode(const bool signal, CollectionItem *parent);
|
||||||
|
|
||||||
// Helpers for ItemFromQuery and ItemFromSong
|
// Helpers for ItemFromQuery and ItemFromSong
|
||||||
CollectionItem *InitItem(const GroupBy type, const bool signal, CollectionItem *parent, const int container_level);
|
CollectionItem *InitItem(const GroupBy group_by, const bool signal, CollectionItem *parent, const int container_level);
|
||||||
void FinishItem(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, CollectionItem *item);
|
void FinishItem(const GroupBy group_by, const bool signal, const bool create_divider, CollectionItem *parent, CollectionItem *item);
|
||||||
|
|
||||||
static QString DividerKey(const GroupBy type, CollectionItem *item);
|
static QString DividerKey(const GroupBy group_by, CollectionItem *item);
|
||||||
static QString DividerDisplayText(const GroupBy type, const QString &key);
|
static QString DividerDisplayText(const GroupBy group_by, const QString &key);
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
static bool IsCompilationArtistNode(const CollectionItem *node) { return node == node->parent->compilation_artist_node_; }
|
static bool IsCompilationArtistNode(const CollectionItem *node) { return node == node->parent->compilation_artist_node_; }
|
||||||
|
@ -284,6 +281,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||||
|
|
||||||
QueryOptions query_options_;
|
QueryOptions query_options_;
|
||||||
Grouping group_by_;
|
Grouping group_by_;
|
||||||
|
bool separate_albums_by_grouping_;
|
||||||
|
|
||||||
// Keyed on database ID
|
// Keyed on database ID
|
||||||
QMap<int, CollectionItem*> song_nodes_;
|
QMap<int, CollectionItem*> song_nodes_;
|
||||||
|
|
|
@ -108,22 +108,31 @@ GroupByDialog::GroupByDialog(QWidget *parent) : QDialog(parent), ui_(new Ui_Grou
|
||||||
GroupByDialog::~GroupByDialog() = default;
|
GroupByDialog::~GroupByDialog() = default;
|
||||||
|
|
||||||
void GroupByDialog::Reset() {
|
void GroupByDialog::Reset() {
|
||||||
|
|
||||||
ui_->combobox_first->setCurrentIndex(2); // Album Artist
|
ui_->combobox_first->setCurrentIndex(2); // Album Artist
|
||||||
ui_->combobox_second->setCurrentIndex(3); // Album
|
ui_->combobox_second->setCurrentIndex(4); // Album Disc
|
||||||
ui_->combobox_third->setCurrentIndex(0); // None
|
ui_->combobox_third->setCurrentIndex(0); // None
|
||||||
|
ui_->checkbox_separate_albums_by_grouping->setChecked(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupByDialog::accept() {
|
void GroupByDialog::accept() {
|
||||||
|
|
||||||
emit Accepted(CollectionModel::Grouping(
|
emit Accepted(CollectionModel::Grouping(
|
||||||
p_->mapping_.get<tag_index>().find(ui_->combobox_first->currentIndex())->group_by,
|
p_->mapping_.get<tag_index>().find(ui_->combobox_first->currentIndex())->group_by,
|
||||||
p_->mapping_.get<tag_index>().find(ui_->combobox_second->currentIndex())->group_by,
|
p_->mapping_.get<tag_index>().find(ui_->combobox_second->currentIndex())->group_by,
|
||||||
p_->mapping_.get<tag_index>().find(ui_->combobox_third->currentIndex())->group_by)
|
p_->mapping_.get<tag_index>().find(ui_->combobox_third->currentIndex())->group_by),
|
||||||
|
ui_->checkbox_separate_albums_by_grouping->isChecked()
|
||||||
);
|
);
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupByDialog::CollectionGroupingChanged(const CollectionModel::Grouping g) {
|
void GroupByDialog::CollectionGroupingChanged(const CollectionModel::Grouping g, const bool separate_albums_by_grouping) {
|
||||||
|
|
||||||
ui_->combobox_first->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[0])->combo_box_index);
|
ui_->combobox_first->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[0])->combo_box_index);
|
||||||
ui_->combobox_second->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[1])->combo_box_index);
|
ui_->combobox_second->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[1])->combo_box_index);
|
||||||
ui_->combobox_third->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[2])->combo_box_index);
|
ui_->combobox_third->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[2])->combo_box_index);
|
||||||
|
ui_->checkbox_separate_albums_by_grouping->setChecked(separate_albums_by_grouping);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,11 @@ class GroupByDialog : public QDialog {
|
||||||
~GroupByDialog() override;
|
~GroupByDialog() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void CollectionGroupingChanged(const CollectionModel::Grouping g);
|
void CollectionGroupingChanged(const CollectionModel::Grouping g, const bool separate_albums_by_grouping);
|
||||||
void accept() override;
|
void accept() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Accepted(CollectionModel::Grouping g);
|
void Accepted(CollectionModel::Grouping g, bool separate_albums_by_grouping);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>354</width>
|
<width>394</width>
|
||||||
<height>246</height>
|
<height>273</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -370,6 +370,13 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkbox_separate_albums_by_grouping">
|
||||||
|
<property name="text">
|
||||||
|
<string>Separate albums by grouping tag</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="spacer_bottom">
|
<spacer name="spacer_bottom">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2015, Nick Lanham <nick@afternight.org>
|
* Copyright 2015, Nick Lanham <nick@afternight.org>
|
||||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
* Copyright 2019-2022, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,35 +22,31 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QWidget>
|
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QItemSelectionModel>
|
#include <QItemSelectionModel>
|
||||||
#include <QAbstractItemModel>
|
|
||||||
#include <QIODevice>
|
|
||||||
#include <QDataStream>
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QVariant>
|
#include <QByteArray>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QDataStream>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTreeView>
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QtDebug>
|
|
||||||
|
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/iconloader.h"
|
#include "core/iconloader.h"
|
||||||
#include "collectionfilterwidget.h"
|
|
||||||
#include "collectionmodel.h"
|
#include "collectionmodel.h"
|
||||||
#include "savedgroupingmanager.h"
|
#include "savedgroupingmanager.h"
|
||||||
#include "ui_savedgroupingmanager.h"
|
#include "ui_savedgroupingmanager.h"
|
||||||
|
|
||||||
SavedGroupingManager::SavedGroupingManager(QWidget *parent)
|
const char *SavedGroupingManager::kSavedGroupingsSettingsGroup = "SavedGroupings";
|
||||||
|
|
||||||
|
SavedGroupingManager::SavedGroupingManager(const QString &saved_groupings_settings_group, QWidget *parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
ui_(new Ui_SavedGroupingManager),
|
ui_(new Ui_SavedGroupingManager),
|
||||||
model_(new QStandardItemModel(0, 4, this)),
|
model_(new QStandardItemModel(0, 4, this)),
|
||||||
filter_(nullptr) {
|
saved_groupings_settings_group_(saved_groupings_settings_group) {
|
||||||
|
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
|
|
||||||
|
@ -71,7 +67,17 @@ SavedGroupingManager::SavedGroupingManager(QWidget *parent)
|
||||||
|
|
||||||
SavedGroupingManager::~SavedGroupingManager() {
|
SavedGroupingManager::~SavedGroupingManager() {
|
||||||
delete ui_;
|
delete ui_;
|
||||||
delete model_;
|
}
|
||||||
|
|
||||||
|
QString SavedGroupingManager::GetSavedGroupingsSettingsGroup(const QString &settings_group) {
|
||||||
|
|
||||||
|
if (settings_group.isEmpty() || settings_group == CollectionSettingsPage::kSettingsGroup) {
|
||||||
|
return kSavedGroupingsSettingsGroup;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QString(kSavedGroupingsSettingsGroup) + "_" + settings_group;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SavedGroupingManager::GroupByToString(const CollectionModel::GroupBy g) {
|
QString SavedGroupingManager::GroupByToString(const CollectionModel::GroupBy g) {
|
||||||
|
@ -151,7 +157,7 @@ void SavedGroupingManager::UpdateModel() {
|
||||||
|
|
||||||
model_->setRowCount(0); // don't use clear, it deletes headers
|
model_->setRowCount(0); // don't use clear, it deletes headers
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(CollectionModel::kSavedGroupingsSettingsGroup);
|
s.beginGroup(saved_groupings_settings_group_);
|
||||||
int version = s.value("version").toInt();
|
int version = s.value("version").toInt();
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
QStringList saved = s.childKeys();
|
QStringList saved = s.childKeys();
|
||||||
|
@ -186,7 +192,7 @@ void SavedGroupingManager::Remove() {
|
||||||
|
|
||||||
if (ui_->list->selectionModel()->hasSelection()) {
|
if (ui_->list->selectionModel()->hasSelection()) {
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(CollectionModel::kSavedGroupingsSettingsGroup);
|
s.beginGroup(saved_groupings_settings_group_);
|
||||||
for (const QModelIndex &idx : ui_->list->selectionModel()->selectedRows()) {
|
for (const QModelIndex &idx : ui_->list->selectionModel()->selectedRows()) {
|
||||||
if (idx.isValid()) {
|
if (idx.isValid()) {
|
||||||
qLog(Debug) << "Remove saved grouping: " << model_->item(idx.row(), 0)->text();
|
qLog(Debug) << "Remove saved grouping: " << model_->item(idx.row(), 0)->text();
|
||||||
|
@ -196,7 +202,8 @@ void SavedGroupingManager::Remove() {
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
}
|
}
|
||||||
UpdateModel();
|
UpdateModel();
|
||||||
filter_->UpdateGroupByActions();
|
|
||||||
|
emit UpdateGroupByActions();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2015, Nick Lanham <nick@afternight.org>
|
* Copyright 2015, Nick Lanham <nick@afternight.org>
|
||||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
* Copyright 2019-2022, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -40,14 +40,20 @@ class SavedGroupingManager : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SavedGroupingManager(QWidget *parent = nullptr);
|
explicit SavedGroupingManager(const QString &saved_groupings_settings_group, QWidget *parent = nullptr);
|
||||||
~SavedGroupingManager() override;
|
~SavedGroupingManager() override;
|
||||||
|
|
||||||
|
static const char *kSavedGroupingsSettingsGroup;
|
||||||
|
|
||||||
|
static QString GetSavedGroupingsSettingsGroup(const QString &settings_group);
|
||||||
|
|
||||||
void UpdateModel();
|
void UpdateModel();
|
||||||
void SetFilter(CollectionFilterWidget *filter) { filter_ = filter; }
|
|
||||||
|
|
||||||
static QString GroupByToString(const CollectionModel::GroupBy g);
|
static QString GroupByToString(const CollectionModel::GroupBy g);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void UpdateGroupByActions();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void UpdateButtonState();
|
void UpdateButtonState();
|
||||||
void Remove();
|
void Remove();
|
||||||
|
@ -55,7 +61,7 @@ class SavedGroupingManager : public QDialog {
|
||||||
private:
|
private:
|
||||||
Ui_SavedGroupingManager *ui_;
|
Ui_SavedGroupingManager *ui_;
|
||||||
QStandardItemModel *model_;
|
QStandardItemModel *model_;
|
||||||
CollectionFilterWidget *filter_;
|
QString saved_groupings_settings_group_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SAVEDGROUPINGMANAGER_H
|
#endif // SAVEDGROUPINGMANAGER_H
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
#include "collection/collectionfilterwidget.h"
|
#include "collection/collectionfilterwidget.h"
|
||||||
#include "collection/collectionmodel.h"
|
#include "collection/collectionmodel.h"
|
||||||
#include "collection/groupbydialog.h"
|
#include "collection/groupbydialog.h"
|
||||||
|
#include "collection/savedgroupingmanager.h"
|
||||||
#include "covermanager/albumcoverloader.h"
|
#include "covermanager/albumcoverloader.h"
|
||||||
#include "covermanager/albumcoverloaderoptions.h"
|
#include "covermanager/albumcoverloaderoptions.h"
|
||||||
#include "covermanager/albumcoverloaderresult.h"
|
#include "covermanager/albumcoverloaderresult.h"
|
||||||
|
@ -179,7 +180,7 @@ void InternetSearchView::Init(Application *app, InternetService *service) {
|
||||||
back_proxy_->sort(0);
|
back_proxy_->sort(0);
|
||||||
|
|
||||||
// Add actions to the settings menu
|
// Add actions to the settings menu
|
||||||
group_by_actions_ = CollectionFilterWidget::CreateGroupByActions(this);
|
group_by_actions_ = CollectionFilterWidget::CreateGroupByActions(SavedGroupingManager::GetSavedGroupingsSettingsGroup(service_->settings_group()), this);
|
||||||
QMenu *settings_menu = new QMenu(this);
|
QMenu *settings_menu = new QMenu(this);
|
||||||
settings_menu->addActions(group_by_actions_->actions());
|
settings_menu->addActions(group_by_actions_->actions());
|
||||||
settings_menu->addSeparator();
|
settings_menu->addSeparator();
|
||||||
|
|
Loading…
Reference in New Issue