diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 813922ae4..54f443e23 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -112,6 +112,7 @@ set(SOURCES core/windows7thumbbar.cpp core/screensaver.cpp core/scopedtransaction.cpp + core/translations.cpp engine/enginetype.cpp engine/enginebase.cpp diff --git a/src/collection/collection.cpp b/src/collection/collection.cpp index 6d1fe12a1..727c7f072 100644 --- a/src/collection/collection.cpp +++ b/src/collection/collection.cpp @@ -68,6 +68,7 @@ SCollection::~SCollection() { watcher_->deleteLater(); watcher_thread_->exit(); watcher_thread_->wait(5000 /* five seconds */); + backend_->deleteLater(); } void SCollection::Init() { diff --git a/src/core/database.cpp b/src/core/database.cpp index d16ca7dbe..04daddbcf 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -210,6 +210,7 @@ int Database::FTSNext(sqlite3_tokenizer_cursor *cursor, const char* *token, int void Database::StaticInit() { + if (sFTSTokenizer) return; sFTSTokenizer = new sqlite3_tokenizer_module; sFTSTokenizer->iVersion = 0; sFTSTokenizer->xCreate = &Database::FTSCreate; @@ -241,6 +242,8 @@ Database::Database(Application *app, QObject *parent, const QString &database_na } +Database::~Database() {} + QSqlDatabase Database::Connect() { QMutexLocker l(&connect_mutex_); @@ -273,7 +276,7 @@ QSqlDatabase Database::Connect() { } // Find Sqlite3 functions in the Qt plugin. - StaticInit(); + if (!sFTSTokenizer) StaticInit(); { diff --git a/src/core/database.h b/src/core/database.h index cc4fba405..05ab644e2 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -51,6 +51,7 @@ class Database : public QObject { public: Database(Application *app, QObject *parent = nullptr, const QString &database_name = QString()); + ~Database(); struct AttachedDatabase { AttachedDatabase() {} diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index 4782e1c89..834603eee 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -1799,7 +1799,7 @@ void MainWindow::SongSaveComplete(TagReaderReply *reply, const QPersistentModelI if (reply->is_successful() && index.isValid()) { app_->playlist_manager()->current()->ReloadItems(QList()<< index.row()); } - metaObject()->invokeMethod(reply, "deleteLater", Qt::QueuedConnection); + reply->deleteLater(); } diff --git a/src/core/network.cpp b/src/core/network.cpp index 650359a62..30d29b0b2 100644 --- a/src/core/network.cpp +++ b/src/core/network.cpp @@ -39,12 +39,15 @@ #include "network.h" QMutex ThreadSafeNetworkDiskCache::sMutex; +ThreadSafeNetworkDiskCache *ThreadSafeNetworkDiskCache::sInstance = nullptr; QNetworkDiskCache *ThreadSafeNetworkDiskCache::sCache = nullptr; ThreadSafeNetworkDiskCache::ThreadSafeNetworkDiskCache(QObject *parent) : QAbstractNetworkCache(parent) { + QMutexLocker l(&sMutex); if (!sCache) { + sInstance = this; sCache = new QNetworkDiskCache; #ifdef Q_OS_WIN32 sCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/strawberry/networkcache"); @@ -52,6 +55,11 @@ ThreadSafeNetworkDiskCache::ThreadSafeNetworkDiskCache(QObject *parent) sCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/networkcache"); #endif } + +} + +ThreadSafeNetworkDiskCache::~ThreadSafeNetworkDiskCache() { + if (this == sInstance) delete sCache; } qint64 ThreadSafeNetworkDiskCache::cacheSize() const { diff --git a/src/core/network.h b/src/core/network.h index 001c8ddd7..a9210abf9 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -47,6 +47,7 @@ class QTimerEvent; class ThreadSafeNetworkDiskCache : public QAbstractNetworkCache { public: explicit ThreadSafeNetworkDiskCache(QObject *parent); + ~ThreadSafeNetworkDiskCache(); qint64 cacheSize() const; QIODevice *data(const QUrl &url); @@ -60,6 +61,7 @@ class ThreadSafeNetworkDiskCache : public QAbstractNetworkCache { private: static QMutex sMutex; + static ThreadSafeNetworkDiskCache *sInstance; static QNetworkDiskCache *sCache; }; diff --git a/src/core/qtfslistener.cpp b/src/core/qtfslistener.cpp index 3dbaada85..0c0af194c 100644 --- a/src/core/qtfslistener.cpp +++ b/src/core/qtfslistener.cpp @@ -20,8 +20,11 @@ #include "config.h" +#include #include +#include "core/logging.h" + #include "filesystemwatcherinterface.h" #include "qtfslistener.h" @@ -33,9 +36,7 @@ QtFSListener::QtFSListener(QObject *parent) : FileSystemWatcherInterface(parent) void QtFSListener::AddPath(const QString &path) { watcher_.addPath(path); } -void QtFSListener::RemovePath(const QString &path) { - watcher_.removePath(path); -} +void QtFSListener::RemovePath(const QString &path) { watcher_.removePath(path); } void QtFSListener::Clear() { watcher_.removePaths(watcher_.directories()); diff --git a/src/core/translations.cpp b/src/core/translations.cpp new file mode 100644 index 000000000..66b4fa99c --- /dev/null +++ b/src/core/translations.cpp @@ -0,0 +1,50 @@ +/* + * Strawberry Music Player + * Copyright 2019, Jonas Kvinge + * + * 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 . + * + */ + +#include "config.h" + +#include +#include +#include + +#include "translations.h" +#include "core/potranslator.h" + +Translations::Translations() {} +Translations::~Translations() { + + for (QTranslator *t : translations_) { + QCoreApplication::removeTranslator(t); + delete t; + } + +} + +void Translations::LoadTranslation(const QString &prefix, const QString &path, const QString &language) { + + QTranslator *t = new PoTranslator; + if (t->load(prefix + "_" + language, path)) { + QCoreApplication::installTranslator(t); + translations_ << t; + } + else { + delete t; + } + +} diff --git a/src/core/translations.h b/src/core/translations.h new file mode 100644 index 000000000..6b4bac44a --- /dev/null +++ b/src/core/translations.h @@ -0,0 +1,36 @@ +/* + * Strawberry Music Player + * Copyright 2019, Jonas Kvinge + * + * 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 . + * + */ + +#include "config.h" + +#include +#include +#include +#include + +class Translations : public QObject { + public: + Translations(); + ~Translations(); + void LoadTranslation(const QString &prefix, const QString &path, const QString &language); + + private: + QList translations_; + +}; diff --git a/src/core/utilities.cpp b/src/core/utilities.cpp index 9cc9d4b9c..710591266 100644 --- a/src/core/utilities.cpp +++ b/src/core/utilities.cpp @@ -60,9 +60,6 @@ #include #include #include -#ifdef HAVE_TRANSLATIONS -# include -#endif #ifdef Q_OS_LINUX # include @@ -101,10 +98,6 @@ # include "scoped_cftyperef.h" #endif -#ifdef HAVE_TRANSLATIONS -# include "potranslator.h" -#endif - namespace Utilities { static QString tr(const char *str) { @@ -821,29 +814,6 @@ QString UnicodeToAscii(const QString &unicode) { } -#ifdef HAVE_TRANSLATIONS - -QString SystemLanguageName() { - - QString system_language = QLocale::system().uiLanguages().empty() ? QLocale::system().name() : QLocale::system().uiLanguages().first(); - // uiLanguages returns strings with "-" as separators for language/region; however QTranslator needs "_" separators - system_language.replace("-", "_"); - - return system_language; - -} - -void LoadTranslation(const QString &prefix, const QString &path, const QString &language) { - - QTranslator *t = new PoTranslator; - if (t->load(prefix + "_" + language, path)) - QCoreApplication::installTranslator(t); - else - delete t; - -} -#endif - } // namespace Utilities ScopedWCharArray::ScopedWCharArray(const QString &str) diff --git a/src/core/utilities.h b/src/core/utilities.h index b3d5a1861..428195ca5 100644 --- a/src/core/utilities.h +++ b/src/core/utilities.h @@ -157,11 +157,6 @@ QString DesktopEnvironment(); QString UnicodeToAscii(const QString &unicode); -#ifdef HAVE_TRANSLATIONS -QString SystemLanguageName(); -void LoadTranslation(const QString &prefix, const QString &path, const QString &language); -#endif - } // namespace class ScopedWCharArray { diff --git a/src/covermanager/coverproviders.cpp b/src/covermanager/coverproviders.cpp index 719c18303..a4a8d29d2 100644 --- a/src/covermanager/coverproviders.cpp +++ b/src/covermanager/coverproviders.cpp @@ -31,6 +31,14 @@ CoverProviders::CoverProviders(QObject *parent) : QObject(parent) {} +CoverProviders::~CoverProviders() { + + while (!cover_providers_.isEmpty()) { + delete cover_providers_.firstKey(); + } + +} + void CoverProviders::AddProvider(CoverProvider *provider) { { diff --git a/src/covermanager/coverproviders.h b/src/covermanager/coverproviders.h index 2c3e4a551..11deac09a 100644 --- a/src/covermanager/coverproviders.h +++ b/src/covermanager/coverproviders.h @@ -42,6 +42,7 @@ class CoverProviders : public QObject { public: explicit CoverProviders(QObject *parent = nullptr); + ~CoverProviders(); // Lets a cover provider register itself in the repository. void AddProvider(CoverProvider *provider); diff --git a/src/device/devicelister.cpp b/src/device/devicelister.cpp index 11202e0eb..5b5ca5770 100644 --- a/src/device/devicelister.cpp +++ b/src/device/devicelister.cpp @@ -46,6 +46,7 @@ DeviceLister::~DeviceLister() { if (thread_) { thread_->quit(); thread_->wait(1000); + thread_->deleteLater(); } } diff --git a/src/dialogs/edittagdialog.cpp b/src/dialogs/edittagdialog.cpp index 58945e819..1fa2c5356 100644 --- a/src/dialogs/edittagdialog.cpp +++ b/src/dialogs/edittagdialog.cpp @@ -910,6 +910,6 @@ void EditTagDialog::SongSaveComplete(TagReaderReply *reply, const QString &filen if (pending_ <= 0) AcceptFinished(); - metaObject()->invokeMethod(reply, "deleteLater", Qt::QueuedConnection); + reply->deleteLater(); } diff --git a/src/engine/gststartup.cpp b/src/engine/gststartup.cpp index 77850df22..ea676aacf 100644 --- a/src/engine/gststartup.cpp +++ b/src/engine/gststartup.cpp @@ -43,6 +43,7 @@ GstStartup::GstStartup(QObject *parent) : QObject(parent) { } GstStartup::~GstStartup() { + //gst_deinit(); } void GstStartup::InitialiseGStreamer() { diff --git a/src/internet/internetservices.cpp b/src/internet/internetservices.cpp index b54193ab8..b86927747 100644 --- a/src/internet/internetservices.cpp +++ b/src/internet/internetservices.cpp @@ -31,12 +31,18 @@ #include "internetservice.h" InternetServices::InternetServices(QObject *parent) : QObject(parent) {} -InternetServices::~InternetServices() {} + +InternetServices::~InternetServices() { + + while (!services_.isEmpty()) { + delete services_.take(services_.firstKey()); + } + +} void InternetServices::AddService(InternetService *service) { services_.insert(service->source(), service); - connect(service, SIGNAL(destroyed()), SLOT(ServiceDeleted())); if (service->has_initial_load_settings()) service->InitialLoadSettings(); else service->ReloadSettings(); @@ -50,12 +56,7 @@ void InternetServices::RemoveService(InternetService *service) { services_.remove(service->source()); disconnect(service, 0, this, 0); -} - -void InternetServices::ServiceDeleted() { - - InternetService *service = qobject_cast(sender()); - if (service) RemoveService(service); + qLog(Debug) << "Removed internet service" << service->name(); } diff --git a/src/internet/internetservices.h b/src/internet/internetservices.h index 8f77bc087..283799abb 100644 --- a/src/internet/internetservices.h +++ b/src/internet/internetservices.h @@ -48,9 +48,6 @@ class InternetServices : public QObject { void RemoveService(InternetService *service); void ReloadSettings(); - private slots: - void ServiceDeleted(); - private: QMap services_; diff --git a/src/lyrics/lyricsproviders.cpp b/src/lyrics/lyricsproviders.cpp index 615bf5294..200f936bc 100644 --- a/src/lyrics/lyricsproviders.cpp +++ b/src/lyrics/lyricsproviders.cpp @@ -32,6 +32,14 @@ LyricsProviders::LyricsProviders(QObject *parent) : QObject(parent) {} +LyricsProviders::~LyricsProviders() { + + while (!lyrics_providers_.isEmpty()) { + delete lyrics_providers_.firstKey(); + } + +} + void LyricsProviders::AddProvider(LyricsProvider *provider) { { diff --git a/src/lyrics/lyricsproviders.h b/src/lyrics/lyricsproviders.h index b359c4eb5..7db188137 100644 --- a/src/lyrics/lyricsproviders.h +++ b/src/lyrics/lyricsproviders.h @@ -39,6 +39,8 @@ class LyricsProviders : public QObject { public: explicit LyricsProviders(QObject *parent = nullptr); + ~LyricsProviders(); + void AddProvider(LyricsProvider *provider); void RemoveProvider(LyricsProvider *provider); QList List() const { return lyrics_providers_.keys(); } diff --git a/src/main.cpp b/src/main.cpp index 5a0969d1f..1bef0bd6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -90,7 +90,7 @@ #include "core/networkproxyfactory.h" #include "core/scangiomodulepath.h" #ifdef HAVE_TRANSLATIONS -# include "core/potranslator.h" +# include "core/translations.h" #endif #include "settings/behavioursettingspage.h" @@ -228,12 +228,18 @@ int main(int argc, char* argv[]) { s.endGroup(); } - const QString language = override_language.isEmpty() ? Utilities::SystemLanguageName() : override_language; + QString system_language = QLocale::system().uiLanguages().empty() ? QLocale::system().name() : QLocale::system().uiLanguages().first(); + // uiLanguages returns strings with "-" as separators for language/region; however QTranslator needs "_" separators + system_language.replace("-", "_"); - Utilities::LoadTranslation("qt", QLibraryInfo::location(QLibraryInfo::TranslationsPath), language); - Utilities::LoadTranslation("strawberry", ":/translations", language); - Utilities::LoadTranslation("strawberry", a.applicationDirPath(), language); - Utilities::LoadTranslation("strawberry", QDir::currentPath(), language); + const QString language = override_language.isEmpty() ? system_language : override_language; + + std::unique_ptr translations(new Translations); + + translations->LoadTranslation("qt", QLibraryInfo::location(QLibraryInfo::TranslationsPath), language); + translations->LoadTranslation("strawberry", ":/translations", language); + translations->LoadTranslation("strawberry", a.applicationDirPath(), language); + translations->LoadTranslation("strawberry", QDir::currentPath(), language); #endif Application app; diff --git a/src/moodbar/moodbarproxystyle.cpp b/src/moodbar/moodbarproxystyle.cpp index 79419b617..e2e605903 100644 --- a/src/moodbar/moodbarproxystyle.cpp +++ b/src/moodbar/moodbarproxystyle.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -59,8 +60,11 @@ MoodbarProxyStyle::MoodbarProxyStyle(Application* app, QSlider* slider) connect(app, SIGNAL(SettingsChanged()), SLOT(ReloadSettings())); ReloadSettings(); + } +MoodbarProxyStyle::~MoodbarProxyStyle() {} + void MoodbarProxyStyle::ReloadSettings() { QSettings s; diff --git a/src/moodbar/moodbarproxystyle.h b/src/moodbar/moodbarproxystyle.h index 6c90d99c6..520b5d709 100644 --- a/src/moodbar/moodbarproxystyle.h +++ b/src/moodbar/moodbarproxystyle.h @@ -38,6 +38,7 @@ class MoodbarProxyStyle : public QProxyStyle { public: MoodbarProxyStyle(Application* app, QSlider* slider); + ~MoodbarProxyStyle(); // QProxyStyle void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const; diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index ca15db8d0..e0aeb88e5 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -399,8 +399,7 @@ void Playlist::SongSaveComplete(TagReaderReply *reply, const QPersistentModelInd emit Error(tr("An error occurred writing metadata to '%1'").arg(QString::fromStdString(reply->request_message().save_file_request().filename()))); } } - - metaObject()->invokeMethod(reply, "deleteLater", Qt::QueuedConnection); + reply->deleteLater(); } diff --git a/src/playlist/playlistdelegates.cpp b/src/playlist/playlistdelegates.cpp index 4316a592a..227a74069 100644 --- a/src/playlist/playlistdelegates.cpp +++ b/src/playlist/playlistdelegates.cpp @@ -395,12 +395,17 @@ TagCompleter::TagCompleter(CollectionBackend *backend, Playlist::Column column, } +TagCompleter::~TagCompleter() { + delete model(); +} + void TagCompleter::ModelReady(QFuture future) { TagCompletionModel *model = future.result(); setModel(model); setCaseSensitivity(Qt::CaseInsensitive); editor_->setCompleter(this); + } QWidget *TagCompletionItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const { @@ -409,6 +414,7 @@ QWidget *TagCompletionItemDelegate::createEditor(QWidget *parent, const QStyleOp new TagCompleter(backend_, column_, editor); return editor; + } QString NativeSeparatorsDelegate::displayText(const QVariant &value, const QLocale&) const { diff --git a/src/playlist/playlistdelegates.h b/src/playlist/playlistdelegates.h index 267211418..8eadf00bb 100644 --- a/src/playlist/playlistdelegates.h +++ b/src/playlist/playlistdelegates.h @@ -144,6 +144,7 @@ class TagCompleter : public QCompleter { public: TagCompleter(CollectionBackend *backend, Playlist::Column column, QLineEdit *editor); + ~TagCompleter(); private slots: void ModelReady(QFuture future); diff --git a/src/qobuz/qobuzservice.cpp b/src/qobuz/qobuzservice.cpp index 46565a258..874c1586c 100644 --- a/src/qobuz/qobuzservice.cpp +++ b/src/qobuz/qobuzservice.cpp @@ -180,6 +180,10 @@ QobuzService::~QobuzService() { stream_url_req->deleteLater(); } + artists_collection_backend_->deleteLater(); + albums_collection_backend_->deleteLater(); + songs_collection_backend_->deleteLater(); + } void QobuzService::ShowConfig() { diff --git a/src/scrobbler/scrobblerservices.cpp b/src/scrobbler/scrobblerservices.cpp index 52f4c270b..680e0b1c0 100644 --- a/src/scrobbler/scrobblerservices.cpp +++ b/src/scrobbler/scrobblerservices.cpp @@ -32,14 +32,19 @@ ScrobblerServices::ScrobblerServices(QObject *parent) : QObject(parent) {} -ScrobblerServices::~ScrobblerServices() {} +ScrobblerServices::~ScrobblerServices() { + + while (!scrobbler_services_.isEmpty()) { + delete scrobbler_services_.take(scrobbler_services_.firstKey()); + } + +} void ScrobblerServices::AddService(ScrobblerService *service) { { QMutexLocker locker(&mutex_); scrobbler_services_.insert(service->name(), service); - connect(service, SIGNAL(destroyed()), SLOT(ServiceDestroyed())); } qLog(Debug) << "Registered scrobbler service" << service->name(); @@ -60,13 +65,6 @@ void ScrobblerServices::RemoveService(ScrobblerService *service) { } -void ScrobblerServices::ServiceDestroyed() { - - ScrobblerService *service = static_cast(sender()); - RemoveService(service); - -} - int ScrobblerServices::NextId() { return next_id_.fetchAndAddRelaxed(1); } ScrobblerService *ScrobblerServices::ServiceByName(const QString &name) { diff --git a/src/scrobbler/scrobblerservices.h b/src/scrobbler/scrobblerservices.h index d17f0b55b..b70c155be 100644 --- a/src/scrobbler/scrobblerservices.h +++ b/src/scrobbler/scrobblerservices.h @@ -53,9 +53,6 @@ class ScrobblerServices : public QObject { return static_cast(this->ServiceByName(T::kName)); } - private slots: - void ServiceDestroyed(); - private: Q_DISABLE_COPY(ScrobblerServices); diff --git a/src/subsonic/subsonicservice.cpp b/src/subsonic/subsonicservice.cpp index e25085f61..e0b685577 100644 --- a/src/subsonic/subsonicservice.cpp +++ b/src/subsonic/subsonicservice.cpp @@ -94,7 +94,9 @@ SubsonicService::SubsonicService(Application *app, QObject *parent) } -SubsonicService::~SubsonicService() {} +SubsonicService::~SubsonicService() { + collection_backend_->deleteLater(); +} void SubsonicService::ShowConfig() { app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Subsonic); diff --git a/src/tidal/tidalservice.cpp b/src/tidal/tidalservice.cpp index d4d5849cc..de4d87960 100644 --- a/src/tidal/tidalservice.cpp +++ b/src/tidal/tidalservice.cpp @@ -186,6 +186,10 @@ TidalService::~TidalService() { stream_url_req->deleteLater(); } + artists_collection_backend_->deleteLater(); + albums_collection_backend_->deleteLater(); + songs_collection_backend_->deleteLater(); + } void TidalService::ShowConfig() { diff --git a/src/widgets/trackslider.cpp b/src/widgets/trackslider.cpp index dc5d308d8..61bf3d984 100644 --- a/src/widgets/trackslider.cpp +++ b/src/widgets/trackslider.cpp @@ -72,11 +72,14 @@ TrackSlider::TrackSlider(QWidget* parent) TrackSlider::~TrackSlider() { delete ui_; +#ifdef HAVE_MOODBAR + if (moodbar_style_) moodbar_style_->deleteLater(); +#endif } void TrackSlider::SetApplication(Application* app) { #ifdef HAVE_MOODBAR - moodbar_style_ = new MoodbarProxyStyle(app, ui_->slider); + if (!moodbar_style_) moodbar_style_ = new MoodbarProxyStyle(app, ui_->slider); #endif }