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

View File

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

View File

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

View File

@ -84,32 +84,32 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "shared_ptr.h"
#include "commandlineoptions.h"
#include "mimedata.h"
#include "iconloader.h"
#include "taskmanager.h"
#include "song.h"
#include "stylehelper.h"
#include "stylesheetloader.h"
#include "constants/filenameconstants.h"
#include "constants/timeconstants.h"
#include "core/shared_ptr.h"
#include "core/commandlineoptions.h"
#include "core/mimedata.h"
#include "core/iconloader.h"
#include "core/taskmanager.h"
#include "core/song.h"
#include "core/stylehelper.h"
#include "core/stylesheetloader.h"
#include "application.h"
#include "database.h"
#include "player.h"
#include "filesystemmusicstorage.h"
#include "deletefiles.h"
#include "core/database.h"
#include "core/filesystemmusicstorage.h"
#include "core/deletefiles.h"
#ifdef Q_OS_MACOS
# include "mac_startup.h"
# include "macsystemtrayicon.h"
# include "core/mac_startup.h"
# include "core/macsystemtrayicon.h"
# include "utilities/macosutils.h"
#else
# include "qtsystemtrayicon.h"
# include "core/qtsystemtrayicon.h"
#endif
#include "networkaccessmanager.h"
#include "settings.h"
#include "core/settings.h"
#include "utilities/envutils.h"
#include "utilities/filemanagerutils.h"
#include "utilities/timeconstants.h"
#include "utilities/screenutils.h"
#include "player/player.h"
#include "engine/enginebase.h"
#include "dialogs/errordialog.h"
#include "dialogs/about.h"
@ -205,6 +205,7 @@
#ifdef HAVE_MOODBAR
# include "moodbar/moodbarcontroller.h"
# include "moodbar/moodbarloader.h"
# include "moodbar/moodbarproxystyle.h"
#endif
@ -213,7 +214,7 @@
#include "organize/organizeerrordialog.h"
#ifdef Q_OS_WIN
# include "windows7thumbbar.h"
# include "core/windows7thumbbar.h"
#endif
#ifdef HAVE_QTSPARKLE
@ -226,7 +227,6 @@ using namespace std::chrono_literals;
using namespace Qt::Literals::StringLiterals;
const char *MainWindow::kSettingsGroup = "MainWindow";
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
namespace {
const int kTrackSliderUpdateTimeMs = 200;
@ -259,7 +259,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
tray_icon_(tray_icon),
osd_(osd),
console_([app]() {
Console *console = new Console(app);
Console *console = new Console(app->database());
return console;
}),
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)),
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
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 connections
@ -300,18 +300,18 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
QObject::connect(add_stream_dialog, &AddStreamDialog::accepted, this, &MainWindow::AddStreamAccepted);
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
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
#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
#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
#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
radio_view_(new RadioViewContainer(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";
QObject::connect(app, &Application::ErrorAdded, this, &MainWindow::ShowErrorDialog);
QObject::connect(app, &Application::SettingsDialogRequested, this, &MainWindow::OpenSettingsDialogAtPage);
// Initialize the UI
ui_->setupUi(this);
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());
context_view_->Init(app_, collection_view_->view(), album_cover_choice_controller_);
ui_->widget_playing->Init(app_, album_cover_choice_controller_);
context_view_->Init(collection_view_->view(), album_cover_choice_controller_, app_->lyrics_providers());
ui_->widget_playing->Init(album_cover_choice_controller_);
// Initialize the search widget
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->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()->SetApplication(app_);
collection_view_->view()->Init(app->task_manager(), app->network(), app->device_manager());
#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
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());
@ -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, ui_->volume, &VolumeSlider::SetValue);
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::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::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(album_cover_choice_controller_, &AlbumCoverChoiceController::Error, this, &MainWindow::ShowErrorDialog);
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);
QObject::connect(ui_->multi_loading_indicator, &MultiLoadingIndicator::TaskCountChange, this, &MainWindow::TaskCountChanged);
ui_->track_slider->SetApplication(app);
ui_->track_slider->Init();
#ifdef HAVE_MOODBAR
// Moodbar connections
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
// Playing widget
@ -875,7 +880,7 @@ MainWindow::MainWindow(Application *app, SharedPtr<SystemTrayIcon> tray_icon, OS
css_loader->SetStyleSheet(this, u":/style/strawberry.css"_s);
// 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());
@ -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::UpdateTotal, lastfm_import_dialog_, &LastFMImportDialog::UpdateTotal);
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
qLog(Debug) << "Loading settings";
@ -1208,7 +1215,7 @@ void MainWindow::ReloadAllSettings() {
ReloadSettings();
// Other settings
app_->ReloadSettings();
//app_->ReloadSettings();
app_->collection()->ReloadSettings();
app_->player()->ReloadSettings();
collection_view_->ReloadSettings();
@ -1228,18 +1235,30 @@ void MainWindow::ReloadAllSettings() {
app_->lyrics_providers()->ReloadSettings();
#ifdef HAVE_MOODBAR
app_->moodbar_controller()->ReloadSettings();
app_->moodbar_loader()->ReloadSettings();
ui_->track_slider->moodbar_style()->ReloadSettings();
#endif
#ifdef HAVE_SUBSONIC
subsonic_view_->ReloadSettings();
#endif
#ifdef HAVE_TIDAL
tidal_view_->ReloadSettings();
tidal_view_->search_view()->ReloadSettings();
#endif
#ifdef HAVE_SPOTIFY
spotify_view_->ReloadSettings();
spotify_view_->search_view()->ReloadSettings();
#endif
#ifdef HAVE_QOBUZ
qobuz_view_->ReloadSettings();
qobuz_view_->search_view()->ReloadSettings();
#endif
}
void MainWindow::MoodbarSettingsChanged() {
#ifdef HAVE_MOODBAR
#endif
}
@ -2810,7 +2829,7 @@ void MainWindow::ShowEqualizer() {
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
settings_dialog->SetGlobalShortcutManager(globalshortcuts_manager_);
#endif
@ -2838,7 +2857,7 @@ void MainWindow::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
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::Error, this, &MainWindow::ShowErrorDialog);
return edit_tag_dialog;

View File

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

View File

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

View File

@ -40,13 +40,13 @@
#include <QEventLoop>
#include "core/logging.h"
#include "shared_ptr.h"
#include "signalchecker.h"
#include "player.h"
#include "song.h"
#include "core/shared_ptr.h"
#include "core/signalchecker.h"
#include "core/song.h"
#include "core/database.h"
#include "core/urlhandlers.h"
#include "songloader.h"
#include "database.h"
#include "player/player.h"
#include "engine/enginebase.h"
#include "tagreader/tagreaderclient.h"
#include "collection/collectionbackend.h"
@ -66,8 +66,9 @@ constexpr int kDefaultTimeout = 5000;
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),
url_handlers_(url_handlers),
player_(player),
collection_backend_(collection_backend),
timeout_timer_(new QTimer(this)),
@ -114,7 +115,7 @@ SongLoader::Result SongLoader::Load(const QUrl &url) {
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,
// or we have a custom handler for the URL, so add it as a raw stream.
AddAsRawStream();

View File

@ -38,10 +38,11 @@
#include <QStringList>
#include <QUrl>
#include "shared_ptr.h"
#include "song.h"
#include "core/shared_ptr.h"
#include "core/song.h"
class QTimer;
class UrlHandlers;
class Player;
class CollectionBackendInterface;
class PlaylistParser;
@ -56,7 +57,7 @@ class SongLoader : public QObject {
Q_OBJECT
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;
enum class Result {
@ -137,8 +138,9 @@ class SongLoader : public QObject {
QUrl url_;
SongList songs_;
const SharedPtr<UrlHandlers> url_handlers_;
const SharedPtr<Player> player_;
SharedPtr<CollectionBackendInterface> collection_backend_;
const SharedPtr<CollectionBackendInterface> collection_backend_;
QTimer *timeout_timer_;
PlaylistParser *playlist_parser_;
CueParser *cue_parser_;

View File

@ -30,7 +30,6 @@
#include <QSettings>
#include <QtConcurrentRun>
#include "core/application.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "core/thread.h"
@ -43,7 +42,6 @@
#include "collectionwatcher.h"
#include "collectionbackend.h"
#include "collectionmodel.h"
#include "scrobbler/lastfmimport.h"
#include "settings/collectionsettingspage.h"
using std::make_shared;
@ -52,9 +50,9 @@ const char *SCollection::kSongsTable = "songs";
const char *SCollection::kDirsTable = "directories";
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),
app_(app),
task_manager_(task_manager),
backend_(nullptr),
model_(nullptr),
watcher_(nullptr),
@ -68,12 +66,12 @@ SCollection::SCollection(Application *app, QObject *parent)
original_thread_ = thread();
backend_ = make_shared<CollectionBackend>();
backend()->moveToThread(app->database()->thread());
qLog(Debug) << &*backend_ << "moved to thread" << app->database()->thread();
backend()->moveToThread(database->thread());
qLog(Debug) << &*backend_ << "moved to thread" << database->thread();
backend_->Init(app->database(), app->task_manager(), Song::Source::Collection, QLatin1String(kSongsTable), QLatin1String(kDirsTable), QLatin1String(kSubdirsTable));
backend_->Init(database, task_manager, Song::Source::Collection, QLatin1String(kSongsTable), QLatin1String(kDirsTable), QLatin1String(kSubdirsTable));
model_ = new CollectionModel(backend_, app_, this);
model_ = new CollectionModel(backend_, album_cover_loader, this);
ReloadSettings();
@ -107,7 +105,7 @@ void SCollection::Init() {
watcher_thread_->start(QThread::IdlePriority);
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::DirectoryAdded, watcher_, &CollectionWatcher::AddDirectory);
@ -125,9 +123,6 @@ void SCollection::Init() {
QObject::connect(watcher_, &CollectionWatcher::CompilationsNeedUpdating, &*backend_, &CollectionBackend::CompilationsNeedUpdating);
QObject::connect(watcher_, &CollectionWatcher::UpdateLastSeen, &*backend_, &CollectionBackend::UpdateLastSeen);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateLastPlayed, &*backend_, &CollectionBackend::UpdateLastPlayed);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdatePlayCount, &*backend_, &CollectionBackend::UpdatePlayCount);
// This will start the watcher checking for updates
backend_->LoadDirectoriesAsync();
@ -198,8 +193,8 @@ void SCollection::SyncPlaycountAndRatingToFilesAsync() {
void SCollection::SyncPlaycountAndRatingToFiles() {
const int task_id = app_->task_manager()->StartTask(tr("Saving playcounts and ratings"));
app_->task_manager()->SetTaskBlocksCollectionScans(task_id);
const int task_id = task_manager_->StartTask(tr("Saving playcounts and ratings"));
task_manager_->SetTaskBlocksCollectionScans(task_id);
const SongList songs = backend_->GetAllSongs();
const qint64 nb_songs = songs.size();
@ -207,16 +202,16 @@ void SCollection::SyncPlaycountAndRatingToFiles() {
for (const Song &song : songs) {
(void)TagReaderClient::Instance()->SaveSongPlaycountBlocking(song.url().toLocalFile(), song.playcount());
(void)TagReaderClient::Instance()->SaveSongRatingBlocking(song.url().toLocalFile(), song.rating());
app_->task_manager()->SetTaskProgress(task_id, ++i, nb_songs);
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) {
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) {
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"
class QThread;
class Application;
class TaskManager;
class Database;
class Thread;
class CollectionBackend;
class CollectionModel;
class CollectionWatcher;
class AlbumCoverLoader;
class SCollection : public QObject {
Q_OBJECT
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;
static const char *kSongsTable;
@ -86,7 +88,7 @@ class SCollection : public QObject {
void ExitFinished();
private:
Application *app_;
SharedPtr<TaskManager> task_manager_;
SharedPtr<CollectionBackend> backend_;
CollectionModel *model_;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -50,8 +50,6 @@
#include <QDragEnterEvent>
#include <QDropEvent>
#include "core/application.h"
#include "core/player.h"
#include "core/song.h"
#include "core/settings.h"
#include "utilities/strutils.h"
@ -73,7 +71,6 @@ constexpr int kWidgetSpacing = 50;
ContextView::ContextView(QWidget *parent)
: QWidget(parent),
app_(nullptr),
collectionview_(nullptr),
album_cover_choice_controller_(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;
album_cover_choice_controller_ = 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::TotalArtistCountUpdated_, this, &ContextView::UpdateNoSong);

View File

@ -46,9 +46,9 @@ class QDragEnterEvent;
class QDropEvent;
class ResizableTextEdit;
class Application;
class CollectionView;
class AlbumCoverChoiceController;
class LyricsProviders;
class LyricsFetcher;
class ContextView : public QWidget {
@ -57,7 +57,7 @@ class ContextView : public QWidget {
public:
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_; }
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);
private:
Application *app_;
CollectionView *collectionview_;
AlbumCoverChoiceController *album_cover_choice_controller_;
LyricsFetcher *lyrics_fetcher_;

View File

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

View File

@ -36,16 +36,17 @@
#include <QStringList>
#include <QRecursiveMutex>
#include "shared_ptr.h"
#include "sqlquery.h"
class QThread;
class Application;
class TaskManager;
class Database : public QObject {
Q_OBJECT
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;
static const int kSchemaVersion;
@ -102,7 +103,7 @@ class Database : public QObject {
void BackupFile(const QString &filename);
static bool OpenDatabase(const QString &filename, sqlite3 **connection);
Application *app_;
SharedPtr<TaskManager> task_manager_;
// Alias -> filename
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

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/timeutils.h"
#include "utilities/coverutils.h"
#include "utilities/timeconstants.h"
#include "constants/timeconstants.h"
#include "utilities/sqlhelper.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 <QtEvents>
#include "utilities/filenameconstants.h"
#include "constants/filenameconstants.h"
#include "utilities/strutils.h"
#include "utilities/mimeutils.h"
#include "utilities/coveroptions.h"
#include "utilities/coverutils.h"
#include "utilities/screenutils.h"
#include "core/application.h"
#include "core/song.h"
#include "core/iconloader.h"
#include "core/settings.h"
@ -88,7 +87,6 @@ QSet<QString> *AlbumCoverChoiceController::sImageExtensions = nullptr;
AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget *parent)
: QWidget(parent),
app_(nullptr),
cover_searcher_(nullptr),
cover_fetcher_(nullptr),
save_file_dialog_(nullptr),
@ -130,12 +128,20 @@ AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget *parent)
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_searcher_ = new AlbumCoverSearcher(QIcon(u":/pictures/cdcase.png"_s), app, this);
cover_fetcher_ = new AlbumCoverFetcher(cover_providers, network, this);
cover_searcher_ = new AlbumCoverSearcher(QIcon(u":/pictures/cdcase.png"_s), album_cover_loader, this);
cover_searcher_->Init(cover_fetcher_);
QObject::connect(cover_fetcher_, &AlbumCoverFetcher::AlbumCoverFetched, this, &AlbumCoverChoiceController::AlbumCoverFetched);
@ -316,7 +322,7 @@ void AlbumCoverChoiceController::LoadCoverFromURL(Song *song) {
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();
@ -548,11 +554,11 @@ void AlbumCoverChoiceController::SaveArtEmbeddedToSong(Song *song, const bool ar
song->set_art_unset(false);
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()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song);
if (*song == current_albumcover_loader_->last_song()) {
current_albumcover_loader_->LoadAlbumCover(*song);
}
}
@ -567,7 +573,7 @@ void AlbumCoverChoiceController::SaveArtManualToSong(Song *song, const QUrl &art
// Update the backends.
switch (song->source()) {
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;
case Song::Source::LocalFile:
case Song::Source::CDDA:
@ -581,7 +587,7 @@ void AlbumCoverChoiceController::SaveArtManualToSong(Song *song, const QUrl &art
case Song::Source::Tidal:
case Song::Source::Spotify:
case Song::Source::Qobuz:
StreamingServicePtr service = app_->streaming_services()->ServiceBySource(song->source());
StreamingServicePtr service = streaming_services_->ServiceBySource(song->source());
if (!service) break;
if (service->artists_collection_backend()) {
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;
}
if (*song == app_->current_albumcover_loader()->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song);
if (*song == current_albumcover_loader_->last_song()) {
current_albumcover_loader_->LoadAlbumCover(*song);
}
}
@ -611,11 +617,11 @@ void AlbumCoverChoiceController::ClearAlbumCoverForSong(Song *song) {
song->clear_art_manual();
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()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song);
if (*song == current_albumcover_loader_->last_song()) {
current_albumcover_loader_->LoadAlbumCover(*song);
}
}
@ -630,11 +636,11 @@ void AlbumCoverChoiceController::UnsetAlbumCoverForSong(Song *song) {
song->clear_art_automatic();
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()) {
app_->current_albumcover_loader()->LoadAlbumCover(*song);
if (*song == current_albumcover_loader_->last_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) {
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>();
QObject::connect(watcher, &QFutureWatcher<SongList>::finished, this, [this, watcher, cover_filename, image_data, mime_type]() {
const SongList collection_songs = watcher->result();
@ -736,7 +742,7 @@ void AlbumCoverChoiceController::SaveCoverEmbeddedToSong(const Song &song, const
QMutexLocker l(&mutex_cover_save_tasks_);
cover_save_tasks_.append(song);
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); });
}

View File

@ -50,11 +50,16 @@ class QMenu;
class QDragEnterEvent;
class QDropEvent;
class Application;
class NetworkAccessManager;
class CollectionBackend;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class AlbumCoverFetcher;
class AlbumCoverSearcher;
class CoverFromURLDialog;
struct CoverSearchStatistics;
class StreamingServices;
// Controller for the common album cover related menu options.
class AlbumCoverChoiceController : public QWidget {
@ -68,7 +73,13 @@ class AlbumCoverChoiceController : public QWidget {
explicit AlbumCoverChoiceController(QWidget *parent = nullptr);
~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();
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 QSet<QString> *sImageExtensions;
Application *app_;
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
SharedPtr<NetworkAccessManager> network_;
SharedPtr<CollectionBackend> collection_backend_;
SharedPtr<StreamingServices> streaming_services_;
AlbumCoverSearcher *cover_searcher_;
AlbumCoverFetcher *cover_fetcher_;

View File

@ -64,10 +64,10 @@
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/logging.h"
#include "core/application.h"
#include "core/iconloader.h"
#include "core/database.h"
#include "core/settings.h"
#include "core/database.h"
#include "core/networkaccessmanager.h"
#include "utilities/strutils.h"
#include "utilities/fileutils.h"
#include "utilities/imageutils.h"
@ -79,7 +79,6 @@
#include "collection/collectionbackend.h"
#include "collection/collectionquery.h"
#include "playlist/songmimedata.h"
#include "coverproviders.h"
#include "albumcovermanager.h"
#include "albumcoversearcher.h"
#include "albumcoverchoicecontroller.h"
@ -88,6 +87,7 @@
#include "albumcoverfetcher.h"
#include "albumcoverloader.h"
#include "albumcoverloaderresult.h"
#include "coverproviders.h"
#include "coversearchstatistics.h"
#include "coversearchstatisticsdialog.h"
#include "albumcoverimageresult.h"
@ -102,18 +102,28 @@ constexpr char kSettingsGroup[] = "CoverManager";
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),
ui_(new Ui_CoverManager),
mainwindow_(mainwindow),
app_(app),
network_(network),
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)),
timer_album_cover_load_(new QTimer(this)),
filter_all_(nullptr),
filter_with_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_export_(nullptr),
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_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);
// Set up the status bar
@ -241,7 +251,7 @@ void AlbumCoverManager::Init() {
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_);
@ -320,7 +330,7 @@ void AlbumCoverManager::SaveSettings() {
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_tasks_.clear();
cover_save_tasks_.clear();
@ -363,7 +373,7 @@ void AlbumCoverManager::Reset() {
}
void AlbumCoverManager::EnableCoversButtons() {
ui_->button_fetch->setEnabled(app_->cover_providers()->HasAnyProviders());
ui_->button_fetch->setEnabled(cover_providers_->HasAnyProviders());
ui_->export_covers->setEnabled(true);
}
@ -466,7 +476,7 @@ void AlbumCoverManager::LoadAlbumCoverAsync(AlbumItem *album_item) {
cover_options.types = cover_types_;
cover_options.desired_scaled_size = QSize(kThumbnailSize, kThumbnailSize);
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);
}
@ -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_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_->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_->clear_cover_action()->setEnabled(some_with_covers || some_unset);
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:{
for (const QUrl &url : std::as_const(album_item->urls)) {
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]() {
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) {
for (const QUrl &url : urls) {
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]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
});

View File

@ -55,8 +55,11 @@ class QEvent;
class QCloseEvent;
class QShowEvent;
class Application;
class NetworkAccessManager;
class CollectionBackend;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class SongMimeData;
class AlbumCoverExport;
class AlbumCoverExporter;
@ -78,7 +81,15 @@ class AlbumCoverManager : public QMainWindow {
Q_OBJECT
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;
void Reset();
@ -190,8 +201,11 @@ class AlbumCoverManager : public QMainWindow {
private:
Ui_CoverManager *ui_;
QMainWindow *mainwindow_;
Application *app_;
SharedPtr<NetworkAccessManager> network_;
SharedPtr<CollectionBackend> collection_backend_;
SharedPtr<TagReaderClient> tagreader_client_;
SharedPtr<AlbumCoverLoader> album_cover_loader_;
SharedPtr<CoverProviders> cover_providers_;
AlbumCoverChoiceController *album_cover_choice_controller_;
QTimer *timer_album_cover_load_;

View File

@ -47,9 +47,7 @@
#include <QKeySequence>
#include <QtEvents>
#include "core/application.h"
#include "utilities/strutils.h"
#include "utilities/timeutils.h"
#include "utilities/mimeutils.h"
#include "widgets/busyindicator.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),
ui_(new Ui_AlbumCoverSearcher),
app_(app),
album_cover_loader_(album_cover_loader),
model_(new QStandardItemModel(this)),
no_cover_icon_(no_cover_icon),
fetcher_(nullptr),
@ -132,7 +130,7 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon &no_cover_icon, Application *
ui_->covers->setItemDelegate(new SizeOverlayDelegate(this));
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_->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);
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;
item->setIcon(no_cover_icon_);

View File

@ -48,7 +48,7 @@ class QPainter;
class QModelIndex;
class QKeyEvent;
class Application;
class AlbumCoverLoader;
class Ui_AlbumCoverSearcher;
class SizeOverlayDelegate : public QStyledItemDelegate {
@ -65,7 +65,7 @@ class AlbumCoverSearcher : public QDialog {
Q_OBJECT
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;
enum Role {
@ -95,7 +95,7 @@ class AlbumCoverSearcher : public QDialog {
private:
Ui_AlbumCoverSearcher *ui_;
Application *app_;
SharedPtr<AlbumCoverLoader> album_cover_loader_;
QStandardItemModel *model_;
QIcon no_cover_icon_;

View File

@ -25,7 +25,6 @@
#include <QString>
#include "core/shared_ptr.h"
#include "core/application.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 "albumcoverfetcher.h"
class Application;
class NetworkAccessManager;
// Each implementation of this interface downloads covers from one online service.
@ -42,7 +41,7 @@ class CoverProvider : public QObject {
Q_OBJECT
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".
QString name() const { return name_; }
@ -79,7 +78,6 @@ class CoverProvider : public QObject {
using Param = QPair<QString, QString>;
using ParamList = QList<Param>;
Application *app_;
SharedPtr<NetworkAccessManager> network_;
QString name_;
bool enabled_;

View File

@ -29,10 +29,9 @@
#include <QImage>
#include <QStandardPaths>
#include "core/application.h"
#include "core/logging.h"
#include "core/song.h"
#include "core/temporaryfile.h"
#include "playlist/playlistmanager.h"
#include "albumcoverloader.h"
#include "albumcoverloaderresult.h"
#include "currentalbumcoverloader.h"
@ -40,9 +39,9 @@
using std::make_unique;
using namespace Qt::Literals::StringLiterals;
CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(Application *app, QObject *parent)
CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(SharedPtr<AlbumCoverLoader> albumcover_loader, QObject *parent)
: QObject(parent),
app_(app),
albumcover_loader_(albumcover_loader),
temp_file_pattern_(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u"/strawberry-cover-XXXXXX.jpg"_s),
id_(0) {
@ -52,8 +51,7 @@ CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(Application *app, QObject *pare
options_.desired_scaled_size = QSize(120, 120);
options_.default_cover = u":/pictures/cdcase.png"_s;
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &CurrentAlbumCoverLoader::LoadAlbumCover);
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CurrentAlbumCoverLoader::AlbumCoverReady);
QObject::connect(&*albumcover_loader, &AlbumCoverLoader::AlbumCoverLoaded, this, &CurrentAlbumCoverLoader::AlbumCoverReady);
ReloadSettingsAsync();
@ -76,7 +74,7 @@ void CurrentAlbumCoverLoader::ReloadSettings() {
void CurrentAlbumCoverLoader::LoadAlbumCover(const 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 "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/temporaryfile.h"
#include "core/song.h"
#include "albumcoverloaderoptions.h"
#include "albumcoverloaderresult.h"
class Application;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader : public QObject {
Q_OBJECT
public:
explicit CurrentAlbumCoverLoader(Application *app, QObject *parent = nullptr);
explicit CurrentAlbumCoverLoader(SharedPtr<AlbumCoverLoader> albumcover_loader, QObject *parent = nullptr);
~CurrentAlbumCoverLoader() override;
const AlbumCoverLoaderOptions &options() const { return options_; }
@ -61,7 +62,7 @@ class CurrentAlbumCoverLoader : public QObject {
void AlbumCoverReady(const quint64 id, AlbumCoverLoaderResult result);
private:
Application *app_;
SharedPtr<AlbumCoverLoader> albumcover_loader_;
AlbumCoverLoaderOptions options_;
QString temp_file_pattern_;

View File

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

View File

@ -34,13 +34,12 @@
class NetworkAccessManager;
class QNetworkReply;
class Application;
class DeezerCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit DeezerCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit DeezerCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~DeezerCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/logging.h"
#include "core/networkaccessmanager.h"
#include "utilities/cryptutils.h"
@ -58,8 +57,8 @@ const char *DiscogsCoverProvider::kAccessKeyB64 = "dGh6ZnljUGJlZ1NEeXBuSFFxSVk="
const char *DiscogsCoverProvider::kSecretKeyB64 = "ZkFIcmlaSER4aHhRSlF2U3d0bm5ZVmdxeXFLWUl0UXI=";
const int DiscogsCoverProvider::kRequestsDelay = 1000;
DiscogsCoverProvider::DiscogsCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Discogs"_s, false, false, 0.0, false, false, app, network, parent),
DiscogsCoverProvider::DiscogsCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Discogs"_s, false, false, 0.0, false, false, network, parent),
timer_flush_requests_(new QTimer(this)) {
timer_flush_requests_->setInterval(kRequestsDelay);

View File

@ -42,13 +42,12 @@
class NetworkAccessManager;
class QNetworkReply;
class QTimer;
class Application;
class DiscogsCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit DiscogsCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit DiscogsCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~DiscogsCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "coverprovider.h"
#include "jsoncoverprovider.h"
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)
: CoverProvider(name, enabled, authentication_required, quality, batch, allow_missing_album, app, network, 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, network, parent) {}
QJsonObject JsonCoverProvider::ExtractJsonObj(const QByteArray &data) {

View File

@ -30,14 +30,13 @@
#include "core/shared_ptr.h"
#include "coverprovider.h"
class Application;
class NetworkAccessManager;
class JsonCoverProvider : public CoverProvider {
Q_OBJECT
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:
QJsonObject ExtractJsonObj(const QByteArray &data);

View File

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

View File

@ -34,13 +34,12 @@
class NetworkAccessManager;
class QNetworkReply;
class Application;
class LastFmCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit LastFmCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit LastFmCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~LastFmCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "albumcoverfetcher.h"
@ -53,8 +52,8 @@ constexpr int kLimit = 8;
constexpr int kRequestsDelay = 1000;
} // namespace
MusicbrainzCoverProvider::MusicbrainzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"MusicBrainz"_s, true, false, 1.5, true, false, app, network, parent),
MusicbrainzCoverProvider::MusicbrainzCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"MusicBrainz"_s, true, false, 1.5, true, false, network, parent),
timer_flush_requests_(new QTimer(this)) {
timer_flush_requests_->setInterval(kRequestsDelay);

View File

@ -35,14 +35,13 @@
class QNetworkReply;
class QTimer;
class Application;
class NetworkAccessManager;
class MusicbrainzCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit MusicbrainzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit MusicbrainzCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~MusicbrainzCoverProvider() 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;
MusixmatchCoverProvider::MusixmatchCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Musixmatch"_s, true, false, 1.0, true, false, app, network, parent) {}
MusixmatchCoverProvider::MusixmatchCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Musixmatch"_s, true, false, 1.0, true, false, network, parent) {}
MusixmatchCoverProvider::~MusixmatchCoverProvider() {

View File

@ -39,7 +39,7 @@ class MusixmatchCoverProvider : public JsonCoverProvider, MusixmatchProvider {
Q_OBJECT
public:
explicit MusixmatchCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit MusixmatchCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~MusixmatchCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "core/settings.h"
#include "utilities/timeconstants.h"
#include "core/song.h"
#include "constants/timeconstants.h"
#include "albumcoverfetcher.h"
#include "jsoncoverprovider.h"
#include "opentidalcoverprovider.h"
@ -61,8 +61,8 @@ constexpr const int kRequestsDelay = 1000;
using std::make_shared;
OpenTidalCoverProvider::OpenTidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"OpenTidal"_s, true, false, 2.5, true, false, app, network, parent),
OpenTidalCoverProvider::OpenTidalCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"OpenTidal"_s, true, false, 2.5, true, false, network, parent),
login_timer_(new QTimer(this)),
timer_flush_requests_(new QTimer(this)),
login_in_progress_(false),

View File

@ -36,7 +36,6 @@
#include "jsoncoverprovider.h"
class QNetworkReply;
class Application;
class NetworkAccessManager;
class QTimer;
@ -44,7 +43,7 @@ class OpenTidalCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit OpenTidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit OpenTidalCoverProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~OpenTidalCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "core/song.h"
@ -53,9 +52,9 @@ namespace {
constexpr int kLimit = 10;
}
QobuzCoverProvider::QobuzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Qobuz"_s, true, true, 2.0, true, true, app, network, parent),
service_(app->streaming_services()->Service<QobuzService>()) {}
QobuzCoverProvider::QobuzCoverProvider(QobuzServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Qobuz"_s, true, true, 2.0, true, true, network, parent),
service_(service) {}
QobuzCoverProvider::~QobuzCoverProvider() {

View File

@ -35,14 +35,13 @@
#include "qobuz/qobuzservice.h"
class QNetworkReply;
class Application;
class NetworkAccessManager;
class QobuzCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit QobuzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit QobuzCoverProvider(QobuzServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~QobuzCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "streaming/streamingservices.h"
#include "spotify/spotifyservice.h"
#include "albumcoverfetcher.h"
#include "jsoncoverprovider.h"
@ -55,9 +53,9 @@ constexpr char kApiUrl[] = "https://api.spotify.com/v1";
constexpr int kLimit = 10;
} // namespace
SpotifyCoverProvider::SpotifyCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Spotify"_s, true, true, 2.5, true, true, app, network, parent),
service_(app->streaming_services()->Service<SpotifyService>()) {}
SpotifyCoverProvider::SpotifyCoverProvider(SpotifyServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Spotify"_s, true, true, 2.5, true, true, network, parent),
service_(service) {}
SpotifyCoverProvider::~SpotifyCoverProvider() {

View File

@ -39,14 +39,13 @@
#include "spotify/spotifyservice.h"
class QNetworkReply;
class Application;
class NetworkAccessManager;
class SpotifyCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit SpotifyCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit SpotifyCoverProvider(SpotifyServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~SpotifyCoverProvider() 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 "core/shared_ptr.h"
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "core/song.h"
#include "streaming/streamingservices.h"
#include "tidal/tidalservice.h"
#include "albumcoverfetcher.h"
#include "jsoncoverprovider.h"
@ -51,9 +49,9 @@ namespace {
constexpr int kLimit = 10;
}
TidalCoverProvider::TidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Tidal"_s, true, true, 2.5, true, true, app, network, parent),
service_(app->streaming_services()->Service<TidalService>()) {}
TidalCoverProvider::TidalCoverProvider(TidalServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(u"Tidal"_s, true, true, 2.5, true, true, network, parent),
service_(service) {}
TidalCoverProvider::~TidalCoverProvider() {

View File

@ -37,14 +37,13 @@
#include "tidal/tidalservice.h"
class QNetworkReply;
class Application;
class NetworkAccessManager;
class TidalCoverProvider : public JsonCoverProvider {
Q_OBJECT
public:
explicit TidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
explicit TidalCoverProvider(TidalServicePtr service, SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
~TidalCoverProvider() 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 "cddadevice.h"
class Application;
class DeviceLister;
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)
: ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, 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, task_manager, database, album_cover_loader, database_id, first_time, parent),
cdda_song_loader_(url) {
QObject::connect(&cdda_song_loader_, &CddaSongLoader::SongsLoaded, this, &CddaDevice::SongsLoaded);

View File

@ -24,22 +24,23 @@
#include "config.h"
#include <cdio/cdio.h>
#include <gst/audio/gstaudiocdsrc.h>
#include <QObject>
#include <QString>
#include <QStringList>
#include <QUrl>
// These must come after Qt includes
#include <cdio/cdio.h>
#include <gst/audio/gstaudiocdsrc.h>
#include "core/shared_ptr.h"
#include "core/song.h"
#include "core/musicstorage.h"
#include "cddasongloader.h"
#include "connecteddevice.h"
class Application;
class TaskManager;
class Database;
class AlbumCoverLoader;
class DeviceLister;
class DeviceManager;
@ -47,7 +48,7 @@ class CddaDevice : public ConnectedDevice {
Q_OBJECT
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;
void Refresh() override;

View File

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

View File

@ -28,7 +28,7 @@
#include "core/logging.h"
#include "core/shared_ptr.h"
#include "core/application.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "collection/collectionbackend.h"
#include "collection/collectionmodel.h"
@ -41,9 +41,8 @@
using namespace Qt::Literals::StringLiterals;
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),
app_(app),
url_(url),
first_time_(first_time),
lister_(lister),
@ -58,22 +57,22 @@ ConnectedDevice::ConnectedDevice(const QUrl &url, DeviceLister *lister, const QS
// Create the backend in the database thread.
backend_ = make_shared<CollectionBackend>();
backend_->moveToThread(app_->database()->thread());
qLog(Debug) << &*backend_ << "for device" << unique_id_ << "moved to thread" << app_->database()->thread();
backend_->moveToThread(database->thread());
qLog(Debug) << &*backend_ << "for device" << unique_id_ << "moved to thread" << database->thread();
if (url_.scheme() != "cdda"_L1) {
QObject::connect(&*backend_, &CollectionBackend::TotalSongCountUpdated, this, &ConnectedDevice::BackendTotalSongCountUpdated);
}
backend_->Init(app_->database(),
app_->task_manager(),
backend_->Init(database,
task_manager,
Song::Source::Device,
QStringLiteral("device_%1_songs").arg(database_id),
QStringLiteral("device_%1_directories").arg(database_id),
QStringLiteral("device_%1_subdirectories").arg(database_id));
// 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/song.h"
class Application;
class TaskManager;
class Database;
class CollectionBackend;
class CollectionModel;
class DeviceLister;
class DeviceManager;
class AlbumCoverLoader;
using std::enable_shared_from_this;
@ -46,7 +48,7 @@ class ConnectedDevice : public QObject, public virtual MusicStorage, public enab
Q_OBJECT
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; }
@ -81,13 +83,12 @@ class ConnectedDevice : public QObject, public virtual MusicStorage, public enab
void SongCountUpdated(const int count);
void DeviceConnectFinished(const QString &id, const bool success);
void DeviceCloseFinished(const QString &id);
void AddError(const QString &error);
protected:
void InitBackendDirectory(const QString &mount_point, const bool first_time, const bool rewrite_path = true);
protected:
Application *app_;
QUrl url_;
bool first_time_;
DeviceLister *lister_;

View File

@ -48,7 +48,6 @@
#include "core/logging.h"
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/application.h"
#include "core/database.h"
#include "core/iconloader.h"
#include "core/musicstorage.h"
@ -88,20 +87,20 @@ using std::make_unique;
const int DeviceManager::kDeviceIconSize = 32;
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),
app_(app),
task_manager_(task_manager),
not_connected_overlay_(IconLoader::Load(u"edit-delete"_s)) {
setObjectName(QLatin1String(metaObject()->className()));
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
backend_ = make_unique<DeviceDatabaseBackend>();
backend_->moveToThread(app_->database()->thread());
backend_->Init(app_->database());
backend_->moveToThread(database->thread());
backend_->Init(database);
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();
#ifdef Q_OS_WIN32
if (ret.startsWith('/')) ret.remove(0, 1);
if (ret.startsWith(u'/')) ret.remove(0, 1);
#endif
return QDir::toNativeSeparators(ret);
}
@ -627,7 +626,7 @@ SharedPtr<ConnectedDevice> DeviceManager::Connect(DeviceInfo *info) {
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;
}
@ -636,8 +635,10 @@ SharedPtr<ConnectedDevice> DeviceManager::Connect(DeviceInfo *info) {
Q_ARG(QUrl, device_url),
Q_ARG(DeviceLister*, info->BestBackend()->lister_),
Q_ARG(QString, info->BestBackend()->unique_id_),
Q_ARG(SharedPtr<DeviceManager>, app_->device_manager()),
Q_ARG(Application*, app_),
Q_ARG(SharedPtr<DeviceManager>, SharedPtr<DeviceManager>(this)),
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(bool, first_time));
@ -842,7 +843,7 @@ void DeviceManager::DeviceTaskStarted(const int id) {
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();
for (const TaskManager::Task &task : tasks) {

View File

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

View File

@ -48,9 +48,9 @@
#include <QMessageBox>
#include <QtEvents>
#include "core/shared_ptr.h"
#include "core/scoped_ptr.h"
#include "core/iconloader.h"
#include "core/application.h"
#include "core/deletefiles.h"
#include "core/mergedproxymodel.h"
#include "core/mimedata.h"
@ -61,8 +61,8 @@
#include "collection/collectiondirectorymodel.h"
#include "collection/collectionmodel.h"
#include "collection/collectionitemdelegate.h"
#include "connecteddevice.h"
#include "devicelister.h"
#include "connecteddevice.h"
#include "devicemanager.h"
#include "deviceproperties.h"
#include "deviceview.h"
@ -175,7 +175,6 @@ void DeviceItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
DeviceView::DeviceView(QWidget *parent)
: AutoExpandingTreeView(parent),
app_(nullptr),
merged_model_(nullptr),
sort_model_(nullptr),
properties_dialog_(new DeviceProperties),
@ -202,16 +201,16 @@ DeviceView::DeviceView(QWidget *parent)
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);
app_ = app;
task_manager_ = task_manager;
device_manager_ = device_manager;
QObject::connect(&*app_->device_manager(), &DeviceManager::DeviceConnected, this, &DeviceView::DeviceConnected);
QObject::connect(&*app_->device_manager(), &DeviceManager::DeviceDisconnected, this, &DeviceView::DeviceDisconnected);
QObject::connect(&*device_manager_, &DeviceManager::DeviceConnected, this, &DeviceView::DeviceConnected);
QObject::connect(&*device_manager_, &DeviceManager::DeviceDisconnected, this, &DeviceView::DeviceDisconnected);
sort_model_ = new QSortFilterProxyModel(this);
sort_model_->setSourceModel(&*app_->device_manager());
sort_model_->setSourceModel(&*device_manager_);
sort_model_->setDynamicSortFilter(true);
sort_model_->setSortCaseSensitivity(Qt::CaseInsensitive);
sort_model_->sort(0);
@ -222,10 +221,10 @@ void DeviceView::SetApplication(Application *app) {
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_->SetDestinationModel(app_->collection_model()->directory_model());
organize_dialog_ = make_unique<OrganizeDialog>(task_manager, nullptr, this);
organize_dialog_->SetDestinationModel(collection_directory_model);
}
@ -257,8 +256,8 @@ void DeviceView::contextMenuEvent(QContextMenuEvent *e) {
const QModelIndex collection_index = MapToCollection(menu_index_);
if (device_index.isValid()) {
const bool is_plugged_in = app_->device_manager()->GetLister(device_index);
const bool is_remembered = app_->device_manager()->GetDatabaseId(device_index) != -1;
const bool is_plugged_in = device_manager_->GetLister(device_index);
const bool is_remembered = device_manager_->GetDatabaseId(device_index) != -1;
forget_action_->setEnabled(is_remembered);
eject_action_->setEnabled(is_plugged_in);
@ -270,7 +269,7 @@ void DeviceView::contextMenuEvent(QContextMenuEvent *e) {
bool is_filesystem_device = false;
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;
}
@ -309,14 +308,14 @@ QModelIndex DeviceView::MapToCollection(const QModelIndex &merged_model_index) c
void DeviceView::Connect() {
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) {
if (!idx.isValid()) return;
SharedPtr<ConnectedDevice> device = app_->device_manager()->GetConnectedDevice(idx);
SharedPtr<ConnectedDevice> device = device_manager_->GetConnectedDevice(idx);
if (!device) return;
QModelIndex sort_idx = sort_model_->mapFromSource(idx);
@ -341,8 +340,8 @@ void DeviceView::DeviceDisconnected(const QModelIndex &idx) {
void DeviceView::Forget() {
QModelIndex device_idx = MapToDevice(menu_index_);
QString unique_id = app_->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)) {
QString unique_id = device_manager_->data(device_idx, DeviceManager::Role_UniqueId).toString();
if (device_manager_->GetLister(device_idx) && device_manager_->GetLister(device_idx)->AskForScan(unique_id)) {
ScopedPtr<QMessageBox> dialog(new QMessageBox(
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."),
@ -353,7 +352,7 @@ void DeviceView::Forget() {
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 device_index = MapToDevice(merged_index);
if (device_index.isValid()) {
if (!app_->device_manager()->GetConnectedDevice(device_index)) {
if (!device_manager_->GetConnectedDevice(device_index)) {
menu_index_ = merged_index;
Connect();
}
@ -433,7 +432,7 @@ void DeviceView::Delete() {
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);
delete_files->Start(GetSelectedSongs());
@ -456,7 +455,7 @@ void DeviceView::Organize() {
void DeviceView::Unmount() {
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) {

View File

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

View File

@ -27,21 +27,25 @@
#include "core/logging.h"
#include "core/shared_ptr.h"
#include "core/application.h"
#include "core/song.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "collection/collectionbackend.h"
#include "collection/collectionmodel.h"
#include "collection/collectionwatcher.h"
#include "covermanager/albumcoverloader.h"
#include "connecteddevice.h"
#include "devicemanager.h"
#include "filesystemdevice.h"
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()),
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_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_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::DirectoryDeleted, watcher_, &CollectionWatcher::RemoveDirectory);

View File

@ -35,16 +35,18 @@
#include "connecteddevice.h"
class QThread;
class Application;
class TaskManager;
class Database;
class CollectionWatcher;
class DeviceLister;
class DeviceManager;
class AlbumCoverLoader;
class FilesystemDevice : public ConnectedDevice, public virtual FilesystemMusicStorage {
Q_OBJECT
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;
Song::Source source() const final { return Song::Source::Device; }

View File

@ -40,10 +40,12 @@
#include "core/logging.h"
#include "core/shared_ptr.h"
#include "core/application.h"
#include "core/temporaryfile.h"
#include "core/taskmanager.h"
#include "core/database.h"
#include "collection/collectionbackend.h"
#include "collection/collectionmodel.h"
#include "covermanager/albumcoverloader.h"
#include "connecteddevice.h"
#include "gpoddevice.h"
#include "gpodloader.h"
@ -54,8 +56,9 @@ class DeviceManager;
using std::make_shared;
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)
: ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time, 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, task_manager, database, album_cover_loader, database_id, first_time, parent),
task_manager_(task_manager),
loader_(nullptr),
loader_thread_(nullptr),
db_(nullptr),
@ -66,7 +69,7 @@ bool GPodDevice::Init() {
InitBackendDirectory(url_.path(), first_time_);
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_->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() {
@ -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));
g_error_free(error);
qLog(Error) << error_text;
app_->AddError(error_text);
Q_EMIT AddError(error_text);
// Need to remove the track from the db again
itdb_track_remove(track);
@ -286,7 +291,7 @@ bool GPodDevice::WriteDatabase(QString &error_text) {
else {
error_text = tr("Writing database failed.");
}
app_->AddError(error_text);
Q_EMIT AddError(error_text);
}
return success;

View File

@ -42,7 +42,6 @@
#include "gpodloader.h"
class QThread;
class Application;
class DeviceLister;
class DeviceManager;
@ -50,7 +49,7 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
Q_OBJECT
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;
bool Init() override;
@ -86,6 +85,7 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
bool WriteDatabase(QString &error_text);
protected:
SharedPtr <TaskManager> task_manager_;
GPodLoader *loader_;
QThread *loader_thread_;

View File

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

View File

@ -37,7 +37,9 @@
#include "connecteddevice.h"
class QThread;
class Application;
class TaskManager;
class Database;
class AlbumCoverLoader;
class DeviceLister;
class DeviceManager;
class MtpLoader;
@ -48,7 +50,7 @@ class MtpDevice : public ConnectedDevice {
Q_OBJECT
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;
static QStringList url_schemes() { return QStringList() << QStringLiteral("mtp"); }
@ -82,6 +84,8 @@ class MtpDevice : public ConnectedDevice {
private:
static bool sInitializedLibMTP;
SharedPtr<TaskManager> task_manager_;
MtpLoader *loader_;
QThread *loader_thread_;
bool closing_;

View File

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

View File

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

View File

@ -70,7 +70,6 @@
#include <QSettings>
#include <QMimeData>
#include "core/application.h"
#include "core/iconloader.h"
#include "core/logging.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::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),
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)),
#ifdef HAVE_MUSICBRAINZ
tag_fetcher_(new TagFetcher(app->network(), this)),
tag_fetcher_(new TagFetcher(network, this)),
results_dialog_(new TrackSelectionDialog(this)),
#endif
lyrics_fetcher_(new LyricsFetcher(app->lyrics_providers(), this)),
lyrics_fetcher_(new LyricsFetcher(lyrics_providers, this)),
cover_menu_(new QMenu(this)),
image_no_cover_thumbnail_(ImageUtils::GenerateNoCoverImage(QSize(128, 128), devicePixelRatioF())),
loading_(false),
@ -130,7 +138,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
save_tag_pending_(0),
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
QObject::connect(tag_fetcher_, &TagFetcher::ResultAvailable, results_dialog_, &TrackSelectionDialog::FetchTagFinished, Qt::QueuedConnection);
@ -140,7 +148,7 @@ EditTagDialog::EditTagDialog(Application *app, QWidget *parent)
#endif
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_->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::MoveToNextPage).toString(QKeySequence::NativeText)));
new TagCompleter(app_->collection_backend(), Playlist::Column::Artist, ui_->artist);
new TagCompleter(app_->collection_backend(), Playlist::Column::Album, ui_->album);
new TagCompleter(app_->collection_backend(), Playlist::Column::AlbumArtist, ui_->albumartist);
new TagCompleter(app_->collection_backend(), Playlist::Column::Genre, ui_->genre);
new TagCompleter(app_->collection_backend(), Playlist::Column::Composer, ui_->composer);
new TagCompleter(app_->collection_backend(), Playlist::Column::Performer, ui_->performer);
new TagCompleter(app_->collection_backend(), Playlist::Column::Grouping, ui_->grouping);
new TagCompleter(collection_backend, Playlist::Column::Artist, ui_->artist);
new TagCompleter(collection_backend, Playlist::Column::Album, ui_->album);
new TagCompleter(collection_backend, Playlist::Column::AlbumArtist, ui_->albumartist);
new TagCompleter(collection_backend, Playlist::Column::Genre, ui_->genre);
new TagCompleter(collection_backend, Playlist::Column::Composer, ui_->composer);
new TagCompleter(collection_backend, Playlist::Column::Performer, ui_->performer);
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_from_file_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_->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()));
@ -734,10 +742,10 @@ void EditTagDialog::SelectionChanged() {
cover_options.desired_scaled_size = QSize(kSmallImageSize, kSmallImageSize);
cover_options.device_pixel_ratio = devicePixelRatioF();
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 {
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.desired_scaled_size = QSize(kSmallImageSize, kSmallImageSize);
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);
@ -1307,8 +1315,8 @@ void EditTagDialog::SaveData() {
if (ref.current_.is_collection_song()) {
collection_songs_.insert(ref.current_.id(), ref.current_);
}
if (ref.current_ == app_->current_albumcover_loader()->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(ref.current_);
if (ref.current_ == current_albumcover_loader_->last_song()) {
current_albumcover_loader_->LoadAlbumCover(ref.current_);
}
}
@ -1321,7 +1329,7 @@ void EditTagDialog::SaveData() {
void EditTagDialog::SaveDataFinished() {
if (!collection_songs_.isEmpty()) {
app_->collection_backend()->AddOrUpdateSongsAsync(collection_songs_.values());
collection_backend_->AddOrUpdateSongsAsync(collection_songs_.values());
collection_songs_.clear();
}
@ -1483,8 +1491,8 @@ void EditTagDialog::SongSaveTagsComplete(TagReaderReplyPtr reply, const QString
}
collection_songs_.insert(song.id(), song);
}
if (cover_action != UpdateCoverAction::None && song == app_->current_albumcover_loader()->last_song()) {
app_->current_albumcover_loader()->LoadAlbumCover(song);
if (cover_action != UpdateCoverAction::None && song == current_albumcover_loader_->last_song()) {
current_albumcover_loader_->LoadAlbumCover(song);
}
}
else {

View File

@ -51,7 +51,12 @@ class QEvent;
class QShowEvent;
class QHideEvent;
class Application;
class NetworkAccessManager;
class CollectionBackend;
class AlbumCoverLoader;
class CurrentAlbumCoverLoader;
class CoverProviders;
class LyricsProviders;
class AlbumCoverChoiceController;
class Ui_EditTagDialog;
#ifdef HAVE_MUSICBRAINZ
@ -64,7 +69,13 @@ class EditTagDialog : public QDialog {
Q_OBJECT
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;
void SetSongs(const SongList &songs, const PlaylistItemPtrList &items = PlaylistItemPtrList());
@ -180,7 +191,11 @@ class EditTagDialog : public QDialog {
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_;
#ifdef HAVE_MUSICBRAINZ
TagFetcher *tag_fetcher_;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,7 +36,6 @@
#include <QPainter>
#include <QRect>
#include "core/application.h"
#include "core/settings.h"
#include "playlist/playlist.h"
#include "playlist/playlistview.h"
@ -51,14 +50,15 @@
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),
app_(app),
view_(view),
moodbar_loader_(moodbar_loader),
playlist_view_(playlist_view),
enabled_(false),
style_(MoodbarRenderer::MoodbarStyle::Normal) {
QObject::connect(app_, &Application::SettingsChanged, this, &MoodbarItemDelegate::ReloadSettings);
QObject::connect(&*moodbar_loader, &MoodbarLoader::SettingsReloaded, this, &MoodbarItemDelegate::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
QByteArray bytes;
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:
data->state_ = Data::State::CannotLoad;
break;
@ -278,7 +278,7 @@ void MoodbarItemDelegate::ImageLoaded(const QUrl &url, const QImage &image) {
data->pixmap_ = QPixmap::fromImage(image);
data->state_ = Data::State::Loaded;
Playlist *playlist = view_->playlist();
Playlist *playlist = playlist_view_->playlist();
const PlaylistFilter *filter = playlist->filter();
// Update all the indices with the new pixmap.

View File

@ -36,10 +36,10 @@
#include <QSize>
#include <QStyleOption>
#include "core/shared_ptr.h"
class QPainter;
class QModelIndex;
class QPersistentModelIndex;
class Application;
class MoodbarLoader;
class MoodbarPipeline;
class PlaylistView;
@ -47,7 +47,7 @@ class MoodbarItemDelegate : public QItemDelegate {
Q_OBJECT
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;
@ -90,8 +90,8 @@ class MoodbarItemDelegate : public QItemDelegate {
void ReloadAllColors();
private:
Application *app_;
PlaylistView *view_;
SharedPtr<MoodbarLoader> moodbar_loader_;
PlaylistView *playlist_view_;
QCache<QUrl, Data> data_;
bool enabled_;

View File

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

View File

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

View File

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

View File

@ -46,13 +46,13 @@ class QTimeLine;
class QWidget;
class QEvent;
class Application;
class MoodbarProxyStyle : public QProxyStyle {
Q_OBJECT
public:
explicit MoodbarProxyStyle(Application *app, QSlider *slider, QObject *parent = nullptr);
explicit MoodbarProxyStyle(QSlider *slider, QObject *parent = nullptr);
void ReloadSettings();
// QProxyStyle
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);
private Q_SLOTS:
void ReloadSettings();
void FaderValueChanged(qreal value);
void ChangeStyle(QAction *action);
Q_SIGNALS:
void SettingsChanged();
private:
Application *app_;
QSlider *slider_;
bool enabled_;

View File

@ -46,10 +46,9 @@
#include "mpris_common.h"
#include "mpris2.h"
#include "constants/timeconstants.h"
#include "core/song.h"
#include "core/application.h"
#include "core/player.h"
#include "utilities/timeconstants.h"
#include "player/player.h"
#include "engine/enginebase.h"
#include "playlist/playlist.h"
#include "playlist/playlistitem.h"
@ -100,9 +99,11 @@ constexpr char kMprisObjectPath[] = "/org/mpris/MediaPlayer2";
constexpr char kServiceName[] = "org.mpris.MediaPlayer2.strawberry";
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),
app_(app),
player_(player),
playlist_manager_(playlist_manager),
current_albumcover_loader_(current_albumcover_loader),
app_name_(QCoreApplication::applicationName()) {
new Mpris2Root(this);
@ -120,16 +121,16 @@ Mpris2::Mpris2(Application *app, QObject *parent)
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(&*app_->player(), &Player::VolumeChanged, this, &Mpris2::VolumeChanged);
QObject::connect(&*app_->player(), &Player::Seeked, this, &Mpris2::Seeked);
QObject::connect(&*player_->engine(), &EngineBase::StateChanged, this, &Mpris2::EngineStateChanged);
QObject::connect(&*player_, &Player::VolumeChanged, this, &Mpris2::VolumeChanged);
QObject::connect(&*player_, &Player::Seeked, this, &Mpris2::Seeked);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::PlaylistManagerInitialized, this, &Mpris2::PlaylistManagerInitialized);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentSongChanged, this, &Mpris2::CurrentSongChanged);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::PlaylistChanged, this, &Mpris2::PlaylistChangedSlot);
QObject::connect(&*app_->playlist_manager(), &PlaylistManager::CurrentChanged, this, &Mpris2::PlaylistCollectionChanged);
QObject::connect(&*playlist_manager_, &PlaylistManager::PlaylistManagerInitialized, this, &Mpris2::PlaylistManagerInitialized);
QObject::connect(&*playlist_manager_, &PlaylistManager::CurrentSongChanged, this, &Mpris2::CurrentSongChanged);
QObject::connect(&*playlist_manager_, &PlaylistManager::PlaylistChanged, this, &Mpris2::PlaylistChangedSlot);
QObject::connect(&*playlist_manager_, &PlaylistManager::CurrentChanged, this, &Mpris2::PlaylistCollectionChanged);
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
void Mpris2::PlaylistManagerInitialized() {
QObject::connect(app_->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::ShuffleModeChanged, this, &Mpris2::ShuffleModeChanged);
QObject::connect(playlist_manager_->sequence(), &PlaylistSequence::RepeatModeChanged, this, &Mpris2::RepeatModeChanged);
}
void Mpris2::EngineStateChanged(EngineBase::State newState) {
@ -295,7 +296,7 @@ void Mpris2::Raise() { Q_EMIT RaiseMainWindow(); }
void Mpris2::Quit() { QCoreApplication::quit(); }
QString Mpris2::PlaybackStatus() const {
return PlaybackStatus(app_->player()->GetState());
return PlaybackStatus(player_->GetState());
}
QString Mpris2::PlaybackStatus(EngineBase::State state) const {
@ -310,11 +311,11 @@ QString Mpris2::PlaybackStatus(EngineBase::State state) const {
QString Mpris2::LoopStatus() const {
if (!app_->playlist_manager()->sequence()) {
if (!playlist_manager_->sequence()) {
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::Playlist: return u"Playlist"_s;
case PlaylistSequence::RepeatMode::Track: return u"Track"_s;
@ -337,7 +338,7 @@ void Mpris2::SetLoopStatus(const QString &value) {
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) {
if (rate == 0) {
app_->player()->Pause();
player_->Pause();
}
}
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;
}
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_; }
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;
}
@ -378,12 +379,12 @@ void Mpris2::SetRating(double rating) {
rating = -1.0;
}
app_->playlist_manager()->RateCurrentSong(static_cast<float>(rating));
playlist_manager_->RateCurrentSong(static_cast<float>(rating));
}
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...
@ -433,15 +434,15 @@ void Mpris2::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &re
}
double Mpris2::Volume() const {
return app_->player()->GetVolume() / 100.0;
return player_->GetVolume() / 100.0;
}
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 {
return app_->player()->engine()->position_nanosec() / kNsecPerUsec;
return player_->engine()->position_nanosec() / kNsecPerUsec;
}
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; }
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 {
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 {
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.
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 {
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; }
void Mpris2::Next() {
if (CanGoNext()) {
app_->player()->Next();
player_->Next();
}
}
void Mpris2::Previous() {
if (CanGoPrevious()) {
app_->player()->Previous();
player_->Previous();
}
}
void Mpris2::Pause() {
if (CanPause() && app_->player()->GetState() != EngineBase::State::Paused) {
app_->player()->Pause();
if (CanPause() && player_->GetState() != EngineBase::State::Paused) {
player_->Pause();
}
}
void Mpris2::PlayPause() {
if (CanPause()) {
app_->player()->PlayPause();
player_->PlayPause();
}
}
void Mpris2::Stop() { app_->player()->Stop(); }
void Mpris2::Stop() { player_->Stop(); }
void Mpris2::Play() {
if (CanPlay()) {
app_->player()->Play();
player_->Play();
}
}
void Mpris2::Seek(qint64 offset) {
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) {
offset *= kNsecPerUsec;
if (offset < app_->player()->GetCurrentItem()->Metadata().length_nanosec()) {
app_->player()->SeekTo(offset / kNsecPerSec);
if (offset < player_->GetCurrentItem()->Metadata().length_nanosec()) {
player_->SeekTo(offset / kNsecPerSec);
}
}
}
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 {
@ -566,7 +567,7 @@ void Mpris2::GoTo(const QDBusObjectPath &trackId) {
}
quint32 Mpris2::PlaylistCount() const {
return app_->playlist_manager()->GetAllPlaylists().size();
return playlist_manager_->GetAllPlaylists().size();
}
QStringList Mpris2::Orderings() const { return QStringList() << u"User"_s; }
@ -582,14 +583,14 @@ QDBusObjectPath MakePlaylistPath(int id) {
MaybePlaylist Mpris2::ActivePlaylist() const {
MaybePlaylist maybe_playlist;
Playlist *current_playlist = app_->playlist_manager()->current();
Playlist *current_playlist = playlist_manager_->current();
maybe_playlist.valid = current_playlist;
if (!current_playlist) {
return maybe_playlist;
}
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;
}
@ -606,12 +607,12 @@ void Mpris2::ActivatePlaylist(const QDBusObjectPath &playlist_id) {
if (!ok) {
return;
}
if (!app_->playlist_manager()->IsPlaylistOpen(p)) {
if (!playlist_manager_->IsPlaylistOpen(p)) {
qLog(Error) << "Playlist isn't opened!";
return;
}
app_->playlist_manager()->SetActivePlaylist(p);
app_->player()->Next();
playlist_manager_->SetActivePlaylist(p);
player_->Next();
}
@ -620,13 +621,13 @@ MprisPlaylistList Mpris2::GetPlaylists(quint32 index, quint32 max_count, const Q
Q_UNUSED(order);
const QList<Playlist*> playlists = app_->playlist_manager()->GetAllPlaylists();
const QList<Playlist*> playlists = playlist_manager_->GetAllPlaylists();
MprisPlaylistList ret;
ret.reserve(playlists.count());
for (Playlist *p : playlists) {
MprisPlaylist mpris_playlist;
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;
}
@ -642,7 +643,7 @@ void Mpris2::PlaylistChangedSlot(Playlist *playlist) {
MprisPlaylist mpris_playlist;
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);

View File

@ -37,10 +37,13 @@
#include <QDBusArgument>
#include <QJsonObject>
#include "core/shared_ptr.h"
#include "engine/enginebase.h"
#include "covermanager/albumcoverloaderresult.h"
class Application;
class Player;
class PlaylistManager;
class CurrentAlbumCoverLoader;
class Song;
class Playlist;
@ -75,7 +78,7 @@ class Mpris2 : public QObject {
Q_OBJECT
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
Q_PROPERTY(bool CanQuit READ CanQuit)
@ -231,7 +234,9 @@ class Mpris2 : public QObject {
QString DesktopEntryAbsolutePath() const;
private:
Application *app_;
SharedPtr<Player> player_;
SharedPtr<PlaylistManager> playlist_manager_;
SharedPtr<CurrentAlbumCoverLoader> current_albumcover_loader_;
QString app_name_;
QString desktopfilepath_;

View File

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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,6 @@
#include "core/song.h"
#include "playlist/playlistsequence.h"
class Application;
class OSDPretty;
class SystemTrayIcon;
@ -43,7 +42,7 @@ class OSDBase : public QObject {
Q_OBJECT
public:
explicit OSDBase(SharedPtr<SystemTrayIcon> tray_icon, Application *app, QObject *parent = nullptr);
explicit OSDBase(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent = nullptr);
~OSDBase() override;
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 AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
private:
enum class MessageType {
Summary,
@ -91,11 +92,7 @@ class OSDBase : public QObject {
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());
private Q_SLOTS:
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
private:
Application *app_;
SharedPtr<SystemTrayIcon> tray_icon_;
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)
: OSDBase(tray_icon, app, parent),
OSDDBus::OSDDBus(SharedPtr<SystemTrayIcon> tray_icon, QObject *parent)
: OSDBase(tray_icon, parent),
version_(1, 1),
notification_id_(0) {

View File

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

View File

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

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