Refactoring

This commit is contained in:
Jonas Kvinge 2024-10-22 18:12:33 +02:00
parent 28222b1832
commit b97b772b2e
221 changed files with 2045 additions and 1530 deletions

View File

@ -176,10 +176,12 @@ if(UNIX AND NOT APPLE)
endif() endif()
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GOBJECT REQUIRED IMPORTED_TARGET gobject-2.0) pkg_check_modules(GOBJECT REQUIRED IMPORTED_TARGET gobject-2.0)
if(UNIX AND NOT APPLE)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
if(GIO_FOUND AND UNIX) if(GIO_FOUND AND UNIX)
pkg_check_modules(GIO_UNIX IMPORTED_TARGET gio-unix-2.0) pkg_check_modules(GIO_UNIX IMPORTED_TARGET gio-unix-2.0)
endif() endif()
endif()
pkg_check_modules(LIBCDIO IMPORTED_TARGET libcdio) pkg_check_modules(LIBCDIO IMPORTED_TARGET libcdio)
pkg_check_modules(GSTREAMER REQUIRED IMPORTED_TARGET gstreamer-1.0) pkg_check_modules(GSTREAMER REQUIRED IMPORTED_TARGET gstreamer-1.0)
pkg_check_modules(GSTREAMER_BASE REQUIRED IMPORTED_TARGET gstreamer-base-1.0) pkg_check_modules(GSTREAMER_BASE REQUIRED IMPORTED_TARGET gstreamer-base-1.0)
@ -327,12 +329,10 @@ optional_component(UDISKS2 ON "Devices: UDisks2 backend"
optional_component(GIO ON "Devices: GIO device backend" optional_component(GIO ON "Devices: GIO device backend"
DEPENDS "libgio" GIO_FOUND DEPENDS "libgio" GIO_FOUND
DEPENDS "Unix or Windows" "NOT APPLE"
) )
optional_component(GIO_UNIX ON "Devices: GIO device backend (Unix support)" optional_component(GIO_UNIX ON "Devices: GIO device backend (Unix support)"
DEPENDS "libgio-unix" GIO_UNIX_FOUND DEPENDS "libgio-unix" GIO_UNIX_FOUND
DEPENDS "Unix or Windows" "NOT APPLE"
) )
optional_component(AUDIOCD ON "Devices: Audio CD support" optional_component(AUDIOCD ON "Devices: Audio CD support"
@ -404,14 +404,11 @@ endif()
set(SOURCES set(SOURCES
src/core/logging.cpp src/core/logging.cpp
src/core/mainwindow.cpp
src/core/application.cpp
src/core/player.cpp
src/core/commandlineoptions.cpp src/core/commandlineoptions.cpp
src/core/database.cpp src/core/database.cpp
src/core/memorydatabase.cpp
src/core/sqlquery.cpp src/core/sqlquery.cpp
src/core/sqlrow.cpp src/core/sqlrow.cpp
src/core/metatypes.cpp
src/core/deletefiles.cpp src/core/deletefiles.cpp
src/core/filesystemmusicstorage.cpp src/core/filesystemmusicstorage.cpp
src/core/filesystemwatcherinterface.cpp src/core/filesystemwatcherinterface.cpp
@ -427,20 +424,29 @@ set(SOURCES
src/core/settingsprovider.cpp src/core/settingsprovider.cpp
src/core/signalchecker.cpp src/core/signalchecker.cpp
src/core/song.cpp src/core/song.cpp
src/core/songloader.cpp
src/core/stylehelper.cpp src/core/stylehelper.cpp
src/core/stylesheetloader.cpp src/core/stylesheetloader.cpp
src/core/taskmanager.cpp src/core/taskmanager.cpp
src/core/thread.cpp src/core/thread.cpp
src/core/urlhandlers.cpp
src/core/urlhandler.cpp src/core/urlhandler.cpp
src/core/iconloader.cpp src/core/iconloader.cpp
src/core/standarditemiconloader.cpp src/core/standarditemiconloader.cpp
src/core/scopedtransaction.cpp src/core/scopedtransaction.cpp
src/core/translations.cpp src/translations/translations.cpp
src/core/systemtrayicon.cpp src/core/systemtrayicon.cpp
src/core/localredirectserver.cpp src/core/localredirectserver.cpp
src/core/mimedata.cpp src/core/mimedata.cpp
src/core/temporaryfile.cpp src/core/temporaryfile.cpp
src/application/mainwindow.cpp
src/application/application.cpp
src/application/songloader.cpp
src/application/metatypes.cpp
src/player/playerinterface.cpp
src/player/player.cpp
src/utilities/strutils.cpp src/utilities/strutils.cpp
src/utilities/envutils.cpp src/utilities/envutils.cpp
src/utilities/colorutils.cpp src/utilities/colorutils.cpp
@ -749,14 +755,24 @@ set(SOURCES
src/transcoder/transcoderoptionsaac.cpp src/transcoder/transcoderoptionsaac.cpp
src/transcoder/transcoderoptionsasf.cpp src/transcoder/transcoderoptionsasf.cpp
src/transcoder/transcoderoptionsmp3.cpp src/transcoder/transcoderoptionsmp3.cpp
src/device/connecteddevice.cpp
src/device/devicedatabasebackend.cpp
src/device/devicelister.cpp
src/device/devicemanager.cpp
src/device/devicestatefiltermodel.cpp
src/device/filesystemdevice.cpp
src/device/deviceviewcontainer.cpp
src/device/deviceview.cpp
src/device/deviceproperties.cpp
src/device/deviceinfo.cpp
) )
set(HEADERS set(HEADERS
src/core/logging.h src/core/logging.h
src/core/mainwindow.h
src/core/application.h
src/core/player.h
src/core/database.h src/core/database.h
src/core/memorydatabase.h
src/core/deletefiles.h src/core/deletefiles.h
src/core/filesystemwatcherinterface.h src/core/filesystemwatcherinterface.h
src/core/mergedproxymodel.h src/core/mergedproxymodel.h
@ -766,15 +782,21 @@ set(HEADERS
src/core/networktimeouts.h src/core/networktimeouts.h
src/core/qtfslistener.h src/core/qtfslistener.h
src/core/settings.h src/core/settings.h
src/core/songloader.h
src/core/taskmanager.h src/core/taskmanager.h
src/core/thread.h src/core/thread.h
src/core/urlhandlers.h
src/core/urlhandler.h src/core/urlhandler.h
src/core/standarditemiconloader.h src/core/standarditemiconloader.h
src/core/mimedata.h src/core/mimedata.h
src/core/stylesheetloader.h src/core/stylesheetloader.h
src/core/localredirectserver.h src/core/localredirectserver.h
src/application/mainwindow.h
src/application/application.h
src/application/songloader.h
src/player/playerinterface.h
src/player/player.h
src/tagreader/tagreaderclient.h src/tagreader/tagreaderclient.h
src/tagreader/tagreaderreply.h src/tagreader/tagreaderreply.h
src/tagreader/tagreaderreadfilereply.h src/tagreader/tagreaderreadfilereply.h
@ -1020,11 +1042,22 @@ set(HEADERS
src/transcoder/transcoderoptionsaac.h src/transcoder/transcoderoptionsaac.h
src/transcoder/transcoderoptionsasf.h src/transcoder/transcoderoptionsasf.h
src/transcoder/transcoderoptionsmp3.h src/transcoder/transcoderoptionsmp3.h
src/device/connecteddevice.h
src/device/devicedatabasebackend.h
src/device/devicelister.h
src/device/devicemanager.h
src/device/devicestatefiltermodel.h
src/device/filesystemdevice.h
src/device/deviceviewcontainer.h
src/device/deviceview.h
src/device/deviceproperties.h
) )
set(UI set(UI
src/core/mainwindow.ui src/application/mainwindow.ui
src/collection/groupbydialog.ui src/collection/groupbydialog.ui
src/collection/collectionfilterwidget.ui src/collection/collectionfilterwidget.ui
@ -1106,6 +1139,10 @@ set(UI
src/transcoder/transcoderoptionsspeex.ui src/transcoder/transcoderoptionsspeex.ui
src/transcoder/transcoderoptionsasf.ui src/transcoder/transcoderoptionsasf.ui
src/transcoder/transcoderoptionsmp3.ui src/transcoder/transcoderoptionsmp3.ui
src/device/deviceproperties.ui
src/device/deviceviewcontainer.ui
) )
if(APPLE) if(APPLE)
@ -1234,33 +1271,6 @@ if(HAVE_MATE_GLOBALSHORTCUTS)
qt_add_dbus_interface(SOURCES src/globalshortcuts/org.mate.SettingsDaemon.MediaKeys.xml matesettingsdaemon) qt_add_dbus_interface(SOURCES src/globalshortcuts/org.mate.SettingsDaemon.MediaKeys.xml matesettingsdaemon)
endif() endif()
optional_source(UNIX
SOURCES
src/device/connecteddevice.cpp
src/device/devicedatabasebackend.cpp
src/device/devicelister.cpp
src/device/devicemanager.cpp
src/device/devicestatefiltermodel.cpp
src/device/filesystemdevice.cpp
src/device/deviceviewcontainer.cpp
src/device/deviceview.cpp
src/device/deviceproperties.cpp
src/device/deviceinfo.cpp
HEADERS
src/device/connecteddevice.h
src/device/devicedatabasebackend.h
src/device/devicelister.h
src/device/devicemanager.h
src/device/devicestatefiltermodel.h
src/device/filesystemdevice.h
src/device/deviceviewcontainer.h
src/device/deviceview.h
src/device/deviceproperties.h
UI
src/device/deviceproperties.ui
src/device/deviceviewcontainer.ui
)
if(UNIX) if(UNIX)
optional_source(HAVE_GIO SOURCES src/device/giolister.cpp HEADERS src/device/giolister.h) optional_source(HAVE_GIO SOURCES src/device/giolister.cpp HEADERS src/device/giolister.h)
endif() endif()

View File

@ -34,17 +34,16 @@
#include "core/logging.h" #include "core/logging.h"
#include "shared_ptr.h" #include "core/shared_ptr.h"
#include "lazy.h" #include "core/lazy.h"
#include "database.h" #include "core/database.h"
#include "taskmanager.h" #include "core/taskmanager.h"
#include "player.h" #include "core/networkaccessmanager.h"
#include "networkaccessmanager.h" #include "player/player.h"
#include "tagreader/tagreaderclient.h" #include "tagreader/tagreaderclient.h"
#include "engine/devicefinders.h" #include "engine/devicefinders.h"
#ifndef Q_OS_WIN #include "core/urlhandlers.h"
#include "device/devicemanager.h" #include "device/devicemanager.h"
#endif
#include "collection/collection.h" #include "collection/collection.h"
#include "playlist/playlistbackend.h" #include "playlist/playlistbackend.h"
#include "playlist/playlistmanager.h" #include "playlist/playlistmanager.h"
@ -120,42 +119,41 @@ class ApplicationImpl {
return client; return client;
}), }),
database_([app]() { database_([app]() {
Database *db = new Database(app); Database *database = new Database(app->task_manager());
app->MoveToNewThread(db); app->MoveToNewThread(database);
QTimer::singleShot(30s, db, &Database::DoBackup); QTimer::singleShot(30s, database, &Database::DoBackup);
return db; return database;
}), }),
task_manager_([]() { return new TaskManager(); }), task_manager_([]() { return new TaskManager(); }),
player_([app]() { return new Player(app); }), player_([app]() { return new Player(app->task_manager(), app->url_handlers(), app->playlist_manager()); }),
network_([]() { return new NetworkAccessManager(); }), network_([]() { return new NetworkAccessManager(); }),
device_finders_([]() { return new DeviceFinders(); }), device_finders_([]() { return new DeviceFinders(); }),
#ifndef Q_OS_WIN url_handlers_([]() { return new UrlHandlers(); }),
device_manager_([app]() { return new DeviceManager(app); }), device_manager_([app]() { return new DeviceManager(app->task_manager(), app->database()); }),
#endif collection_([app]() { return new SCollection(app->database(), app->task_manager(), app->album_cover_loader()); }),
collection_([app]() { return new SCollection(app); }),
playlist_backend_([this, app]() { playlist_backend_([this, app]() {
PlaylistBackend *backend = new PlaylistBackend(app); PlaylistBackend *playlist_backend = new PlaylistBackend(app->database(), app->collection_backend());
app->MoveToThread(backend, database_->thread()); app->MoveToThread(playlist_backend, database_->thread());
return backend; return playlist_backend;
}), }),
playlist_manager_([app]() { return new PlaylistManager(app); }), playlist_manager_([app]() { return new PlaylistManager(app->player(), app->url_handlers()); }),
cover_providers_([app]() { cover_providers_([app]() {
CoverProviders *cover_providers = new CoverProviders(); CoverProviders *cover_providers = new CoverProviders();
// Initialize the repository of cover providers. // Initialize the repository of cover providers.
cover_providers->AddProvider(new LastFmCoverProvider(app, app->network())); cover_providers->AddProvider(new LastFmCoverProvider(app->network()));
cover_providers->AddProvider(new MusicbrainzCoverProvider(app, app->network())); cover_providers->AddProvider(new MusicbrainzCoverProvider(app->network()));
cover_providers->AddProvider(new DiscogsCoverProvider(app, app->network())); cover_providers->AddProvider(new DiscogsCoverProvider(app->network()));
cover_providers->AddProvider(new DeezerCoverProvider(app, app->network())); cover_providers->AddProvider(new DeezerCoverProvider(app->network()));
cover_providers->AddProvider(new MusixmatchCoverProvider(app, app->network())); cover_providers->AddProvider(new MusixmatchCoverProvider(app->network()));
cover_providers->AddProvider(new OpenTidalCoverProvider(app, app->network())); cover_providers->AddProvider(new OpenTidalCoverProvider(app->network()));
#ifdef HAVE_TIDAL #ifdef HAVE_TIDAL
cover_providers->AddProvider(new TidalCoverProvider(app, app->network())); cover_providers->AddProvider(new TidalCoverProvider(app->streaming_services()->Service<TidalService>(), app->network()));
#endif #endif
#ifdef HAVE_SPOTIFY #ifdef HAVE_SPOTIFY
cover_providers->AddProvider(new SpotifyCoverProvider(app, app->network())); cover_providers->AddProvider(new SpotifyCoverProvider(app->streaming_services()->Service<SpotifyService>(), app->network()));
#endif #endif
#ifdef HAVE_QOBUZ #ifdef HAVE_QOBUZ
cover_providers->AddProvider(new QobuzCoverProvider(app, app->network())); cover_providers->AddProvider(new QobuzCoverProvider(app->streaming_services()->Service<QobuzService>(), app->network()));
#endif #endif
cover_providers->ReloadSettings(); cover_providers->ReloadSettings();
return cover_providers; return cover_providers;
@ -165,7 +163,7 @@ class ApplicationImpl {
app->MoveToNewThread(loader); app->MoveToNewThread(loader);
return loader; return loader;
}), }),
current_albumcover_loader_([app]() { return new CurrentAlbumCoverLoader(app); }), current_albumcover_loader_([app]() { return new CurrentAlbumCoverLoader(app->album_cover_loader()); }),
lyrics_providers_([app]() { lyrics_providers_([app]() {
LyricsProviders *lyrics_providers = new LyricsProviders(app); LyricsProviders *lyrics_providers = new LyricsProviders(app);
// Initialize the repository of lyrics providers. // Initialize the repository of lyrics providers.
@ -185,33 +183,33 @@ class ApplicationImpl {
streaming_services_([app]() { streaming_services_([app]() {
StreamingServices *streaming_services = new StreamingServices(); StreamingServices *streaming_services = new StreamingServices();
#ifdef HAVE_SUBSONIC #ifdef HAVE_SUBSONIC
streaming_services->AddService(make_shared<SubsonicService>(app)); streaming_services->AddService(make_shared<SubsonicService>(app->task_manager(), app->database(), app->url_handlers(), app->album_cover_loader()));
#endif #endif
#ifdef HAVE_TIDAL #ifdef HAVE_TIDAL
streaming_services->AddService(make_shared<TidalService>(app)); streaming_services->AddService(make_shared<TidalService>(app->task_manager(), app->database(), app->network(), app->url_handlers(), app->album_cover_loader()));
#endif #endif
#ifdef HAVE_SPOTIFY #ifdef HAVE_SPOTIFY
streaming_services->AddService(make_shared<SpotifyService>(app)); streaming_services->AddService(make_shared<SpotifyService>(app->task_manager(), app->database(), app->network(), app->album_cover_loader()));
#endif #endif
#ifdef HAVE_QOBUZ #ifdef HAVE_QOBUZ
streaming_services->AddService(make_shared<QobuzService>(app)); streaming_services->AddService(make_shared<QobuzService>(app->task_manager(), app->database(), app->network(), app->url_handlers(), app->album_cover_loader()));
#endif #endif
return streaming_services; return streaming_services;
}), }),
radio_services_([app]() { return new RadioServices(app); }), radio_services_([app]() { return new RadioServices(app->task_manager(), app->network(), app->database(), app->album_cover_loader()); }),
scrobbler_([app]() { scrobbler_([app]() {
AudioScrobbler *scrobbler = new AudioScrobbler(app); AudioScrobbler *scrobbler = new AudioScrobbler(app);
scrobbler->AddService(make_shared<LastFMScrobbler>(scrobbler->settings(), app->network())); scrobbler->AddService(make_shared<LastFMScrobbler>(scrobbler->settings(), app->network()));
scrobbler->AddService(make_shared<LibreFMScrobbler>(scrobbler->settings(), app->network())); scrobbler->AddService(make_shared<LibreFMScrobbler>(scrobbler->settings(), app->network()));
scrobbler->AddService(make_shared<ListenBrainzScrobbler>(scrobbler->settings(), app->network())); scrobbler->AddService(make_shared<ListenBrainzScrobbler>(scrobbler->settings(), app->network()));
#ifdef HAVE_SUBSONIC #ifdef HAVE_SUBSONIC
scrobbler->AddService(make_shared<SubsonicScrobbler>(scrobbler->settings(), app)); scrobbler->AddService(make_shared<SubsonicScrobbler>(scrobbler->settings(), app->streaming_services()->Service<SubsonicService>(), app));
#endif #endif
return scrobbler; return scrobbler;
}), }),
#ifdef HAVE_MOODBAR #ifdef HAVE_MOODBAR
moodbar_loader_([app]() { return new MoodbarLoader(app); }), moodbar_loader_([app]() { return new MoodbarLoader(app); }),
moodbar_controller_([app]() { return new MoodbarController(app); }), moodbar_controller_([app]() { return new MoodbarController(app->player(), app->moodbar_loader()); }),
#endif #endif
lastfm_import_([app]() { return new LastFMImport(app->network()); }) lastfm_import_([app]() { return new LastFMImport(app->network()); })
{} {}
@ -222,9 +220,8 @@ class ApplicationImpl {
Lazy<Player> player_; Lazy<Player> player_;
Lazy<NetworkAccessManager> network_; Lazy<NetworkAccessManager> network_;
Lazy<DeviceFinders> device_finders_; Lazy<DeviceFinders> device_finders_;
#ifndef Q_OS_WIN Lazy<UrlHandlers> url_handlers_;
Lazy<DeviceManager> device_manager_; Lazy<DeviceManager> device_manager_;
#endif
Lazy<SCollection> collection_; Lazy<SCollection> collection_;
Lazy<PlaylistBackend> playlist_backend_; Lazy<PlaylistBackend> playlist_backend_;
Lazy<PlaylistManager> playlist_manager_; Lazy<PlaylistManager> playlist_manager_;
@ -252,7 +249,7 @@ Application::Application(QObject *parent)
collection()->Init(); collection()->Init();
tag_reader_client(); tag_reader_client();
QObject::connect(&*database(), &Database::Error, this, &Application::ErrorAdded); //QObject::connect(&*database(), &Database::Error, this, &Application::ErrorAdded);
} }
@ -298,9 +295,7 @@ void Application::Exit() {
<< &*collection() << &*collection()
<< &*playlist_backend() << &*playlist_backend()
<< &*album_cover_loader() << &*album_cover_loader()
#ifndef Q_OS_WIN
<< &*device_manager() << &*device_manager()
#endif
<< &*streaming_services() << &*streaming_services()
<< &*radio_services()->radio_backend(); << &*radio_services()->radio_backend();
@ -316,10 +311,8 @@ void Application::Exit() {
QObject::connect(&*album_cover_loader(), &AlbumCoverLoader::ExitFinished, this, &Application::ExitReceived); QObject::connect(&*album_cover_loader(), &AlbumCoverLoader::ExitFinished, this, &Application::ExitReceived);
album_cover_loader()->ExitAsync(); album_cover_loader()->ExitAsync();
#ifndef Q_OS_WIN
QObject::connect(&*device_manager(), &DeviceManager::ExitFinished, this, &Application::ExitReceived); QObject::connect(&*device_manager(), &DeviceManager::ExitFinished, this, &Application::ExitReceived);
device_manager()->Exit(); device_manager()->Exit();
#endif
QObject::connect(&*streaming_services(), &StreamingServices::ExitFinished, this, &Application::ExitReceived); QObject::connect(&*streaming_services(), &StreamingServices::ExitFinished, this, &Application::ExitReceived);
streaming_services()->Exit(); streaming_services()->Exit();
@ -345,19 +338,14 @@ void Application::ExitReceived() {
} }
void Application::AddError(const QString &message) { Q_EMIT ErrorAdded(message); }
void Application::ReloadSettings() { Q_EMIT SettingsChanged(); }
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { Q_EMIT SettingsDialogRequested(page); }
SharedPtr<TagReaderClient> Application::tag_reader_client() const { return p_->tag_reader_client_.ptr(); } SharedPtr<TagReaderClient> Application::tag_reader_client() const { return p_->tag_reader_client_.ptr(); }
SharedPtr<Database> Application::database() const { return p_->database_.ptr(); } SharedPtr<Database> Application::database() const { return p_->database_.ptr(); }
SharedPtr<TaskManager> Application::task_manager() const { return p_->task_manager_.ptr(); } SharedPtr<TaskManager> Application::task_manager() const { return p_->task_manager_.ptr(); }
SharedPtr<Player> Application::player() const { return p_->player_.ptr(); } SharedPtr<Player> Application::player() const { return p_->player_.ptr(); }
SharedPtr<NetworkAccessManager> Application::network() const { return p_->network_.ptr(); } SharedPtr<NetworkAccessManager> Application::network() const { return p_->network_.ptr(); }
SharedPtr<DeviceFinders> Application::device_finders() const { return p_->device_finders_.ptr(); } SharedPtr<DeviceFinders> Application::device_finders() const { return p_->device_finders_.ptr(); }
#ifndef Q_OS_WIN SharedPtr<UrlHandlers> Application::url_handlers() const { return p_->url_handlers_.ptr(); }
SharedPtr<DeviceManager> Application::device_manager() const { return p_->device_manager_.ptr(); } SharedPtr<DeviceManager> Application::device_manager() const { return p_->device_manager_.ptr(); }
#endif
SharedPtr<SCollection> Application::collection() const { return p_->collection_.ptr(); } SharedPtr<SCollection> Application::collection() const { return p_->collection_.ptr(); }
SharedPtr<CollectionBackend> Application::collection_backend() const { return collection()->backend(); } SharedPtr<CollectionBackend> Application::collection_backend() const { return collection()->backend(); }
CollectionModel *Application::collection_model() const { return collection()->model(); } CollectionModel *Application::collection_model() const { return collection()->model(); }

View File

@ -29,10 +29,8 @@
#include <QList> #include <QList>
#include <QString> #include <QString>
#include "scoped_ptr.h" #include "core/scoped_ptr.h"
#include "shared_ptr.h" #include "core/shared_ptr.h"
#include "settings/settingsdialog.h"
class QThread; class QThread;
@ -41,6 +39,7 @@ class ApplicationImpl;
class TagReaderClient; class TagReaderClient;
class Database; class Database;
class DeviceFinders; class DeviceFinders;
class UrlHandlers;
class Player; class Player;
class NetworkAccessManager; class NetworkAccessManager;
class SCollection; class SCollection;
@ -48,9 +47,7 @@ class CollectionBackend;
class CollectionModel; class CollectionModel;
class PlaylistBackend; class PlaylistBackend;
class PlaylistManager; class PlaylistManager;
#ifndef Q_OS_WIN
class DeviceManager; class DeviceManager;
#endif
class CoverProviders; class CoverProviders;
class AlbumCoverLoader; class AlbumCoverLoader;
class CurrentAlbumCoverLoader; class CurrentAlbumCoverLoader;
@ -78,9 +75,8 @@ class Application : public QObject {
SharedPtr<Player> player() const; SharedPtr<Player> player() const;
SharedPtr<NetworkAccessManager> network() const; SharedPtr<NetworkAccessManager> network() const;
SharedPtr<DeviceFinders> device_finders() const; SharedPtr<DeviceFinders> device_finders() const;
#ifndef Q_OS_WIN SharedPtr<UrlHandlers> url_handlers() const;
SharedPtr<DeviceManager> device_manager() const; SharedPtr<DeviceManager> device_manager() const;
#endif
SharedPtr<SCollection> collection() const; SharedPtr<SCollection> collection() const;
SharedPtr<CollectionBackend> collection_backend() const; SharedPtr<CollectionBackend> collection_backend() const;
@ -115,23 +111,13 @@ class Application : public QObject {
private Q_SLOTS: private Q_SLOTS:
void ExitReceived(); void ExitReceived();
public Q_SLOTS:
void AddError(const QString &message);
void ReloadSettings();
void OpenSettingsDialogAtPage(SettingsDialog::Page page);
Q_SIGNALS: Q_SIGNALS:
void ErrorAdded(const QString &message);
void SettingsChanged();
void SettingsDialogRequested(const SettingsDialog::Page page);
void ExitFinished(); void ExitFinished();
void ClearPixmapDiskCache();
private: private:
ScopedPtr<ApplicationImpl> p_; ScopedPtr<ApplicationImpl> p_;
QList<QThread*> threads_; QList<QThread*> threads_;
QList<QObject*> wait_for_exit_; QList<QObject*> wait_for_exit_;
}; };
#endif // APPLICATION_H #endif // APPLICATION_H

View File

@ -84,32 +84,32 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "shared_ptr.h" #include "constants/filenameconstants.h"
#include "commandlineoptions.h" #include "constants/timeconstants.h"
#include "mimedata.h" #include "core/shared_ptr.h"
#include "iconloader.h" #include "core/commandlineoptions.h"
#include "taskmanager.h" #include "core/mimedata.h"
#include "song.h" #include "core/iconloader.h"
#include "stylehelper.h" #include "core/taskmanager.h"
#include "stylesheetloader.h" #include "core/song.h"
#include "core/stylehelper.h"
#include "core/stylesheetloader.h"
#include "application.h" #include "application.h"
#include "database.h" #include "core/database.h"
#include "player.h" #include "core/filesystemmusicstorage.h"
#include "filesystemmusicstorage.h" #include "core/deletefiles.h"
#include "deletefiles.h"
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
# include "mac_startup.h" # include "core/mac_startup.h"
# include "macsystemtrayicon.h" # include "core/macsystemtrayicon.h"
# include "utilities/macosutils.h" # include "utilities/macosutils.h"
#else #else
# include "qtsystemtrayicon.h" # include "core/qtsystemtrayicon.h"
#endif #endif
#include "networkaccessmanager.h" #include "core/settings.h"
#include "settings.h"
#include "utilities/envutils.h" #include "utilities/envutils.h"
#include "utilities/filemanagerutils.h" #include "utilities/filemanagerutils.h"
#include "utilities/timeconstants.h"
#include "utilities/screenutils.h" #include "utilities/screenutils.h"
#include "player/player.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "dialogs/errordialog.h" #include "dialogs/errordialog.h"
#include "dialogs/about.h" #include "dialogs/about.h"
@ -205,6 +205,7 @@
#ifdef HAVE_MOODBAR #ifdef HAVE_MOODBAR
# include "moodbar/moodbarcontroller.h" # include "moodbar/moodbarcontroller.h"
# include "moodbar/moodbarloader.h"
# include "moodbar/moodbarproxystyle.h" # include "moodbar/moodbarproxystyle.h"
#endif #endif
@ -213,7 +214,7 @@
#include "organize/organizeerrordialog.h" #include "organize/organizeerrordialog.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# include "windows7thumbbar.h" # include "core/windows7thumbbar.h"
#endif #endif
#ifdef HAVE_QTSPARKLE #ifdef HAVE_QTSPARKLE
@ -226,7 +227,6 @@ using namespace std::chrono_literals;
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
const char *MainWindow::kSettingsGroup = "MainWindow"; const char *MainWindow::kSettingsGroup = "MainWindow";
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
namespace { namespace {
const int kTrackSliderUpdateTimeMs = 200; const int kTrackSliderUpdateTimeMs = 200;
@ -259,7 +259,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
tray_icon_(tray_icon), tray_icon_(tray_icon),
osd_(osd), osd_(osd),
console_([app]() { console_([app]() {
Console *console = new Console(app); Console *console = new Console(app->database());
return console; return console;
}), }),
edit_tag_dialog_(std::bind(&MainWindow::CreateEditTagDialog, this)), edit_tag_dialog_(std::bind(&MainWindow::CreateEditTagDialog, this)),
@ -277,7 +277,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
queue_view_(new QueueView(this)), queue_view_(new QueueView(this)),
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)), settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
cover_manager_([this, app]() { cover_manager_([this, app]() {
AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend(), this); AlbumCoverManager *cover_manager = new AlbumCoverManager(app->network(), app->collection_backend(), app->tag_reader_client(), app->album_cover_loader(), app->current_albumcover_loader(), app->cover_providers(), app->streaming_services(), this);
cover_manager->Init(); cover_manager->Init();
// Cover manager connections // Cover manager connections
@ -300,18 +300,18 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
QObject::connect(add_stream_dialog, &AddStreamDialog::accepted, this, &MainWindow::AddStreamAccepted); QObject::connect(add_stream_dialog, &AddStreamDialog::accepted, this, &MainWindow::AddStreamAccepted);
return add_stream_dialog; return add_stream_dialog;
}), }),
smartplaylists_view_(new SmartPlaylistsViewContainer(app, this)), smartplaylists_view_(new SmartPlaylistsViewContainer(app->player(), app->playlist_manager(), app->collection_backend(), app->moodbar_loader(), app->current_albumcover_loader(), this)),
#ifdef HAVE_SUBSONIC #ifdef HAVE_SUBSONIC
subsonic_view_(new StreamingSongsView(app_, app->streaming_services()->ServiceBySource(Song::Source::Subsonic), QLatin1String(SubsonicSettingsPage::kSettingsGroup), SettingsDialog::Page::Subsonic, this)), subsonic_view_(new StreamingSongsView(app->streaming_services()->ServiceBySource(Song::Source::Subsonic), QLatin1String(SubsonicSettingsPage::kSettingsGroup), SettingsDialog::Page::Subsonic, this)),
#endif #endif
#ifdef HAVE_TIDAL #ifdef HAVE_TIDAL
tidal_view_(new StreamingTabsView(app_, app->streaming_services()->ServiceBySource(Song::Source::Tidal), QLatin1String(TidalSettingsPage::kSettingsGroup), SettingsDialog::Page::Tidal, this)), tidal_view_(new StreamingTabsView(app->streaming_services()->ServiceBySource(Song::Source::Tidal), app->album_cover_loader(), QLatin1String(TidalSettingsPage::kSettingsGroup), SettingsDialog::Page::Tidal, this)),
#endif #endif
#ifdef HAVE_SPOTIFY #ifdef HAVE_SPOTIFY
spotify_view_(new StreamingTabsView(app_, app->streaming_services()->ServiceBySource(Song::Source::Spotify), QLatin1String(SpotifySettingsPage::kSettingsGroup), SettingsDialog::Page::Spotify, this)), spotify_view_(new StreamingTabsView(app->streaming_services()->ServiceBySource(Song::Source::Spotify), app->album_cover_loader(), QLatin1String(SpotifySettingsPage::kSettingsGroup), SettingsDialog::Page::Spotify, this)),
#endif #endif
#ifdef HAVE_QOBUZ #ifdef HAVE_QOBUZ
qobuz_view_(new StreamingTabsView(app_, app->streaming_services()->ServiceBySource(Song::Source::Qobuz), QLatin1String(QobuzSettingsPage::kSettingsGroup), SettingsDialog::Page::Qobuz, this)), qobuz_view_(new StreamingTabsView(app->streaming_services()->ServiceBySource(Song::Source::Qobuz), app->album_cover_loader(), QLatin1String(QobuzSettingsPage::kSettingsGroup), SettingsDialog::Page::Qobuz, this)),
#endif #endif
radio_view_(new RadioViewContainer(this)), radio_view_(new RadioViewContainer(this)),
lastfm_import_dialog_(new LastFMImportDialog(app_->lastfm_import(), this)), lastfm_import_dialog_(new LastFMImportDialog(app_->lastfm_import(), this)),
@ -358,19 +358,19 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
qLog(Debug) << "Starting"; qLog(Debug) << "Starting";
QObject::connect(app, &Application::ErrorAdded, this, &MainWindow::ShowErrorDialog);
QObject::connect(app, &Application::SettingsDialogRequested, this, &MainWindow::OpenSettingsDialogAtPage);
// Initialize the UI // Initialize the UI
ui_->setupUi(this); ui_->setupUi(this);
setWindowIcon(IconLoader::Load(u"strawberry"_s)); setWindowIcon(IconLoader::Load(u"strawberry"_s));
album_cover_choice_controller_->Init(app); QObject::connect(&*app->database(), &Database::Error, this, &MainWindow::ShowErrorDialog);
//QObject::connect(app, &Application::SettingsDialogRequested, this, &MainWindow::OpenSettingsDialogAtPage);
album_cover_choice_controller_->Init(app->network(), app->collection()->backend(), app->album_cover_loader(), app->current_albumcover_loader(), app->cover_providers(), app->streaming_services());
ui_->multi_loading_indicator->SetTaskManager(app_->task_manager()); ui_->multi_loading_indicator->SetTaskManager(app_->task_manager());
context_view_->Init(app_, collection_view_->view(), album_cover_choice_controller_); context_view_->Init(collection_view_->view(), album_cover_choice_controller_, app_->lyrics_providers());
ui_->widget_playing->Init(app_, album_cover_choice_controller_); ui_->widget_playing->Init(album_cover_choice_controller_);
// Initialize the search widget // Initialize the search widget
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker()); StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
@ -423,14 +423,14 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
ui_->playlist->SetManager(app_->playlist_manager()); ui_->playlist->SetManager(app_->playlist_manager());
ui_->playlist->view()->Init(app_); ui_->playlist->view()->Init(app_->player(), app_->playlist_manager(), app_->collection_backend(), app_->moodbar_loader(), app_->current_albumcover_loader());
collection_view_->view()->setModel(app_->collection()->model()->filter()); collection_view_->view()->setModel(app_->collection()->model()->filter());
collection_view_->view()->SetApplication(app_); collection_view_->view()->Init(app->task_manager(), app->network(), app->device_manager());
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
device_view_->view()->SetApplication(app_); device_view_->view()->Init(app->task_manager(), app->device_manager(), app->collection_model()->directory_model());
#endif #endif
playlist_list_->SetApplication(app_); playlist_list_->Init(app_->task_manager(), app_->player(), app_->playlist_manager(), app_->playlist_backend(), app_->device_manager());
organize_dialog_->SetDestinationModel(app_->collection()->model()->directory_model()); organize_dialog_->SetDestinationModel(app_->collection()->model()->directory_model());
@ -604,6 +604,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
QObject::connect(&*app_->player(), &Player::VolumeChanged, osd_, &OSDBase::VolumeChanged); QObject::connect(&*app_->player(), &Player::VolumeChanged, osd_, &OSDBase::VolumeChanged);
QObject::connect(&*app_->player(), &Player::VolumeChanged, ui_->volume, &VolumeSlider::SetValue); QObject::connect(&*app_->player(), &Player::VolumeChanged, ui_->volume, &VolumeSlider::SetValue);
QObject::connect(&*app_->player(), &Player::ForceShowOSD, this, &MainWindow::ForceShowOSD); QObject::connect(&*app_->player(), &Player::ForceShowOSD, this, &MainWindow::ForceShowOSD);
QObject::connect(&*app_->current_albumcover_loader(), &CurrentAlbumCoverLoader::ThumbnailLoaded, osd_, &OSDBase::AlbumCoverLoaded);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::AllPlaylistsLoaded, &*app->player(), &Player::PlaylistsLoaded); QObject::connect(&*app_->playlist_manager(), &PlaylistManager::AllPlaylistsLoaded, &*app->player(), &Player::PlaylistsLoaded);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &MainWindow::SongChanged); QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &MainWindow::SongChanged);
@ -641,6 +642,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
QObject::connect(&*app_->task_manager(), &TaskManager::PauseCollectionWatchers, &*app_->collection(), &SCollection::PauseWatcher); QObject::connect(&*app_->task_manager(), &TaskManager::PauseCollectionWatchers, &*app_->collection(), &SCollection::PauseWatcher);
QObject::connect(&*app_->task_manager(), &TaskManager::ResumeCollectionWatchers, &*app_->collection(), &SCollection::ResumeWatcher); QObject::connect(&*app_->task_manager(), &TaskManager::ResumeCollectionWatchers, &*app_->collection(), &SCollection::ResumeWatcher);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, &*app_->current_albumcover_loader(), &CurrentAlbumCoverLoader::LoadAlbumCover);
QObject::connect(&*app_->current_albumcover_loader(), &CurrentAlbumCoverLoader::AlbumCoverLoaded, this, &MainWindow::AlbumCoverLoaded); QObject::connect(&*app_->current_albumcover_loader(), &CurrentAlbumCoverLoader::AlbumCoverLoaded, this, &MainWindow::AlbumCoverLoaded);
QObject::connect(album_cover_choice_controller_, &AlbumCoverChoiceController::Error, this, &MainWindow::ShowErrorDialog); QObject::connect(album_cover_choice_controller_, &AlbumCoverChoiceController::Error, this, &MainWindow::ShowErrorDialog);
QObject::connect(album_cover_choice_controller_->cover_from_file_action(), &QAction::triggered, this, &MainWindow::LoadCoverFromFile); QObject::connect(album_cover_choice_controller_->cover_from_file_action(), &QAction::triggered, this, &MainWindow::LoadCoverFromFile);
@ -849,11 +851,14 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
ui_->status_bar_stack->setCurrentWidget(ui_->playlist_summary_page); ui_->status_bar_stack->setCurrentWidget(ui_->playlist_summary_page);
QObject::connect(ui_->multi_loading_indicator, &MultiLoadingIndicator::TaskCountChange, this, &MainWindow::TaskCountChanged); QObject::connect(ui_->multi_loading_indicator, &MultiLoadingIndicator::TaskCountChange, this, &MainWindow::TaskCountChanged);
ui_->track_slider->SetApplication(app); ui_->track_slider->Init();
#ifdef HAVE_MOODBAR #ifdef HAVE_MOODBAR
// Moodbar connections // Moodbar connections
QObject::connect(&*app_->moodbar_controller(), &MoodbarController::CurrentMoodbarDataChanged, ui_->track_slider->moodbar_style(), &MoodbarProxyStyle::SetMoodbarData); QObject::connect(&*app_->moodbar_controller(), &MoodbarController::CurrentMoodbarDataChanged, ui_->track_slider->moodbar_style(), &MoodbarProxyStyle::SetMoodbarData);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, &*app_->moodbar_controller(), &MoodbarController::CurrentSongChanged);
QObject::connect(&*app_->player(), &Player::Stopped, &*app_->moodbar_controller(), &MoodbarController::PlaybackStopped);
QObject::connect(ui_->track_slider->moodbar_style(), &MoodbarProxyStyle::SettingsChanged, this, &MainWindow::MoodbarSettingsChanged);
#endif #endif
// Playing widget // Playing widget
@ -875,7 +880,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
css_loader->SetStyleSheet(this, u":/style/strawberry.css"_s); css_loader->SetStyleSheet(this, u":/style/strawberry.css"_s);
// Load playlists // Load playlists
app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist); app_->playlist_manager()->Init(app_->task_manager(), app->url_handlers(), app_->collection_backend(), app_->playlist_backend(), app_->current_albumcover_loader(), ui_->playlist_sequence, ui_->playlist);
queue_view_->SetPlaylistManager(app_->playlist_manager()); queue_view_->SetPlaylistManager(app_->playlist_manager());
@ -902,6 +907,8 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
QObject::connect(&*app_->lastfm_import(), &LastFMImport::FinishedWithError, lastfm_import_dialog_, &LastFMImportDialog::FinishedWithError); QObject::connect(&*app_->lastfm_import(), &LastFMImport::FinishedWithError, lastfm_import_dialog_, &LastFMImportDialog::FinishedWithError);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateTotal, lastfm_import_dialog_, &LastFMImportDialog::UpdateTotal); QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateTotal, lastfm_import_dialog_, &LastFMImportDialog::UpdateTotal);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateProgress, lastfm_import_dialog_, &LastFMImportDialog::UpdateProgress); QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateProgress, lastfm_import_dialog_, &LastFMImportDialog::UpdateProgress);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateLastPlayed, &*app_->collection_backend(), &CollectionBackend::UpdateLastPlayed);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdatePlayCount, &*app_->collection_backend(), &CollectionBackend::UpdatePlayCount);
// Load settings // Load settings
qLog(Debug) << "Loading settings"; qLog(Debug) << "Loading settings";
@ -1208,7 +1215,7 @@ void MainWindow::ReloadAllSettings() {
ReloadSettings(); ReloadSettings();
// Other settings // Other settings
app_->ReloadSettings(); //app_->ReloadSettings();
app_->collection()->ReloadSettings(); app_->collection()->ReloadSettings();
app_->player()->ReloadSettings(); app_->player()->ReloadSettings();
collection_view_->ReloadSettings(); collection_view_->ReloadSettings();
@ -1228,18 +1235,30 @@ void MainWindow::ReloadAllSettings() {
app_->lyrics_providers()->ReloadSettings(); app_->lyrics_providers()->ReloadSettings();
#ifdef HAVE_MOODBAR #ifdef HAVE_MOODBAR
app_->moodbar_controller()->ReloadSettings(); app_->moodbar_controller()->ReloadSettings();
app_->moodbar_loader()->ReloadSettings();
ui_->track_slider->moodbar_style()->ReloadSettings();
#endif #endif
#ifdef HAVE_SUBSONIC #ifdef HAVE_SUBSONIC
subsonic_view_->ReloadSettings(); subsonic_view_->ReloadSettings();
#endif #endif
#ifdef HAVE_TIDAL #ifdef HAVE_TIDAL
tidal_view_->ReloadSettings(); tidal_view_->ReloadSettings();
tidal_view_->search_view()->ReloadSettings();
#endif #endif
#ifdef HAVE_SPOTIFY #ifdef HAVE_SPOTIFY
spotify_view_->ReloadSettings(); spotify_view_->ReloadSettings();
spotify_view_->search_view()->ReloadSettings();
#endif #endif
#ifdef HAVE_QOBUZ #ifdef HAVE_QOBUZ
qobuz_view_->ReloadSettings(); qobuz_view_->ReloadSettings();
qobuz_view_->search_view()->ReloadSettings();
#endif
}
void MainWindow::MoodbarSettingsChanged() {
#ifdef HAVE_MOODBAR
#endif #endif
} }
@ -2810,7 +2829,7 @@ void MainWindow::ShowEqualizer() {
SettingsDialog *MainWindow::CreateSettingsDialog() { SettingsDialog *MainWindow::CreateSettingsDialog() {
SettingsDialog *settings_dialog = new SettingsDialog(app_, osd_, this); SettingsDialog *settings_dialog = new SettingsDialog(app_->player(), app_->device_finders(), app_->collection(), app_->cover_providers(), app_->lyrics_providers(), app_->scrobbler(), app_->streaming_services(), osd_, this);
#ifdef HAVE_GLOBALSHORTCUTS #ifdef HAVE_GLOBALSHORTCUTS
settings_dialog->SetGlobalShortcutManager(globalshortcuts_manager_); settings_dialog->SetGlobalShortcutManager(globalshortcuts_manager_);
#endif #endif
@ -2838,7 +2857,7 @@ void MainWindow::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
EditTagDialog *MainWindow::CreateEditTagDialog() { EditTagDialog *MainWindow::CreateEditTagDialog() {
EditTagDialog *edit_tag_dialog = new EditTagDialog(app_); EditTagDialog *edit_tag_dialog = new EditTagDialog(app_->network(), app_->collection_backend(), app_->album_cover_loader(), app_->current_albumcover_loader(), app_->cover_providers(), app_->lyrics_providers());
QObject::connect(edit_tag_dialog, &EditTagDialog::accepted, this, &MainWindow::EditTagDialogAccepted); QObject::connect(edit_tag_dialog, &EditTagDialog::accepted, this, &MainWindow::EditTagDialogAccepted);
QObject::connect(edit_tag_dialog, &EditTagDialog::Error, this, &MainWindow::ShowErrorDialog); QObject::connect(edit_tag_dialog, &EditTagDialog::Error, this, &MainWindow::ShowErrorDialog);
return edit_tag_dialog; return edit_tag_dialog;

View File

@ -46,12 +46,12 @@
#include <QSettings> #include <QSettings>
#include <QtEvents> #include <QtEvents>
#include "scoped_ptr.h" #include "core/scoped_ptr.h"
#include "shared_ptr.h" #include "core/shared_ptr.h"
#include "lazy.h" #include "core/lazy.h"
#include "platforminterface.h" #include "core/platforminterface.h"
#include "song.h" #include "core/song.h"
#include "settings.h" #include "core/settings.h"
#include "tagreader/tagreaderclient.h" #include "tagreader/tagreaderclient.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "osd/osdbase.h" #include "osd/osdbase.h"
@ -108,7 +108,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
~MainWindow() override; ~MainWindow() override;
static const char *kSettingsGroup; static const char *kSettingsGroup;
static const char *kAllFilesFilterSpec;
void SetHiddenInTray(const bool hidden); void SetHiddenInTray(const bool hidden);
void CommandlineOptionsReceived(const CommandlineOptions &options); void CommandlineOptionsReceived(const CommandlineOptions &options);
@ -205,6 +204,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void ShowCollectionConfig(); void ShowCollectionConfig();
void ReloadSettings(); void ReloadSettings();
void ReloadAllSettings(); void ReloadAllSettings();
void MoodbarSettingsChanged();
void RefreshStyleSheet(); void RefreshStyleSheet();
void SetHiddenInTray() { SetHiddenInTray(true); } void SetHiddenInTray() { SetHiddenInTray(true); }

View File

@ -43,7 +43,7 @@
# include <QDBusArgument> # include <QDBusArgument>
#endif #endif
#include "song.h" #include "core/song.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "engine/enginemetadata.h" #include "engine/enginemetadata.h"
@ -57,7 +57,7 @@
#include "equalizer/equalizer.h" #include "equalizer/equalizer.h"
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
# include "dbus_metatypes.h" # include "core/dbus_metatypes.h"
#endif #endif
#ifdef HAVE_MPRIS2 #ifdef HAVE_MPRIS2

View File

@ -40,13 +40,13 @@
#include <QEventLoop> #include <QEventLoop>
#include "core/logging.h" #include "core/logging.h"
#include "core/shared_ptr.h"
#include "shared_ptr.h" #include "core/signalchecker.h"
#include "signalchecker.h" #include "core/song.h"
#include "player.h" #include "core/database.h"
#include "song.h" #include "core/urlhandlers.h"
#include "songloader.h" #include "songloader.h"
#include "database.h" #include "player/player.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "tagreader/tagreaderclient.h" #include "tagreader/tagreaderclient.h"
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
@ -66,8 +66,9 @@ constexpr int kDefaultTimeout = 5000;
QSet<QString> SongLoader::sRawUriSchemes; QSet<QString> SongLoader::sRawUriSchemes;
SongLoader::SongLoader(SharedPtr<CollectionBackendInterface> collection_backend, const SharedPtr<Player> player, QObject *parent) SongLoader::SongLoader(const SharedPtr<UrlHandlers> url_handlers, const SharedPtr<Player> player, const SharedPtr<CollectionBackendInterface> collection_backend, QObject *parent)
: QObject(parent), : QObject(parent),
url_handlers_(url_handlers),
player_(player), player_(player),
collection_backend_(collection_backend), collection_backend_(collection_backend),
timeout_timer_(new QTimer(this)), timeout_timer_(new QTimer(this)),
@ -114,7 +115,7 @@ SongLoader::Result SongLoader::Load(const QUrl &url) {
return LoadLocal(url_.toLocalFile()); return LoadLocal(url_.toLocalFile());
} }
if (sRawUriSchemes.contains(url_.scheme()) || player_->HandlerForUrl(url)) { if (sRawUriSchemes.contains(url_.scheme()) || url_handlers_->CanHandle(url)) {
// The URI scheme indicates that it can't possibly be a playlist, // The URI scheme indicates that it can't possibly be a playlist,
// or we have a custom handler for the URL, so add it as a raw stream. // or we have a custom handler for the URL, so add it as a raw stream.
AddAsRawStream(); AddAsRawStream();

View File

@ -38,10 +38,11 @@
#include <QStringList> #include <QStringList>
#include <QUrl> #include <QUrl>
#include "shared_ptr.h" #include "core/shared_ptr.h"
#include "song.h" #include "core/song.h"
class QTimer; class QTimer;
class UrlHandlers;
class Player; class Player;
class CollectionBackendInterface; class CollectionBackendInterface;
class PlaylistParser; class PlaylistParser;
@ -56,7 +57,7 @@ class SongLoader : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit SongLoader(SharedPtr<CollectionBackendInterface> collection_backend, const SharedPtr<Player> player, QObject *parent = nullptr); explicit SongLoader(const SharedPtr<UrlHandlers> url_handlers, const SharedPtr<Player> player, const SharedPtr<CollectionBackendInterface> collection_backend, QObject *parent = nullptr);
~SongLoader() override; ~SongLoader() override;
enum class Result { enum class Result {
@ -137,8 +138,9 @@ class SongLoader : public QObject {
QUrl url_; QUrl url_;
SongList songs_; SongList songs_;
const SharedPtr<UrlHandlers> url_handlers_;
const SharedPtr<Player> player_; const SharedPtr<Player> player_;
SharedPtr<CollectionBackendInterface> collection_backend_; const SharedPtr<CollectionBackendInterface> collection_backend_;
QTimer *timeout_timer_; QTimer *timeout_timer_;
PlaylistParser *playlist_parser_; PlaylistParser *playlist_parser_;
CueParser *cue_parser_; CueParser *cue_parser_;

View File

@ -30,7 +30,6 @@
#include <QSettings> #include <QSettings>
#include <QtConcurrentRun> #include <QtConcurrentRun>
#include "core/application.h"
#include "core/taskmanager.h" #include "core/taskmanager.h"
#include "core/database.h" #include "core/database.h"
#include "core/thread.h" #include "core/thread.h"
@ -43,7 +42,6 @@
#include "collectionwatcher.h" #include "collectionwatcher.h"
#include "collectionbackend.h" #include "collectionbackend.h"
#include "collectionmodel.h" #include "collectionmodel.h"
#include "scrobbler/lastfmimport.h"
#include "settings/collectionsettingspage.h" #include "settings/collectionsettingspage.h"
using std::make_shared; using std::make_shared;
@ -52,9 +50,9 @@ const char *SCollection::kSongsTable = "songs";
const char *SCollection::kDirsTable = "directories"; const char *SCollection::kDirsTable = "directories";
const char *SCollection::kSubdirsTable = "subdirectories"; const char *SCollection::kSubdirsTable = "subdirectories";
SCollection::SCollection(Application *app, QObject *parent) SCollection::SCollection(SharedPtr<Database> database, SharedPtr<TaskManager> task_manager, SharedPtr<AlbumCoverLoader> album_cover_loader, QObject *parent)
: QObject(parent), : QObject(parent),
app_(app), task_manager_(task_manager),
backend_(nullptr), backend_(nullptr),
model_(nullptr), model_(nullptr),
watcher_(nullptr), watcher_(nullptr),
@ -68,12 +66,12 @@ SCollection::SCollection(Application *app, QObject *parent)
original_thread_ = thread(); original_thread_ = thread();
backend_ = make_shared<CollectionBackend>(); backend_ = make_shared<CollectionBackend>();
backend()->moveToThread(app->database()->thread()); backend()->moveToThread(database->thread());
qLog(Debug) << &*backend_ << "moved to thread" << app->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_, album_cover_loader, this);
ReloadSettings(); ReloadSettings();
@ -107,7 +105,7 @@ void SCollection::Init() {
watcher_thread_->start(QThread::IdlePriority); watcher_thread_->start(QThread::IdlePriority);
watcher_->set_backend(backend_); watcher_->set_backend(backend_);
watcher_->set_task_manager(app_->task_manager()); watcher_->set_task_manager(task_manager_);
QObject::connect(&*backend_, &CollectionBackend::Error, this, &SCollection::Error); QObject::connect(&*backend_, &CollectionBackend::Error, this, &SCollection::Error);
QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory); QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory);
@ -125,9 +123,6 @@ void SCollection::Init() {
QObject::connect(watcher_, &CollectionWatcher::CompilationsNeedUpdating, &*backend_, &CollectionBackend::CompilationsNeedUpdating); QObject::connect(watcher_, &CollectionWatcher::CompilationsNeedUpdating, &*backend_, &CollectionBackend::CompilationsNeedUpdating);
QObject::connect(watcher_, &CollectionWatcher::UpdateLastSeen, &*backend_, &CollectionBackend::UpdateLastSeen); 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 // This will start the watcher checking for updates
backend_->LoadDirectoriesAsync(); backend_->LoadDirectoriesAsync();
@ -198,8 +193,8 @@ void SCollection::SyncPlaycountAndRatingToFilesAsync() {
void SCollection::SyncPlaycountAndRatingToFiles() { void SCollection::SyncPlaycountAndRatingToFiles() {
const int task_id = app_->task_manager()->StartTask(tr("Saving playcounts and ratings")); const int task_id = task_manager_->StartTask(tr("Saving playcounts and ratings"));
app_->task_manager()->SetTaskBlocksCollectionScans(task_id); task_manager_->SetTaskBlocksCollectionScans(task_id);
const SongList songs = backend_->GetAllSongs(); const SongList songs = backend_->GetAllSongs();
const qint64 nb_songs = songs.size(); const qint64 nb_songs = songs.size();
@ -207,16 +202,16 @@ void SCollection::SyncPlaycountAndRatingToFiles() {
for (const Song &song : songs) { for (const Song &song : songs) {
(void)TagReaderClient::Instance()->SaveSongPlaycountBlocking(song.url().toLocalFile(), song.playcount()); (void)TagReaderClient::Instance()->SaveSongPlaycountBlocking(song.url().toLocalFile(), song.playcount());
(void)TagReaderClient::Instance()->SaveSongRatingBlocking(song.url().toLocalFile(), song.rating()); (void)TagReaderClient::Instance()->SaveSongRatingBlocking(song.url().toLocalFile(), song.rating());
app_->task_manager()->SetTaskProgress(task_id, ++i, nb_songs); 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 SCollection::SongsPlaycountChanged(const SongList &songs, const bool save_tags) {
if (save_tags || save_playcounts_to_files_) { if (save_tags || save_playcounts_to_files_) {
app_->tag_reader_client()->SaveSongsPlaycountAsync(songs); TagReaderClient::Instance()->SaveSongsPlaycountAsync(songs);
} }
} }
@ -224,7 +219,7 @@ void SCollection::SongsPlaycountChanged(const SongList &songs, const bool save_t
void SCollection::SongsRatingChanged(const SongList &songs, const bool save_tags) { void SCollection::SongsRatingChanged(const SongList &songs, const bool save_tags) {
if (save_tags || save_ratings_to_files_) { if (save_tags || save_ratings_to_files_) {
app_->tag_reader_client()->SaveSongsRatingAsync(songs); TagReaderClient::Instance()->SaveSongsRatingAsync(songs);
} }
} }

View File

@ -33,17 +33,19 @@
#include "core/song.h" #include "core/song.h"
class QThread; class QThread;
class Application; class TaskManager;
class Database;
class Thread; class Thread;
class CollectionBackend; class CollectionBackend;
class CollectionModel; class CollectionModel;
class CollectionWatcher; class CollectionWatcher;
class AlbumCoverLoader;
class SCollection : public QObject { class SCollection : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit SCollection(Application *app, QObject *parent = nullptr); explicit SCollection(SharedPtr<Database> database, SharedPtr<TaskManager> task_manager, SharedPtr<AlbumCoverLoader> album_cover_loader, QObject *parent = nullptr);
~SCollection() override; ~SCollection() override;
static const char *kSongsTable; static const char *kSongsTable;
@ -86,7 +88,7 @@ class SCollection : public QObject {
void ExitFinished(); void ExitFinished();
private: private:
Application *app_; SharedPtr<TaskManager> task_manager_;
SharedPtr<CollectionBackend> backend_; SharedPtr<CollectionBackend> backend_;
CollectionModel *model_; CollectionModel *model_;

View File

@ -55,11 +55,9 @@
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/database.h" #include "core/database.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/sqlrow.h"
#include "core/settings.h" #include "core/settings.h"
#include "collectionfilteroptions.h" #include "collectionfilteroptions.h"
#include "collectionquery.h" #include "collectionquery.h"
@ -85,12 +83,10 @@ constexpr char kPixmapDiskCacheDir[] = "pixmapcache";
constexpr char kVariousArtists[] = QT_TR_NOOP("Various artists"); constexpr char kVariousArtists[] = QT_TR_NOOP("Various artists");
} // namespace } // namespace
QNetworkDiskCache *CollectionModel::sIconCache = nullptr; CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, SharedPtr<AlbumCoverLoader> album_cover_loader, QObject *parent)
CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Application *app, QObject *parent)
: SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent), : SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent),
backend_(backend), backend_(backend),
app_(app), album_cover_loader_(album_cover_loader),
dir_model_(new CollectionDirectoryModel(backend, this)), dir_model_(new CollectionDirectoryModel(backend, this)),
filter_(new CollectionFilter(this)), filter_(new CollectionFilter(this)),
timer_reload_(new QTimer(this)), timer_reload_(new QTimer(this)),
@ -100,7 +96,8 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
total_song_count_(0), total_song_count_(0),
total_artist_count_(0), total_artist_count_(0),
total_album_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()))); setObjectName(backend_->source() == Song::Source::Collection ? QLatin1String(metaObject()->className()) : QStringLiteral("%1%2").arg(Song::DescriptionForSource(backend_->source()), QLatin1String(metaObject()->className())));
@ -108,8 +105,8 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
filter_->setSortRole(Role_SortText); filter_->setSortRole(Role_SortText);
filter_->sort(0); filter_->sort(0);
if (app_) { if (album_cover_loader_) {
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded); QObject::connect(&*album_cover_loader_, &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded);
} }
QIcon nocover = IconLoader::Load(u"cdcase"_s); QIcon nocover = IconLoader::Load(u"cdcase"_s);
@ -118,10 +115,9 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
pixmap_no_cover_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); pixmap_no_cover_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
} }
if (app_ && !sIconCache) { if (!qgetenv("DISPLAY").isEmpty() && !icon_disk_cache_) {
sIconCache = new QNetworkDiskCache(this); icon_disk_cache_ = new QNetworkDiskCache(this);
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' + QLatin1String(kPixmapDiskCacheDir)); icon_disk_cache_->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' + QLatin1String(kPixmapDiskCacheDir) + u'-' + Song::TextForSource(backend_->source()));
QObject::connect(app_, &Application::ClearPixmapDiskCache, this, &CollectionModel::ClearDiskCache);
} }
QObject::connect(&*backend_, &CollectionBackend::SongsAdded, this, &CollectionModel::AddReAddOrUpdate); QObject::connect(&*backend_, &CollectionBackend::SongsAdded, this, &CollectionModel::AddReAddOrUpdate);
@ -238,8 +234,8 @@ void CollectionModel::ReloadSettings() {
use_disk_cache_ = settings.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool(); use_disk_cache_ = settings.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool();
QPixmapCache::setCacheLimit(static_cast<int>(MaximumCacheSize(&settings, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024)); QPixmapCache::setCacheLimit(static_cast<int>(MaximumCacheSize(&settings, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024));
if (sIconCache) { if (icon_disk_cache_) {
sIconCache->setMaximumCacheSize(MaximumCacheSize(&settings, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit, CollectionSettingsPage::kSettingsDiskCacheSizeDefault)); icon_disk_cache_->setMaximumCacheSize(MaximumCacheSize(&settings, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit, CollectionSettingsPage::kSettingsDiskCacheSizeDefault));
} }
settings.endGroup(); settings.endGroup();
@ -258,7 +254,7 @@ void CollectionModel::ReloadSettings() {
} }
if (!use_disk_cache_) { if (!use_disk_cache_) {
ClearDiskCache(); ClearIconDiskCache();
} }
} }
@ -778,7 +774,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->display_text = song.TitleWithCompilationArtist();
item->sort_text = HasParentAlbumGroupBy(item->parent) ? SortTextForSong(song) : SortText(song.title()); item->sort_text = HasParentAlbumGroupBy(item->parent) ? SortTextForSong(song) : SortText(song.title());
@ -879,7 +875,7 @@ void CollectionModel::ClearItemPixmapCache(CollectionItem *item) {
// Remove from pixmap cache // Remove from pixmap cache
const QString cache_key = AlbumIconPixmapCacheKey(ItemToIndex(item)); const QString cache_key = AlbumIconPixmapCacheKey(ItemToIndex(item));
QPixmapCache::remove(cache_key); 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)) { if (pending_cache_keys_.contains(cache_key)) {
pending_cache_keys_.remove(cache_key); pending_cache_keys_.remove(cache_key);
} }
@ -910,8 +906,8 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
} }
// Try to load it from the disk cache // Try to load it from the disk cache
if (use_disk_cache_ && sIconCache) { if (use_disk_cache_ && icon_disk_cache_) {
ScopedPtr<QIODevice> disk_cache_img(sIconCache->data(AlbumIconPixmapDiskCacheKey(cache_key))); ScopedPtr<QIODevice> disk_cache_img(icon_disk_cache_->data(AlbumIconPixmapDiskCacheKey(cache_key)));
if (disk_cache_img) { if (disk_cache_img) {
QImage cached_image; QImage cached_image;
if (cached_image.load(&*disk_cache_img, "XPM")) { if (cached_image.load(&*disk_cache_img, "XPM")) {
@ -932,7 +928,7 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
AlbumCoverLoaderOptions cover_loader_options(AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage); AlbumCoverLoaderOptions cover_loader_options(AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage);
cover_loader_options.desired_scaled_size = QSize(kPrettyCoverSize, kPrettyCoverSize); cover_loader_options.desired_scaled_size = QSize(kPrettyCoverSize, kPrettyCoverSize);
cover_loader_options.types = cover_types_; cover_loader_options.types = cover_types_;
const quint64 id = app_->album_cover_loader()->LoadImageAsync(cover_loader_options, songs.first()); const quint64 id = album_cover_loader_->LoadImageAsync(cover_loader_options, songs.first());
pending_art_[id] = ItemAndCacheKey(item, cache_key); pending_art_[id] = ItemAndCacheKey(item, cache_key);
pending_cache_keys_.insert(cache_key); pending_cache_keys_.insert(cache_key);
} }
@ -965,19 +961,19 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderR
} }
// If we have a valid cover not already in the disk cache // 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); 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) { if (!disk_cache_img) {
QNetworkCacheMetaData disk_cache_metadata; QNetworkCacheMetaData disk_cache_metadata;
disk_cache_metadata.setSaveToDisk(true); disk_cache_metadata.setSaveToDisk(true);
disk_cache_metadata.setUrl(disk_cache_key); disk_cache_metadata.setUrl(disk_cache_key);
// Qt 6 now ignores any entry without headers, so add a fake header. // 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())); 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) { if (device_iconcache) {
result.image_scaled.save(device_iconcache, "XPM"); result.image_scaled.save(device_iconcache, "XPM");
sIconCache->insert(device_iconcache); icon_disk_cache_->insert(device_iconcache);
} }
} }
} }
@ -1553,8 +1549,11 @@ void CollectionModel::TotalAlbumCountUpdatedSlot(const int count) {
} }
void CollectionModel::ClearDiskCache() { void CollectionModel::ClearIconDiskCache() {
if (sIconCache) sIconCache->clear();
if (icon_disk_cache_) icon_disk_cache_->clear();
QPixmapCache::clear();
} }
void CollectionModel::RowsInserted(const QModelIndex &parent, const int first, const int last) { void CollectionModel::RowsInserted(const QModelIndex &parent, const int first, const int last) {

View File

@ -47,7 +47,6 @@
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/simpletreemodel.h" #include "core/simpletreemodel.h"
#include "core/song.h" #include "core/song.h"
#include "core/sqlrow.h"
#include "covermanager/albumcoverloaderoptions.h" #include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h" #include "covermanager/albumcoverloaderresult.h"
#include "collectionmodelupdate.h" #include "collectionmodelupdate.h"
@ -57,16 +56,16 @@
class QTimer; class QTimer;
class Settings; class Settings;
class Application;
class CollectionBackend; class CollectionBackend;
class CollectionDirectoryModel; class CollectionDirectoryModel;
class CollectionFilter; class CollectionFilter;
class AlbumCoverLoader;
class CollectionModel : public SimpleTreeModel<CollectionItem> { class CollectionModel : public SimpleTreeModel<CollectionItem> {
Q_OBJECT Q_OBJECT
public: public:
explicit CollectionModel(SharedPtr<CollectionBackend> backend, Application *app, QObject *parent = nullptr); explicit CollectionModel(SharedPtr<CollectionBackend> backend, SharedPtr<AlbumCoverLoader> album_cover_loader, QObject *parent = nullptr);
~CollectionModel() override; ~CollectionModel() override;
static const int kPrettyCoverSize; static const int kPrettyCoverSize;
@ -156,7 +155,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
int total_artist_count() const { return total_artist_count_; } int total_artist_count() const { return total_artist_count_; }
int total_album_count() const { return total_album_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; } 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>()); 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 AddReAddOrUpdate(const SongList &songs);
void RemoveSongs(const SongList &songs); void RemoveSongs(const SongList &songs);
void ClearIconDiskCache();
private: private:
void Clear(); void Clear();
void BeginReset(); void BeginReset();
@ -238,7 +239,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
void CreateDividerItem(const QString &divider_key, const QString &display_text, CollectionItem *parent); 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); 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 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); CollectionItem *CreateCompilationArtistNode(CollectionItem *parent);
void LoadSongsFromSqlAsync(); void LoadSongsFromSqlAsync();
@ -267,15 +268,12 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
void TotalArtistCountUpdatedSlot(const int count); void TotalArtistCountUpdatedSlot(const int count);
void TotalAlbumCountUpdatedSlot(const int count); void TotalAlbumCountUpdatedSlot(const int count);
static void ClearDiskCache();
void RowsInserted(const QModelIndex &parent, const int first, const int last); void RowsInserted(const QModelIndex &parent, const int first, const int last);
void RowsRemoved(const QModelIndex &parent, const int first, const int last); void RowsRemoved(const QModelIndex &parent, const int first, const int last);
private: private:
static QNetworkDiskCache *sIconCache;
SharedPtr<CollectionBackend> backend_; SharedPtr<CollectionBackend> backend_;
Application *app_; SharedPtr<AlbumCoverLoader> album_cover_loader_;
CollectionDirectoryModel *dir_model_; CollectionDirectoryModel *dir_model_;
CollectionFilter *filter_; CollectionFilter *filter_;
QTimer *timer_reload_; QTimer *timer_reload_;
@ -310,6 +308,8 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
using ItemAndCacheKey = QPair<CollectionItem*, QString>; using ItemAndCacheKey = QPair<CollectionItem*, QString>;
QMap<quint64, ItemAndCacheKey> pending_art_; QMap<quint64, ItemAndCacheKey> pending_art_;
QSet<QString> pending_cache_keys_; QSet<QString> pending_cache_keys_;
QNetworkDiskCache *icon_disk_cache_;
}; };
Q_DECLARE_METATYPE(CollectionModel::Grouping) Q_DECLARE_METATYPE(CollectionModel::Grouping)

View File

@ -50,7 +50,6 @@
#include <QKeyEvent> #include <QKeyEvent>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include "core/application.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/mimedata.h" #include "core/mimedata.h"
#include "core/musicstorage.h" #include "core/musicstorage.h"
@ -80,7 +79,6 @@ using namespace Qt::Literals::StringLiterals;
CollectionView::CollectionView(QWidget *parent) CollectionView::CollectionView(QWidget *parent)
: AutoExpandingTreeView(parent), : AutoExpandingTreeView(parent),
app_(nullptr),
filter_(nullptr), filter_(nullptr),
total_song_count_(-1), total_song_count_(-1),
total_artist_count_(-1), total_artist_count_(-1),
@ -123,6 +121,30 @@ CollectionView::CollectionView(QWidget *parent)
CollectionView::~CollectionView() = default; CollectionView::~CollectionView() = default;
void CollectionView::Init(SharedPtr<TaskManager> task_manager,
SharedPtr<NetworkAccessManager> network,
SharedPtr<DeviceManager> device_manager) {
task_manager_ = task_manager;
network_ = network;
device_manager_ = device_manager;
ReloadSettings();
}
QSortFilterProxyModel *CollectionView::sort_filter_proxy_model() const {
return qobject_cast<QSortFilterProxyModel*>(model());
}
CollectionModel *CollectionView::collection_model() const {
return qobject_cast<CollectionModel*>(sort_filter_proxy_model()->sourceModel());
}
void CollectionView::SaveFocus() { void CollectionView::SaveFocus() {
const QModelIndex current = currentIndex(); const QModelIndex current = currentIndex();
@ -142,8 +164,8 @@ void CollectionView::SaveFocus() {
switch (item_type) { switch (item_type) {
case CollectionItem::Type::Song:{ case CollectionItem::Type::Song:{
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current); QModelIndex index = sort_filter_proxy_model()->mapToSource(current);
SongList songs = app_->collection_model()->GetChildSongs(index); SongList songs = collection_model()->GetChildSongs(index);
if (!songs.isEmpty()) { if (!songs.isEmpty()) {
last_selected_song_ = songs.last(); last_selected_song_ = songs.last();
} }
@ -210,8 +232,8 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
break; break;
case CollectionItem::Type::Song: case CollectionItem::Type::Song:
if (!last_selected_song_.url().isEmpty()) { if (!last_selected_song_.url().isEmpty()) {
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current); QModelIndex index = sort_filter_proxy_model()->mapToSource(current);
const SongList songs = app_->collection_model()->GetChildSongs(index); const SongList songs = collection_model()->GetChildSongs(index);
if (std::any_of(songs.begin(), songs.end(), [this](const Song &song) { return song == last_selected_song_; })) { if (std::any_of(songs.begin(), songs.end(), [this](const Song &song) { return song == last_selected_song_; })) {
setCurrentIndex(current); setCurrentIndex(current);
return true; return true;
@ -241,6 +263,7 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
} }
} }
} }
return false; return false;
} }
@ -255,14 +278,6 @@ void CollectionView::ReloadSettings() {
} }
void CollectionView::SetApplication(Application *app) {
app_ = app;
ReloadSettings();
}
void CollectionView::SetFilter(CollectionFilterWidget *filter) { filter_ = filter; } void CollectionView::SetFilter(CollectionFilterWidget *filter) { filter_ = filter; }
void CollectionView::TotalSongCountUpdated(const int count) { void CollectionView::TotalSongCountUpdated(const int count) {
@ -417,8 +432,8 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_->addMenu(filter_->menu()); context_menu_->addMenu(filter_->menu());
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
action_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0); action_copy_to_device_->setDisabled(device_manager_->connected_devices_model()->rowCount() == 0);
QObject::connect(app_->device_manager()->connected_devices_model(), &DeviceStateFilterModel::IsEmptyChanged, action_copy_to_device_, &QAction::setDisabled); QObject::connect(device_manager_->connected_devices_model(), &DeviceStateFilterModel::IsEmptyChanged, action_copy_to_device_, &QAction::setDisabled);
#endif #endif
} }
@ -426,16 +441,16 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_index_ = indexAt(e->pos()); context_menu_index_ = indexAt(e->pos());
if (!context_menu_index_.isValid()) return; if (!context_menu_index_.isValid()) return;
context_menu_index_ = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(context_menu_index_); context_menu_index_ = sort_filter_proxy_model()->mapToSource(context_menu_index_);
const QModelIndexList selected_indexes = qobject_cast<QSortFilterProxyModel*>(model())->mapSelectionToSource(selectionModel()->selection()).indexes(); const QModelIndexList selected_indexes = sort_filter_proxy_model()->mapSelectionToSource(selectionModel()->selection()).indexes();
int regular_elements = 0; int regular_elements = 0;
int regular_editable = 0; int regular_editable = 0;
for (const QModelIndex &idx : selected_indexes) { for (const QModelIndex &idx : selected_indexes) {
++regular_elements; ++regular_elements;
if (app_->collection_model()->data(idx, CollectionModel::Role_Editable).toBool()) { if (collection_model()->data(idx, CollectionModel::Role_Editable).toBool()) {
++regular_editable; ++regular_editable;
} }
} }
@ -502,7 +517,7 @@ void CollectionView::SetShowInVarious(const bool on) {
if (on && albums.keys().count() == 1) { if (on && albums.keys().count() == 1) {
const QStringList albums_list = albums.keys(); const QStringList albums_list = albums.keys();
const QString album = albums_list.first(); const QString album = albums_list.first();
const SongList all_of_album = app_->collection_backend()->GetSongsByAlbum(album); const SongList all_of_album = collection_model()->backend()->GetSongsByAlbum(album);
QSet<QString> other_artists; QSet<QString> other_artists;
for (const Song &s : all_of_album) { for (const Song &s : all_of_album) {
if (!albums.contains(album, s.artist()) && !other_artists.contains(s.artist())) { if (!albums.contains(album, s.artist()) && !other_artists.contains(s.artist())) {
@ -520,7 +535,7 @@ void CollectionView::SetShowInVarious(const bool on) {
const QSet<QString> albums_set = QSet<QString>(albums.keyBegin(), albums.keyEnd()); const QSet<QString> albums_set = QSet<QString>(albums.keyBegin(), albums.keyEnd());
for (const QString &album : albums_set) { for (const QString &album : albums_set) {
app_->collection_backend()->ForceCompilation(album, albums.values(album), on); collection_model()->backend()->ForceCompilation(album, albums.values(album), on);
} }
} }
@ -584,11 +599,12 @@ void CollectionView::SearchForThis() {
return; return;
} }
QString search; QString search;
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
QModelIndex index = sort_filter_proxy_model()->mapToSource(current);
switch (item_type) { switch (item_type) {
case CollectionItem::Type::Song:{ case CollectionItem::Type::Song:{
SongList songs = app_->collection_model()->GetChildSongs(index); SongList songs = collection_model()->GetChildSongs(index);
if (!songs.isEmpty()) { if (!songs.isEmpty()) {
last_selected_song_ = songs.last(); last_selected_song_ = songs.last();
} }
@ -601,8 +617,8 @@ void CollectionView::SearchForThis() {
} }
case CollectionItem::Type::Container:{ case CollectionItem::Type::Container:{
CollectionItem *item = app_->collection_model()->IndexToItem(index); CollectionItem *item = collection_model()->IndexToItem(index);
const CollectionModel::GroupBy group_by = app_->collection_model()->GetGroupBy()[item->container_level]; const CollectionModel::GroupBy group_by = collection_model()->GetGroupBy()[item->container_level];
while (!item->children.isEmpty()) { while (!item->children.isEmpty()) {
item = item->children.constFirst(); item = item->children.constFirst();
} }
@ -688,18 +704,18 @@ void CollectionView::scrollTo(const QModelIndex &idx, ScrollHint hint) {
SongList CollectionView::GetSelectedSongs() const { SongList CollectionView::GetSelectedSongs() const {
QModelIndexList selected_indexes = qobject_cast<QSortFilterProxyModel*>(model())->mapSelectionToSource(selectionModel()->selection()).indexes(); QModelIndexList selected_indexes = sort_filter_proxy_model()->mapSelectionToSource(selectionModel()->selection()).indexes();
return app_->collection_model()->GetChildSongs(selected_indexes); return collection_model()->GetChildSongs(selected_indexes);
} }
void CollectionView::Organize() { void CollectionView::Organize() {
if (!organize_dialog_) { if (!organize_dialog_) {
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), app_->collection_backend(), this); organize_dialog_ = make_unique<OrganizeDialog>(task_manager_, collection_model()->backend(), this);
} }
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model()); organize_dialog_->SetDestinationModel(collection_model()->directory_model());
organize_dialog_->SetCopy(false); organize_dialog_->SetCopy(false);
const SongList songs = GetSelectedSongs(); const SongList songs = GetSelectedSongs();
if (organize_dialog_->SetSongs(songs)) { if (organize_dialog_->SetSongs(songs)) {
@ -714,7 +730,7 @@ void CollectionView::Organize() {
void CollectionView::EditTracks() { void CollectionView::EditTracks() {
if (!edit_tag_dialog_) { if (!edit_tag_dialog_) {
edit_tag_dialog_ = make_unique<EditTagDialog>(app_, this); edit_tag_dialog_ = make_unique<EditTagDialog>(network_, collection_model()->backend(), albumcover_loader_, current_albumcover_loader_, cover_providers_, lyrics_providers_, this);
QObject::connect(&*edit_tag_dialog_, &EditTagDialog::Error, this, &CollectionView::EditTagError); QObject::connect(&*edit_tag_dialog_, &EditTagDialog::Error, this, &CollectionView::EditTagError);
} }
const SongList songs = GetSelectedSongs(); const SongList songs = GetSelectedSongs();
@ -729,7 +745,7 @@ void CollectionView::EditTagError(const QString &message) {
void CollectionView::RescanSongs() { void CollectionView::RescanSongs() {
app_->collection()->Rescan(GetSelectedSongs()); //collection_->Rescan(GetSelectedSongs());
} }
@ -737,10 +753,10 @@ void CollectionView::CopyToDevice() {
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
if (!organize_dialog_) { if (!organize_dialog_) {
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), nullptr, this); organize_dialog_ = make_unique<OrganizeDialog>(task_manager_, 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_->SetCopy(true);
organize_dialog_->SetSongs(GetSelectedSongs()); organize_dialog_->SetSongs(GetSelectedSongs());
organize_dialog_->show(); organize_dialog_->show();
@ -812,9 +828,9 @@ void CollectionView::Delete() {
if (DeleteConfirmationDialog::warning(files) != QDialogButtonBox::Yes) return; 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. // 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 = collection_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); QObject::connect(delete_files, &DeleteFiles::Finished, this, &CollectionView::DeleteFilesFinished);
delete_files->Start(songs); delete_files->Start(songs);

View File

@ -31,9 +31,11 @@
#include <QSet> #include <QSet>
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/song.h" #include "core/song.h"
#include "widgets/autoexpandingtreeview.h" #include "widgets/autoexpandingtreeview.h"
class QSortFilterProxyModel;
class QMenu; class QMenu;
class QAction; class QAction;
class QContextMenuEvent; class QContextMenuEvent;
@ -41,8 +43,15 @@ class QMouseEvent;
class QPaintEvent; class QPaintEvent;
class QKeyEvent; class QKeyEvent;
class Application; class TaskManager;
class NetworkAccessManager;
class CollectionModel;
class CollectionFilterWidget; class CollectionFilterWidget;
class DeviceManager;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class LyricsProviders;
class EditTagDialog; class EditTagDialog;
class OrganizeDialog; class OrganizeDialog;
@ -57,7 +66,10 @@ 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. // 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; SongList GetSelectedSongs() const;
void SetApplication(Application *app); void Init(SharedPtr<TaskManager> task_manager,
SharedPtr<NetworkAccessManager> network,
SharedPtr<DeviceManager> device_manager);
void SetFilter(CollectionFilterWidget *filter); void SetFilter(CollectionFilterWidget *filter);
// QTreeView // QTreeView
@ -114,15 +126,24 @@ class CollectionView : public AutoExpandingTreeView {
void DeleteFilesFinished(const SongList &songs_with_errors); void DeleteFilesFinished(const SongList &songs_with_errors);
private: private:
QSortFilterProxyModel *sort_filter_proxy_model() const;
CollectionModel *collection_model() const;
void RecheckIsEmpty(); void RecheckIsEmpty();
void SetShowInVarious(const bool on); void SetShowInVarious(const bool on);
bool RestoreLevelFocus(const QModelIndex &parent = QModelIndex()); bool RestoreLevelFocus(const QModelIndex &parent = QModelIndex());
void SaveContainerPath(const QModelIndex &child); void SaveContainerPath(const QModelIndex &child);
private: private:
Application *app_;
CollectionFilterWidget *filter_; CollectionFilterWidget *filter_;
SharedPtr<TaskManager> task_manager_;
SharedPtr<NetworkAccessManager> network_;
SharedPtr<DeviceManager> device_manager_;
SharedPtr<AlbumCoverLoader> albumcover_loader_;
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
SharedPtr<CoverProviders> cover_providers_;
SharedPtr<LyricsProviders> lyrics_providers_;
int total_song_count_; int total_song_count_;
int total_artist_count_; int total_artist_count_;
int total_album_count_; int total_album_count_;

View File

@ -50,7 +50,7 @@
#include "core/taskmanager.h" #include "core/taskmanager.h"
#include "core/settings.h" #include "core/settings.h"
#include "utilities/imageutils.h" #include "utilities/imageutils.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "tagreader/tagreaderclient.h" #include "tagreader/tagreaderclient.h"
#include "collectiondirectory.h" #include "collectiondirectory.h"
#include "collectionbackend.h" #include "collectionbackend.h"

View File

@ -20,6 +20,8 @@
#ifndef FILENAMECONSTANTS_H #ifndef FILENAMECONSTANTS_H
#define FILENAMECONSTANTS_H #define FILENAMECONSTANTS_H
#include <QtGlobal>
#include "core/arraysize.h" #include "core/arraysize.h"
constexpr char kProblematicCharactersRegex[] = "[:?*\"<>|]"; constexpr char kProblematicCharactersRegex[] = "[:?*\"<>|]";
@ -27,5 +29,6 @@ constexpr char kInvalidFatCharactersRegex[] = "[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~
constexpr char kInvalidDirCharactersRegex[] = "[/\\\\]"; constexpr char kInvalidDirCharactersRegex[] = "[/\\\\]";
constexpr char kInvalidPrefixCharacters[] = "."; constexpr char kInvalidPrefixCharacters[] = ".";
constexpr int kInvalidPrefixCharactersCount = arraysize(kInvalidPrefixCharacters) - 1; constexpr int kInvalidPrefixCharactersCount = arraysize(kInvalidPrefixCharacters) - 1;
constexpr char kAllFilesFilterSpec[] = QT_TR_NOOP("All Files (*)");
#endif // FILENAMECONSTANTS_H #endif // FILENAMECONSTANTS_H

View File

@ -50,8 +50,6 @@
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QDropEvent> #include <QDropEvent>
#include "core/application.h"
#include "core/player.h"
#include "core/song.h" #include "core/song.h"
#include "core/settings.h" #include "core/settings.h"
#include "utilities/strutils.h" #include "utilities/strutils.h"
@ -73,7 +71,6 @@ constexpr int kWidgetSpacing = 50;
ContextView::ContextView(QWidget *parent) ContextView::ContextView(QWidget *parent)
: QWidget(parent), : QWidget(parent),
app_(nullptr),
collectionview_(nullptr), collectionview_(nullptr),
album_cover_choice_controller_(nullptr), album_cover_choice_controller_(nullptr),
lyrics_fetcher_(nullptr), lyrics_fetcher_(nullptr),
@ -241,14 +238,13 @@ ContextView::ContextView(QWidget *parent)
} }
void ContextView::Init(Application *app, CollectionView *collectionview, AlbumCoverChoiceController *album_cover_choice_controller) { void ContextView::Init(CollectionView *collectionview, AlbumCoverChoiceController *album_cover_choice_controller, SharedPtr<LyricsProviders> lyrics_providers) {
app_ = app;
collectionview_ = collectionview; collectionview_ = collectionview;
album_cover_choice_controller_ = album_cover_choice_controller; album_cover_choice_controller_ = album_cover_choice_controller;
widget_album_->Init(this, album_cover_choice_controller_); widget_album_->Init(this, album_cover_choice_controller_);
lyrics_fetcher_ = new LyricsFetcher(app_->lyrics_providers(), this); lyrics_fetcher_ = new LyricsFetcher(lyrics_providers, this);
QObject::connect(collectionview_, &CollectionView::TotalSongCountUpdated_, this, &ContextView::UpdateNoSong); QObject::connect(collectionview_, &CollectionView::TotalSongCountUpdated_, this, &ContextView::UpdateNoSong);
QObject::connect(collectionview_, &CollectionView::TotalArtistCountUpdated_, this, &ContextView::UpdateNoSong); QObject::connect(collectionview_, &CollectionView::TotalArtistCountUpdated_, this, &ContextView::UpdateNoSong);

View File

@ -46,9 +46,9 @@ class QDragEnterEvent;
class QDropEvent; class QDropEvent;
class ResizableTextEdit; class ResizableTextEdit;
class Application;
class CollectionView; class CollectionView;
class AlbumCoverChoiceController; class AlbumCoverChoiceController;
class LyricsProviders;
class LyricsFetcher; class LyricsFetcher;
class ContextView : public QWidget { class ContextView : public QWidget {
@ -57,7 +57,7 @@ class ContextView : public QWidget {
public: public:
explicit ContextView(QWidget *parent = nullptr); explicit ContextView(QWidget *parent = nullptr);
void Init(Application *app, CollectionView *collectionview, AlbumCoverChoiceController *album_cover_choice_controller); void Init(CollectionView *collectionview, AlbumCoverChoiceController *album_cover_choice_controller, SharedPtr<LyricsProviders> lyrics_providers);
ContextAlbum *album_widget() const { return widget_album_; } ContextAlbum *album_widget() const { return widget_album_; }
bool album_enabled() const { return action_show_album_->isChecked(); } bool album_enabled() const { return action_show_album_->isChecked(); }
@ -101,7 +101,6 @@ class ContextView : public QWidget {
void AlbumCoverLoaded(const Song &song, const QImage &image); void AlbumCoverLoaded(const Song &song, const QImage &image);
private: private:
Application *app_;
CollectionView *collectionview_; CollectionView *collectionview_;
AlbumCoverChoiceController *album_cover_choice_controller_; AlbumCoverChoiceController *album_cover_choice_controller_;
LyricsFetcher *lyrics_fetcher_; LyricsFetcher *lyrics_fetcher_;

View File

@ -45,7 +45,6 @@
#include "core/logging.h" #include "core/logging.h"
#include "taskmanager.h" #include "taskmanager.h"
#include "database.h" #include "database.h"
#include "application.h"
#include "sqlquery.h" #include "sqlquery.h"
#include "scopedtransaction.h" #include "scopedtransaction.h"
@ -62,9 +61,9 @@ constexpr char kMagicAllSongsTables[] = "%allsongstables";
int Database::sNextConnectionId = 1; int Database::sNextConnectionId = 1;
QMutex Database::sNextConnectionIdMutex; QMutex Database::sNextConnectionIdMutex;
Database::Database(Application *app, QObject *parent, const QString &database_name) : Database::Database(SharedPtr<TaskManager> task_manager, QObject *parent, const QString &database_name) :
QObject(parent), QObject(parent),
app_(app), task_manager_(task_manager),
injected_database_name_(database_name), injected_database_name_(database_name),
query_hash_(0), query_hash_(0),
startup_schema_version_(-1), startup_schema_version_(-1),
@ -145,7 +144,7 @@ QSqlDatabase Database::Connect() {
} }
if (!db.open()) { if (!db.open()) {
app_->AddError(u"Database: "_s + db.lastError().text()); Q_EMIT Error(u"Database: "_s + db.lastError().text());
return db; return db;
} }
@ -492,7 +491,7 @@ void Database::ReportErrors(const SqlQuery &query) {
bool Database::IntegrityCheck(const QSqlDatabase &db) { bool Database::IntegrityCheck(const QSqlDatabase &db) {
qLog(Debug) << "Starting database integrity check"; qLog(Debug) << "Starting database integrity check";
const int task_id = app_->task_manager()->StartTask(tr("Integrity check")); const int task_id = task_manager_->StartTask(tr("Integrity check"));
bool ok = false; bool ok = false;
// Ask for 10 error messages at most. // Ask for 10 error messages at most.
@ -509,8 +508,8 @@ bool Database::IntegrityCheck(const QSqlDatabase &db) {
break; break;
} }
else { else {
if (!error_reported) { app_->AddError(tr("Database corruption detected.")); } if (!error_reported) { Q_EMIT Error(tr("Database corruption detected.")); }
app_->AddError(u"Database: "_s + message); Q_EMIT Error(u"Database: "_s + message);
error_reported = true; error_reported = true;
} }
} }
@ -519,7 +518,7 @@ bool Database::IntegrityCheck(const QSqlDatabase &db) {
ReportErrors(q); ReportErrors(q);
} }
app_->task_manager()->SetTaskFinished(task_id); task_manager_->SetTaskFinished(task_id);
return ok; return ok;
@ -563,7 +562,7 @@ void Database::BackupFile(const QString &filename) {
qLog(Debug) << "Starting database backup"; qLog(Debug) << "Starting database backup";
QString dest_filename = QStringLiteral("%1.bak").arg(filename); QString dest_filename = QStringLiteral("%1.bak").arg(filename);
const int task_id = app_->task_manager()->StartTask(tr("Backing up database")); const int task_id = task_manager_->StartTask(tr("Backing up database"));
sqlite3 *source_connection = nullptr; sqlite3 *source_connection = nullptr;
sqlite3 *dest_connection = nullptr; sqlite3 *dest_connection = nullptr;
@ -575,7 +574,7 @@ void Database::BackupFile(const QString &filename) {
if (dest_connection) { if (dest_connection) {
sqlite3_close(dest_connection); sqlite3_close(dest_connection);
} }
app_->task_manager()->SetTaskFinished(task_id); task_manager_->SetTaskFinished(task_id);
}); });
bool success = OpenDatabase(filename, &source_connection); bool success = OpenDatabase(filename, &source_connection);
@ -599,7 +598,7 @@ void Database::BackupFile(const QString &filename) {
do { do {
ret = sqlite3_backup_step(backup, 16); ret = sqlite3_backup_step(backup, 16);
const int page_count = sqlite3_backup_pagecount(backup); const int page_count = sqlite3_backup_pagecount(backup);
app_->task_manager()->SetTaskProgress(task_id, page_count - sqlite3_backup_remaining(backup), page_count); task_manager_->SetTaskProgress(task_id, page_count - sqlite3_backup_remaining(backup), page_count);
} }
while (ret == SQLITE_OK); while (ret == SQLITE_OK);

View File

@ -36,16 +36,17 @@
#include <QStringList> #include <QStringList>
#include <QRecursiveMutex> #include <QRecursiveMutex>
#include "shared_ptr.h"
#include "sqlquery.h" #include "sqlquery.h"
class QThread; class QThread;
class Application; class TaskManager;
class Database : public QObject { class Database : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit Database(Application *app, QObject *parent = nullptr, const QString &database_name = QString()); explicit Database(SharedPtr<TaskManager> task_manager, QObject *parent = nullptr, const QString &database_name = QString());
~Database() override; ~Database() override;
static const int kSchemaVersion; static const int kSchemaVersion;
@ -102,7 +103,7 @@ class Database : public QObject {
void BackupFile(const QString &filename); void BackupFile(const QString &filename);
static bool OpenDatabase(const QString &filename, sqlite3 **connection); static bool OpenDatabase(const QString &filename, sqlite3 **connection);
Application *app_; SharedPtr<TaskManager> task_manager_;
// Alias -> filename // Alias -> filename
QMap<QString, AttachedDatabase> attached_databases_; QMap<QString, AttachedDatabase> attached_databases_;
@ -130,16 +131,4 @@ class Database : public QObject {
}; };
class MemoryDatabase : public Database {
Q_OBJECT
public:
explicit MemoryDatabase(Application *app, QObject *parent = nullptr)
: Database(app, parent, QStringLiteral(":memory:")) {}
~MemoryDatabase() override {
// Make sure Qt doesn't reuse the same database
QSqlDatabase::removeDatabase(Connect().connectionName());
}
};
#endif // DATABASE_H #endif // DATABASE_H

View File

@ -0,0 +1,30 @@
/*
* Strawberry Music Player
* Copyright 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 "memorydatabase.h"
using namespace Qt::Literals::StringLiterals;
MemoryDatabase::MemoryDatabase(SharedPtr<TaskManager> task_manager, QObject *parent)
: Database(task_manager, parent, u":memory:"_s) {}
MemoryDatabase::~MemoryDatabase() {
// Make sure Qt doesn't reuse the same database
Close();
}

37
src/core/memorydatabase.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Strawberry Music Player
* Copyright 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/>.
*
*/
#ifndef MEMORYDATABASE_H
#define MEMORYDATABASE_H
#include "shared_ptr.h"
class TaskManager;
#include "database.h"
class MemoryDatabase : public Database {
Q_OBJECT
public:
explicit MemoryDatabase(SharedPtr<TaskManager> task_manager, QObject *parent = nullptr);
~MemoryDatabase() override;
};
#endif // MEMORYDATABASE_H

View File

@ -55,7 +55,7 @@
#include "utilities/strutils.h" #include "utilities/strutils.h"
#include "utilities/timeutils.h" #include "utilities/timeutils.h"
#include "utilities/coverutils.h" #include "utilities/coverutils.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "utilities/sqlhelper.h" #include "utilities/sqlhelper.h"
#include "song.h" #include "song.h"

95
src/core/urlhandlers.cpp Normal file
View File

@ -0,0 +1,95 @@
/*
* Strawberry Music Player
* Copyright 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 <QString>
#include "core/logging.h"
#include "urlhandlers.h"
#include "urlhandler.h"
UrlHandlers::UrlHandlers(QObject *parent) : QObject(parent) {}
void UrlHandlers::Register(UrlHandler *url_handler) {
const QString scheme = url_handler->scheme();
if (url_handlers_.contains(scheme)) {
qLog(Warning) << "Tried to register a URL handler for" << scheme << "but one was already registered";
return;
}
qLog(Info) << "Registered URL handler for" << scheme;
url_handlers_.insert(scheme, url_handler);
QObject::connect(url_handler, &UrlHandler::destroyed, this, &UrlHandlers::Destroyed);
Q_EMIT Registered(url_handler);
}
void UrlHandlers::Unregister(UrlHandler *url_handler) {
const QString scheme = url_handlers_.key(url_handler);
if (scheme.isEmpty()) {
qLog(Warning) << "Tried to unregister a URL handler for" << url_handler->scheme() << "that wasn't registered";
return;
}
qLog(Info) << "Unregistered URL handler for" << scheme;
url_handlers_.remove(scheme);
QObject::disconnect(url_handler, &UrlHandler::destroyed, this, &UrlHandlers::Destroyed);
QObject::disconnect(url_handler, &UrlHandler::AsyncLoadComplete, nullptr, nullptr);
}
void UrlHandlers::Destroyed(QObject *object) {
UrlHandler *handler = static_cast<UrlHandler*>(object);
const QString scheme = url_handlers_.key(handler);
if (!scheme.isEmpty()) {
url_handlers_.remove(scheme);
}
}
bool UrlHandlers::CanHandle(const QString &scheme) const {
return url_handlers_.contains(scheme);
}
bool UrlHandlers::CanHandle(const QUrl &url) const {
return url_handlers_.contains(url.scheme());
}
UrlHandler *UrlHandlers::GetUrlHandler(const QString &scheme) const {
if (!CanHandle(scheme)) return nullptr;
return url_handlers_.value(scheme);
}
UrlHandler *UrlHandlers::GetUrlHandler(const QUrl &url) const {
return GetUrlHandler(url.scheme());
}

56
src/core/urlhandlers.h Normal file
View File

@ -0,0 +1,56 @@
/*
* Strawberry Music Player
* Copyright 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/>.
*
*/
#ifndef URLHANDLERS_H
#define URLHANDLERS_H
#include "config.h"
#include <QObject>
#include <QMap>
#include <QString>
#include <QUrl>
class UrlHandler;
class UrlHandlers : public QObject {
Q_OBJECT
public:
explicit UrlHandlers(QObject *parent = nullptr);
void Register(UrlHandler *url_handler);
void Unregister(UrlHandler *url_handler);
void Destroyed(QObject *object);
bool CanHandle(const QString &scheme) const;
bool CanHandle(const QUrl &url) const;
UrlHandler *GetUrlHandler(const QString &scheme) const;
UrlHandler *GetUrlHandler(const QUrl &url) const;
Q_SIGNALS:
void Registered(UrlHandler *url_handler);
void UnRegistered(UrlHandler *url_handler);
private:
QMap<QString, UrlHandler*> url_handlers_;
};
#endif // URLHANDLERS_H

View File

@ -54,13 +54,12 @@
#include <QSettings> #include <QSettings>
#include <QtEvents> #include <QtEvents>
#include "utilities/filenameconstants.h" #include "constants/filenameconstants.h"
#include "utilities/strutils.h" #include "utilities/strutils.h"
#include "utilities/mimeutils.h" #include "utilities/mimeutils.h"
#include "utilities/coveroptions.h" #include "utilities/coveroptions.h"
#include "utilities/coverutils.h" #include "utilities/coverutils.h"
#include "utilities/screenutils.h" #include "utilities/screenutils.h"
#include "core/application.h"
#include "core/song.h" #include "core/song.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/settings.h" #include "core/settings.h"
@ -88,7 +87,6 @@ QSet<QString> *AlbumCoverChoiceController::sImageExtensions = nullptr;
AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget *parent) AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget *parent)
: QWidget(parent), : QWidget(parent),
app_(nullptr),
cover_searcher_(nullptr), cover_searcher_(nullptr),
cover_fetcher_(nullptr), cover_fetcher_(nullptr),
save_file_dialog_(nullptr), save_file_dialog_(nullptr),
@ -130,12 +128,20 @@ AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget *parent)
AlbumCoverChoiceController::~AlbumCoverChoiceController() = default; AlbumCoverChoiceController::~AlbumCoverChoiceController() = default;
void AlbumCoverChoiceController::Init(Application *app) { void AlbumCoverChoiceController::Init(SharedPtr<NetworkAccessManager> network,
SharedPtr<CollectionBackend> collection_backend,
SharedPtr<AlbumCoverLoader> album_cover_loader,
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
SharedPtr<CoverProviders> cover_providers,
SharedPtr<StreamingServices> streaming_services) {
app_ = app; network_ = network;
collection_backend_ = collection_backend;
current_albumcover_loader_ = current_albumcover_loader;
streaming_services_ = streaming_services;
cover_fetcher_ = new AlbumCoverFetcher(app_->cover_providers(), app->network(), this); cover_fetcher_ = new AlbumCoverFetcher(cover_providers, network, this);
cover_searcher_ = new AlbumCoverSearcher(QIcon(u":/pictures/cdcase.png"_s), app, this); cover_searcher_ = new AlbumCoverSearcher(QIcon(u":/pictures/cdcase.png"_s), album_cover_loader, this);
cover_searcher_->Init(cover_fetcher_); cover_searcher_->Init(cover_fetcher_);
QObject::connect(cover_fetcher_, &AlbumCoverFetcher::AlbumCoverFetched, this, &AlbumCoverChoiceController::AlbumCoverFetched); QObject::connect(cover_fetcher_, &AlbumCoverFetcher::AlbumCoverFetched, this, &AlbumCoverChoiceController::AlbumCoverFetched);
@ -316,7 +322,7 @@ void AlbumCoverChoiceController::LoadCoverFromURL(Song *song) {
AlbumCoverImageResult AlbumCoverChoiceController::LoadImageFromURL() { AlbumCoverImageResult AlbumCoverChoiceController::LoadImageFromURL() {
if (!cover_from_url_dialog_) { cover_from_url_dialog_ = new CoverFromURLDialog(app_->network(), this); } if (!cover_from_url_dialog_) { cover_from_url_dialog_ = new CoverFromURLDialog(network_, this); }
return cover_from_url_dialog_->Exec(); return cover_from_url_dialog_->Exec();
@ -548,11 +554,11 @@ void AlbumCoverChoiceController::SaveArtEmbeddedToSong(Song *song, const bool ar
song->set_art_unset(false); song->set_art_unset(false);
if (song->source() == Song::Source::Collection) { if (song->source() == Song::Source::Collection) {
app_->collection_backend()->UpdateEmbeddedAlbumArtAsync(song->effective_albumartist(), song->album(), art_embedded); collection_backend_->UpdateEmbeddedAlbumArtAsync(song->effective_albumartist(), song->album(), art_embedded);
} }
if (*song == app_->current_albumcover_loader()->last_song()) { if (*song == current_albumcover_loader_->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song); current_albumcover_loader_->LoadAlbumCover(*song);
} }
} }
@ -567,7 +573,7 @@ void AlbumCoverChoiceController::SaveArtManualToSong(Song *song, const QUrl &art
// Update the backends. // Update the backends.
switch (song->source()) { switch (song->source()) {
case Song::Source::Collection: case Song::Source::Collection:
app_->collection_backend()->UpdateManualAlbumArtAsync(song->effective_albumartist(), song->album(), art_manual); collection_backend_->UpdateManualAlbumArtAsync(song->effective_albumartist(), song->album(), art_manual);
break; break;
case Song::Source::LocalFile: case Song::Source::LocalFile:
case Song::Source::CDDA: case Song::Source::CDDA:
@ -581,7 +587,7 @@ void AlbumCoverChoiceController::SaveArtManualToSong(Song *song, const QUrl &art
case Song::Source::Tidal: case Song::Source::Tidal:
case Song::Source::Spotify: case Song::Source::Spotify:
case Song::Source::Qobuz: case Song::Source::Qobuz:
StreamingServicePtr service = app_->streaming_services()->ServiceBySource(song->source()); StreamingServicePtr service = streaming_services_->ServiceBySource(song->source());
if (!service) break; if (!service) break;
if (service->artists_collection_backend()) { if (service->artists_collection_backend()) {
service->artists_collection_backend()->UpdateManualAlbumArtAsync(song->effective_albumartist(), song->album(), art_manual); service->artists_collection_backend()->UpdateManualAlbumArtAsync(song->effective_albumartist(), song->album(), art_manual);
@ -595,8 +601,8 @@ void AlbumCoverChoiceController::SaveArtManualToSong(Song *song, const QUrl &art
break; break;
} }
if (*song == app_->current_albumcover_loader()->last_song()) { if (*song == current_albumcover_loader_->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song); current_albumcover_loader_->LoadAlbumCover(*song);
} }
} }
@ -611,11 +617,11 @@ void AlbumCoverChoiceController::ClearAlbumCoverForSong(Song *song) {
song->clear_art_manual(); song->clear_art_manual();
if (song->source() == Song::Source::Collection) { if (song->source() == Song::Source::Collection) {
app_->collection_backend()->ClearAlbumArtAsync(song->effective_albumartist(), song->album(), false); collection_backend_->ClearAlbumArtAsync(song->effective_albumartist(), song->album(), false);
} }
if (*song == app_->current_albumcover_loader()->last_song()) { if (*song == current_albumcover_loader_->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song); current_albumcover_loader_->LoadAlbumCover(*song);
} }
} }
@ -630,11 +636,11 @@ void AlbumCoverChoiceController::UnsetAlbumCoverForSong(Song *song) {
song->clear_art_automatic(); song->clear_art_automatic();
if (song->source() == Song::Source::Collection) { if (song->source() == Song::Source::Collection) {
app_->collection_backend()->UnsetAlbumArtAsync(song->effective_albumartist(), song->album()); collection_backend_->UnsetAlbumArtAsync(song->effective_albumartist(), song->album());
} }
if (*song == app_->current_albumcover_loader()->last_song()) { if (*song == current_albumcover_loader_->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song); current_albumcover_loader_->LoadAlbumCover(*song);
} }
} }
@ -718,7 +724,7 @@ void AlbumCoverChoiceController::SaveCoverEmbeddedToCollectionSongs(const Song &
void AlbumCoverChoiceController::SaveCoverEmbeddedToCollectionSongs(const QString &effective_albumartist, const QString &effective_album, const QString &cover_filename, const QByteArray &image_data, const QString &mime_type) { void AlbumCoverChoiceController::SaveCoverEmbeddedToCollectionSongs(const QString &effective_albumartist, const QString &effective_album, const QString &cover_filename, const QByteArray &image_data, const QString &mime_type) {
QFuture<SongList> future = QtConcurrent::run(&CollectionBackend::GetAlbumSongs, app_->collection_backend(), effective_albumartist, effective_album, CollectionFilterOptions()); QFuture<SongList> future = QtConcurrent::run(&CollectionBackend::GetAlbumSongs, collection_backend_, effective_albumartist, effective_album, CollectionFilterOptions());
QFutureWatcher<SongList> *watcher = new QFutureWatcher<SongList>(); QFutureWatcher<SongList> *watcher = new QFutureWatcher<SongList>();
QObject::connect(watcher, &QFutureWatcher<SongList>::finished, this, [this, watcher, cover_filename, image_data, mime_type]() { QObject::connect(watcher, &QFutureWatcher<SongList>::finished, this, [this, watcher, cover_filename, image_data, mime_type]() {
const SongList collection_songs = watcher->result(); const SongList collection_songs = watcher->result();
@ -736,7 +742,7 @@ void AlbumCoverChoiceController::SaveCoverEmbeddedToSong(const Song &song, const
QMutexLocker l(&mutex_cover_save_tasks_); QMutexLocker l(&mutex_cover_save_tasks_);
cover_save_tasks_.append(song); cover_save_tasks_.append(song);
const bool art_embedded = !image_data.isNull(); const bool art_embedded = !image_data.isNull();
TagReaderReplyPtr reply = app_->tag_reader_client()->SaveCoverAsync(song.url().toLocalFile(), SaveTagCoverData(cover_filename, image_data, mime_type)); TagReaderReplyPtr reply = TagReaderClient::Instance()->SaveCoverAsync(song.url().toLocalFile(), SaveTagCoverData(cover_filename, image_data, mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, song, art_embedded]() { SaveEmbeddedCoverFinished(reply, song, art_embedded); }); QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, song, art_embedded]() { SaveEmbeddedCoverFinished(reply, song, art_embedded); });
} }

View File

@ -50,11 +50,16 @@ class QMenu;
class QDragEnterEvent; class QDragEnterEvent;
class QDropEvent; class QDropEvent;
class Application; class NetworkAccessManager;
class CollectionBackend;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class AlbumCoverFetcher; class AlbumCoverFetcher;
class AlbumCoverSearcher; class AlbumCoverSearcher;
class CoverFromURLDialog; class CoverFromURLDialog;
struct CoverSearchStatistics; struct CoverSearchStatistics;
class StreamingServices;
// Controller for the common album cover related menu options. // Controller for the common album cover related menu options.
class AlbumCoverChoiceController : public QWidget { class AlbumCoverChoiceController : public QWidget {
@ -68,7 +73,13 @@ class AlbumCoverChoiceController : public QWidget {
explicit AlbumCoverChoiceController(QWidget *parent = nullptr); explicit AlbumCoverChoiceController(QWidget *parent = nullptr);
~AlbumCoverChoiceController() override; ~AlbumCoverChoiceController() override;
void Init(Application *app); void Init(SharedPtr<NetworkAccessManager> network,
SharedPtr<CollectionBackend> collection_backend,
SharedPtr<AlbumCoverLoader> album_cover_loader,
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
SharedPtr<CoverProviders> cover_providers,
SharedPtr<StreamingServices> streaming_services);
void ReloadSettings(); void ReloadSettings();
CoverOptions::CoverType get_save_album_cover_type() const { return (save_embedded_cover_override_ ? CoverOptions::CoverType::Embedded : cover_options_.cover_type); } CoverOptions::CoverType get_save_album_cover_type() const { return (save_embedded_cover_override_ ? CoverOptions::CoverType::Embedded : cover_options_.cover_type); }
@ -172,7 +183,11 @@ class AlbumCoverChoiceController : public QWidget {
static bool IsKnownImageExtension(const QString &suffix); static bool IsKnownImageExtension(const QString &suffix);
static QSet<QString> *sImageExtensions; static QSet<QString> *sImageExtensions;
Application *app_; SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
SharedPtr<NetworkAccessManager> network_;
SharedPtr<CollectionBackend> collection_backend_;
SharedPtr<StreamingServices> streaming_services_;
AlbumCoverSearcher *cover_searcher_; AlbumCoverSearcher *cover_searcher_;
AlbumCoverFetcher *cover_fetcher_; AlbumCoverFetcher *cover_fetcher_;

View File

@ -64,10 +64,10 @@
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/application.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/database.h"
#include "core/settings.h" #include "core/settings.h"
#include "core/database.h"
#include "core/networkaccessmanager.h"
#include "utilities/strutils.h" #include "utilities/strutils.h"
#include "utilities/fileutils.h" #include "utilities/fileutils.h"
#include "utilities/imageutils.h" #include "utilities/imageutils.h"
@ -79,7 +79,6 @@
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
#include "collection/collectionquery.h" #include "collection/collectionquery.h"
#include "playlist/songmimedata.h" #include "playlist/songmimedata.h"
#include "coverproviders.h"
#include "albumcovermanager.h" #include "albumcovermanager.h"
#include "albumcoversearcher.h" #include "albumcoversearcher.h"
#include "albumcoverchoicecontroller.h" #include "albumcoverchoicecontroller.h"
@ -88,6 +87,7 @@
#include "albumcoverfetcher.h" #include "albumcoverfetcher.h"
#include "albumcoverloader.h" #include "albumcoverloader.h"
#include "albumcoverloaderresult.h" #include "albumcoverloaderresult.h"
#include "coverproviders.h"
#include "coversearchstatistics.h" #include "coversearchstatistics.h"
#include "coversearchstatisticsdialog.h" #include "coversearchstatisticsdialog.h"
#include "albumcoverimageresult.h" #include "albumcoverimageresult.h"
@ -102,18 +102,28 @@ constexpr char kSettingsGroup[] = "CoverManager";
constexpr int kThumbnailSize = 120; constexpr int kThumbnailSize = 120;
} }
AlbumCoverManager::AlbumCoverManager(Application *app, SharedPtr<CollectionBackend> collection_backend, QMainWindow *mainwindow, QWidget *parent) AlbumCoverManager::AlbumCoverManager(SharedPtr<NetworkAccessManager> network,
SharedPtr<CollectionBackend> collection_backend,
SharedPtr<TagReaderClient> tagreader_client,
SharedPtr<AlbumCoverLoader> album_cover_loader,
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
SharedPtr<CoverProviders> cover_providers,
SharedPtr<StreamingServices> streaming_services,
QMainWindow *mainwindow, QWidget *parent)
: QMainWindow(parent), : QMainWindow(parent),
ui_(new Ui_CoverManager), ui_(new Ui_CoverManager),
mainwindow_(mainwindow), mainwindow_(mainwindow),
app_(app), network_(network),
collection_backend_(collection_backend), collection_backend_(collection_backend),
tagreader_client_(tagreader_client),
album_cover_loader_(album_cover_loader),
cover_providers_(cover_providers),
album_cover_choice_controller_(new AlbumCoverChoiceController(this)), album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
timer_album_cover_load_(new QTimer(this)), timer_album_cover_load_(new QTimer(this)),
filter_all_(nullptr), filter_all_(nullptr),
filter_with_covers_(nullptr), filter_with_covers_(nullptr),
filter_without_covers_(nullptr), filter_without_covers_(nullptr),
cover_fetcher_(new AlbumCoverFetcher(app_->cover_providers(), app_->network(), this)), cover_fetcher_(new AlbumCoverFetcher(cover_providers, network, this)),
cover_searcher_(nullptr), cover_searcher_(nullptr),
cover_export_(nullptr), cover_export_(nullptr),
cover_exporter_(new AlbumCoverExporter(this)), cover_exporter_(new AlbumCoverExporter(this)),
@ -142,9 +152,9 @@ AlbumCoverManager::AlbumCoverManager(Application *app, SharedPtr<CollectionBacke
ui_->action_add_to_playlist->setIcon(IconLoader::Load(u"media-playback-start"_s)); ui_->action_add_to_playlist->setIcon(IconLoader::Load(u"media-playback-start"_s));
ui_->action_load->setIcon(IconLoader::Load(u"media-playback-start"_s)); ui_->action_load->setIcon(IconLoader::Load(u"media-playback-start"_s));
album_cover_choice_controller_->Init(app_); album_cover_choice_controller_->Init(network, collection_backend, album_cover_loader, current_albumcover_loader, cover_providers, streaming_services);
cover_searcher_ = new AlbumCoverSearcher(icon_nocover_item_, app_, this); cover_searcher_ = new AlbumCoverSearcher(icon_nocover_item_, album_cover_loader_, this);
cover_export_ = new AlbumCoverExport(this); cover_export_ = new AlbumCoverExport(this);
// Set up the status bar // Set up the status bar
@ -241,7 +251,7 @@ void AlbumCoverManager::Init() {
s.endGroup(); s.endGroup();
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &AlbumCoverManager::AlbumCoverLoaded); QObject::connect(&*album_cover_loader_, &AlbumCoverLoader::AlbumCoverLoaded, this, &AlbumCoverManager::AlbumCoverLoaded);
cover_searcher_->Init(cover_fetcher_); cover_searcher_->Init(cover_fetcher_);
@ -320,7 +330,7 @@ void AlbumCoverManager::SaveSettings() {
void AlbumCoverManager::CancelRequests() { void AlbumCoverManager::CancelRequests() {
app_->album_cover_loader()->CancelTasks(QSet<quint64>(cover_loading_tasks_.keyBegin(), cover_loading_tasks_.keyEnd())); album_cover_loader_->CancelTasks(QSet<quint64>(cover_loading_tasks_.keyBegin(), cover_loading_tasks_.keyEnd()));
cover_loading_pending_.clear(); cover_loading_pending_.clear();
cover_loading_tasks_.clear(); cover_loading_tasks_.clear();
cover_save_tasks_.clear(); cover_save_tasks_.clear();
@ -363,7 +373,7 @@ void AlbumCoverManager::Reset() {
} }
void AlbumCoverManager::EnableCoversButtons() { void AlbumCoverManager::EnableCoversButtons() {
ui_->button_fetch->setEnabled(app_->cover_providers()->HasAnyProviders()); ui_->button_fetch->setEnabled(cover_providers_->HasAnyProviders());
ui_->export_covers->setEnabled(true); ui_->export_covers->setEnabled(true);
} }
@ -466,7 +476,7 @@ void AlbumCoverManager::LoadAlbumCoverAsync(AlbumItem *album_item) {
cover_options.types = cover_types_; cover_options.types = cover_types_;
cover_options.desired_scaled_size = QSize(kThumbnailSize, kThumbnailSize); cover_options.desired_scaled_size = QSize(kThumbnailSize, kThumbnailSize);
cover_options.device_pixel_ratio = devicePixelRatioF(); cover_options.device_pixel_ratio = devicePixelRatioF();
quint64 cover_load_id = app_->album_cover_loader()->LoadImageAsync(cover_options, album_item->data(Role_ArtEmbedded).toBool(), album_item->data(Role_ArtAutomatic).toUrl(), album_item->data(Role_ArtManual).toUrl(), album_item->data(Role_ArtUnset).toBool(), album_item->urls.constFirst()); quint64 cover_load_id = album_cover_loader_->LoadImageAsync(cover_options, album_item->data(Role_ArtEmbedded).toBool(), album_item->data(Role_ArtAutomatic).toUrl(), album_item->data(Role_ArtManual).toUrl(), album_item->data(Role_ArtUnset).toBool(), album_item->urls.constFirst());
cover_loading_tasks_.insert(cover_load_id, album_item); cover_loading_tasks_.insert(cover_load_id, album_item);
} }
@ -643,7 +653,7 @@ bool AlbumCoverManager::eventFilter(QObject *obj, QEvent *e) {
album_cover_choice_controller_->cover_to_file_action()->setEnabled(some_with_covers); album_cover_choice_controller_->cover_to_file_action()->setEnabled(some_with_covers);
album_cover_choice_controller_->cover_from_file_action()->setEnabled(context_menu_items_.size() == 1); album_cover_choice_controller_->cover_from_file_action()->setEnabled(context_menu_items_.size() == 1);
album_cover_choice_controller_->cover_from_url_action()->setEnabled(context_menu_items_.size() == 1); album_cover_choice_controller_->cover_from_url_action()->setEnabled(context_menu_items_.size() == 1);
album_cover_choice_controller_->search_for_cover_action()->setEnabled(app_->cover_providers()->HasAnyProviders()); album_cover_choice_controller_->search_for_cover_action()->setEnabled(cover_providers_->HasAnyProviders());
album_cover_choice_controller_->unset_cover_action()->setEnabled(some_with_covers || some_clear); album_cover_choice_controller_->unset_cover_action()->setEnabled(some_with_covers || some_clear);
album_cover_choice_controller_->clear_cover_action()->setEnabled(some_with_covers || some_unset); album_cover_choice_controller_->clear_cover_action()->setEnabled(some_with_covers || some_unset);
album_cover_choice_controller_->delete_cover_action()->setEnabled(some_with_covers); album_cover_choice_controller_->delete_cover_action()->setEnabled(some_with_covers);
@ -844,7 +854,7 @@ void AlbumCoverManager::SaveImageToAlbums(Song *song, const AlbumCoverImageResul
case CoverOptions::CoverType::Embedded:{ case CoverOptions::CoverType::Embedded:{
for (const QUrl &url : std::as_const(album_item->urls)) { for (const QUrl &url : std::as_const(album_item->urls)) {
const bool art_embedded = !result.image_data.isEmpty(); const bool art_embedded = !result.image_data.isEmpty();
TagReaderReplyPtr reply = app_->tag_reader_client()->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.image_data, result.mime_type)); TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.image_data, result.mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() { QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded); SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
}); });
@ -994,7 +1004,7 @@ void AlbumCoverManager::SaveAndSetCover(AlbumItem *album_item, const AlbumCoverI
if (album_cover_choice_controller_->get_save_album_cover_type() == CoverOptions::CoverType::Embedded && Song::save_embedded_cover_supported(filetype) && !has_cue) { if (album_cover_choice_controller_->get_save_album_cover_type() == CoverOptions::CoverType::Embedded && Song::save_embedded_cover_supported(filetype) && !has_cue) {
for (const QUrl &url : urls) { for (const QUrl &url : urls) {
const bool art_embedded = !result.image_data.isEmpty(); const bool art_embedded = !result.image_data.isEmpty();
TagReaderReplyPtr reply = app_->tag_reader_client()->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.cover_url.isValid() ? result.cover_url.toLocalFile() : QString(), result.image_data, result.mime_type)); TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.cover_url.isValid() ? result.cover_url.toLocalFile() : QString(), result.image_data, result.mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() { QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded); SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
}); });

View File

@ -55,8 +55,11 @@ class QEvent;
class QCloseEvent; class QCloseEvent;
class QShowEvent; class QShowEvent;
class Application; class NetworkAccessManager;
class CollectionBackend; class CollectionBackend;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class SongMimeData; class SongMimeData;
class AlbumCoverExport; class AlbumCoverExport;
class AlbumCoverExporter; class AlbumCoverExporter;
@ -78,7 +81,15 @@ class AlbumCoverManager : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
explicit AlbumCoverManager(Application *app, SharedPtr<CollectionBackend> collection_backend, QMainWindow *mainwindow, QWidget *parent = nullptr); explicit AlbumCoverManager(SharedPtr<NetworkAccessManager> network,
SharedPtr<CollectionBackend> collection_backend,
SharedPtr<TagReaderClient> tagreader_client,
SharedPtr<AlbumCoverLoader> album_cover_loader,
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
SharedPtr<CoverProviders> cover_providers,
SharedPtr<StreamingServices> streaming_services,
QMainWindow *mainwindow,
QWidget *parent = nullptr);
~AlbumCoverManager() override; ~AlbumCoverManager() override;
void Reset(); void Reset();
@ -190,8 +201,11 @@ class AlbumCoverManager : public QMainWindow {
private: private:
Ui_CoverManager *ui_; Ui_CoverManager *ui_;
QMainWindow *mainwindow_; QMainWindow *mainwindow_;
Application *app_; SharedPtr<NetworkAccessManager> network_;
SharedPtr<CollectionBackend> collection_backend_; SharedPtr<CollectionBackend> collection_backend_;
SharedPtr<TagReaderClient> tagreader_client_;
SharedPtr<AlbumCoverLoader> album_cover_loader_;
SharedPtr<CoverProviders> cover_providers_;
AlbumCoverChoiceController *album_cover_choice_controller_; AlbumCoverChoiceController *album_cover_choice_controller_;
QTimer *timer_album_cover_load_; QTimer *timer_album_cover_load_;

View File

@ -47,9 +47,7 @@
#include <QKeySequence> #include <QKeySequence>
#include <QtEvents> #include <QtEvents>
#include "core/application.h"
#include "utilities/strutils.h" #include "utilities/strutils.h"
#include "utilities/timeutils.h"
#include "utilities/mimeutils.h" #include "utilities/mimeutils.h"
#include "widgets/busyindicator.h" #include "widgets/busyindicator.h"
#include "widgets/forcescrollperpixel.h" #include "widgets/forcescrollperpixel.h"
@ -114,10 +112,10 @@ void SizeOverlayDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
} }
AlbumCoverSearcher::AlbumCoverSearcher(const QIcon &no_cover_icon, Application *app, QWidget *parent) AlbumCoverSearcher::AlbumCoverSearcher(const QIcon &no_cover_icon, SharedPtr<AlbumCoverLoader> album_cover_loader, QWidget *parent)
: QDialog(parent), : QDialog(parent),
ui_(new Ui_AlbumCoverSearcher), ui_(new Ui_AlbumCoverSearcher),
app_(app), album_cover_loader_(album_cover_loader),
model_(new QStandardItemModel(this)), model_(new QStandardItemModel(this)),
no_cover_icon_(no_cover_icon), no_cover_icon_(no_cover_icon),
fetcher_(nullptr), fetcher_(nullptr),
@ -132,7 +130,7 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon &no_cover_icon, Application *
ui_->covers->setItemDelegate(new SizeOverlayDelegate(this)); ui_->covers->setItemDelegate(new SizeOverlayDelegate(this));
ui_->covers->setModel(model_); ui_->covers->setModel(model_);
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &AlbumCoverSearcher::AlbumCoverLoaded); QObject::connect(&*album_cover_loader_, &AlbumCoverLoader::AlbumCoverLoaded, this, &AlbumCoverSearcher::AlbumCoverLoaded);
QObject::connect(ui_->search, &QPushButton::clicked, this, &AlbumCoverSearcher::Search); QObject::connect(ui_->search, &QPushButton::clicked, this, &AlbumCoverSearcher::Search);
QObject::connect(ui_->covers, &GroupedIconView::doubleClicked, this, &AlbumCoverSearcher::CoverDoubleClicked); QObject::connect(ui_->covers, &GroupedIconView::doubleClicked, this, &AlbumCoverSearcher::CoverDoubleClicked);
@ -220,7 +218,7 @@ void AlbumCoverSearcher::SearchFinished(const quint64 id, const CoverProviderSea
AlbumCoverLoaderOptions cover_options(AlbumCoverLoaderOptions::Option::RawImageData | AlbumCoverLoaderOptions::Option::OriginalImage | AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage); AlbumCoverLoaderOptions cover_options(AlbumCoverLoaderOptions::Option::RawImageData | AlbumCoverLoaderOptions::Option::OriginalImage | AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage);
cover_options.desired_scaled_size = ui_->covers->iconSize(), ui_->covers->iconSize(); cover_options.desired_scaled_size = ui_->covers->iconSize(), ui_->covers->iconSize();
quint64 new_id = app_->album_cover_loader()->LoadImageAsync(cover_options, false, result.image_url, QUrl(), false); quint64 new_id = album_cover_loader_->LoadImageAsync(cover_options, false, result.image_url, QUrl(), false);
QStandardItem *item = new QStandardItem; QStandardItem *item = new QStandardItem;
item->setIcon(no_cover_icon_); item->setIcon(no_cover_icon_);

View File

@ -48,7 +48,7 @@ class QPainter;
class QModelIndex; class QModelIndex;
class QKeyEvent; class QKeyEvent;
class Application; class AlbumCoverLoader;
class Ui_AlbumCoverSearcher; class Ui_AlbumCoverSearcher;
class SizeOverlayDelegate : public QStyledItemDelegate { class SizeOverlayDelegate : public QStyledItemDelegate {
@ -65,7 +65,7 @@ class AlbumCoverSearcher : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit AlbumCoverSearcher(const QIcon &no_cover_icon, Application *app, QWidget *parent); explicit AlbumCoverSearcher(const QIcon &no_cover_icon, SharedPtr<AlbumCoverLoader> album_cover_loader, QWidget *parent);
~AlbumCoverSearcher() override; ~AlbumCoverSearcher() override;
enum Role { enum Role {
@ -95,7 +95,7 @@ class AlbumCoverSearcher : public QDialog {
private: private:
Ui_AlbumCoverSearcher *ui_; Ui_AlbumCoverSearcher *ui_;
Application *app_; SharedPtr<AlbumCoverLoader> album_cover_loader_;
QStandardItemModel *model_; QStandardItemModel *model_;
QIcon no_cover_icon_; QIcon no_cover_icon_;

View File

@ -25,7 +25,6 @@
#include <QString> #include <QString>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "coverprovider.h" #include "coverprovider.h"
CoverProvider::CoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) : QObject(parent), app_(app), network_(network), name_(name), enabled_(enabled), order_(0), authentication_required_(authentication_required), quality_(quality), batch_(batch), allow_missing_album_(allow_missing_album) {} CoverProvider::CoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, SharedPtr<NetworkAccessManager> network, QObject *parent) : QObject(parent), network_(network), name_(name), enabled_(enabled), order_(0), authentication_required_(authentication_required), quality_(quality), batch_(batch), allow_missing_album_(allow_missing_album) {}

View File

@ -33,7 +33,6 @@
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "albumcoverfetcher.h" #include "albumcoverfetcher.h"
class Application;
class NetworkAccessManager; class NetworkAccessManager;
// Each implementation of this interface downloads covers from one online service. // Each implementation of this interface downloads covers from one online service.
@ -42,7 +41,7 @@ class CoverProvider : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit CoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent); explicit CoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, SharedPtr<NetworkAccessManager> network, QObject *parent);
// A name (very short description) of this provider, like "last.fm". // A name (very short description) of this provider, like "last.fm".
QString name() const { return name_; } QString name() const { return name_; }
@ -79,7 +78,6 @@ class CoverProvider : public QObject {
using Param = QPair<QString, QString>; using Param = QPair<QString, QString>;
using ParamList = QList<Param>; using ParamList = QList<Param>;
Application *app_;
SharedPtr<NetworkAccessManager> network_; SharedPtr<NetworkAccessManager> network_;
QString name_; QString name_;
bool enabled_; bool enabled_;

View File

@ -29,10 +29,9 @@
#include <QImage> #include <QImage>
#include <QStandardPaths> #include <QStandardPaths>
#include "core/application.h" #include "core/logging.h"
#include "core/song.h" #include "core/song.h"
#include "core/temporaryfile.h" #include "core/temporaryfile.h"
#include "playlist/playlistmanager.h"
#include "albumcoverloader.h" #include "albumcoverloader.h"
#include "albumcoverloaderresult.h" #include "albumcoverloaderresult.h"
#include "currentalbumcoverloader.h" #include "currentalbumcoverloader.h"
@ -40,9 +39,9 @@
using std::make_unique; using std::make_unique;
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(Application *app, QObject *parent) CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(SharedPtr<AlbumCoverLoader> albumcover_loader, QObject *parent)
: QObject(parent), : QObject(parent),
app_(app), albumcover_loader_(albumcover_loader),
temp_file_pattern_(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u"/strawberry-cover-XXXXXX.jpg"_s), temp_file_pattern_(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u"/strawberry-cover-XXXXXX.jpg"_s),
id_(0) { id_(0) {
@ -52,8 +51,7 @@ CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(Application *app, QObject *pare
options_.desired_scaled_size = QSize(120, 120); options_.desired_scaled_size = QSize(120, 120);
options_.default_cover = u":/pictures/cdcase.png"_s; options_.default_cover = u":/pictures/cdcase.png"_s;
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &CurrentAlbumCoverLoader::LoadAlbumCover); QObject::connect(&*albumcover_loader, &AlbumCoverLoader::AlbumCoverLoaded, this, &CurrentAlbumCoverLoader::AlbumCoverReady);
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CurrentAlbumCoverLoader::AlbumCoverReady);
ReloadSettingsAsync(); ReloadSettingsAsync();
@ -76,7 +74,7 @@ void CurrentAlbumCoverLoader::ReloadSettings() {
void CurrentAlbumCoverLoader::LoadAlbumCover(const Song &song) { void CurrentAlbumCoverLoader::LoadAlbumCover(const Song &song) {
last_song_ = song; last_song_ = song;
id_ = app_->album_cover_loader()->LoadImageAsync(options_, last_song_); id_ = albumcover_loader_->LoadImageAsync(options_, last_song_);
} }

View File

@ -30,18 +30,19 @@
#include <QImage> #include <QImage>
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/temporaryfile.h" #include "core/temporaryfile.h"
#include "core/song.h" #include "core/song.h"
#include "albumcoverloaderoptions.h" #include "albumcoverloaderoptions.h"
#include "albumcoverloaderresult.h" #include "albumcoverloaderresult.h"
class Application; class AlbumCoverLoader;
class CurrentAlbumCoverLoader : public QObject { class CurrentAlbumCoverLoader : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit CurrentAlbumCoverLoader(Application *app, QObject *parent = nullptr); explicit CurrentAlbumCoverLoader(SharedPtr<AlbumCoverLoader> albumcover_loader, QObject *parent = nullptr);
~CurrentAlbumCoverLoader() override; ~CurrentAlbumCoverLoader() override;
const AlbumCoverLoaderOptions &options() const { return options_; } const AlbumCoverLoaderOptions &options() const { return options_; }
@ -61,7 +62,7 @@ class CurrentAlbumCoverLoader : public QObject {
void AlbumCoverReady(const quint64 id, AlbumCoverLoaderResult result); void AlbumCoverReady(const quint64 id, AlbumCoverLoaderResult result);
private: private:
Application *app_; SharedPtr<AlbumCoverLoader> albumcover_loader_;
AlbumCoverLoaderOptions options_; AlbumCoverLoaderOptions options_;
QString temp_file_pattern_; QString temp_file_pattern_;

View File

@ -39,7 +39,6 @@
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/song.h" #include "core/song.h"
@ -55,8 +54,8 @@ constexpr char kApiUrl[] = "https://api.deezer.com";
constexpr int kLimit = 10; constexpr int kLimit = 10;
} }
DeezerCoverProvider::DeezerCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) DeezerCoverProvider::DeezerCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Deezer"_s, true, false, 2.0, true, true, app, network, parent) {} : JsonCoverProvider(u"Deezer"_s, true, false, 2.0, true, true, network, parent) {}
DeezerCoverProvider::~DeezerCoverProvider() { DeezerCoverProvider::~DeezerCoverProvider() {

View File

@ -34,13 +34,12 @@
class NetworkAccessManager; class NetworkAccessManager;
class QNetworkReply; class QNetworkReply;
class Application;
class DeezerCoverProvider : public JsonCoverProvider { class DeezerCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit DeezerCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit DeezerCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~DeezerCoverProvider() override; ~DeezerCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -42,7 +42,6 @@
#include <QJsonArray> #include <QJsonArray>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "utilities/cryptutils.h" #include "utilities/cryptutils.h"
@ -58,8 +57,8 @@ const char *DiscogsCoverProvider::kAccessKeyB64 = "dGh6ZnljUGJlZ1NEeXBuSFFxSVk="
const char *DiscogsCoverProvider::kSecretKeyB64 = "ZkFIcmlaSER4aHhRSlF2U3d0bm5ZVmdxeXFLWUl0UXI="; const char *DiscogsCoverProvider::kSecretKeyB64 = "ZkFIcmlaSER4aHhRSlF2U3d0bm5ZVmdxeXFLWUl0UXI=";
const int DiscogsCoverProvider::kRequestsDelay = 1000; const int DiscogsCoverProvider::kRequestsDelay = 1000;
DiscogsCoverProvider::DiscogsCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) DiscogsCoverProvider::DiscogsCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Discogs"_s, false, false, 0.0, false, false, app, network, parent), : JsonCoverProvider(u"Discogs"_s, false, false, 0.0, false, false, network, parent),
timer_flush_requests_(new QTimer(this)) { timer_flush_requests_(new QTimer(this)) {
timer_flush_requests_->setInterval(kRequestsDelay); timer_flush_requests_->setInterval(kRequestsDelay);

View File

@ -42,13 +42,12 @@
class NetworkAccessManager; class NetworkAccessManager;
class QNetworkReply; class QNetworkReply;
class QTimer; class QTimer;
class Application;
class DiscogsCoverProvider : public JsonCoverProvider { class DiscogsCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit DiscogsCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit DiscogsCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~DiscogsCoverProvider() override; ~DiscogsCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -26,15 +26,14 @@
#include <QJsonObject> #include <QJsonObject>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "coverprovider.h" #include "coverprovider.h"
#include "jsoncoverprovider.h" #include "jsoncoverprovider.h"
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
JsonCoverProvider::JsonCoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) JsonCoverProvider::JsonCoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, SharedPtr<NetworkAccessManager> network, QObject *parent)
: CoverProvider(name, enabled, authentication_required, quality, batch, allow_missing_album, app, network, parent) {} : CoverProvider(name, enabled, authentication_required, quality, batch, allow_missing_album, network, parent) {}
QJsonObject JsonCoverProvider::ExtractJsonObj(const QByteArray &data) { QJsonObject JsonCoverProvider::ExtractJsonObj(const QByteArray &data) {

View File

@ -30,14 +30,13 @@
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "coverprovider.h" #include "coverprovider.h"
class Application;
class NetworkAccessManager; class NetworkAccessManager;
class JsonCoverProvider : public CoverProvider { class JsonCoverProvider : public CoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit JsonCoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent); explicit JsonCoverProvider(const QString &name, const bool enabled, const bool authentication_required, const float quality, const bool batch, const bool allow_missing_album, SharedPtr<NetworkAccessManager> network, QObject *parent);
protected: protected:
QJsonObject ExtractJsonObj(const QByteArray &data); QJsonObject ExtractJsonObj(const QByteArray &data);

View File

@ -39,7 +39,6 @@
#include <QJsonArray> #include <QJsonArray>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
@ -55,8 +54,8 @@ constexpr char kApiKey[] = "211990b4c96782c05d1536e7219eb56e";
constexpr char kSecret[] = "80fd738f49596e9709b1bf9319c444a8"; constexpr char kSecret[] = "80fd738f49596e9709b1bf9319c444a8";
} // namespace } // namespace
LastFmCoverProvider::LastFmCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) LastFmCoverProvider::LastFmCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Last.fm"_s, true, false, 1.0, true, false, app, network, parent) {} : JsonCoverProvider(u"Last.fm"_s, true, false, 1.0, true, false, network, parent) {}
LastFmCoverProvider::~LastFmCoverProvider() { LastFmCoverProvider::~LastFmCoverProvider() {

View File

@ -34,13 +34,12 @@
class NetworkAccessManager; class NetworkAccessManager;
class QNetworkReply; class QNetworkReply;
class Application;
class LastFmCoverProvider : public JsonCoverProvider { class LastFmCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit LastFmCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit LastFmCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~LastFmCoverProvider() override; ~LastFmCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -37,7 +37,6 @@
#include <QJsonArray> #include <QJsonArray>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
#include "albumcoverfetcher.h" #include "albumcoverfetcher.h"
@ -53,8 +52,8 @@ constexpr int kLimit = 8;
constexpr int kRequestsDelay = 1000; constexpr int kRequestsDelay = 1000;
} // namespace } // namespace
MusicbrainzCoverProvider::MusicbrainzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) MusicbrainzCoverProvider::MusicbrainzCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"MusicBrainz"_s, true, false, 1.5, true, false, app, network, parent), : JsonCoverProvider(u"MusicBrainz"_s, true, false, 1.5, true, false, network, parent),
timer_flush_requests_(new QTimer(this)) { timer_flush_requests_(new QTimer(this)) {
timer_flush_requests_->setInterval(kRequestsDelay); timer_flush_requests_->setInterval(kRequestsDelay);

View File

@ -35,14 +35,13 @@
class QNetworkReply; class QNetworkReply;
class QTimer; class QTimer;
class Application;
class NetworkAccessManager; class NetworkAccessManager;
class MusicbrainzCoverProvider : public JsonCoverProvider { class MusicbrainzCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit MusicbrainzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit MusicbrainzCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~MusicbrainzCoverProvider() override; ~MusicbrainzCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -42,8 +42,8 @@
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
MusixmatchCoverProvider::MusixmatchCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) MusixmatchCoverProvider::MusixmatchCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Musixmatch"_s, true, false, 1.0, true, false, app, network, parent) {} : JsonCoverProvider(u"Musixmatch"_s, true, false, 1.0, true, false, network, parent) {}
MusixmatchCoverProvider::~MusixmatchCoverProvider() { MusixmatchCoverProvider::~MusixmatchCoverProvider() {

View File

@ -39,7 +39,7 @@ class MusixmatchCoverProvider : public JsonCoverProvider, MusixmatchProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit MusixmatchCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit MusixmatchCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~MusixmatchCoverProvider() override; ~MusixmatchCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -38,11 +38,11 @@
#include <QTimer> #include <QTimer>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/settings.h" #include "core/settings.h"
#include "utilities/timeconstants.h" #include "core/song.h"
#include "constants/timeconstants.h"
#include "albumcoverfetcher.h" #include "albumcoverfetcher.h"
#include "jsoncoverprovider.h" #include "jsoncoverprovider.h"
#include "opentidalcoverprovider.h" #include "opentidalcoverprovider.h"
@ -61,8 +61,8 @@ constexpr const int kRequestsDelay = 1000;
using std::make_shared; using std::make_shared;
OpenTidalCoverProvider::OpenTidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) OpenTidalCoverProvider::OpenTidalCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"OpenTidal"_s, true, false, 2.5, true, false, app, network, parent), : JsonCoverProvider(u"OpenTidal"_s, true, false, 2.5, true, false, network, parent),
login_timer_(new QTimer(this)), login_timer_(new QTimer(this)),
timer_flush_requests_(new QTimer(this)), timer_flush_requests_(new QTimer(this)),
login_in_progress_(false), login_in_progress_(false),

View File

@ -36,7 +36,6 @@
#include "jsoncoverprovider.h" #include "jsoncoverprovider.h"
class QNetworkReply; class QNetworkReply;
class Application;
class NetworkAccessManager; class NetworkAccessManager;
class QTimer; class QTimer;
@ -44,7 +43,7 @@ class OpenTidalCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit OpenTidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit OpenTidalCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~OpenTidalCoverProvider() override; ~OpenTidalCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -37,7 +37,6 @@
#include <QJsonArray> #include <QJsonArray>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/song.h" #include "core/song.h"
@ -53,9 +52,9 @@ namespace {
constexpr int kLimit = 10; constexpr int kLimit = 10;
} }
QobuzCoverProvider::QobuzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) QobuzCoverProvider::QobuzCoverProvider(QobuzServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Qobuz"_s, true, true, 2.0, true, true, app, network, parent), : JsonCoverProvider(u"Qobuz"_s, true, true, 2.0, true, true, network, parent),
service_(app->streaming_services()->Service<QobuzService>()) {} service_(service) {}
QobuzCoverProvider::~QobuzCoverProvider() { QobuzCoverProvider::~QobuzCoverProvider() {

View File

@ -35,14 +35,13 @@
#include "qobuz/qobuzservice.h" #include "qobuz/qobuzservice.h"
class QNetworkReply; class QNetworkReply;
class Application;
class NetworkAccessManager; class NetworkAccessManager;
class QobuzCoverProvider : public JsonCoverProvider { class QobuzCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit QobuzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit QobuzCoverProvider(QobuzServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~QobuzCoverProvider() override; ~QobuzCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -39,10 +39,8 @@
#include <QMessageBox> #include <QMessageBox>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
#include "streaming/streamingservices.h"
#include "spotify/spotifyservice.h" #include "spotify/spotifyservice.h"
#include "albumcoverfetcher.h" #include "albumcoverfetcher.h"
#include "jsoncoverprovider.h" #include "jsoncoverprovider.h"
@ -55,9 +53,9 @@ constexpr char kApiUrl[] = "https://api.spotify.com/v1";
constexpr int kLimit = 10; constexpr int kLimit = 10;
} // namespace } // namespace
SpotifyCoverProvider::SpotifyCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) SpotifyCoverProvider::SpotifyCoverProvider(SpotifyServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Spotify"_s, true, true, 2.5, true, true, app, network, parent), : JsonCoverProvider(u"Spotify"_s, true, true, 2.5, true, true, network, parent),
service_(app->streaming_services()->Service<SpotifyService>()) {} service_(service) {}
SpotifyCoverProvider::~SpotifyCoverProvider() { SpotifyCoverProvider::~SpotifyCoverProvider() {

View File

@ -39,14 +39,13 @@
#include "spotify/spotifyservice.h" #include "spotify/spotifyservice.h"
class QNetworkReply; class QNetworkReply;
class Application;
class NetworkAccessManager; class NetworkAccessManager;
class SpotifyCoverProvider : public JsonCoverProvider { class SpotifyCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit SpotifyCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit SpotifyCoverProvider(SpotifyServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~SpotifyCoverProvider() override; ~SpotifyCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -35,11 +35,9 @@
#include <QJsonArray> #include <QJsonArray>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/song.h" #include "core/song.h"
#include "streaming/streamingservices.h"
#include "tidal/tidalservice.h" #include "tidal/tidalservice.h"
#include "albumcoverfetcher.h" #include "albumcoverfetcher.h"
#include "jsoncoverprovider.h" #include "jsoncoverprovider.h"
@ -51,9 +49,9 @@ namespace {
constexpr int kLimit = 10; constexpr int kLimit = 10;
} }
TidalCoverProvider::TidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) TidalCoverProvider::TidalCoverProvider(TidalServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Tidal"_s, true, true, 2.5, true, true, app, network, parent), : JsonCoverProvider(u"Tidal"_s, true, true, 2.5, true, true, network, parent),
service_(app->streaming_services()->Service<TidalService>()) {} service_(service) {}
TidalCoverProvider::~TidalCoverProvider() { TidalCoverProvider::~TidalCoverProvider() {

View File

@ -37,14 +37,13 @@
#include "tidal/tidalservice.h" #include "tidal/tidalservice.h"
class QNetworkReply; class QNetworkReply;
class Application;
class NetworkAccessManager; class NetworkAccessManager;
class TidalCoverProvider : public JsonCoverProvider { class TidalCoverProvider : public JsonCoverProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit TidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit TidalCoverProvider(TidalServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~TidalCoverProvider() override; ~TidalCoverProvider() override;
bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override; bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id) override;

View File

@ -30,12 +30,11 @@
#include "connecteddevice.h" #include "connecteddevice.h"
#include "cddadevice.h" #include "cddadevice.h"
class Application;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
CddaDevice::CddaDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, int database_id, bool first_time, QObject *parent) CddaDevice::CddaDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, int database_id, bool first_time, QObject *parent)
: ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, parent), : ConnectedDevice(url, lister, unique_id, manager, task_manager, database, album_cover_loader, database_id, first_time, parent),
cdda_song_loader_(url) { cdda_song_loader_(url) {
QObject::connect(&cdda_song_loader_, &CddaSongLoader::SongsLoaded, this, &CddaDevice::SongsLoaded); QObject::connect(&cdda_song_loader_, &CddaSongLoader::SongsLoaded, this, &CddaDevice::SongsLoaded);

View File

@ -24,22 +24,23 @@
#include "config.h" #include "config.h"
#include <cdio/cdio.h>
#include <gst/audio/gstaudiocdsrc.h>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QUrl> #include <QUrl>
// These must come after Qt includes
#include <cdio/cdio.h>
#include <gst/audio/gstaudiocdsrc.h>
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/song.h" #include "core/song.h"
#include "core/musicstorage.h" #include "core/musicstorage.h"
#include "cddasongloader.h" #include "cddasongloader.h"
#include "connecteddevice.h" #include "connecteddevice.h"
class Application; class TaskManager;
class Database;
class AlbumCoverLoader;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
@ -47,7 +48,7 @@ class CddaDevice : public ConnectedDevice {
Q_OBJECT Q_OBJECT
public: public:
Q_INVOKABLE explicit CddaDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent = nullptr); Q_INVOKABLE explicit CddaDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent = nullptr);
bool Init() override; bool Init() override;
void Refresh() override; void Refresh() override;

View File

@ -43,7 +43,7 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
using std::make_shared; using std::make_shared;

View File

@ -28,7 +28,7 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h" #include "core/taskmanager.h"
#include "core/database.h" #include "core/database.h"
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
#include "collection/collectionmodel.h" #include "collection/collectionmodel.h"
@ -41,9 +41,8 @@
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
using std::make_shared; using std::make_shared;
ConnectedDevice::ConnectedDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent) ConnectedDevice::ConnectedDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent)
: QObject(parent), : QObject(parent),
app_(app),
url_(url), url_(url),
first_time_(first_time), first_time_(first_time),
lister_(lister), lister_(lister),
@ -58,22 +57,22 @@ ConnectedDevice::ConnectedDevice(const QUrl &url, DeviceLister *lister, const QS
// Create the backend in the database thread. // Create the backend in the database thread.
backend_ = make_shared<CollectionBackend>(); backend_ = make_shared<CollectionBackend>();
backend_->moveToThread(app_->database()->thread()); backend_->moveToThread(database->thread());
qLog(Debug) << &*backend_ << "for device" << unique_id_ << "moved to thread" << app_->database()->thread(); qLog(Debug) << &*backend_ << "for device" << unique_id_ << "moved to thread" << database->thread();
if (url_.scheme() != "cdda"_L1) { if (url_.scheme() != "cdda"_L1) {
QObject::connect(&*backend_, &CollectionBackend::TotalSongCountUpdated, this, &ConnectedDevice::BackendTotalSongCountUpdated); QObject::connect(&*backend_, &CollectionBackend::TotalSongCountUpdated, this, &ConnectedDevice::BackendTotalSongCountUpdated);
} }
backend_->Init(app_->database(), backend_->Init(database,
app_->task_manager(), task_manager,
Song::Source::Device, Song::Source::Device,
QStringLiteral("device_%1_songs").arg(database_id), QStringLiteral("device_%1_songs").arg(database_id),
QStringLiteral("device_%1_directories").arg(database_id), QStringLiteral("device_%1_directories").arg(database_id),
QStringLiteral("device_%1_subdirectories").arg(database_id)); QStringLiteral("device_%1_subdirectories").arg(database_id));
// Create the model // Create the model
model_ = new CollectionModel(backend_, app_, this); model_ = new CollectionModel(backend_, album_cover_loader, this);
} }

View File

@ -34,11 +34,13 @@
#include "core/musicstorage.h" #include "core/musicstorage.h"
#include "core/song.h" #include "core/song.h"
class Application; class TaskManager;
class Database;
class CollectionBackend; class CollectionBackend;
class CollectionModel; class CollectionModel;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
class AlbumCoverLoader;
using std::enable_shared_from_this; using std::enable_shared_from_this;
@ -46,7 +48,7 @@ class ConnectedDevice : public QObject, public virtual MusicStorage, public enab
Q_OBJECT Q_OBJECT
public: public:
explicit ConnectedDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent = nullptr); explicit ConnectedDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent = nullptr);
Song::Source source() const override { return Song::Source::Device; } Song::Source source() const override { return Song::Source::Device; }
@ -81,13 +83,12 @@ class ConnectedDevice : public QObject, public virtual MusicStorage, public enab
void SongCountUpdated(const int count); void SongCountUpdated(const int count);
void DeviceConnectFinished(const QString &id, const bool success); void DeviceConnectFinished(const QString &id, const bool success);
void DeviceCloseFinished(const QString &id); void DeviceCloseFinished(const QString &id);
void AddError(const QString &error);
protected: protected:
void InitBackendDirectory(const QString &mount_point, const bool first_time, const bool rewrite_path = true); void InitBackendDirectory(const QString &mount_point, const bool first_time, const bool rewrite_path = true);
protected: protected:
Application *app_;
QUrl url_; QUrl url_;
bool first_time_; bool first_time_;
DeviceLister *lister_; DeviceLister *lister_;

View File

@ -48,7 +48,6 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/database.h" #include "core/database.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/musicstorage.h" #include "core/musicstorage.h"
@ -88,20 +87,20 @@ using std::make_unique;
const int DeviceManager::kDeviceIconSize = 32; const int DeviceManager::kDeviceIconSize = 32;
const int DeviceManager::kDeviceIconOverlaySize = 16; const int DeviceManager::kDeviceIconOverlaySize = 16;
DeviceManager::DeviceManager(Application *app, QObject *parent) DeviceManager::DeviceManager(SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, QObject *parent)
: SimpleTreeModel<DeviceInfo>(new DeviceInfo(this), parent), : SimpleTreeModel<DeviceInfo>(new DeviceInfo(this), parent),
app_(app), task_manager_(task_manager),
not_connected_overlay_(IconLoader::Load(u"edit-delete"_s)) { not_connected_overlay_(IconLoader::Load(u"edit-delete"_s)) {
setObjectName(QLatin1String(metaObject()->className())); setObjectName(QLatin1String(metaObject()->className()));
thread_pool_.setMaxThreadCount(1); thread_pool_.setMaxThreadCount(1);
QObject::connect(&*app_->task_manager(), &TaskManager::TasksChanged, this, &DeviceManager::TasksChanged); QObject::connect(&*task_manager, &TaskManager::TasksChanged, this, &DeviceManager::TasksChanged);
// Create the backend in the database thread // Create the backend in the database thread
backend_ = make_unique<DeviceDatabaseBackend>(); backend_ = make_unique<DeviceDatabaseBackend>();
backend_->moveToThread(app_->database()->thread()); backend_->moveToThread(database->thread());
backend_->Init(app_->database()); backend_->Init(database);
QObject::connect(this, &DeviceManager::DeviceCreatedFromDB, this, &DeviceManager::AddDeviceFromDB); QObject::connect(this, &DeviceManager::DeviceCreatedFromDB, this, &DeviceManager::AddDeviceFromDB);
@ -363,7 +362,7 @@ QVariant DeviceManager::data(const QModelIndex &idx, int role) const {
QString ret = info->device_->url().path(); QString ret = info->device_->url().path();
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
if (ret.startsWith('/')) ret.remove(0, 1); if (ret.startsWith(u'/')) ret.remove(0, 1);
#endif #endif
return QDir::toNativeSeparators(ret); return QDir::toNativeSeparators(ret);
} }
@ -627,7 +626,7 @@ SharedPtr<ConnectedDevice> DeviceManager::Connect(DeviceInfo *info) {
url_strings << url.toString(); url_strings << url.toString();
} }
app_->AddError(tr("This type of device is not supported: %1").arg(url_strings.join(", "_L1))); Q_EMIT AddError(tr("This type of device is not supported: %1").arg(url_strings.join(", "_L1)));
return ret; return ret;
} }
@ -636,8 +635,10 @@ SharedPtr<ConnectedDevice> DeviceManager::Connect(DeviceInfo *info) {
Q_ARG(QUrl, device_url), Q_ARG(QUrl, device_url),
Q_ARG(DeviceLister*, info->BestBackend()->lister_), Q_ARG(DeviceLister*, info->BestBackend()->lister_),
Q_ARG(QString, info->BestBackend()->unique_id_), Q_ARG(QString, info->BestBackend()->unique_id_),
Q_ARG(SharedPtr<DeviceManager>, app_->device_manager()), Q_ARG(SharedPtr<DeviceManager>, SharedPtr<DeviceManager>(this)),
Q_ARG(Application*, app_), Q_ARG(SharedPtr<TaskManager>, task_manager_),
Q_ARG(SharedPtr<Database>, database_),
Q_ARG(SharedPtr<AlbumCoverLoader>, album_cover_loader_),
Q_ARG(int, info->database_id_), Q_ARG(int, info->database_id_),
Q_ARG(bool, first_time)); Q_ARG(bool, first_time));
@ -842,7 +843,7 @@ void DeviceManager::DeviceTaskStarted(const int id) {
void DeviceManager::TasksChanged() { void DeviceManager::TasksChanged() {
const QList<TaskManager::Task> tasks = app_->task_manager()->GetTasks(); const QList<TaskManager::Task> tasks = task_manager_->GetTasks();
QList<QPersistentModelIndex> finished_tasks = active_tasks_.values(); QList<QPersistentModelIndex> finished_tasks = active_tasks_.values();
for (const TaskManager::Task &task : tasks) { for (const TaskManager::Task &task : tasks) {

View File

@ -49,7 +49,8 @@
class QModelIndex; class QModelIndex;
class QPersistentModelIndex; class QPersistentModelIndex;
class Application; class TaskManager;
class Database;
class ConnectedDevice; class ConnectedDevice;
class DeviceLister; class DeviceLister;
class DeviceStateFilterModel; class DeviceStateFilterModel;
@ -58,7 +59,7 @@ class DeviceManager : public SimpleTreeModel<DeviceInfo> {
Q_OBJECT Q_OBJECT
public: public:
explicit DeviceManager(Application *app, QObject *parent = nullptr); explicit DeviceManager(SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, QObject *parent = nullptr);
~DeviceManager() override; ~DeviceManager() override;
enum Role { enum Role {
@ -123,6 +124,7 @@ class DeviceManager : public SimpleTreeModel<DeviceInfo> {
void DeviceConnected(const QModelIndex idx); void DeviceConnected(const QModelIndex idx);
void DeviceDisconnected(const QModelIndex idx); void DeviceDisconnected(const QModelIndex idx);
void DeviceCreatedFromDB(DeviceInfo *info); void DeviceCreatedFromDB(DeviceInfo *info);
void AddError(const QString &error);
private Q_SLOTS: private Q_SLOTS:
void PhysicalDeviceAdded(const QString &id); void PhysicalDeviceAdded(const QString &id);
@ -152,7 +154,10 @@ class DeviceManager : public SimpleTreeModel<DeviceInfo> {
void CloseBackend(); void CloseBackend();
private: private:
Application *app_; SharedPtr<TaskManager> task_manager_;
SharedPtr<Database> database_;
SharedPtr<AlbumCoverLoader> album_cover_loader_;
ScopedPtr<DeviceDatabaseBackend> backend_; ScopedPtr<DeviceDatabaseBackend> backend_;
DeviceStateFilterModel *connected_devices_model_; DeviceStateFilterModel *connected_devices_model_;

View File

@ -48,9 +48,9 @@
#include <QMessageBox> #include <QMessageBox>
#include <QtEvents> #include <QtEvents>
#include "core/shared_ptr.h"
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/application.h"
#include "core/deletefiles.h" #include "core/deletefiles.h"
#include "core/mergedproxymodel.h" #include "core/mergedproxymodel.h"
#include "core/mimedata.h" #include "core/mimedata.h"
@ -61,8 +61,8 @@
#include "collection/collectiondirectorymodel.h" #include "collection/collectiondirectorymodel.h"
#include "collection/collectionmodel.h" #include "collection/collectionmodel.h"
#include "collection/collectionitemdelegate.h" #include "collection/collectionitemdelegate.h"
#include "connecteddevice.h"
#include "devicelister.h" #include "devicelister.h"
#include "connecteddevice.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "deviceproperties.h" #include "deviceproperties.h"
#include "deviceview.h" #include "deviceview.h"
@ -175,7 +175,6 @@ void DeviceItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
DeviceView::DeviceView(QWidget *parent) DeviceView::DeviceView(QWidget *parent)
: AutoExpandingTreeView(parent), : AutoExpandingTreeView(parent),
app_(nullptr),
merged_model_(nullptr), merged_model_(nullptr),
sort_model_(nullptr), sort_model_(nullptr),
properties_dialog_(new DeviceProperties), properties_dialog_(new DeviceProperties),
@ -202,16 +201,16 @@ DeviceView::DeviceView(QWidget *parent)
DeviceView::~DeviceView() = default; DeviceView::~DeviceView() = default;
void DeviceView::SetApplication(Application *app) { void DeviceView::Init(SharedPtr<TaskManager> task_manager, SharedPtr<DeviceManager> device_manager, CollectionDirectoryModel *collection_directory_model) {
Q_ASSERT(app_ == nullptr); task_manager_ = task_manager;
app_ = app; device_manager_ = device_manager;
QObject::connect(&*app_->device_manager(), &DeviceManager::DeviceConnected, this, &DeviceView::DeviceConnected); QObject::connect(&*device_manager_, &DeviceManager::DeviceConnected, this, &DeviceView::DeviceConnected);
QObject::connect(&*app_->device_manager(), &DeviceManager::DeviceDisconnected, this, &DeviceView::DeviceDisconnected); QObject::connect(&*device_manager_, &DeviceManager::DeviceDisconnected, this, &DeviceView::DeviceDisconnected);
sort_model_ = new QSortFilterProxyModel(this); sort_model_ = new QSortFilterProxyModel(this);
sort_model_->setSourceModel(&*app_->device_manager()); sort_model_->setSourceModel(&*device_manager_);
sort_model_->setDynamicSortFilter(true); sort_model_->setDynamicSortFilter(true);
sort_model_->setSortCaseSensitivity(Qt::CaseInsensitive); sort_model_->setSortCaseSensitivity(Qt::CaseInsensitive);
sort_model_->sort(0); sort_model_->sort(0);
@ -222,10 +221,10 @@ void DeviceView::SetApplication(Application *app) {
QObject::connect(merged_model_, &MergedProxyModel::SubModelReset, this, &AutoExpandingTreeView::RecursivelyExpandSlot); QObject::connect(merged_model_, &MergedProxyModel::SubModelReset, this, &AutoExpandingTreeView::RecursivelyExpandSlot);
properties_dialog_->SetDeviceManager(app_->device_manager()); properties_dialog_->SetDeviceManager(device_manager_);
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), nullptr, this); organize_dialog_ = make_unique<OrganizeDialog>(task_manager, nullptr, this);
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model()); organize_dialog_->SetDestinationModel(collection_directory_model);
} }
@ -257,8 +256,8 @@ void DeviceView::contextMenuEvent(QContextMenuEvent *e) {
const QModelIndex collection_index = MapToCollection(menu_index_); const QModelIndex collection_index = MapToCollection(menu_index_);
if (device_index.isValid()) { if (device_index.isValid()) {
const bool is_plugged_in = app_->device_manager()->GetLister(device_index); const bool is_plugged_in = device_manager_->GetLister(device_index);
const bool is_remembered = app_->device_manager()->GetDatabaseId(device_index) != -1; const bool is_remembered = device_manager_->GetDatabaseId(device_index) != -1;
forget_action_->setEnabled(is_remembered); forget_action_->setEnabled(is_remembered);
eject_action_->setEnabled(is_plugged_in); eject_action_->setEnabled(is_plugged_in);
@ -270,7 +269,7 @@ void DeviceView::contextMenuEvent(QContextMenuEvent *e) {
bool is_filesystem_device = false; bool is_filesystem_device = false;
if (parent_device_index.isValid()) { if (parent_device_index.isValid()) {
SharedPtr<ConnectedDevice> device = app_->device_manager()->GetConnectedDevice(parent_device_index); SharedPtr<ConnectedDevice> device = device_manager_->GetConnectedDevice(parent_device_index);
if (device && !device->LocalPath().isEmpty()) is_filesystem_device = true; if (device && !device->LocalPath().isEmpty()) is_filesystem_device = true;
} }
@ -309,14 +308,14 @@ QModelIndex DeviceView::MapToCollection(const QModelIndex &merged_model_index) c
void DeviceView::Connect() { void DeviceView::Connect() {
QModelIndex device_idx = MapToDevice(menu_index_); QModelIndex device_idx = MapToDevice(menu_index_);
app_->device_manager()->data(device_idx, MusicStorage::Role_StorageForceConnect); device_manager_->data(device_idx, MusicStorage::Role_StorageForceConnect);
} }
void DeviceView::DeviceConnected(const QModelIndex &idx) { void DeviceView::DeviceConnected(const QModelIndex &idx) {
if (!idx.isValid()) return; if (!idx.isValid()) return;
SharedPtr<ConnectedDevice> device = app_->device_manager()->GetConnectedDevice(idx); SharedPtr<ConnectedDevice> device = device_manager_->GetConnectedDevice(idx);
if (!device) return; if (!device) return;
QModelIndex sort_idx = sort_model_->mapFromSource(idx); QModelIndex sort_idx = sort_model_->mapFromSource(idx);
@ -341,8 +340,8 @@ void DeviceView::DeviceDisconnected(const QModelIndex &idx) {
void DeviceView::Forget() { void DeviceView::Forget() {
QModelIndex device_idx = MapToDevice(menu_index_); QModelIndex device_idx = MapToDevice(menu_index_);
QString unique_id = app_->device_manager()->data(device_idx, DeviceManager::Role_UniqueId).toString(); QString unique_id = device_manager_->data(device_idx, DeviceManager::Role_UniqueId).toString();
if (app_->device_manager()->GetLister(device_idx) && app_->device_manager()->GetLister(device_idx)->AskForScan(unique_id)) { if (device_manager_->GetLister(device_idx) && device_manager_->GetLister(device_idx)->AskForScan(unique_id)) {
ScopedPtr<QMessageBox> dialog(new QMessageBox( ScopedPtr<QMessageBox> dialog(new QMessageBox(
QMessageBox::Question, tr("Forget device"), QMessageBox::Question, tr("Forget device"),
tr("Forgetting a device will remove it from this list and Strawberry will have to rescan all the songs again next time you connect it."), tr("Forgetting a device will remove it from this list and Strawberry will have to rescan all the songs again next time you connect it."),
@ -353,7 +352,7 @@ void DeviceView::Forget() {
if (dialog->clickedButton() != forget) return; if (dialog->clickedButton() != forget) return;
} }
app_->device_manager()->Forget(device_idx); device_manager_->Forget(device_idx);
} }
@ -368,7 +367,7 @@ void DeviceView::mouseDoubleClickEvent(QMouseEvent *e) {
QModelIndex merged_index = indexAt(e->pos()); QModelIndex merged_index = indexAt(e->pos());
QModelIndex device_index = MapToDevice(merged_index); QModelIndex device_index = MapToDevice(merged_index);
if (device_index.isValid()) { if (device_index.isValid()) {
if (!app_->device_manager()->GetConnectedDevice(device_index)) { if (!device_manager_->GetConnectedDevice(device_index)) {
menu_index_ = merged_index; menu_index_ = merged_index;
Connect(); Connect();
} }
@ -433,7 +432,7 @@ void DeviceView::Delete() {
SharedPtr<MusicStorage> storage = device_index.data(MusicStorage::Role_Storage).value<SharedPtr<MusicStorage>>(); SharedPtr<MusicStorage> storage = device_index.data(MusicStorage::Role_Storage).value<SharedPtr<MusicStorage>>();
DeleteFiles *delete_files = new DeleteFiles(app_->task_manager(), storage, false); DeleteFiles *delete_files = new DeleteFiles(task_manager_, storage, false);
QObject::connect(delete_files, &DeleteFiles::Finished, this, &DeviceView::DeleteFinished); QObject::connect(delete_files, &DeleteFiles::Finished, this, &DeviceView::DeleteFinished);
delete_files->Start(GetSelectedSongs()); delete_files->Start(GetSelectedSongs());
@ -456,7 +455,7 @@ void DeviceView::Organize() {
void DeviceView::Unmount() { void DeviceView::Unmount() {
QModelIndex device_idx = MapToDevice(menu_index_); QModelIndex device_idx = MapToDevice(menu_index_);
app_->device_manager()->Unmount(device_idx); device_manager_->Unmount(device_idx);
} }
void DeviceView::DeleteFinished(const SongList &songs_with_errors) { void DeviceView::DeleteFinished(const SongList &songs_with_errors) {

View File

@ -31,6 +31,7 @@
#include <QString> #include <QString>
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/song.h" #include "core/song.h"
#include "collection/collectionitemdelegate.h" #include "collection/collectionitemdelegate.h"
#include "widgets/autoexpandingtreeview.h" #include "widgets/autoexpandingtreeview.h"
@ -43,8 +44,10 @@ class QAction;
class QMouseEvent; class QMouseEvent;
class QContextMenuEvent; class QContextMenuEvent;
class Application; class TaskManager;
class DeviceManager;
class DeviceProperties; class DeviceProperties;
class CollectionDirectoryModel;
class MergedProxyModel; class MergedProxyModel;
class OrganizeDialog; class OrganizeDialog;
@ -67,7 +70,7 @@ class DeviceView : public AutoExpandingTreeView {
explicit DeviceView(QWidget *parent = nullptr); explicit DeviceView(QWidget *parent = nullptr);
~DeviceView() override; ~DeviceView() override;
void SetApplication(Application *app); void Init(SharedPtr<TaskManager> task_manager, SharedPtr<DeviceManager> device_manager, CollectionDirectoryModel *collection_directory_model);
// AutoExpandingTreeView // AutoExpandingTreeView
bool CanRecursivelyExpand(const QModelIndex &idx) const override; bool CanRecursivelyExpand(const QModelIndex &idx) const override;
@ -102,7 +105,8 @@ class DeviceView : public AutoExpandingTreeView {
SongList GetSelectedSongs() const; SongList GetSelectedSongs() const;
private: private:
Application *app_; SharedPtr<TaskManager> task_manager_;
SharedPtr<DeviceManager> device_manager_;
MergedProxyModel *merged_model_; MergedProxyModel *merged_model_;
QSortFilterProxyModel *sort_model_; QSortFilterProxyModel *sort_model_;

View File

@ -27,21 +27,25 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/song.h" #include "core/song.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
#include "collection/collectionmodel.h" #include "collection/collectionmodel.h"
#include "collection/collectionwatcher.h" #include "collection/collectionwatcher.h"
#include "covermanager/albumcoverloader.h"
#include "connecteddevice.h" #include "connecteddevice.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "filesystemdevice.h" #include "filesystemdevice.h"
class DeviceLister; class DeviceLister;
FilesystemDevice::FilesystemDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent) FilesystemDevice::FilesystemDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent)
: FilesystemMusicStorage(Song::Source::Device, url.toLocalFile()), : FilesystemMusicStorage(Song::Source::Device, url.toLocalFile()),
ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, parent), ConnectedDevice(url, lister, unique_id, manager, task_manager, database, album_cover_loader, database_id, first_time, parent),
watcher_(new CollectionWatcher(Song::Source::Device)), watcher_(new CollectionWatcher(Song::Source::Device)),
watcher_thread_(new QThread(this)) { watcher_thread_(new QThread(this)) {
@ -51,7 +55,7 @@ FilesystemDevice::FilesystemDevice(const QUrl &url, DeviceLister *lister, const
watcher_->set_device_name(manager->DeviceNameByID(unique_id)); watcher_->set_device_name(manager->DeviceNameByID(unique_id));
watcher_->set_backend(backend_); watcher_->set_backend(backend_);
watcher_->set_task_manager(app_->task_manager()); watcher_->set_task_manager(task_manager);
QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory); QObject::connect(&*backend_, &CollectionBackend::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory);
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, watcher_, &CollectionWatcher::RemoveDirectory); QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, watcher_, &CollectionWatcher::RemoveDirectory);

View File

@ -35,16 +35,18 @@
#include "connecteddevice.h" #include "connecteddevice.h"
class QThread; class QThread;
class Application; class TaskManager;
class Database;
class CollectionWatcher; class CollectionWatcher;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
class AlbumCoverLoader;
class FilesystemDevice : public ConnectedDevice, public virtual FilesystemMusicStorage { class FilesystemDevice : public ConnectedDevice, public virtual FilesystemMusicStorage {
Q_OBJECT Q_OBJECT
public: public:
Q_INVOKABLE FilesystemDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent = nullptr); Q_INVOKABLE FilesystemDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent = nullptr);
~FilesystemDevice() override; ~FilesystemDevice() override;
Song::Source source() const final { return Song::Source::Device; } Song::Source source() const final { return Song::Source::Device; }

View File

@ -40,10 +40,12 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/temporaryfile.h" #include "core/temporaryfile.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
#include "collection/collectionmodel.h" #include "collection/collectionmodel.h"
#include "covermanager/albumcoverloader.h"
#include "connecteddevice.h" #include "connecteddevice.h"
#include "gpoddevice.h" #include "gpoddevice.h"
#include "gpodloader.h" #include "gpodloader.h"
@ -54,8 +56,9 @@ class DeviceManager;
using std::make_shared; using std::make_shared;
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
GPodDevice::GPodDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent) GPodDevice::GPodDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent)
: ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, parent), : ConnectedDevice(url, lister, unique_id, manager, task_manager, database, album_cover_loader, database_id, first_time, parent),
task_manager_(task_manager),
loader_(nullptr), loader_(nullptr),
loader_thread_(nullptr), loader_thread_(nullptr),
db_(nullptr), db_(nullptr),
@ -66,7 +69,7 @@ bool GPodDevice::Init() {
InitBackendDirectory(url_.path(), first_time_); InitBackendDirectory(url_.path(), first_time_);
model_->Init(); model_->Init();
loader_ = new GPodLoader(url_.path(), app_->task_manager(), backend_, shared_from_this()); loader_ = new GPodLoader(url_.path(), task_manager_, backend_, shared_from_this());
loader_thread_ = new QThread(); loader_thread_ = new QThread();
loader_->moveToThread(loader_thread_); loader_->moveToThread(loader_thread_);
@ -135,7 +138,9 @@ void GPodDevice::LoadFinished(Itdb_iTunesDB *db, const bool success) {
} }
void GPodDevice::LoaderError(const QString &message) { app_->AddError(message); } void GPodDevice::LoaderError(const QString &message) {
Q_EMIT AddError(message);
}
void GPodDevice::Start() { void GPodDevice::Start() {
@ -240,7 +245,7 @@ bool GPodDevice::CopyToStorage(const CopyJob &job, QString &error_text) {
error_text = tr("Could not copy %1 to %2: %3").arg(job.metadata_.url().toLocalFile(), url_.path(), QString::fromUtf8(error->message)); error_text = tr("Could not copy %1 to %2: %3").arg(job.metadata_.url().toLocalFile(), url_.path(), QString::fromUtf8(error->message));
g_error_free(error); g_error_free(error);
qLog(Error) << error_text; qLog(Error) << error_text;
app_->AddError(error_text); Q_EMIT AddError(error_text);
// Need to remove the track from the db again // Need to remove the track from the db again
itdb_track_remove(track); itdb_track_remove(track);
@ -286,7 +291,7 @@ bool GPodDevice::WriteDatabase(QString &error_text) {
else { else {
error_text = tr("Writing database failed."); error_text = tr("Writing database failed.");
} }
app_->AddError(error_text); Q_EMIT AddError(error_text);
} }
return success; return success;

View File

@ -42,7 +42,6 @@
#include "gpodloader.h" #include "gpodloader.h"
class QThread; class QThread;
class Application;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
@ -50,7 +49,7 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
Q_OBJECT Q_OBJECT
public: public:
Q_INVOKABLE GPodDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent = nullptr); Q_INVOKABLE GPodDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent = nullptr);
~GPodDevice() override; ~GPodDevice() override;
bool Init() override; bool Init() override;
@ -86,6 +85,7 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
bool WriteDatabase(QString &error_text); bool WriteDatabase(QString &error_text);
protected: protected:
SharedPtr <TaskManager> task_manager_;
GPodLoader *loader_; GPodLoader *loader_;
QThread *loader_thread_; QThread *loader_thread_;

View File

@ -35,7 +35,6 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/musicstorage.h" #include "core/musicstorage.h"
#include "collection/collectionmodel.h" #include "collection/collectionmodel.h"
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
@ -46,13 +45,17 @@
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
class TaskManager;
class Database;
class AlbumCoverLoader;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
bool MtpDevice::sInitializedLibMTP = false; bool MtpDevice::sInitializedLibMTP = false;
MtpDevice::MtpDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent) MtpDevice::MtpDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent)
: ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, parent), : ConnectedDevice(url, lister, unique_id, manager, task_manager, database, album_cover_loader, database_id, first_time, parent),
task_manager_(task_manager),
loader_(nullptr), loader_(nullptr),
loader_thread_(nullptr), loader_thread_(nullptr),
closing_(false) { closing_(false) {
@ -81,7 +84,7 @@ bool MtpDevice::Init() {
InitBackendDirectory(u"/"_s, first_time_, false); InitBackendDirectory(u"/"_s, first_time_, false);
model_->Init(); model_->Init();
loader_ = new MtpLoader(url_, app_->task_manager(), backend_); loader_ = new MtpLoader(url_, task_manager_, backend_);
loader_thread_ = new QThread(); loader_thread_ = new QThread();
loader_->moveToThread(loader_thread_); loader_->moveToThread(loader_thread_);
@ -132,7 +135,7 @@ void MtpDevice::LoadFinished(const bool success, MtpConnection *connection) {
} }
void MtpDevice::LoaderError(const QString &message) { void MtpDevice::LoaderError(const QString &message) {
app_->AddError(message); Q_EMIT AddError(message);
} }
bool MtpDevice::StartCopy(QList<Song::FileType> *supported_types) { bool MtpDevice::StartCopy(QList<Song::FileType> *supported_types) {

View File

@ -37,7 +37,9 @@
#include "connecteddevice.h" #include "connecteddevice.h"
class QThread; class QThread;
class Application; class TaskManager;
class Database;
class AlbumCoverLoader;
class DeviceLister; class DeviceLister;
class DeviceManager; class DeviceManager;
class MtpLoader; class MtpLoader;
@ -48,7 +50,7 @@ class MtpDevice : public ConnectedDevice {
Q_OBJECT Q_OBJECT
public: public:
Q_INVOKABLE MtpDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, Application *app, const int database_id, const bool first_time, QObject *parent = nullptr); Q_INVOKABLE MtpDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, SharedPtr<DeviceManager> manager, SharedPtr<TaskManager> task_manager, SharedPtr<Database> database, SharedPtr<AlbumCoverLoader> album_cover_loader, const int database_id, const bool first_time, QObject *parent = nullptr);
~MtpDevice() override; ~MtpDevice() override;
static QStringList url_schemes() { return QStringList() << QStringLiteral("mtp"); } static QStringList url_schemes() { return QStringList() << QStringLiteral("mtp"); }
@ -82,6 +84,8 @@ class MtpDevice : public ConnectedDevice {
private: private:
static bool sInitializedLibMTP; static bool sInitializedLibMTP;
SharedPtr<TaskManager> task_manager_;
MtpLoader *loader_; MtpLoader *loader_;
QThread *loader_thread_; QThread *loader_thread_;
bool closing_; bool closing_;

View File

@ -36,13 +36,14 @@
#include <QTextBrowser> #include <QTextBrowser>
#include "console.h" #include "console.h"
#include "core/shared_ptr.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/application.h"
#include "core/database.h" #include "core/database.h"
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
Console::Console(Application *app, QWidget *parent) : QDialog(parent), ui_{}, app_(app) { Console::Console(SharedPtr<Database> database, QWidget *parent) : QDialog(parent), ui_{}, database_(database) {
ui_.setupUi(this); ui_.setupUi(this);
@ -60,7 +61,7 @@ Console::Console(Application *app, QWidget *parent) : QDialog(parent), ui_{}, ap
void Console::RunQuery() { void Console::RunQuery() {
QSqlDatabase db = app_->database()->Connect(); QSqlDatabase db = database_->Connect();
QSqlQuery query(db); QSqlQuery query(db);
if (!query.prepare(ui_.query->text())) { if (!query.prepare(ui_.query->text())) {
qLog(Error) << query.lastError(); qLog(Error) << query.lastError();

View File

@ -31,20 +31,22 @@
#include "ui_console.h" #include "ui_console.h"
class Application; #include "core/shared_ptr.h"
class Database;
class Console : public QDialog { class Console : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit Console(Application *app, QWidget *parent = nullptr); explicit Console(SharedPtr<Database> database, QWidget *parent = nullptr);
private Q_SLOTS: private Q_SLOTS:
void RunQuery(); void RunQuery();
private: private:
Ui::Console ui_; Ui::Console ui_;
Application *app_; SharedPtr<Database> database_;
}; };
#endif // CONSOLE_H #endif // CONSOLE_H

View File

@ -70,7 +70,6 @@
#include <QSettings> #include <QSettings>
#include <QMimeData> #include <QMimeData>
#include "core/application.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/settings.h" #include "core/settings.h"
@ -110,16 +109,25 @@ constexpr int kSmallImageSize = 128;
const char EditTagDialog::kTagsDifferentHintText[] = QT_TR_NOOP("(different across multiple songs)"); const char EditTagDialog::kTagsDifferentHintText[] = QT_TR_NOOP("(different across multiple songs)");
const char EditTagDialog::kArtDifferentHintText[] = QT_TR_NOOP("Different art across multiple songs."); const char EditTagDialog::kArtDifferentHintText[] = QT_TR_NOOP("Different art across multiple songs.");
EditTagDialog::EditTagDialog(Application *app, QWidget *parent) EditTagDialog::EditTagDialog(SharedPtr<NetworkAccessManager> network,
SharedPtr<CollectionBackend> collection_backend,
SharedPtr<AlbumCoverLoader> albumcover_loader,
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
SharedPtr<CoverProviders> cover_providers,
SharedPtr<LyricsProviders> lyrics_providers,
QWidget *parent)
: QDialog(parent), : QDialog(parent),
ui_(new Ui_EditTagDialog), ui_(new Ui_EditTagDialog),
app_(app), collection_backend_(collection_backend),
album_cover_loader_(albumcover_loader),
current_albumcover_loader_(current_albumcover_loader),
cover_providers_(cover_providers),
album_cover_choice_controller_(new AlbumCoverChoiceController(this)), album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
#ifdef HAVE_MUSICBRAINZ #ifdef HAVE_MUSICBRAINZ
tag_fetcher_(new TagFetcher(app->network(), this)), tag_fetcher_(new TagFetcher(network, this)),
results_dialog_(new TrackSelectionDialog(this)), results_dialog_(new TrackSelectionDialog(this)),
#endif #endif
lyrics_fetcher_(new LyricsFetcher(app->lyrics_providers(), this)), lyrics_fetcher_(new LyricsFetcher(lyrics_providers, this)),
cover_menu_(new QMenu(this)), cover_menu_(new QMenu(this)),
image_no_cover_thumbnail_(ImageUtils::GenerateNoCoverImage(QSize(128, 128), devicePixelRatioF())), image_no_cover_thumbnail_(ImageUtils::GenerateNoCoverImage(QSize(128, 128), devicePixelRatioF())),
loading_(false), loading_(false),
@ -130,7 +138,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
save_tag_pending_(0), save_tag_pending_(0),
lyrics_id_(-1) { lyrics_id_(-1) {
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &EditTagDialog::AlbumCoverLoaded); QObject::connect(&*album_cover_loader_, &AlbumCoverLoader::AlbumCoverLoaded, this, &EditTagDialog::AlbumCoverLoaded);
#ifdef HAVE_MUSICBRAINZ #ifdef HAVE_MUSICBRAINZ
QObject::connect(tag_fetcher_, &TagFetcher::ResultAvailable, results_dialog_, &TrackSelectionDialog::FetchTagFinished, Qt::QueuedConnection); QObject::connect(tag_fetcher_, &TagFetcher::ResultAvailable, results_dialog_, &TrackSelectionDialog::FetchTagFinished, Qt::QueuedConnection);
@ -140,7 +148,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
#endif #endif
QObject::connect(lyrics_fetcher_, &LyricsFetcher::LyricsFetched, this, &EditTagDialog::UpdateLyrics); QObject::connect(lyrics_fetcher_, &LyricsFetcher::LyricsFetched, this, &EditTagDialog::UpdateLyrics);
album_cover_choice_controller_->Init(app_); //album_cover_choice_controller_->Init(app_);
ui_->setupUi(this); ui_->setupUi(this);
ui_->splitter->setSizes(QList<int>() << 200 << width() - 200); ui_->splitter->setSizes(QList<int>() << 200 << width() - 200);
@ -259,13 +267,13 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
QKeySequence(QKeySequence::Forward).toString(QKeySequence::NativeText), QKeySequence(QKeySequence::Forward).toString(QKeySequence::NativeText),
QKeySequence(QKeySequence::MoveToNextPage).toString(QKeySequence::NativeText))); QKeySequence(QKeySequence::MoveToNextPage).toString(QKeySequence::NativeText)));
new TagCompleter(app_->collection_backend(), Playlist::Column::Artist, ui_->artist); new TagCompleter(collection_backend, Playlist::Column::Artist, ui_->artist);
new TagCompleter(app_->collection_backend(), Playlist::Column::Album, ui_->album); new TagCompleter(collection_backend, Playlist::Column::Album, ui_->album);
new TagCompleter(app_->collection_backend(), Playlist::Column::AlbumArtist, ui_->albumartist); new TagCompleter(collection_backend, Playlist::Column::AlbumArtist, ui_->albumartist);
new TagCompleter(app_->collection_backend(), Playlist::Column::Genre, ui_->genre); new TagCompleter(collection_backend, Playlist::Column::Genre, ui_->genre);
new TagCompleter(app_->collection_backend(), Playlist::Column::Composer, ui_->composer); new TagCompleter(collection_backend, Playlist::Column::Composer, ui_->composer);
new TagCompleter(app_->collection_backend(), Playlist::Column::Performer, ui_->performer); new TagCompleter(collection_backend, Playlist::Column::Performer, ui_->performer);
new TagCompleter(app_->collection_backend(), Playlist::Column::Grouping, ui_->grouping); new TagCompleter(collection_backend, Playlist::Column::Grouping, ui_->grouping);
} }
@ -725,7 +733,7 @@ void EditTagDialog::SelectionChanged() {
album_cover_choice_controller_->cover_to_file_action()->setEnabled(first_song.has_valid_art() && !first_song.art_unset()); album_cover_choice_controller_->cover_to_file_action()->setEnabled(first_song.has_valid_art() && !first_song.art_unset());
album_cover_choice_controller_->cover_from_file_action()->setEnabled(enable_change_art); album_cover_choice_controller_->cover_from_file_action()->setEnabled(enable_change_art);
album_cover_choice_controller_->cover_from_url_action()->setEnabled(enable_change_art); album_cover_choice_controller_->cover_from_url_action()->setEnabled(enable_change_art);
album_cover_choice_controller_->search_for_cover_action()->setEnabled(app_->cover_providers()->HasAnyProviders() && enable_change_art); album_cover_choice_controller_->search_for_cover_action()->setEnabled(cover_providers_->HasAnyProviders() && enable_change_art);
album_cover_choice_controller_->unset_cover_action()->setEnabled(enable_change_art && !first_song.art_unset()); album_cover_choice_controller_->unset_cover_action()->setEnabled(enable_change_art && !first_song.art_unset());
album_cover_choice_controller_->clear_cover_action()->setEnabled(enable_change_art && (!first_song.art_manual().isEmpty() || first_song.art_unset())); album_cover_choice_controller_->clear_cover_action()->setEnabled(enable_change_art && (!first_song.art_manual().isEmpty() || first_song.art_unset()));
album_cover_choice_controller_->delete_cover_action()->setEnabled(enable_change_art && (first_song.art_embedded() || !first_song.art_automatic().isEmpty() || !first_song.art_manual().isEmpty())); album_cover_choice_controller_->delete_cover_action()->setEnabled(enable_change_art && (first_song.art_embedded() || !first_song.art_automatic().isEmpty() || !first_song.art_manual().isEmpty()));
@ -734,10 +742,10 @@ void EditTagDialog::SelectionChanged() {
cover_options.desired_scaled_size = QSize(kSmallImageSize, kSmallImageSize); cover_options.desired_scaled_size = QSize(kSmallImageSize, kSmallImageSize);
cover_options.device_pixel_ratio = devicePixelRatioF(); cover_options.device_pixel_ratio = devicePixelRatioF();
if (data_.value(indexes.first().row()).cover_action_ == UpdateCoverAction::None) { if (data_.value(indexes.first().row()).cover_action_ == UpdateCoverAction::None) {
tags_cover_art_id_ = app_->album_cover_loader()->LoadImageAsync(cover_options, first_song); tags_cover_art_id_ = album_cover_loader_->LoadImageAsync(cover_options, first_song);
} }
else { else {
tags_cover_art_id_ = app_->album_cover_loader()->LoadImageAsync(cover_options, data_[indexes.first().row()].cover_result_); tags_cover_art_id_ = album_cover_loader_->LoadImageAsync(cover_options, data_[indexes.first().row()].cover_result_);
} }
} }
@ -788,7 +796,7 @@ void EditTagDialog::UpdateSummaryTab(const Song &song) {
cover_options.types = cover_types_; cover_options.types = cover_types_;
cover_options.desired_scaled_size = QSize(kSmallImageSize, kSmallImageSize); cover_options.desired_scaled_size = QSize(kSmallImageSize, kSmallImageSize);
cover_options.device_pixel_ratio = devicePixelRatioF(); cover_options.device_pixel_ratio = devicePixelRatioF();
summary_cover_art_id_ = app_->album_cover_loader()->LoadImageAsync(cover_options, song); summary_cover_art_id_ = album_cover_loader_->LoadImageAsync(cover_options, song);
ui_->summary->setText(u"<p><b>"_s + song.PrettyTitleWithArtist().toHtmlEscaped() + u"</b></p>"_s); ui_->summary->setText(u"<p><b>"_s + song.PrettyTitleWithArtist().toHtmlEscaped() + u"</b></p>"_s);
@ -1307,8 +1315,8 @@ void EditTagDialog::SaveData() {
if (ref.current_.is_collection_song()) { if (ref.current_.is_collection_song()) {
collection_songs_.insert(ref.current_.id(), ref.current_); collection_songs_.insert(ref.current_.id(), ref.current_);
} }
if (ref.current_ == app_->current_albumcover_loader()->last_song()) { if (ref.current_ == current_albumcover_loader_->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(ref.current_); current_albumcover_loader_->LoadAlbumCover(ref.current_);
} }
} }
@ -1321,7 +1329,7 @@ void EditTagDialog::SaveData() {
void EditTagDialog::SaveDataFinished() { void EditTagDialog::SaveDataFinished() {
if (!collection_songs_.isEmpty()) { if (!collection_songs_.isEmpty()) {
app_->collection_backend()->AddOrUpdateSongsAsync(collection_songs_.values()); collection_backend_->AddOrUpdateSongsAsync(collection_songs_.values());
collection_songs_.clear(); collection_songs_.clear();
} }
@ -1483,8 +1491,8 @@ void EditTagDialog::SongSaveTagsComplete(TagReaderReplyPtr reply, const QString
} }
collection_songs_.insert(song.id(), song); collection_songs_.insert(song.id(), song);
} }
if (cover_action != UpdateCoverAction::None && song == app_->current_albumcover_loader()->last_song()) { if (cover_action != UpdateCoverAction::None && song == current_albumcover_loader_->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(song); current_albumcover_loader_->LoadAlbumCover(song);
} }
} }
else { else {

View File

@ -51,7 +51,12 @@ class QEvent;
class QShowEvent; class QShowEvent;
class QHideEvent; class QHideEvent;
class Application; class NetworkAccessManager;
class CollectionBackend;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class LyricsProviders;
class AlbumCoverChoiceController; class AlbumCoverChoiceController;
class Ui_EditTagDialog; class Ui_EditTagDialog;
#ifdef HAVE_MUSICBRAINZ #ifdef HAVE_MUSICBRAINZ
@ -64,7 +69,13 @@ class EditTagDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit EditTagDialog(Application *app, QWidget *parent = nullptr); explicit EditTagDialog(SharedPtr<NetworkAccessManager> network,
SharedPtr<CollectionBackend> collection_backend,
SharedPtr<AlbumCoverLoader> albumcover_loader,
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader,
SharedPtr<CoverProviders> cover_providers,
SharedPtr<LyricsProviders> lyrics_providers,
QWidget *parent = nullptr);
~EditTagDialog() override; ~EditTagDialog() override;
void SetSongs(const SongList &songs, const PlaylistItemPtrList &items = PlaylistItemPtrList()); void SetSongs(const SongList &songs, const PlaylistItemPtrList &items = PlaylistItemPtrList());
@ -180,7 +191,11 @@ class EditTagDialog : public QDialog {
Ui_EditTagDialog *ui_; Ui_EditTagDialog *ui_;
Application *app_; SharedPtr<CollectionBackend> collection_backend_;
SharedPtr<AlbumCoverLoader> album_cover_loader_;
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
SharedPtr<CoverProviders> cover_providers_;
AlbumCoverChoiceController *album_cover_choice_controller_; AlbumCoverChoiceController *album_cover_choice_controller_;
#ifdef HAVE_MUSICBRAINZ #ifdef HAVE_MUSICBRAINZ
TagFetcher *tag_fetcher_; TagFetcher *tag_fetcher_;

View File

@ -19,7 +19,7 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/mainwindow.h" #include "application/mainwindow.h"
#include "utilities/screenutils.h" #include "utilities/screenutils.h"
#include "snapdialog.h" #include "snapdialog.h"

View File

@ -31,7 +31,7 @@
#include <QSettings> #include <QSettings>
#include "utilities/envutils.h" #include "utilities/envutils.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "core/networkproxyfactory.h" #include "core/networkproxyfactory.h"
#include "core/settings.h" #include "core/settings.h"
#include "enginebase.h" #include "enginebase.h"

View File

@ -54,7 +54,7 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/taskmanager.h" #include "core/taskmanager.h"
#include "core/signalchecker.h" #include "core/signalchecker.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "enginebase.h" #include "enginebase.h"
#include "gstengine.h" #include "gstengine.h"
#include "gstenginepipeline.h" #include "gstenginepipeline.h"

View File

@ -61,7 +61,7 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/signalchecker.h" #include "core/signalchecker.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "settings/backendsettingspage.h" #include "settings/backendsettingspage.h"
#include "gstengine.h" #include "gstengine.h"
#include "gstenginepipeline.h" #include "gstenginepipeline.h"

View File

@ -87,11 +87,11 @@
#ifdef HAVE_MPRIS2 #ifdef HAVE_MPRIS2
# include "mpris2/mpris2.h" # include "mpris2/mpris2.h"
#endif #endif
#include "core/metatypes.h" #include "application/metatypes.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "core/mainwindow.h" #include "application/mainwindow.h"
#include "core/commandlineoptions.h" #include "core/commandlineoptions.h"
#include "core/application.h" #include "application/application.h"
#include "core/networkproxyfactory.h" #include "core/networkproxyfactory.h"
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
# include "core/macsystemtrayicon.h" # include "core/macsystemtrayicon.h"
@ -99,7 +99,7 @@
# include "core/qtsystemtrayicon.h" # include "core/qtsystemtrayicon.h"
#endif #endif
#ifdef HAVE_TRANSLATIONS #ifdef HAVE_TRANSLATIONS
# include "core/translations.h" # include "translations/translations.h"
#endif #endif
#include "settings/behavioursettingspage.h" #include "settings/behavioursettingspage.h"
#include "settings/appearancesettingspage.h" #include "settings/appearancesettingspage.h"
@ -307,7 +307,7 @@ int main(int argc, char *argv[]) {
#endif #endif
#ifdef HAVE_MPRIS2 #ifdef HAVE_MPRIS2
mpris::Mpris2 mpris2(&app); mpris::Mpris2 mpris2(app.player(), app.playlist_manager(), app.current_albumcover_loader());
#endif #endif
// Window // Window

View File

@ -23,26 +23,22 @@
#include <QByteArray> #include <QByteArray>
#include <QUrl> #include <QUrl>
#include "core/application.h"
#include "core/player.h"
#include "core/song.h" #include "core/song.h"
#include "core/settings.h" #include "core/settings.h"
#include "player/player.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "settings/moodbarsettingspage.h" #include "settings/moodbarsettingspage.h"
#include "playlist/playlistmanager.h"
#include "moodbarcontroller.h" #include "moodbarcontroller.h"
#include "moodbarloader.h" #include "moodbarloader.h"
#include "moodbarpipeline.h" #include "moodbarpipeline.h"
MoodbarController::MoodbarController(Application *app, QObject *parent) MoodbarController::MoodbarController(SharedPtr<Player> player, SharedPtr<MoodbarLoader> moodbar_loader, QObject *parent)
: QObject(parent), : QObject(parent),
app_(app), player_(player),
moodbar_loader_(moodbar_loader),
enabled_(false) { enabled_(false) {
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &MoodbarController::CurrentSongChanged);
QObject::connect(&*app_->player(), &Player::Stopped, this, &MoodbarController::PlaybackStopped);
ReloadSettings(); ReloadSettings();
} }
@ -62,7 +58,7 @@ void MoodbarController::CurrentSongChanged(const Song &song) {
QByteArray data; QByteArray data;
MoodbarPipeline *pipeline = nullptr; MoodbarPipeline *pipeline = nullptr;
const MoodbarLoader::Result result = app_->moodbar_loader()->Load(song.url(), song.has_cue(), &data, &pipeline); const MoodbarLoader::Result result = moodbar_loader_->Load(song.url(), song.has_cue(), &data, &pipeline);
switch (result) { switch (result) {
case MoodbarLoader::Result::CannotLoad: case MoodbarLoader::Result::CannotLoad:
@ -95,12 +91,12 @@ void MoodbarController::PlaybackStopped() {
void MoodbarController::AsyncLoadComplete(MoodbarPipeline *pipeline, const QUrl &url) { void MoodbarController::AsyncLoadComplete(MoodbarPipeline *pipeline, const QUrl &url) {
// Is this song still playing? // Is this song still playing?
PlaylistItemPtr current_item = app_->player()->GetCurrentItem(); PlaylistItemPtr current_item = player_->GetCurrentItem();
if (current_item && current_item->Url() != url) { if (current_item && current_item->Url() != url) {
return; return;
} }
// Did we stop the song? // Did we stop the song?
switch (app_->player()->GetState()) { switch (player_->GetState()) {
case EngineBase::State::Error: case EngineBase::State::Error:
case EngineBase::State::Empty: case EngineBase::State::Empty:
case EngineBase::State::Idle: case EngineBase::State::Idle:

View File

@ -27,28 +27,34 @@
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
class Application; #include "core/shared_ptr.h"
class MoodbarLoader;
class MoodbarPipeline; class MoodbarPipeline;
class Song; class Song;
class Player;
class MoodbarController : public QObject { class MoodbarController : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit MoodbarController(Application *app, QObject *parent = nullptr); explicit MoodbarController(SharedPtr<Player> player, SharedPtr<MoodbarLoader> moodbar_loader, QObject *parent = nullptr);
void ReloadSettings(); void ReloadSettings();
Q_SIGNALS: Q_SIGNALS:
void CurrentMoodbarDataChanged(const QByteArray &data); void CurrentMoodbarDataChanged(const QByteArray &data);
private Q_SLOTS: public Q_SLOTS:
void CurrentSongChanged(const Song &song); void CurrentSongChanged(const Song &song);
void PlaybackStopped(); void PlaybackStopped();
private Q_SLOTS:
void AsyncLoadComplete(MoodbarPipeline *pipeline, const QUrl &url); void AsyncLoadComplete(MoodbarPipeline *pipeline, const QUrl &url);
private: private:
Application *app_; SharedPtr<Player> player_;
SharedPtr<MoodbarLoader> moodbar_loader_;
bool enabled_; bool enabled_;
}; };

View File

@ -36,7 +36,6 @@
#include <QPainter> #include <QPainter>
#include <QRect> #include <QRect>
#include "core/application.h"
#include "core/settings.h" #include "core/settings.h"
#include "playlist/playlist.h" #include "playlist/playlist.h"
#include "playlist/playlistview.h" #include "playlist/playlistview.h"
@ -51,14 +50,15 @@
MoodbarItemDelegate::Data::Data() : state_(State::None) {} MoodbarItemDelegate::Data::Data() : state_(State::None) {}
MoodbarItemDelegate::MoodbarItemDelegate(Application *app, PlaylistView *view, QObject *parent) MoodbarItemDelegate::MoodbarItemDelegate(SharedPtr<MoodbarLoader> moodbar_loader, PlaylistView *playlist_view, QObject *parent)
: QItemDelegate(parent), : QItemDelegate(parent),
app_(app), moodbar_loader_(moodbar_loader),
view_(view), playlist_view_(playlist_view),
enabled_(false), enabled_(false),
style_(MoodbarRenderer::MoodbarStyle::Normal) { style_(MoodbarRenderer::MoodbarStyle::Normal) {
QObject::connect(app_, &Application::SettingsChanged, this, &MoodbarItemDelegate::ReloadSettings); QObject::connect(&*moodbar_loader, &MoodbarLoader::SettingsReloaded, this, &MoodbarItemDelegate::ReloadSettings);
ReloadSettings(); ReloadSettings();
} }
@ -151,7 +151,7 @@ void MoodbarItemDelegate::StartLoadingData(const QUrl &url, const bool has_cue,
// Load a mood file for this song and generate some colors from it // Load a mood file for this song and generate some colors from it
QByteArray bytes; QByteArray bytes;
MoodbarPipeline *pipeline = nullptr; MoodbarPipeline *pipeline = nullptr;
switch (app_->moodbar_loader()->Load(url, has_cue, &bytes, &pipeline)) { switch (moodbar_loader_->Load(url, has_cue, &bytes, &pipeline)) {
case MoodbarLoader::Result::CannotLoad: case MoodbarLoader::Result::CannotLoad:
data->state_ = Data::State::CannotLoad; data->state_ = Data::State::CannotLoad;
break; break;
@ -278,7 +278,7 @@ void MoodbarItemDelegate::ImageLoaded(const QUrl &url, const QImage &image) {
data->pixmap_ = QPixmap::fromImage(image); data->pixmap_ = QPixmap::fromImage(image);
data->state_ = Data::State::Loaded; data->state_ = Data::State::Loaded;
Playlist *playlist = view_->playlist(); Playlist *playlist = playlist_view_->playlist();
const PlaylistFilter *filter = playlist->filter(); const PlaylistFilter *filter = playlist->filter();
// Update all the indices with the new pixmap. // Update all the indices with the new pixmap.

View File

@ -36,10 +36,10 @@
#include <QSize> #include <QSize>
#include <QStyleOption> #include <QStyleOption>
#include "core/shared_ptr.h"
class QPainter; class QPainter;
class QModelIndex; class MoodbarLoader;
class QPersistentModelIndex;
class Application;
class MoodbarPipeline; class MoodbarPipeline;
class PlaylistView; class PlaylistView;
@ -47,7 +47,7 @@ class MoodbarItemDelegate : public QItemDelegate {
Q_OBJECT Q_OBJECT
public: public:
explicit MoodbarItemDelegate(Application *app, PlaylistView *view, QObject *parent = nullptr); explicit MoodbarItemDelegate(SharedPtr<MoodbarLoader> moodbar_loader, PlaylistView *view, QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const override; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const override;
@ -90,8 +90,8 @@ class MoodbarItemDelegate : public QItemDelegate {
void ReloadAllColors(); void ReloadAllColors();
private: private:
Application *app_; SharedPtr<MoodbarLoader> moodbar_loader_;
PlaylistView *view_; PlaylistView *playlist_view_;
QCache<QUrl, Data> data_; QCache<QUrl, Data> data_;
bool enabled_; bool enabled_;

View File

@ -43,7 +43,6 @@
#include "core/logging.h" #include "core/logging.h"
#include "core/scoped_ptr.h" #include "core/scoped_ptr.h"
#include "core/application.h"
#include "core/settings.h" #include "core/settings.h"
#include "moodbarpipeline.h" #include "moodbarpipeline.h"
@ -57,7 +56,7 @@ using namespace Qt::Literals::StringLiterals;
# include <windows.h> # include <windows.h>
#endif #endif
MoodbarLoader::MoodbarLoader(Application *app, QObject *parent) MoodbarLoader::MoodbarLoader(QObject *parent)
: QObject(parent), : QObject(parent),
cache_(new QNetworkDiskCache(this)), cache_(new QNetworkDiskCache(this)),
thread_(new QThread(this)), thread_(new QThread(this)),
@ -67,7 +66,6 @@ MoodbarLoader::MoodbarLoader(Application *app, QObject *parent)
cache_->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u"/moodbar"_s); cache_->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u"/moodbar"_s);
cache_->setMaximumCacheSize(60LL * 1024LL * 1024LL); // 60MB - enough for 20,000 moodbars cache_->setMaximumCacheSize(60LL * 1024LL * 1024LL); // 60MB - enough for 20,000 moodbars
QObject::connect(app, &Application::SettingsChanged, this, &MoodbarLoader::ReloadSettings);
ReloadSettings(); ReloadSettings();
} }
@ -86,6 +84,8 @@ void MoodbarLoader::ReloadSettings() {
MaybeTakeNextRequest(); MaybeTakeNextRequest();
Q_EMIT SettingsReloaded();
} }
QStringList MoodbarLoader::MoodFilenames(const QString &song_filename) { QStringList MoodbarLoader::MoodFilenames(const QString &song_filename) {

View File

@ -33,14 +33,13 @@
class QThread; class QThread;
class QByteArray; class QByteArray;
class QNetworkDiskCache; class QNetworkDiskCache;
class Application;
class MoodbarPipeline; class MoodbarPipeline;
class MoodbarLoader : public QObject { class MoodbarLoader : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit MoodbarLoader(Application *app, QObject *parent = nullptr); explicit MoodbarLoader(QObject *parent = nullptr);
~MoodbarLoader() override; ~MoodbarLoader() override;
enum class Result { enum class Result {
@ -56,11 +55,11 @@ class MoodbarLoader : public QObject {
WillLoadAsync WillLoadAsync
}; };
void ReloadSettings();
Result Load(const QUrl &url, const bool has_cue, QByteArray *data, MoodbarPipeline **async_pipeline); Result Load(const QUrl &url, const bool has_cue, QByteArray *data, MoodbarPipeline **async_pipeline);
private Q_SLOTS: private Q_SLOTS:
void ReloadSettings();
void RequestFinished(MoodbarPipeline *request, const QUrl &url); void RequestFinished(MoodbarPipeline *request, const QUrl &url);
void MaybeTakeNextRequest(); void MaybeTakeNextRequest();
@ -68,6 +67,9 @@ class MoodbarLoader : public QObject {
static QStringList MoodFilenames(const QString &song_filename); static QStringList MoodFilenames(const QString &song_filename);
static QUrl CacheUrlEntry(const QString &filename); static QUrl CacheUrlEntry(const QString &filename);
Q_SIGNALS:
void SettingsReloaded();
private: private:
QNetworkDiskCache *cache_; QNetworkDiskCache *cache_;
QThread *thread_; QThread *thread_;

View File

@ -40,7 +40,6 @@
#include <QEvent> #include <QEvent>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include "core/application.h"
#include "core/settings.h" #include "core/settings.h"
#include "moodbarproxystyle.h" #include "moodbarproxystyle.h"
@ -54,9 +53,8 @@ constexpr int kArrowWidth = 17;
constexpr int kArrowHeight = 13; constexpr int kArrowHeight = 13;
} // namespace } // namespace
MoodbarProxyStyle::MoodbarProxyStyle(Application *app, QSlider *slider, QObject *parent) MoodbarProxyStyle::MoodbarProxyStyle(QSlider *slider, QObject *parent)
: QProxyStyle(nullptr), : QProxyStyle(nullptr),
app_(app),
slider_(slider), slider_(slider),
enabled_(true), enabled_(true),
moodbar_style_(MoodbarRenderer::MoodbarStyle::Normal), moodbar_style_(MoodbarRenderer::MoodbarStyle::Normal),
@ -75,8 +73,6 @@ MoodbarProxyStyle::MoodbarProxyStyle(Application *app, QSlider *slider, QObject
QObject::connect(fade_timeline_, &QTimeLine::valueChanged, this, &MoodbarProxyStyle::FaderValueChanged); QObject::connect(fade_timeline_, &QTimeLine::valueChanged, this, &MoodbarProxyStyle::FaderValueChanged);
QObject::connect(app, &Application::SettingsChanged, this, &MoodbarProxyStyle::ReloadSettings);
ReloadSettings(); ReloadSettings();
} }
@ -121,7 +117,7 @@ void MoodbarProxyStyle::SetMoodbarEnabled(const bool enabled) {
s.setValue("show", enabled); s.setValue("show", enabled);
s.endGroup(); s.endGroup();
app_->ReloadSettings(); Q_EMIT SettingsChanged();
} }
@ -417,6 +413,6 @@ void MoodbarProxyStyle::ChangeStyle(QAction *action) {
s.setValue("style", action->data().toInt()); s.setValue("style", action->data().toInt());
s.endGroup(); s.endGroup();
app_->ReloadSettings(); //app_->ReloadSettings();
} }

View File

@ -46,13 +46,13 @@ class QTimeLine;
class QWidget; class QWidget;
class QEvent; class QEvent;
class Application;
class MoodbarProxyStyle : public QProxyStyle { class MoodbarProxyStyle : public QProxyStyle {
Q_OBJECT Q_OBJECT
public: public:
explicit MoodbarProxyStyle(Application *app, QSlider *slider, QObject *parent = nullptr); explicit MoodbarProxyStyle(QSlider *slider, QObject *parent = nullptr);
void ReloadSettings();
// QProxyStyle // QProxyStyle
void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const override; void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const override;
@ -87,12 +87,13 @@ class MoodbarProxyStyle : public QProxyStyle {
static QPixmap MoodbarPixmap(const ColorVector &colors, const QSize size, const QPalette &palette, const QStyleOptionSlider *opt); static QPixmap MoodbarPixmap(const ColorVector &colors, const QSize size, const QPalette &palette, const QStyleOptionSlider *opt);
private Q_SLOTS: private Q_SLOTS:
void ReloadSettings();
void FaderValueChanged(qreal value); void FaderValueChanged(qreal value);
void ChangeStyle(QAction *action); void ChangeStyle(QAction *action);
Q_SIGNALS:
void SettingsChanged();
private: private:
Application *app_;
QSlider *slider_; QSlider *slider_;
bool enabled_; bool enabled_;

View File

@ -46,10 +46,9 @@
#include "mpris_common.h" #include "mpris_common.h"
#include "mpris2.h" #include "mpris2.h"
#include "constants/timeconstants.h"
#include "core/song.h" #include "core/song.h"
#include "core/application.h" #include "player/player.h"
#include "core/player.h"
#include "utilities/timeconstants.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "playlist/playlist.h" #include "playlist/playlist.h"
#include "playlist/playlistitem.h" #include "playlist/playlistitem.h"
@ -100,9 +99,11 @@ constexpr char kMprisObjectPath[] = "/org/mpris/MediaPlayer2";
constexpr char kServiceName[] = "org.mpris.MediaPlayer2.strawberry"; constexpr char kServiceName[] = "org.mpris.MediaPlayer2.strawberry";
constexpr char kFreedesktopPath[] = "org.freedesktop.DBus.Properties"; constexpr char kFreedesktopPath[] = "org.freedesktop.DBus.Properties";
Mpris2::Mpris2(Application *app, QObject *parent) Mpris2::Mpris2(SharedPtr<Player> player, SharedPtr<PlaylistManager> playlist_manager, SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader, QObject *parent)
: QObject(parent), : QObject(parent),
app_(app), player_(player),
playlist_manager_(playlist_manager),
current_albumcover_loader_(current_albumcover_loader),
app_name_(QCoreApplication::applicationName()) { app_name_(QCoreApplication::applicationName()) {
new Mpris2Root(this); new Mpris2Root(this);
@ -120,16 +121,16 @@ Mpris2::Mpris2(Application *app, QObject *parent)
return; return;
} }
QObject::connect(&*app_->current_albumcover_loader(), &CurrentAlbumCoverLoader::AlbumCoverLoaded, this, &Mpris2::AlbumCoverLoaded); QObject::connect(&*current_albumcover_loader_, &CurrentAlbumCoverLoader::AlbumCoverLoaded, this, &Mpris2::AlbumCoverLoaded);
QObject::connect(&*app_->player()->engine(), &EngineBase::StateChanged, this, &Mpris2::EngineStateChanged); QObject::connect(&*player_->engine(), &EngineBase::StateChanged, this, &Mpris2::EngineStateChanged);
QObject::connect(&*app_->player(), &Player::VolumeChanged, this, &Mpris2::VolumeChanged); QObject::connect(&*player_, &Player::VolumeChanged, this, &Mpris2::VolumeChanged);
QObject::connect(&*app_->player(), &Player::Seeked, this, &Mpris2::Seeked); QObject::connect(&*player_, &Player::Seeked, this, &Mpris2::Seeked);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::PlaylistManagerInitialized, this, &Mpris2::PlaylistManagerInitialized); QObject::connect(&*playlist_manager_, &PlaylistManager::PlaylistManagerInitialized, this, &Mpris2::PlaylistManagerInitialized);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &Mpris2::CurrentSongChanged); QObject::connect(&*playlist_manager_, &PlaylistManager::CurrentSongChanged, this, &Mpris2::CurrentSongChanged);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::PlaylistChanged, this, &Mpris2::PlaylistChangedSlot); QObject::connect(&*playlist_manager_, &PlaylistManager::PlaylistChanged, this, &Mpris2::PlaylistChangedSlot);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentChanged, this, &Mpris2::PlaylistCollectionChanged); QObject::connect(&*playlist_manager_, &PlaylistManager::CurrentChanged, this, &Mpris2::PlaylistCollectionChanged);
app_name_[0] = app_name_[0].toUpper(); app_name_[0] = app_name_[0].toUpper();
@ -159,8 +160,8 @@ Mpris2::Mpris2(Application *app, QObject *parent)
// when PlaylistManager gets it ready, we connect PlaylistSequence with this // when PlaylistManager gets it ready, we connect PlaylistSequence with this
void Mpris2::PlaylistManagerInitialized() { void Mpris2::PlaylistManagerInitialized() {
QObject::connect(app_->playlist_manager()->sequence(), &PlaylistSequence::ShuffleModeChanged, this, &Mpris2::ShuffleModeChanged); QObject::connect(playlist_manager_->sequence(), &PlaylistSequence::ShuffleModeChanged, this, &Mpris2::ShuffleModeChanged);
QObject::connect(app_->playlist_manager()->sequence(), &PlaylistSequence::RepeatModeChanged, this, &Mpris2::RepeatModeChanged); QObject::connect(playlist_manager_->sequence(), &PlaylistSequence::RepeatModeChanged, this, &Mpris2::RepeatModeChanged);
} }
void Mpris2::EngineStateChanged(EngineBase::State newState) { void Mpris2::EngineStateChanged(EngineBase::State newState) {
@ -295,7 +296,7 @@ void Mpris2::Raise() { Q_EMIT RaiseMainWindow(); }
void Mpris2::Quit() { QCoreApplication::quit(); } void Mpris2::Quit() { QCoreApplication::quit(); }
QString Mpris2::PlaybackStatus() const { QString Mpris2::PlaybackStatus() const {
return PlaybackStatus(app_->player()->GetState()); return PlaybackStatus(player_->GetState());
} }
QString Mpris2::PlaybackStatus(EngineBase::State state) const { QString Mpris2::PlaybackStatus(EngineBase::State state) const {
@ -310,11 +311,11 @@ QString Mpris2::PlaybackStatus(EngineBase::State state) const {
QString Mpris2::LoopStatus() const { QString Mpris2::LoopStatus() const {
if (!app_->playlist_manager()->sequence()) { if (!playlist_manager_->sequence()) {
return u"None"_s; return u"None"_s;
} }
switch (app_->playlist_manager()->active() ? app_->playlist_manager()->active()->RepeatMode() : app_->playlist_manager()->sequence()->repeat_mode()) { switch (playlist_manager_->active() ? playlist_manager_->active()->RepeatMode() : playlist_manager_->sequence()->repeat_mode()) {
case PlaylistSequence::RepeatMode::Album: case PlaylistSequence::RepeatMode::Album:
case PlaylistSequence::RepeatMode::Playlist: return u"Playlist"_s; case PlaylistSequence::RepeatMode::Playlist: return u"Playlist"_s;
case PlaylistSequence::RepeatMode::Track: return u"Track"_s; case PlaylistSequence::RepeatMode::Track: return u"Track"_s;
@ -337,7 +338,7 @@ void Mpris2::SetLoopStatus(const QString &value) {
mode = PlaylistSequence::RepeatMode::Playlist; mode = PlaylistSequence::RepeatMode::Playlist;
} }
app_->playlist_manager()->active()->sequence()->SetRepeatMode(mode); playlist_manager_->active()->sequence()->SetRepeatMode(mode);
} }
@ -346,26 +347,26 @@ double Mpris2::Rate() const { return 1.0; }
void Mpris2::SetRate(double rate) { void Mpris2::SetRate(double rate) {
if (rate == 0) { if (rate == 0) {
app_->player()->Pause(); player_->Pause();
} }
} }
bool Mpris2::Shuffle() const { bool Mpris2::Shuffle() const {
const PlaylistSequence::ShuffleMode shuffle_mode = app_->playlist_manager()->active() ? app_->playlist_manager()->active()->ShuffleMode() : app_->playlist_manager()->sequence()->shuffle_mode(); const PlaylistSequence::ShuffleMode shuffle_mode = playlist_manager_->active() ? playlist_manager_->active()->ShuffleMode() : playlist_manager_->sequence()->shuffle_mode();
return shuffle_mode != PlaylistSequence::ShuffleMode::Off; return shuffle_mode != PlaylistSequence::ShuffleMode::Off;
} }
void Mpris2::SetShuffle(bool enable) { void Mpris2::SetShuffle(bool enable) {
app_->playlist_manager()->active()->sequence()->SetShuffleMode(enable ? PlaylistSequence::ShuffleMode::All : PlaylistSequence::ShuffleMode::Off); playlist_manager_->active()->sequence()->SetShuffleMode(enable ? PlaylistSequence::ShuffleMode::All : PlaylistSequence::ShuffleMode::Off);
} }
QVariantMap Mpris2::Metadata() const { return last_metadata_; } QVariantMap Mpris2::Metadata() const { return last_metadata_; }
double Mpris2::Rating() const { double Mpris2::Rating() const {
float rating = app_->playlist_manager()->active()->current_item_metadata().rating(); float rating = playlist_manager_->active()->current_item_metadata().rating();
return (rating <= 0) ? 0 : rating; return (rating <= 0) ? 0 : rating;
} }
@ -378,12 +379,12 @@ void Mpris2::SetRating(double rating) {
rating = -1.0; rating = -1.0;
} }
app_->playlist_manager()->RateCurrentSong(static_cast<float>(rating)); playlist_manager_->RateCurrentSong(static_cast<float>(rating));
} }
QDBusObjectPath Mpris2::current_track_id() const { QDBusObjectPath Mpris2::current_track_id() const {
return QDBusObjectPath(QStringLiteral("/org/strawberrymusicplayer/strawberry/Track/%1").arg(QString::number(app_->playlist_manager()->active()->current_row()))); return QDBusObjectPath(QStringLiteral("/org/strawberrymusicplayer/strawberry/Track/%1").arg(QString::number(playlist_manager_->active()->current_row())));
} }
// We send Metadata change notification as soon as the process of changing song starts... // We send Metadata change notification as soon as the process of changing song starts...
@ -433,15 +434,15 @@ void Mpris2::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &re
} }
double Mpris2::Volume() const { double Mpris2::Volume() const {
return app_->player()->GetVolume() / 100.0; return player_->GetVolume() / 100.0;
} }
void Mpris2::SetVolume(const double volume) { void Mpris2::SetVolume(const double volume) {
app_->player()->SetVolume(static_cast<uint>(qBound(0L, lround(volume * 100.0), 100L))); player_->SetVolume(static_cast<uint>(qBound(0L, lround(volume * 100.0), 100L)));
} }
qint64 Mpris2::Position() const { qint64 Mpris2::Position() const {
return app_->player()->engine()->position_nanosec() / kNsecPerUsec; return player_->engine()->position_nanosec() / kNsecPerUsec;
} }
double Mpris2::MaximumRate() const { return 1.0; } double Mpris2::MaximumRate() const { return 1.0; }
@ -449,66 +450,66 @@ double Mpris2::MaximumRate() const { return 1.0; }
double Mpris2::MinimumRate() const { return 1.0; } double Mpris2::MinimumRate() const { return 1.0; }
bool Mpris2::CanGoNext() const { bool Mpris2::CanGoNext() const {
return app_->playlist_manager()->active() && app_->playlist_manager()->active()->next_row() != -1; return playlist_manager_->active() && playlist_manager_->active()->next_row() != -1;
} }
bool Mpris2::CanGoPrevious() const { bool Mpris2::CanGoPrevious() const {
return app_->playlist_manager()->active() && (app_->playlist_manager()->active()->previous_row() != -1 || app_->player()->PreviousWouldRestartTrack()); return playlist_manager_->active() && (playlist_manager_->active()->previous_row() != -1 || player_->PreviousWouldRestartTrack());
} }
bool Mpris2::CanPlay() const { bool Mpris2::CanPlay() const {
return app_->playlist_manager()->active() && app_->playlist_manager()->active()->rowCount() != 0; return playlist_manager_->active() && playlist_manager_->active()->rowCount() != 0;
} }
// This one's a bit different than MPRIS 1 - we want this to be true even when the song is already paused or stopped. // This one's a bit different than MPRIS 1 - we want this to be true even when the song is already paused or stopped.
bool Mpris2::CanPause() const { bool Mpris2::CanPause() const {
return (app_->player()->GetCurrentItem() && app_->player()->GetState() == EngineBase::State::Playing && !(app_->player()->GetCurrentItem()->options() & PlaylistItem::Option::PauseDisabled)) || PlaybackStatus() == "Paused"_L1 || PlaybackStatus() == "Stopped"_L1; return (player_->GetCurrentItem() && player_->GetState() == EngineBase::State::Playing && !(player_->GetCurrentItem()->options() & PlaylistItem::Option::PauseDisabled)) || PlaybackStatus() == "Paused"_L1 || PlaybackStatus() == "Stopped"_L1;
} }
bool Mpris2::CanSeek() const { return CanSeek(app_->player()->GetState()); } bool Mpris2::CanSeek() const { return CanSeek(player_->GetState()); }
bool Mpris2::CanSeek(EngineBase::State state) const { bool Mpris2::CanSeek(EngineBase::State state) const {
return app_->player()->GetCurrentItem() && state != EngineBase::State::Empty && !app_->player()->GetCurrentItem()->Metadata().is_stream(); return player_->GetCurrentItem() && state != EngineBase::State::Empty && !player_->GetCurrentItem()->Metadata().is_stream();
} }
bool Mpris2::CanControl() const { return true; } bool Mpris2::CanControl() const { return true; }
void Mpris2::Next() { void Mpris2::Next() {
if (CanGoNext()) { if (CanGoNext()) {
app_->player()->Next(); player_->Next();
} }
} }
void Mpris2::Previous() { void Mpris2::Previous() {
if (CanGoPrevious()) { if (CanGoPrevious()) {
app_->player()->Previous(); player_->Previous();
} }
} }
void Mpris2::Pause() { void Mpris2::Pause() {
if (CanPause() && app_->player()->GetState() != EngineBase::State::Paused) { if (CanPause() && player_->GetState() != EngineBase::State::Paused) {
app_->player()->Pause(); player_->Pause();
} }
} }
void Mpris2::PlayPause() { void Mpris2::PlayPause() {
if (CanPause()) { if (CanPause()) {
app_->player()->PlayPause(); player_->PlayPause();
} }
} }
void Mpris2::Stop() { app_->player()->Stop(); } void Mpris2::Stop() { player_->Stop(); }
void Mpris2::Play() { void Mpris2::Play() {
if (CanPlay()) { if (CanPlay()) {
app_->player()->Play(); player_->Play();
} }
} }
void Mpris2::Seek(qint64 offset) { void Mpris2::Seek(qint64 offset) {
if (CanSeek()) { if (CanSeek()) {
app_->player()->SeekTo(app_->player()->engine()->position_nanosec() / kNsecPerSec + offset / kUsecPerSec); player_->SeekTo(player_->engine()->position_nanosec() / kNsecPerSec + offset / kUsecPerSec);
} }
} }
@ -518,15 +519,15 @@ void Mpris2::SetPosition(const QDBusObjectPath &trackId, qint64 offset) {
if (CanSeek() && trackId == current_track_id() && offset >= 0) { if (CanSeek() && trackId == current_track_id() && offset >= 0) {
offset *= kNsecPerUsec; offset *= kNsecPerUsec;
if (offset < app_->player()->GetCurrentItem()->Metadata().length_nanosec()) { if (offset < player_->GetCurrentItem()->Metadata().length_nanosec()) {
app_->player()->SeekTo(offset / kNsecPerSec); player_->SeekTo(offset / kNsecPerSec);
} }
} }
} }
void Mpris2::OpenUri(const QString &uri) { void Mpris2::OpenUri(const QString &uri) {
app_->playlist_manager()->active()->InsertUrls(QList<QUrl>() << QUrl(uri), -1, true); playlist_manager_->active()->InsertUrls(QList<QUrl>() << QUrl(uri), -1, true);
} }
Track_Ids Mpris2::Tracks() const { Track_Ids Mpris2::Tracks() const {
@ -566,7 +567,7 @@ void Mpris2::GoTo(const QDBusObjectPath &trackId) {
} }
quint32 Mpris2::PlaylistCount() const { quint32 Mpris2::PlaylistCount() const {
return app_->playlist_manager()->GetAllPlaylists().size(); return playlist_manager_->GetAllPlaylists().size();
} }
QStringList Mpris2::Orderings() const { return QStringList() << u"User"_s; } QStringList Mpris2::Orderings() const { return QStringList() << u"User"_s; }
@ -582,14 +583,14 @@ QDBusObjectPath MakePlaylistPath(int id) {
MaybePlaylist Mpris2::ActivePlaylist() const { MaybePlaylist Mpris2::ActivePlaylist() const {
MaybePlaylist maybe_playlist; MaybePlaylist maybe_playlist;
Playlist *current_playlist = app_->playlist_manager()->current(); Playlist *current_playlist = playlist_manager_->current();
maybe_playlist.valid = current_playlist; maybe_playlist.valid = current_playlist;
if (!current_playlist) { if (!current_playlist) {
return maybe_playlist; return maybe_playlist;
} }
maybe_playlist.playlist.id = MakePlaylistPath(current_playlist->id()); maybe_playlist.playlist.id = MakePlaylistPath(current_playlist->id());
maybe_playlist.playlist.name = app_->playlist_manager()->GetPlaylistName(current_playlist->id()); maybe_playlist.playlist.name = playlist_manager_->GetPlaylistName(current_playlist->id());
return maybe_playlist; return maybe_playlist;
} }
@ -606,12 +607,12 @@ void Mpris2::ActivatePlaylist(const QDBusObjectPath &playlist_id) {
if (!ok) { if (!ok) {
return; return;
} }
if (!app_->playlist_manager()->IsPlaylistOpen(p)) { if (!playlist_manager_->IsPlaylistOpen(p)) {
qLog(Error) << "Playlist isn't opened!"; qLog(Error) << "Playlist isn't opened!";
return; return;
} }
app_->playlist_manager()->SetActivePlaylist(p); playlist_manager_->SetActivePlaylist(p);
app_->player()->Next(); player_->Next();
} }
@ -620,13 +621,13 @@ MprisPlaylistList Mpris2::GetPlaylists(quint32 index, quint32 max_count, const Q
Q_UNUSED(order); Q_UNUSED(order);
const QList<Playlist*> playlists = app_->playlist_manager()->GetAllPlaylists(); const QList<Playlist*> playlists = playlist_manager_->GetAllPlaylists();
MprisPlaylistList ret; MprisPlaylistList ret;
ret.reserve(playlists.count()); ret.reserve(playlists.count());
for (Playlist *p : playlists) { for (Playlist *p : playlists) {
MprisPlaylist mpris_playlist; MprisPlaylist mpris_playlist;
mpris_playlist.id = MakePlaylistPath(p->id()); mpris_playlist.id = MakePlaylistPath(p->id());
mpris_playlist.name = app_->playlist_manager()->GetPlaylistName(p->id()); mpris_playlist.name = playlist_manager_->GetPlaylistName(p->id());
ret << mpris_playlist; ret << mpris_playlist;
} }
@ -642,7 +643,7 @@ void Mpris2::PlaylistChangedSlot(Playlist *playlist) {
MprisPlaylist mpris_playlist; MprisPlaylist mpris_playlist;
mpris_playlist.id = MakePlaylistPath(playlist->id()); mpris_playlist.id = MakePlaylistPath(playlist->id());
mpris_playlist.name = app_->playlist_manager()->GetPlaylistName(playlist->id()); mpris_playlist.name = playlist_manager_->GetPlaylistName(playlist->id());
Q_EMIT PlaylistChanged(mpris_playlist); Q_EMIT PlaylistChanged(mpris_playlist);

View File

@ -37,10 +37,13 @@
#include <QDBusArgument> #include <QDBusArgument>
#include <QJsonObject> #include <QJsonObject>
#include "core/shared_ptr.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
#include "covermanager/albumcoverloaderresult.h" #include "covermanager/albumcoverloaderresult.h"
class Application; class Player;
class PlaylistManager;
class CurrentAlbumCoverLoader;
class Song; class Song;
class Playlist; class Playlist;
@ -75,7 +78,7 @@ class Mpris2 : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit Mpris2(Application *app, QObject *parent = nullptr); explicit Mpris2(SharedPtr<Player> player, SharedPtr<PlaylistManager> playlist_manager, SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader, QObject *parent = nullptr);
// org.mpris.MediaPlayer2 MPRIS 2.0 Root interface // org.mpris.MediaPlayer2 MPRIS 2.0 Root interface
Q_PROPERTY(bool CanQuit READ CanQuit) Q_PROPERTY(bool CanQuit READ CanQuit)
@ -231,7 +234,9 @@ class Mpris2 : public QObject {
QString DesktopEntryAbsolutePath() const; QString DesktopEntryAbsolutePath() const;
private: private:
Application *app_; SharedPtr<Player> player_;
SharedPtr<PlaylistManager> playlist_manager_;
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
QString app_name_; QString app_name_;
QString desktopfilepath_; QString desktopfilepath_;

View File

@ -45,7 +45,7 @@
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "core/networktimeouts.h" #include "core/networktimeouts.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "acoustidclient.h" #include "acoustidclient.h"

View File

@ -32,7 +32,7 @@
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/networkaccessmanager.h" #include "core/networkaccessmanager.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "engine/chromaprinter.h" #include "engine/chromaprinter.h"
#include "acoustidclient.h" #include "acoustidclient.h"
#include "musicbrainzclient.h" #include "musicbrainzclient.h"

View File

@ -28,8 +28,8 @@
#include <QFileInfo> #include <QFileInfo>
#include <QValidator> #include <QValidator>
#include "utilities/filenameconstants.h" #include "constants/filenameconstants.h"
#include "utilities/timeconstants.h" #include "constants/timeconstants.h"
#include "utilities/transliterate.h" #include "utilities/transliterate.h"
#include "core/song.h" #include "core/song.h"

View File

@ -32,7 +32,6 @@
#include "osdpretty.h" #include "osdpretty.h"
#include "core/shared_ptr.h" #include "core/shared_ptr.h"
#include "core/application.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/settings.h" #include "core/settings.h"
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
@ -41,15 +40,13 @@
# include "core/qtsystemtrayicon.h" # include "core/qtsystemtrayicon.h"
#endif #endif
#include "utilities/strutils.h" #include "utilities/strutils.h"
#include "covermanager/currentalbumcoverloader.h"
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
const char *OSDBase::kSettingsGroup = "OSD"; const char *OSDBase::kSettingsGroup = "OSD";
OSDBase::OSDBase(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject *parent) OSDBase::OSDBase(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent)
: QObject(parent), : QObject(parent),
app_(app),
tray_icon_(tray_icon), tray_icon_(tray_icon),
pretty_popup_(new OSDPretty(OSDPretty::Mode::Popup)), pretty_popup_(new OSDPretty(OSDPretty::Mode::Popup)),
app_name_(QCoreApplication::applicationName()), app_name_(QCoreApplication::applicationName()),
@ -65,8 +62,6 @@ OSDBase::OSDBase(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject
ignore_next_stopped_(false), ignore_next_stopped_(false),
playing_(false) { playing_(false) {
QObject::connect(&*app_->current_albumcover_loader(), &CurrentAlbumCoverLoader::ThumbnailLoaded, this, &OSDBase::AlbumCoverLoaded);
app_name_[0] = app_name_[0].toUpper(); app_name_[0] = app_name_[0].toUpper();
} }

View File

@ -35,7 +35,6 @@
#include "core/song.h" #include "core/song.h"
#include "playlist/playlistsequence.h" #include "playlist/playlistsequence.h"
class Application;
class OSDPretty; class OSDPretty;
class SystemTrayIcon; class SystemTrayIcon;
@ -43,7 +42,7 @@ class OSDBase : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit OSDBase(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject *parent = nullptr); explicit OSDBase(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent = nullptr);
~OSDBase() override; ~OSDBase() override;
static const char *kSettingsGroup; static const char *kSettingsGroup;
@ -81,6 +80,8 @@ class OSDBase : public QObject {
void ShowPreview(const OSDBase::Behaviour type, const QString &line1, const QString &line2, const Song &song); void ShowPreview(const OSDBase::Behaviour type, const QString &line1, const QString &line2, const Song &song);
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
private: private:
enum class MessageType { enum class MessageType {
Summary, Summary,
@ -91,11 +92,7 @@ class OSDBase : public QObject {
QString ReplaceMessage(const MessageType type, const QString &message, const Song &song); QString ReplaceMessage(const MessageType type, const QString &message, const Song &song);
virtual void ShowMessageNative(const QString &summary, const QString &message, const QString &icon = QString(), const QImage &image = QImage()); virtual void ShowMessageNative(const QString &summary, const QString &message, const QString &icon = QString(), const QImage &image = QImage());
private Q_SLOTS:
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
private: private:
Application *app_;
SharedPtr<SystemTrayIcon> tray_icon_; SharedPtr<SystemTrayIcon> tray_icon_;
OSDPretty *pretty_popup_; OSDPretty *pretty_popup_;

View File

@ -105,8 +105,8 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, QImage &image) {
} }
OSDDBus::OSDDBus(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject *parent) OSDDBus::OSDDBus(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent)
: OSDBase(tray_icon, app, parent), : OSDBase(tray_icon, parent),
version_(1, 1), version_(1, 1),
notification_id_(0) { notification_id_(0) {

View File

@ -39,14 +39,13 @@
class OrgFreedesktopNotificationsInterface; class OrgFreedesktopNotificationsInterface;
class QDBusPendingCallWatcher; class QDBusPendingCallWatcher;
class Application;
class SystemTrayIcon; class SystemTrayIcon;
class OSDDBus : public OSDBase { class OSDDBus : public OSDBase {
Q_OBJECT Q_OBJECT
public: public:
explicit OSDDBus(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject *parent = nullptr); explicit OSDDBus(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent = nullptr);
~OSDDBus() override; ~OSDDBus() override;
static const char *kSettingsGroup; static const char *kSettingsGroup;

View File

@ -37,7 +37,7 @@ class OSDMac : public OSDBase {
Q_OBJECT Q_OBJECT
public: public:
explicit OSDMac(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject *parent = nullptr); explicit OSDMac(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent = nullptr);
~OSDMac() override; ~OSDMac() override;
bool SupportsNativeNotifications() override; bool SupportsNativeNotifications() override;

Some files were not shown because too many files have changed in this diff Show More