diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -71,8 +71,6 @@ ../src/elisautils.cpp ) -ecm_qt_declare_logging_category(mediaplaylistTest_SOURCES HEADER elisa_debug.h IDENTIFIER lcModelTest CATEGORY_NAME qt.modeltest) - ecm_add_test(${mediaplaylistTest_SOURCES} TEST_NAME "mediaplaylistTest" LINK_LIBRARIES @@ -98,22 +96,30 @@ datamodeltest.cpp ) -ecm_qt_declare_logging_category(datamodeltest_SOURCES HEADER elisa_debug.h IDENTIFIER lcModelTest CATEGORY_NAME qt.modeltest) - ecm_add_test(${datamodeltest_SOURCES} TEST_NAME "datamodeltest" LINK_LIBRARIES Qt5::Test elisaLib Qt5::CorePrivate ) target_include_directories(datamodeltest PRIVATE ${CMAKE_SOURCE_DIR}/src) +set(viewsmodeltest_SOURCES + viewsmodeltest.cpp +) + +ecm_add_test(${viewsmodeltest_SOURCES} + TEST_NAME "viewsmodeltest" + LINK_LIBRARIES + Qt5::Test elisaLib Qt5::CorePrivate +) + +target_include_directories(viewsmodeltest PRIVATE ${CMAKE_SOURCE_DIR}/src) + set(trackmetadatamodeltest_SOURCES trackmetadatamodeltest.cpp ) -ecm_qt_declare_logging_category(trackmetadatamodeltest_SOURCES HEADER elisa_debug.h IDENTIFIER lcModelTest CATEGORY_NAME qt.modeltest) - ecm_add_test(${trackmetadatamodeltest_SOURCES} TEST_NAME "trackmetadatamodeltest" LINK_LIBRARIES @@ -126,8 +132,6 @@ alltracksproxymodeltest.cpp ) -ecm_qt_declare_logging_category(alltracksproxymodeltest_SOURCES HEADER elisa_debug.h IDENTIFIER lcModelTest CATEGORY_NAME qt.modeltest) - ecm_add_test(${alltracksproxymodeltest_SOURCES} TEST_NAME "alltracksproxymodeltest" LINK_LIBRARIES diff --git a/autotests/datamodeltest.cpp b/autotests/datamodeltest.cpp --- a/autotests/datamodeltest.cpp +++ b/autotests/datamodeltest.cpp @@ -1134,6 +1134,8 @@ musicDb.insertTracksList(mNewTracks, mNewCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 7); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1147,6 +1149,8 @@ musicDb.removeTracksList({firstTrack[DatabaseInterface::ResourceRole].toUrl()}); + beginRemoveRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 6); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1193,6 +1197,8 @@ musicDb.insertTracksList(mNewTracks, mNewCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 7); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1216,6 +1222,8 @@ musicDb.insertTracksList(newTracks, mNewCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 8); QCOMPARE(beginInsertRowsSpy.count(), 2); QCOMPARE(endInsertRowsSpy.count(), 2); @@ -1273,6 +1281,8 @@ musicDb.insertTracksList(mNewTracks, mNewCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 1); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1332,6 +1342,8 @@ musicDb.insertTracksList(mNewTracks, mNewCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 4); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1392,6 +1404,8 @@ musicDb.insertTracksList(mNewTracks, mNewCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 2); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1451,6 +1465,8 @@ artistsModel.initialize(nullptr, &musicDb, ElisaUtils::Track, ElisaUtils::FilterById, {}, {}, albumId); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 4); QCOMPARE(beginInsertRowsSpy.count(), 1); QCOMPARE(endInsertRowsSpy.count(), 1); @@ -1483,6 +1499,8 @@ musicDb.insertTracksList(newTracks, newCovers); + beginInsertRowsSpy.wait(); + QCOMPARE(artistsModel.rowCount(), 5); QCOMPARE(beginInsertRowsSpy.count(), 2); QCOMPARE(endInsertRowsSpy.count(), 2); diff --git a/autotests/viewsmodeltest.cpp b/autotests/viewsmodeltest.cpp new file mode 100644 --- /dev/null +++ b/autotests/viewsmodeltest.cpp @@ -0,0 +1,539 @@ +/* + * Copyright 2015-2017 Matthieu Gallien + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "databasetestdata.h" + +#include "databaseinterface.h" +#include "models/viewsmodel.h" +#include "musicaudiotrack.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +class ViewsModelTests : public QObject, public DatabaseTestData +{ + Q_OBJECT + +private Q_SLOTS: + + void initTestCase() + { + qRegisterMetaType>("QHash"); + qRegisterMetaType>("QHash"); + qRegisterMetaType>("QList"); + qRegisterMetaType>("QVector"); + qRegisterMetaType>("QHash"); + } + + void switchToEmbeddedGenreCategory() + { + DatabaseInterface musicDb; + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + musicDb.init(QStringLiteral("testDb")); + + viewsModel.setDatabase(&musicDb); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + musicDb.insertTracksList(mNewTracks, mNewCovers); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllGenres); + + beginInsertRowsSpy.wait(); + + QCOMPARE(beginInsertRowsSpy.count(), 1); + QCOMPARE(endInsertRowsSpy.count(), 1); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 12); + + viewsModel.setEmbeddedCategory(ViewManager::NoView); + + QCOMPARE(beginInsertRowsSpy.count(), 2); + QCOMPARE(endInsertRowsSpy.count(), 2); + QCOMPARE(beginRemoveRowsSpy.count(), 2); + QCOMPARE(endRemoveRowsSpy.count(), 2); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + } + + void switchToEmbeddedGenreCategoryWithInsert() + { + DatabaseInterface musicDb; + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + musicDb.init(QStringLiteral("testDb")); + + viewsModel.setDatabase(&musicDb); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllGenres); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + musicDb.insertTracksList(mNewTracks, mNewCovers); + + beginInsertRowsSpy.wait(); + + QCOMPARE(beginInsertRowsSpy.count(), 4); + QCOMPARE(endInsertRowsSpy.count(), 4); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 12); + + auto newTracks = QList{ + {true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), + QStringLiteral("artist2"), QStringLiteral("album3"), {}, + 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/test/$23"))}, + QDateTime::fromMSecsSinceEpoch(23), + QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, + QStringLiteral("genre7"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, + {true, QStringLiteral("$24"), QStringLiteral("0"), QStringLiteral("track7"), + QStringLiteral("artist3"), QStringLiteral("album3"), {}, + 7, 1, QTime::fromMSecsSinceStartOfDay(24), {QUrl::fromLocalFile(QStringLiteral("/test/$24"))}, + QDateTime::fromMSecsSinceEpoch(24), + QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, + QStringLiteral("genre6"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, + {true, QStringLiteral("$25"), QStringLiteral("0"), QStringLiteral("track8"), + QStringLiteral("artist4"), QStringLiteral("album3"), {}, + 8, 1, QTime::fromMSecsSinceStartOfDay(25), {QUrl::fromLocalFile(QStringLiteral("/test/$25"))}, + QDateTime::fromMSecsSinceEpoch(25), + QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, + QStringLiteral("genre5"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}}; + + auto newCovers = mNewCovers; + newCovers[QStringLiteral("/test/$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); + newCovers[QStringLiteral("/test/$24")] = QUrl::fromLocalFile(QStringLiteral("album3")); + newCovers[QStringLiteral("/test/$25")] = QUrl::fromLocalFile(QStringLiteral("album3")); + + musicDb.insertTracksList(newTracks, newCovers); + + beginInsertRowsSpy.wait(); + + QCOMPARE(beginInsertRowsSpy.count(), 7); + QCOMPARE(endInsertRowsSpy.count(), 7); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 15); + + viewsModel.setEmbeddedCategory(ViewManager::NoView); + + QCOMPARE(beginInsertRowsSpy.count(), 8); + QCOMPARE(endInsertRowsSpy.count(), 8); + QCOMPARE(beginRemoveRowsSpy.count(), 2); + QCOMPARE(endRemoveRowsSpy.count(), 2); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + } + + void switchToEmbeddedAlbumCategoryWithInsertAndRemove() + { + DatabaseInterface musicDb; + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + musicDb.init(QStringLiteral("testDb")); + + viewsModel.setDatabase(&musicDb); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllAlbums); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + musicDb.insertTracksList(mNewTracks, mNewCovers); + + beginInsertRowsSpy.wait(); + + QCOMPARE(beginInsertRowsSpy.count(), 1); + QCOMPARE(endInsertRowsSpy.count(), 1); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 13); + + auto newTracks = QList{ + {true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), + QStringLiteral("artist2"), QStringLiteral("album8"), {}, + 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/test/$23"))}, + QDateTime::fromMSecsSinceEpoch(23), + QUrl::fromLocalFile(QStringLiteral("album8")), 5, true, + QStringLiteral("genre7"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, + {true, QStringLiteral("$24"), QStringLiteral("0"), QStringLiteral("track7"), + QStringLiteral("artist3"), QStringLiteral("album9"), {}, + 7, 1, QTime::fromMSecsSinceStartOfDay(24), {QUrl::fromLocalFile(QStringLiteral("/test/$24"))}, + QDateTime::fromMSecsSinceEpoch(24), + QUrl::fromLocalFile(QStringLiteral("album9")), 5, true, + QStringLiteral("genre6"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, + {true, QStringLiteral("$25"), QStringLiteral("0"), QStringLiteral("track8"), + QStringLiteral("artist4"), QStringLiteral("album10"), {}, + 8, 1, QTime::fromMSecsSinceStartOfDay(25), {QUrl::fromLocalFile(QStringLiteral("/test/$25"))}, + QDateTime::fromMSecsSinceEpoch(25), + QUrl::fromLocalFile(QStringLiteral("album10")), 5, true, + QStringLiteral("genre5"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}}; + + auto newCovers = mNewCovers; + newCovers[QStringLiteral("/test/$23")] = QUrl::fromLocalFile(QStringLiteral("album8")); + newCovers[QStringLiteral("/test/$24")] = QUrl::fromLocalFile(QStringLiteral("album9")); + newCovers[QStringLiteral("/test/$25")] = QUrl::fromLocalFile(QStringLiteral("album10")); + + musicDb.insertTracksList(newTracks, newCovers); + + beginInsertRowsSpy.wait(); + + QCOMPARE(beginInsertRowsSpy.count(), 2); + QCOMPARE(endInsertRowsSpy.count(), 2); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 16); + + musicDb.removeTracksList({{QUrl::fromLocalFile(QStringLiteral("/test/$23"))}, + {QUrl::fromLocalFile(QStringLiteral("/test/$24"))}, + {QUrl::fromLocalFile(QStringLiteral("/test/$25"))}}); + + beginRemoveRowsSpy.wait(); + + QCOMPARE(beginInsertRowsSpy.count(), 2); + QCOMPARE(endInsertRowsSpy.count(), 2); + QCOMPARE(beginRemoveRowsSpy.count(), 4); + QCOMPARE(endRemoveRowsSpy.count(), 4); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 13); + + viewsModel.setEmbeddedCategory(ViewManager::NoView); + + QCOMPARE(beginInsertRowsSpy.count(), 3); + QCOMPARE(endInsertRowsSpy.count(), 3); + QCOMPARE(beginRemoveRowsSpy.count(), 5); + QCOMPARE(endRemoveRowsSpy.count(), 5); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + } + + void simpleSwitchToEmbeddedAlbumCategory() + { + DatabaseInterface musicDb; + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + musicDb.init(QStringLiteral("testDb")); + + viewsModel.setDatabase(&musicDb); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllAlbums); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + QCOMPARE(viewsModel.data(viewsModel.index(0, 0), Qt::DisplayRole), QStringLiteral("Now Playing")); + QCOMPARE(viewsModel.data(viewsModel.index(1, 0), Qt::DisplayRole), QStringLiteral("Recently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(2, 0), Qt::DisplayRole), QStringLiteral("Frequently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(3, 0), Qt::DisplayRole), QStringLiteral("Artists")); + QCOMPARE(viewsModel.data(viewsModel.index(4, 0), Qt::DisplayRole), QStringLiteral("Tracks")); + QCOMPARE(viewsModel.data(viewsModel.index(5, 0), Qt::DisplayRole), QStringLiteral("Genres")); + QCOMPARE(viewsModel.data(viewsModel.index(6, 0), Qt::DisplayRole), QStringLiteral("Files")); + QCOMPARE(viewsModel.data(viewsModel.index(7, 0), Qt::DisplayRole), QStringLiteral("Radios")); + } + + void simpleSwitchToEmbeddedArtistCategory() + { + DatabaseInterface musicDb; + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + musicDb.init(QStringLiteral("testDb")); + + viewsModel.setDatabase(&musicDb); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllArtists); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + QCOMPARE(viewsModel.data(viewsModel.index(0, 0), Qt::DisplayRole), QStringLiteral("Now Playing")); + QCOMPARE(viewsModel.data(viewsModel.index(1, 0), Qt::DisplayRole), QStringLiteral("Recently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(2, 0), Qt::DisplayRole), QStringLiteral("Frequently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(3, 0), Qt::DisplayRole), QStringLiteral("Albums")); + QCOMPARE(viewsModel.data(viewsModel.index(4, 0), Qt::DisplayRole), QStringLiteral("Tracks")); + QCOMPARE(viewsModel.data(viewsModel.index(5, 0), Qt::DisplayRole), QStringLiteral("Genres")); + QCOMPARE(viewsModel.data(viewsModel.index(6, 0), Qt::DisplayRole), QStringLiteral("Files")); + QCOMPARE(viewsModel.data(viewsModel.index(7, 0), Qt::DisplayRole), QStringLiteral("Radios")); + } + + void simpleSwitchToEmbeddedGenreCategory() + { + DatabaseInterface musicDb; + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + musicDb.init(QStringLiteral("testDb")); + + viewsModel.setDatabase(&musicDb); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllGenres); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + QCOMPARE(viewsModel.data(viewsModel.index(0, 0), Qt::DisplayRole), QStringLiteral("Now Playing")); + QCOMPARE(viewsModel.data(viewsModel.index(1, 0), Qt::DisplayRole), QStringLiteral("Recently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(2, 0), Qt::DisplayRole), QStringLiteral("Frequently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(3, 0), Qt::DisplayRole), QStringLiteral("Albums")); + QCOMPARE(viewsModel.data(viewsModel.index(4, 0), Qt::DisplayRole), QStringLiteral("Artists")); + QCOMPARE(viewsModel.data(viewsModel.index(5, 0), Qt::DisplayRole), QStringLiteral("Tracks")); + QCOMPARE(viewsModel.data(viewsModel.index(6, 0), Qt::DisplayRole), QStringLiteral("Files")); + QCOMPARE(viewsModel.data(viewsModel.index(7, 0), Qt::DisplayRole), QStringLiteral("Radios")); + } + + void simpleSwitchToEmbeddedAlbumCategoryWithoutDatabase() + { + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllAlbums); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + QCOMPARE(viewsModel.data(viewsModel.index(0, 0), Qt::DisplayRole), QStringLiteral("Now Playing")); + QCOMPARE(viewsModel.data(viewsModel.index(1, 0), Qt::DisplayRole), QStringLiteral("Recently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(2, 0), Qt::DisplayRole), QStringLiteral("Frequently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(3, 0), Qt::DisplayRole), QStringLiteral("Artists")); + QCOMPARE(viewsModel.data(viewsModel.index(4, 0), Qt::DisplayRole), QStringLiteral("Tracks")); + QCOMPARE(viewsModel.data(viewsModel.index(5, 0), Qt::DisplayRole), QStringLiteral("Genres")); + QCOMPARE(viewsModel.data(viewsModel.index(6, 0), Qt::DisplayRole), QStringLiteral("Files")); + QCOMPARE(viewsModel.data(viewsModel.index(7, 0), Qt::DisplayRole), QStringLiteral("Radios")); + } + + void simpleSwitchToEmbeddedArtistCategoryWithoutDatabase() + { + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllArtists); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + QCOMPARE(viewsModel.data(viewsModel.index(0, 0), Qt::DisplayRole), QStringLiteral("Now Playing")); + QCOMPARE(viewsModel.data(viewsModel.index(1, 0), Qt::DisplayRole), QStringLiteral("Recently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(2, 0), Qt::DisplayRole), QStringLiteral("Frequently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(3, 0), Qt::DisplayRole), QStringLiteral("Albums")); + QCOMPARE(viewsModel.data(viewsModel.index(4, 0), Qt::DisplayRole), QStringLiteral("Tracks")); + QCOMPARE(viewsModel.data(viewsModel.index(5, 0), Qt::DisplayRole), QStringLiteral("Genres")); + QCOMPARE(viewsModel.data(viewsModel.index(6, 0), Qt::DisplayRole), QStringLiteral("Files")); + QCOMPARE(viewsModel.data(viewsModel.index(7, 0), Qt::DisplayRole), QStringLiteral("Radios")); + } + + void simpleSwitchToEmbeddedGenreCategoryWithoutDatabase() + { + ViewsModel viewsModel; + QAbstractItemModelTester testModel(&viewsModel); + + QSignalSpy beginInsertRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeInserted); + QSignalSpy endInsertRowsSpy(&viewsModel, &ViewsModel::rowsInserted); + QSignalSpy beginRemoveRowsSpy(&viewsModel, &ViewsModel::rowsAboutToBeRemoved); + QSignalSpy endRemoveRowsSpy(&viewsModel, &ViewsModel::rowsRemoved); + QSignalSpy dataChangedSpy(&viewsModel, &ViewsModel::dataChanged); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 0); + QCOMPARE(endRemoveRowsSpy.count(), 0); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 9); + + viewsModel.setEmbeddedCategory(ViewManager::AllGenres); + + QCOMPARE(beginInsertRowsSpy.count(), 0); + QCOMPARE(endInsertRowsSpy.count(), 0); + QCOMPARE(beginRemoveRowsSpy.count(), 1); + QCOMPARE(endRemoveRowsSpy.count(), 1); + QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(viewsModel.rowCount(), 8); + + QCOMPARE(viewsModel.data(viewsModel.index(0, 0), Qt::DisplayRole), QStringLiteral("Now Playing")); + QCOMPARE(viewsModel.data(viewsModel.index(1, 0), Qt::DisplayRole), QStringLiteral("Recently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(2, 0), Qt::DisplayRole), QStringLiteral("Frequently Played")); + QCOMPARE(viewsModel.data(viewsModel.index(3, 0), Qt::DisplayRole), QStringLiteral("Albums")); + QCOMPARE(viewsModel.data(viewsModel.index(4, 0), Qt::DisplayRole), QStringLiteral("Artists")); + QCOMPARE(viewsModel.data(viewsModel.index(5, 0), Qt::DisplayRole), QStringLiteral("Tracks")); + QCOMPARE(viewsModel.data(viewsModel.index(6, 0), Qt::DisplayRole), QStringLiteral("Files")); + QCOMPARE(viewsModel.data(viewsModel.index(7, 0), Qt::DisplayRole), QStringLiteral("Radios")); + } +}; + +QTEST_GUILESS_MAIN(ViewsModelTests) + +#include "viewsmodeltest.moc" diff --git a/src/elisa_core.kcfg b/src/elisa_core.kcfg --- a/src/elisa_core.kcfg +++ b/src/elisa_core.kcfg @@ -8,4 +8,14 @@ + + + + + + + + + + diff --git a/src/elisaapplication.h b/src/elisaapplication.h --- a/src/elisaapplication.h +++ b/src/elisaapplication.h @@ -24,6 +24,8 @@ #include "elisautils.h" +#include "viewmanager.h" + #include #include @@ -49,6 +51,10 @@ WRITE setArguments NOTIFY argumentsChanged) + Q_PROPERTY(ViewManager::ViewsType embeddedView + READ embeddedView + NOTIFY embeddedViewChanged) + Q_PROPERTY(MusicListenersManager *musicManager READ musicManager NOTIFY musicManagerChanged) @@ -100,6 +106,8 @@ ManageHeaderBar *manageHeaderBar() const; + ViewManager::ViewsType embeddedView() const; + Q_SIGNALS: void argumentsChanged(); @@ -123,6 +131,8 @@ void initializationDone(); + void embeddedViewChanged(); + public Q_SLOTS: void appHelpActivated(); diff --git a/src/elisaapplication.cpp b/src/elisaapplication.cpp --- a/src/elisaapplication.cpp +++ b/src/elisaapplication.cpp @@ -438,7 +438,7 @@ bool ElisaApplication::eventFilter(QObject *object, QEvent *event) { - Q_UNUSED(object); + Q_UNUSED(object) QKeyEvent *keyEvent = static_cast(event); auto playPauseAction = d->mCollection.action(tr("Play-Pause")); @@ -484,4 +484,27 @@ return d->mManageHeaderBar.get(); } +ViewManager::ViewsType ElisaApplication::embeddedView() const +{ + ViewManager::ViewsType result = ViewManager::NoView; + + switch (Elisa::ElisaConfiguration::self()->embeddedView()) + { + case 0: + result = ViewManager::NoView; + break; + case 1: + result = ViewManager::AllAlbums; + break; + case 2: + result = ViewManager::AllArtists; + break; + case 3: + result = ViewManager::AllGenres; + break; + } + + return result; +} + #include "moc_elisaapplication.cpp" diff --git a/src/models/datamodel.cpp b/src/models/datamodel.cpp --- a/src/models/datamodel.cpp +++ b/src/models/datamodel.cpp @@ -409,39 +409,39 @@ d->mDataLoader.setDatabase(database); connect(&d->mDataLoader, &ModelDataLoader::allTracksData, - this, &DataModel::tracksAdded); + this, &DataModel::tracksAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::allRadiosData, - this, &DataModel::radiosAdded); + this, &DataModel::radiosAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::allAlbumsData, - this, &DataModel::albumsAdded); + this, &DataModel::albumsAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::allArtistsData, - this, &DataModel::artistsAdded); + this, &DataModel::artistsAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::allGenresData, - this, &DataModel::genresAdded); + this, &DataModel::genresAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::genresAdded, - this, &DataModel::genresAdded); + this, &DataModel::genresAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::albumsAdded, - this, &DataModel::albumsAdded); + this, &DataModel::albumsAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::albumModified, - this, &DataModel::albumModified); + this, &DataModel::albumModified, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::albumRemoved, - this, &DataModel::albumRemoved); + this, &DataModel::albumRemoved, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::tracksAdded, - this, &DataModel::tracksAdded); + this, &DataModel::tracksAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::trackModified, - this, &DataModel::trackModified); + this, &DataModel::trackModified, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::trackRemoved, - this, &DataModel::trackRemoved); + this, &DataModel::trackRemoved, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::artistsAdded, - this, &DataModel::artistsAdded); + this, &DataModel::artistsAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::artistRemoved, - this, &DataModel::artistRemoved); + this, &DataModel::artistRemoved, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::radioAdded, - this, &DataModel::radioAdded); + this, &DataModel::radioAdded, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::radioModified, - this, &DataModel::radioModified); + this, &DataModel::radioModified, Qt::QueuedConnection); connect(&d->mDataLoader, &ModelDataLoader::radioRemoved, - this, &DataModel::radioRemoved); + this, &DataModel::radioRemoved, Qt::QueuedConnection); } void DataModel::tracksAdded(ListTrackDataType newData) diff --git a/src/models/viewsmodel.h b/src/models/viewsmodel.h --- a/src/models/viewsmodel.h +++ b/src/models/viewsmodel.h @@ -26,17 +26,34 @@ #include +class MusicListenersManager; +class DatabaseInterface; class ViewsModelPrivate; class ELISALIB_EXPORT ViewsModel : public QAbstractListModel { Q_OBJECT -public: + Q_PROPERTY(ViewManager::ViewsType embeddedCategory + READ embeddedCategory + WRITE setEmbeddedCategory + NOTIFY embeddedCategoryChanged) + + Q_PROPERTY(MusicListenersManager* manager + READ manager + WRITE setManager + NOTIFY managerChanged) + + Q_PROPERTY(DatabaseInterface* database + READ database + WRITE setDatabase + NOTIFY databaseChanged) +public: enum ColumnRoles { ItemType = Qt::UserRole + 1, ImageName, + UseColorOverlay, }; explicit ViewsModel(QObject *parent = nullptr); @@ -57,14 +74,48 @@ Q_INVOKABLE int indexFromViewType(ViewManager::ViewsType type); - Q_INVOKABLE QString viewMainTitle(ViewManager::ViewsType type, QString suggestedMainTitle) const; + Q_INVOKABLE QString viewMainTitle(int index, QString suggestedMainTitle) const; + + Q_INVOKABLE QUrl viewImageUrl(int index, QUrl suggestedImageUrl) const; + + ViewManager::ViewsType embeddedCategory() const; + + MusicListenersManager* manager() const; + + DatabaseInterface* database() const; + +Q_SIGNALS: + + void embeddedCategoryChanged(); + + void managerChanged(); - Q_INVOKABLE QUrl viewImageUrl(ViewManager::ViewsType type, QUrl suggestedImageUrl) const; + void databaseChanged(); + +public Q_SLOTS: + + void setEmbeddedCategory(ViewManager::ViewsType aEmbeddedView); + + void setManager(MusicListenersManager *aManager); + + void setDatabase(DatabaseInterface *aDatabase); + +private Q_SLOTS: + + void secondaryModelRowsAboutToBeInserted(const QModelIndex &parent, int first, int last); + + void secondaryModelRowsInserted(const QModelIndex &parent, int first, int last); + + void secondaryModelRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); + + void secondaryModelRowsRemoved(const QModelIndex &parent, int first, int last); private: + void createEmbeddedCategoryModel(ViewManager::ViewsType aEmbeddedCategory); - std::unique_ptr d; + void clearEmbeddedCategoryModel(); + std::unique_ptr d; }; #endif // VIEWSMODEL_H diff --git a/src/models/viewsmodel.cpp b/src/models/viewsmodel.cpp --- a/src/models/viewsmodel.cpp +++ b/src/models/viewsmodel.cpp @@ -17,56 +17,71 @@ #include "viewsmodel.h" +#include "datamodel.h" #include "viewmanager.h" +#include "musiclistenersmanager.h" +#include "databaseinterface.h" #include +#include #include +#include + class ViewsModelPrivate { public: - QList mTypes; QHash mNames; QHash mIcons; + ViewManager::ViewsType mEmbeddedCategory = ViewManager::NoView; + + int mRemovedCategoryIndex = -1; + + std::unique_ptr mSecondaryModel; + + MusicListenersManager *mManager = nullptr; + + DatabaseInterface *mDatabase = nullptr; + ViewsModelPrivate() { - mTypes = {ViewManager::Context, ViewManager::RecentlyPlayedTracks, - ViewManager::FrequentlyPlayedTracks, ViewManager::AllAlbums, - ViewManager::AllArtists, ViewManager::AllTracks, - ViewManager::AllGenres, ViewManager::FilesBrowser, - ViewManager::RadiosBrowser}; - - mNames = {{ViewManager::Context, {i18nc("Title of the view of the playlist", "Now Playing")}}, - {ViewManager::RecentlyPlayedTracks, {i18nc("Title of the view of recently played tracks", "Recently Played")}}, - {ViewManager::FrequentlyPlayedTracks, {i18nc("Title of the view of frequently played tracks", "Frequently Played")}}, - {ViewManager::AllAlbums, {i18nc("Title of the view of all albums", "Albums")}}, - {ViewManager::AllArtists, {i18nc("Title of the view of all artists", "Artists")}}, - {ViewManager::AllTracks, {i18nc("Title of the view of all tracks", "Tracks")}}, - {ViewManager::AllGenres, {i18nc("Title of the view of all genres", "Genres")}}, - {ViewManager::FilesBrowser, {i18nc("Title of the file browser view", "Files")}}, - {ViewManager::RadiosBrowser, {i18nc("Title of the file radios browser view", "Radios")}}}; - - mIcons = {{ViewManager::Context, QUrl{QStringLiteral("image://icon/view-media-lyrics")}}, - {ViewManager::RecentlyPlayedTracks, QUrl{QStringLiteral("image://icon/media-playlist-play")}}, - {ViewManager::FrequentlyPlayedTracks, QUrl{QStringLiteral("image://icon/view-media-playcount")}}, - {ViewManager::AllAlbums, QUrl{QStringLiteral("image://icon/view-media-album-cover")}}, - {ViewManager::AllArtists, QUrl{QStringLiteral("image://icon/view-media-artist")}}, - {ViewManager::AllTracks, QUrl{QStringLiteral("image://icon/view-media-track")}}, - {ViewManager::AllGenres, QUrl{QStringLiteral("image://icon/view-media-genre")}}, - {ViewManager::FilesBrowser, QUrl{QStringLiteral("image://icon/document-open-folder")}}, - {ViewManager::RadiosBrowser, QUrl{QStringLiteral("image://icon/radio")}}}; + mTypes = { ViewManager::Context, ViewManager::RecentlyPlayedTracks, + ViewManager::FrequentlyPlayedTracks, ViewManager::AllAlbums, + ViewManager::AllArtists, ViewManager::AllTracks, + ViewManager::AllGenres, ViewManager::FilesBrowser, + ViewManager::RadiosBrowser }; + + mNames = { { ViewManager::Context, { i18nc("Title of the view of the playlist", "Now Playing") } }, + { ViewManager::RecentlyPlayedTracks, { i18nc("Title of the view of recently played tracks", "Recently Played") } }, + { ViewManager::FrequentlyPlayedTracks, { i18nc("Title of the view of frequently played tracks", "Frequently Played") } }, + { ViewManager::AllAlbums, { i18nc("Title of the view of all albums", "Albums") } }, + { ViewManager::AllArtists, { i18nc("Title of the view of all artists", "Artists") } }, + { ViewManager::AllTracks, { i18nc("Title of the view of all tracks", "Tracks") } }, + { ViewManager::AllGenres, { i18nc("Title of the view of all genres", "Genres") } }, + { ViewManager::FilesBrowser, { i18nc("Title of the file browser view", "Files") } }, + { ViewManager::RadiosBrowser, { i18nc("Title of the file radios browser view", "Radios") } } }; + + mIcons = { { ViewManager::Context, QUrl { QStringLiteral("image://icon/view-media-lyrics") } }, + { ViewManager::RecentlyPlayedTracks, QUrl { QStringLiteral("image://icon/media-playlist-play") } }, + { ViewManager::FrequentlyPlayedTracks, QUrl { QStringLiteral("image://icon/view-media-playcount") } }, + { ViewManager::AllAlbums, QUrl { QStringLiteral("image://icon/view-media-album-cover") } }, + { ViewManager::AllArtists, QUrl { QStringLiteral("image://icon/view-media-artist") } }, + { ViewManager::AllTracks, QUrl { QStringLiteral("image://icon/view-media-track") } }, + { ViewManager::AllGenres, QUrl { QStringLiteral("image://icon/view-media-genre") } }, + { ViewManager::FilesBrowser, QUrl { QStringLiteral("image://icon/document-open-folder") } }, + { ViewManager::RadiosBrowser, QUrl { QStringLiteral("image://icon/radio") } } }; } - }; ViewsModel::ViewsModel(QObject *parent) - : QAbstractListModel(parent), d(std::make_unique()) + : QAbstractListModel(parent) + , d(std::make_unique()) { } @@ -78,6 +93,7 @@ result[ItemType] = "type"; result[ImageName] = "image"; + result[UseColorOverlay] = "useColorOverlay"; return result; } @@ -93,32 +109,139 @@ int ViewsModel::rowCount(const QModelIndex &parent) const { + Q_ASSERT(checkIndex(parent)); + if (parent.isValid()) { return 0; } - return d->mTypes.count(); + switch (d->mEmbeddedCategory) { + case ViewManager::AllAlbums: + case ViewManager::AllArtists: + case ViewManager::AllGenres: + if (d->mSecondaryModel) { + return d->mTypes.count() - 1 + d->mSecondaryModel->rowCount(); + } else { + return d->mTypes.count() - 1; + } + case ViewManager::NoView: + case ViewManager::OneArtist: + case ViewManager::OneArtistFromGenre: + case ViewManager::OneAlbum: + case ViewManager::OneAlbumFromArtist: + case ViewManager::OneAlbumFromArtistAndGenre: + case ViewManager::AllTracks: + case ViewManager::AllArtistsFromGenre: + case ViewManager::RecentlyPlayedTracks: + case ViewManager::FrequentlyPlayedTracks: + case ViewManager::FilesBrowser: + case ViewManager::Context: + case ViewManager::RadiosBrowser: + return d->mTypes.count(); + } + + return 0; } QVariant ViewsModel::data(const QModelIndex &index, int role) const { - auto result = QVariant{}; + auto result = QVariant {}; if (!index.isValid()) { return result; } - switch(role) - { - case Qt::DisplayRole: - result = d->mNames[d->mTypes[index.row()]]; - break; - case ColumnRoles::ImageName: - result = d->mIcons[d->mTypes[index.row()]]; - break; - case ColumnRoles::ItemType: - result = d->mTypes[index.row()]; - break; + auto modelRow = index.row(); + + if (d->mEmbeddedCategory == ViewManager::AllAlbums || d->mEmbeddedCategory == ViewManager::AllArtists || d->mEmbeddedCategory == ViewManager::AllGenres) { + if (modelRow >= d->mRemovedCategoryIndex) { + ++modelRow; + } + } + + if (modelRow < d->mTypes.size()) { + switch (role) { + case Qt::DisplayRole: + result = d->mNames[d->mTypes[modelRow]]; + break; + case ColumnRoles::ImageName: + result = d->mIcons[d->mTypes[modelRow]]; + break; + case ColumnRoles::ItemType: + result = d->mTypes[modelRow]; + break; + case UseColorOverlay: + result = true; + break; + } + } else { + switch (role) { + case Qt::DisplayRole: + result = d->mSecondaryModel->data(d->mSecondaryModel->index(modelRow - d->mTypes.size(), 0), role); + break; + case ColumnRoles::ImageName: + { + const auto &imageUrl = d->mSecondaryModel->data(d->mSecondaryModel->index(modelRow - d->mTypes.size(), 0), DatabaseInterface::ColumnsRoles::ImageUrlRole); + if (!imageUrl.isNull()) { + result = imageUrl; + } else { + switch (d->mEmbeddedCategory) + { + case ViewManager::AllAlbums: + case ViewManager::AllArtists: + case ViewManager::AllGenres: + result = d->mIcons[d->mEmbeddedCategory]; + break; + case ViewManager::OneAlbum: + case ViewManager::OneAlbumFromArtist: + case ViewManager::OneAlbumFromArtistAndGenre: + case ViewManager::OneArtist: + case ViewManager::OneArtistFromGenre: + case ViewManager::AllTracks: + case ViewManager::AllArtistsFromGenre: + case ViewManager::FrequentlyPlayedTracks: + case ViewManager::RecentlyPlayedTracks: + case ViewManager::RadiosBrowser: + case ViewManager::FilesBrowser: + case ViewManager::Context: + case ViewManager::NoView: + break; + } + } + break; + } + case ColumnRoles::ItemType: + switch (d->mEmbeddedCategory) + { + case ViewManager::AllAlbums: + result = ViewManager::OneAlbum; + break; + case ViewManager::AllArtists: + result = ViewManager::OneArtist; + break; + case ViewManager::AllGenres: + result = ViewManager::AllArtistsFromGenre; + break; + case ViewManager::OneAlbum: + case ViewManager::OneAlbumFromArtist: + case ViewManager::OneAlbumFromArtistAndGenre: + case ViewManager::OneArtist: + case ViewManager::OneArtistFromGenre: + case ViewManager::AllTracks: + case ViewManager::AllArtistsFromGenre: + case ViewManager::FrequentlyPlayedTracks: + case ViewManager::RecentlyPlayedTracks: + case ViewManager::RadiosBrowser: + case ViewManager::FilesBrowser: + case ViewManager::Context: + case ViewManager::NoView: + break; + } + break; + case UseColorOverlay: + result = false; + break; + } } return result; @@ -152,22 +275,42 @@ int ViewsModel::indexFromViewType(ViewManager::ViewsType type) { - switch(type) + switch (type) { case ViewManager::Context: return 0; case ViewManager::RecentlyPlayedTracks: return 1; case ViewManager::FrequentlyPlayedTracks: return 2; case ViewManager::AllAlbums: - return 3; + switch (d->mEmbeddedCategory) { + case ViewManager::AllAlbums: + return -1; + default: + return 3; + } case ViewManager::AllArtists: - return 4; + switch (d->mEmbeddedCategory) { + case ViewManager::AllAlbums: + return 3; + case ViewManager::AllArtists: + return -1; + default: + return 4; + } case ViewManager::AllTracks: return 5; case ViewManager::AllGenres: - return 6; + switch (d->mEmbeddedCategory) { + case ViewManager::AllAlbums: + case ViewManager::AllArtists: + return 5; + case ViewManager::AllGenres: + return -1; + default: + return 6; + } case ViewManager::FilesBrowser: return 7; case ViewManager::RadiosBrowser: @@ -178,37 +321,216 @@ case ViewManager::OneArtistFromGenre: case ViewManager::OneAlbumFromArtistAndGenre: case ViewManager::AllArtistsFromGenre: + case ViewManager::NoView: break; } return -1; } -QString ViewsModel::viewMainTitle(ViewManager::ViewsType type, QString suggestedMainTitle) const +QString ViewsModel::viewMainTitle(int index, QString suggestedMainTitle) const { auto result = std::move(suggestedMainTitle); if (!result.isEmpty()) { return result; } - result = d->mNames[type]; + if (d->mEmbeddedCategory == ViewManager::AllAlbums || d->mEmbeddedCategory == ViewManager::AllArtists || d->mEmbeddedCategory == ViewManager::AllGenres) { + if (index >= d->mRemovedCategoryIndex) { + ++index; + } + } + + if (index < d->mTypes.size()) { + result = d->mNames[d->mTypes[index]]; + } else { + result= d->mSecondaryModel->data(d->mSecondaryModel->index(index - d->mTypes.size(), 0), Qt::DisplayRole).toString(); + } return result; } -QUrl ViewsModel::viewImageUrl(ViewManager::ViewsType type, QUrl suggestedImageUrl) const +QUrl ViewsModel::viewImageUrl(int index, QUrl suggestedImageUrl) const { auto result = std::move(suggestedImageUrl); if (!result.isEmpty()) { return result; } - result = d->mIcons[type]; + if (index < d->mTypes.size()) { + result = d->mIcons[d->mTypes[index]]; + } else { + result= d->mSecondaryModel->data(d->mSecondaryModel->index(index - d->mTypes.size(), 0), ViewsModel::ImageName).toUrl(); + } return result; } +ViewManager::ViewsType ViewsModel::embeddedCategory() const +{ + return d->mEmbeddedCategory; +} + +MusicListenersManager* ViewsModel::manager() const +{ + return d->mManager; +} + +DatabaseInterface* ViewsModel::database() const +{ + return d->mDatabase; +} + +void ViewsModel::setEmbeddedCategory(ViewManager::ViewsType aEmbeddedView) +{ + if (d->mEmbeddedCategory != ViewManager::NoView) { + clearEmbeddedCategoryModel(); + } + + createEmbeddedCategoryModel(aEmbeddedView); + + Q_EMIT embeddedCategoryChanged(); +} + +void ViewsModel::setManager(MusicListenersManager *aManager) +{ + d->mManager = aManager; + Q_EMIT managerChanged(); + + if ((d->mManager || d->mDatabase) && d->mEmbeddedCategory != ViewManager::NoView && + !d->mSecondaryModel) { + createEmbeddedCategoryModel(d->mEmbeddedCategory); + } +} + +void ViewsModel::setDatabase(DatabaseInterface *aDatabase) +{ + d->mDatabase = aDatabase; + Q_EMIT databaseChanged(); +} + +void ViewsModel::secondaryModelRowsAboutToBeInserted(const QModelIndex &parent, int first, int last) +{ + Q_UNUSED(parent) + + beginInsertRows({}, d->mTypes.size() - 1 + first, d->mTypes.size() - 1 + last); +} + +void ViewsModel::secondaryModelRowsInserted(const QModelIndex &parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + endInsertRows(); +} + +void ViewsModel::secondaryModelRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) +{ + Q_UNUSED(parent) + + beginRemoveRows({}, d->mTypes.size() - 1 + first, d->mTypes.size() - 1 + last); +} + +void ViewsModel::secondaryModelRowsRemoved(const QModelIndex &parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + endRemoveRows(); +} + +void ViewsModel::createEmbeddedCategoryModel(ViewManager::ViewsType aEmbeddedCategory) +{ + if (aEmbeddedCategory != ViewManager::AllAlbums && aEmbeddedCategory != ViewManager::AllArtists && aEmbeddedCategory != ViewManager::AllGenres) { + d->mEmbeddedCategory = aEmbeddedCategory; + return; + } + + if (d->mSecondaryModel) { + return; + } + + if (d->mEmbeddedCategory != aEmbeddedCategory && !d->mSecondaryModel) { + d->mRemovedCategoryIndex = indexFromViewType(aEmbeddedCategory); + beginRemoveRows({}, d->mRemovedCategoryIndex, d->mRemovedCategoryIndex); + d->mEmbeddedCategory = aEmbeddedCategory; + if (d->mManager || d->mDatabase) { + d->mSecondaryModel = std::make_unique(); + } + endRemoveRows(); + } else if ((d->mManager || d->mDatabase) && !d->mSecondaryModel) { + d->mSecondaryModel = std::make_unique(); + } + + if (d->mSecondaryModel) { + connect(d->mSecondaryModel.get(), &QAbstractItemModel::rowsAboutToBeInserted, + this, &ViewsModel::secondaryModelRowsAboutToBeInserted); + connect(d->mSecondaryModel.get(), &QAbstractItemModel::rowsInserted, + this, &ViewsModel::secondaryModelRowsInserted); + connect(d->mSecondaryModel.get(), &QAbstractItemModel::rowsAboutToBeRemoved, + this, &ViewsModel::secondaryModelRowsAboutToBeRemoved); + connect(d->mSecondaryModel.get(), &QAbstractItemModel::rowsRemoved, + this, &ViewsModel::secondaryModelRowsRemoved); + + switch (d->mEmbeddedCategory) + { + case ViewManager::AllAlbums: + d->mSecondaryModel->initialize(d->mManager, d->mDatabase, ElisaUtils::Album, ElisaUtils::NoFilter, {}, {}, {}); + break; + case ViewManager::AllArtists: + d->mSecondaryModel->initialize(d->mManager, d->mDatabase, ElisaUtils::Artist, ElisaUtils::NoFilter, {}, {}, {}); + break; + case ViewManager::AllGenres: + d->mSecondaryModel->initialize(d->mManager, d->mDatabase, ElisaUtils::Genre, ElisaUtils::NoFilter, {}, {}, {}); + break; + case ViewManager::AllTracks: + case ViewManager::AllArtistsFromGenre: + case ViewManager::OneAlbum: + case ViewManager::OneAlbumFromArtist: + case ViewManager::OneAlbumFromArtistAndGenre: + case ViewManager::OneArtist: + case ViewManager::OneArtistFromGenre: + case ViewManager::FrequentlyPlayedTracks: + case ViewManager::RecentlyPlayedTracks: + case ViewManager::FilesBrowser: + case ViewManager::RadiosBrowser: + case ViewManager::Context: + case ViewManager::NoView: + break; + } + } +} + +void ViewsModel::clearEmbeddedCategoryModel() +{ + if (d->mSecondaryModel->rowCount()) { + beginRemoveRows({}, d->mTypes.size() - 1, d->mTypes.size() - 1 + d->mSecondaryModel->rowCount() - 1); + d->mSecondaryModel.reset(); + endRemoveRows(); + } + + int directCategoryRow = 0; + switch (d->mEmbeddedCategory) { + case ViewManager::AllAlbums: + directCategoryRow = 3; + break; + case ViewManager::AllArtists: + directCategoryRow = 4; + break; + case ViewManager::AllGenres: + directCategoryRow = 6; + break; + default: + directCategoryRow = 0; + } + + beginInsertRows({}, directCategoryRow, directCategoryRow); + d->mEmbeddedCategory = ViewManager::NoView; + endInsertRows(); +} #include "moc_viewsmodel.cpp" diff --git a/src/qml/ContentView.qml b/src/qml/ContentView.qml --- a/src/qml/ContentView.qml +++ b/src/qml/ContentView.qml @@ -60,7 +60,10 @@ onOpenGridView: { if (expectedDepth === 1) { - listViews.setCurrentIndex(pageModel.indexFromViewType(viewType)) + let viewIndex = pageModel.indexFromViewType(viewType) + if (viewIndex !== -1) { + listViews.setCurrentIndex(pageModel.indexFromViewType(viewType)) + } } while(browseStackView.depth > expectedDepth) { @@ -149,6 +152,9 @@ ViewsModel { id: pageModel + + manager: elisa.musicManager + embeddedCategory: elisa.embeddedView } ViewSelector { @@ -164,7 +170,7 @@ } } - onSwitchView: viewManager.openParentView(viewType, pageModel.viewMainTitle(viewType, ""), pageModel.viewImageUrl(viewType, "")) + onSwitchView: viewManager.openParentView(viewType, pageModel.viewMainTitle(viewIndex, ""), pageModel.viewImageUrl(viewIndex, "")) } Kirigami.Separator { diff --git a/src/qml/ViewSelector.qml b/src/qml/ViewSelector.qml --- a/src/qml/ViewSelector.qml +++ b/src/qml/ViewSelector.qml @@ -29,7 +29,7 @@ property double textOpacity property alias model: pageDelegateModel.model - signal switchView(var viewType) + signal switchView(var viewType, var viewIndex) function setCurrentIndex(index) { @@ -40,64 +40,46 @@ implicitWidth: 225 - ScrollView { - focus: true + ListView { + id: viewModeView anchors.fill: parent - z: 2 + ScrollBar.vertical: ScrollBar { + id: scrollBar + } + boundsBehavior: Flickable.StopAtBounds clip: true - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: viewModeView - - Accessible.role: Accessible.List - - focus: true - activeFocusOnTab: true - keyNavigationEnabled: true - - property bool ignoreCurrentItemChanges: false - - z: 2 - - anchors.topMargin: elisaTheme.layoutHorizontalMargin * 2 - model: DelegateModel { - id: pageDelegateModel - - delegate: ViewSelectorDelegate { - id: entry + ScrollHelper { + id: scrollHelper + flickable: viewModeView + anchors.fill: viewModeView + } - height: Math.round(elisaTheme.viewSelectorDelegateHeight * 1.4) - width: viewModeView.width + property bool ignoreCurrentItemChanges: false - focus: true + model: DelegateModel { + id: pageDelegateModel - isSelected: viewModeView.currentIndex === index + delegate: ViewSelectorDelegate { + id: entry - onClicked: { - viewModeView.currentIndex = index - entry.forceActiveFocus() - } - } - } + height: Math.round(elisaTheme.viewSelectorDelegateHeight * 1.4) + width: scrollBar.visible ? (!LayoutMirroring.enabled ? viewModeView.width - scrollBar.width : viewModeView.width) : viewModeView.width - footer: MouseArea { - width: viewModeView.width - height: viewModeView.height - y + focus: true - acceptedButtons: Qt.LeftButton + isSelected: viewModeView.currentIndex === index - onClicked: - { - rootFocusScope.focus = true + onClicked: { + viewModeView.currentIndex = index + entry.forceActiveFocus() } } - - onCurrentItemChanged: if (!ignoreCurrentItemChanges) switchView(currentItem.viewType) } + + onCurrentItemChanged: if (!ignoreCurrentItemChanges) switchView(currentItem.viewType, currentIndex) } Connections { diff --git a/src/qml/ViewSelectorDelegate.qml b/src/qml/ViewSelectorDelegate.qml --- a/src/qml/ViewSelectorDelegate.qml +++ b/src/qml/ViewSelectorDelegate.qml @@ -107,9 +107,10 @@ height: elisaTheme.viewSelectorDelegateHeight } - source: model.image + source: model.image !== undefined ? model.image : '' + visible: model.image !== undefined - layer.enabled: true + layer.enabled: model.useColorOverlay layer.effect: ColorOverlay { color: nameLabel.color } diff --git a/src/viewmanager.h b/src/viewmanager.h --- a/src/viewmanager.h +++ b/src/viewmanager.h @@ -45,7 +45,8 @@ RecentlyPlayedTracks, FilesBrowser, Context, - RadiosBrowser + RadiosBrowser, + NoView, }; Q_ENUM(ViewsType) @@ -75,6 +76,13 @@ Q_ENUM(RadioSpecificStyle) + enum ViewHierarchy { + ChildViewWithParent, + TopView, + }; + + Q_ENUM(ViewHierarchy) + explicit ViewManager(QObject *parent = nullptr); Q_SIGNALS: @@ -134,11 +142,13 @@ void openRadiosBrowser(const QString &mainTitle, const QUrl &imageUrl); void openOneAlbum(const QString &albumTitle, const QString &albumAuthor, - const QUrl &albumCover, qulonglong albumDatabaseId, ViewManager::AlbumViewStyle albumDiscHeader); + const QUrl &albumCover, qulonglong albumDatabaseId, ViewManager::AlbumViewStyle albumDiscHeader, + ViewManager::ViewHierarchy viewHierarchy); - void openOneArtist(const QString &artistName, const QUrl &artistImageUrl, qulonglong artistDatabaseId); + void openOneArtist(const QString &artistName, const QUrl &artistImageUrl, qulonglong artistDatabaseId, + ViewManager::ViewHierarchy viewHierarchy); - void openAllArtistsFromGenre(const QString &genreName); + void openAllArtistsFromGenre(const QString &genreName, ViewManager::ViewHierarchy viewHierarchy); void recentlyPlayedTracksIsLoaded(); diff --git a/src/viewmanager.cpp b/src/viewmanager.cpp --- a/src/viewmanager.cpp +++ b/src/viewmanager.cpp @@ -55,11 +55,18 @@ openRadiosBrowser(mainTitle, mainImage); break; case OneAlbum: + openOneAlbum(mainTitle, {}, mainImage, {}, ViewManager::DiscHeaders, ViewManager::TopView); + break; case OneArtist: + openOneArtist(mainTitle, mainImage, {}, ViewManager::TopView); + break; + case AllArtistsFromGenre: + openAllArtistsFromGenre(mainTitle, ViewManager::TopView); + break; case OneAlbumFromArtist: - case OneArtistFromGenre: case OneAlbumFromArtistAndGenre: - case AllArtistsFromGenre: + case OneArtistFromGenre: + case ViewManager::NoView: break; } } @@ -71,13 +78,13 @@ switch(dataType) { case ElisaUtils::Album: - openOneAlbum(innerMainTitle, innerSecondaryTitle, innerImage, databaseId, albumDiscHeader); + openOneAlbum(innerMainTitle, innerSecondaryTitle, innerImage, databaseId, albumDiscHeader, ViewManager::ChildViewWithParent); break; case ElisaUtils::Artist: - openOneArtist(innerMainTitle, innerImage, databaseId); + openOneArtist(innerMainTitle, innerImage, databaseId, ViewManager::ChildViewWithParent); break; case ElisaUtils::Genre: - openAllArtistsFromGenre(innerMainTitle); + openAllArtistsFromGenre(innerMainTitle, ViewManager::ChildViewWithParent); break; case ElisaUtils::Track: case ElisaUtils::FileName: @@ -138,6 +145,8 @@ case ViewsType::RadiosBrowser: radiosBrowserViewIsLoaded(); break; + case ViewManager::NoView: + break; } } @@ -175,36 +184,41 @@ void ViewManager::openOneAlbum(const QString &albumTitle, const QString &albumAuthor, const QUrl &albumCover, qulonglong albumDatabaseId, - AlbumViewStyle albumDiscHeader) + AlbumViewStyle albumDiscHeader, ViewManager::ViewHierarchy viewHierarchy) { mTargetAlbumTitle = albumTitle; mTargetAlbumAuthor = albumAuthor; mTargetDatabaseId = albumDatabaseId; mTargetImageUrl = albumCover; mAlbumDiscHeader = albumDiscHeader; - if (mCurrentView == ViewsType::AllAlbums) { + if (mCurrentView == ViewsType::AllAlbums && viewHierarchy == ViewManager::ChildViewWithParent) { mTargetView = ViewsType::OneAlbum; Q_EMIT openListView(mTargetView, ElisaUtils::FilterById, 2, mTargetAlbumTitle, mTargetAlbumAuthor, mTargetDatabaseId, mTargetImageUrl, ElisaUtils::Track, {}, SortOrder::NoSort, SingleAlbum, mAlbumDiscHeader, IsTrack); - } else if (mCurrentView == ViewsType::OneArtist && mCurrentArtistName == mTargetAlbumAuthor) { + } else if (mCurrentView == ViewsType::OneArtist && mCurrentArtistName == mTargetAlbumAuthor && viewHierarchy == ViewManager::ChildViewWithParent) { mTargetView = ViewsType::OneAlbumFromArtist; Q_EMIT openListView(mTargetView, ElisaUtils::FilterById, 3, mTargetAlbumTitle, mTargetAlbumAuthor, mTargetDatabaseId, mTargetImageUrl, ElisaUtils::Track, {}, SortOrder::NoSort, SingleAlbum, mAlbumDiscHeader, IsTrack); - } else if (mCurrentView == ViewsType::OneArtist && mCurrentArtistName != mTargetAlbumAuthor) { + } else if (mCurrentView == ViewsType::OneArtist && mCurrentArtistName != mTargetAlbumAuthor && viewHierarchy == ViewManager::ChildViewWithParent) { mTargetView = ViewsType::OneAlbumFromArtist; Q_EMIT popOneView(); - } else if (mCurrentView == ViewsType::OneArtistFromGenre) { + } else if (mCurrentView == ViewsType::OneArtistFromGenre && viewHierarchy == ViewManager::ChildViewWithParent) { mTargetView = ViewsType::OneAlbumFromArtistAndGenre; Q_EMIT openListView(mTargetView, ElisaUtils::FilterById, 4, mTargetAlbumTitle, mTargetAlbumAuthor, mTargetDatabaseId, mTargetImageUrl, ElisaUtils::Track, {}, SortOrder::NoSort, SingleAlbum, mAlbumDiscHeader, IsTrack); - } else { + } else if (viewHierarchy == ViewManager::ChildViewWithParent) { mTargetView = ViewsType::OneAlbum; Q_EMIT openGridView(ViewsType::AllAlbums, ElisaUtils::NoFilter, 1, {}, {}, {}, ElisaUtils::Album, QUrl(QStringLiteral("image://icon/media-optical-audio")), {}, {}, true, true); + } else if (viewHierarchy == ViewManager::TopView) { + mTargetView = ViewsType::OneAlbum; + Q_EMIT openListView(mTargetView, ElisaUtils::FilterById, 1, mTargetAlbumTitle, mTargetAlbumAuthor, + mTargetDatabaseId, mTargetImageUrl, ElisaUtils::Track, {}, + SortOrder::NoSort, SingleAlbum, mAlbumDiscHeader, IsTrack); } } @@ -218,7 +232,8 @@ } } -void ViewManager::openOneArtist(const QString &artistName, const QUrl &artistImageUrl, qulonglong artistDatabaseId) +void ViewManager::openOneArtist(const QString &artistName, const QUrl &artistImageUrl, + qulonglong artistDatabaseId, ViewHierarchy viewHierarchy) { mTargetArtistName = artistName; mTargetDatabaseId = artistDatabaseId; @@ -230,23 +245,27 @@ mTargetView = ViewsType::OneArtist; } - if (mCurrentView == ViewsType::AllArtists && mTargetView == ViewsType::OneArtist) { + if (mCurrentView == ViewsType::AllArtists && mTargetView == ViewsType::OneArtist && viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByArtist, 2, mTargetArtistName, {}, mTargetImageUrl, ElisaUtils::Album, QUrl(QStringLiteral("image://icon/media-optical-audio")), {}, mTargetArtistName, true, true); } else if (mCurrentView == ViewsType::OneArtist && mCurrentArtistName != mTargetArtistName && - mTargetView == ViewsType::OneArtist) { + mTargetView == ViewsType::OneArtist && viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByArtist, 2, mTargetArtistName, {}, mTargetImageUrl, ElisaUtils::Album, QUrl(QStringLiteral("image://icon/media-optical-audio")), {}, mTargetArtistName, true, true); } else if (mCurrentView == ViewsType::OneAlbumFromArtist && mCurrentArtistName != mTargetArtistName && - mTargetView == ViewsType::OneArtist) { + mTargetView == ViewsType::OneArtist && viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByArtist, 2, mTargetArtistName, {}, mTargetImageUrl, ElisaUtils::Album, QUrl(QStringLiteral("image://icon/media-optical-audio")), {}, mTargetArtistName, true, true); - } else if (mCurrentView == ViewsType::AllArtistsFromGenre && mTargetView == ViewsType::OneArtistFromGenre) { + } else if (mCurrentView == ViewsType::AllArtistsFromGenre && mTargetView == ViewsType::OneArtistFromGenre + && viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByGenreAndArtist, 3, mTargetArtistName, {}, mTargetImageUrl, ElisaUtils::Album, QUrl(QStringLiteral("image://icon/media-optical-audio")), mTargetGenreName, mTargetArtistName, true, true); - } else { + } else if (viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(ViewsType::AllArtists, ElisaUtils::NoFilter, 1, {}, {}, {}, ElisaUtils::Artist, QUrl(QStringLiteral("image://icon/view-media-artist")), {}, {}, false, false); + } else { + Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByArtist, 1, mTargetArtistName, {}, mTargetImageUrl, ElisaUtils::Album, + QUrl(QStringLiteral("image://icon/media-optical-audio")), {}, mTargetArtistName, true, true); } } @@ -270,17 +289,20 @@ } } -void ViewManager::openAllArtistsFromGenre(const QString &genreName) +void ViewManager::openAllArtistsFromGenre(const QString &genreName, ViewManager::ViewHierarchy viewHierarchy) { mTargetView = ViewsType::AllArtistsFromGenre; mTargetGenreName = genreName; - if (mCurrentView == ViewsType::AllGenres) { + if (mCurrentView == ViewsType::AllGenres && viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByGenre, 2, mTargetGenreName, {}, QUrl(QStringLiteral("image://icon/view-media-artist")), ElisaUtils::Artist, QUrl(QStringLiteral("image://icon/view-media-artist")), mTargetGenreName, {}, false, false); - } else { + } else if (viewHierarchy == ViewManager::ChildViewWithParent) { Q_EMIT openGridView(ViewsType::AllGenres, ElisaUtils::NoFilter, 1, {}, {}, {}, ElisaUtils::Genre, QUrl(QStringLiteral("image://icon/view-media-genre")), {}, {}, false, false); + } else { + Q_EMIT openGridView(mTargetView, ElisaUtils::FilterByGenre, 1, mTargetGenreName, {}, QUrl(QStringLiteral("image://icon/view-media-artist")), + ElisaUtils::Artist, QUrl(QStringLiteral("image://icon/view-media-artist")), mTargetGenreName, {}, false, false); } }