Refactoring

This commit is contained in:
Jonas Kvinge
2024-10-22 18:12:33 +02:00
parent dfcf715291
commit 8da2b9cd94
623 changed files with 9071 additions and 5126 deletions

View File

@@ -45,13 +45,11 @@
#include <QSqlQuery>
#include <QSqlError>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/logging.h"
#include "core/database.h"
#include "core/scopedtransaction.h"
#include "core/song.h"
#include "core/sqlrow.h"
#include "smartplaylists/smartplaylistsearch.h"
#include "collectiondirectory.h"
#include "collectionbackend.h"
@@ -1932,37 +1930,26 @@ void CollectionBackend::DeleteAll() {
}
SongList CollectionBackend::SmartPlaylistsFindSongs(const SmartPlaylistSearch &search) {
SongList CollectionBackend::ExecuteQuery(const QString &sql) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
// Build the query
QString sql = search.ToSql(songs_table());
// Run the query
SongList ret;
SqlQuery query(db);
query.prepare(sql);
if (!query.Exec()) {
db_->ReportErrors(query);
return ret;
return SongList();
}
// Read the results
SongList songs;
while (query.next()) {
Song song;
song.InitFromQuery(query, true);
ret << song;
songs << song;
}
return ret;
}
SongList CollectionBackend::SmartPlaylistsGetAllSongs() {
// Get all the songs!
return SmartPlaylistsFindSongs(SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::FieldAsc, SmartPlaylistSearchTerm::Field::Artist, -1));
return songs;
}

View File

@@ -36,7 +36,7 @@
#include <QUrl>
#include <QSqlDatabase>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/song.h"
#include "collectionfilteroptions.h"
#include "collectionquery.h"
@@ -45,7 +45,6 @@
class QThread;
class TaskManager;
class Database;
class SmartPlaylistSearch;
class CollectionBackendInterface : public QObject {
Q_OBJECT
@@ -227,8 +226,7 @@ class CollectionBackend : public CollectionBackendInterface {
SongList GetSongsByFingerprint(const QString &fingerprint) override;
SongList SmartPlaylistsGetAllSongs();
SongList SmartPlaylistsFindSongs(const SmartPlaylistSearch &search);
SongList ExecuteQuery(const QString &sql);
void AddOrUpdateSongsAsync(const SongList &songs);
void UpdateSongsBySongIDAsync(const SongMap &new_songs);

View File

@@ -29,7 +29,7 @@
#include <QVariant>
#include <QString>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/filesystemmusicstorage.h"
#include "core/iconloader.h"
#include "core/musicstorage.h"

View File

@@ -33,7 +33,7 @@
#include <QStringList>
#include <QIcon>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "collectiondirectory.h"
class QModelIndex;

View File

@@ -28,10 +28,9 @@
#include <QUrl>
#include "core/song.h"
#include "core/songmimedata.h"
#include "filterparser/filterparser.h"
#include "filterparser/filtertree.h"
#include "playlist/songmimedata.h"
#include "playlist/playlistmanager.h"
#include "collectionbackend.h"
#include "collectionfilter.h"
#include "collectionmodel.h"
@@ -95,7 +94,7 @@ QMimeData *CollectionFilter::mimeData(const QModelIndexList &indexes) const {
}
data->setUrls(urls);
data->name_for_new_playlist_ = PlaylistManager::GetNameForNewPlaylist(data->songs);
data->name_for_new_playlist_ = Song::GetNameForNewPlaylist(data->songs);
return data;

View File

@@ -55,8 +55,8 @@
#include "groupbydialog.h"
#include "ui_collectionfilterwidget.h"
#include "widgets/searchfield.h"
#include "settings/collectionsettingspage.h"
#include "settings/appearancesettingspage.h"
#include "constants/collectionsettings.h"
#include "constants/appearancesettings.h"
using namespace Qt::Literals::StringLiterals;
@@ -204,8 +204,8 @@ void CollectionFilterWidget::setFilter(CollectionFilter *filter) {
void CollectionFilterWidget::ReloadSettings() {
Settings s;
s.beginGroup(AppearanceSettingsPage::kSettingsGroup);
int iconsize = s.value(AppearanceSettingsPage::kIconSizeConfigureButtons, 20).toInt();
s.beginGroup(AppearanceSettings::kSettingsGroup);
int iconsize = s.value(AppearanceSettings::kIconSizeConfigureButtons, 20).toInt();
s.endGroup();
ui_->options->setIconSize(QSize(iconsize, iconsize));
ui_->search_field->setIconSize(iconsize);
@@ -345,7 +345,7 @@ void CollectionFilterWidget::SaveGroupBy() {
qLog(Debug) << "Saving current grouping to" << name;
Settings s;
if (settings_group_.isEmpty() || settings_group_ == QLatin1String(CollectionSettingsPage::kSettingsGroup)) {
if (settings_group_.isEmpty() || settings_group_ == QLatin1String(CollectionSettings::kSettingsGroup)) {
s.beginGroup(SavedGroupingManager::kSavedGroupingsSettingsGroup);
}
else {

View File

@@ -0,0 +1,32 @@
/*
* Strawberry Music Player
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "collectionitem.h"
CollectionItem::CollectionItem(SimpleTreeModel<CollectionItem> *_model)
: SimpleTreeItem<CollectionItem>(_model),
type(Type::Root),
container_level(-1),
compilation_artist_node_(nullptr) {}
CollectionItem::CollectionItem(const Type _type, CollectionItem *_parent)
: SimpleTreeItem<CollectionItem>(_parent),
type(_type),
container_level(-1),
compilation_artist_node_(nullptr) {}

View File

@@ -1,8 +1,6 @@
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2018-2024, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,8 +20,6 @@
#ifndef COLLECTIONITEM_H
#define COLLECTIONITEM_H
#include "config.h"
#include "core/simpletreeitem.h"
#include "core/song.h"
@@ -37,17 +33,8 @@ class CollectionItem : public SimpleTreeItem<CollectionItem> {
LoadingIndicator,
};
explicit CollectionItem(SimpleTreeModel<CollectionItem> *_model)
: SimpleTreeItem<CollectionItem>(_model),
type(Type::Root),
container_level(-1),
compilation_artist_node_(nullptr) {}
explicit CollectionItem(const Type _type, CollectionItem *_parent = nullptr)
: SimpleTreeItem<CollectionItem>(_parent),
type(_type),
container_level(-1),
compilation_artist_node_(nullptr) {}
explicit CollectionItem(SimpleTreeModel<CollectionItem> *_model);
explicit CollectionItem(const Type _type, CollectionItem *_parent = nullptr);
Type type;
int container_level;

View File

@@ -30,7 +30,6 @@
#include <QSettings>
#include <QtConcurrentRun>
#include "core/application.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "core/thread.h"
@@ -39,22 +38,26 @@
#include "core/settings.h"
#include "tagreader/tagreaderclient.h"
#include "utilities/threadutils.h"
#include "collection.h"
#include "collectionlibrary.h"
#include "collectionwatcher.h"
#include "collectionbackend.h"
#include "collectionmodel.h"
#include "scrobbler/lastfmimport.h"
#include "settings/collectionsettingspage.h"
#include "constants/collectionsettings.h"
using std::make_shared;
const char *SCollection::kSongsTable = "songs";
const char *SCollection::kDirsTable = "directories";
const char *SCollection::kSubdirsTable = "subdirectories";
const char *CollectionLibrary::kSongsTable = "songs";
const char *CollectionLibrary::kDirsTable = "directories";
const char *CollectionLibrary::kSubdirsTable = "subdirectories";
SCollection::SCollection(Application *app, QObject *parent)
CollectionLibrary::CollectionLibrary(const SharedPtr<Database> database,
const SharedPtr<TaskManager> task_manager,
const SharedPtr<TagReaderClient> tagreader_client,
const SharedPtr<AlbumCoverLoader> albumcover_loader,
QObject *parent)
: QObject(parent),
app_(app),
task_manager_(task_manager),
tagreader_client_(tagreader_client),
backend_(nullptr),
model_(nullptr),
watcher_(nullptr),
@@ -68,18 +71,18 @@ SCollection::SCollection(Application *app, QObject *parent)
original_thread_ = thread();
backend_ = make_shared<CollectionBackend>();
backend()->moveToThread(app->database()->thread());
qLog(Debug) << &*backend_ << "moved to thread" << app->database()->thread();
backend()->moveToThread(database->thread());
qLog(Debug) << &*backend_ << "moved to thread" << database->thread();
backend_->Init(app->database(), app->task_manager(), Song::Source::Collection, QLatin1String(kSongsTable), QLatin1String(kDirsTable), QLatin1String(kSubdirsTable));
backend_->Init(database, task_manager, Song::Source::Collection, QLatin1String(kSongsTable), QLatin1String(kDirsTable), QLatin1String(kSubdirsTable));
model_ = new CollectionModel(backend_, app_, this);
model_ = new CollectionModel(backend_, albumcover_loader, this);
ReloadSettings();
}
SCollection::~SCollection() {
CollectionLibrary::~CollectionLibrary() {
if (watcher_) {
watcher_->Abort();
@@ -92,9 +95,9 @@ SCollection::~SCollection() {
}
void SCollection::Init() {
void CollectionLibrary::Init() {
watcher_ = new CollectionWatcher(Song::Source::Collection);
watcher_ = new CollectionWatcher(Song::Source::Collection, task_manager_, tagreader_client_, backend_);
watcher_thread_ = new Thread(this);
watcher_thread_->setObjectName(watcher_->objectName());
@@ -106,14 +109,11 @@ void SCollection::Init() {
watcher_thread_->start(QThread::IdlePriority);
watcher_->set_backend(backend_);
watcher_->set_task_manager(app_->task_manager());
QObject::connect(&*backend_, &CollectionBackend::Error, this, &SCollection::Error);
QObject::connect(&*backend_, &CollectionBackend::Error, this, &CollectionLibrary::Error);
QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory);
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, watcher_, &CollectionWatcher::RemoveDirectory);
QObject::connect(&*backend_, &CollectionBackend::SongsRatingChanged, this, &SCollection::SongsRatingChanged);
QObject::connect(&*backend_, &CollectionBackend::SongsStatisticsChanged, this, &SCollection::SongsPlaycountChanged);
QObject::connect(&*backend_, &CollectionBackend::SongsRatingChanged, this, &CollectionLibrary::SongsRatingChanged);
QObject::connect(&*backend_, &CollectionBackend::SongsStatisticsChanged, this, &CollectionLibrary::SongsPlaycountChanged);
QObject::connect(watcher_, &CollectionWatcher::NewOrUpdatedSongs, &*backend_, &CollectionBackend::AddOrUpdateSongs);
QObject::connect(watcher_, &CollectionWatcher::SongsMTimeUpdated, &*backend_, &CollectionBackend::UpdateMTimesOnly);
@@ -125,30 +125,27 @@ void SCollection::Init() {
QObject::connect(watcher_, &CollectionWatcher::CompilationsNeedUpdating, &*backend_, &CollectionBackend::CompilationsNeedUpdating);
QObject::connect(watcher_, &CollectionWatcher::UpdateLastSeen, &*backend_, &CollectionBackend::UpdateLastSeen);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateLastPlayed, &*backend_, &CollectionBackend::UpdateLastPlayed);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdatePlayCount, &*backend_, &CollectionBackend::UpdatePlayCount);
// This will start the watcher checking for updates
backend_->LoadDirectoriesAsync();
}
void SCollection::Exit() {
void CollectionLibrary::Exit() {
wait_for_exit_ << &*backend_ << watcher_;
QObject::disconnect(&*backend_, nullptr, watcher_, nullptr);
QObject::disconnect(watcher_, nullptr, &*backend_, nullptr);
QObject::connect(&*backend_, &CollectionBackend::ExitFinished, this, &SCollection::ExitReceived);
QObject::connect(watcher_, &CollectionWatcher::ExitFinished, this, &SCollection::ExitReceived);
QObject::connect(&*backend_, &CollectionBackend::ExitFinished, this, &CollectionLibrary::ExitReceived);
QObject::connect(watcher_, &CollectionWatcher::ExitFinished, this, &CollectionLibrary::ExitReceived);
backend_->ExitAsync();
watcher_->Abort();
watcher_->ExitAsync();
}
void SCollection::ExitReceived() {
void CollectionLibrary::ExitReceived() {
QObject *obj = sender();
QObject::disconnect(obj, nullptr, this, nullptr);
@@ -158,13 +155,13 @@ void SCollection::ExitReceived() {
}
void SCollection::IncrementalScan() { watcher_->IncrementalScanAsync(); }
void CollectionLibrary::IncrementalScan() { watcher_->IncrementalScanAsync(); }
void SCollection::FullScan() { watcher_->FullScanAsync(); }
void CollectionLibrary::FullScan() { watcher_->FullScanAsync(); }
void SCollection::StopScan() { watcher_->Stop(); }
void CollectionLibrary::StopScan() { watcher_->Stop(); }
void SCollection::Rescan(const SongList &songs) {
void CollectionLibrary::Rescan(const SongList &songs) {
qLog(Debug) << "Rescan" << songs.size() << "songs";
if (!songs.isEmpty()) {
@@ -173,58 +170,58 @@ void SCollection::Rescan(const SongList &songs) {
}
void SCollection::PauseWatcher() { watcher_->SetRescanPausedAsync(true); }
void CollectionLibrary::PauseWatcher() { watcher_->SetRescanPausedAsync(true); }
void SCollection::ResumeWatcher() { watcher_->SetRescanPausedAsync(false); }
void CollectionLibrary::ResumeWatcher() { watcher_->SetRescanPausedAsync(false); }
void SCollection::ReloadSettings() {
void CollectionLibrary::ReloadSettings() {
watcher_->ReloadSettingsAsync();
model_->ReloadSettings();
Settings s;
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
save_playcounts_to_files_ = s.value("save_playcounts", false).toBool();
save_ratings_to_files_ = s.value("save_ratings", false).toBool();
s.beginGroup(CollectionSettings::kSettingsGroup);
save_playcounts_to_files_ = s.value(CollectionSettings::kSavePlayCounts, false).toBool();
save_ratings_to_files_ = s.value(CollectionSettings::kSaveRatings, false).toBool();
s.endGroup();
}
void SCollection::SyncPlaycountAndRatingToFilesAsync() {
void CollectionLibrary::SyncPlaycountAndRatingToFilesAsync() {
(void)QtConcurrent::run(&SCollection::SyncPlaycountAndRatingToFiles, this);
(void)QtConcurrent::run(&CollectionLibrary::SyncPlaycountAndRatingToFiles, this);
}
void SCollection::SyncPlaycountAndRatingToFiles() {
void CollectionLibrary::SyncPlaycountAndRatingToFiles() {
const int task_id = app_->task_manager()->StartTask(tr("Saving playcounts and ratings"));
app_->task_manager()->SetTaskBlocksCollectionScans(task_id);
const int task_id = task_manager_->StartTask(tr("Saving playcounts and ratings"));
task_manager_->SetTaskBlocksCollectionScans(task_id);
const SongList songs = backend_->GetAllSongs();
const qint64 nb_songs = songs.size();
int i = 0;
for (const Song &song : songs) {
(void)TagReaderClient::Instance()->SaveSongPlaycountBlocking(song.url().toLocalFile(), song.playcount());
(void)TagReaderClient::Instance()->SaveSongRatingBlocking(song.url().toLocalFile(), song.rating());
app_->task_manager()->SetTaskProgress(task_id, ++i, nb_songs);
(void)tagreader_client_->SaveSongPlaycountBlocking(song.url().toLocalFile(), song.playcount());
(void)tagreader_client_->SaveSongRatingBlocking(song.url().toLocalFile(), song.rating());
task_manager_->SetTaskProgress(task_id, ++i, nb_songs);
}
app_->task_manager()->SetTaskFinished(task_id);
task_manager_->SetTaskFinished(task_id);
}
void SCollection::SongsPlaycountChanged(const SongList &songs, const bool save_tags) {
void CollectionLibrary::SongsPlaycountChanged(const SongList &songs, const bool save_tags) const {
if (save_tags || save_playcounts_to_files_) {
app_->tag_reader_client()->SaveSongsPlaycountAsync(songs);
tagreader_client_->SaveSongsPlaycountAsync(songs);
}
}
void SCollection::SongsRatingChanged(const SongList &songs, const bool save_tags) {
void CollectionLibrary::SongsRatingChanged(const SongList &songs, const bool save_tags) const {
if (save_tags || save_ratings_to_files_) {
app_->tag_reader_client()->SaveSongsRatingAsync(songs);
tagreader_client_->SaveSongsRatingAsync(songs);
}
}

View File

@@ -29,22 +29,30 @@
#include <QHash>
#include <QString>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/song.h"
class QThread;
class Application;
class Thread;
class Database;
class TaskManager;
class TagReaderClient;
class CollectionBackend;
class CollectionModel;
class CollectionWatcher;
class AlbumCoverLoader;
class SCollection : public QObject {
class CollectionLibrary : public QObject {
Q_OBJECT
public:
explicit SCollection(Application *app, QObject *parent = nullptr);
~SCollection() override;
explicit CollectionLibrary(const SharedPtr<Database> database,
const SharedPtr<TaskManager> task_manager,
const SharedPtr<TagReaderClient> tagreader_client,
const SharedPtr<AlbumCoverLoader> albumcover_loader,
QObject *parent = nullptr);
~CollectionLibrary() override;
static const char *kSongsTable;
static const char *kFtsTable;
@@ -78,15 +86,17 @@ class SCollection : public QObject {
private Q_SLOTS:
void ExitReceived();
void SongsPlaycountChanged(const SongList &songs, const bool save_tags = false);
void SongsRatingChanged(const SongList &songs, const bool save_tags = false);
void SongsPlaycountChanged(const SongList &songs, const bool save_tags = false) const;
void SongsRatingChanged(const SongList &songs, const bool save_tags = false) const;
Q_SIGNALS:
void Error(const QString &error);
void ExitFinished();
private:
Application *app_;
const SharedPtr<TaskManager> task_manager_;
const SharedPtr<TagReaderClient> tagreader_client_;
SharedPtr<CollectionBackend> backend_;
CollectionModel *model_;

View File

@@ -53,14 +53,13 @@
#include <QStandardPaths>
#include <QTimer>
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/application.h"
#include "includes/scoped_ptr.h"
#include "includes/shared_ptr.h"
#include "core/database.h"
#include "core/iconloader.h"
#include "core/logging.h"
#include "core/sqlrow.h"
#include "core/settings.h"
#include "core/songmimedata.h"
#include "collectionfilteroptions.h"
#include "collectionquery.h"
#include "collectionbackend.h"
@@ -69,12 +68,10 @@
#include "collectionmodel.h"
#include "collectionmodelupdate.h"
#include "collectionfilter.h"
#include "playlist/playlistmanager.h"
#include "playlist/songmimedata.h"
#include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h"
#include "covermanager/albumcoverloader.h"
#include "settings/collectionsettingspage.h"
#include "constants/collectionsettings.h"
using namespace std::chrono_literals;
using namespace Qt::Literals::StringLiterals;
@@ -85,12 +82,10 @@ constexpr char kPixmapDiskCacheDir[] = "pixmapcache";
constexpr char kVariousArtists[] = QT_TR_NOOP("Various artists");
} // namespace
QNetworkDiskCache *CollectionModel::sIconCache = nullptr;
CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Application *app, QObject *parent)
CollectionModel::CollectionModel(const SharedPtr<CollectionBackend> backend, const SharedPtr<AlbumCoverLoader> albumcover_loader, QObject *parent)
: SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent),
backend_(backend),
app_(app),
albumcover_loader_(albumcover_loader),
dir_model_(new CollectionDirectoryModel(backend, this)),
filter_(new CollectionFilter(this)),
timer_reload_(new QTimer(this)),
@@ -100,7 +95,8 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
total_song_count_(0),
total_artist_count_(0),
total_album_count_(0),
loading_(false) {
loading_(false),
icon_disk_cache_(nullptr) {
setObjectName(backend_->source() == Song::Source::Collection ? QLatin1String(metaObject()->className()) : QStringLiteral("%1%2").arg(Song::DescriptionForSource(backend_->source()), QLatin1String(metaObject()->className())));
@@ -108,8 +104,8 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
filter_->setSortRole(Role_SortText);
filter_->sort(0);
if (app_) {
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded);
if (albumcover_loader_) {
QObject::connect(&*albumcover_loader_, &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded);
}
QIcon nocover = IconLoader::Load(u"cdcase"_s);
@@ -118,10 +114,9 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
pixmap_no_cover_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
if (app_ && !sIconCache) {
sIconCache = new QNetworkDiskCache(this);
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' + QLatin1String(kPixmapDiskCacheDir));
QObject::connect(app_, &Application::ClearPixmapDiskCache, this, &CollectionModel::ClearDiskCache);
if (!qgetenv("DISPLAY").isEmpty() && !icon_disk_cache_) {
icon_disk_cache_ = new QNetworkDiskCache(this);
icon_disk_cache_->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' + QLatin1String(kPixmapDiskCacheDir) + u'-' + Song::TextForSource(backend_->source()));
}
QObject::connect(&*backend_, &CollectionBackend::SongsAdded, this, &CollectionModel::AddReAddOrUpdate);
@@ -230,16 +225,16 @@ void CollectionModel::ScheduleReset() {
void CollectionModel::ReloadSettings() {
Settings settings;
settings.beginGroup(CollectionSettingsPage::kSettingsGroup);
const bool show_pretty_covers = settings.value("pretty_covers", true).toBool();
const bool show_dividers= settings.value("show_dividers", true).toBool();
const bool show_various_artists = settings.value("various_artists", true).toBool();
const bool sort_skips_articles = settings.value("sort_skips_articles", true).toBool();
settings.beginGroup(CollectionSettings::kSettingsGroup);
const bool show_pretty_covers = settings.value(CollectionSettings::kPrettyCovers, true).toBool();
const bool show_dividers= settings.value(CollectionSettings::kShowDividers, true).toBool();
const bool show_various_artists = settings.value(CollectionSettings::kVariousArtists, true).toBool();
const bool sort_skips_articles = settings.value(CollectionSettings::kSortSkipsArticles, true).toBool();
use_disk_cache_ = settings.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool();
QPixmapCache::setCacheLimit(static_cast<int>(MaximumCacheSize(&settings, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024));
if (sIconCache) {
sIconCache->setMaximumCacheSize(MaximumCacheSize(&settings, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit, CollectionSettingsPage::kSettingsDiskCacheSizeDefault));
use_disk_cache_ = settings.value(CollectionSettings::kSettingsDiskCacheEnable, false).toBool();
QPixmapCache::setCacheLimit(static_cast<int>(MaximumCacheSize(&settings, CollectionSettings::kSettingsCacheSize, CollectionSettings::kSettingsCacheSizeUnit, CollectionSettings::kSettingsCacheSizeDefault) / 1024));
if (icon_disk_cache_) {
icon_disk_cache_->setMaximumCacheSize(MaximumCacheSize(&settings, CollectionSettings::kSettingsDiskCacheSize, CollectionSettings::kSettingsDiskCacheSizeUnit, CollectionSettings::kSettingsDiskCacheSizeDefault));
}
settings.endGroup();
@@ -258,7 +253,7 @@ void CollectionModel::ReloadSettings() {
}
if (!use_disk_cache_) {
ClearDiskCache();
ClearIconDiskCache();
}
}
@@ -427,7 +422,7 @@ QMimeData *CollectionModel::mimeData(const QModelIndexList &indexes) const {
}
data->setUrls(urls);
data->name_for_new_playlist_ = PlaylistManager::GetNameForNewPlaylist(data->songs);
data->name_for_new_playlist_ = Song::GetNameForNewPlaylist(data->songs);
return data;
@@ -778,7 +773,7 @@ void CollectionModel::CreateSongItem(const Song &song, CollectionItem *parent) {
}
void CollectionModel::SetSongItemData(CollectionItem *item, const Song &song) {
void CollectionModel::SetSongItemData(CollectionItem *item, const Song &song) const {
item->display_text = song.TitleWithCompilationArtist();
item->sort_text = HasParentAlbumGroupBy(item->parent) ? SortTextForSong(song) : SortText(song.title());
@@ -879,7 +874,7 @@ void CollectionModel::ClearItemPixmapCache(CollectionItem *item) {
// Remove from pixmap cache
const QString cache_key = AlbumIconPixmapCacheKey(ItemToIndex(item));
QPixmapCache::remove(cache_key);
if (use_disk_cache_ && sIconCache) sIconCache->remove(AlbumIconPixmapDiskCacheKey(cache_key));
if (use_disk_cache_ && icon_disk_cache_) icon_disk_cache_->remove(AlbumIconPixmapDiskCacheKey(cache_key));
if (pending_cache_keys_.contains(cache_key)) {
pending_cache_keys_.remove(cache_key);
}
@@ -910,8 +905,8 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
}
// Try to load it from the disk cache
if (use_disk_cache_ && sIconCache) {
ScopedPtr<QIODevice> disk_cache_img(sIconCache->data(AlbumIconPixmapDiskCacheKey(cache_key)));
if (use_disk_cache_ && icon_disk_cache_) {
ScopedPtr<QIODevice> disk_cache_img(icon_disk_cache_->data(AlbumIconPixmapDiskCacheKey(cache_key)));
if (disk_cache_img) {
QImage cached_image;
if (cached_image.load(&*disk_cache_img, "XPM")) {
@@ -932,7 +927,7 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
AlbumCoverLoaderOptions cover_loader_options(AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage);
cover_loader_options.desired_scaled_size = QSize(kPrettyCoverSize, kPrettyCoverSize);
cover_loader_options.types = cover_types_;
const quint64 id = app_->album_cover_loader()->LoadImageAsync(cover_loader_options, songs.first());
const quint64 id = albumcover_loader_->LoadImageAsync(cover_loader_options, songs.first());
pending_art_[id] = ItemAndCacheKey(item, cache_key);
pending_cache_keys_.insert(cache_key);
}
@@ -965,19 +960,19 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderR
}
// If we have a valid cover not already in the disk cache
if (use_disk_cache_ && sIconCache && result.success && !result.image_scaled.isNull()) {
if (use_disk_cache_ && icon_disk_cache_ && result.success && !result.image_scaled.isNull()) {
const QUrl disk_cache_key = AlbumIconPixmapDiskCacheKey(cache_key);
ScopedPtr<QIODevice> disk_cache_img(sIconCache->data(disk_cache_key));
ScopedPtr<QIODevice> disk_cache_img(icon_disk_cache_->data(disk_cache_key));
if (!disk_cache_img) {
QNetworkCacheMetaData disk_cache_metadata;
disk_cache_metadata.setSaveToDisk(true);
disk_cache_metadata.setUrl(disk_cache_key);
// Qt 6 now ignores any entry without headers, so add a fake header.
disk_cache_metadata.setRawHeaders(QNetworkCacheMetaData::RawHeaderList() << qMakePair(QByteArray("collection-thumbnail"), cache_key.toUtf8()));
QIODevice *device_iconcache = sIconCache->prepare(disk_cache_metadata);
QIODevice *device_iconcache = icon_disk_cache_->prepare(disk_cache_metadata);
if (device_iconcache) {
result.image_scaled.save(device_iconcache, "XPM");
sIconCache->insert(device_iconcache);
icon_disk_cache_->insert(device_iconcache);
}
}
}
@@ -1450,7 +1445,7 @@ bool CollectionModel::HasParentAlbumGroupBy(CollectionItem *item) const {
qint64 CollectionModel::MaximumCacheSize(Settings *s, const char *size_id, const char *size_unit_id, const qint64 cache_size_default) {
qint64 size = s->value(size_id, cache_size_default).toInt();
int unit = s->value(size_unit_id, static_cast<int>(CollectionSettingsPage::CacheSizeUnit::MB)).toInt() + 1;
int unit = s->value(size_unit_id, static_cast<int>(CollectionSettings::CacheSizeUnit::MB)).toInt() + 1;
do {
size *= 1024;
@@ -1553,8 +1548,11 @@ void CollectionModel::TotalAlbumCountUpdatedSlot(const int count) {
}
void CollectionModel::ClearDiskCache() {
if (sIconCache) sIconCache->clear();
void CollectionModel::ClearIconDiskCache() {
if (icon_disk_cache_) icon_disk_cache_->clear();
QPixmapCache::clear();
}
void CollectionModel::RowsInserted(const QModelIndex &parent, const int first, const int last) {

View File

@@ -44,10 +44,9 @@
#include <QNetworkDiskCache>
#include <QQueue>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/simpletreemodel.h"
#include "core/song.h"
#include "core/sqlrow.h"
#include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h"
#include "collectionmodelupdate.h"
@@ -57,16 +56,16 @@
class QTimer;
class Settings;
class Application;
class CollectionBackend;
class CollectionDirectoryModel;
class CollectionFilter;
class AlbumCoverLoader;
class CollectionModel : public SimpleTreeModel<CollectionItem> {
Q_OBJECT
public:
explicit CollectionModel(SharedPtr<CollectionBackend> backend, Application *app, QObject *parent = nullptr);
explicit CollectionModel(const SharedPtr<CollectionBackend> backend, const SharedPtr<AlbumCoverLoader> albumcover_loader, QObject *parent = nullptr);
~CollectionModel() override;
static const int kPrettyCoverSize;
@@ -156,7 +155,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
int total_artist_count() const { return total_artist_count_; }
int total_album_count() const { return total_album_count_; }
quint64 icon_cache_disk_size() { return sIconCache->cacheSize(); }
quint64 icon_disk_cache_size() { return icon_disk_cache_->cacheSize(); }
const CollectionModel::Grouping GetGroupBy() const { return options_current_.group_by; }
void SetGroupBy(const CollectionModel::Grouping g, const std::optional<bool> separate_albums_by_grouping = std::optional<bool>());
@@ -218,6 +217,8 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
void AddReAddOrUpdate(const SongList &songs);
void RemoveSongs(const SongList &songs);
void ClearIconDiskCache();
private:
void Clear();
void BeginReset();
@@ -238,7 +239,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
void CreateDividerItem(const QString &divider_key, const QString &display_text, CollectionItem *parent);
CollectionItem *CreateContainerItem(const GroupBy group_by, const int container_level, const QString &container_key, const Song &song, CollectionItem *parent);
void CreateSongItem(const Song &song, CollectionItem *parent);
void SetSongItemData(CollectionItem *item, const Song &song);
void SetSongItemData(CollectionItem *item, const Song &song) const;
CollectionItem *CreateCompilationArtistNode(CollectionItem *parent);
void LoadSongsFromSqlAsync();
@@ -267,15 +268,12 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
void TotalArtistCountUpdatedSlot(const int count);
void TotalAlbumCountUpdatedSlot(const int count);
static void ClearDiskCache();
void RowsInserted(const QModelIndex &parent, const int first, const int last);
void RowsRemoved(const QModelIndex &parent, const int first, const int last);
private:
static QNetworkDiskCache *sIconCache;
SharedPtr<CollectionBackend> backend_;
Application *app_;
const SharedPtr<CollectionBackend> backend_;
const SharedPtr<AlbumCoverLoader> albumcover_loader_;
CollectionDirectoryModel *dir_model_;
CollectionFilter *filter_;
QTimer *timer_reload_;
@@ -310,6 +308,8 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
using ItemAndCacheKey = QPair<CollectionItem*, QString>;
QMap<quint64, ItemAndCacheKey> pending_art_;
QSet<QString> pending_cache_keys_;
QNetworkDiskCache *icon_disk_cache_;
};
Q_DECLARE_METATYPE(CollectionModel::Grouping)

View File

@@ -19,7 +19,7 @@
#include <QString>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/taskmanager.h"
#include "collectiontask.h"

View File

@@ -23,7 +23,7 @@
#include <QtGlobal>
#include <QString>
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
class TaskManager;

View File

@@ -50,20 +50,20 @@
#include <QKeyEvent>
#include <QContextMenuEvent>
#include "core/application.h"
#include "core/iconloader.h"
#include "core/mimedata.h"
#include "core/musicstorage.h"
#include "core/deletefiles.h"
#include "core/settings.h"
#include "utilities/filemanagerutils.h"
#include "collection.h"
#include "collectionlibrary.h"
#include "collectionbackend.h"
#include "collectiondirectorymodel.h"
#include "collectionmodel.h"
#include "collectionfilter.h"
#include "collectionfilterwidget.h"
#include "collectionitem.h"
#include "collectionitemdelegate.h"
#include "collectionmodel.h"
#include "collectionview.h"
#ifndef Q_OS_WIN
# include "device/devicemanager.h"
@@ -73,15 +73,16 @@
#include "dialogs/deleteconfirmationdialog.h"
#include "organize/organizedialog.h"
#include "organize/organizeerrordialog.h"
#include "settings/collectionsettingspage.h"
#include "constants/collectionsettings.h"
using std::make_unique;
using namespace Qt::Literals::StringLiterals;
CollectionView::CollectionView(QWidget *parent)
: AutoExpandingTreeView(parent),
app_(nullptr),
model_(nullptr),
filter_(nullptr),
filter_widget_(nullptr),
total_song_count_(-1),
total_artist_count_(-1),
total_album_count_(-1),
@@ -123,6 +124,35 @@ CollectionView::CollectionView(QWidget *parent)
CollectionView::~CollectionView() = default;
void CollectionView::Init(const SharedPtr<TaskManager> task_manager,
const SharedPtr<TagReaderClient> tagreader_client,
const SharedPtr<NetworkAccessManager> network,
const SharedPtr<AlbumCoverLoader> albumcover_loader,
const SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
const SharedPtr<CoverProviders> cover_providers,
const SharedPtr<LyricsProviders> lyrics_providers,
const SharedPtr<CollectionLibrary> collection,
const SharedPtr<DeviceManager> device_manager,
const SharedPtr<StreamingServices> streaming_services) {
task_manager_ = task_manager;
tagreader_client_ = tagreader_client;
network_ = network;
albumcover_loader_ = albumcover_loader;
current_albumcover_loader_ = current_albumcover_loader;
cover_providers_ = cover_providers;
lyrics_providers_ = lyrics_providers;
collection_ = collection;
device_manager_ = device_manager;
streaming_services_ = streaming_services;
backend_ = collection_->backend();
model_ = collection_->model();
filter_ = collection_->model()->filter();
ReloadSettings();
}
void CollectionView::SaveFocus() {
const QModelIndex current = currentIndex();
@@ -142,8 +172,8 @@ void CollectionView::SaveFocus() {
switch (item_type) {
case CollectionItem::Type::Song:{
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
SongList songs = app_->collection_model()->GetChildSongs(index);
QModelIndex index = filter_->mapToSource(current);
SongList songs = model_->GetChildSongs(index);
if (!songs.isEmpty()) {
last_selected_song_ = songs.last();
}
@@ -210,8 +240,8 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
break;
case CollectionItem::Type::Song:
if (!last_selected_song_.url().isEmpty()) {
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
const SongList songs = app_->collection_model()->GetChildSongs(index);
QModelIndex index = filter_->mapToSource(current);
const SongList songs = model_->GetChildSongs(index);
if (std::any_of(songs.begin(), songs.end(), [this](const Song &song) { return song == last_selected_song_; })) {
setCurrentIndex(current);
return true;
@@ -241,6 +271,7 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
}
}
}
return false;
}
@@ -248,22 +279,14 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
void CollectionView::ReloadSettings() {
Settings settings;
settings.beginGroup(CollectionSettingsPage::kSettingsGroup);
SetAutoOpen(settings.value("auto_open", false).toBool());
delete_files_ = settings.value("delete_files", false).toBool();
settings.beginGroup(CollectionSettings::kSettingsGroup);
SetAutoOpen(settings.value(CollectionSettings::kAutoOpen, false).toBool());
delete_files_ = settings.value(CollectionSettings::kDeleteFiles, false).toBool();
settings.endGroup();
}
void CollectionView::SetApplication(Application *app) {
app_ = app;
ReloadSettings();
}
void CollectionView::SetFilter(CollectionFilterWidget *filter) { filter_ = filter; }
void CollectionView::SetFilterWidget(CollectionFilterWidget *filter_widget) { filter_widget_ = filter_widget; }
void CollectionView::TotalSongCountUpdated(const int count) {
@@ -353,7 +376,7 @@ void CollectionView::mouseReleaseEvent(QMouseEvent *e) {
QTreeView::mouseReleaseEvent(e);
if (total_song_count_ == 0) {
Q_EMIT ShowConfigDialog();
Q_EMIT ShowSettingsDialog();
}
}
@@ -414,11 +437,11 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_->addSeparator();
context_menu_->addMenu(filter_->menu());
context_menu_->addMenu(filter_widget_->menu());
#ifndef Q_OS_WIN
action_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
QObject::connect(app_->device_manager()->connected_devices_model(), &DeviceStateFilterModel::IsEmptyChanged, action_copy_to_device_, &QAction::setDisabled);
action_copy_to_device_->setDisabled(device_manager_->connected_devices_model()->rowCount() == 0);
QObject::connect(device_manager_->connected_devices_model(), &DeviceStateFilterModel::IsEmptyChanged, action_copy_to_device_, &QAction::setDisabled);
#endif
}
@@ -426,16 +449,16 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_index_ = indexAt(e->pos());
if (!context_menu_index_.isValid()) return;
context_menu_index_ = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(context_menu_index_);
context_menu_index_ = filter_->mapToSource(context_menu_index_);
const QModelIndexList selected_indexes = qobject_cast<QSortFilterProxyModel*>(model())->mapSelectionToSource(selectionModel()->selection()).indexes();
const QModelIndexList selected_indexes = filter_->mapSelectionToSource(selectionModel()->selection()).indexes();
int regular_elements = 0;
int regular_editable = 0;
for (const QModelIndex &idx : selected_indexes) {
++regular_elements;
if (app_->collection_model()->data(idx, CollectionModel::Role_Editable).toBool()) {
if (model_->data(idx, CollectionModel::Role_Editable).toBool()) {
++regular_editable;
}
}
@@ -502,7 +525,7 @@ void CollectionView::SetShowInVarious(const bool on) {
if (on && albums.keys().count() == 1) {
const QStringList albums_list = albums.keys();
const QString album = albums_list.first();
const SongList all_of_album = app_->collection_backend()->GetSongsByAlbum(album);
const SongList all_of_album = backend_->GetSongsByAlbum(album);
QSet<QString> other_artists;
for (const Song &s : all_of_album) {
if (!albums.contains(album, s.artist()) && !other_artists.contains(s.artist())) {
@@ -520,7 +543,7 @@ void CollectionView::SetShowInVarious(const bool on) {
const QSet<QString> albums_set = QSet<QString>(albums.keyBegin(), albums.keyEnd());
for (const QString &album : albums_set) {
app_->collection_backend()->ForceCompilation(album, albums.values(album), on);
backend_->ForceCompilation(album, albums.values(album), on);
}
}
@@ -584,11 +607,12 @@ void CollectionView::SearchForThis() {
return;
}
QString search;
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
QModelIndex index = filter_->mapToSource(current);
switch (item_type) {
case CollectionItem::Type::Song:{
SongList songs = app_->collection_model()->GetChildSongs(index);
SongList songs = model_->GetChildSongs(index);
if (!songs.isEmpty()) {
last_selected_song_ = songs.last();
}
@@ -601,8 +625,8 @@ void CollectionView::SearchForThis() {
}
case CollectionItem::Type::Container:{
CollectionItem *item = app_->collection_model()->IndexToItem(index);
const CollectionModel::GroupBy group_by = app_->collection_model()->GetGroupBy()[item->container_level];
CollectionItem *item = model_->IndexToItem(index);
const CollectionModel::GroupBy group_by = model_->GetGroupBy()[item->container_level];
while (!item->children.isEmpty()) {
item = item->children.constFirst();
}
@@ -663,7 +687,7 @@ void CollectionView::SearchForThis() {
return;
}
filter_->ShowInCollection(search);
filter_widget_->ShowInCollection(search);
}
@@ -688,18 +712,18 @@ void CollectionView::scrollTo(const QModelIndex &idx, ScrollHint hint) {
SongList CollectionView::GetSelectedSongs() const {
QModelIndexList selected_indexes = qobject_cast<QSortFilterProxyModel*>(model())->mapSelectionToSource(selectionModel()->selection()).indexes();
return app_->collection_model()->GetChildSongs(selected_indexes);
QModelIndexList selected_indexes = filter_->mapSelectionToSource(selectionModel()->selection()).indexes();
return model_->GetChildSongs(selected_indexes);
}
void CollectionView::Organize() {
if (!organize_dialog_) {
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), app_->collection_backend(), this);
organize_dialog_ = make_unique<OrganizeDialog>(task_manager_, tagreader_client_, backend_, this);
}
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
organize_dialog_->SetDestinationModel(model_->directory_model());
organize_dialog_->SetCopy(false);
const SongList songs = GetSelectedSongs();
if (organize_dialog_->SetSongs(songs)) {
@@ -714,7 +738,7 @@ void CollectionView::Organize() {
void CollectionView::EditTracks() {
if (!edit_tag_dialog_) {
edit_tag_dialog_ = make_unique<EditTagDialog>(app_, this);
edit_tag_dialog_ = make_unique<EditTagDialog>(network_, tagreader_client_, backend_, albumcover_loader_, current_albumcover_loader_, cover_providers_, lyrics_providers_, streaming_services_, this);
QObject::connect(&*edit_tag_dialog_, &EditTagDialog::Error, this, &CollectionView::EditTagError);
}
const SongList songs = GetSelectedSongs();
@@ -729,7 +753,7 @@ void CollectionView::EditTagError(const QString &message) {
void CollectionView::RescanSongs() {
app_->collection()->Rescan(GetSelectedSongs());
collection_->Rescan(GetSelectedSongs());
}
@@ -737,10 +761,10 @@ void CollectionView::CopyToDevice() {
#ifndef Q_OS_WIN
if (!organize_dialog_) {
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), nullptr, this);
organize_dialog_ = make_unique<OrganizeDialog>(task_manager_, tagreader_client_, nullptr, this);
}
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
organize_dialog_->SetDestinationModel(device_manager_->connected_devices_model(), true);
organize_dialog_->SetCopy(true);
organize_dialog_->SetSongs(GetSelectedSongs());
organize_dialog_->show();
@@ -812,9 +836,9 @@ void CollectionView::Delete() {
if (DeleteConfirmationDialog::warning(files) != QDialogButtonBox::Yes) return;
// We can cheat and always take the storage of the first directory, since they'll all be FilesystemMusicStorage in a collection and deleting doesn't check the actual directory.
SharedPtr<MusicStorage> storage = app_->collection_model()->directory_model()->index(0, 0).data(MusicStorage::Role_Storage).value<SharedPtr<MusicStorage>>();
SharedPtr<MusicStorage> storage = model_->directory_model()->index(0, 0).data(MusicStorage::Role_Storage).value<SharedPtr<MusicStorage>>();
DeleteFiles *delete_files = new DeleteFiles(app_->task_manager(), storage, true);
DeleteFiles *delete_files = new DeleteFiles(task_manager_, storage, true);
QObject::connect(delete_files, &DeleteFiles::Finished, this, &CollectionView::DeleteFilesFinished);
delete_files->Start(songs);

View File

@@ -30,10 +30,12 @@
#include <QPixmap>
#include <QSet>
#include "core/scoped_ptr.h"
#include "includes/scoped_ptr.h"
#include "includes/shared_ptr.h"
#include "core/song.h"
#include "widgets/autoexpandingtreeview.h"
class QSortFilterProxyModel;
class QMenu;
class QAction;
class QContextMenuEvent;
@@ -41,8 +43,20 @@ class QMouseEvent;
class QPaintEvent;
class QKeyEvent;
class Application;
class TaskManager;
class TagReaderClient;
class NetworkAccessManager;
class CollectionLibrary;
class CollectionBackend;
class CollectionModel;
class CollectionFilter;
class CollectionFilterWidget;
class DeviceManager;
class StreamingServices;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class LyricsProviders;
class EditTagDialog;
class OrganizeDialog;
@@ -57,8 +71,18 @@ class CollectionView : public AutoExpandingTreeView {
// Please note that the selection is recursive meaning that if for example an album is selected this will return all of it's songs.
SongList GetSelectedSongs() const;
void SetApplication(Application *app);
void SetFilter(CollectionFilterWidget *filter);
void Init(const SharedPtr<TaskManager> task_manager,
const SharedPtr<TagReaderClient> tagreader_client,
const SharedPtr<NetworkAccessManager> network,
const SharedPtr<AlbumCoverLoader> albumcover_loader,
const SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
const SharedPtr<CoverProviders> cover_providers,
const SharedPtr<LyricsProviders> lyrics_providers,
const SharedPtr<CollectionLibrary> collection,
const SharedPtr<DeviceManager> device_manager,
const SharedPtr<StreamingServices> streaming_services);
void SetFilterWidget(CollectionFilterWidget *filter_widget);
// QTreeView
void keyboardSearch(const QString &search) override;
@@ -82,7 +106,7 @@ class CollectionView : public AutoExpandingTreeView {
void EditTagError(const QString &message);
Q_SIGNALS:
void ShowConfigDialog();
void ShowSettingsDialog();
void TotalSongCountUpdated_();
void TotalArtistCountUpdated_();
@@ -120,8 +144,21 @@ class CollectionView : public AutoExpandingTreeView {
void SaveContainerPath(const QModelIndex &child);
private:
Application *app_;
CollectionFilterWidget *filter_;
SharedPtr<TaskManager> task_manager_;
SharedPtr<TagReaderClient> tagreader_client_;
SharedPtr<NetworkAccessManager> network_;
SharedPtr<DeviceManager> device_manager_;
SharedPtr<AlbumCoverLoader> albumcover_loader_;
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
SharedPtr<CollectionLibrary> collection_;
SharedPtr<CoverProviders> cover_providers_;
SharedPtr<LyricsProviders> lyrics_providers_;
SharedPtr<StreamingServices> streaming_services_;
SharedPtr<CollectionBackend> backend_;
CollectionModel *model_;
CollectionFilter *filter_;
CollectionFilterWidget *filter_widget_;
int total_song_count_;
int total_artist_count_;

View File

@@ -31,7 +31,7 @@
CollectionViewContainer::CollectionViewContainer(QWidget *parent) : QWidget(parent), ui_(new Ui_CollectionViewContainer) {
ui_->setupUi(this);
view()->SetFilter(filter_widget());
view()->SetFilterWidget(filter_widget());
QObject::connect(filter_widget(), &CollectionFilterWidget::UpPressed, view(), &CollectionView::UpAndFocus);
QObject::connect(filter_widget(), &CollectionFilterWidget::DownPressed, view(), &CollectionView::DownAndFocus);

View File

@@ -50,13 +50,13 @@
#include "core/taskmanager.h"
#include "core/settings.h"
#include "utilities/imageutils.h"
#include "utilities/timeconstants.h"
#include "constants/timeconstants.h"
#include "tagreader/tagreaderclient.h"
#include "collectiondirectory.h"
#include "collectionbackend.h"
#include "collectionwatcher.h"
#include "playlistparsers/cueparser.h"
#include "settings/collectionsettingspage.h"
#include "constants/collectionsettings.h"
#include "engine/ebur128measures.h"
#ifdef HAVE_SONGFINGERPRINTING
# include "engine/chromaprinter.h"
@@ -75,11 +75,16 @@ using namespace Qt::Literals::StringLiterals;
QStringList CollectionWatcher::sValidImages = QStringList() << u"jpg"_s << u"png"_s << u"gif"_s << u"jpeg"_s;
CollectionWatcher::CollectionWatcher(const Song::Source source, QObject *parent)
CollectionWatcher::CollectionWatcher(const Song::Source source,
const SharedPtr<TaskManager> task_manager,
const SharedPtr<TagReaderClient> tagreader_client,
const SharedPtr<CollectionBackend> backend,
QObject *parent)
: QObject(parent),
source_(source),
backend_(nullptr),
task_manager_(nullptr),
task_manager_(task_manager),
tagreader_client_(tagreader_client),
backend_(backend),
fs_watcher_(FileSystemWatcherInterface::Create(this)),
original_thread_(nullptr),
scan_on_startup_(true),
@@ -96,7 +101,7 @@ CollectionWatcher::CollectionWatcher(const Song::Source source, QObject *parent)
periodic_scan_timer_(new QTimer(this)),
rescan_paused_(false),
total_watches_(0),
cue_parser_(new CueParser(backend_, this)),
cue_parser_(new CueParser(tagreader_client, backend, this)),
last_scan_time_(0) {
setObjectName(source_ == Song::Source::Collection ? QLatin1String(metaObject()->className()) : QStringLiteral("%1%2").arg(Song::DescriptionForSource(source_), QLatin1String(metaObject()->className())));
@@ -196,29 +201,29 @@ void CollectionWatcher::ReloadSettings() {
const bool was_monitoring_before = monitor_;
Settings s;
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
s.beginGroup(CollectionSettings::kSettingsGroup);
if (source_ == Song::Source::Collection) {
scan_on_startup_ = s.value("startup_scan", true).toBool();
monitor_ = s.value("monitor", true).toBool();
scan_on_startup_ = s.value(CollectionSettings::kStartupScan, true).toBool();
monitor_ = s.value(CollectionSettings::kMonitor, true).toBool();
}
else {
scan_on_startup_ = true;
monitor_ = true;
}
const QStringList filters = s.value("cover_art_patterns", QStringList() << u"front"_s << u"cover"_s).toStringList();
const QStringList filters = s.value(CollectionSettings::kCoverArtPatterns, QStringList() << u"front"_s << u"cover"_s).toStringList();
if (source_ == Song::Source::Collection) {
song_tracking_ = s.value("song_tracking", false).toBool();
song_ebur128_loudness_analysis_ = s.value("song_ebur128_loudness_analysis", false).toBool();
mark_songs_unavailable_ = song_tracking_ ? true : s.value("mark_songs_unavailable", true).toBool();
song_tracking_ = s.value(CollectionSettings::kSongTracking, false).toBool();
song_ebur128_loudness_analysis_ = s.value(CollectionSettings::kSongENUR128LoudnessAnalysis, false).toBool();
mark_songs_unavailable_ = song_tracking_ ? true : s.value(CollectionSettings::kMarkSongsUnavailable, true).toBool();
}
else {
song_tracking_ = false;
song_ebur128_loudness_analysis_ = false;
mark_songs_unavailable_ = false;
}
expire_unavailable_songs_days_ = s.value("expire_unavailable_songs", 60).toInt();
overwrite_playcount_ = s.value("overwrite_playcount", false).toBool();
overwrite_rating_ = s.value("overwrite_rating", false).toBool();
expire_unavailable_songs_days_ = s.value(CollectionSettings::kExpireUnavailableSongs, 60).toInt();
overwrite_playcount_ = s.value(CollectionSettings::kOverwritePlaycount, false).toBool();
overwrite_rating_ = s.value(CollectionSettings::kOverwriteRating, false).toBool();
s.endGroup();
best_art_filters_.clear();
@@ -575,7 +580,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
album_art[dir_part] << child;
t->AddToProgress(1);
}
else if (TagReaderClient::Instance()->IsMediaFileBlocking(child)) {
else if (tagreader_client_->IsMediaFileBlocking(child)) {
files_on_disk << child;
}
else {
@@ -874,7 +879,7 @@ void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file,
}
Song song_on_disk(source_);
const TagReaderResult result = TagReaderClient::Instance()->ReadFileBlocking(file, &song_on_disk);
const TagReaderResult result = tagreader_client_->ReadFileBlocking(file, &song_on_disk);
if (result.success() && song_on_disk.is_valid()) {
song_on_disk.set_source(source_);
song_on_disk.set_directory_id(t->dir());
@@ -927,7 +932,7 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
}
else { // It's a normal media file
Song song(source_);
const TagReaderResult result = TagReaderClient::Instance()->ReadFileBlocking(file, &song);
const TagReaderResult result = tagreader_client_->ReadFileBlocking(file, &song);
if (result.success() && song.is_valid()) {
song.set_source(source_);
PerformEBUR128Analysis(song);

View File

@@ -36,28 +36,32 @@
#include <QMutex>
#include "collectiondirectory.h"
#include "core/shared_ptr.h"
#include "includes/shared_ptr.h"
#include "core/song.h"
class QThread;
class QTimer;
class TaskManager;
class TagReaderClient;
class CollectionBackend;
class FileSystemWatcherInterface;
class TaskManager;
class CueParser;
class CollectionWatcher : public QObject {
Q_OBJECT
public:
explicit CollectionWatcher(const Song::Source source, QObject *parent = nullptr);
explicit CollectionWatcher(const Song::Source source,
const SharedPtr<TaskManager> task_manager,
const SharedPtr<TagReaderClient> tagreader_client,
const SharedPtr<CollectionBackend> backend,
QObject *parent = nullptr);
~CollectionWatcher();
Song::Source source() { return source_; }
Song::Source source() const { return source_; }
void set_backend(SharedPtr<CollectionBackend> backend) { backend_ = backend; }
void set_task_manager(SharedPtr<TaskManager> task_manager) { task_manager_ = task_manager; }
void set_device_name(const QString &device_name) { device_name_ = device_name; }
void IncrementalScanAsync();
@@ -213,9 +217,12 @@ class CollectionWatcher : public QObject {
QString FindCueFilename(const QString &filename);
private:
Song::Source source_;
SharedPtr<CollectionBackend> backend_;
SharedPtr<TaskManager> task_manager_;
const Song::Source source_;
const SharedPtr<TaskManager> task_manager_;
const SharedPtr<TagReaderClient> tagreader_client_;
const SharedPtr<CollectionBackend> backend_;
QString device_name_;
FileSystemWatcherInterface *fs_watcher_;

View File

@@ -28,13 +28,13 @@
#include <QObject>
#include <QString>
#include "core/scoped_ptr.h"
#include "includes/scoped_ptr.h"
#include "collectionmodel.h"
#include "ui_groupbydialog.h"
class QWidget;
class GroupByDialogPrivate;
class Ui_GroupByDialog;
class GroupByDialog : public QDialog {
Q_OBJECT

View File

@@ -39,7 +39,7 @@
#include "core/logging.h"
#include "core/iconloader.h"
#include "core/settings.h"
#include "settings/collectionsettingspage.h"
#include "constants/collectionsettings.h"
#include "collectionmodel.h"
#include "savedgroupingmanager.h"
#include "ui_savedgroupingmanager.h"
@@ -77,7 +77,7 @@ SavedGroupingManager::~SavedGroupingManager() {
QString SavedGroupingManager::GetSavedGroupingsSettingsGroup(const QString &settings_group) {
if (settings_group.isEmpty() || settings_group == QLatin1String(CollectionSettingsPage::kSettingsGroup)) {
if (settings_group.isEmpty() || settings_group == QLatin1String(CollectionSettings::kSettingsGroup)) {
return QLatin1String(kSavedGroupingsSettingsGroup);
}