/* SPDX-FileCopyrightText: 2020 (c) Matthieu Gallien SPDX-License-Identifier: LGPL-3.0-or-later */ #include "viewslistdata.h" #include "modeldataloader.h" #include "databaseinterface.h" #include "musiclistenersmanager.h" #include "viewsLogging.h" #include #include #include #include class ViewsListDataPrivate { public: QList mViewsParameters = {{{i18nc("@title:window Title of the view of the playlist", "Now Playing")}, QUrl{QStringLiteral("image://icon/view-media-lyrics")}, ViewManager::ContextView}, {{i18nc("@title:window Title of the view of recently played tracks", "Recently Played")}, QUrl{QStringLiteral("image://icon/media-playlist-play")}, ViewManager::TrackView, ViewManager::GenericDataModel, ElisaUtils::FilterByRecentlyPlayed, ElisaUtils::Track, DataTypes::LastPlayDate, {DataTypes::LastPlayDate}, {i18nc("@title:menu", "Last Played Date")}, Qt::DescendingOrder, {i18nc("@item:inmenu", "Least Recently Played First"), i18nc("@item:inmenu", "Most Recently Played First")}, ViewManager::MultipleAlbum, ViewManager::NoDiscHeaders}, {{i18nc("@title:window Title of the view of frequently played tracks", "Frequently Played")}, QUrl{QStringLiteral("image://icon/view-media-playcount")}, ViewManager::TrackView, ViewManager::GenericDataModel, ElisaUtils::FilterByFrequentlyPlayed, ElisaUtils::Track, DataTypes::PlayCounter, {DataTypes::PlayCounter}, {i18nc("@title:menu", "Play Frequency")}, Qt::DescendingOrder, {i18nc("@item:inmenu", "Least Frequently Played First"), i18nc("@item:inmenu", "Most Frequently Played First")}, ViewManager::MultipleAlbum, ViewManager::NoDiscHeaders}, {{i18nc("@title:window Title of the view of all albums", "Albums")}, QUrl{QStringLiteral("image://icon/view-media-album-cover")}, ViewManager::GridView, ViewManager::GenericDataModel, ElisaUtils::NoFilter, ElisaUtils::Album, DataTypes::TitleRole, {DataTypes::TitleRole, DataTypes::ArtistRole, DataTypes::GenreRole, DataTypes::YearRole}, {i18nc("@title:menu", "Title"), i18nc("@title:menu", "Artist"), i18nc("@title:menu", "Genre"), i18nc("@title:menu", "Year")}, Qt::AscendingOrder, {i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "Oldest First"), i18nc("@item:inmenu", "Newest First")}, QUrl{QStringLiteral("image://icon/media-default-album")}, ViewManager::DelegateWithSecondaryText, ViewManager::ViewShowRating}, {{i18nc("@title:window Title of the view of all artists", "Artists")}, QUrl{QStringLiteral("image://icon/view-media-artist")}, ViewManager::GridView, ViewManager::GenericDataModel, ElisaUtils::NoFilter, ElisaUtils::Artist, Qt::DisplayRole, {Qt::DisplayRole}, {i18nc("@title:menu", "Name")}, Qt::AscendingOrder, {i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A")}, QUrl{QStringLiteral("image://icon/view-media-artist")}, ViewManager::DelegateWithoutSecondaryText, ViewManager::ViewHideRating}, {{i18nc("@title:window Title of the view of all tracks", "Tracks")}, QUrl{QStringLiteral("image://icon/view-media-track")}, ViewManager::TrackView, ViewManager::GenericDataModel, ElisaUtils::NoFilter, ElisaUtils::Track, DataTypes::TitleRole, {DataTypes::TitleRole, DataTypes::AlbumRole, DataTypes::ArtistRole, DataTypes::GenreRole, DataTypes::YearRole, DataTypes::DurationRole, DataTypes::ComposerRole, DataTypes::LyricistRole, DataTypes::FileModificationTime}, {i18nc("@title:menu", "Title"), i18nc("@title:menu", "Album"), i18nc("@title:menu", "Artist"), i18nc("@title:menu", "Genre"), i18nc("@title:menu", "Year"), i18nc("@title:menu", "Duration"), i18nc("@title:menu", "Composer"), i18nc("@title:menu", "Lyricist"), i18nc("@title:menu", "Last Modified")}, Qt::AscendingOrder, {i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "Oldest First"), i18nc("@item:inmenu", "Newest First"), i18nc("@item:inmenu", "Shortest First"), i18nc("@item:inmenu", "Longest First"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A"), i18nc("@item:inmenu", "Oldest First"), i18nc("@item:inmenu", "Newest First")}, ViewManager::MultipleAlbum, ViewManager::NoDiscHeaders}, {{i18nc("@title:window Title of the view of all genres", "Genres")}, QUrl{QStringLiteral("image://icon/view-media-genre")}, ViewManager::GridView, ViewManager::GenericDataModel, ElisaUtils::NoFilter, ElisaUtils::Genre, Qt::DisplayRole, {Qt::DisplayRole}, {i18nc("@title:menu", "Genre")}, Qt::AscendingOrder, {i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A")}, QUrl{QStringLiteral("image://icon/view-media-genre")}, ViewManager::DelegateWithoutSecondaryText, ViewManager::ViewHideRating}, {{i18nc("@title:window Title of the file browser view", "Files")}, QUrl{QStringLiteral("image://icon/document-open-folder")}, ViewManager::GridView, ViewManager::FileBrowserModel, ElisaUtils::NoFilter, ElisaUtils::FileName, QUrl{QStringLiteral("image://icon/document-open-folder")}, ViewManager::DelegateWithoutSecondaryText, ViewManager::ViewHideRating, QUrl::fromLocalFile(QDir::rootPath()) }, {{i18nc("@title:window Title of the file radios browser view", "Radio Stations")}, QUrl{QStringLiteral("image://icon/radio")}, ViewManager::TrackView, ViewManager::GenericDataModel, ElisaUtils::NoFilter, ElisaUtils::Radio, Qt::DisplayRole, {Qt::DisplayRole}, {i18nc("@title:menu", "Name")}, Qt::AscendingOrder, {i18nc("@item:inmenu", "A-Z"), i18nc("@item:inmenu", "Z-A")}, ViewManager::MultipleAlbum, ViewManager::NoDiscHeaders}}; const int mNumOfBaseViews = mViewsParameters.count(); QMap mDefaultIcons = {{ElisaUtils::Album, QUrl{QStringLiteral("image://icon/view-media-album-cover")}}, {ElisaUtils::Artist, QUrl{QStringLiteral("image://icon/view-media-artist")}}, {ElisaUtils::Genre, QUrl{QStringLiteral("image://icon/view-media-genre")}},}; ElisaUtils::PlayListEntryType mEmbeddedCategory = ElisaUtils::Unknown; ModelDataLoader *mDataLoader = nullptr; MusicListenersManager *mManager = nullptr; DatabaseInterface *mDatabase = nullptr; }; ViewsListData::ViewsListData(QObject *parent) : QObject(parent) , d(std::make_unique()) { d->mDataLoader = new ModelDataLoader; connect(this, &ViewsListData::destroyed, d->mDataLoader, &ModelDataLoader::deleteLater); } ViewsListData::~ViewsListData() = default; int ViewsListData::count() const { return d->mViewsParameters.count(); } bool ViewsListData::isEmpty() const { return d->mViewsParameters.isEmpty(); } const ViewParameters &ViewsListData::viewParameters(int index) const { return d->mViewsParameters[index]; } const QString &ViewsListData::title(int index) const { return d->mViewsParameters[index].mMainTitle; } const QString &ViewsListData::secondTitle(int index) const { return d->mViewsParameters[index].mSecondaryTitle; } bool ViewsListData::useSecondTitle(int index) const { return d->mViewsParameters[index].mUseSecondTitle; } const QUrl &ViewsListData::iconUrl(int index) const { return d->mViewsParameters[index].mMainImage; } qulonglong ViewsListData::databaseId(int index) const { return d->mViewsParameters[index].mDataFilter.databaseId(); } bool ViewsListData::defaultEntry(int index) const { return d->mEmbeddedCategory == ElisaUtils::Unknown || d->mViewsParameters[index].mEntryType != d->mEmbeddedCategory; } ElisaUtils::PlayListEntryType ViewsListData::dataType(int index) const { return d->mViewsParameters[index].mDataType; } ElisaUtils::PlayListEntryType ViewsListData::embeddedCategory() const { return d->mEmbeddedCategory; } void ViewsListData::setEmbeddedCategory(ElisaUtils::PlayListEntryType aEmbeddedView) { if (d->mEmbeddedCategory != aEmbeddedView) { d->mEmbeddedCategory = aEmbeddedView; Q_EMIT embeddedCategoryChanged(); refreshEmbeddedCategory(); } } void ViewsListData::genresAdded(const DataTypes::ListGenreDataType &newData) { if (d->mEmbeddedCategory != ElisaUtils::Genre) { return; } if (!newData.size()) { return; } Q_EMIT dataAboutToBeAdded(d->mViewsParameters.size(), d->mViewsParameters.size() + newData.size() - 1); for (const auto &oneGenre : newData) { d->mViewsParameters.push_back({oneGenre.title(), QUrl{QStringLiteral("image://icon/view-media-genre")}, ViewManager::GridView, ViewManager::GenericDataModel, ElisaUtils::FilterByGenre, oneGenre.databaseId(), ElisaUtils::Artist, ElisaUtils::Genre, QUrl{QStringLiteral("image://icon/view-media-artist")}, ViewManager::DelegateWithoutSecondaryText, ViewManager::ViewHideRating}); } Q_EMIT dataAdded(); } void ViewsListData::artistsAdded(const DataTypes::ListArtistDataType &newData) { if (d->mEmbeddedCategory != ElisaUtils::Artist) { return; } if (!newData.size()) { return; } Q_EMIT dataAboutToBeAdded(d->mViewsParameters.size(), d->mViewsParameters.size() + newData.size() - 1); for (const auto &oneArtist : newData) { d->mViewsParameters.push_back({oneArtist.name(), oneArtist.artistArtURI(), ViewManager::GridView, ViewManager::GenericDataModel, ElisaUtils::FilterByArtist, oneArtist.databaseId(), ElisaUtils::Album, ElisaUtils::Artist, QUrl{QStringLiteral("image://icon/media-default-album")}, ViewManager::DelegateWithSecondaryText, ViewManager::ViewShowRating}); } Q_EMIT dataAdded(); } void ViewsListData::artistRemoved(qulonglong removedDatabaseId) { if (d->mEmbeddedCategory != ElisaUtils::Artist) { return; } for (int i = 0; i < d->mViewsParameters.count(); ++i) { const auto &data = d->mViewsParameters[i]; if (data.mDataFilter.databaseId() == removedDatabaseId) { Q_EMIT dataAboutToBeRemoved(i, i); d->mViewsParameters.removeAt(i); Q_EMIT dataRemoved(); break; } } } void ViewsListData::albumsAdded(const DataTypes::ListAlbumDataType &newData) { if (d->mEmbeddedCategory != ElisaUtils::Album) { return; } if (!newData.size()) { return; } Q_EMIT dataAboutToBeAdded(d->mViewsParameters.size(), d->mViewsParameters.size() + newData.size() - 1); for (const auto &oneAlbum : newData) { auto coverImage = oneAlbum.albumArtURI(); if (!coverImage.isValid()) { coverImage = d->mDefaultIcons[d->mEmbeddedCategory]; } d->mViewsParameters.push_back({oneAlbum.title(), coverImage, ViewManager::TrackView, ViewManager::GenericDataModel, ElisaUtils::FilterById, oneAlbum.databaseId(), ElisaUtils::Track, ElisaUtils::Album, Qt::DisplayRole, {Qt::DisplayRole}, {QStringLiteral("Title")}, Qt::AscendingOrder, {QStringLiteral("A-Z"), QStringLiteral("Z-A")}, ViewManager::SingleAlbum, ViewManager::DiscHeaders}); } Q_EMIT dataAdded(); } void ViewsListData::albumRemoved(qulonglong removedDatabaseId) { if (d->mEmbeddedCategory != ElisaUtils::Album) { return; } for (int i = 0; i < d->mViewsParameters.count(); ++i) { const auto &data = d->mViewsParameters[i]; if (data.mDataFilter.databaseId() == removedDatabaseId) { Q_EMIT dataAboutToBeRemoved(i, i); d->mViewsParameters.removeAt(i); Q_EMIT dataRemoved(); break; } } } void ViewsListData::albumModified(const DataTypes::AlbumDataType &modifiedAlbum) { if (d->mEmbeddedCategory != ElisaUtils::Album) { return; } for (int i = 0; i < d->mViewsParameters.count(); ++i) { auto &data = d->mViewsParameters[i]; if (data.mDataFilter.databaseId() == modifiedAlbum.databaseId()) { data.mMainTitle = modifiedAlbum.title(); if (modifiedAlbum.albumArtURI().isValid()) { data.mMainImage = modifiedAlbum.albumArtURI(); } else { data.mMainImage = d->mDefaultIcons[d->mEmbeddedCategory]; } data.mSecondaryTitle = modifiedAlbum.artist(); Q_EMIT dataModified(i); break; } } } void ViewsListData::clearEmbeddedItems() { if (d->mViewsParameters.count() > d->mNumOfBaseViews) { const int startIndex = d->mNumOfBaseViews; const int numToRemove = d->mViewsParameters.count() - startIndex; Q_EMIT dataAboutToBeRemoved(startIndex, d->mViewsParameters.count() - 1); d->mViewsParameters.remove(startIndex, numToRemove); Q_EMIT dataRemoved(); } } void ViewsListData::cleanedDatabase() { qCDebug(orgKdeElisaViews) << "ViewsListData::cleanedDatabase" << d->mEmbeddedCategory; clearEmbeddedItems(); } void ViewsListData::refreshEmbeddedCategory() { clearEmbeddedItems(); switch (d->mEmbeddedCategory) { case ElisaUtils::Album: case ElisaUtils::Artist: case ElisaUtils::Genre: Q_EMIT needData(d->mEmbeddedCategory); break; case ElisaUtils::Radio: case ElisaUtils::Track: case ElisaUtils::Unknown: case ElisaUtils::Composer: case ElisaUtils::FileName: case ElisaUtils::Lyricist: case ElisaUtils::Container: case ElisaUtils::PlayList: break; } } MusicListenersManager* ViewsListData::manager() const { return d->mManager; } void ViewsListData::setManager(MusicListenersManager *aManager) { if (d->mManager != aManager) { d->mManager = aManager; Q_EMIT managerChanged(); d->mManager->connectModel(d->mDataLoader); setDatabase(d->mManager->viewDatabase()); } } DatabaseInterface* ViewsListData::database() const { return d->mDatabase; } void ViewsListData::setDatabase(DatabaseInterface *aDatabase) { if (d->mDatabase != aDatabase) { d->mDatabase = aDatabase; Q_EMIT databaseChanged(); d->mDataLoader->setDatabase(aDatabase); connect(d->mDataLoader, &ModelDataLoader::allAlbumsData, this, &ViewsListData::albumsAdded); connect(d->mDataLoader, &ModelDataLoader::allArtistsData, this, &ViewsListData::artistsAdded); connect(d->mDataLoader, &ModelDataLoader::allGenresData, this, &ViewsListData::genresAdded); connect(d->mDatabase, &DatabaseInterface::genresAdded, this, &ViewsListData::genresAdded); connect(d->mDatabase, &DatabaseInterface::artistsAdded, this, &ViewsListData::artistsAdded); connect(d->mDatabase, &DatabaseInterface::artistRemoved, this, &ViewsListData::artistRemoved); connect(d->mDatabase, &DatabaseInterface::albumsAdded, this, &ViewsListData::albumsAdded); connect(d->mDatabase, &DatabaseInterface::albumRemoved, this, &ViewsListData::albumRemoved); connect(d->mDatabase, &DatabaseInterface::albumModified, this, &ViewsListData::albumModified); connect(d->mDatabase, &DatabaseInterface::cleanedDatabase, this, &ViewsListData::cleanedDatabase); connect(this, &ViewsListData::needData, d->mDataLoader, &ModelDataLoader::loadData); refreshEmbeddedCategory(); } } #include "moc_viewslistdata.cpp"