diff --git a/autotests/databaseinterfacetest.cpp b/autotests/databaseinterfacetest.cpp index 904220cc..90a7b12e 100644 --- a/autotests/databaseinterfacetest.cpp +++ b/autotests/databaseinterfacetest.cpp @@ -1,4771 +1,4771 @@ /* * 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 "musicalbum.h" #include "musicaudiotrack.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include class DatabaseInterfaceTests: public QObject, public DatabaseTestData { Q_OBJECT private: private Q_SLOTS: void initTestCase() { qRegisterMetaType>("QHash"); qRegisterMetaType>("QHash"); qRegisterMetaType>("QList"); qRegisterMetaType>("QVector"); qRegisterMetaType>("QHash"); qRegisterMetaType>("QHash"); qRegisterMetaType("ListTrackDataType"); qRegisterMetaType("ListAlbumDataType"); qRegisterMetaType("ListArtistDataType"); qRegisterMetaType("ListGenreDataType"); qRegisterMetaType("TrackDataType"); qRegisterMetaType("AlbumDataType"); qRegisterMetaType("ArtistDataType"); qRegisterMetaType("GenreDataType"); } void avoidCrashInTrackIdFromTitleAlbumArtist() { DatabaseInterface musicDb; musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album3"), 1, 1); } void avoidCrashInAllArtists() { DatabaseInterface musicDb; musicDb.allArtistsData(); } void avoidCrashInAllAlbums() { DatabaseInterface musicDb; musicDb.allAlbums(); } void addOneTrackWithoutAlbumArtist() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addOneTrackWithoutAlbumArtist" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto track = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1)); QCOMPARE(track.isValid(), true); QCOMPARE(track.title(), QStringLiteral("track6")); QCOMPARE(track.artist(), QStringLiteral("artist2")); QCOMPARE(track.albumName(), QStringLiteral("album3")); QCOMPARE(track.albumArtist(), QStringLiteral("artist2")); QCOMPARE(track.isValidAlbumArtist(), false); QCOMPARE(track.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(track.trackNumber(), 6); QCOMPARE(track.discNumber(), 1); QCOMPARE(track.duration(), QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(track.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(track.rating(), 5); QCOMPARE(track.genre(), QStringLiteral("genre1")); QCOMPARE(track.composer(), QStringLiteral("composer1")); QCOMPARE(track.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(track.albumId(), qulonglong(1)); auto album = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist2")); QCOMPARE(album.isValid(), true); QCOMPARE(album.tracksCount(), 1); QCOMPARE(album.title(), QStringLiteral("album3")); QCOMPARE(album.artist(), QStringLiteral("artist2")); QCOMPARE(album.isValidArtist(), false); QCOMPARE(album.albumArtURI(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(album.isSingleDiscAlbum(), true); } void addAndRemoveOneTrackWithoutAlbum() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack {true, QStringLiteral("$24"), QStringLiteral("0"), QStringLiteral("track10"), QStringLiteral("artist8"), {}, QStringLiteral("artist8"), 9, 1, QTime::fromMSecsSinceStartOfDay(24), {QUrl::fromLocalFile(QStringLiteral("/$24"))}, QDateTime::fromMSecsSinceEpoch(24), {}, 9, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$24")] = QUrl::fromLocalFile(QStringLiteral("album4")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto track = musicDb.trackFromDatabaseId(musicDb.trackIdFromFileName(QUrl::fromLocalFile(QStringLiteral("/$24")))); QCOMPARE(track.isValid(), true); QCOMPARE(track.title(), QStringLiteral("track10")); QCOMPARE(track.artist(), QStringLiteral("artist8")); QCOMPARE(track.albumName(), QString()); QEXPECT_FAIL("","Album artist is currently associated with the album in the database. if the album is missing, we lose this information", Continue); QCOMPARE(track.isValidAlbumArtist(), true); QCOMPARE(track.albumCover(), QUrl()); QCOMPARE(track.trackNumber(), 9); QCOMPARE(track.discNumber(), 1); QCOMPARE(track.duration(), QTime::fromMSecsSinceStartOfDay(24)); QCOMPARE(track.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$24"))); QCOMPARE(track.rating(), 9); QCOMPARE(track.genre(), QStringLiteral("genre1")); QCOMPARE(track.composer(), QStringLiteral("composer1")); QCOMPARE(track.lyricist(), QStringLiteral("lyricist1")); musicDb.removeTracksList({track.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumRemovedSpy.count(), 1); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addAndRemoveOneTrackWithoutTrackNumber() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack {true, QStringLiteral("$26"), QStringLiteral("0"), QStringLiteral("track12"), QStringLiteral("artist8"), QStringLiteral("album4"), QStringLiteral("artist8"), -1, 1, QTime::fromMSecsSinceStartOfDay(26), {QUrl::fromLocalFile(QStringLiteral("/$26"))}, QDateTime::fromMSecsSinceEpoch(26), QUrl::fromLocalFile(QStringLiteral("file://image$26")), 9, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$26")] = QUrl::fromLocalFile(QStringLiteral("album4")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto track = musicDb.trackFromDatabaseId(musicDb.trackIdFromFileName(QUrl::fromLocalFile(QStringLiteral("/$26")))); QCOMPARE(track.isValid(), true); QCOMPARE(track.title(), QStringLiteral("track12")); QCOMPARE(track.artist(), QStringLiteral("artist8")); QCOMPARE(track.albumName(), QStringLiteral("album4")); QCOMPARE(track.albumArtist(), QStringLiteral("artist8")); QCOMPARE(track.isValidAlbumArtist(), true); QCOMPARE(track.albumCover(), QUrl::fromLocalFile(QStringLiteral("album4"))); QCOMPARE(track.trackNumber(), -1); QCOMPARE(track.discNumber(), 1); QCOMPARE(track.duration(), QTime::fromMSecsSinceStartOfDay(26)); QCOMPARE(track.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$26"))); QCOMPARE(track.rating(), 9); QCOMPARE(track.genre(), QStringLiteral("genre1")); QCOMPARE(track.composer(), QStringLiteral("composer1")); QCOMPARE(track.lyricist(), QStringLiteral("lyricist1")); musicDb.removeTracksList({track.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumRemovedSpy.count(), 1); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addAndRemoveOneTrackWithoutArtist() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack {true, QStringLiteral("$26"), QStringLiteral("0"), QStringLiteral("track11"), {}, QStringLiteral("album4"), {}, 9, 1, QTime::fromMSecsSinceStartOfDay(26), {QUrl::fromLocalFile(QStringLiteral("/$26"))}, QDateTime::fromMSecsSinceEpoch(26), QUrl::fromLocalFile(QStringLiteral("file://image$26")), 9, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$26")] = QUrl::fromLocalFile(QStringLiteral("album4")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto track = musicDb.trackFromDatabaseId(musicDb.trackIdFromFileName(QUrl::fromLocalFile(QStringLiteral("/$26")))); QCOMPARE(track.isValid(), true); QCOMPARE(track.title(), QStringLiteral("track11")); QCOMPARE(track.artist(), QString()); QCOMPARE(track.albumName(), QStringLiteral("album4")); QCOMPARE(track.albumArtist(), QString()); QCOMPARE(track.isValidAlbumArtist(), false); QCOMPARE(track.albumCover(), QUrl::fromLocalFile(QStringLiteral("album4"))); QCOMPARE(track.trackNumber(), 9); QCOMPARE(track.discNumber(), 1); QCOMPARE(track.duration(), QTime::fromMSecsSinceStartOfDay(26)); QCOMPARE(track.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$26"))); QCOMPARE(track.rating(), 9); QCOMPARE(track.genre(), QStringLiteral("genre1")); QCOMPARE(track.composer(), QStringLiteral("composer1")); QCOMPARE(track.lyricist(), QStringLiteral("lyricist1")); musicDb.removeTracksList({track.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 1); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addOneTrackWithoutAlbumArtistAndAnotherTrackWith() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack {true, QStringLiteral("$26"), QStringLiteral("0"), QStringLiteral("track11"), {}, QStringLiteral("album4"), {}, 9, 1, QTime::fromMSecsSinceStartOfDay(26), {QUrl::fromLocalFile(QStringLiteral("/$26"))}, QDateTime::fromMSecsSinceEpoch(26), QUrl::fromLocalFile(QStringLiteral("file://image$26")), 9, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$26")] = QUrl::fromLocalFile(QStringLiteral("album4")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto track = musicDb.trackFromDatabaseId(musicDb.trackIdFromFileName(QUrl::fromLocalFile(QStringLiteral("/$26")))); QCOMPARE(track.isValid(), true); QCOMPARE(track.title(), QStringLiteral("track11")); QCOMPARE(track.artist(), QString()); QCOMPARE(track.albumName(), QStringLiteral("album4")); QCOMPARE(track.albumArtist(), QString()); QCOMPARE(track.isValidAlbumArtist(), false); QCOMPARE(track.albumCover(), QUrl::fromLocalFile(QStringLiteral("album4"))); QCOMPARE(track.trackNumber(), 9); QCOMPARE(track.discNumber(), 1); QCOMPARE(track.duration(), QTime::fromMSecsSinceStartOfDay(26)); QCOMPARE(track.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$26"))); QCOMPARE(track.rating(), 9); QCOMPARE(track.genre(), QStringLiteral("genre1")); QCOMPARE(track.composer(), QStringLiteral("composer1")); QCOMPARE(track.lyricist(), QStringLiteral("lyricist1")); newTrack = MusicAudioTrack {true, QStringLiteral("$27"), QStringLiteral("0"), QStringLiteral("track12"), QStringLiteral("artist1"), QStringLiteral("album4"), QStringLiteral("artist2"), 10, 1, QTime::fromMSecsSinceStartOfDay(27), {QUrl::fromLocalFile(QStringLiteral("/autre/$27"))}, QDateTime::fromMSecsSinceEpoch(27), QUrl::fromLocalFile(QStringLiteral("file://image$27")), 10, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; newTracks = QList(); newTracks.push_back(newTrack); newCovers = mNewCovers; newCovers[QStringLiteral("file:///autre/$27")] = QUrl::fromLocalFile(QStringLiteral("album4")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 2); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addTwoTracksWithoutAlbumArtist() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksWithoutAlbumArtist" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$19"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 6, 1, QTime::fromMSecsSinceStartOfDay(19), {QUrl::fromLocalFile(QStringLiteral("/$19"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), true}, {true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist3"), QStringLiteral("album3"), {}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/$20"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); newCovers[QStringLiteral("file:///$20")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 2); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1)); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrack.title(), QStringLiteral("track6")); QCOMPARE(firstTrack.artist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.albumName(), QStringLiteral("album3")); QCOMPARE(firstTrack.albumArtist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.isValidAlbumArtist(), false); QCOMPARE(firstTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrack.trackNumber(), 6); QCOMPARE(firstTrack.discNumber(), 1); QCOMPARE(firstTrack.duration(), QTime::fromMSecsSinceStartOfDay(19)); QCOMPARE(firstTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$19"))); QCOMPARE(firstTrack.rating(), 5); QCOMPARE(firstTrack.genre(), QStringLiteral("genre1")); QCOMPARE(firstTrack.composer(), QStringLiteral("composer1")); QCOMPARE(firstTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(firstTrack.albumId(), qulonglong(1)); QCOMPARE(firstTrack.hasEmbeddedCover(), true); auto secondTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track7"), QStringLiteral("artist3"), QStringLiteral("album3"), 7, 1)); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrack.title(), QStringLiteral("track7")); QCOMPARE(secondTrack.artist(), QStringLiteral("artist3")); QCOMPARE(secondTrack.albumName(), QStringLiteral("album3")); QCOMPARE(secondTrack.albumArtist(), QStringLiteral("artist3")); QCOMPARE(secondTrack.isValidAlbumArtist(), false); QCOMPARE(secondTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrack.trackNumber(), 7); QCOMPARE(secondTrack.discNumber(), 1); QCOMPARE(secondTrack.duration(), QTime::fromMSecsSinceStartOfDay(20)); QCOMPARE(secondTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$20"))); QCOMPARE(secondTrack.rating(), 5); QCOMPARE(secondTrack.genre(), QStringLiteral("genre1")); QCOMPARE(secondTrack.composer(), QStringLiteral("composer1")); QCOMPARE(secondTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(secondTrack.albumId(), qulonglong(1)); QCOMPARE(secondTrack.hasEmbeddedCover(), false); auto album = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist2")); QCOMPARE(album.isValid(), true); QCOMPARE(album.tracksCount(), 2); QCOMPARE(album.title(), QStringLiteral("album3")); QCOMPARE(album.artist(), QStringLiteral("Various Artists")); QCOMPARE(album.isValidArtist(), false); QCOMPARE(album.albumArtURI(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(album.isSingleDiscAlbum(), true); } void addThreeTracksWithoutAlbumArtistButSameArtist() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$19"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 6, 1, QTime::fromMSecsSinceStartOfDay(19), {QUrl::fromLocalFile(QStringLiteral("/$19"))}, QDateTime::fromMSecsSinceEpoch(19), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 4, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$21"), QStringLiteral("0"), QStringLiteral("track8"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 8, 1, QTime::fromMSecsSinceStartOfDay(21), {QUrl::fromLocalFile(QStringLiteral("/$21"))}, QDateTime::fromMSecsSinceEpoch(21), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 3, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$19")] = QUrl::fromLocalFile(QStringLiteral("album3")); newCovers[QStringLiteral("file:///$20")] = QUrl::fromLocalFile(QStringLiteral("album3")); newCovers[QStringLiteral("file:///$21")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 3); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1)); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrack.title(), QStringLiteral("track6")); QCOMPARE(firstTrack.artist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.albumName(), QStringLiteral("album3")); QCOMPARE(firstTrack.albumArtist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.isValidAlbumArtist(), false); QCOMPARE(firstTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrack.trackNumber(), 6); QCOMPARE(firstTrack.discNumber(), 1); QCOMPARE(firstTrack.duration(), QTime::fromMSecsSinceStartOfDay(19)); QCOMPARE(firstTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$19"))); QCOMPARE(firstTrack.rating(), 5); QCOMPARE(firstTrack.genre(), QStringLiteral("genre1")); QCOMPARE(firstTrack.composer(), QStringLiteral("composer1")); QCOMPARE(firstTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(firstTrack.isSingleDiscAlbum(), true); QCOMPARE(firstTrack.albumId(), qulonglong(1)); auto secondTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track7"), QStringLiteral("artist2"), QStringLiteral("album3"), 7, 1)); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrack.title(), QStringLiteral("track7")); QCOMPARE(secondTrack.artist(), QStringLiteral("artist2")); QCOMPARE(secondTrack.albumName(), QStringLiteral("album3")); QCOMPARE(secondTrack.albumArtist(), QStringLiteral("artist2")); QCOMPARE(secondTrack.isValidAlbumArtist(), false); QCOMPARE(secondTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrack.trackNumber(), 7); QCOMPARE(secondTrack.discNumber(), 1); QCOMPARE(secondTrack.duration(), QTime::fromMSecsSinceStartOfDay(20)); QCOMPARE(secondTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$20"))); QCOMPARE(secondTrack.rating(), 4); QCOMPARE(secondTrack.genre(), QStringLiteral("genre1")); QCOMPARE(secondTrack.composer(), QStringLiteral("composer1")); QCOMPARE(secondTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(secondTrack.isSingleDiscAlbum(), true); QCOMPARE(secondTrack.albumId(), qulonglong(1)); QCOMPARE(secondTrack.hasEmbeddedCover(), false); auto thirdTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track8"), QStringLiteral("artist2"), QStringLiteral("album3"), 8, 1)); QCOMPARE(thirdTrack.isValid(), true); QCOMPARE(thirdTrack.title(), QStringLiteral("track8")); QCOMPARE(thirdTrack.artist(), QStringLiteral("artist2")); QCOMPARE(thirdTrack.albumName(), QStringLiteral("album3")); QCOMPARE(thirdTrack.albumArtist(), QStringLiteral("artist2")); QCOMPARE(thirdTrack.isValidAlbumArtist(), false); QCOMPARE(thirdTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(thirdTrack.trackNumber(), 8); QCOMPARE(thirdTrack.discNumber(), 1); QCOMPARE(thirdTrack.duration(), QTime::fromMSecsSinceStartOfDay(21)); QCOMPARE(thirdTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$21"))); QCOMPARE(thirdTrack.rating(), 3); QCOMPARE(thirdTrack.genre(), QStringLiteral("genre1")); QCOMPARE(thirdTrack.composer(), QStringLiteral("composer1")); QCOMPARE(thirdTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(thirdTrack.isSingleDiscAlbum(), true); QCOMPARE(thirdTrack.albumId(), qulonglong(1)); auto album = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist2")); QCOMPARE(album.isValid(), true); QCOMPARE(album.tracksCount(), 3); QCOMPARE(album.title(), QStringLiteral("album3")); QCOMPARE(album.artist(), QStringLiteral("artist2")); QCOMPARE(album.isValidArtist(), false); QCOMPARE(album.albumArtURI(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(album.isSingleDiscAlbum(), true); } void addTwoTracksWithPartialAlbumArtist() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksWithPartialAlbumArtist" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$19"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 6, 1, QTime::fromMSecsSinceStartOfDay(19), {QUrl::fromLocalFile(QStringLiteral("/$19"))}, QDateTime::fromMSecsSinceEpoch(19), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), true}, {true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist3"), QStringLiteral("album3"), {QStringLiteral("artist4")}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$19")] = QUrl::fromLocalFile(QStringLiteral("album3")); newCovers[QStringLiteral("file:///$20")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 3); QCOMPARE(musicDb.allTracks().count(), 2); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1)); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrack.title(), QStringLiteral("track6")); QCOMPARE(firstTrack.artist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.albumName(), QStringLiteral("album3")); QCOMPARE(firstTrack.albumArtist(), QStringLiteral("artist4")); QCOMPARE(firstTrack.isValidAlbumArtist(), true); QCOMPARE(firstTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrack.trackNumber(), 6); QCOMPARE(firstTrack.discNumber(), 1); QCOMPARE(firstTrack.duration(), QTime::fromMSecsSinceStartOfDay(19)); QCOMPARE(firstTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$19"))); QCOMPARE(firstTrack.rating(), 5); QCOMPARE(firstTrack.genre(), QStringLiteral("genre1")); QCOMPARE(firstTrack.composer(), QStringLiteral("composer1")); QCOMPARE(firstTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(firstTrack.isSingleDiscAlbum(), true); QCOMPARE(firstTrack.albumId(), qulonglong(1)); QCOMPARE(firstTrack.hasEmbeddedCover(), true); auto secondTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track7"), QStringLiteral("artist3"), QStringLiteral("album3"), 7, 1)); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrack.title(), QStringLiteral("track7")); QCOMPARE(secondTrack.artist(), QStringLiteral("artist3")); QCOMPARE(secondTrack.albumName(), QStringLiteral("album3")); QCOMPARE(secondTrack.albumArtist(), QStringLiteral("artist4")); QCOMPARE(secondTrack.isValidAlbumArtist(), true); QCOMPARE(secondTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrack.trackNumber(), 7); QCOMPARE(secondTrack.discNumber(), 1); QCOMPARE(secondTrack.duration(), QTime::fromMSecsSinceStartOfDay(20)); QCOMPARE(secondTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$20"))); QCOMPARE(secondTrack.rating(), 5); QCOMPARE(secondTrack.genre(), QStringLiteral("genre1")); QCOMPARE(secondTrack.composer(), QStringLiteral("composer1")); QCOMPARE(secondTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(secondTrack.isSingleDiscAlbum(), true); QCOMPARE(secondTrack.albumId(), qulonglong(1)); QCOMPARE(secondTrack.hasEmbeddedCover(), false); auto album = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist4")); QCOMPARE(album.isValid(), true); QCOMPARE(album.tracksCount(), 2); QCOMPARE(album.title(), QStringLiteral("album3")); QCOMPARE(album.artist(), QStringLiteral("artist4")); QCOMPARE(album.isValidArtist(), true); QCOMPARE(album.albumArtURI(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(album.isSingleDiscAlbum(), true); } void addMultipleTimeSameTracks() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addMultipleTimeSameTracks" << databaseFile.fileName(); DatabaseInterface musicDb; QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); auto firstAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album1"), QStringLiteral("Various Artists")); QCOMPARE(firstAlbum.isValid(), true); QCOMPARE(firstAlbum.title(), QStringLiteral("album1")); auto firstAlbumInvalid = musicDb.albumFromTitleAndArtist(QStringLiteral("album1Invalid"), QStringLiteral("Invalid Artist")); QCOMPARE(firstAlbumInvalid.isValid(), false); } void addTwiceSameTracksWithDatabaseFile() { QTemporaryFile myTempDatabase; myTempDatabase.open(); { DatabaseInterface musicDb; QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.init(QStringLiteral("testDb1"), myTempDatabase.fileName()); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); auto firstAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album1"), QStringLiteral("Various Artists")); QCOMPARE(firstAlbum.isValid(), true); QCOMPARE(firstAlbum.title(), QStringLiteral("album1")); auto firstAlbumInvalid = musicDb.albumFromTitleAndArtist(QStringLiteral("album1Invalid"), QStringLiteral("Invalid Artist")); QCOMPARE(firstAlbumInvalid.isValid(), false); } { DatabaseInterface musicDb; QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.init(QStringLiteral("testDb2"), myTempDatabase.fileName()); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); auto firstAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album1"), QStringLiteral("Various Artists")); QCOMPARE(firstAlbum.isValid(), true); QCOMPARE(firstAlbum.title(), QStringLiteral("album1")); auto firstAlbumInvalid = musicDb.albumFromTitleAndArtist(QStringLiteral("album1Invalid"), QStringLiteral("Invalid Artist")); QCOMPARE(firstAlbumInvalid.isValid(), false); } } void restoreModifiedTracksWidthDatabaseFile() { QTemporaryFile myTempDatabase; myTempDatabase.open(); { DatabaseInterface musicDb; QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allNewTracks = mNewTracks; allNewTracks.push_back({true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}); musicDb.init(QStringLiteral("testDb1"), myTempDatabase.fileName()); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); qDebug() << "restoreModifiedTracksWidthDatabaseFile" << myTempDatabase.fileName(); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(allNewTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album1"), QStringLiteral("Various Artists")); QCOMPARE(firstAlbum.isValid(), true); QCOMPARE(firstAlbum.title(), QStringLiteral("album1")); auto firstAlbumInvalid = musicDb.albumFromTitleAndArtist(QStringLiteral("album1Invalid"), QStringLiteral("Invalid Artist")); QCOMPARE(firstAlbumInvalid.isValid(), false); auto fourthAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist2")); QCOMPARE(fourthAlbum.isValid(), true); QCOMPARE(fourthAlbum.title(), QStringLiteral("album3")); QCOMPARE(fourthAlbum.tracksCount(), 4); const auto &oneTrack = fourthAlbum.trackFromIndex(3); QCOMPARE(oneTrack.isValid(), true); QCOMPARE(oneTrack.rating(), 5); } { DatabaseInterface musicDb; QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allNewTracks = mNewTracks; allNewTracks.push_back({true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 3, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}); musicDb.init(QStringLiteral("testDb2"), myTempDatabase.fileName()); qDebug() << "restoreModifiedTracksWidthDatabaseFile" << myTempDatabase.fileName(); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(allNewTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 2); QCOMPARE(musicDbTrackModifiedSpy.count(), 2); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QCOMPARE(musicDb.allAlbums().count(), 5); auto firstAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album1"), QStringLiteral("Various Artists")); QCOMPARE(firstAlbum.isValid(), true); QCOMPARE(firstAlbum.title(), QStringLiteral("album1")); auto firstAlbumInvalid = musicDb.albumFromTitleAndArtist(QStringLiteral("album1Invalid"), QStringLiteral("Invalid Artist")); QCOMPARE(firstAlbumInvalid.isValid(), false); auto fourthAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist2")); QCOMPARE(fourthAlbum.isValid(), true); QCOMPARE(fourthAlbum.title(), QStringLiteral("album3")); QCOMPARE(fourthAlbum.tracksCount(), 4); const auto &oneTrack = fourthAlbum.trackFromIndex(3); QCOMPARE(oneTrack.isValid(), true); QCOMPARE(oneTrack.title(), QStringLiteral("track6")); QCOMPARE(oneTrack.rating(), 3); } } void simpleAccessor() { DatabaseInterface musicDb; QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.init(QStringLiteral("testDb")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto invalidTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 2, 1); QCOMPARE(invalidTrackId, decltype(invalidTrackId)(0)); auto trackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); auto firstTrack = musicDb.trackFromDatabaseId(trackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track1")); QCOMPARE(firstTrackArtist, QStringLiteral("artist1")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstTrackAlbum, QStringLiteral("album1")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(1)); QCOMPARE(firstTrackMilliSecondsDuration, 1); QCOMPARE(firstTrackTrackNumber, 1); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$1"))); QCOMPARE(firstTrackRating, 1); QCOMPARE(firstIsSingleDiscAlbum, false); auto secondAlbumTitle = allAlbums[1].title(); auto secondAlbumArtist = allAlbums[1].artist(); auto secondAlbumImage = allAlbums[1].albumArtURI(); auto secondAlbumTracksCount = allAlbums[1].tracksCount(); auto secondAlbumIsSingleDiscAlbum = allAlbums[1].isSingleDiscAlbum(); QCOMPARE(secondAlbumTitle, QStringLiteral("album2")); QCOMPARE(secondAlbumArtist, QStringLiteral("artist1")); QCOMPARE(secondAlbumImage.isValid(), true); QCOMPARE(secondAlbumImage, QUrl::fromLocalFile(QStringLiteral("album2"))); QCOMPARE(secondAlbumTracksCount, 6); QCOMPARE(secondAlbumIsSingleDiscAlbum, true); } void simpleAccessorAndVariousArtistAlbum() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDbVariousArtistAlbum")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto invalidTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 2, 1); QCOMPARE(invalidTrackId, decltype(invalidTrackId)(0)); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track1")); QCOMPARE(firstTrackArtist, QStringLiteral("artist1")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstTrackAlbum, QStringLiteral("album1")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(1)); QCOMPARE(firstTrackMilliSecondsDuration, 1); QCOMPARE(firstTrackTrackNumber, 1); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$1"))); QCOMPARE(firstTrackRating, 1); QCOMPARE(firstIsSingleDiscAlbum, false); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track2"), QStringLiteral("artist2"), QStringLiteral("album1"), 2, 2); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto seconfTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track2")); QCOMPARE(secondTrackArtist, QStringLiteral("artist2")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(secondTrackAlbum, QStringLiteral("album1")); QCOMPARE(seconfTrackImage.isValid(), true); QCOMPARE(seconfTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(2)); QCOMPARE(secondTrackMilliSecondsDuration, 2); QCOMPARE(secondTrackTrackNumber, 2); QCOMPARE(secondTrackDiscNumber, 2); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$2"))); QCOMPARE(secondTrackRating, 2); QCOMPARE(secondIsSingleDiscAlbum, false); auto thirdTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), 3, 3); auto thirdTrack = musicDb.trackFromDatabaseId(thirdTrackId); auto thirdTrackTitle = thirdTrack.title(); auto thirdTrackArtist = thirdTrack.artist(); auto thirdTrackAlbumArtist = thirdTrack.albumArtist(); auto thirdTrackAlbum = thirdTrack.albumName(); auto thirdTrackImage = thirdTrack.albumCover(); auto thirdTrackDuration = thirdTrack.duration(); auto thirdTrackMilliSecondsDuration = thirdTrack.duration().msecsSinceStartOfDay(); auto thirdTrackTrackNumber = thirdTrack.trackNumber(); auto thirdTrackDiscNumber = thirdTrack.discNumber(); const auto &thirdTrackResource = thirdTrack.resourceURI(); auto thirdTrackRating = thirdTrack.rating(); auto thirdIsSingleDiscAlbum = thirdTrack.isSingleDiscAlbum(); QCOMPARE(thirdTrack.isValid(), true); QCOMPARE(thirdTrackTitle, QStringLiteral("track3")); QCOMPARE(thirdTrackArtist, QStringLiteral("artist3")); QCOMPARE(thirdTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(thirdTrackAlbum, QStringLiteral("album1")); QCOMPARE(thirdTrackImage.isValid(), true); QCOMPARE(thirdTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(thirdTrackDuration, QTime::fromMSecsSinceStartOfDay(3)); QCOMPARE(thirdTrackMilliSecondsDuration, 3); QCOMPARE(thirdTrackTrackNumber, 3); QCOMPARE(thirdTrackDiscNumber, 3); QCOMPARE(thirdTrackResource.isValid(), true); QCOMPARE(thirdTrackResource, QUrl::fromLocalFile(QStringLiteral("/$3"))); QCOMPARE(thirdTrackRating, 3); QCOMPARE(thirdIsSingleDiscAlbum, false); auto fourthTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track4"), QStringLiteral("artist4"), QStringLiteral("album1"), 4, 4); auto fourthTrack = musicDb.trackFromDatabaseId(fourthTrackId); auto fourthTrackTitle = fourthTrack.title(); auto fourthTrackArtist = fourthTrack.artist(); auto fourthTrackAlbumArtist = fourthTrack.albumArtist(); auto fourthTrackAlbum = fourthTrack.albumName(); auto fourthTrackImage = fourthTrack.albumCover(); auto fourthTrackDuration = fourthTrack.duration(); auto fourthTrackMilliSecondsDuration = fourthTrack.duration().msecsSinceStartOfDay(); auto fourthTrackTrackNumber = fourthTrack.trackNumber(); auto fourthTrackDiscNumber = fourthTrack.discNumber(); const auto &fourthTrackResource = fourthTrack.resourceURI(); auto fourthTrackRating = thirdTrack.rating(); auto fourthIsSingleDiscAlbum = fourthTrack.isSingleDiscAlbum(); QCOMPARE(fourthTrack.isValid(), true); QCOMPARE(fourthTrackTitle, QStringLiteral("track4")); QCOMPARE(fourthTrackArtist, QStringLiteral("artist4")); QCOMPARE(fourthTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(fourthTrackAlbum, QStringLiteral("album1")); QCOMPARE(fourthTrackImage.isValid(), true); QCOMPARE(fourthTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(fourthTrackDuration, QTime::fromMSecsSinceStartOfDay(4)); QCOMPARE(fourthTrackMilliSecondsDuration, 4); QCOMPARE(fourthTrackTrackNumber, 4); QCOMPARE(fourthTrackDiscNumber, 4); QCOMPARE(fourthTrackResource.isValid(), true); QCOMPARE(fourthTrackResource, QUrl::fromLocalFile(QStringLiteral("/$4"))); QCOMPARE(fourthTrackRating, 3); QCOMPARE(fourthIsSingleDiscAlbum, false); auto secondAlbumTitle = allAlbums[1].title(); auto secondAlbumArtist = allAlbums[1].artist(); auto secondAlbumImage = allAlbums[1].albumArtURI(); auto secondAlbumTracksCount = allAlbums[1].tracksCount(); auto secondAlbumIsSingleDiscAlbum = allAlbums[1].isSingleDiscAlbum(); QCOMPARE(secondAlbumTitle, QStringLiteral("album2")); QCOMPARE(secondAlbumArtist, QStringLiteral("artist1")); QCOMPARE(secondAlbumImage.isValid(), true); QCOMPARE(secondAlbumImage, QUrl::fromLocalFile(QStringLiteral("album2"))); QCOMPARE(secondAlbumTracksCount, 6); QCOMPARE(secondAlbumIsSingleDiscAlbum, true); } void fetchAllTracksFromSource() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDbVariousArtistAlbum")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newFiles2 = QList(); for (const auto &oneTrack : newTracks) { newFiles2.push_back(oneTrack.resourceURI()); } auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("image$19")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest2")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 8); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); auto allTracks = musicDb.allTracksFromSource(QStringLiteral("autoTest")); auto allTracks2 = musicDb.allTracksFromSource(QStringLiteral("autoTest2")); QCOMPARE(allTracks.count(), 22); QCOMPARE(allTracks2.count(), 1); } void simpleAccessorAndVariousArtistAlbumWithFile() { QTemporaryFile myDatabaseFile; myDatabaseFile.open(); { DatabaseInterface musicDb; QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); musicDb.init(QStringLiteral("testDbVariousArtistAlbum1"), myDatabaseFile.fileName()); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto invalidTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 2, 1); QCOMPARE(invalidTrackId, decltype(invalidTrackId)(0)); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track1")); QCOMPARE(firstTrackArtist, QStringLiteral("artist1")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstTrackAlbum, QStringLiteral("album1")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(1)); QCOMPARE(firstTrackMilliSecondsDuration, 1); QCOMPARE(firstTrackTrackNumber, 1); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$1"))); QCOMPARE(firstTrackRating, 1); QCOMPARE(firstIsSingleDiscAlbum, false); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track2"), QStringLiteral("artist2"), QStringLiteral("album1"), 2, 2); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto seconfTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track2")); QCOMPARE(secondTrackArtist, QStringLiteral("artist2")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(secondTrackAlbum, QStringLiteral("album1")); QCOMPARE(seconfTrackImage.isValid(), true); QCOMPARE(seconfTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(2)); QCOMPARE(secondTrackMilliSecondsDuration, 2); QCOMPARE(secondTrackTrackNumber, 2); QCOMPARE(secondTrackDiscNumber, 2); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$2"))); QCOMPARE(secondTrackRating, 2); QCOMPARE(secondIsSingleDiscAlbum, false); auto thirdTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), 3, 3); auto thirdTrack = musicDb.trackFromDatabaseId(thirdTrackId); auto thirdTrackTitle = thirdTrack.title(); auto thirdTrackArtist = thirdTrack.artist(); auto thirdTrackAlbumArtist = thirdTrack.albumArtist(); auto thirdTrackAlbum = thirdTrack.albumName(); auto thirdTrackImage = thirdTrack.albumCover(); auto thirdTrackDuration = thirdTrack.duration(); auto thirdTrackMilliSecondsDuration = thirdTrack.duration().msecsSinceStartOfDay(); auto thirdTrackTrackNumber = thirdTrack.trackNumber(); auto thirdTrackDiscNumber = thirdTrack.discNumber(); const auto &thirdTrackResource = thirdTrack.resourceURI(); auto thirdTrackRating = thirdTrack.rating(); auto thirdIsSingleDiscAlbum = thirdTrack.isSingleDiscAlbum(); QCOMPARE(thirdTrack.isValid(), true); QCOMPARE(thirdTrackTitle, QStringLiteral("track3")); QCOMPARE(thirdTrackArtist, QStringLiteral("artist3")); QCOMPARE(thirdTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(thirdTrackAlbum, QStringLiteral("album1")); QCOMPARE(thirdTrackImage.isValid(), true); QCOMPARE(thirdTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(thirdTrackDuration, QTime::fromMSecsSinceStartOfDay(3)); QCOMPARE(thirdTrackMilliSecondsDuration, 3); QCOMPARE(thirdTrackTrackNumber, 3); QCOMPARE(thirdTrackDiscNumber, 3); QCOMPARE(thirdTrackResource.isValid(), true); QCOMPARE(thirdTrackResource, QUrl::fromLocalFile(QStringLiteral("/$3"))); QCOMPARE(thirdTrackRating, 3); QCOMPARE(thirdIsSingleDiscAlbum, false); auto fourthTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track4"), QStringLiteral("artist4"), QStringLiteral("album1"), 4, 4); auto fourthTrack = musicDb.trackFromDatabaseId(fourthTrackId); auto fourthTrackTitle = fourthTrack.title(); auto fourthTrackArtist = fourthTrack.artist(); auto fourthTrackAlbumArtist = fourthTrack.albumArtist(); auto fourthTrackAlbum = fourthTrack.albumName(); auto fourthTrackImage = fourthTrack.albumCover(); auto fourthTrackDuration = fourthTrack.duration(); auto fourthTrackMilliSecondsDuration = fourthTrack.duration().msecsSinceStartOfDay(); auto fourthTrackTrackNumber = fourthTrack.trackNumber(); auto fourthTrackDiscNumber = fourthTrack.discNumber(); const auto &fourthTrackResource = fourthTrack.resourceURI(); auto fourthTrackRating = thirdTrack.rating(); auto fourthIsSingleDiscAlbum = fourthTrack.isSingleDiscAlbum(); QCOMPARE(fourthTrack.isValid(), true); QCOMPARE(fourthTrackTitle, QStringLiteral("track4")); QCOMPARE(fourthTrackArtist, QStringLiteral("artist4")); QCOMPARE(fourthTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(fourthTrackAlbum, QStringLiteral("album1")); QCOMPARE(fourthTrackImage.isValid(), true); QCOMPARE(fourthTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(fourthTrackDuration, QTime::fromMSecsSinceStartOfDay(4)); QCOMPARE(fourthTrackMilliSecondsDuration, 4); QCOMPARE(fourthTrackTrackNumber, 4); QCOMPARE(fourthTrackDiscNumber, 4); QCOMPARE(fourthTrackResource.isValid(), true); QCOMPARE(fourthTrackResource, QUrl::fromLocalFile(QStringLiteral("/$4"))); QCOMPARE(fourthTrackRating, 3); QCOMPARE(fourthIsSingleDiscAlbum, false); auto secondAlbumTitle = allAlbums[1].title(); auto secondAlbumArtist = allAlbums[1].artist(); auto secondAlbumImage = allAlbums[1].albumArtURI(); auto secondAlbumTracksCount = allAlbums[1].tracksCount(); auto secondAlbumIsSingleDiscAlbum = allAlbums[1].isSingleDiscAlbum(); QCOMPARE(secondAlbumTitle, QStringLiteral("album2")); QCOMPARE(secondAlbumArtist, QStringLiteral("artist1")); QCOMPARE(secondAlbumImage.isValid(), true); QCOMPARE(secondAlbumImage, QUrl::fromLocalFile(QStringLiteral("album2"))); QCOMPARE(secondAlbumTracksCount, 6); QCOMPARE(secondAlbumIsSingleDiscAlbum, true); } { DatabaseInterface musicDb; QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); musicDb.init(QStringLiteral("testDbVariousArtistAlbum2"), myDatabaseFile.fileName()); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto invalidTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 2, 1); QCOMPARE(invalidTrackId, decltype(invalidTrackId)(0)); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track1")); QCOMPARE(firstTrackArtist, QStringLiteral("artist1")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstTrackAlbum, QStringLiteral("album1")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(1)); QCOMPARE(firstTrackMilliSecondsDuration, 1); QCOMPARE(firstTrackTrackNumber, 1); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$1"))); QCOMPARE(firstTrackRating, 1); QCOMPARE(firstIsSingleDiscAlbum, false); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track2"), QStringLiteral("artist2"), QStringLiteral("album1"), 2, 2); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto seconfTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track2")); QCOMPARE(secondTrackArtist, QStringLiteral("artist2")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(secondTrackAlbum, QStringLiteral("album1")); QCOMPARE(seconfTrackImage.isValid(), true); QCOMPARE(seconfTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(2)); QCOMPARE(secondTrackMilliSecondsDuration, 2); QCOMPARE(secondTrackTrackNumber, 2); QCOMPARE(secondTrackDiscNumber, 2); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$2"))); QCOMPARE(secondTrackRating, 2); QCOMPARE(secondIsSingleDiscAlbum, false); auto thirdTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), 3, 3); auto thirdTrack = musicDb.trackFromDatabaseId(thirdTrackId); auto thirdTrackTitle = thirdTrack.title(); auto thirdTrackArtist = thirdTrack.artist(); auto thirdTrackAlbumArtist = thirdTrack.albumArtist(); auto thirdTrackAlbum = thirdTrack.albumName(); auto thirdTrackImage = thirdTrack.albumCover(); auto thirdTrackDuration = thirdTrack.duration(); auto thirdTrackMilliSecondsDuration = thirdTrack.duration().msecsSinceStartOfDay(); auto thirdTrackTrackNumber = thirdTrack.trackNumber(); auto thirdTrackDiscNumber = thirdTrack.discNumber(); const auto &thirdTrackResource = thirdTrack.resourceURI(); auto thirdTrackRating = thirdTrack.rating(); auto thirdIsSingleDiscAlbum = thirdTrack.isSingleDiscAlbum(); QCOMPARE(thirdTrack.isValid(), true); QCOMPARE(thirdTrackTitle, QStringLiteral("track3")); QCOMPARE(thirdTrackArtist, QStringLiteral("artist3")); QCOMPARE(thirdTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(thirdTrackAlbum, QStringLiteral("album1")); QCOMPARE(thirdTrackImage.isValid(), true); QCOMPARE(thirdTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(thirdTrackDuration, QTime::fromMSecsSinceStartOfDay(3)); QCOMPARE(thirdTrackMilliSecondsDuration, 3); QCOMPARE(thirdTrackTrackNumber, 3); QCOMPARE(thirdTrackDiscNumber, 3); QCOMPARE(thirdTrackResource.isValid(), true); QCOMPARE(thirdTrackResource, QUrl::fromLocalFile(QStringLiteral("/$3"))); QCOMPARE(thirdTrackRating, 3); QCOMPARE(thirdIsSingleDiscAlbum, false); auto fourthTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track4"), QStringLiteral("artist4"), QStringLiteral("album1"), 4, 4); auto fourthTrack = musicDb.trackFromDatabaseId(fourthTrackId); auto fourthTrackTitle = fourthTrack.title(); auto fourthTrackArtist = fourthTrack.artist(); auto fourthTrackAlbumArtist = fourthTrack.albumArtist(); auto fourthTrackAlbum = fourthTrack.albumName(); auto fourthTrackImage = fourthTrack.albumCover(); auto fourthTrackDuration = fourthTrack.duration(); auto fourthTrackMilliSecondsDuration = fourthTrack.duration().msecsSinceStartOfDay(); auto fourthTrackTrackNumber = fourthTrack.trackNumber(); auto fourthTrackDiscNumber = fourthTrack.discNumber(); const auto &fourthTrackResource = fourthTrack.resourceURI(); auto fourthTrackRating = thirdTrack.rating(); auto fourthIsSingleDiscAlbum = fourthTrack.isSingleDiscAlbum(); QCOMPARE(fourthTrack.isValid(), true); QCOMPARE(fourthTrackTitle, QStringLiteral("track4")); QCOMPARE(fourthTrackArtist, QStringLiteral("artist4")); QCOMPARE(fourthTrackAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(fourthTrackAlbum, QStringLiteral("album1")); QCOMPARE(fourthTrackImage.isValid(), true); QCOMPARE(fourthTrackImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(fourthTrackDuration, QTime::fromMSecsSinceStartOfDay(4)); QCOMPARE(fourthTrackMilliSecondsDuration, 4); QCOMPARE(fourthTrackTrackNumber, 4); QCOMPARE(fourthTrackDiscNumber, 4); QCOMPARE(fourthTrackResource.isValid(), true); QCOMPARE(fourthTrackResource, QUrl::fromLocalFile(QStringLiteral("/$4"))); QCOMPARE(fourthTrackRating, 3); QCOMPARE(fourthIsSingleDiscAlbum, false); auto secondAlbumTitle = allAlbums[1].title(); auto secondAlbumArtist = allAlbums[1].artist(); auto secondAlbumImage = allAlbums[1].albumArtURI(); auto secondAlbumTracksCount = allAlbums[1].tracksCount(); auto secondAlbumIsSingleDiscAlbum = allAlbums[1].isSingleDiscAlbum(); QCOMPARE(secondAlbumTitle, QStringLiteral("album2")); QCOMPARE(secondAlbumArtist, QStringLiteral("artist1")); QCOMPARE(secondAlbumImage.isValid(), true); QCOMPARE(secondAlbumImage, QUrl::fromLocalFile(QStringLiteral("album2"))); QCOMPARE(secondAlbumTracksCount, 6); QCOMPARE(secondAlbumIsSingleDiscAlbum, true); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist8"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newFiles2 = QList(); for (const auto &oneTrack : newTracks) { newFiles2.push_back(oneTrack.resourceURI()); } auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("image$19")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 8); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); } } void testTracksFromAuthor() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDbVariousArtistAlbum")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); - auto allTracks = musicDb.tracksFromAuthor(QStringLiteral("artist1")); + auto allTracks = musicDb.tracksDataFromAuthor(QStringLiteral("artist1")); QCOMPARE(allTracks.size(), 6); QCOMPARE(allTracks[0].albumArtist(), QStringLiteral("Various Artists")); QCOMPARE(allTracks[1].albumArtist(), QStringLiteral("artist1")); QCOMPARE(allTracks[2].albumArtist(), QStringLiteral("artist1")); QCOMPARE(allTracks[3].albumArtist(), QStringLiteral("artist1")); QCOMPARE(allTracks[4].albumArtist(), QStringLiteral("artist1")); QCOMPARE(allTracks[5].albumArtist(), QStringLiteral("artist1")); } void removeOneTrack() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "removeOneTrack" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto trackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); QVERIFY2(trackId != 0, "trackId should be different from 0"); auto firstTrack = musicDb.trackFromDatabaseId(trackId); QCOMPARE(firstTrack.isValid(), true); musicDb.removeTracksList({firstTrack.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 21); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbumsV2 = musicDb.allAlbums(); const auto &firstAlbum = allAlbumsV2[0]; QCOMPARE(musicDb.allAlbums().isEmpty(), false); QCOMPARE(firstAlbum.isValid(), true); auto firstAlbumTitleV2 = firstAlbum.title(); auto firstAlbumArtistV2 = firstAlbum.artist(); auto firstAlbumImageV2 = firstAlbum.albumArtURI(); auto firstAlbumTracksCountV2 = firstAlbum.tracksCount(); auto firstAlbumIsSingleDiscAlbumV2 = firstAlbum.isSingleDiscAlbum(); QCOMPARE(firstAlbumTitleV2, QStringLiteral("album1")); QCOMPARE(firstAlbumArtistV2, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImageV2.isValid(), true); QCOMPARE(firstAlbumImageV2, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCountV2, 3); QCOMPARE(firstAlbumIsSingleDiscAlbumV2, false); auto removedTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); QCOMPARE(removedTrackId, qulonglong(0)); } void removeOneTrackAndModifyIt() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "removeOneTrackAndModifyIt" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto trackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); QCOMPARE(trackId != 0, true); auto firstTrack = musicDb.trackFromDatabaseId(trackId); QCOMPARE(firstTrack.isValid(), true); musicDb.removeTracksList({firstTrack.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 21); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbumsV2 = musicDb.allAlbums(); const auto &firstAlbum = allAlbumsV2[0]; QCOMPARE(musicDb.allAlbums().isEmpty(), false); QCOMPARE(firstAlbum.isValid(), true); auto firstAlbumTitleV2 = firstAlbum.title(); auto firstAlbumArtistV2 = firstAlbum.artist(); auto firstAlbumImageV2 = firstAlbum.albumArtURI(); auto firstAlbumTracksCountV2 = firstAlbum.tracksCount(); auto firstAlbumIsSingleDiscAlbumV2 = firstAlbum.isSingleDiscAlbum(); QCOMPARE(firstAlbumTitleV2, QStringLiteral("album1")); QCOMPARE(firstAlbumArtistV2, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImageV2.isValid(), true); QCOMPARE(firstAlbumImageV2, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCountV2, 3); QCOMPARE(firstAlbumIsSingleDiscAlbumV2, false); auto removedTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); QCOMPARE(removedTrackId, qulonglong(0)); firstTrack.setDatabaseId(0); musicDb.modifyTracksList({firstTrack}, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 2); QCOMPARE(musicDbTrackModifiedSpy.count(), 3); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbums3 = musicDb.allAlbums(); auto firstAlbumTitle3 = allAlbums3[0].title(); auto firstAlbumArtist3 = allAlbums3[0].artist(); auto firstAlbumImage3 = allAlbums3[0].albumArtURI(); auto firstAlbumTracksCount3 = allAlbums3[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum3 = allAlbums3[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle3, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist3, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage3.isValid(), true); QCOMPARE(firstAlbumImage3, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount3, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum3, false); auto trackId3 = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album1"), 1, 1); QCOMPARE(trackId3 != 0, true); } void removeOneAlbum() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "removeOneAlbum" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album2"), 1, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track2"), QStringLiteral("artist1"), QStringLiteral("album2"), 2, 1); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto thirdTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist1"), QStringLiteral("album2"), 3, 1); auto thirdTrack = musicDb.trackFromDatabaseId(thirdTrackId); auto fourthTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track4"), QStringLiteral("artist1"), QStringLiteral("album2"), 4, 1); auto fourthTrack = musicDb.trackFromDatabaseId(fourthTrackId); auto fithTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track5"), QStringLiteral("artist1"), QStringLiteral("album2"), 5, 1); auto fithTrack = musicDb.trackFromDatabaseId(fithTrackId); auto sixthTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist1 and artist2"), QStringLiteral("album2"), 6, 1); auto sixthTrack = musicDb.trackFromDatabaseId(sixthTrackId); musicDb.removeTracksList({firstTrack.resourceURI(), secondTrack.resourceURI(), thirdTrack.resourceURI(), fourthTrack.resourceURI(), fithTrack.resourceURI(), sixthTrack.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 4); QCOMPARE(musicDb.allArtistsData().count(), 6); QCOMPARE(musicDb.allTracks().count(), 16); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumRemovedSpy.count(), 1); QCOMPARE(musicDbTrackRemovedSpy.count(), 6); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto removedAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album2"), QStringLiteral("artist1")); QCOMPARE(removedAlbum.isValid(), false); } void removeOneArtist() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album1")); QCOMPARE(firstAlbumArtist, QStringLiteral("Various Artists")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album1"))); QCOMPARE(firstAlbumTracksCount, 4); QCOMPARE(firstAlbumIsSingleDiscAlbum, false); auto trackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), 3, 3); auto track = musicDb.trackFromDatabaseId(trackId); musicDb.removeTracksList({track.resourceURI()}); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 6); QCOMPARE(musicDb.allTracks().count(), 21); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 1); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addOneTrack() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 3); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addTwoTracksSameAlbumSameTitle() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksSameAlbumSameTitle" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track6")); QCOMPARE(firstTrackArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbum, QStringLiteral("album3")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(firstTrackMilliSecondsDuration, 23); QCOMPARE(firstTrackTrackNumber, 6); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(firstTrackRating, 5); QCOMPARE(firstIsSingleDiscAlbum, true); auto allAlbums = musicDb.allAlbums(); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount, 1); QCOMPARE(firstAlbumIsSingleDiscAlbum, true); auto newTrack2 = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks2 = QList(); newTracks2.push_back(newTrack2); auto newCovers2 = mNewCovers; newCovers2[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("image$19")); musicDb.insertTracksList(newTracks2, newCovers2, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(50); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), 6, 1); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto secondTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track6")); QCOMPARE(secondTrackArtist, QStringLiteral("artist9")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("artist2")); QCOMPARE(secondTrackAlbum, QStringLiteral("album3")); QCOMPARE(secondTrackImage.isValid(), true); QCOMPARE(secondTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(secondTrackMilliSecondsDuration, 23); QCOMPARE(secondTrackTrackNumber, 6); QCOMPARE(secondTrackDiscNumber, 1); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(secondTrackRating, 5); QCOMPARE(secondIsSingleDiscAlbum, true); auto allAlbums2 = musicDb.allAlbums(); auto firstAlbumTitle2 = allAlbums2[0].title(); auto firstAlbumArtist2 = allAlbums2[0].artist(); auto firstAlbumImage2 = allAlbums2[0].albumArtURI(); auto firstAlbumTracksCount2 = allAlbums2[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum2 = allAlbums2[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle2, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist2, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage2.isValid(), true); QCOMPARE(firstAlbumImage2, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount2, 1); QCOMPARE(firstAlbumIsSingleDiscAlbum2, true); } void addTwoTracksSameFileWithAlbumSameName() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksSameFileWithAlbumSameName" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track6")); QCOMPARE(firstTrackArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbum, QStringLiteral("album3")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(firstTrackMilliSecondsDuration, 23); QCOMPARE(firstTrackTrackNumber, 6); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(firstTrackRating, 5); QCOMPARE(firstIsSingleDiscAlbum, true); auto allAlbums = musicDb.allAlbums(); QCOMPARE(allAlbums.size(), 1); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount, 1); QCOMPARE(firstAlbumIsSingleDiscAlbum, true); auto newTrack2 = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), QStringLiteral("artist9"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks2 = QList(); newTracks2.push_back(newTrack2); auto newCovers2 = mNewCovers; newCovers2[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks2, newCovers2, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(50); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), 6, 1); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto secondTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track6")); QCOMPARE(secondTrackArtist, QStringLiteral("artist9")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("artist9")); QCOMPARE(secondTrackAlbum, QStringLiteral("album3")); QCOMPARE(secondTrackImage.isValid(), true); QCOMPARE(secondTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(secondTrackMilliSecondsDuration, 23); QCOMPARE(secondTrackTrackNumber, 6); QCOMPARE(secondTrackDiscNumber, 1); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(secondTrackRating, 5); QCOMPARE(secondIsSingleDiscAlbum, true); auto allAlbums2 = musicDb.allAlbums(); auto firstAlbumTitle2 = allAlbums2[0].title(); auto firstAlbumArtist2 = allAlbums2[0].artist(); auto firstAlbumImage2 = allAlbums2[0].albumArtURI(); auto firstAlbumTracksCount2 = allAlbums2[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum2 = allAlbums2[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle2, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist2, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage2.isValid(), true); QCOMPARE(firstAlbumImage2, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount2, 0); QCOMPARE(firstAlbumIsSingleDiscAlbum2, true); auto secondAlbumTitle = allAlbums2[1].title(); auto secondAlbumArtist = allAlbums2[1].artist(); auto secondAlbumImage = allAlbums2[1].albumArtURI(); auto secondAlbumTracksCount = allAlbums2[1].tracksCount(); auto secondAlbumIsSingleDiscAlbum = allAlbums2[1].isSingleDiscAlbum(); QCOMPARE(secondAlbumTitle, QStringLiteral("album3")); QCOMPARE(secondAlbumArtist, QStringLiteral("artist9")); QCOMPARE(secondAlbumImage.isValid(), true); QCOMPARE(secondAlbumImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondAlbumTracksCount, 1); QCOMPARE(secondAlbumIsSingleDiscAlbum, true); auto modifiedAlbumIds = QList{musicDbAlbumModifiedSpy.at(0).at(1).toULongLong(),}; std::sort(modifiedAlbumIds.begin(), modifiedAlbumIds.end()); QCOMPARE(modifiedAlbumIds.at(0), qulonglong(1)); } void addTwoTracksWithAlbumSameName() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksWithAlbumSameName" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track6")); QCOMPARE(firstTrackArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbum, QStringLiteral("album3")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(firstTrackMilliSecondsDuration, 23); QCOMPARE(firstTrackTrackNumber, 6); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(firstTrackRating, 5); QCOMPARE(firstIsSingleDiscAlbum, true); auto allAlbums = musicDb.allAlbums(); QCOMPARE(allAlbums.size(), 1); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount, 1); QCOMPARE(firstAlbumIsSingleDiscAlbum, true); auto newTrack2 = MusicAudioTrack{true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), QStringLiteral("artist9"), 6, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("file://image$20"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks2 = QList(); newTracks2.push_back(newTrack2); auto newCovers2 = mNewCovers; newCovers2[QStringLiteral("file:///$20")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks2, newCovers2, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(50); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 2); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist9"), QStringLiteral("album3"), 6, 1); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto secondTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track6")); QCOMPARE(secondTrackArtist, QStringLiteral("artist9")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("artist9")); QCOMPARE(secondTrackAlbum, QStringLiteral("album3")); QCOMPARE(secondTrackImage.isValid(), true); QCOMPARE(secondTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(20)); QCOMPARE(secondTrackMilliSecondsDuration, 20); QCOMPARE(secondTrackTrackNumber, 6); QCOMPARE(secondTrackDiscNumber, 1); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$20"))); QCOMPARE(secondTrackRating, 5); QCOMPARE(secondIsSingleDiscAlbum, true); auto allAlbums2 = musicDb.allAlbums(); auto firstAlbumTitle2 = allAlbums2[0].title(); auto firstAlbumArtist2 = allAlbums2[0].artist(); auto firstAlbumImage2 = allAlbums2[0].albumArtURI(); auto firstAlbumTracksCount2 = allAlbums2[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum2 = allAlbums2[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle2, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist2, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage2.isValid(), true); QCOMPARE(firstAlbumImage2, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount2, 1); QCOMPARE(firstAlbumIsSingleDiscAlbum2, true); auto secondAlbumTitle = allAlbums2[1].title(); auto secondAlbumArtist = allAlbums2[1].artist(); auto secondAlbumImage = allAlbums2[1].albumArtURI(); auto secondAlbumTracksCount = allAlbums2[1].tracksCount(); auto secondAlbumIsSingleDiscAlbum = allAlbums2[1].isSingleDiscAlbum(); QCOMPARE(secondAlbumTitle, QStringLiteral("album3")); QCOMPARE(secondAlbumArtist, QStringLiteral("artist9")); QCOMPARE(secondAlbumImage.isValid(), true); QCOMPARE(secondAlbumImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondAlbumTracksCount, 1); QCOMPARE(secondAlbumIsSingleDiscAlbum, true); } void addTwoTracksInAlbumWithoutCover() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album7"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl(); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 6); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto trackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album7"), 6, 1); const auto &firstTrack = musicDb.trackFromDatabaseId(trackId); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrack.albumCover(), QUrl()); auto newTrack2 = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist2"), QStringLiteral("album7"), QStringLiteral("artist2"), 7, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks2 = QList(); newTracks2.push_back(newTrack2); auto newCovers2 = mNewCovers; newCovers2[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album7")); musicDb.insertTracksList(newTracks2, newCovers2, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 6); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track7"), QStringLiteral("artist2"), QStringLiteral("album7"), 7, 1); const auto &secondTrack = musicDb.trackFromDatabaseId(secondTrackId); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album7"))); } void modifyOneTrack() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "modifyOneTrack" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto modifiedTrack = MusicAudioTrack{true, QStringLiteral("$3"), QStringLiteral("0"), QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), QStringLiteral("Various Artists"), 5, 3, QTime::fromMSecsSinceStartOfDay(3), {QUrl::fromLocalFile(QStringLiteral("/$3"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("file://image$3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; musicDb.modifyTracksList({modifiedTrack}, mNewCovers, QStringLiteral("autoTest")); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto trackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), 5, 3); QCOMPARE(trackId != 0, true); auto track = musicDb.trackFromDatabaseId(trackId); QCOMPARE(track.isValid(), true); QCOMPARE(track.trackNumber(), 5); } void addOneAlbum() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album7"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCover = QUrl::fromLocalFile(QStringLiteral("file://image$19")); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = newCover; musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 6); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); const auto &newAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album7"), QStringLiteral("artist2")); QCOMPARE(newAlbum.albumArtURI(), QUrl::fromLocalFile(QStringLiteral("file://image$19"))); } void addOneArtist() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("Various Artists"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), QUrl::fromLocalFile(QStringLiteral("album1")), 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newFiles2 = QList(); for (const auto &oneTrack : newTracks) { newFiles2.push_back(oneTrack.resourceURI()); } auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album1")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 8); QCOMPARE(musicDb.allTracks().count(), 23); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 4); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void reloadDatabaseWithAllTracks() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "reloadDatabaseWithAllTracks" << databaseFile.fileName(); { DatabaseInterface musicDb; QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } DatabaseInterface musicDb2; QSignalSpy musicDbArtistAddedSpy2(&musicDb2, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy2(&musicDb2, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy2(&musicDb2, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy2(&musicDb2, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy2(&musicDb2, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy2(&musicDb2, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy2(&musicDb2, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy2(&musicDb2, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy2(&musicDb2, &DatabaseInterface::databaseError); QCOMPARE(musicDb2.allAlbums().count(), 0); QCOMPARE(musicDb2.allArtistsData().count(), 0); QCOMPARE(musicDb2.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy2.count(), 0); QCOMPARE(musicDbAlbumAddedSpy2.count(), 0); QCOMPARE(musicDbTrackAddedSpy2.count(), 0); QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy2.count(), 0); QCOMPARE(musicDbTrackModifiedSpy2.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy2.count(), 0); musicDb2.init(QStringLiteral("testDb2"), databaseFile.fileName()); musicDbTrackAddedSpy2.wait(300); QCOMPARE(musicDb2.allAlbums().count(), 5); QCOMPARE(musicDb2.allArtistsData().count(), 7); QCOMPARE(musicDb2.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy2.count(), 1); QCOMPARE(musicDbAlbumAddedSpy2.count(), 1); QCOMPARE(musicDbTrackAddedSpy2.count(), 1); QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy2.count(), 0); QCOMPARE(musicDbTrackModifiedSpy2.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy2.count(), 0); musicDb2.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); QCOMPARE(musicDb2.allAlbums().count(), 5); QCOMPARE(musicDb2.allArtistsData().count(), 7); QCOMPARE(musicDb2.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy2.count(), 1); QCOMPARE(musicDbAlbumAddedSpy2.count(), 1); QCOMPARE(musicDbTrackAddedSpy2.count(), 1); QCOMPARE(musicDbArtistRemovedSpy2.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy2.count(), 0); QCOMPARE(musicDbTrackRemovedSpy2.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy2.count(), 1); QCOMPARE(musicDbTrackModifiedSpy2.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy2.count(), 0); } void testRemovalOfTracksFromInvalidSource() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.removeAllTracksFromSource(QStringLiteral("autoTestNotValid")); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void testRemovalOfTracksFromValidSource() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "testRemovalOfTracksFromValidSource" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QList secondNewTracks = { {true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track1"), QStringLiteral("artist6"), QStringLiteral("album7"), QStringLiteral("artist6"), 1, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 1, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$24"), QStringLiteral("0"), QStringLiteral("track2"), QStringLiteral("artist6"), QStringLiteral("album7"), QStringLiteral("artist6"), 2, 1, QTime::fromMSecsSinceStartOfDay(24), {QUrl::fromLocalFile(QStringLiteral("/$24"))}, QDateTime::fromMSecsSinceEpoch(24), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 2, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$25"), QStringLiteral("0"), QStringLiteral("track3"), QStringLiteral("artist6"), QStringLiteral("album7"), QStringLiteral("artist6"), 3, 1, QTime::fromMSecsSinceStartOfDay(25), {QUrl::fromLocalFile(QStringLiteral("/$25"))}, QDateTime::fromMSecsSinceEpoch(25), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 3, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$26"), QStringLiteral("0"), QStringLiteral("track4"), QStringLiteral("artist6"), QStringLiteral("album7"), QStringLiteral("artist6"), 4, 1, QTime::fromMSecsSinceStartOfDay(26), {QUrl::fromLocalFile(QStringLiteral("/$26"))}, QDateTime::fromMSecsSinceEpoch(26), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 4, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$27"), QStringLiteral("0"), QStringLiteral("track5"), QStringLiteral("artist6"), QStringLiteral("album7"), QStringLiteral("artist6"), 5, 1, QTime::fromMSecsSinceStartOfDay(27), {QUrl::fromLocalFile(QStringLiteral("/$27"))}, QDateTime::fromMSecsSinceEpoch(27), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 5, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$28"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist6"), QStringLiteral("album7"), QStringLiteral("artist6"), 6, 1, QTime::fromMSecsSinceStartOfDay(28), {QUrl::fromLocalFile(QStringLiteral("/$28"))}, QDateTime::fromMSecsSinceEpoch(28), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 6, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$29"), QStringLiteral("0"), QStringLiteral("track2"), QStringLiteral("artist2"), QStringLiteral("album1"), QStringLiteral("Various Artists"), 2, 2, QTime::fromMSecsSinceStartOfDay(29), {QUrl::fromLocalFile(QStringLiteral("/$29"))}, QDateTime::fromMSecsSinceEpoch(29), {QUrl::fromLocalFile(QStringLiteral("file://image$2"))}, 2, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, }; musicDb.insertTracksList(secondNewTracks, mNewCovers, QStringLiteral("autoTestSource2")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 6); QCOMPARE(musicDb.allArtistsData().count(), 8); QCOMPARE(musicDb.allTracks().count(), 28); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.removeAllTracksFromSource(QStringLiteral("autoTest")); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 3); QCOMPARE(musicDb.allTracks().count(), 7); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 2); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 5); QCOMPARE(musicDbAlbumRemovedSpy.count(), 4); QCOMPARE(musicDbTrackRemovedSpy.count(), 21); QCOMPARE(musicDbAlbumModifiedSpy.count(), 2); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void testAddAlbumsSameName() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "testAddAlbumsSameName" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QList newTracks = { {true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track1"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("artist6"), 1, 1, QTime::fromMSecsSinceStartOfDay(1), {QUrl::fromLocalFile(QStringLiteral("/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 1, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$21"), QStringLiteral("0"), QStringLiteral("track2"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("artist6"), 2, 1, QTime::fromMSecsSinceStartOfDay(2), {QUrl::fromLocalFile(QStringLiteral("/$21"))}, QDateTime::fromMSecsSinceEpoch(21), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 2, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$22"), QStringLiteral("0"), QStringLiteral("track3"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("artist6"), 3, 1, QTime::fromMSecsSinceStartOfDay(3), {QUrl::fromLocalFile(QStringLiteral("/$22"))}, QDateTime::fromMSecsSinceEpoch(22), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 3, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track4"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("artist6"), 4, 1, QTime::fromMSecsSinceStartOfDay(4), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 4, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$24"), QStringLiteral("0"), QStringLiteral("track5"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("artist6"), 5, 1, QTime::fromMSecsSinceStartOfDay(4), {QUrl::fromLocalFile(QStringLiteral("/$24"))}, QDateTime::fromMSecsSinceEpoch(24), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 5, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$25"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist6"), QStringLiteral("album1"), QStringLiteral("artist6"), 6, 1, QTime::fromMSecsSinceStartOfDay(5), {QUrl::fromLocalFile(QStringLiteral("/$25"))}, QDateTime::fromMSecsSinceEpoch(25), {QUrl::fromLocalFile(QStringLiteral("file://image$6"))}, 6, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$2"), QStringLiteral("0"), QStringLiteral("track2"), QStringLiteral("artist2"), QStringLiteral("album1"), QStringLiteral("Various Artists"), 2, 2, QTime::fromMSecsSinceStartOfDay(2), {QUrl::fromLocalFile(QStringLiteral("/$26"))}, QDateTime::fromMSecsSinceEpoch(26), {QUrl::fromLocalFile(QStringLiteral("file://image$2"))}, 2, false, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, }; musicDb.insertTracksList(newTracks, mNewCovers, QStringLiteral("autoTestSource2")); musicDbTrackAddedSpy.wait(100); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 3); QCOMPARE(musicDb.allTracks().count(), 7); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstAlbum = musicDb.albumFromTitleAndArtist(QStringLiteral("album1"), QStringLiteral("Invalid Artist")); } void addTwoIdenticalTracksWithPartialAlbumArtist() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksWithoutAlbumArtist" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), {}, 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), true},}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1)); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrack.title(), QStringLiteral("track6")); QCOMPARE(firstTrack.artist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.albumName(), QStringLiteral("album3")); QCOMPARE(firstTrack.albumArtist(), QStringLiteral("artist2")); QCOMPARE(firstTrack.isValidAlbumArtist(), false); QCOMPARE(firstTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrack.trackNumber(), 6); QCOMPARE(firstTrack.discNumber(), 1); QCOMPARE(firstTrack.duration(), QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(firstTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(firstTrack.rating(), 5); QCOMPARE(firstTrack.genre(), QStringLiteral("genre1")); QCOMPARE(firstTrack.composer(), QStringLiteral("composer1")); QCOMPARE(firstTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(firstTrack.albumId(), qulonglong(1)); QCOMPARE(firstTrack.hasEmbeddedCover(), true); auto newTracks2 = QList(); newTracks2 = {{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false},}; auto newCovers2 = mNewCovers; newCovers2[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks2, newCovers2, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void addTwoTracksWithPartialAlbumArtist2() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksWithPartialAlbumArtist" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist3"), QStringLiteral("album3"), {QStringLiteral("artist4")}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); newCovers[QStringLiteral("file:///$20")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks2 = QList(); newTracks2 = {{true, QStringLiteral("$19"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist4"), QStringLiteral("album3"), {}, 6, 1, QTime::fromMSecsSinceStartOfDay(19), {QUrl::fromLocalFile(QStringLiteral("/$19"))}, QDateTime::fromMSecsSinceEpoch(19), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), true}}; musicDb.insertTracksList(newTracks2, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 2); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist4"), QStringLiteral("album3"), 6, 1)); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrack.title(), QStringLiteral("track6")); QCOMPARE(firstTrack.artist(), QStringLiteral("artist4")); QCOMPARE(firstTrack.albumName(), QStringLiteral("album3")); QCOMPARE(firstTrack.albumArtist(), QStringLiteral("artist4")); QCOMPARE(firstTrack.isValidAlbumArtist(), true); QCOMPARE(firstTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrack.trackNumber(), 6); QCOMPARE(firstTrack.discNumber(), 1); QCOMPARE(firstTrack.duration(), QTime::fromMSecsSinceStartOfDay(19)); QCOMPARE(firstTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$19"))); QCOMPARE(firstTrack.rating(), 5); QCOMPARE(firstTrack.genre(), QStringLiteral("genre1")); QCOMPARE(firstTrack.composer(), QStringLiteral("composer1")); QCOMPARE(firstTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(firstTrack.albumId(), qulonglong(1)); QCOMPARE(firstTrack.hasEmbeddedCover(), true); auto secondTrack = musicDb.trackFromDatabaseId(musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track7"), QStringLiteral("artist3"), QStringLiteral("album3"), 7, 1)); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrack.title(), QStringLiteral("track7")); QCOMPARE(secondTrack.artist(), QStringLiteral("artist3")); QCOMPARE(secondTrack.albumName(), QStringLiteral("album3")); QCOMPARE(secondTrack.albumArtist(), QStringLiteral("artist4")); QCOMPARE(secondTrack.isValidAlbumArtist(), true); QCOMPARE(secondTrack.albumCover(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrack.trackNumber(), 7); QCOMPARE(secondTrack.discNumber(), 1); QCOMPARE(secondTrack.duration(), QTime::fromMSecsSinceStartOfDay(20)); QCOMPARE(secondTrack.resourceURI(), QUrl::fromLocalFile(QStringLiteral("/$20"))); QCOMPARE(secondTrack.rating(), 5); QCOMPARE(secondTrack.genre(), QStringLiteral("genre1")); QCOMPARE(secondTrack.composer(), QStringLiteral("composer1")); QCOMPARE(secondTrack.lyricist(), QStringLiteral("lyricist1")); QCOMPARE(secondTrack.albumId(), qulonglong(1)); QCOMPARE(secondTrack.hasEmbeddedCover(), false); auto album = musicDb.albumFromTitleAndArtist(QStringLiteral("album3"), QStringLiteral("artist4")); QCOMPARE(album.isValid(), true); QCOMPARE(album.tracksCount(), 2); QCOMPARE(album.title(), QStringLiteral("album3")); QCOMPARE(album.artist(), QStringLiteral("artist4")); QCOMPARE(album.isValidArtist(), true); QCOMPARE(album.albumArtURI(), QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(album.isSingleDiscAlbum(), true); } void addTowAlbumsWithDifferentPathsAndSameName() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTowAlbumsWithDifferentPathsAndSameName" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist1"), QStringLiteral("album7"), {}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/album7/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$21"), QStringLiteral("0"), QStringLiteral("track8"), QStringLiteral("artist2"), QStringLiteral("album7"), {}, 8, 1, QTime::fromMSecsSinceStartOfDay(21), {QUrl::fromLocalFile(QStringLiteral("/album7/$21"))}, QDateTime::fromMSecsSinceEpoch(21), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre2"), QStringLiteral("composer2"), QStringLiteral("lyricist2"), false}, {true, QStringLiteral("$22"), QStringLiteral("0"), QStringLiteral("track9"), QStringLiteral("artist3"), QStringLiteral("album7"), {}, 9, 1, QTime::fromMSecsSinceStartOfDay(22), {QUrl::fromLocalFile(QStringLiteral("/album8/$22"))}, QDateTime::fromMSecsSinceEpoch(22), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre3"), QStringLiteral("composer3"), QStringLiteral("lyricist3"), false}, {true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track10"), QStringLiteral("artist4"), QStringLiteral("album7"), {}, 10, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/album8/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre4"), QStringLiteral("composer4"), QStringLiteral("lyricist4"), false},}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///album7/$20")] = QUrl::fromLocalFile(QStringLiteral("album7")); newCovers[QStringLiteral("file:///album7/$21")] = QUrl::fromLocalFile(QStringLiteral("album7")); newCovers[QStringLiteral("file:///album8/$22")] = QUrl::fromLocalFile(QStringLiteral("album8")); newCovers[QStringLiteral("file:///album8/$23")] = QUrl::fromLocalFile(QStringLiteral("album8")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 4); QCOMPARE(musicDb.allTracks().count(), 4); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QCOMPARE(musicDb.allAlbums().size(), 2); QCOMPARE(musicDb.allArtistsData().size(), 4); QCOMPARE(musicDb.allTracks().size(), 4); auto allAlbums = musicDb.allAlbums(); auto firstAlbum = allAlbums[0]; QCOMPARE(firstAlbum.tracksCount(), 2); auto secondAlbum = allAlbums[1]; QCOMPARE(secondAlbum.tracksCount(), 2); } void addTowAlbumsWithDifferentPathsAndSameTracks() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTowAlbumsWithDifferentPathsAndSameName" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTracks = QList(); newTracks = {{true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist1"), QStringLiteral("album7"), {}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/album7/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$21"), QStringLiteral("0"), QStringLiteral("track8"), QStringLiteral("artist2"), QStringLiteral("album7"), {}, 8, 1, QTime::fromMSecsSinceStartOfDay(21), {QUrl::fromLocalFile(QStringLiteral("/album7/$21"))}, QDateTime::fromMSecsSinceEpoch(21), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre2"), QStringLiteral("composer2"), QStringLiteral("lyricist2"), false}, {true, QStringLiteral("$22"), QStringLiteral("0"), QStringLiteral("track9"), QStringLiteral("artist3"), QStringLiteral("album7"), {}, 9, 1, QTime::fromMSecsSinceStartOfDay(22), {QUrl::fromLocalFile(QStringLiteral("/album7/$22"))}, QDateTime::fromMSecsSinceEpoch(22), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre3"), QStringLiteral("composer3"), QStringLiteral("lyricist3"), false}, {true, QStringLiteral("$20"), QStringLiteral("0"), QStringLiteral("track7"), QStringLiteral("artist1"), QStringLiteral("album7"), {}, 7, 1, QTime::fromMSecsSinceStartOfDay(20), {QUrl::fromLocalFile(QStringLiteral("/album8/$20"))}, QDateTime::fromMSecsSinceEpoch(20), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}, {true, QStringLiteral("$21"), QStringLiteral("0"), QStringLiteral("track8"), QStringLiteral("artist2"), QStringLiteral("album7"), {}, 8, 1, QTime::fromMSecsSinceStartOfDay(21), {QUrl::fromLocalFile(QStringLiteral("/album8/$21"))}, QDateTime::fromMSecsSinceEpoch(21), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre2"), QStringLiteral("composer2"), QStringLiteral("lyricist2"), false}, {true, QStringLiteral("$22"), QStringLiteral("0"), QStringLiteral("track9"), QStringLiteral("artist3"), QStringLiteral("album7"), {}, 9, 1, QTime::fromMSecsSinceStartOfDay(22), {QUrl::fromLocalFile(QStringLiteral("/album8/$22"))}, QDateTime::fromMSecsSinceEpoch(22), {QUrl::fromLocalFile(QStringLiteral("album7"))}, 5, true, QStringLiteral("genre3"), QStringLiteral("composer3"), QStringLiteral("lyricist3"), false},}; auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///album7/$20")] = QUrl::fromLocalFile(QStringLiteral("album7")); newCovers[QStringLiteral("file:///album7/$21")] = QUrl::fromLocalFile(QStringLiteral("album7")); newCovers[QStringLiteral("file:///album7/$22")] = QUrl::fromLocalFile(QStringLiteral("album7")); newCovers[QStringLiteral("file:///album8/$20")] = QUrl::fromLocalFile(QStringLiteral("album8")); newCovers[QStringLiteral("file:///album8/$21")] = QUrl::fromLocalFile(QStringLiteral("album8")); newCovers[QStringLiteral("file:///album8/$22")] = QUrl::fromLocalFile(QStringLiteral("album8")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 2); QCOMPARE(musicDb.allArtistsData().count(), 3); QCOMPARE(musicDb.allTracks().count(), 6); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto allAlbums = musicDb.allAlbums(); auto firstAlbum = allAlbums[0]; QCOMPARE(firstAlbum.tracksCount(), 3); auto secondAlbum = allAlbums[1]; QCOMPARE(secondAlbum.tracksCount(), 3); } void addTwoTracksFromSameAlbumButDifferentDiscs() { QTemporaryFile databaseFile; databaseFile.open(); qDebug() << "addTwoTracksFromSameAlbumButDifferentDiscs" << databaseFile.fileName(); DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb"), databaseFile.fileName()); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/$23"))}, QDateTime::fromMSecsSinceEpoch(23), {QUrl::fromLocalFile(QStringLiteral("album3"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto firstTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), 6, 1); auto firstTrack = musicDb.trackFromDatabaseId(firstTrackId); auto firstTrackTitle = firstTrack.title(); auto firstTrackArtist = firstTrack.artist(); auto firstTrackAlbumArtist = firstTrack.albumArtist(); auto firstTrackAlbum = firstTrack.albumName(); auto firstTrackImage = firstTrack.albumCover(); auto firstTrackDuration = firstTrack.duration(); auto firstTrackMilliSecondsDuration = firstTrack.duration().msecsSinceStartOfDay(); auto firstTrackTrackNumber = firstTrack.trackNumber(); auto firstTrackDiscNumber = firstTrack.discNumber(); const auto &firstTrackResource = firstTrack.resourceURI(); auto firstTrackRating = firstTrack.rating(); auto firstIsSingleDiscAlbum = firstTrack.isSingleDiscAlbum(); QCOMPARE(firstTrack.isValid(), true); QCOMPARE(firstTrackTitle, QStringLiteral("track6")); QCOMPARE(firstTrackArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstTrackAlbum, QStringLiteral("album3")); QCOMPARE(firstTrackImage.isValid(), true); QCOMPARE(firstTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); QCOMPARE(firstTrackMilliSecondsDuration, 23); QCOMPARE(firstTrackTrackNumber, 6); QCOMPARE(firstTrackDiscNumber, 1); QCOMPARE(firstTrackResource.isValid(), true); QCOMPARE(firstTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); QCOMPARE(firstTrackRating, 5); QCOMPARE(firstIsSingleDiscAlbum, true); auto allAlbums = musicDb.allAlbums(); QCOMPARE(allAlbums.size(), 1); auto firstAlbumTitle = allAlbums[0].title(); auto firstAlbumArtist = allAlbums[0].artist(); auto firstAlbumImage = allAlbums[0].albumArtURI(); auto firstAlbumTracksCount = allAlbums[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum = allAlbums[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage.isValid(), true); QCOMPARE(firstAlbumImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount, 1); QCOMPARE(firstAlbumIsSingleDiscAlbum, true); auto newTrack2 = MusicAudioTrack{true, QStringLiteral("$25"), QStringLiteral("0"), QStringLiteral("track8"), QStringLiteral("artist9"), QStringLiteral("album3"), QStringLiteral("artist2"), 8, 2, QTime::fromMSecsSinceStartOfDay(25), {QUrl::fromLocalFile(QStringLiteral("/$25"))}, QDateTime::fromMSecsSinceEpoch(25), {QUrl::fromLocalFile(QStringLiteral("file://image$25"))}, 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks2 = QList(); newTracks2.push_back(newTrack2); auto newCovers2 = mNewCovers; newCovers2[QStringLiteral("file:///$25")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks2, newCovers2, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(50); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 2); QCOMPARE(musicDb.allTracks().count(), 2); QCOMPARE(musicDbArtistAddedSpy.count(), 2); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 2); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 1); QCOMPARE(musicDbTrackModifiedSpy.count(), 1); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto secondTrackId = musicDb.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track8"), QStringLiteral("artist9"), QStringLiteral("album3"), 8, 2); auto secondTrack = musicDb.trackFromDatabaseId(secondTrackId); auto secondTrackTitle = secondTrack.title(); auto secondTrackArtist = secondTrack.artist(); auto secondTrackAlbumArtist = secondTrack.albumArtist(); auto secondTrackAlbum = secondTrack.albumName(); auto secondTrackImage = secondTrack.albumCover(); auto secondTrackDuration = secondTrack.duration(); auto secondTrackMilliSecondsDuration = secondTrack.duration().msecsSinceStartOfDay(); auto secondTrackTrackNumber = secondTrack.trackNumber(); auto secondTrackDiscNumber = secondTrack.discNumber(); const auto &secondTrackResource = secondTrack.resourceURI(); auto secondTrackRating = secondTrack.rating(); auto secondIsSingleDiscAlbum = secondTrack.isSingleDiscAlbum(); QCOMPARE(secondTrack.isValid(), true); QCOMPARE(secondTrackTitle, QStringLiteral("track8")); QCOMPARE(secondTrackArtist, QStringLiteral("artist9")); QCOMPARE(secondTrackAlbumArtist, QStringLiteral("artist2")); QCOMPARE(secondTrackAlbum, QStringLiteral("album3")); QCOMPARE(secondTrackImage.isValid(), true); QCOMPARE(secondTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(secondTrackDuration, QTime::fromMSecsSinceStartOfDay(25)); QCOMPARE(secondTrackMilliSecondsDuration, 25); QCOMPARE(secondTrackTrackNumber, 8); QCOMPARE(secondTrackDiscNumber, 2); QCOMPARE(secondTrackResource.isValid(), true); QCOMPARE(secondTrackResource, QUrl::fromLocalFile(QStringLiteral("/$25"))); QCOMPARE(secondTrackRating, 5); QCOMPARE(secondIsSingleDiscAlbum, false); const auto &modifiedTrackSignal = musicDbTrackModifiedSpy.at(0); QCOMPARE(modifiedTrackSignal.count(), 1); const auto &modifiedTrack = modifiedTrackSignal.at(0).value(); // auto modifiedTrackTitle = modifiedTrack.title(); // auto modifiedTrackArtist = modifiedTrack.artist(); // auto modifiedTrackAlbumArtist = modifiedTrack.albumArtist(); // auto modifiedTrackAlbum = modifiedTrack.albumName(); // auto modifiedTrackImage = modifiedTrack.albumCover(); // auto modifiedTrackDuration = modifiedTrack.duration(); // auto modifiedTrackMilliSecondsDuration = modifiedTrack.duration().msecsSinceStartOfDay(); // auto modifiedTrackTrackNumber = modifiedTrack.trackNumber(); // auto modifiedTrackDiscNumber = modifiedTrack.discNumber(); // const auto &modifiedTrackResource = modifiedTrack.resourceURI(); // auto modifiedTrackRating = modifiedTrack.rating(); // auto modifiedTrackIsSingleDiscAlbum = modifiedTrack.isSingleDiscAlbum(); // QCOMPARE(modifiedTrack.isValid(), true); // QCOMPARE(modifiedTrackTitle, QStringLiteral("track6")); // QCOMPARE(modifiedTrackArtist, QStringLiteral("artist2")); // QCOMPARE(modifiedTrackAlbumArtist, QStringLiteral("artist2")); // QCOMPARE(modifiedTrackAlbum, QStringLiteral("album3")); // QCOMPARE(modifiedTrackImage.isValid(), true); // QCOMPARE(modifiedTrackImage, QUrl::fromLocalFile(QStringLiteral("album3"))); // QCOMPARE(modifiedTrackDuration, QTime::fromMSecsSinceStartOfDay(23)); // QCOMPARE(modifiedTrackMilliSecondsDuration, 23); // QCOMPARE(modifiedTrackTrackNumber, 6); // QCOMPARE(modifiedTrackDiscNumber, 1); // QCOMPARE(modifiedTrackResource.isValid(), true); // QCOMPARE(modifiedTrackResource, QUrl::fromLocalFile(QStringLiteral("/$23"))); // QCOMPARE(modifiedTrackRating, 5); // QCOMPARE(modifiedTrackIsSingleDiscAlbum, false); auto allAlbums2 = musicDb.allAlbums(); auto firstAlbumTitle2 = allAlbums2[0].title(); auto firstAlbumArtist2 = allAlbums2[0].artist(); auto firstAlbumImage2 = allAlbums2[0].albumArtURI(); auto firstAlbumTracksCount2 = allAlbums2[0].tracksCount(); auto firstAlbumIsSingleDiscAlbum2 = allAlbums2[0].isSingleDiscAlbum(); QCOMPARE(firstAlbumTitle2, QStringLiteral("album3")); QCOMPARE(firstAlbumArtist2, QStringLiteral("artist2")); QCOMPARE(firstAlbumImage2.isValid(), true); QCOMPARE(firstAlbumImage2, QUrl::fromLocalFile(QStringLiteral("album3"))); QCOMPARE(firstAlbumTracksCount2, 2); QCOMPARE(firstAlbumIsSingleDiscAlbum2, false); } void addTwoIdenticalInvalidTracks() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), {}, {}, {}, {}, {}, {}, {}, {QUrl::fromLocalFile(QStringLiteral("file:///$23"))}, QDateTime::fromMSecsSinceEpoch(23), {}, {}, {}, {}, {}, {}, false}; auto newTracks = QList(); newTracks.push_back(newTrack); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("file:///$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } void checkRestoredTracks() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QSignalSpy musicDbRestoredTracksSpy(&musicDb, &DatabaseInterface::restoredTracks); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QCOMPARE(musicDbRestoredTracksSpy.count(), 0); musicDb.insertTracksList(mNewTracks, mNewCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QCOMPARE(musicDbRestoredTracksSpy.count(), 0); musicDb.askRestoredTracks(QStringLiteral("autoTest")); QCOMPARE(musicDb.allAlbums().count(), 5); QCOMPARE(musicDb.allArtistsData().count(), 7); QCOMPARE(musicDb.allTracks().count(), 22); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); QCOMPARE(musicDbRestoredTracksSpy.count(), 1); const auto &firstSignal = musicDbRestoredTracksSpy.at(0); QCOMPARE(firstSignal.count(), 2); const auto &restoredSource = firstSignal.at(0).toString(); QCOMPARE(restoredSource, QStringLiteral("autoTest")); const auto &restoredTracks = firstSignal.at(1).value>(); QCOMPARE(restoredTracks.count(), 23); } void addOneTrackWithParticularPath() { DatabaseInterface musicDb; musicDb.init(QStringLiteral("testDb")); QSignalSpy musicDbArtistAddedSpy(&musicDb, &DatabaseInterface::artistsAdded); QSignalSpy musicDbAlbumAddedSpy(&musicDb, &DatabaseInterface::albumsAdded); QSignalSpy musicDbTrackAddedSpy(&musicDb, &DatabaseInterface::tracksAdded); QSignalSpy musicDbArtistRemovedSpy(&musicDb, &DatabaseInterface::artistRemoved); QSignalSpy musicDbAlbumRemovedSpy(&musicDb, &DatabaseInterface::albumRemoved); QSignalSpy musicDbTrackRemovedSpy(&musicDb, &DatabaseInterface::trackRemoved); QSignalSpy musicDbAlbumModifiedSpy(&musicDb, &DatabaseInterface::albumModified); QSignalSpy musicDbTrackModifiedSpy(&musicDb, &DatabaseInterface::trackModified); QSignalSpy musicDbDatabaseErrorSpy(&musicDb, &DatabaseInterface::databaseError); QCOMPARE(musicDb.allAlbums().count(), 0); QCOMPARE(musicDb.allArtistsData().count(), 0); QCOMPARE(musicDb.allTracks().count(), 0); QCOMPARE(musicDbArtistAddedSpy.count(), 0); QCOMPARE(musicDbAlbumAddedSpy.count(), 0); QCOMPARE(musicDbTrackAddedSpy.count(), 0); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); auto newTrack = MusicAudioTrack{true, QStringLiteral("$23"), QStringLiteral("0"), QStringLiteral("track6"), QStringLiteral("artist2"), QStringLiteral("album3"), QStringLiteral("artist2"), 6, 1, QTime::fromMSecsSinceStartOfDay(23), {QUrl::fromLocalFile(QStringLiteral("/test{{test}}/$23"))}, QDateTime::fromMSecsSinceEpoch(23), QUrl::fromLocalFile(QStringLiteral("album3")), 5, true, QStringLiteral("genre1"), QStringLiteral("composer1"), QStringLiteral("lyricist1"), false}; auto newTracks = QList(); newTracks.push_back(newTrack); auto newCovers = mNewCovers; newCovers[QStringLiteral("/test{{test}}/$23")] = QUrl::fromLocalFile(QStringLiteral("album3")); musicDb.insertTracksList(newTracks, newCovers, QStringLiteral("autoTest")); musicDbTrackAddedSpy.wait(300); QCOMPARE(musicDb.allAlbums().count(), 1); QCOMPARE(musicDb.allArtistsData().count(), 1); QCOMPARE(musicDb.allTracks().count(), 1); QCOMPARE(musicDbArtistAddedSpy.count(), 1); QCOMPARE(musicDbAlbumAddedSpy.count(), 1); QCOMPARE(musicDbTrackAddedSpy.count(), 1); QCOMPARE(musicDbArtistRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumRemovedSpy.count(), 0); QCOMPARE(musicDbTrackRemovedSpy.count(), 0); QCOMPARE(musicDbAlbumModifiedSpy.count(), 0); QCOMPARE(musicDbTrackModifiedSpy.count(), 0); QCOMPARE(musicDbDatabaseErrorSpy.count(), 0); } }; QTEST_GUILESS_MAIN(DatabaseInterfaceTests) #include "databaseinterfacetest.moc" diff --git a/src/databaseinterface.cpp b/src/databaseinterface.cpp index 0816f78c..de702610 100644 --- a/src/databaseinterface.cpp +++ b/src/databaseinterface.cpp @@ -1,5243 +1,5243 @@ /* * Copyright 2016-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 "databaseinterface.h" #include #include #include #include #include #include #include #include #include #include #include class DatabaseInterfacePrivate { public: DatabaseInterfacePrivate(const QSqlDatabase &tracksDatabase) : mTracksDatabase(tracksDatabase), mSelectAlbumQuery(mTracksDatabase), mSelectTrackQuery(mTracksDatabase), mSelectAlbumIdFromTitleQuery(mTracksDatabase), mInsertAlbumQuery(mTracksDatabase), mSelectTrackIdFromTitleAlbumIdArtistQuery(mTracksDatabase), mInsertTrackQuery(mTracksDatabase), mSelectTracksFromArtist(mTracksDatabase), mSelectTrackFromIdQuery(mTracksDatabase), mSelectCountAlbumsForArtistQuery(mTracksDatabase), mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery(mTracksDatabase), mSelectAllAlbumsQuery(mTracksDatabase), mSelectAllAlbumsFromArtistQuery(mTracksDatabase), mSelectAllArtistsQuery(mTracksDatabase), mInsertArtistsQuery(mTracksDatabase), mSelectArtistByNameQuery(mTracksDatabase), mSelectArtistQuery(mTracksDatabase), mSelectTrackFromFilePathQuery(mTracksDatabase), mRemoveTrackQuery(mTracksDatabase), mRemoveAlbumQuery(mTracksDatabase), mRemoveArtistQuery(mTracksDatabase), mSelectAllTracksQuery(mTracksDatabase), mInsertTrackMapping(mTracksDatabase), mSelectAllTracksFromSourceQuery(mTracksDatabase), mInsertMusicSource(mTracksDatabase), mSelectMusicSource(mTracksDatabase), mUpdateTrackMapping(mTracksDatabase), mSelectTracksMapping(mTracksDatabase), mSelectTracksMappingPriority(mTracksDatabase), mUpdateAlbumArtUriFromAlbumIdQuery(mTracksDatabase), mSelectTracksMappingPriorityByTrackId(mTracksDatabase), mSelectAllTrackFilesFromSourceQuery(mTracksDatabase), mSelectAlbumIdsFromArtist(mTracksDatabase), mRemoveTracksMappingFromSource(mTracksDatabase), mRemoveTracksMapping(mTracksDatabase), mSelectTracksWithoutMappingQuery(mTracksDatabase), mSelectAlbumIdFromTitleAndArtistQuery(mTracksDatabase), mSelectAlbumIdFromTitleWithoutArtistQuery(mTracksDatabase), mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery(mTracksDatabase), mSelectAlbumArtUriFromAlbumIdQuery(mTracksDatabase), mInsertComposerQuery(mTracksDatabase), mSelectComposerByNameQuery(mTracksDatabase), mSelectComposerQuery(mTracksDatabase), mInsertLyricistQuery(mTracksDatabase), mSelectLyricistByNameQuery(mTracksDatabase), mSelectLyricistQuery(mTracksDatabase), mInsertGenreQuery(mTracksDatabase), mSelectGenreByNameQuery(mTracksDatabase), mSelectGenreQuery(mTracksDatabase), mSelectAllTracksShortQuery(mTracksDatabase), mSelectAllAlbumsShortQuery(mTracksDatabase), mSelectAllComposersQuery(mTracksDatabase), mSelectAllLyricistsQuery(mTracksDatabase), mSelectCountAlbumsForComposerQuery(mTracksDatabase), mSelectCountAlbumsForLyricistQuery(mTracksDatabase), mSelectAllGenresQuery(mTracksDatabase), mSelectGenreForArtistQuery(mTracksDatabase), mSelectGenreForAlbumQuery(mTracksDatabase), mUpdateTrackQuery(mTracksDatabase), mUpdateAlbumArtistQuery(mTracksDatabase), mUpdateAlbumArtistInTracksQuery(mTracksDatabase), mQueryMaximumTrackIdQuery(mTracksDatabase), mQueryMaximumAlbumIdQuery(mTracksDatabase), mQueryMaximumArtistIdQuery(mTracksDatabase), mQueryMaximumLyricistIdQuery(mTracksDatabase), mQueryMaximumComposerIdQuery(mTracksDatabase), mQueryMaximumGenreIdQuery(mTracksDatabase) { } QSqlDatabase mTracksDatabase; QSqlQuery mSelectAlbumQuery; QSqlQuery mSelectTrackQuery; QSqlQuery mSelectAlbumIdFromTitleQuery; QSqlQuery mInsertAlbumQuery; QSqlQuery mSelectTrackIdFromTitleAlbumIdArtistQuery; QSqlQuery mInsertTrackQuery; QSqlQuery mSelectTracksFromArtist; QSqlQuery mSelectTrackFromIdQuery; QSqlQuery mSelectCountAlbumsForArtistQuery; QSqlQuery mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery; QSqlQuery mSelectAllAlbumsQuery; QSqlQuery mSelectAllAlbumsFromArtistQuery; QSqlQuery mSelectAllArtistsQuery; QSqlQuery mInsertArtistsQuery; QSqlQuery mSelectArtistByNameQuery; QSqlQuery mSelectArtistQuery; QSqlQuery mSelectTrackFromFilePathQuery; QSqlQuery mRemoveTrackQuery; QSqlQuery mRemoveAlbumQuery; QSqlQuery mRemoveArtistQuery; QSqlQuery mSelectAllTracksQuery; QSqlQuery mInsertTrackMapping; QSqlQuery mSelectAllTracksFromSourceQuery; QSqlQuery mInsertMusicSource; QSqlQuery mSelectMusicSource; QSqlQuery mUpdateTrackMapping; QSqlQuery mSelectTracksMapping; QSqlQuery mSelectTracksMappingPriority; QSqlQuery mUpdateAlbumArtUriFromAlbumIdQuery; QSqlQuery mSelectTracksMappingPriorityByTrackId; QSqlQuery mSelectAllTrackFilesFromSourceQuery; QSqlQuery mSelectAlbumIdsFromArtist; QSqlQuery mRemoveTracksMappingFromSource; QSqlQuery mRemoveTracksMapping; QSqlQuery mSelectTracksWithoutMappingQuery; QSqlQuery mSelectAlbumIdFromTitleAndArtistQuery; QSqlQuery mSelectAlbumIdFromTitleWithoutArtistQuery; QSqlQuery mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery; QSqlQuery mSelectAlbumArtUriFromAlbumIdQuery; QSqlQuery mInsertComposerQuery; QSqlQuery mSelectComposerByNameQuery; QSqlQuery mSelectComposerQuery; QSqlQuery mInsertLyricistQuery; QSqlQuery mSelectLyricistByNameQuery; QSqlQuery mSelectLyricistQuery; QSqlQuery mInsertGenreQuery; QSqlQuery mSelectGenreByNameQuery; QSqlQuery mSelectGenreQuery; QSqlQuery mSelectAllTracksShortQuery; QSqlQuery mSelectAllAlbumsShortQuery; QSqlQuery mSelectAllComposersQuery; QSqlQuery mSelectAllLyricistsQuery; QSqlQuery mSelectCountAlbumsForComposerQuery; QSqlQuery mSelectCountAlbumsForLyricistQuery; QSqlQuery mSelectAllGenresQuery; QSqlQuery mSelectGenreForArtistQuery; QSqlQuery mSelectGenreForAlbumQuery; QSqlQuery mUpdateTrackQuery; QSqlQuery mUpdateAlbumArtistQuery; QSqlQuery mUpdateAlbumArtistInTracksQuery; QSqlQuery mQueryMaximumTrackIdQuery; QSqlQuery mQueryMaximumAlbumIdQuery; QSqlQuery mQueryMaximumArtistIdQuery; QSqlQuery mQueryMaximumLyricistIdQuery; QSqlQuery mQueryMaximumComposerIdQuery; QSqlQuery mQueryMaximumGenreIdQuery; QHash mTracksCache; QHash mAlbumsCache; QSet mModifiedTrackIds; QSet mModifiedAlbumIds; QSet mModifiedArtistIds; QSet mInsertedTracks; QSet mInsertedAlbums; QSet mInsertedArtists; qulonglong mAlbumId = 1; qulonglong mArtistId = 1; qulonglong mComposerId = 1; qulonglong mLyricistId = 1; qulonglong mGenreId = 1; qulonglong mTrackId = 1; qulonglong mDiscoverId = 1; QAtomicInt mStopRequest = 0; bool mInitFinished = false; }; DatabaseInterface::DatabaseInterface(QObject *parent) : QObject(parent), d(nullptr) { } DatabaseInterface::~DatabaseInterface() { if (d) { d->mTracksDatabase.close(); } } void DatabaseInterface::init(const QString &dbName, const QString &databaseFileName) { QSqlDatabase tracksDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), dbName); if (!databaseFileName.isEmpty()) { tracksDatabase.setDatabaseName(QStringLiteral("file:") + databaseFileName); } else { tracksDatabase.setDatabaseName(QStringLiteral("file:memdb1?mode=memory")); } tracksDatabase.setConnectOptions(QStringLiteral("foreign_keys = ON;locking_mode = EXCLUSIVE;QSQLITE_OPEN_URI;QSQLITE_BUSY_TIMEOUT=500000")); auto result = tracksDatabase.open(); if (result) { qDebug() << "database open"; } else { qDebug() << "database not open"; } qDebug() << "DatabaseInterface::init" << (tracksDatabase.driver()->hasFeature(QSqlDriver::Transactions) ? "yes" : "no"); tracksDatabase.exec(QStringLiteral("PRAGMA foreign_keys = ON;")); d = std::make_unique(tracksDatabase); initDatabase(); initRequest(); if (!databaseFileName.isEmpty()) { reloadExistingDatabase(); } } MusicAlbum DatabaseInterface::albumFromTitleAndArtist(const QString &title, const QString &artist) { auto result = MusicAlbum(); auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalAlbumFromTitleAndArtist(title, artist); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } DatabaseInterface::ListTrackDataType DatabaseInterface::allTracksData() { auto result = ListTrackDataType{}; if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalAllTracksPartialData(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } DatabaseInterface::ListAlbumDataType DatabaseInterface::allAlbumsData() { auto result = ListAlbumDataType{}; if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalAllAlbumsPartialData(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } DatabaseInterface::ListTrackDataType DatabaseInterface::albumData(qulonglong databaseId) { auto result = ListTrackDataType{}; if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } d->mSelectTrackQuery.bindValue(QStringLiteral(":albumId"), databaseId); auto queryResult = d->mSelectTrackQuery.exec(); if (!queryResult || !d->mSelectTrackQuery.isSelect() || !d->mSelectTrackQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::albumData" << d->mSelectTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::albumData" << d->mSelectTrackQuery.boundValues(); qDebug() << "DatabaseInterface::albumData" << d->mSelectTrackQuery.lastError(); } while (d->mSelectTrackQuery.next()) { const auto ¤tRecord = d->mSelectTrackQuery.record(); result.push_back(buildTrackDataFromDatabaseRecord(currentRecord)); } d->mSelectTrackQuery.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } DatabaseInterface::ListArtistDataType DatabaseInterface::allArtistsData() { auto result = ListArtistDataType{}; if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalAllArtistsPartialData(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } DatabaseInterface::ListGenreDataType DatabaseInterface::allGenresData() { auto result = ListGenreDataType{}; if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalAllGenresPartialData(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } DatabaseInterface::DataType DatabaseInterface::oneData(ElisaUtils::PlayListEntryType aType, qulonglong databaseId) { auto result = DataType{}; if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } switch (aType) { case ElisaUtils::Artist: result = internalOneArtistPartialData(databaseId); break; case ElisaUtils::Album: result = internalOneAlbumPartialData(databaseId); break; case ElisaUtils::Track: result = internalOneTrackPartialData(databaseId); break; case ElisaUtils::Genre: result = internalOneGenrePartialData(databaseId); break; case ElisaUtils::Composer: result = internalOneComposerPartialData(databaseId); break; case ElisaUtils::Lyricist: result = internalOneLyricistPartialData(databaseId); break; case ElisaUtils::Unknown: case ElisaUtils::FileName: break; }; transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } QList DatabaseInterface::allTracks() { auto result = QList(); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } auto queryResult = d->mSelectAllTracksQuery.exec(); if (!queryResult || !d->mSelectAllTracksQuery.isSelect() || !d->mSelectAllTracksQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllTracksQuery.lastQuery(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllTracksQuery.boundValues(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllTracksQuery.lastError(); return result; } while(d->mSelectAllTracksQuery.next()) { const auto ¤tRecord = d->mSelectAllTracksQuery.record(); result.push_back(buildTrackFromDatabaseRecord(currentRecord)); } d->mSelectAllTracksQuery.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } QList DatabaseInterface::allTracksFromSource(const QString &musicSource) { auto result = QList(); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } d->mSelectAllTracksFromSourceQuery.bindValue(QStringLiteral(":source"), musicSource); auto queryResult = d->mSelectAllTracksFromSourceQuery.exec(); if (!queryResult || !d->mSelectAllTracksFromSourceQuery.isSelect() || !d->mSelectAllTracksFromSourceQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllTracksFromSourceQuery.lastQuery(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllTracksFromSourceQuery.boundValues(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllTracksFromSourceQuery.lastError(); d->mSelectAllTracksFromSourceQuery.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } while(d->mSelectAllTracksFromSourceQuery.next()) { const auto ¤tRecord = d->mSelectAllTracksFromSourceQuery.record(); result.push_back(buildTrackFromDatabaseRecord(currentRecord)); } d->mSelectAllTracksFromSourceQuery.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } QList DatabaseInterface::allAlbums() { auto result = QList(); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } auto queryResult = d->mSelectAllAlbumsQuery.exec(); if (!queryResult || !d->mSelectAllAlbumsQuery.isSelect() || !d->mSelectAllAlbumsQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllAlbumsQuery.lastQuery(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllAlbumsQuery.boundValues(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllAlbumsQuery.lastError(); return result; } while(d->mSelectAllAlbumsQuery.next()) { const auto ¤tRecord = d->mSelectAllAlbumsQuery.record(); auto albumId = currentRecord.value(0).toULongLong(); auto &newAlbum = d->mAlbumsCache[albumId]; if (newAlbum.isValid()) { result.push_back(newAlbum); continue; } newAlbum.setDatabaseId(albumId); newAlbum.setTitle(currentRecord.value(1).toString()); newAlbum.setId(currentRecord.value(2).toString()); newAlbum.setArtist(currentRecord.value(3).toString()); newAlbum.setAlbumPath(currentRecord.value(4).toUrl()); newAlbum.setAlbumArtURI(currentRecord.value(5).toUrl()); newAlbum.setTracksCount(currentRecord.value(6).toInt()); newAlbum.setIsSingleDiscAlbum(currentRecord.value(7).toBool()); newAlbum.setTracks(fetchTracks(newAlbum.databaseId())); newAlbum.setValid(true); d->mSelectGenreForAlbumQuery.bindValue(QStringLiteral(":albumId"), newAlbum.databaseId()); queryResult = d->mSelectGenreForAlbumQuery.exec(); if (!queryResult || !d->mSelectGenreForAlbumQuery.isSelect() || !d->mSelectGenreForAlbumQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectGenreForAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectGenreForAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectGenreForAlbumQuery.lastError(); d->mSelectGenreForAlbumQuery.finish(); return result; } QStringList allGenres; while(d->mSelectGenreForAlbumQuery.next()) { allGenres.push_back(d->mSelectGenreForAlbumQuery.record().value(0).toString()); } newAlbum.setGenres(allGenres); d->mSelectGenreForAlbumQuery.finish(); result.push_back(newAlbum); } d->mSelectAllAlbumsQuery.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } QList DatabaseInterface::allGenres() { auto result = QList(); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } auto queryResult = d->mSelectAllGenresQuery.exec(); if (!queryResult || !d->mSelectAllGenresQuery.isSelect() || !d->mSelectAllGenresQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllGenresQuery.lastQuery(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllGenresQuery.boundValues(); qDebug() << "DatabaseInterface::allAlbums" << d->mSelectAllGenresQuery.lastError(); return result; } while(d->mSelectAllGenresQuery.next()) { auto newGenre = MusicAudioGenre(); const auto ¤tRecord = d->mSelectAllGenresQuery.record(); newGenre.setDatabaseId(currentRecord.value(0).toULongLong()); newGenre.setName(currentRecord.value(1).toString()); result.push_back(newGenre); } d->mSelectAllGenresQuery.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } -DatabaseInterface::ListTrackDataType DatabaseInterface::tracksFromAuthor(const QString &ArtistName) +DatabaseInterface::ListTrackDataType DatabaseInterface::tracksDataFromAuthor(const QString &ArtistName) { auto allTracks = ListTrackDataType{}; auto transactionResult = startTransaction(); if (!transactionResult) { return allTracks; } allTracks = internalTracksFromAuthor(ArtistName); transactionResult = finishTransaction(); if (!transactionResult) { return allTracks; } return allTracks; } DatabaseInterface::TrackDataType DatabaseInterface::trackDataFromDatabaseId(qulonglong id) { auto result = TrackDataType(); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalOneTrackPartialData(id); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } MusicAudioTrack DatabaseInterface::trackFromDatabaseId(qulonglong id) { auto result = MusicAudioTrack(); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalTrackFromDatabaseId(id); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } qulonglong DatabaseInterface::trackIdFromTitleAlbumTrackDiscNumber(const QString &title, const QString &artist, const QString &album, int trackNumber, int discNumber) { auto result = qulonglong(0); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalTrackIdFromTitleAlbumTracDiscNumber(title, artist, album, trackNumber, discNumber); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } qulonglong DatabaseInterface::trackIdFromFileName(const QUrl &fileName) { auto result = qulonglong(0); if (!d) { return result; } auto transactionResult = startTransaction(); if (!transactionResult) { return result; } result = internalTrackIdFromFileName(fileName); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } void DatabaseInterface::applicationAboutToQuit() { d->mStopRequest = 1; } void DatabaseInterface::removeAllTracksFromSource(const QString &sourceName) { auto transactionResult = startTransaction(); if (!transactionResult) { return; } initChangesTrackers(); auto sourceId = internalSourceIdFromName(sourceName); auto allFileNames = internalAllFileNameFromSource(sourceId); internalRemoveTracksList(allFileNames, sourceId); if (!d->mInsertedArtists.isEmpty()) { ListArtistDataType newArtists; for (auto artistId : qAsConst(d->mInsertedArtists)) { newArtists.push_back({{DatabaseIdRole, artistId}}); } Q_EMIT artistsAdded(newArtists); } transactionResult = finishTransaction(); if (!transactionResult) { return; } } void DatabaseInterface::getAlbumFromAlbumId(qulonglong id) { auto result = MusicAlbum(); auto transactionResult = startTransaction(); if (!transactionResult) { Q_EMIT sentAlbumData(result); } result = internalAlbumFromId(id); transactionResult = finishTransaction(); if (!transactionResult) { Q_EMIT sentAlbumData(result); } Q_EMIT sentAlbumData(result); } void DatabaseInterface::askRestoredTracks(const QString &musicSource) { auto transactionResult = startTransaction(); if (!transactionResult) { return; } auto result = internalAllFileNameFromSource(internalSourceIdFromName(musicSource)); Q_EMIT restoredTracks(musicSource, result); transactionResult = finishTransaction(); if (!transactionResult) { return; } } void DatabaseInterface::initChangesTrackers() { d->mModifiedTrackIds.clear(); d->mModifiedAlbumIds.clear(); d->mModifiedArtistIds.clear(); d->mInsertedTracks.clear(); d->mInsertedAlbums.clear(); d->mInsertedArtists.clear(); } void DatabaseInterface::recordModifiedTrack(qulonglong trackId) { d->mModifiedTrackIds.insert(trackId); d->mTracksCache.remove(trackId); } void DatabaseInterface::recordModifiedAlbum(qulonglong albumId) { d->mModifiedAlbumIds.insert(albumId); d->mAlbumsCache.remove(albumId); } void DatabaseInterface::insertTracksList(const QList &tracks, const QHash &covers, const QString &musicSource) { if (d->mStopRequest == 1) { return; } auto transactionResult = startTransaction(); if (!transactionResult) { return; } initChangesTrackers(); for(const auto &oneTrack : tracks) { d->mSelectTracksMapping.bindValue(QStringLiteral(":fileName"), oneTrack.resourceURI()); auto result = d->mSelectTracksMapping.exec(); if (!result || !d->mSelectTracksMapping.isSelect() || !d->mSelectTracksMapping.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertTracksList" << d->mSelectTracksMapping.lastQuery(); qDebug() << "DatabaseInterface::insertTracksList" << d->mSelectTracksMapping.boundValues(); qDebug() << "DatabaseInterface::insertTracksList" << d->mSelectTracksMapping.lastError(); d->mSelectTracksMapping.finish(); rollBackTransaction(); return; } bool isNewTrack = !d->mSelectTracksMapping.next(); if (isNewTrack) { insertTrackOrigin(oneTrack.resourceURI(), oneTrack.fileModificationTime(), insertMusicSource(musicSource)); } else if (!d->mSelectTracksMapping.record().value(0).isNull() && d->mSelectTracksMapping.record().value(0).toULongLong() != 0) { updateTrackOrigin(d->mSelectTracksMapping.record().value(0).toULongLong(), oneTrack.resourceURI(), oneTrack.fileModificationTime()); } else { continue; } d->mSelectTracksMapping.finish(); const auto insertedTrackId = internalInsertTrack(oneTrack, covers, 0, (isNewTrack ? TrackFileInsertType::NewTrackFileInsert : TrackFileInsertType::ModifiedTrackFileInsert)); if (isNewTrack && insertedTrackId != 0) { d->mInsertedTracks.insert(insertedTrackId); } if (d->mStopRequest == 1) { transactionResult = finishTransaction(); if (!transactionResult) { return; } return; } } if (!d->mInsertedArtists.isEmpty()) { ListArtistDataType newArtists; for (auto artistId : qAsConst(d->mInsertedArtists)) { newArtists.push_back({{DatabaseIdRole, artistId}}); } Q_EMIT artistsAdded(newArtists); } if (!d->mInsertedAlbums.isEmpty()) { ListAlbumDataType newAlbums; for (auto albumId : qAsConst(d->mInsertedAlbums)) { d->mModifiedAlbumIds.remove(albumId); newAlbums.push_back(internalOneAlbumPartialData(albumId)); } Q_EMIT albumsAdded(newAlbums); } for (auto albumId : qAsConst(d->mModifiedAlbumIds)) { Q_EMIT albumModified({{DatabaseIdRole, albumId}}, albumId); } if (!d->mInsertedTracks.isEmpty()) { ListTrackDataType newTracks; for (auto trackId : qAsConst(d->mInsertedTracks)) { newTracks.push_back(internalOneTrackPartialData(trackId)); d->mModifiedTrackIds.remove(trackId); } Q_EMIT tracksAdded(newTracks); } for (auto trackId : qAsConst(d->mModifiedTrackIds)) { Q_EMIT trackModified(internalOneTrackPartialData(trackId)); } transactionResult = finishTransaction(); if (!transactionResult) { return; } } void DatabaseInterface::removeTracksList(const QList &removedTracks) { auto transactionResult = startTransaction(); if (!transactionResult) { return; } initChangesTrackers(); internalRemoveTracksList(removedTracks); if (!d->mInsertedArtists.isEmpty()) { ListArtistDataType newArtists; for (auto artistId : qAsConst(d->mInsertedArtists)) { newArtists.push_back({{DatabaseIdRole, artistId}}); } Q_EMIT artistsAdded(newArtists); } transactionResult = finishTransaction(); if (!transactionResult) { return; } } void DatabaseInterface::modifyTracksList(const QList &modifiedTracks, const QHash &covers, const QString &musicSource) { auto transactionResult = startTransaction(); if (!transactionResult) { return; } initChangesTrackers(); for (const auto &oneModifiedTrack : modifiedTracks) { if (oneModifiedTrack.albumArtist().isEmpty()) { continue; } bool modifyExistingTrack = internalTrackFromDatabaseId(oneModifiedTrack.databaseId()).isValid() || (internalTrackIdFromFileName(oneModifiedTrack.resourceURI()) != 0); auto originTrackId = oneModifiedTrack.databaseId(); if (!originTrackId) { originTrackId = internalTrackIdFromFileName(oneModifiedTrack.resourceURI()); } if (!modifyExistingTrack) { insertTrackOrigin(oneModifiedTrack.resourceURI(), oneModifiedTrack.fileModificationTime(), insertMusicSource(musicSource)); } else { updateTrackOrigin(originTrackId, oneModifiedTrack.resourceURI(), oneModifiedTrack.fileModificationTime()); } const auto insertedTrackId = internalInsertTrack(oneModifiedTrack, covers, (modifyExistingTrack ? originTrackId : 0), (modifyExistingTrack ? TrackFileInsertType::ModifiedTrackFileInsert : TrackFileInsertType::NewTrackFileInsert)); if (!modifyExistingTrack && insertedTrackId != 0) { d->mInsertedTracks.insert(insertedTrackId); } } if (!d->mInsertedArtists.isEmpty()) { ListArtistDataType newArtists; for (auto artistId : qAsConst(d->mInsertedArtists)) { newArtists.push_back({{DatabaseIdRole, artistId}}); } Q_EMIT artistsAdded(newArtists); } if (!d->mInsertedAlbums.isEmpty()) { ListAlbumDataType newAlbums; for (auto albumId : qAsConst(d->mInsertedAlbums)) { d->mModifiedAlbumIds.remove(albumId); newAlbums.push_back(internalOneAlbumPartialData(albumId)); } Q_EMIT albumsAdded(newAlbums); } for (auto albumId : qAsConst(d->mModifiedAlbumIds)) { Q_EMIT albumModified({{DatabaseIdRole, albumId}}, albumId); } if (!d->mInsertedTracks.isEmpty()) { ListTrackDataType newTracks; for (auto trackId : qAsConst(d->mInsertedTracks)) { newTracks.push_back(internalOneTrackPartialData(trackId)); d->mModifiedTrackIds.remove(trackId); } Q_EMIT tracksAdded(newTracks); } for (auto trackId : qAsConst(d->mModifiedTrackIds)) { Q_EMIT trackModified(internalOneTrackPartialData(trackId)); } transactionResult = finishTransaction(); if (!transactionResult) { return; } } bool DatabaseInterface::startTransaction() const { auto result = false; auto transactionResult = d->mTracksDatabase.transaction(); if (!transactionResult) { qDebug() << "transaction failed" << d->mTracksDatabase.lastError() << d->mTracksDatabase.lastError().driverText(); return result; } result = true; return result; } bool DatabaseInterface::finishTransaction() const { auto result = false; auto transactionResult = d->mTracksDatabase.commit(); if (!transactionResult) { qDebug() << "commit failed" << d->mTracksDatabase.lastError() << d->mTracksDatabase.lastError().nativeErrorCode(); return result; } result = true; return result; } bool DatabaseInterface::rollBackTransaction() const { auto result = false; auto transactionResult = d->mTracksDatabase.rollback(); if (!transactionResult) { qDebug() << "commit failed" << d->mTracksDatabase.lastError() << d->mTracksDatabase.lastError().nativeErrorCode(); return result; } result = true; return result; } void DatabaseInterface::initDatabase() { auto transactionResult = startTransaction(); if (!transactionResult) { return; } auto listTables = d->mTracksDatabase.tables(); if (!listTables.contains(QStringLiteral("DatabaseVersionV7"))) { auto oldTables = QStringList{ QStringLiteral("DatabaseVersionV2"), QStringLiteral("DatabaseVersionV3"), QStringLiteral("DatabaseVersionV4"), QStringLiteral("DatabaseVersionV5"), QStringLiteral("DatabaseVersionV6"), QStringLiteral("AlbumsArtists"), QStringLiteral("TracksArtists"), QStringLiteral("TracksMapping"), QStringLiteral("Tracks"), QStringLiteral("Composer"), QStringLiteral("Genre"), QStringLiteral("Lyricist"), QStringLiteral("Albums"), QStringLiteral("DiscoverSource"), QStringLiteral("Artists"),}; for (const auto &oneTable : oldTables) { if (listTables.indexOf(oneTable) == -1) { continue; } QSqlQuery createSchemaQuery(d->mTracksDatabase); auto result = createSchemaQuery.exec(QStringLiteral("DROP TABLE ") + oneTable); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } listTables = d->mTracksDatabase.tables(); } if (!listTables.contains(QStringLiteral("DatabaseVersionV7"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `DatabaseVersionV7` (`Version` INTEGER PRIMARY KEY NOT NULL)")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("DiscoverSource"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `DiscoverSource` (`ID` INTEGER PRIMARY KEY NOT NULL, " "`Name` VARCHAR(55) NOT NULL, " "UNIQUE (`Name`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("Artists"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `Artists` (`ID` INTEGER PRIMARY KEY NOT NULL, " "`Name` VARCHAR(55) NOT NULL, " "UNIQUE (`Name`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("Composer"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `Composer` (`ID` INTEGER PRIMARY KEY NOT NULL, " "`Name` VARCHAR(55) NOT NULL, " "UNIQUE (`Name`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("Genre"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `Genre` (`ID` INTEGER PRIMARY KEY NOT NULL, " "`Name` VARCHAR(85) NOT NULL, " "UNIQUE (`Name`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("Lyricist"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `Lyricist` (`ID` INTEGER PRIMARY KEY NOT NULL, " "`Name` VARCHAR(55) NOT NULL, " "UNIQUE (`Name`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("Albums"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `Albums` (" "`ID` INTEGER PRIMARY KEY NOT NULL, " "`Title` VARCHAR(55) NOT NULL, " "`ArtistName` VARCHAR(55), " "`AlbumPath` VARCHAR(255) NOT NULL, " "`CoverFileName` VARCHAR(255) NOT NULL, " "`AlbumInternalID` VARCHAR(55), " "UNIQUE (`Title`, `ArtistName`, `AlbumPath`), " "CONSTRAINT fk_artists FOREIGN KEY (`ArtistName`) REFERENCES `Artists`(`Name`) " "ON DELETE CASCADE)")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); } } if (!listTables.contains(QStringLiteral("Tracks"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `Tracks` (" "`ID` INTEGER PRIMARY KEY NOT NULL, " "`Title` VARCHAR(85) NOT NULL, " "`ArtistName` VARCHAR(55), " "`AlbumTitle` VARCHAR(55), " "`AlbumArtistName` VARCHAR(55), " "`AlbumPath` VARCHAR(255), " "`TrackNumber` INTEGER DEFAULT -1, " "`DiscNumber` INTEGER DEFAULT -1, " "`Duration` INTEGER NOT NULL, " "`Rating` INTEGER NOT NULL DEFAULT 0, " "`GenreID` INTEGER DEFAULT -1, " "`ComposerID` INTEGER, " "`LyricistID` INTEGER, " "`Comment` VARCHAR(85) DEFAULT '', " "`Year` INTEGER DEFAULT 0, " "`Channels` INTEGER DEFAULT -1, " "`BitRate` INTEGER DEFAULT -1, " "`SampleRate` INTEGER DEFAULT -1, " "`HasEmbeddedCover` BOOLEAN NOT NULL, " "UNIQUE (" "`Title`, `AlbumTitle`, `AlbumArtistName`, " "`AlbumPath`, `TrackNumber`, `DiscNumber`" "), " "CONSTRAINT fk_artist FOREIGN KEY (`ArtistName`) REFERENCES `Artists`(`Name`), " "CONSTRAINT fk_tracks_composer FOREIGN KEY (`ComposerID`) REFERENCES `Composer`(`ID`), " "CONSTRAINT fk_tracks_lyricist FOREIGN KEY (`LyricistID`) REFERENCES `Lyricist`(`ID`), " "CONSTRAINT fk_tracks_genre FOREIGN KEY (`GenreID`) REFERENCES `Genre`(`ID`), " "CONSTRAINT fk_tracks_album FOREIGN KEY (" "`AlbumTitle`, `AlbumArtistName`, `AlbumPath`)" "REFERENCES `Albums`(`Title`, `ArtistName`, `AlbumPath`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); Q_EMIT databaseError(); } } if (!listTables.contains(QStringLiteral("TracksMapping"))) { QSqlQuery createSchemaQuery(d->mTracksDatabase); const auto &result = createSchemaQuery.exec(QStringLiteral("CREATE TABLE `TracksMapping` (" "`TrackID` INTEGER NULL, " "`DiscoverID` INTEGER NOT NULL, " "`FileName` VARCHAR(255) NOT NULL, " "`Priority` INTEGER NOT NULL, " "`FileModifiedTime` DATETIME NOT NULL, " "PRIMARY KEY (`FileName`), " "CONSTRAINT TracksUnique UNIQUE (`TrackID`, `Priority`), " "CONSTRAINT fk_tracksmapping_trackID FOREIGN KEY (`TrackID`) REFERENCES `Tracks`(`ID`) ON DELETE CASCADE, " "CONSTRAINT fk_tracksmapping_discoverID FOREIGN KEY (`DiscoverID`) REFERENCES `DiscoverSource`(`ID`))")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createSchemaQuery.lastError(); } } { QSqlQuery createTrackIndex(d->mTracksDatabase); const auto &result = createTrackIndex.exec(QStringLiteral("CREATE INDEX " "IF NOT EXISTS " "`TitleAlbumsIndex` ON `Albums` " "(`Title`)")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastError(); Q_EMIT databaseError(); } } { QSqlQuery createTrackIndex(d->mTracksDatabase); const auto &result = createTrackIndex.exec(QStringLiteral("CREATE INDEX " "IF NOT EXISTS " "`ArtistNameAlbumsIndex` ON `Albums` " "(`ArtistName`)")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastError(); Q_EMIT databaseError(); } } { QSqlQuery createTrackIndex(d->mTracksDatabase); const auto &result = createTrackIndex.exec(QStringLiteral("CREATE INDEX " "IF NOT EXISTS " "`TracksAlbumIndex` ON `Tracks` " "(`AlbumTitle`, `AlbumArtistName`, `AlbumPath`)")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastError(); Q_EMIT databaseError(); } } { QSqlQuery createTrackIndex(d->mTracksDatabase); const auto &result = createTrackIndex.exec(QStringLiteral("CREATE INDEX " "IF NOT EXISTS " "`TracksFileNameIndex` ON `TracksMapping` " "(`FileName`)")); if (!result) { qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastQuery(); qDebug() << "DatabaseInterface::initDatabase" << createTrackIndex.lastError(); Q_EMIT databaseError(); } } transactionResult = finishTransaction(); if (!transactionResult) { return; } } void DatabaseInterface::initRequest() { auto transactionResult = startTransaction(); if (!transactionResult) { return; } { auto selectAlbumQueryText = QStringLiteral("SELECT " "album.`ID`, " "album.`Title`, " "album.`AlbumInternalID`, " "album.`ArtistName`, " "album.`AlbumPath`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(*) " "FROM " "`Tracks` tracks3 " "WHERE " "tracks3.`AlbumTitle` = album.`Title` AND " "(tracks3.`AlbumArtistName` = album.`ArtistName` OR " "(tracks3.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks3.`AlbumPath` = album.`AlbumPath` " ") as `TracksCount`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "GROUP_CONCAT(tracks.`ArtistName`, ', ') as AllArtists, " "MAX(tracks.`Rating`) as HighestRating, " "GROUP_CONCAT(genres.`Name`, ', ') as AllGenres " "FROM " "`Albums` album LEFT JOIN " "`Tracks` tracks ON " "tracks.`AlbumTitle` = album.`Title` AND " "(" "tracks.`AlbumArtistName` = album.`ArtistName` OR " "(" "tracks.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks.`AlbumPath` = album.`AlbumPath`" "LEFT JOIN " "`Genre` genres ON tracks.`GenreID` = genres.`ID` " "WHERE " "album.`ID` = :albumId " "GROUP BY album.`ID`"); auto result = prepareQuery(d->mSelectAlbumQuery, selectAlbumQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllAlbumsText = QStringLiteral("SELECT " "album.`ID`, " "album.`Title`, " "album.`AlbumInternalID`, " "album.`ArtistName`, " "album.`AlbumPath`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(*) " "FROM " "`Tracks` tracks " "WHERE " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR " "(tracks.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks.`AlbumPath` = album.`AlbumPath` " ") as `TracksCount`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum` " "FROM `Albums` album " "ORDER BY album.`Title` COLLATE NOCASE"); auto result = prepareQuery(d->mSelectAllAlbumsQuery, selectAllAlbumsText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllGenresText = QStringLiteral("SELECT " "genre.`ID`, " "genre.`Name` " "FROM `Genre` genre " "ORDER BY genre.`Name` COLLATE NOCASE"); auto result = prepareQuery(d->mSelectAllGenresQuery, selectAllGenresText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllAlbumsText = QStringLiteral("SELECT " "album.`ID`, " "album.`Title`, " "album.`ArtistName` as SecondaryText, " "album.`CoverFileName`, " "album.`ArtistName`, " "GROUP_CONCAT(tracks.`ArtistName`, ', ') as AllArtists, " "MAX(tracks.`Rating`) as HighestRating, " "GROUP_CONCAT(genres.`Name`, ', ') as AllGenres " "FROM " "`Albums` album, " "`Tracks` tracks LEFT JOIN " "`Genre` genres ON tracks.`GenreID` = genres.`ID` " "WHERE " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR " "(tracks.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks.`AlbumPath` = album.`AlbumPath` " "GROUP BY album.`ID`, album.`Title`, album.`AlbumPath` " "ORDER BY album.`Title` COLLATE NOCASE"); auto result = prepareQuery(d->mSelectAllAlbumsShortQuery, selectAllAlbumsText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsShortQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsShortQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllArtistsWithFilterText = QStringLiteral("SELECT artists.`ID`, " "artists.`Name`, " "GROUP_CONCAT(genres.`Name`, ', ') as AllGenres " "FROM `Artists` artists LEFT JOIN " "`Tracks` tracks ON artists.`Name` = tracks.`ArtistName` LEFT JOIN " "`Genre` genres ON tracks.`GenreID` = genres.`ID` " "GROUP BY artists.`ID` " "ORDER BY artists.`Name` COLLATE NOCASE"); auto result = prepareQuery(d->mSelectAllArtistsQuery, selectAllArtistsWithFilterText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllArtistsQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllArtistsQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllComposersWithFilterText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Artists` " "ORDER BY `Name` COLLATE NOCASE"); auto result = prepareQuery(d->mSelectAllComposersQuery, selectAllComposersWithFilterText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllComposersQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllComposersQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllLyricistsWithFilterText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Lyricist` " "ORDER BY `Name` COLLATE NOCASE"); auto result = prepareQuery(d->mSelectAllLyricistsQuery, selectAllLyricistsWithFilterText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllLyricistsQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllLyricistsQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllTracksText = QStringLiteral("SELECT " "tracks.`ID`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate`, " "tracks.`HasEmbeddedCover` " "FROM " "`Tracks` tracks, " "`TracksMapping` tracksMapping " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "WHERE " "tracksMapping.`TrackID` = tracks.`ID` AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`)"); auto result = prepareQuery(d->mSelectAllTracksQuery, selectAllTracksText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllTracksShortText = QStringLiteral("SELECT " "tracks.`ID`, " "tracks.`Title`, " "tracks.`ArtistName`, " "tracks.`AlbumTitle`, " "tracks.`AlbumArtistName`, " "tracks.`Duration`, " "album.`CoverFileName`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Rating` " "FROM " "`Tracks` tracks " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " ""); auto result = prepareQuery(d->mSelectAllTracksShortQuery, selectAllTracksShortText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksShortQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksShortQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAllTracksFromSourceQueryText = QStringLiteral("SELECT " "tracks.`ID`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate`, " "tracks.`HasEmbeddedCover` " "FROM " "`Tracks` tracks, " "`TracksMapping` tracksMapping, " "`DiscoverSource` source " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "source.`Name` = :source AND " "source.`ID` = tracksMapping.`DiscoverID` AND " "tracksMapping.`TrackID` = tracks.`ID` AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`)"); auto result = prepareQuery(d->mSelectAllTracksFromSourceQuery, selectAllTracksFromSourceQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksFromSourceQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksFromSourceQuery.lastError(); Q_EMIT databaseError(); } } { auto selectArtistByNameText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Artists` " "WHERE " "`Name` = :name"); auto result = prepareQuery(d->mSelectArtistByNameQuery, selectArtistByNameText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectArtistByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectArtistByNameQuery.lastError(); Q_EMIT databaseError(); } } { auto selectComposerByNameText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Composer` " "WHERE " "`Name` = :name"); auto result = prepareQuery(d->mSelectComposerByNameQuery, selectComposerByNameText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectComposerByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectComposerByNameQuery.lastError(); } } { auto selectLyricistByNameText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Lyricist` " "WHERE " "`Name` = :name"); auto result = prepareQuery(d->mSelectLyricistByNameQuery, selectLyricistByNameText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectLyricistByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectLyricistByNameQuery.lastError(); } } { auto selectGenreByNameText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Genre` " "WHERE " "`Name` = :name"); auto result = prepareQuery(d->mSelectGenreByNameQuery, selectGenreByNameText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreByNameQuery.lastError(); Q_EMIT databaseError(); } } { auto insertArtistsText = QStringLiteral("INSERT INTO `Artists` (`ID`, `Name`) " "VALUES (:artistId, :name)"); auto result = prepareQuery(d->mInsertArtistsQuery, insertArtistsText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertArtistsQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertArtistsQuery.lastError(); Q_EMIT databaseError(); } } { auto insertGenreText = QStringLiteral("INSERT INTO `Genre` (`ID`, `Name`) " "VALUES (:genreId, :name)"); auto result = prepareQuery(d->mInsertGenreQuery, insertGenreText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertGenreQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertGenreQuery.lastError(); Q_EMIT databaseError(); } } { auto insertComposerText = QStringLiteral("INSERT INTO `Composer` (`ID`, `Name`) " "VALUES (:composerId, :name)"); auto result = prepareQuery(d->mInsertComposerQuery, insertComposerText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertComposerQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertComposerQuery.lastError(); } } { auto insertLyricistText = QStringLiteral("INSERT INTO `Lyricist` (`ID`, `Name`) " "VALUES (:lyricistId, :name)"); auto result = prepareQuery(d->mInsertLyricistQuery, insertLyricistText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertLyricistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertLyricistQuery.lastError(); } } { auto selectTrackQueryText = QStringLiteral("SELECT " "tracks.`ID`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate`, " "tracks.`HasEmbeddedCover` " "FROM " "`Tracks` tracks, " "`TracksMapping` tracksMapping " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "tracksMapping.`TrackID` = tracks.`ID` AND " "album.`ID` = :albumId AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`) " "ORDER BY tracks.`DiscNumber` ASC, " "tracks.`TrackNumber` ASC"); auto result = prepareQuery(d->mSelectTrackQuery, selectTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackQuery.lastError(); Q_EMIT databaseError(); } } { auto selectTrackFromIdQueryText = QStringLiteral("SELECT " "tracks.`Id`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate`, " "tracks.`HasEmbeddedCover` " "FROM " "`Tracks` tracks, " "`TracksMapping` tracksMapping " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "tracks.`ID` = :trackId AND " "tracksMapping.`TrackID` = tracks.`ID` AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`)"); auto result = prepareQuery(d->mSelectTrackFromIdQuery, selectTrackFromIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackFromIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackFromIdQuery.lastError(); Q_EMIT databaseError(); } } { auto selectCountAlbumsQueryText = QStringLiteral("SELECT count(*) " "FROM `Albums` album " "WHERE album.`ArtistName` = :artistName "); const auto result = prepareQuery(d->mSelectCountAlbumsForArtistQuery, selectCountAlbumsQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectCountAlbumsForArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectCountAlbumsForArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto selectGenreForArtistQueryText = QStringLiteral("SELECT DISTINCT trackGenre.`Name` " "FROM " "`Tracks` tracks " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "album.`ArtistName` = :artistName"); const auto result = prepareQuery(d->mSelectGenreForArtistQuery, selectGenreForArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreForArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreForArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto selectGenreForAlbumQueryText = QStringLiteral("SELECT DISTINCT trackGenre.`Name` " "FROM " "`Tracks` tracks " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "album.`ID` = :albumId"); const auto result = prepareQuery(d->mSelectGenreForAlbumQuery, selectGenreForAlbumQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreForAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreForAlbumQuery.lastError(); Q_EMIT databaseError(); } } { auto selectCountAlbumsQueryText = QStringLiteral("SELECT distinct count(album.`ID`) " "FROM " "`Tracks` tracks, " "`Albums` album " "LEFT JOIN `Composer` albumComposer ON albumComposer.`ID` = tracks.`ComposerID` " "WHERE " "(tracks.`AlbumTitle` = album.`Title` OR tracks.`AlbumTitle` IS NULL ) AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "(tracks.`AlbumPath` = album.`AlbumPath` OR tracks.`AlbumPath` IS NULL ) AND " "albumComposer.`Name` = :artistName"); const auto result = prepareQuery(d->mSelectCountAlbumsForComposerQuery, selectCountAlbumsQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectCountAlbumsForComposerQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectCountAlbumsForComposerQuery.lastError(); Q_EMIT databaseError(); } } { auto selectCountAlbumsQueryText = QStringLiteral("SELECT distinct count(album.`ID`) " "FROM " "`Tracks` tracks, " "`Albums` album " "LEFT JOIN `Lyricist` albumLyricist ON albumLyricist.`ID` = tracks.`LyricistID` " "WHERE " "(tracks.`AlbumTitle` = album.`Title` OR tracks.`AlbumTitle` IS NULL ) AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "(tracks.`AlbumPath` = album.`AlbumPath` OR tracks.`AlbumPath` IS NULL ) AND " "albumLyricist.`Name` = :artistName"); const auto result = prepareQuery(d->mSelectCountAlbumsForLyricistQuery, selectCountAlbumsQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectCountAlbumsForLyricistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectCountAlbumsForLyricistQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAlbumIdFromTitleQueryText = QStringLiteral("SELECT " "album.`ID` " "FROM " "`Albums` album " "WHERE " "album.`ArtistName` = :artistName AND " "album.`Title` = :title"); auto result = prepareQuery(d->mSelectAlbumIdFromTitleQuery, selectAlbumIdFromTitleQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdFromTitleQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdFromTitleQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAlbumIdFromTitleAndArtistQueryText = QStringLiteral("SELECT " "album.`ID` " "FROM " "`Albums` album " "WHERE " "album.`ArtistName` = :artistName AND " "album.`Title` = :title AND " "album.`AlbumPath` = :albumPath"); auto result = prepareQuery(d->mSelectAlbumIdFromTitleAndArtistQuery, selectAlbumIdFromTitleAndArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdFromTitleAndArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdFromTitleAndArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAlbumIdFromTitleWithoutArtistQueryText = QStringLiteral("SELECT " "album.`ID` " "FROM " "`Albums` album " "WHERE " "album.`AlbumPath` = :albumPath AND " "album.`Title` = :title AND " "album.`ArtistName` IS NULL"); auto result = prepareQuery(d->mSelectAlbumIdFromTitleWithoutArtistQuery, selectAlbumIdFromTitleWithoutArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto insertAlbumQueryText = QStringLiteral("INSERT INTO `Albums` " "(`ID`, " "`Title`, " "`ArtistName`, " "`AlbumPath`, " "`CoverFileName`) " "VALUES " "(:albumId, " ":title, " ":albumArtist, " ":albumPath, " ":coverFileName)"); auto result = prepareQuery(d->mInsertAlbumQuery, insertAlbumQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertAlbumQuery.lastError(); Q_EMIT databaseError(); } } { auto insertTrackMappingQueryText = QStringLiteral("INSERT INTO " "`TracksMapping` " "(`FileName`, " "`DiscoverID`, " "`Priority`, " "`FileModifiedTime`) " "VALUES (:fileName, :discoverId, :priority, :mtime)"); auto result = prepareQuery(d->mInsertTrackMapping, insertTrackMappingQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertTrackMapping.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertTrackMapping.lastError(); Q_EMIT databaseError(); } } { auto initialUpdateTracksValidityQueryText = QStringLiteral("UPDATE `TracksMapping` " "SET " "`TrackID` = :trackId, " "`Priority` = :priority, " "`FileModifiedTime` = :mtime " "WHERE `FileName` = :fileName"); auto result = prepareQuery(d->mUpdateTrackMapping, initialUpdateTracksValidityQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mUpdateTrackMapping.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mUpdateTrackMapping.lastError(); Q_EMIT databaseError(); } } { auto removeTracksMappingFromSourceQueryText = QStringLiteral("DELETE FROM `TracksMapping` " "WHERE `FileName` = :fileName AND `DiscoverID` = :sourceId"); auto result = prepareQuery(d->mRemoveTracksMappingFromSource, removeTracksMappingFromSourceQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mRemoveTracksMappingFromSource.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mRemoveTracksMappingFromSource.lastError(); Q_EMIT databaseError(); } } { auto removeTracksMappingQueryText = QStringLiteral("DELETE FROM `TracksMapping` " "WHERE `FileName` = :fileName"); auto result = prepareQuery(d->mRemoveTracksMapping, removeTracksMappingQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mRemoveTracksMapping.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mRemoveTracksMapping.lastError(); Q_EMIT databaseError(); } } { auto selectTracksWithoutMappingQueryText = QStringLiteral("SELECT " "tracks.`Id`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "\"\" as FileName, " "NULL as FileModifiedTime, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate`, " "tracks.`HasEmbeddedCover` " "FROM " "`Tracks` tracks " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "tracks.`ID` NOT IN (SELECT tracksMapping2.`TrackID` FROM `TracksMapping` tracksMapping2)"); auto result = prepareQuery(d->mSelectTracksWithoutMappingQuery, selectTracksWithoutMappingQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksWithoutMappingQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksWithoutMappingQuery.lastError(); Q_EMIT databaseError(); } } { auto selectTracksMappingQueryText = QStringLiteral("SELECT " "`TrackID`, " "`FileName`, " "`DiscoverID`, " "`Priority`, " "`FileModifiedTime` " "FROM " "`TracksMapping` " "WHERE " "`FileName` = :fileName"); auto result = prepareQuery(d->mSelectTracksMapping, selectTracksMappingQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksMapping.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksMapping.lastError(); Q_EMIT databaseError(); } } { auto selectTracksMappingPriorityQueryText = QStringLiteral("SELECT " "`Priority` " "FROM " "`TracksMapping` " "WHERE " "`TrackID` = :trackId AND " "`FileName` = :fileName"); auto result = prepareQuery(d->mSelectTracksMappingPriority, selectTracksMappingPriorityQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksMappingPriority.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksMappingPriority.lastError(); Q_EMIT databaseError(); } } { auto selectTracksMappingPriorityQueryByTrackIdText = QStringLiteral("SELECT " "MAX(`Priority`) " "FROM " "`TracksMapping` " "WHERE " "`TrackID` = :trackId"); auto result = prepareQuery(d->mSelectTracksMappingPriorityByTrackId, selectTracksMappingPriorityQueryByTrackIdText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksMappingPriorityByTrackId.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksMappingPriorityByTrackId.lastError(); Q_EMIT databaseError(); } } { auto selectAllTrackFilesFromSourceQueryText = QStringLiteral("SELECT " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime` " "FROM " "`TracksMapping` tracksMapping " "WHERE " "tracksMapping.`DiscoverID` = :discoverId"); auto result = prepareQuery(d->mSelectAllTrackFilesFromSourceQuery, selectAllTrackFilesFromSourceQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTrackFilesFromSourceQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTrackFilesFromSourceQuery.lastError(); Q_EMIT databaseError(); } } { auto insertMusicSourceQueryText = QStringLiteral("INSERT OR IGNORE INTO `DiscoverSource` (`ID`, `Name`) " "VALUES (:discoverId, :name)"); auto result = prepareQuery(d->mInsertMusicSource, insertMusicSourceQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertMusicSource.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertMusicSource.lastError(); Q_EMIT databaseError(); } } { auto selectMusicSourceQueryText = QStringLiteral("SELECT `ID` FROM `DiscoverSource` WHERE `Name` = :name"); auto result = prepareQuery(d->mSelectMusicSource, selectMusicSourceQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectMusicSource.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectMusicSource.lastError(); Q_EMIT databaseError(); } } { auto selectTrackQueryText = QStringLiteral("SELECT " "tracks.`ID`, tracksMapping.`FileName` " "FROM " "`Tracks` tracks, " "`Albums` album, " "`TracksMapping` tracksMapping " "WHERE " "tracks.`Title` = :title AND " "album.`ID` = :album AND " "(tracks.`AlbumTitle` = album.`Title` OR tracks.`AlbumTitle` IS NULL ) AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "(tracks.`AlbumPath` = album.`AlbumPath` OR tracks.`AlbumPath` IS NULL ) AND " "tracks.`ArtistName` = :artist AND " "tracksMapping.`TrackID` = tracks.`ID` AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`)"); auto result = prepareQuery(d->mSelectTrackIdFromTitleAlbumIdArtistQuery, selectTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackIdFromTitleAlbumIdArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackIdFromTitleAlbumIdArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto insertTrackQueryText = QStringLiteral("INSERT INTO `Tracks` " "(" "`ID`, " "`Title`, " "`ArtistName`, " "`AlbumTitle`, " "`AlbumArtistName`, " "`AlbumPath`, " "`GenreID`, " "`ComposerID`, " "`LyricistID`, " "`Comment`, " "`TrackNumber`, " "`DiscNumber`, " "`Channels`, " "`BitRate`, " "`SampleRate`, " "`Year`, " "`Duration`, " "`Rating`, " "`HasEmbeddedCover`) " "VALUES " "(" ":trackId, " ":title, " ":artistName, " ":albumTitle, " ":albumArtistName, " ":albumPath, " ":genreId, " ":composerId, " ":lyricistId, " ":comment, " ":trackNumber, " ":discNumber, " ":channels, " ":bitRate, " ":sampleRate, " ":year, " ":trackDuration, " ":trackRating, " ":hasEmbeddedCover)"); auto result = prepareQuery(d->mInsertTrackQuery, insertTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mInsertTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mInsertTrackQuery.lastError(); Q_EMIT databaseError(); } } { auto updateTrackQueryText = QStringLiteral("UPDATE `Tracks` " "SET " "`Title` = :title, " "`ArtistName` = :artistName, " "`AlbumTitle` = :albumTitle, " "`AlbumArtistName` = :albumArtistName, " "`AlbumPath` = :albumPath, " "`GenreID` = :genreId, " "`ComposerID` = :composerId, " "`LyricistID` = :lyricistId, " "`Comment` = :comment, " "`TrackNumber` = :trackNumber, " "`DiscNumber` = :discNumber, " "`Channels` = :channels, " "`BitRate` = :bitRate, " "`SampleRate` = :sampleRate, " "`Year` = :year, " " `Duration` = :trackDuration, " "`Rating` = :trackRating " "WHERE " "`ID` = :trackId"); auto result = prepareQuery(d->mUpdateTrackQuery, updateTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mUpdateTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mUpdateTrackQuery.lastError(); Q_EMIT databaseError(); } } { auto updateAlbumArtistQueryText = QStringLiteral("UPDATE `Albums` " "SET " "`ArtistName` = :artistName " "WHERE " "`ID` = :albumId"); auto result = prepareQuery(d->mUpdateAlbumArtistQuery, updateAlbumArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mUpdateAlbumArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mUpdateAlbumArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto updateAlbumArtistInTracksQueryText = QStringLiteral("UPDATE `Tracks` " "SET " "`AlbumArtistName` = :artistName " "WHERE " "`AlbumTitle` = :albumTitle AND " "`AlbumPath` = :albumPath AND " "`AlbumArtistName` IS NULL"); auto result = prepareQuery(d->mUpdateAlbumArtistInTracksQuery, updateAlbumArtistInTracksQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mUpdateAlbumArtistInTracksQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mUpdateAlbumArtistInTracksQuery.lastError(); Q_EMIT databaseError(); } } { auto queryMaximumTrackIdQueryText = QStringLiteral("SELECT MAX(tracks.`ID`)" "FROM " "`Tracks` tracks"); auto result = prepareQuery(d->mQueryMaximumTrackIdQuery, queryMaximumTrackIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumTrackIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumTrackIdQuery.lastError(); Q_EMIT databaseError(); } } { auto queryMaximumAlbumIdQueryText = QStringLiteral("SELECT MAX(albums.`ID`)" "FROM " "`Albums` albums"); auto result = prepareQuery(d->mQueryMaximumAlbumIdQuery, queryMaximumAlbumIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumAlbumIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumAlbumIdQuery.lastError(); Q_EMIT databaseError(); } } { auto queryMaximumArtistIdQueryText = QStringLiteral("SELECT MAX(artists.`ID`)" "FROM " "`Artists` artists"); auto result = prepareQuery(d->mQueryMaximumArtistIdQuery, queryMaximumArtistIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumArtistIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumArtistIdQuery.lastError(); Q_EMIT databaseError(); } } { auto queryMaximumLyricistIdQueryText = QStringLiteral("SELECT MAX(lyricists.`ID`)" "FROM " "`Lyricist` lyricists"); auto result = prepareQuery(d->mQueryMaximumLyricistIdQuery, queryMaximumLyricistIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumLyricistIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumLyricistIdQuery.lastError(); Q_EMIT databaseError(); } } { auto queryMaximumComposerIdQueryText = QStringLiteral("SELECT MAX(composers.`ID`)" "FROM " "`Composer` composers"); auto result = prepareQuery(d->mQueryMaximumComposerIdQuery, queryMaximumComposerIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumComposerIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumComposerIdQuery.lastError(); Q_EMIT databaseError(); } } { auto queryMaximumGenreIdQueryText = QStringLiteral("SELECT MAX(genres.`ID`)" "FROM " "`Genre` genres"); auto result = prepareQuery(d->mQueryMaximumGenreIdQuery, queryMaximumGenreIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumGenreIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mQueryMaximumGenreIdQuery.lastError(); Q_EMIT databaseError(); } } { auto selectTrackQueryText = QStringLiteral("SELECT " "tracks.ID " "FROM " "`Tracks` tracks " "WHERE " "tracks.`Title` = :title AND " "tracks.`AlbumTitle` = :album AND " "tracks.`TrackNumber` = :trackNumber AND " "tracks.`DiscNumber` = :discNumber AND " "tracks.`ArtistName` = :artist"); auto result = prepareQuery(d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery, selectTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.lastError(); Q_EMIT databaseError(); } } { auto selectTrackQueryText = QStringLiteral("SELECT " "tracks.ID " "FROM " "`Tracks` tracks, " "`Albums` albums " "WHERE " "tracks.`Title` = :title AND " "tracks.`AlbumTitle` = albums.`Title` AND " "tracks.`AlbumArtistName` = albums.`ArtistName` AND " "tracks.`AlbumPath` = albums.`AlbumPath` AND " "albums.`Title` = :album AND " "albums.`AlbumPath` = :albumPath AND " "tracks.`TrackNumber` = :trackNumber AND " "tracks.`DiscNumber` = :discNumber AND " "( " "( albums.`ArtistName` IS NULL) OR " "( albums.`ArtistName` = :albumArtist) " ")"); auto result = prepareQuery(d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery, selectTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.lastError(); Q_EMIT databaseError(); } } { auto selectAlbumArtUriFromAlbumIdQueryText = QStringLiteral("SELECT `CoverFileName`" "FROM " "`Albums` " "WHERE " "`ID` = :albumId"); auto result = prepareQuery(d->mSelectAlbumArtUriFromAlbumIdQuery, selectAlbumArtUriFromAlbumIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumArtUriFromAlbumIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumArtUriFromAlbumIdQuery.lastError(); Q_EMIT databaseError(); } } { auto updateAlbumArtUriFromAlbumIdQueryText = QStringLiteral("UPDATE `Albums` " "SET `CoverFileName` = :coverFileName " "WHERE " "`ID` = :albumId"); auto result = prepareQuery(d->mUpdateAlbumArtUriFromAlbumIdQuery, updateAlbumArtUriFromAlbumIdQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mUpdateAlbumArtUriFromAlbumIdQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mUpdateAlbumArtUriFromAlbumIdQuery.lastError(); Q_EMIT databaseError(); } } { auto selectTracksFromArtistQueryText = QStringLiteral("SELECT " "tracks.`ID`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate`, " "tracks.`HasEmbeddedCover` " "FROM " "`Tracks` tracks, " "`TracksMapping` tracksMapping " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "tracks.`ArtistName` = :artistName AND " "tracksMapping.`TrackID` = tracks.`ID` AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`) " "ORDER BY tracks.`Title` ASC, " "album.`Title` ASC"); auto result = prepareQuery(d->mSelectTracksFromArtist, selectTracksFromArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksFromArtist.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTracksFromArtist.lastError(); Q_EMIT databaseError(); } } { auto selectAlbumIdsFromArtistQueryText = QStringLiteral("SELECT " "album.`ID` " "FROM " "`Albums` album " "WHERE " "album.`ArtistName` = :artistName"); auto result = prepareQuery(d->mSelectAlbumIdsFromArtist, selectAlbumIdsFromArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdsFromArtist.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectAlbumIdsFromArtist.lastError(); Q_EMIT databaseError(); } } { auto selectArtistQueryText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Artists` " "WHERE " "`ID` = :artistId"); auto result = prepareQuery(d->mSelectArtistQuery, selectArtistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectArtistQuery.lastError(); Q_EMIT databaseError(); } } { auto selectGenreQueryText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Genre` " "WHERE " "`ID` = :genreId"); auto result = prepareQuery(d->mSelectGenreQuery, selectGenreQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectGenreQuery.lastError(); Q_EMIT databaseError(); } } { auto selectComposerQueryText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Composer` " "WHERE " "`ID` = :composerId"); auto result = prepareQuery(d->mSelectComposerQuery, selectComposerQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectComposerQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectComposerQuery.lastError(); } } { auto selectLyricistQueryText = QStringLiteral("SELECT `ID`, " "`Name` " "FROM `Lyricist` " "WHERE " "`ID` = :lyricistId"); auto result = prepareQuery(d->mSelectLyricistQuery, selectLyricistQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectLyricistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectLyricistQuery.lastError(); } } { auto selectTrackFromFilePathQueryText = QStringLiteral("SELECT " "tracks.`ID`, " "tracks.`Title`, " "album.`ID`, " "tracks.`ArtistName`, " "tracks.`AlbumArtistName`, " "tracksMapping.`FileName`, " "tracksMapping.`FileModifiedTime`, " "tracks.`TrackNumber`, " "tracks.`DiscNumber`, " "tracks.`Duration`, " "tracks.`AlbumTitle`, " "tracks.`Rating`, " "album.`CoverFileName`, " "(" "SELECT " "COUNT(DISTINCT tracks2.DiscNumber) <= 1 " "FROM " "`Tracks` tracks2 " "WHERE " "tracks2.`AlbumTitle` = album.`Title` AND " "(tracks2.`AlbumArtistName` = album.`ArtistName` OR " "(tracks2.`AlbumArtistName` IS NULL AND " "album.`ArtistName` IS NULL" ")" ") AND " "tracks2.`AlbumPath` = album.`AlbumPath` " ") as `IsSingleDiscAlbum`, " "trackGenre.`Name`, " "trackComposer.`Name`, " "trackLyricist.`Name`, " "tracks.`Comment`, " "tracks.`Year`, " "tracks.`Channels`, " "tracks.`BitRate`, " "tracks.`SampleRate` " "FROM " "`Tracks` tracks, " "`TracksMapping` tracksMapping " "LEFT JOIN " "`Albums` album " "ON " "tracks.`AlbumTitle` = album.`Title` AND " "(tracks.`AlbumArtistName` = album.`ArtistName` OR tracks.`AlbumArtistName` IS NULL ) AND " "tracks.`AlbumPath` = album.`AlbumPath` " "LEFT JOIN `Composer` trackComposer ON trackComposer.`ID` = tracks.`ComposerID` " "LEFT JOIN `Lyricist` trackLyricist ON trackLyricist.`ID` = tracks.`LyricistID` " "LEFT JOIN `Genre` trackGenre ON trackGenre.`ID` = tracks.`GenreID` " "WHERE " "tracksMapping.`TrackID` = tracks.`ID` AND " "tracksMapping.`FileName` = :filePath AND " "tracksMapping.`Priority` = (SELECT MIN(`Priority`) FROM `TracksMapping` WHERE `TrackID` = tracks.`ID`)"); auto result = prepareQuery(d->mSelectTrackFromFilePathQuery, selectTrackFromFilePathQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackFromFilePathQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mSelectTrackFromFilePathQuery.lastError(); Q_EMIT databaseError(); } } { auto removeTrackQueryText = QStringLiteral("DELETE FROM `Tracks` " "WHERE " "`ID` = :trackId"); auto result = prepareQuery(d->mRemoveTrackQuery, removeTrackQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mRemoveTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mRemoveTrackQuery.lastError(); Q_EMIT databaseError(); } } { auto removeAlbumQueryText = QStringLiteral("DELETE FROM `Albums` " "WHERE " "`ID` = :albumId"); auto result = prepareQuery(d->mRemoveAlbumQuery, removeAlbumQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mRemoveAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mRemoveAlbumQuery.lastError(); Q_EMIT databaseError(); } } { auto removeAlbumQueryText = QStringLiteral("DELETE FROM `Artists` " "WHERE " "`ID` = :artistId"); auto result = prepareQuery(d->mRemoveArtistQuery, removeAlbumQueryText); if (!result) { qDebug() << "DatabaseInterface::initRequest" << d->mRemoveArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::initRequest" << d->mRemoveArtistQuery.lastError(); Q_EMIT databaseError(); } } finishTransaction(); d->mInitFinished = true; Q_EMIT requestsInitDone(); } qulonglong DatabaseInterface::insertAlbum(const QString &title, const QString &albumArtist, const QString &trackArtist, const QString &trackPath, const QUrl &albumArtURI) { auto result = qulonglong(0); if (title.isEmpty()) { return result; } if (!albumArtist.isEmpty() || !trackArtist.isEmpty()) { d->mSelectAlbumIdFromTitleAndArtistQuery.bindValue(QStringLiteral(":title"), title); d->mSelectAlbumIdFromTitleAndArtistQuery.bindValue(QStringLiteral(":albumPath"), trackPath); if (!albumArtist.isEmpty()) { d->mSelectAlbumIdFromTitleAndArtistQuery.bindValue(QStringLiteral(":artistName"), albumArtist); } else { d->mSelectAlbumIdFromTitleAndArtistQuery.bindValue(QStringLiteral(":artistName"), trackArtist); } auto queryResult = d->mSelectAlbumIdFromTitleAndArtistQuery.exec(); if (!queryResult || !d->mSelectAlbumIdFromTitleAndArtistQuery.isSelect() || !d->mSelectAlbumIdFromTitleAndArtistQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertAlbum" << d->mSelectAlbumIdFromTitleAndArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::insertAlbum" << d->mSelectAlbumIdFromTitleAndArtistQuery.boundValues(); qDebug() << "DatabaseInterface::insertAlbum" << d->mSelectAlbumIdFromTitleAndArtistQuery.lastError(); d->mSelectAlbumIdFromTitleAndArtistQuery.finish(); return result; } if (d->mSelectAlbumIdFromTitleAndArtistQuery.next()) { result = d->mSelectAlbumIdFromTitleAndArtistQuery.record().value(0).toULongLong(); d->mSelectAlbumIdFromTitleAndArtistQuery.finish(); return result; } d->mSelectAlbumIdFromTitleAndArtistQuery.finish(); } if (result == 0) { d->mSelectAlbumIdFromTitleWithoutArtistQuery.bindValue(QStringLiteral(":title"), title); d->mSelectAlbumIdFromTitleWithoutArtistQuery.bindValue(QStringLiteral(":albumPath"), trackPath); auto queryResult = d->mSelectAlbumIdFromTitleWithoutArtistQuery.exec(); if (!queryResult || !d->mSelectAlbumIdFromTitleWithoutArtistQuery.isSelect() || !d->mSelectAlbumIdFromTitleWithoutArtistQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertAlbum" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::insertAlbum" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.boundValues(); qDebug() << "DatabaseInterface::insertAlbum" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.lastError(); d->mSelectAlbumIdFromTitleWithoutArtistQuery.finish(); return result; } if (d->mSelectAlbumIdFromTitleWithoutArtistQuery.next()) { result = d->mSelectAlbumIdFromTitleWithoutArtistQuery.record().value(0).toULongLong(); d->mSelectAlbumIdFromTitleWithoutArtistQuery.finish(); return result; } d->mSelectAlbumIdFromTitleWithoutArtistQuery.finish(); } d->mInsertAlbumQuery.bindValue(QStringLiteral(":albumId"), d->mAlbumId); d->mInsertAlbumQuery.bindValue(QStringLiteral(":title"), title); if (!albumArtist.isEmpty()) { insertArtist(albumArtist); d->mInsertAlbumQuery.bindValue(QStringLiteral(":albumArtist"), albumArtist); } else { d->mInsertAlbumQuery.bindValue(QStringLiteral(":albumArtist"), {}); } d->mInsertAlbumQuery.bindValue(QStringLiteral(":albumPath"), trackPath); d->mInsertAlbumQuery.bindValue(QStringLiteral(":coverFileName"), albumArtURI); auto queryResult = d->mInsertAlbumQuery.exec(); if (!queryResult || !d->mInsertAlbumQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertAlbum" << d->mInsertAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::insertAlbum" << d->mInsertAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::insertAlbum" << d->mInsertAlbumQuery.lastError(); d->mInsertAlbumQuery.finish(); return result; } result = d->mAlbumId; d->mInsertAlbumQuery.finish(); ++d->mAlbumId; d->mInsertedAlbums.insert(result); return result; } bool DatabaseInterface::updateAlbumFromId(qulonglong albumId, const QUrl &albumArtUri, const MusicAudioTrack ¤tTrack, const QString &albumPath) { auto modifiedAlbum = false; modifiedAlbum = true; if (!albumArtUri.isValid()) { return modifiedAlbum; } auto storedAlbumArtUri = internalAlbumArtUriFromAlbumId(albumId); if (!storedAlbumArtUri.isValid() || storedAlbumArtUri != albumArtUri) { d->mUpdateAlbumArtUriFromAlbumIdQuery.bindValue(QStringLiteral(":albumId"), albumId); d->mUpdateAlbumArtUriFromAlbumIdQuery.bindValue(QStringLiteral(":coverFileName"), albumArtUri); auto result = d->mUpdateAlbumArtUriFromAlbumIdQuery.exec(); if (!result || !d->mUpdateAlbumArtUriFromAlbumIdQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::updateAlbumFromId" << d->mUpdateAlbumArtUriFromAlbumIdQuery.lastQuery(); qDebug() << "DatabaseInterface::updateAlbumFromId" << d->mUpdateAlbumArtUriFromAlbumIdQuery.boundValues(); qDebug() << "DatabaseInterface::updateAlbumFromId" << d->mUpdateAlbumArtUriFromAlbumIdQuery.lastError(); d->mUpdateAlbumArtUriFromAlbumIdQuery.finish(); return modifiedAlbum; } d->mUpdateAlbumArtUriFromAlbumIdQuery.finish(); modifiedAlbum = true; } if (!isValidArtist(albumId) && currentTrack.isValidAlbumArtist()) { updateAlbumArtist(albumId, currentTrack.albumName(), albumPath, currentTrack.albumArtist()); modifiedAlbum = true; } return modifiedAlbum; } qulonglong DatabaseInterface::insertArtist(const QString &name) { auto result = qulonglong(0); if (name.isEmpty()) { return result; } d->mSelectArtistByNameQuery.bindValue(QStringLiteral(":name"), name); auto queryResult = d->mSelectArtistByNameQuery.exec(); if (!queryResult || !d->mSelectArtistByNameQuery.isSelect() || !d->mSelectArtistByNameQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectArtistByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectArtistByNameQuery.boundValues(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectArtistByNameQuery.lastError(); d->mSelectArtistByNameQuery.finish(); return result; } if (d->mSelectArtistByNameQuery.next()) { result = d->mSelectArtistByNameQuery.record().value(0).toULongLong(); d->mSelectArtistByNameQuery.finish(); return result; } d->mSelectArtistByNameQuery.finish(); d->mInsertArtistsQuery.bindValue(QStringLiteral(":artistId"), d->mArtistId); d->mInsertArtistsQuery.bindValue(QStringLiteral(":name"), name); queryResult = d->mInsertArtistsQuery.exec(); if (!queryResult || !d->mInsertArtistsQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertArtist" << d->mInsertArtistsQuery.lastQuery(); qDebug() << "DatabaseInterface::insertArtist" << d->mInsertArtistsQuery.boundValues(); qDebug() << "DatabaseInterface::insertArtist" << d->mInsertArtistsQuery.lastError(); d->mInsertArtistsQuery.finish(); return result; } result = d->mArtistId; ++d->mArtistId; d->mInsertedArtists.insert(result); d->mInsertArtistsQuery.finish(); return result; } qulonglong DatabaseInterface::insertComposer(const QString &name) { auto result = qulonglong(0); if (name.isEmpty()) { return result; } d->mSelectComposerByNameQuery.bindValue(QStringLiteral(":name"), name); auto queryResult = d->mSelectComposerByNameQuery.exec(); if (!queryResult || !d->mSelectComposerByNameQuery.isSelect() || !d->mSelectComposerByNameQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertComposer" << d->mSelectComposerByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::insertComposer" << d->mSelectComposerByNameQuery.boundValues(); qDebug() << "DatabaseInterface::insertComposer" << d->mSelectComposerByNameQuery.lastError(); d->mSelectComposerByNameQuery.finish(); return result; } if (d->mSelectComposerByNameQuery.next()) { result = d->mSelectComposerByNameQuery.record().value(0).toULongLong(); d->mSelectComposerByNameQuery.finish(); return result; } d->mSelectComposerByNameQuery.finish(); d->mInsertComposerQuery.bindValue(QStringLiteral(":composerId"), d->mComposerId); d->mInsertComposerQuery.bindValue(QStringLiteral(":name"), name); queryResult = d->mInsertComposerQuery.exec(); if (!queryResult || !d->mInsertComposerQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertComposer" << d->mInsertComposerQuery.lastQuery(); qDebug() << "DatabaseInterface::insertComposer" << d->mInsertComposerQuery.boundValues(); qDebug() << "DatabaseInterface::insertComposer" << d->mInsertComposerQuery.lastError(); d->mInsertComposerQuery.finish(); return result; } result = d->mComposerId; ++d->mComposerId; d->mInsertComposerQuery.finish(); Q_EMIT composersAdded(internalAllComposersPartialData()); return result; } qulonglong DatabaseInterface::insertGenre(const QString &name) { auto result = qulonglong(0); if (name.isEmpty()) { return result; } d->mSelectGenreByNameQuery.bindValue(QStringLiteral(":name"), name); auto queryResult = d->mSelectGenreByNameQuery.exec(); if (!queryResult || !d->mSelectGenreByNameQuery.isSelect() || !d->mSelectGenreByNameQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertGenre" << d->mSelectGenreByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::insertGenre" << d->mSelectGenreByNameQuery.boundValues(); qDebug() << "DatabaseInterface::insertGenre" << d->mSelectGenreByNameQuery.lastError(); d->mSelectGenreByNameQuery.finish(); return result; } if (d->mSelectGenreByNameQuery.next()) { result = d->mSelectGenreByNameQuery.record().value(0).toULongLong(); d->mSelectGenreByNameQuery.finish(); return result; } d->mSelectGenreByNameQuery.finish(); d->mInsertGenreQuery.bindValue(QStringLiteral(":genreId"), d->mGenreId); d->mInsertGenreQuery.bindValue(QStringLiteral(":name"), name); queryResult = d->mInsertGenreQuery.exec(); if (!queryResult || !d->mInsertGenreQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertGenre" << d->mInsertGenreQuery.lastQuery(); qDebug() << "DatabaseInterface::insertGenre" << d->mInsertGenreQuery.boundValues(); qDebug() << "DatabaseInterface::insertGenre" << d->mInsertGenreQuery.lastError(); d->mInsertGenreQuery.finish(); return result; } result = d->mGenreId; ++d->mGenreId; d->mInsertGenreQuery.finish(); Q_EMIT genresAdded({{{DatabaseIdRole, result}}}); return result; } MusicAudioGenre DatabaseInterface::internalGenreFromId(qulonglong genreId) { auto result = MusicAudioGenre{}; if (!d || !d->mTracksDatabase.isValid() || !d->mInitFinished) { return result; } d->mSelectGenreQuery.bindValue(QStringLiteral(":genreId"), genreId); auto queryResult = d->mSelectGenreQuery.exec(); if (!queryResult || !d->mSelectGenreQuery.isSelect() || !d->mSelectGenreQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalGenreFromId" << d->mSelectGenreQuery.lastQuery(); qDebug() << "DatabaseInterface::internalGenreFromId" << d->mSelectGenreQuery.boundValues(); qDebug() << "DatabaseInterface::internalGenreFromId" << d->mSelectGenreQuery.lastError(); d->mSelectGenreQuery.finish(); return result; } if (!d->mSelectGenreQuery.next()) { d->mSelectGenreQuery.finish(); return result; } const auto ¤tRecord = d->mSelectGenreQuery.record(); result.setDatabaseId(currentRecord.value(0).toULongLong()); result.setName(currentRecord.value(1).toString()); d->mSelectGenreQuery.finish(); return result; } void DatabaseInterface::insertTrackOrigin(const QUrl &fileNameURI, const QDateTime &fileModifiedTime, qulonglong discoverId) { d->mInsertTrackMapping.bindValue(QStringLiteral(":discoverId"), discoverId); d->mInsertTrackMapping.bindValue(QStringLiteral(":fileName"), fileNameURI); d->mInsertTrackMapping.bindValue(QStringLiteral(":priority"), 1); d->mInsertTrackMapping.bindValue(QStringLiteral(":mtime"), fileModifiedTime); auto queryResult = d->mInsertTrackMapping.exec(); if (!queryResult || !d->mInsertTrackMapping.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertArtist" << d->mInsertTrackMapping.lastQuery(); qDebug() << "DatabaseInterface::insertArtist" << d->mInsertTrackMapping.boundValues(); qDebug() << "DatabaseInterface::insertArtist" << d->mInsertTrackMapping.lastError(); d->mInsertTrackMapping.finish(); return; } d->mInsertTrackMapping.finish(); } void DatabaseInterface::updateTrackOrigin(qulonglong trackId, const QUrl &fileName, const QDateTime &fileModifiedTime) { d->mUpdateTrackMapping.bindValue(QStringLiteral(":trackId"), trackId); d->mUpdateTrackMapping.bindValue(QStringLiteral(":fileName"), fileName); d->mUpdateTrackMapping.bindValue(QStringLiteral(":priority"), computeTrackPriority(trackId, fileName)); d->mUpdateTrackMapping.bindValue(QStringLiteral(":mtime"), fileModifiedTime); auto queryResult = d->mUpdateTrackMapping.exec(); if (!queryResult || !d->mUpdateTrackMapping.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::updateTrackOrigin" << d->mUpdateTrackMapping.lastQuery(); qDebug() << "DatabaseInterface::updateTrackOrigin" << d->mUpdateTrackMapping.boundValues(); qDebug() << "DatabaseInterface::updateTrackOrigin" << d->mUpdateTrackMapping.lastError(); d->mUpdateTrackMapping.finish(); return; } d->mInsertTrackMapping.finish(); } int DatabaseInterface::computeTrackPriority(qulonglong trackId, const QUrl &fileName) { auto result = int(1); if (!d) { return result; } d->mSelectTracksMappingPriority.bindValue(QStringLiteral(":trackId"), trackId); d->mSelectTracksMappingPriority.bindValue(QStringLiteral(":fileName"), fileName); auto queryResult = d->mSelectTracksMappingPriority.exec(); if (!queryResult || !d->mSelectTracksMappingPriority.isSelect() || !d->mSelectTracksMappingPriority.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMappingPriority.lastQuery(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMappingPriority.boundValues(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMappingPriority.lastError(); d->mSelectTracksMappingPriority.finish(); return result; } if (d->mSelectTracksMappingPriority.next()) { result = d->mSelectTracksMappingPriority.record().value(0).toInt(); d->mSelectTracksMappingPriority.finish(); return result; } d->mSelectTracksMappingPriority.finish(); d->mSelectTracksMappingPriorityByTrackId.bindValue(QStringLiteral(":trackId"), trackId); queryResult = d->mSelectTracksMappingPriorityByTrackId.exec(); if (!queryResult || !d->mSelectTracksMappingPriorityByTrackId.isSelect() || !d->mSelectTracksMappingPriorityByTrackId.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMappingPriorityByTrackId.lastQuery(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMappingPriorityByTrackId.boundValues(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMappingPriorityByTrackId.lastError(); d->mSelectTracksMappingPriorityByTrackId.finish(); return result; } if (d->mSelectTracksMappingPriorityByTrackId.next()) { result = d->mSelectTracksMappingPriorityByTrackId.record().value(0).toInt() + 1; } d->mSelectTracksMappingPriorityByTrackId.finish(); return result; } qulonglong DatabaseInterface::internalInsertTrack(const MusicAudioTrack &oneTrack, const QHash &covers, qulonglong originTrackId, TrackFileInsertType insertType) { qulonglong resultId = 0; if (oneTrack.title().isEmpty()) { return resultId; } auto oldTrack = oneTrack; QUrl::FormattingOptions currentOptions = QUrl::PreferLocalFile | QUrl::RemoveAuthority | QUrl::RemoveFilename | QUrl::RemoveFragment | QUrl::RemovePassword | QUrl::RemovePort | QUrl::RemoveQuery | QUrl::RemoveScheme | QUrl::RemoveUserInfo; const auto &trackPath = oneTrack.resourceURI().toString(currentOptions); auto albumId = insertAlbum(oneTrack.albumName(), (oneTrack.isValidAlbumArtist() ? oneTrack.albumArtist() : QString()), oneTrack.artist(), trackPath, covers[oneTrack.resourceURI().toString()]); const auto ¤tAlbum = internalAlbumFromId(albumId); auto otherTrackId = getDuplicateTrackIdFromTitleAlbumTrackDiscNumber(oneTrack.title(), oneTrack.albumName(), oneTrack.albumArtist(), trackPath, oneTrack.trackNumber(), oneTrack.discNumber()); bool isModifiedTrack = (otherTrackId != 0) || (insertType == TrackFileInsertType::ModifiedTrackFileInsert); bool isSameTrack = false; qulonglong oldAlbumId = 0; if (isModifiedTrack) { if (otherTrackId == 0) { otherTrackId = internalTrackIdFromFileName(oneTrack.resourceURI()); } originTrackId = otherTrackId; oldTrack = internalTrackFromDatabaseId(originTrackId); isSameTrack = (oldTrack.title() == oneTrack.title()); isSameTrack = isSameTrack && (oldTrack.albumName() == oneTrack.albumName()); isSameTrack = isSameTrack && (oldTrack.artist() == oneTrack.artist()); isSameTrack = isSameTrack && (oldTrack.trackNumber() == oneTrack.trackNumber()); isSameTrack = isSameTrack && (oldTrack.discNumber() == oneTrack.discNumber()); isSameTrack = isSameTrack && (oldTrack.duration() == oneTrack.duration()); isSameTrack = isSameTrack && (oldTrack.rating() == oneTrack.rating()); isSameTrack = isSameTrack && (oldTrack.resourceURI() == oneTrack.resourceURI()); isSameTrack = isSameTrack && (oldTrack.genre() == oneTrack.genre()); isSameTrack = isSameTrack && (oldTrack.composer() == oneTrack.composer()); isSameTrack = isSameTrack && (oldTrack.lyricist() == oneTrack.lyricist()); isSameTrack = isSameTrack && (oldTrack.comment() == oneTrack.comment()); isSameTrack = isSameTrack && (oldTrack.year() == oneTrack.year()); isSameTrack = isSameTrack && (oldTrack.channels() == oneTrack.channels()); isSameTrack = isSameTrack && (oldTrack.bitRate() == oneTrack.bitRate()); isSameTrack = isSameTrack && (oldTrack.sampleRate() == oneTrack.sampleRate()); oldAlbumId = internalAlbumIdFromTitleAndArtist(oldTrack.albumName(), oldTrack.albumArtist()); if (!isSameTrack) { auto newTrack = oneTrack; newTrack.setDatabaseId(oldTrack.databaseId()); updateTrackInDatabase(newTrack, trackPath); updateTrackOrigin(newTrack.databaseId(), oneTrack.resourceURI(), oneTrack.fileModificationTime()); updateAlbumFromId(albumId, oneTrack.albumCover(), oneTrack, trackPath); recordModifiedTrack(originTrackId); if (albumId != 0) { recordModifiedAlbum(albumId); } if (oldAlbumId != 0) { recordModifiedAlbum(oldAlbumId); } isSameTrack = true; } } else { originTrackId = d->mTrackId; } resultId = originTrackId; if (!isSameTrack) { d->mInsertTrackQuery.bindValue(QStringLiteral(":trackId"), originTrackId); d->mInsertTrackQuery.bindValue(QStringLiteral(":title"), oneTrack.title()); insertArtist(oneTrack.artist()); d->mInsertTrackQuery.bindValue(QStringLiteral(":artistName"), oneTrack.artist()); d->mInsertTrackQuery.bindValue(QStringLiteral(":albumTitle"), currentAlbum.title()); if (currentAlbum.isValidArtist()) { d->mInsertTrackQuery.bindValue(QStringLiteral(":albumArtistName"), currentAlbum.artist()); } else { d->mInsertTrackQuery.bindValue(QStringLiteral(":albumArtistName"), {}); } d->mInsertTrackQuery.bindValue(QStringLiteral(":albumPath"), trackPath); d->mInsertTrackQuery.bindValue(QStringLiteral(":trackNumber"), oneTrack.trackNumber()); d->mInsertTrackQuery.bindValue(QStringLiteral(":discNumber"), oneTrack.discNumber()); d->mInsertTrackQuery.bindValue(QStringLiteral(":trackDuration"), QVariant::fromValue(oneTrack.duration().msecsSinceStartOfDay())); d->mInsertTrackQuery.bindValue(QStringLiteral(":trackRating"), oneTrack.rating()); auto genreId = insertGenre(oneTrack.genre()); if (genreId != 0) { d->mInsertTrackQuery.bindValue(QStringLiteral(":genreId"), genreId); } else { d->mInsertTrackQuery.bindValue(QStringLiteral(":genreId"), {}); } auto composerId = insertComposer(oneTrack.composer()); if (composerId != 0) { d->mInsertTrackQuery.bindValue(QStringLiteral(":composerId"), composerId); } else { d->mInsertTrackQuery.bindValue(QStringLiteral(":composerId"), {}); } auto lyricistId = insertLyricist(oneTrack.lyricist()); if (lyricistId != 0) { d->mInsertTrackQuery.bindValue(QStringLiteral(":lyricistId"), lyricistId); } else { d->mInsertTrackQuery.bindValue(QStringLiteral(":lyricistId"), {}); } d->mInsertTrackQuery.bindValue(QStringLiteral(":comment"), oneTrack.comment()); d->mInsertTrackQuery.bindValue(QStringLiteral(":year"), oneTrack.year()); d->mInsertTrackQuery.bindValue(QStringLiteral(":channels"), oneTrack.channels()); d->mInsertTrackQuery.bindValue(QStringLiteral(":bitRate"), oneTrack.bitRate()); d->mInsertTrackQuery.bindValue(QStringLiteral(":sampleRate"), oneTrack.sampleRate()); d->mInsertTrackQuery.bindValue(QStringLiteral(":hasEmbeddedCover"), oneTrack.hasEmbeddedCover()); auto result = d->mInsertTrackQuery.exec(); if (result && d->mInsertTrackQuery.isActive()) { d->mInsertTrackQuery.finish(); if (!isModifiedTrack) { ++d->mTrackId; } updateTrackOrigin(originTrackId, oneTrack.resourceURI(), oneTrack.fileModificationTime()); if (isModifiedTrack) { recordModifiedTrack(originTrackId); if (albumId != 0) { recordModifiedAlbum(albumId); } if (oldAlbumId != 0) { recordModifiedAlbum(oldAlbumId); } } if (albumId != 0) { if (updateAlbumFromId(albumId, covers[oneTrack.resourceURI().toString()], oneTrack, trackPath)) { auto modifiedTracks = fetchTrackIds(albumId); for (auto oneModifiedTrack : modifiedTracks) { if (oneModifiedTrack != resultId) { recordModifiedTrack(oneModifiedTrack); } } } recordModifiedAlbum(albumId); } } else { d->mInsertTrackQuery.finish(); Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalInsertTrack" << oneTrack << oneTrack.resourceURI(); qDebug() << "DatabaseInterface::internalInsertTrack" << d->mInsertTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::internalInsertTrack" << d->mInsertTrackQuery.boundValues(); qDebug() << "DatabaseInterface::internalInsertTrack" << d->mInsertTrackQuery.lastError(); } } return resultId; } MusicAudioTrack DatabaseInterface::buildTrackFromDatabaseRecord(const QSqlRecord &trackRecord) const { auto id = trackRecord.value(0).toULongLong(); auto &result = d->mTracksCache[id]; if (result.isValid()) { return result; } result.setDatabaseId(id); result.setTitle(trackRecord.value(1).toString()); result.setParentId(trackRecord.value(2).toString()); result.setArtist(trackRecord.value(3).toString()); if (trackRecord.value(4).isValid()) { result.setAlbumArtist(trackRecord.value(4).toString()); } result.setResourceURI(trackRecord.value(5).toUrl()); result.setFileModificationTime(trackRecord.value(6).toDateTime()); result.setTrackNumber(trackRecord.value(7).toInt()); result.setDiscNumber(trackRecord.value(8).toInt()); result.setDuration(QTime::fromMSecsSinceStartOfDay(trackRecord.value(9).toInt())); result.setAlbumName(trackRecord.value(10).toString()); result.setRating(trackRecord.value(11).toInt()); result.setAlbumCover(trackRecord.value(12).toUrl()); result.setIsSingleDiscAlbum(trackRecord.value(13).toBool()); result.setGenre(trackRecord.value(14).toString()); result.setComposer(trackRecord.value(15).toString()); result.setLyricist(trackRecord.value(16).toString()); result.setComment(trackRecord.value(17).toString()); result.setYear(trackRecord.value(18).toInt()); result.setChannels(trackRecord.value(19).toInt()); result.setBitRate(trackRecord.value(20).toInt()); result.setSampleRate(trackRecord.value(21).toInt()); result.setAlbumId(trackRecord.value(2).toULongLong()); result.setHasEmbeddedCover(trackRecord.value(22).toBool()); result.setValid(true); return result; } DatabaseInterface::TrackDataType DatabaseInterface::buildTrackDataFromDatabaseRecord(const QSqlRecord &trackRecord) const { TrackDataType result; result[TrackDataType::key_type::DatabaseIdRole] = trackRecord.value(0); result[TrackDataType::key_type::TitleRole] = trackRecord.value(1); result[TrackDataType::key_type::AlbumRole] = trackRecord.value(10); result[TrackDataType::key_type::AlbumIdRole] = trackRecord.value(2); result[TrackDataType::key_type::ArtistRole] = trackRecord.value(3); result[TrackDataType::key_type::AlbumArtistRole] = trackRecord.value(4); result[TrackDataType::key_type::ResourceRole] = trackRecord.value(5); result[TrackDataType::key_type::TrackNumberRole] = trackRecord.value(7); result[TrackDataType::key_type::DiscNumberRole] = trackRecord.value(8); result[TrackDataType::key_type::DurationRole] = QTime::fromMSecsSinceStartOfDay(trackRecord.value(9).toInt()); result[TrackDataType::key_type::MilliSecondsDurationRole] = trackRecord.value(9).toInt(); result[TrackDataType::key_type::RatingRole] = trackRecord.value(11); result[TrackDataType::key_type::ImageUrlRole] = QUrl(trackRecord.value(12).toString()); result[TrackDataType::key_type::IsSingleDiscAlbumRole] = trackRecord.value(13); return result; } void DatabaseInterface::internalRemoveTracksList(const QList &removedTracks) { for (const auto &removedTrackFileName : removedTracks) { d->mRemoveTracksMapping.bindValue(QStringLiteral(":fileName"), removedTrackFileName.toString()); auto result = d->mRemoveTracksMapping.exec(); if (!result || !d->mRemoveTracksMapping.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalRemoveTracksList" << d->mRemoveTracksMapping.lastQuery(); qDebug() << "DatabaseInterface::internalRemoveTracksList" << d->mRemoveTracksMapping.boundValues(); qDebug() << "DatabaseInterface::internalRemoveTracksList" << d->mRemoveTracksMapping.lastError(); continue; } d->mRemoveTracksMapping.finish(); } internalRemoveTracksWithoutMapping(); } void DatabaseInterface::internalRemoveTracksList(const QHash &removedTracks, qulonglong sourceId) { for (auto itRemovedTrack = removedTracks.begin(); itRemovedTrack != removedTracks.end(); ++itRemovedTrack) { d->mRemoveTracksMappingFromSource.bindValue(QStringLiteral(":fileName"), itRemovedTrack.key().toString()); d->mRemoveTracksMappingFromSource.bindValue(QStringLiteral(":sourceId"), sourceId); auto result = d->mRemoveTracksMappingFromSource.exec(); if (!result || !d->mRemoveTracksMappingFromSource.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::removeTracksList" << d->mRemoveTracksMappingFromSource.lastQuery(); qDebug() << "DatabaseInterface::removeTracksList" << d->mRemoveTracksMappingFromSource.boundValues(); qDebug() << "DatabaseInterface::removeTracksList" << d->mRemoveTracksMappingFromSource.lastError(); continue; } d->mRemoveTracksMappingFromSource.finish(); } internalRemoveTracksWithoutMapping(); } void DatabaseInterface::internalRemoveTracksWithoutMapping() { auto queryResult = d->mSelectTracksWithoutMappingQuery.exec(); if (!queryResult || !d->mSelectTracksWithoutMappingQuery.isSelect() || !d->mSelectTracksWithoutMappingQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectTracksWithoutMappingQuery.lastQuery(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectTracksWithoutMappingQuery.boundValues(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectTracksWithoutMappingQuery.lastError(); d->mSelectTracksWithoutMappingQuery.finish(); return; } QList willRemoveTrack; while (d->mSelectTracksWithoutMappingQuery.next()) { const auto ¤tRecord = d->mSelectTracksWithoutMappingQuery.record(); willRemoveTrack.push_back(buildTrackFromDatabaseRecord(currentRecord)); } d->mSelectTracksWithoutMappingQuery.finish(); QSet modifiedAlbums; QUrl::FormattingOptions currentOptions = QUrl::PreferLocalFile | QUrl::RemoveAuthority | QUrl::RemoveFilename | QUrl::RemoveFragment | QUrl::RemovePassword | QUrl::RemovePort | QUrl::RemoveQuery | QUrl::RemoveScheme | QUrl::RemoveUserInfo; for (const auto &oneRemovedTrack : willRemoveTrack) { removeTrackInDatabase(oneRemovedTrack.databaseId()); Q_EMIT trackRemoved(oneRemovedTrack.databaseId()); const auto &modifiedAlbumId = internalAlbumIdFromTitleAndArtist(oneRemovedTrack.albumName(), oneRemovedTrack.albumArtist()); const auto &allTracksFromArtist = internalTracksFromAuthor(oneRemovedTrack.artist()); const auto &allAlbumsFromArtist = internalAlbumIdsFromAuthor(oneRemovedTrack.artist()); const auto &removedArtistId = internalArtistIdFromName(oneRemovedTrack.artist()); const auto &trackPath = oneRemovedTrack.resourceURI().toString(currentOptions); recordModifiedAlbum(modifiedAlbumId); modifiedAlbums.insert(modifiedAlbumId); updateAlbumFromId(modifiedAlbumId, oneRemovedTrack.albumCover(), oneRemovedTrack, trackPath); if (removedArtistId != 0 && allTracksFromArtist.isEmpty() && allAlbumsFromArtist.isEmpty()) { removeArtistInDatabase(removedArtistId); Q_EMIT artistRemoved(removedArtistId); } } for (auto modifiedAlbumId : modifiedAlbums) { auto modifiedAlbum = internalAlbumFromId(modifiedAlbumId); if (modifiedAlbum.isValid() && !modifiedAlbum.isEmpty()) { Q_EMIT albumModified({{DatabaseIdRole, modifiedAlbumId}}, modifiedAlbumId); } else { removeAlbumInDatabase(modifiedAlbum.databaseId()); Q_EMIT albumRemoved(modifiedAlbumId); const auto &allTracksFromArtist = internalTracksFromAuthor(modifiedAlbum.artist()); const auto &allAlbumsFromArtist = internalAlbumIdsFromAuthor(modifiedAlbum.artist()); const auto &removedArtistId = internalArtistIdFromName(modifiedAlbum.artist()); if (removedArtistId != 0 && allTracksFromArtist.isEmpty() && allAlbumsFromArtist.isEmpty()) { removeArtistInDatabase(removedArtistId); Q_EMIT artistRemoved(removedArtistId); } } } } QUrl DatabaseInterface::internalAlbumArtUriFromAlbumId(qulonglong albumId) { auto result = QUrl(); d->mSelectAlbumArtUriFromAlbumIdQuery.bindValue(QStringLiteral(":albumId"), albumId); auto queryResult = d->mSelectAlbumArtUriFromAlbumIdQuery.exec(); if (!queryResult || !d->mSelectAlbumArtUriFromAlbumIdQuery.isSelect() || !d->mSelectAlbumArtUriFromAlbumIdQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectAlbumArtUriFromAlbumIdQuery.lastQuery(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectAlbumArtUriFromAlbumIdQuery.boundValues(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectAlbumArtUriFromAlbumIdQuery.lastError(); d->mSelectAlbumArtUriFromAlbumIdQuery.finish(); return result; } if (!d->mSelectAlbumArtUriFromAlbumIdQuery.next()) { d->mSelectAlbumArtUriFromAlbumIdQuery.finish(); return result; } result = d->mSelectAlbumArtUriFromAlbumIdQuery.record().value(0).toUrl(); d->mSelectAlbumArtUriFromAlbumIdQuery.finish(); return result; } bool DatabaseInterface::isValidArtist(qulonglong albumId) { auto result = false; d->mSelectAlbumQuery.bindValue(QStringLiteral(":albumId"), albumId); auto queryResult = d->mSelectAlbumQuery.exec(); if (!queryResult || !d->mSelectAlbumQuery.isSelect() || !d->mSelectAlbumQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectAlbumQuery.lastError(); d->mSelectAlbumQuery.finish(); return result; } if (!d->mSelectAlbumQuery.next()) { d->mSelectAlbumQuery.finish(); return result; } const auto ¤tRecord = d->mSelectAlbumQuery.record(); result = !currentRecord.value(3).toString().isEmpty(); return result; } qulonglong DatabaseInterface::internalSourceIdFromName(const QString &sourceName) { qulonglong sourceId = 0; d->mSelectMusicSource.bindValue(QStringLiteral(":name"), sourceName); auto queryResult = d->mSelectMusicSource.exec(); if (!queryResult || !d->mSelectMusicSource.isSelect() || !d->mSelectMusicSource.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.lastQuery(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.boundValues(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.lastError(); d->mSelectMusicSource.finish(); return sourceId; } if (!d->mSelectMusicSource.next()) { return sourceId; } sourceId = d->mSelectMusicSource.record().value(0).toULongLong(); d->mSelectMusicSource.finish(); return sourceId; } QHash DatabaseInterface::internalAllFileNameFromSource(qulonglong sourceId) { QHash allFileNames; d->mSelectAllTrackFilesFromSourceQuery.bindValue(QStringLiteral(":discoverId"), sourceId); auto queryResult = d->mSelectAllTrackFilesFromSourceQuery.exec(); if (!queryResult || !d->mSelectAllTrackFilesFromSourceQuery.isSelect() || !d->mSelectAllTrackFilesFromSourceQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectAllTrackFilesFromSourceQuery.lastQuery(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectAllTrackFilesFromSourceQuery.boundValues(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectAllTrackFilesFromSourceQuery.lastError(); d->mSelectAllTrackFilesFromSourceQuery.finish(); return allFileNames; } while(d->mSelectAllTrackFilesFromSourceQuery.next()) { auto fileName = d->mSelectAllTrackFilesFromSourceQuery.record().value(0).toUrl(); auto fileModificationTime = d->mSelectAllTrackFilesFromSourceQuery.record().value(1).toDateTime(); allFileNames[fileName] = fileModificationTime; } d->mSelectAllTrackFilesFromSourceQuery.finish(); return allFileNames; } bool DatabaseInterface::internalGenericPartialData(QSqlQuery &query) { auto result = false; auto queryResult = query.exec(); if (!queryResult || !query.isSelect() || !query.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAllGenericPartialData" << query.lastQuery(); qDebug() << "DatabaseInterface::internalAllGenericPartialData" << query.boundValues(); qDebug() << "DatabaseInterface::internalAllGenericPartialData" << query.lastError(); query.finish(); auto transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } result = true; return result; } qulonglong DatabaseInterface::insertLyricist(const QString &name) { auto result = qulonglong(0); if (name.isEmpty()) { return result; } d->mSelectLyricistByNameQuery.bindValue(QStringLiteral(":name"), name); auto queryResult = d->mSelectLyricistByNameQuery.exec(); if (!queryResult || !d->mSelectLyricistByNameQuery.isSelect() || !d->mSelectLyricistByNameQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertLyricist" << d->mSelectLyricistByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::insertLyricist" << d->mSelectLyricistByNameQuery.boundValues(); qDebug() << "DatabaseInterface::insertLyricist" << d->mSelectLyricistByNameQuery.lastError(); d->mSelectLyricistByNameQuery.finish(); return result; } if (d->mSelectLyricistByNameQuery.next()) { result = d->mSelectLyricistByNameQuery.record().value(0).toULongLong(); d->mSelectLyricistByNameQuery.finish(); return result; } d->mSelectLyricistByNameQuery.finish(); d->mInsertLyricistQuery.bindValue(QStringLiteral(":lyricistId"), d->mLyricistId); d->mInsertLyricistQuery.bindValue(QStringLiteral(":name"), name); queryResult = d->mInsertLyricistQuery.exec(); if (!queryResult || !d->mInsertLyricistQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertLyricist" << d->mInsertLyricistQuery.lastQuery(); qDebug() << "DatabaseInterface::insertLyricist" << d->mInsertLyricistQuery.boundValues(); qDebug() << "DatabaseInterface::insertLyricist" << d->mInsertLyricistQuery.lastError(); d->mInsertLyricistQuery.finish(); return result; } result = d->mLyricistId; ++d->mLyricistId; d->mInsertLyricistQuery.finish(); Q_EMIT lyricistsAdded(internalAllLyricistsPartialData()); return result; } qulonglong DatabaseInterface::internalArtistIdFromName(const QString &name) { auto result = qulonglong(0); if (name.isEmpty()) { return result; } d->mSelectArtistByNameQuery.bindValue(QStringLiteral(":name"), name); auto queryResult = d->mSelectArtistByNameQuery.exec(); if (!queryResult || !d->mSelectArtistByNameQuery.isSelect() || !d->mSelectArtistByNameQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectArtistByNameQuery.lastQuery(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectArtistByNameQuery.boundValues(); qDebug() << "DatabaseInterface::insertArtist" << d->mSelectArtistByNameQuery.lastError(); d->mSelectArtistByNameQuery.finish(); return result; } if (!d->mSelectArtistByNameQuery.next()) { d->mSelectArtistByNameQuery.finish(); return result; } result = d->mSelectArtistByNameQuery.record().value(0).toULongLong(); d->mSelectArtistByNameQuery.finish(); return result; } void DatabaseInterface::removeTrackInDatabase(qulonglong trackId) { d->mRemoveTrackQuery.bindValue(QStringLiteral(":trackId"), trackId); d->mTracksCache.remove(trackId); auto result = d->mRemoveTrackQuery.exec(); if (!result || !d->mRemoveTrackQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::removeTrackInDatabase" << d->mRemoveTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::removeTrackInDatabase" << d->mRemoveTrackQuery.boundValues(); qDebug() << "DatabaseInterface::removeTrackInDatabase" << d->mRemoveTrackQuery.lastError(); } d->mRemoveTrackQuery.finish(); } void DatabaseInterface::updateTrackInDatabase(const MusicAudioTrack &oneTrack, const QString &albumPath) { d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackId"), oneTrack.databaseId()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":title"), oneTrack.title()); insertArtist(oneTrack.artist()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":artistName"), oneTrack.artist()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":albumTitle"), oneTrack.albumName()); if (oneTrack.isValidAlbumArtist()) { d->mUpdateTrackQuery.bindValue(QStringLiteral(":albumArtistName"), oneTrack.albumArtist()); } else { d->mUpdateTrackQuery.bindValue(QStringLiteral(":albumArtistName"), {}); } d->mUpdateTrackQuery.bindValue(QStringLiteral(":albumPath"), albumPath); d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackNumber"), oneTrack.trackNumber()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":discNumber"), oneTrack.discNumber()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackDuration"), QVariant::fromValue(oneTrack.duration().msecsSinceStartOfDay())); d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackRating"), oneTrack.rating()); auto genreId = insertGenre(oneTrack.genre()); if (genreId != 0) { d->mUpdateTrackQuery.bindValue(QStringLiteral(":genreId"), genreId); } else { d->mUpdateTrackQuery.bindValue(QStringLiteral(":genreId"), {}); } auto composerId = insertComposer(oneTrack.composer()); if (composerId != 0) { d->mUpdateTrackQuery.bindValue(QStringLiteral(":composerId"), composerId); } else { d->mUpdateTrackQuery.bindValue(QStringLiteral(":composerId"), {}); } auto lyricistId = insertLyricist(oneTrack.lyricist()); if (lyricistId != 0) { d->mUpdateTrackQuery.bindValue(QStringLiteral(":lyricistId"), lyricistId); } else { d->mUpdateTrackQuery.bindValue(QStringLiteral(":lyricistId"), {}); } d->mUpdateTrackQuery.bindValue(QStringLiteral(":comment"), oneTrack.comment()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":year"), oneTrack.year()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":channels"), oneTrack.channels()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":bitRate"), oneTrack.bitRate()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":sampleRate"), oneTrack.sampleRate()); auto result = d->mUpdateTrackQuery.exec(); if (!result || !d->mUpdateTrackQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::updateTrackInDatabase" << d->mUpdateTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::updateTrackInDatabase" << d->mUpdateTrackQuery.boundValues(); qDebug() << "DatabaseInterface::updateTrackInDatabase" << d->mUpdateTrackQuery.lastError(); } d->mUpdateTrackQuery.finish(); } void DatabaseInterface::removeAlbumInDatabase(qulonglong albumId) { d->mRemoveAlbumQuery.bindValue(QStringLiteral(":albumId"), albumId); d->mAlbumsCache.remove(albumId); auto result = d->mRemoveAlbumQuery.exec(); if (!result || !d->mRemoveAlbumQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::removeAlbumInDatabase" << d->mRemoveAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::removeAlbumInDatabase" << d->mRemoveAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::removeAlbumInDatabase" << d->mRemoveAlbumQuery.lastError(); } d->mRemoveAlbumQuery.finish(); } void DatabaseInterface::removeArtistInDatabase(qulonglong artistId) { d->mRemoveArtistQuery.bindValue(QStringLiteral(":artistId"), artistId); auto result = d->mRemoveArtistQuery.exec(); if (!result || !d->mRemoveArtistQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::removeArtistInDatabase" << d->mRemoveArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::removeArtistInDatabase" << d->mRemoveArtistQuery.boundValues(); qDebug() << "DatabaseInterface::removeArtistInDatabase" << d->mRemoveArtistQuery.lastError(); } d->mRemoveArtistQuery.finish(); } void DatabaseInterface::reloadExistingDatabase() { auto transactionResult = startTransaction(); if (!transactionResult) { return; } //d->mInitialUpdateTracksValidity.exec(); qDebug() << "DatabaseInterface::reloadExistingDatabase"; transactionResult = finishTransaction(); if (!transactionResult) { return; } d->mArtistId = initialId(DataUtils::DataType::AllArtists); if (d->mArtistId > 1) { Q_EMIT artistsAdded(allArtistsData()); } d->mComposerId = initialId(DataUtils::DataType::AllComposers); d->mLyricistId = initialId(DataUtils::DataType::AllLyricists); d->mAlbumId = initialId(DataUtils::DataType::AllAlbums); if (d->mAlbumId > 1) { Q_EMIT albumsAdded(allAlbumsData()); } d->mTrackId = initialId(DataUtils::DataType::AllTracks); if (d->mTrackId > 1) { Q_EMIT tracksAdded(allTracksData()); } d->mGenreId = initialId(DataUtils::DataType::AllGenres);; if (d->mGenreId > 1) { Q_EMIT genresAdded(allGenresData()); } } qulonglong DatabaseInterface::initialId(DataUtils::DataType aType) { switch (aType) { case DataUtils::DataType::AllAlbums: return genericInitialId(d->mQueryMaximumAlbumIdQuery); case DataUtils::DataType::AllArtists: return genericInitialId(d->mQueryMaximumArtistIdQuery); case DataUtils::DataType::AllComposers: return genericInitialId(d->mQueryMaximumComposerIdQuery); case DataUtils::DataType::AllGenres: return genericInitialId(d->mQueryMaximumGenreIdQuery); case DataUtils::DataType::AllLyricists: return genericInitialId(d->mQueryMaximumLyricistIdQuery); case DataUtils::DataType::AllTracks: return genericInitialId(d->mQueryMaximumTrackIdQuery); case DataUtils::DataType::UnknownType: break; } return 1; } qulonglong DatabaseInterface::genericInitialId(QSqlQuery &request) { auto result = qulonglong(0); auto transactionResult = startTransaction(); if (!transactionResult) { return result; } auto queryResult = request.exec(); if (!queryResult || !request.isSelect() || !request.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertMusicSource" << request.lastQuery(); qDebug() << "DatabaseInterface::insertMusicSource" << request.boundValues(); qDebug() << "DatabaseInterface::insertMusicSource" << request.lastError(); request.finish(); transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } if (request.next()) { result = request.record().value(0).toULongLong() + 1; request.finish(); } transactionResult = finishTransaction(); if (!transactionResult) { return result; } return result; } qulonglong DatabaseInterface::insertMusicSource(const QString &name) { qulonglong result = 0; d->mSelectMusicSource.bindValue(QStringLiteral(":name"), name); auto queryResult = d->mSelectMusicSource.exec(); if (!queryResult || !d->mSelectMusicSource.isSelect() || !d->mSelectMusicSource.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.lastQuery(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.boundValues(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.lastError(); d->mSelectMusicSource.finish(); return result; } if (d->mSelectMusicSource.next()) { result = d->mSelectMusicSource.record().value(0).toULongLong(); d->mSelectMusicSource.finish(); return result; } d->mSelectMusicSource.finish(); d->mInsertMusicSource.bindValue(QStringLiteral(":discoverId"), d->mDiscoverId); d->mInsertMusicSource.bindValue(QStringLiteral(":name"), name); queryResult = d->mInsertMusicSource.exec(); if (!queryResult || !d->mInsertMusicSource.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mInsertMusicSource.lastQuery(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mInsertMusicSource.boundValues(); qDebug() << "DatabaseInterface::insertMusicSource" << d->mInsertMusicSource.lastError(); d->mInsertMusicSource.finish(); return d->mDiscoverId; } d->mInsertMusicSource.finish(); ++d->mDiscoverId; return d->mDiscoverId - 1; } QList DatabaseInterface::fetchTracks(qulonglong albumId) { auto allTracks = QList(); d->mSelectTrackQuery.bindValue(QStringLiteral(":albumId"), albumId); auto result = d->mSelectTrackQuery.exec(); if (!result || !d->mSelectTrackQuery.isSelect() || !d->mSelectTrackQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::fetchTracks" << d->mSelectTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::fetchTracks" << d->mSelectTrackQuery.boundValues(); qDebug() << "DatabaseInterface::fetchTracks" << d->mSelectTrackQuery.lastError(); } while (d->mSelectTrackQuery.next()) { const auto ¤tRecord = d->mSelectTrackQuery.record(); allTracks.push_back(buildTrackFromDatabaseRecord(currentRecord)); } d->mSelectTrackQuery.finish(); return allTracks; } QList DatabaseInterface::fetchTrackIds(qulonglong albumId) { auto allTracks = QList(); d->mSelectTrackQuery.bindValue(QStringLiteral(":albumId"), albumId); auto result = d->mSelectTrackQuery.exec(); if (!result || !d->mSelectTrackQuery.isSelect() || !d->mSelectTrackQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::fetchTracks" << d->mSelectTrackQuery.lastQuery(); qDebug() << "DatabaseInterface::fetchTracks" << d->mSelectTrackQuery.boundValues(); qDebug() << "DatabaseInterface::fetchTracks" << d->mSelectTrackQuery.lastError(); } while (d->mSelectTrackQuery.next()) { const auto ¤tRecord = d->mSelectTrackQuery.record(); allTracks.push_back(currentRecord.value(0).toULongLong()); } d->mSelectTrackQuery.finish(); return allTracks; } MusicAlbum DatabaseInterface::internalAlbumFromId(qulonglong albumId) { auto &retrievedAlbum = d->mAlbumsCache[albumId]; if (retrievedAlbum.isValid()) { return retrievedAlbum; } d->mSelectAlbumQuery.bindValue(QStringLiteral(":albumId"), albumId); auto result = d->mSelectAlbumQuery.exec(); if (!result || !d->mSelectAlbumQuery.isSelect() || !d->mSelectAlbumQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectAlbumQuery.lastError(); d->mSelectAlbumQuery.finish(); return retrievedAlbum; } if (!d->mSelectAlbumQuery.next()) { d->mSelectAlbumQuery.finish(); return retrievedAlbum; } const auto ¤tRecord = d->mSelectAlbumQuery.record(); retrievedAlbum.setDatabaseId(currentRecord.value(0).toULongLong()); retrievedAlbum.setTitle(currentRecord.value(1).toString()); retrievedAlbum.setId(currentRecord.value(2).toString()); retrievedAlbum.setArtist(currentRecord.value(3).toString()); retrievedAlbum.setAlbumPath(currentRecord.value(4).toUrl()); retrievedAlbum.setAlbumArtURI(currentRecord.value(5).toUrl()); retrievedAlbum.setTracksCount(currentRecord.value(6).toInt()); retrievedAlbum.setIsSingleDiscAlbum(currentRecord.value(7).toBool()); retrievedAlbum.setTracks(fetchTracks(albumId)); retrievedAlbum.setValid(true); d->mSelectAlbumQuery.finish(); d->mSelectGenreForAlbumQuery.bindValue(QStringLiteral(":albumId"), albumId); result = d->mSelectGenreForAlbumQuery.exec(); if (!result || !d->mSelectGenreForAlbumQuery.isSelect() || !d->mSelectGenreForAlbumQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectGenreForAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectGenreForAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::internalAlbumFromId" << d->mSelectGenreForAlbumQuery.lastError(); d->mSelectGenreForAlbumQuery.finish(); return retrievedAlbum; } QStringList allGenres; while(d->mSelectGenreForAlbumQuery.next()) { allGenres.push_back(d->mSelectGenreForAlbumQuery.record().value(0).toString()); } retrievedAlbum.setGenres(allGenres); d->mSelectGenreForAlbumQuery.finish(); return retrievedAlbum; } MusicAlbum DatabaseInterface::internalAlbumFromTitleAndArtist(const QString &title, const QString &artist) { auto result = MusicAlbum(); auto albumId = internalAlbumIdFromTitleAndArtist(title, artist); if (albumId == 0) { return result; } result = internalAlbumFromId(albumId); return result; } qulonglong DatabaseInterface::internalAlbumIdFromTitleAndArtist(const QString &title, const QString &artist) { auto result = qulonglong(0); d->mSelectAlbumIdFromTitleQuery.bindValue(QStringLiteral(":title"), title); d->mSelectAlbumIdFromTitleQuery.bindValue(QStringLiteral(":artistName"), artist); auto queryResult = d->mSelectAlbumIdFromTitleQuery.exec(); if (!queryResult || !d->mSelectAlbumIdFromTitleQuery.isSelect() || !d->mSelectAlbumIdFromTitleQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAlbumIdFromTitleAndArtist" << d->mSelectAlbumIdFromTitleQuery.lastQuery(); qDebug() << "DatabaseInterface::internalAlbumIdFromTitleAndArtist" << d->mSelectAlbumIdFromTitleQuery.boundValues(); qDebug() << "DatabaseInterface::internalAlbumIdFromTitleAndArtist" << d->mSelectAlbumIdFromTitleQuery.lastError(); d->mSelectAlbumIdFromTitleQuery.finish(); return result; } if (d->mSelectAlbumIdFromTitleQuery.next()) { result = d->mSelectAlbumIdFromTitleQuery.record().value(0).toULongLong(); } d->mSelectAlbumIdFromTitleQuery.finish(); if (result == 0) { d->mSelectAlbumIdFromTitleWithoutArtistQuery.bindValue(QStringLiteral(":title"), title); auto queryResult = d->mSelectAlbumIdFromTitleWithoutArtistQuery.exec(); if (!queryResult || !d->mSelectAlbumIdFromTitleWithoutArtistQuery.isSelect() || !d->mSelectAlbumIdFromTitleWithoutArtistQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalAlbumIdFromTitleAndArtist" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::internalAlbumIdFromTitleAndArtist" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.boundValues(); qDebug() << "DatabaseInterface::internalAlbumIdFromTitleAndArtist" << d->mSelectAlbumIdFromTitleWithoutArtistQuery.lastError(); d->mSelectAlbumIdFromTitleWithoutArtistQuery.finish(); return result; } if (d->mSelectAlbumIdFromTitleWithoutArtistQuery.next()) { result = d->mSelectAlbumIdFromTitleWithoutArtistQuery.record().value(0).toULongLong(); } d->mSelectAlbumIdFromTitleWithoutArtistQuery.finish(); } return result; } MusicAudioTrack DatabaseInterface::internalTrackFromDatabaseId(qulonglong id) { auto result = MusicAudioTrack(); if (result.isValid()) { return result; } if (!d || !d->mTracksDatabase.isValid() || !d->mInitFinished) { return result; } d->mSelectTrackFromIdQuery.bindValue(QStringLiteral(":trackId"), id); auto queryResult = d->mSelectTrackFromIdQuery.exec(); if (!queryResult || !d->mSelectTrackFromIdQuery.isSelect() || !d->mSelectTrackFromIdQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalTrackFromDatabaseId" << d->mSelectAlbumQuery.lastQuery(); qDebug() << "DatabaseInterface::internalTrackFromDatabaseId" << d->mSelectAlbumQuery.boundValues(); qDebug() << "DatabaseInterface::internalTrackFromDatabaseId" << d->mSelectAlbumQuery.lastError(); d->mSelectTrackFromIdQuery.finish(); return result; } if (!d->mSelectTrackFromIdQuery.next()) { d->mSelectTrackFromIdQuery.finish(); return result; } const auto ¤tRecord = d->mSelectTrackFromIdQuery.record(); result = buildTrackFromDatabaseRecord(currentRecord); d->mSelectTrackFromIdQuery.finish(); return result; } qulonglong DatabaseInterface::internalTrackIdFromTitleAlbumTracDiscNumber(const QString &title, const QString &artist, const QString &album, int trackNumber, int discNumber) { auto result = qulonglong(0); if (!d) { return result; } d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":title"), title); d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":artist"), artist); d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":album"), album); d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":trackNumber"), trackNumber); d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":discNumber"), discNumber); auto queryResult = d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.exec(); if (!queryResult || !d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.isSelect() || !d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::trackIdFromTitleAlbumArtist" << d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.lastQuery(); qDebug() << "DatabaseInterface::trackIdFromTitleAlbumArtist" << d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.boundValues(); qDebug() << "DatabaseInterface::trackIdFromTitleAlbumArtist" << d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.lastError(); d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.finish(); return result; } if (d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.next()) { result = d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.record().value(0).toULongLong(); } d->mSelectTrackIdFromTitleArtistAlbumTrackDiscNumberQuery.finish(); return result; } qulonglong DatabaseInterface::getDuplicateTrackIdFromTitleAlbumTrackDiscNumber(const QString &title, const QString &album, const QString &albumArtist, const QString &trackPath, int trackNumber, int discNumber) { auto result = qulonglong(0); if (!d) { return result; } d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":title"), title); d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":album"), album); d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":albumPath"), trackPath); d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":albumArtist"), albumArtist); d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":trackNumber"), trackNumber); d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.bindValue(QStringLiteral(":discNumber"), discNumber); auto queryResult = d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.exec(); if (!queryResult || !d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.isSelect() || !d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::trackIdFromTitleAlbumArtist" << d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.lastQuery(); qDebug() << "DatabaseInterface::trackIdFromTitleAlbumArtist" << d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.boundValues(); qDebug() << "DatabaseInterface::trackIdFromTitleAlbumArtist" << d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.lastError(); d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.finish(); return result; } if (d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.next()) { result = d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.record().value(0).toULongLong(); } d->mSelectTrackIdFromTitleAlbumTrackDiscNumberQuery.finish(); return result; } qulonglong DatabaseInterface::internalTrackIdFromFileName(const QUrl &fileName) { auto result = qulonglong(0); if (!d) { return result; } d->mSelectTracksMapping.bindValue(QStringLiteral(":fileName"), fileName); auto queryResult = d->mSelectTracksMapping.exec(); if (!queryResult || !d->mSelectTracksMapping.isSelect() || !d->mSelectTracksMapping.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMapping.lastQuery(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMapping.boundValues(); qDebug() << "DatabaseInterface::internalTrackIdFromFileName" << d->mSelectTracksMapping.lastError(); d->mSelectTracksMapping.finish(); return result; } if (d->mSelectTracksMapping.next()) { const auto ¤tRecordValue = d->mSelectTracksMapping.record().value(0); if (currentRecordValue.isValid()) { result = currentRecordValue.toULongLong(); } } d->mSelectTracksMapping.finish(); return result; } DatabaseInterface::ListTrackDataType DatabaseInterface::internalTracksFromAuthor(const QString &ArtistName) { auto allTracks = ListTrackDataType{}; d->mSelectTracksFromArtist.bindValue(QStringLiteral(":artistName"), ArtistName); auto result = d->mSelectTracksFromArtist.exec(); if (!result || !d->mSelectTracksFromArtist.isSelect() || !d->mSelectTracksFromArtist.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::tracksFromAuthor" << d->mSelectTracksFromArtist.lastQuery(); qDebug() << "DatabaseInterface::tracksFromAuthor" << d->mSelectTracksFromArtist.boundValues(); qDebug() << "DatabaseInterface::tracksFromAuthor" << d->mSelectTracksFromArtist.lastError(); return allTracks; } while (d->mSelectTracksFromArtist.next()) { const auto ¤tRecord = d->mSelectTracksFromArtist.record(); allTracks.push_back(buildTrackDataFromDatabaseRecord(currentRecord)); } d->mSelectTracksFromArtist.finish(); return allTracks; } QList DatabaseInterface::internalAlbumIdsFromAuthor(const QString &ArtistName) { auto allAlbumIds = QList(); d->mSelectAlbumIdsFromArtist.bindValue(QStringLiteral(":artistName"), ArtistName); auto result = d->mSelectAlbumIdsFromArtist.exec(); if (!result || !d->mSelectAlbumIdsFromArtist.isSelect() || !d->mSelectAlbumIdsFromArtist.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::tracksFromAuthor" << d->mSelectAlbumIdsFromArtist.lastQuery(); qDebug() << "DatabaseInterface::tracksFromAuthor" << d->mSelectAlbumIdsFromArtist.boundValues(); qDebug() << "DatabaseInterface::tracksFromAuthor" << d->mSelectAlbumIdsFromArtist.lastError(); return allAlbumIds; } while (d->mSelectAlbumIdsFromArtist.next()) { const auto ¤tRecord = d->mSelectAlbumIdsFromArtist.record(); allAlbumIds.push_back(currentRecord.value(0).toULongLong()); } d->mSelectAlbumIdsFromArtist.finish(); return allAlbumIds; } DatabaseInterface::ListArtistDataType DatabaseInterface::internalAllArtistsPartialData() { auto result = ListArtistDataType{}; if (!internalGenericPartialData(d->mSelectAllArtistsQuery)) { return result; } while(d->mSelectAllArtistsQuery.next()) { auto newData = ArtistDataType{}; const auto ¤tRecord = d->mSelectAllArtistsQuery.record(); newData[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); newData[DataType::key_type::TitleRole] = currentRecord.value(1); newData[DataType::key_type::GenreRole] = QVariant::fromValue(currentRecord.value(2).toString().split(QStringLiteral(", "))); result.push_back(newData); } d->mSelectAllArtistsQuery.finish(); return result; } DatabaseInterface::ArtistDataType DatabaseInterface::internalOneArtistPartialData(qulonglong databaseId) { auto result = ArtistDataType{}; d->mSelectArtistQuery.bindValue(QStringLiteral(":artistId"), databaseId); if (!internalGenericPartialData(d->mSelectArtistQuery)) { return result; } if (d->mSelectArtistQuery.next()) { const auto ¤tRecord = d->mSelectArtistQuery.record(); result[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); result[DataType::key_type::TitleRole] = currentRecord.value(1); result[DataType::key_type::GenreRole] = QVariant::fromValue(currentRecord.value(2).toString().split(QStringLiteral(", "))); } d->mSelectArtistQuery.finish(); return result; } DatabaseInterface::ListAlbumDataType DatabaseInterface::internalAllAlbumsPartialData() { auto result = ListAlbumDataType{}; if (!internalGenericPartialData(d->mSelectAllAlbumsShortQuery)) { return result; } while(d->mSelectAllAlbumsShortQuery.next()) { auto newData = AlbumDataType{}; const auto ¤tRecord = d->mSelectAllAlbumsShortQuery.record(); newData[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); newData[DataType::key_type::TitleRole] = currentRecord.value(1); newData[DataType::key_type::SecondaryTextRole] = currentRecord.value(2); newData[DataType::key_type::ImageUrlRole] = currentRecord.value(3); newData[DataType::key_type::ArtistRole] = currentRecord.value(4); newData[DataType::key_type::AllArtistsRole] = QVariant::fromValue(currentRecord.value(5).toString().split(QStringLiteral(", "))); newData[DataType::key_type::HighestTrackRating] = currentRecord.value(6); newData[DataType::key_type::GenreRole] = QVariant::fromValue(currentRecord.value(7).toString().split(QStringLiteral(", "))); result.push_back(newData); } d->mSelectAllAlbumsShortQuery.finish(); return result; } DatabaseInterface::AlbumDataType DatabaseInterface::internalOneAlbumPartialData(qulonglong databaseId) { auto result = AlbumDataType{}; d->mSelectAlbumQuery.bindValue(QStringLiteral(":albumId"), databaseId); if (!internalGenericPartialData(d->mSelectAlbumQuery)) { return result; } if (d->mSelectAlbumQuery.next()) { const auto ¤tRecord = d->mSelectAlbumQuery.record(); result[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); result[DataType::key_type::TitleRole] = currentRecord.value(1); result[DataType::key_type::SecondaryTextRole] = currentRecord.value(3); result[DataType::key_type::ImageUrlRole] = currentRecord.value(5); result[DataType::key_type::ArtistRole] = currentRecord.value(3); result[DataType::key_type::AllArtistsRole] = QVariant::fromValue(currentRecord.value(9).toString().split(QStringLiteral(", "))); result[DataType::key_type::HighestTrackRating] = currentRecord.value(10); result[DataType::key_type::GenreRole] = QVariant::fromValue(currentRecord.value(11).toString().split(QStringLiteral(", "))); } d->mSelectAlbumQuery.finish(); return result; } DatabaseInterface::ListTrackDataType DatabaseInterface::internalAllTracksPartialData() { auto result = ListTrackDataType{}; if (!internalGenericPartialData(d->mSelectAllTracksShortQuery)) { return result; } while(d->mSelectAllTracksShortQuery.next()) { auto newData = TrackDataType{}; const auto ¤tRecord = d->mSelectAllTracksShortQuery.record(); newData[TrackDataType::key_type::DatabaseIdRole] = currentRecord.value(0); newData[TrackDataType::key_type::TitleRole] = currentRecord.value(1); newData[TrackDataType::key_type::ArtistRole] = currentRecord.value(2); newData[TrackDataType::key_type::AlbumRole] = currentRecord.value(3); newData[TrackDataType::key_type::AlbumArtistRole] = currentRecord.value(4); newData[TrackDataType::key_type::DurationRole] = currentRecord.value(5); newData[TrackDataType::key_type::ImageUrlRole] = currentRecord.value(6); newData[TrackDataType::key_type::TrackNumberRole] = currentRecord.value(7); newData[TrackDataType::key_type::DiscNumberRole] = currentRecord.value(8); newData[TrackDataType::key_type::RatingRole] = currentRecord.value(9); newData[TrackDataType::key_type::IsSingleDiscAlbumRole] = currentRecord.value(13); result.push_back(newData); } d->mSelectAllTracksShortQuery.finish(); return result; } DatabaseInterface::TrackDataType DatabaseInterface::internalOneTrackPartialData(qulonglong databaseId) { auto result = TrackDataType{}; d->mSelectTrackFromIdQuery.bindValue(QStringLiteral(":trackId"), databaseId); if (!internalGenericPartialData(d->mSelectTrackFromIdQuery)) { return result; } if (d->mSelectTrackFromIdQuery.next()) { const auto ¤tRecord = d->mSelectTrackFromIdQuery.record(); result = buildTrackDataFromDatabaseRecord(currentRecord); } d->mSelectTrackFromIdQuery.finish(); return result; } DatabaseInterface::ListGenreDataType DatabaseInterface::internalAllGenresPartialData() { ListGenreDataType result; if (!internalGenericPartialData(d->mSelectAllGenresQuery)) { return result; } while(d->mSelectAllGenresQuery.next()) { auto newData = GenreDataType{}; const auto ¤tRecord = d->mSelectAllGenresQuery.record(); newData[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); newData[DataType::key_type::TitleRole] = currentRecord.value(1); result.push_back(newData); } d->mSelectAllGenresQuery.finish(); return result; } DatabaseInterface::GenreDataType DatabaseInterface::internalOneGenrePartialData(qulonglong databaseId) { auto result = GenreDataType{}; d->mSelectGenreQuery.bindValue(QStringLiteral(":genreId"), databaseId); if (!internalGenericPartialData(d->mSelectGenreQuery)) { return result; } if (d->mSelectGenreQuery.next()) { const auto ¤tRecord = d->mSelectGenreQuery.record(); result[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); result[DataType::key_type::TitleRole] = currentRecord.value(1); } d->mSelectGenreQuery.finish(); return result; } DatabaseInterface::ListArtistDataType DatabaseInterface::internalAllComposersPartialData() { ListArtistDataType result; if (!internalGenericPartialData(d->mSelectAllComposersQuery)) { return result; } while(d->mSelectAllComposersQuery.next()) { auto newData = ArtistDataType{}; const auto ¤tRecord = d->mSelectAllComposersQuery.record(); newData[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); newData[DataType::key_type::TitleRole] = currentRecord.value(1); result.push_back(newData); } d->mSelectAllComposersQuery.finish(); return result; } DatabaseInterface::ArtistDataType DatabaseInterface::internalOneComposerPartialData(qulonglong databaseId) { auto result = ArtistDataType{}; d->mSelectComposerQuery.bindValue(QStringLiteral(":composerId"), databaseId); if (!internalGenericPartialData(d->mSelectComposerQuery)) { return result; } if (d->mSelectComposerQuery.next()) { const auto ¤tRecord = d->mSelectComposerQuery.record(); result[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); result[DataType::key_type::TitleRole] = currentRecord.value(1); } d->mSelectComposerQuery.finish(); return result; } DatabaseInterface::ListArtistDataType DatabaseInterface::internalAllLyricistsPartialData() { ListArtistDataType result; if (!internalGenericPartialData(d->mSelectAllLyricistsQuery)) { return result; } while(d->mSelectAllLyricistsQuery.next()) { auto newData = ArtistDataType{}; const auto ¤tRecord = d->mSelectAllLyricistsQuery.record(); newData[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); newData[DataType::key_type::TitleRole] = currentRecord.value(1); result.push_back(newData); } d->mSelectAllLyricistsQuery.finish(); return result; } DatabaseInterface::ArtistDataType DatabaseInterface::internalOneLyricistPartialData(qulonglong databaseId) { auto result = ArtistDataType{}; d->mSelectLyricistQuery.bindValue(QStringLiteral(":lyricistId"), databaseId); if (!internalGenericPartialData(d->mSelectLyricistQuery)) { return result; } if (d->mSelectLyricistQuery.next()) { const auto ¤tRecord = d->mSelectLyricistQuery.record(); result[DataType::key_type::DatabaseIdRole] = currentRecord.value(0); result[DataType::key_type::TitleRole] = currentRecord.value(1); } d->mSelectLyricistQuery.finish(); return result; } bool DatabaseInterface::prepareQuery(QSqlQuery &query, const QString &queryText) const { query.setForwardOnly(true); return query.prepare(queryText); } void DatabaseInterface::updateAlbumArtist(qulonglong albumId, const QString &title, const QString &albumPath, const QString &artistName) { d->mUpdateAlbumArtistQuery.bindValue(QStringLiteral(":albumId"), albumId); insertArtist(artistName); d->mUpdateAlbumArtistQuery.bindValue(QStringLiteral(":artistName"), artistName); auto queryResult = d->mUpdateAlbumArtistQuery.exec(); if (!queryResult || !d->mUpdateAlbumArtistQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::updateAlbumArtist" << d->mUpdateAlbumArtistQuery.lastQuery(); qDebug() << "DatabaseInterface::updateAlbumArtist" << d->mUpdateAlbumArtistQuery.boundValues(); qDebug() << "DatabaseInterface::updateAlbumArtist" << d->mUpdateAlbumArtistQuery.lastError(); d->mUpdateAlbumArtistQuery.finish(); return; } d->mUpdateAlbumArtistQuery.finish(); d->mUpdateAlbumArtistInTracksQuery.bindValue(QStringLiteral(":albumTitle"), title); d->mUpdateAlbumArtistInTracksQuery.bindValue(QStringLiteral(":albumPath"), albumPath); d->mUpdateAlbumArtistInTracksQuery.bindValue(QStringLiteral(":artistName"), artistName); queryResult = d->mUpdateAlbumArtistInTracksQuery.exec(); if (!queryResult || !d->mUpdateAlbumArtistInTracksQuery.isActive()) { Q_EMIT databaseError(); qDebug() << "DatabaseInterface::updateAlbumArtist" << d->mUpdateAlbumArtistInTracksQuery.lastQuery(); qDebug() << "DatabaseInterface::updateAlbumArtist" << d->mUpdateAlbumArtistInTracksQuery.boundValues(); qDebug() << "DatabaseInterface::updateAlbumArtist" << d->mUpdateAlbumArtistInTracksQuery.lastError(); d->mUpdateAlbumArtistInTracksQuery.finish(); return; } d->mUpdateAlbumArtistInTracksQuery.finish(); } #include "moc_databaseinterface.cpp" diff --git a/src/databaseinterface.h b/src/databaseinterface.h index 2888c0ce..f9a49247 100644 --- a/src/databaseinterface.h +++ b/src/databaseinterface.h @@ -1,447 +1,447 @@ /* * Copyright 2016-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 . */ #ifndef DATABASEINTERFACE_H #define DATABASEINTERFACE_H #include "elisaLib_export.h" #include "datatype.h" #include "elisautils.h" #include "musicalbum.h" #include "musicaudiotrack.h" #include "musicaudiogenre.h" #include #include #include #include #include #include #include #include #include class DatabaseInterfacePrivate; class QMutex; class QSqlRecord; class QSqlQuery; class ELISALIB_EXPORT DatabaseInterface : public QObject { Q_OBJECT public: enum ColumnsRoles { TitleRole = Qt::UserRole + 1, SecondaryTextRole, ImageUrlRole, ShadowForImageRole, ChildModelRole, DurationRole, MilliSecondsDurationRole, ArtistRole, AllArtistsRole, HighestTrackRating, AlbumRole, AlbumArtistRole, TrackNumberRole, DiscNumberRole, RatingRole, GenreRole, LyricistRole, ComposerRole, CommentRole, YearRole, ChannelsRole, BitRateRole, SampleRateRole, ResourceRole, IdRole, DatabaseIdRole, IsSingleDiscAlbumRole, ContainerDataRole, IsPartialDataRole, AlbumIdRole, }; Q_ENUM(ColumnsRoles) private: using DataType = QMap; public: class TrackDataType : public DataType { public: using DataType::DataType; qulonglong databaseId() const { return operator[](key_type::DatabaseIdRole).toULongLong(); } QString title() const { return operator[](key_type::TitleRole).toString(); } QString artist() const { return operator[](key_type::ArtistRole).toString(); } QString album() const { return operator[](key_type::AlbumRole).toString(); } QString albumArtist() const { return operator[](key_type::AlbumArtistRole).toString(); } int trackNumber() const { return operator[](key_type::TrackNumberRole).toInt(); } int discNumber() const { return operator[](key_type::DiscNumberRole).toInt(); } int duration() const { return operator[](key_type::DurationRole).toInt(); } QUrl resourceURI() const { return operator[](key_type::ResourceRole).toUrl(); } }; using ListTrackDataType = QList; class AlbumDataType : public DataType { public: using DataType::DataType; qulonglong databaseId() const { return operator[](key_type::DatabaseIdRole).toULongLong(); } }; using ListAlbumDataType = QList; class ArtistDataType : public DataType { public: using DataType::DataType; qulonglong databaseId() const { return operator[](key_type::DatabaseIdRole).toULongLong(); } }; using ListArtistDataType = QList; class GenreDataType : public DataType { public: using DataType::DataType; qulonglong databaseId() const { return operator[](key_type::DatabaseIdRole).toULongLong(); } }; using ListGenreDataType = QList; enum PropertyType { DatabaseId, DisplayRole, SecondaryRole, }; Q_ENUM(PropertyType) enum AlbumDiscsCount { SingleDiscAlbum, MultipleDiscsAlbum, }; Q_ENUM(AlbumDiscsCount) explicit DatabaseInterface(QObject *parent = nullptr); ~DatabaseInterface() override; Q_INVOKABLE void init(const QString &dbName, const QString &databaseFileName = {}); MusicAlbum albumFromTitleAndArtist(const QString &title, const QString &artist); ListTrackDataType allTracksData(); ListAlbumDataType allAlbumsData(); ListTrackDataType albumData(qulonglong databaseId); ListArtistDataType allArtistsData(); ListGenreDataType allGenresData(); DataType oneData(ElisaUtils::PlayListEntryType aType, qulonglong databaseId); QList allTracks(); QList allTracksFromSource(const QString &musicSource); QList allAlbums(); QList allGenres(); - ListTrackDataType tracksFromAuthor(const QString &artistName); + ListTrackDataType tracksDataFromAuthor(const QString &artistName); TrackDataType trackDataFromDatabaseId(qulonglong id); MusicAudioTrack trackFromDatabaseId(qulonglong id); qulonglong trackIdFromTitleAlbumTrackDiscNumber(const QString &title, const QString &artist, const QString &album, int trackNumber, int discNumber); qulonglong trackIdFromFileName(const QUrl &fileName); void applicationAboutToQuit(); Q_SIGNALS: void artistsAdded(const ListArtistDataType &newArtists); void composersAdded(const ListArtistDataType &newComposers); void lyricistsAdded(const ListArtistDataType &newLyricists); void albumsAdded(const ListAlbumDataType &newAlbums); void tracksAdded(const ListTrackDataType &allTracks); void genresAdded(const ListGenreDataType &allGenres); void artistRemoved(qulonglong removedArtistId); void albumRemoved(qulonglong removedAlbumId); void trackRemoved(qulonglong id); void albumModified(const AlbumDataType &modifiedAlbum, qulonglong modifiedAlbumId); void trackModified(const TrackDataType &modifiedTrack); void sentAlbumData(const MusicAlbum albumData); void requestsInitDone(); void databaseError(); void restoredTracks(const QString &musicSource, QHash allFiles); public Q_SLOTS: void insertTracksList(const QList &tracks, const QHash &covers, const QString &musicSource); void removeTracksList(const QList &removedTracks); void modifyTracksList(const QList &modifiedTracks, const QHash &covers, const QString &musicSource); void removeAllTracksFromSource(const QString &sourceName); void getAlbumFromAlbumId(qulonglong id); void askRestoredTracks(const QString &musicSource); private: enum class TrackFileInsertType { NewTrackFileInsert, ModifiedTrackFileInsert, }; void initChangesTrackers(); void recordModifiedTrack(qulonglong trackId); void recordModifiedAlbum(qulonglong albumId); bool startTransaction() const; bool finishTransaction() const; bool rollBackTransaction() const; QList fetchTracks(qulonglong albumId); QList fetchTrackIds(qulonglong albumId); MusicAlbum internalAlbumFromId(qulonglong albumId); MusicAlbum internalAlbumFromTitleAndArtist(const QString &title, const QString &artist); qulonglong internalAlbumIdFromTitleAndArtist(const QString &title, const QString &artist); MusicAudioTrack internalTrackFromDatabaseId(qulonglong id); qulonglong internalTrackIdFromTitleAlbumTracDiscNumber(const QString &title, const QString &artist, const QString &album, int trackNumber, int discNumber); qulonglong getDuplicateTrackIdFromTitleAlbumTrackDiscNumber(const QString &title, const QString &album, const QString &albumArtist, const QString &trackPath, int trackNumber, int discNumber); qulonglong internalTrackIdFromFileName(const QUrl &fileName); ListTrackDataType internalTracksFromAuthor(const QString &artistName); QList internalAlbumIdsFromAuthor(const QString &artistName); void initDatabase(); void initRequest(); qulonglong insertAlbum(const QString &title, const QString &albumArtist, const QString &trackArtist, const QString &trackPath, const QUrl &albumArtURI); bool updateAlbumFromId(qulonglong albumId, const QUrl &albumArtUri, const MusicAudioTrack ¤tTrack, const QString &albumPath); qulonglong insertArtist(const QString &name); qulonglong internalArtistIdFromName(const QString &name); qulonglong insertGenre(const QString &name); MusicAudioGenre internalGenreFromId(qulonglong genreId); void removeTrackInDatabase(qulonglong trackId); void updateTrackInDatabase(const MusicAudioTrack &oneTrack, const QString &albumPath); void removeAlbumInDatabase(qulonglong albumId); void removeArtistInDatabase(qulonglong artistId); void reloadExistingDatabase(); qulonglong initialId(DataUtils::DataType aType); qulonglong genericInitialId(QSqlQuery &request); qulonglong insertMusicSource(const QString &name); void insertTrackOrigin(const QUrl &fileNameURI, const QDateTime &fileModifiedTime, qulonglong discoverId); void updateTrackOrigin(qulonglong trackId, const QUrl &fileName, const QDateTime &fileModifiedTime); int computeTrackPriority(qulonglong trackId, const QUrl &fileName); qulonglong internalInsertTrack(const MusicAudioTrack &oneModifiedTrack, const QHash &covers, qulonglong originTrackId, TrackFileInsertType insertType); MusicAudioTrack buildTrackFromDatabaseRecord(const QSqlRecord &trackRecord) const; TrackDataType buildTrackDataFromDatabaseRecord(const QSqlRecord &trackRecord) const; void internalRemoveTracksList(const QList &removedTracks); void internalRemoveTracksList(const QHash &removedTracks, qulonglong sourceId); void internalRemoveTracksWithoutMapping(); QUrl internalAlbumArtUriFromAlbumId(qulonglong albumId); bool isValidArtist(qulonglong albumId); qulonglong insertComposer(const QString &name); qulonglong insertLyricist(const QString &name); qulonglong internalSourceIdFromName(const QString &sourceName); QHash internalAllFileNameFromSource(qulonglong sourceId); bool internalGenericPartialData(QSqlQuery &query); ListArtistDataType internalAllArtistsPartialData(); ArtistDataType internalOneArtistPartialData(qulonglong databaseId); ListAlbumDataType internalAllAlbumsPartialData(); AlbumDataType internalOneAlbumPartialData(qulonglong databaseId); ListTrackDataType internalAllTracksPartialData(); TrackDataType internalOneTrackPartialData(qulonglong databaseId); ListGenreDataType internalAllGenresPartialData(); GenreDataType internalOneGenrePartialData(qulonglong databaseId); ListArtistDataType internalAllComposersPartialData(); ArtistDataType internalOneComposerPartialData(qulonglong databaseId); ListArtistDataType internalAllLyricistsPartialData(); ArtistDataType internalOneLyricistPartialData(qulonglong databaseId); bool prepareQuery(QSqlQuery &query, const QString &queryText) const; void updateAlbumArtist(qulonglong albumId, const QString &title, const QString &albumPath, const QString &artistName); std::unique_ptr d; }; Q_DECLARE_METATYPE(DatabaseInterface::TrackDataType) Q_DECLARE_METATYPE(DatabaseInterface::AlbumDataType) Q_DECLARE_METATYPE(DatabaseInterface::ArtistDataType) Q_DECLARE_METATYPE(DatabaseInterface::GenreDataType) Q_DECLARE_METATYPE(DatabaseInterface::ListTrackDataType) Q_DECLARE_METATYPE(DatabaseInterface::ListAlbumDataType) Q_DECLARE_METATYPE(DatabaseInterface::ListArtistDataType) Q_DECLARE_METATYPE(DatabaseInterface::ListGenreDataType) #endif // DATABASEINTERFACE_H diff --git a/src/elisaapplication.cpp b/src/elisaapplication.cpp index b16eae5d..2d0169f0 100644 --- a/src/elisaapplication.cpp +++ b/src/elisaapplication.cpp @@ -1,575 +1,579 @@ /* * Copyright 2017 Matthieu Gallien * Copyright (C) 2012 Aleix Pol Gonzalez * * 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 "elisaapplication.h" #include "musiclistenersmanager.h" #include "models/allalbumsproxymodel.h" #include "models/alltracksproxymodel.h" #include "models/allartistsproxymodel.h" #include "models/singleartistproxymodel.h" #include "models/singlealbumproxymodel.h" #if defined KF5KIO_FOUND && KF5KIO_FOUND #include "models/filebrowserproxymodel.h" #endif #include "mediaplaylist.h" #include "audiowrapper.h" #include "manageaudioplayer.h" #include "managemediaplayercontrol.h" #include "manageheaderbar.h" #include "elisa_settings.h" #include #if defined KF5ConfigWidgets_FOUND && KF5ConfigWidgets_FOUND #include #endif #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND #include #include #include #include #include #endif #if defined KF5KCMUtils_FOUND && KF5KCMUtils_FOUND #include #endif #include #include #include #include #include #include #include #include #include #include #include #include class ElisaApplicationPrivate { public: explicit ElisaApplicationPrivate(QObject *parent) #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND : mCollection(parent) #endif { Q_UNUSED(parent) auto configurationFileName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); configurationFileName += QStringLiteral("/elisarc"); Elisa::ElisaConfiguration::instance(configurationFileName); Elisa::ElisaConfiguration::self()->load(); Elisa::ElisaConfiguration::self()->save(); } #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND KActionCollection mCollection; #endif ElisaUtils::EntryDataList mArguments; std::unique_ptr mMusicManager; std::unique_ptr mAllAlbumsProxyModel; std::unique_ptr mAllArtistsProxyModel; std::unique_ptr mAllTracksProxyModel; std::unique_ptr mAllGenresProxyModel; std::unique_ptr mAllComposersProxyModel; std::unique_ptr mAllLyricistsProxyModel; std::unique_ptr mSingleArtistProxyModel; std::unique_ptr mSingleAlbumProxyModel; #if defined KF5KIO_FOUND && KF5KIO_FOUND std::unique_ptr mFileBrowserProxyModel; #endif std::unique_ptr mMediaPlayList; std::unique_ptr mAudioWrapper; std::unique_ptr mAudioControl; std::unique_ptr mPlayerControl; std::unique_ptr mManageHeaderBar; }; ElisaApplication::ElisaApplication(QObject *parent) : QObject(parent), d(std::make_unique(this)) { } ElisaApplication::~ElisaApplication() = default; void ElisaApplication::setupActions(const QString &actionName) { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND if (actionName == QStringLiteral("file_quit")) { auto quitAction = KStandardAction::quit(QCoreApplication::instance(), &QCoreApplication::quit, &d->mCollection); d->mCollection.addAction(actionName, quitAction); } if (actionName == QStringLiteral("help_contents") && KAuthorized::authorizeAction(actionName)) { auto handBookAction = KStandardAction::helpContents(this, &ElisaApplication::appHelpActivated, &d->mCollection); d->mCollection.addAction(handBookAction->objectName(), handBookAction); } if (actionName == QStringLiteral("help_report_bug") && KAuthorized::authorizeAction(actionName) && !KAboutData::applicationData().bugAddress().isEmpty()) { auto reportBugAction = KStandardAction::reportBug(this, &ElisaApplication::reportBug, &d->mCollection); d->mCollection.addAction(reportBugAction->objectName(), reportBugAction); } if (actionName == QStringLiteral("help_about_app") && KAuthorized::authorizeAction(actionName)) { auto aboutAppAction = KStandardAction::aboutApp(this, &ElisaApplication::aboutApplication, this); d->mCollection.addAction(aboutAppAction->objectName(), aboutAppAction); } if (actionName == QStringLiteral("options_configure") && KAuthorized::authorizeAction(actionName)) { auto preferencesAction = KStandardAction::preferences(this, &ElisaApplication::configureElisa, this); d->mCollection.addAction(preferencesAction->objectName(), preferencesAction); } if (actionName == QStringLiteral("options_configure_keybinding") && KAuthorized::authorizeAction(actionName)) { auto keyBindingsAction = KStandardAction::keyBindings(this, &ElisaApplication::configureShortcuts, this); d->mCollection.addAction(keyBindingsAction->objectName(), keyBindingsAction); } if (actionName == QStringLiteral("go_back") && KAuthorized::authorizeAction(actionName)) { auto goBackAction = KStandardAction::back(this, &ElisaApplication::goBack, this); d->mCollection.addAction(goBackAction->objectName(), goBackAction); } if (actionName == QStringLiteral("toggle_playlist") && KAuthorized::authorizeAction(actionName)) { auto togglePlaylistAction = d->mCollection.addAction(actionName, this, &ElisaApplication::togglePlaylist); togglePlaylistAction->setShortcut(QKeySequence(Qt::Key_F9)); togglePlaylistAction->setText(QStringLiteral("Toggle Playlist")); } if (actionName == QStringLiteral("edit_find") && KAuthorized::authorizeAction(actionName)) { auto findAction = KStandardAction::find(this, &ElisaApplication::find, this); d->mCollection.addAction(findAction->objectName(), findAction); } d->mCollection.readSettings(); #endif } void ElisaApplication::setArguments(const ElisaUtils::EntryDataList &newArguments) { if (d->mArguments == newArguments) { return; } d->mArguments = checkFileListAndMakeAbsolute(newArguments, QDir::currentPath()); Q_EMIT argumentsChanged(); if (!d->mArguments.isEmpty()) { Q_EMIT enqueue(d->mArguments, ElisaUtils::FileName, ElisaUtils::PlayListEnqueueMode::AppendPlayList, ElisaUtils::PlayListEnqueueTriggerPlay::TriggerPlay); } } void ElisaApplication::activateActionRequested(const QString &actionName, const QVariant ¶meter) { Q_UNUSED(actionName) Q_UNUSED(parameter) } void ElisaApplication::activateRequested(const QStringList &arguments, const QString &workingDirectory) { if (arguments.size() > 1) { auto realArguments = ElisaUtils::EntryDataList{}; bool isFirst = true; for (const auto &oneArgument : arguments) { if (isFirst) { isFirst = false; continue; } realArguments.push_back({0, oneArgument}); } Q_EMIT enqueue(checkFileListAndMakeAbsolute(realArguments, workingDirectory), ElisaUtils::FileName, ElisaUtils::PlayListEnqueueMode::AppendPlayList, ElisaUtils::PlayListEnqueueTriggerPlay::TriggerPlay); } } void ElisaApplication::openRequested(const QList &uris) { Q_UNUSED(uris) } void ElisaApplication::appHelpActivated() { QDesktopServices::openUrl(QUrl(QStringLiteral("help:/"))); } void ElisaApplication::aboutApplication() { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND static QPointer dialog; if (!dialog) { dialog = new KAboutApplicationDialog(KAboutData::applicationData(), nullptr); dialog->setAttribute(Qt::WA_DeleteOnClose); } dialog->show(); #endif } void ElisaApplication::reportBug() { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND static QPointer dialog; if (!dialog) { dialog = new KBugReport(KAboutData::applicationData(), nullptr); dialog->setAttribute(Qt::WA_DeleteOnClose); } dialog->show(); #endif } void ElisaApplication::configureShortcuts() { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, nullptr); dlg.setModal(true); dlg.addCollection(&d->mCollection); dlg.configure(); #endif } void ElisaApplication::configureElisa() { #if defined KF5KCMUtils_FOUND && KF5KCMUtils_FOUND KCMultiDialog configurationDialog; configurationDialog.addModule(QStringLiteral("kcm_elisa_local_file")); configurationDialog.setModal(true); configurationDialog.exec(); #endif } void ElisaApplication::goBack() {} void ElisaApplication::find() {} void ElisaApplication::togglePlaylist() {} ElisaUtils::EntryDataList ElisaApplication::checkFileListAndMakeAbsolute(const ElisaUtils::EntryDataList &filesList, const QString &workingDirectory) const { auto filesToOpen = ElisaUtils::EntryDataList{}; for (const auto &oneFile : filesList) { auto newFile = QFileInfo(std::get<1>(oneFile)); if (newFile.isRelative()) { newFile = QFileInfo(workingDirectory + QStringLiteral("/") + std::get<1>(oneFile)); } if (newFile.exists()) { filesToOpen.push_back({0, newFile.canonicalFilePath()}); } } return filesToOpen; } void ElisaApplication::initialize() { initializeModels(); initializePlayer(); Q_EMIT initializationDone(); } void ElisaApplication::initializeModels() { d->mMusicManager = std::make_unique(); Q_EMIT musicManagerChanged(); d->mAllAlbumsProxyModel = std::make_unique(); Q_EMIT allAlbumsProxyModelChanged(); d->mAllArtistsProxyModel = std::make_unique(); Q_EMIT allArtistsProxyModelChanged(); d->mAllGenresProxyModel = std::make_unique(); Q_EMIT allGenresProxyModelChanged(); d->mAllComposersProxyModel = std::make_unique(); Q_EMIT allComposersProxyModelChanged(); d->mAllLyricistsProxyModel = std::make_unique(); Q_EMIT allLyricistsProxyModelChanged(); d->mAllTracksProxyModel = std::make_unique(); Q_EMIT allTracksProxyModelChanged(); d->mSingleArtistProxyModel = std::make_unique(); Q_EMIT singleArtistProxyModelChanged(); d->mSingleAlbumProxyModel = std::make_unique(); Q_EMIT singleAlbumProxyModelChanged(); #if defined KF5KIO_FOUND && KF5KIO_FOUND d->mFileBrowserProxyModel = std::make_unique(); Q_EMIT fileBrowserProxyModelChanged(); #endif d->mMediaPlayList = std::make_unique(); Q_EMIT mediaPlayListChanged(); d->mMusicManager->setElisaApplication(this); d->mMediaPlayList->setMusicListenersManager(d->mMusicManager.get()); QObject::connect(this, &ElisaApplication::enqueue, d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); d->mAllAlbumsProxyModel->setSourceModel(d->mMusicManager->allAlbumsModel()); d->mAllArtistsProxyModel->setSourceModel(d->mMusicManager->allArtistsModel()); d->mAllGenresProxyModel->setSourceModel(d->mMusicManager->allGenresModel()); d->mAllComposersProxyModel->setSourceModel(d->mMusicManager->allComposersModel()); d->mAllLyricistsProxyModel->setSourceModel(d->mMusicManager->allLyricistsModel()); d->mAllTracksProxyModel->setSourceModel(d->mMusicManager->allTracksModel()); d->mSingleArtistProxyModel->setSourceModel(d->mMusicManager->allAlbumsModel()); d->mSingleAlbumProxyModel->setSourceModel(d->mMusicManager->albumModel()); QObject::connect(d->mAllAlbumsProxyModel.get(), &AllAlbumsProxyModel::albumToEnqueue, - d->mMediaPlayList.get(), static_cast &, + d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); QObject::connect(d->mAllArtistsProxyModel.get(), &AllArtistsProxyModel::artistToEnqueue, d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); QObject::connect(d->mAllTracksProxyModel.get(), &AllTracksProxyModel::trackToEnqueue, - d->mMediaPlayList.get(), static_cast &, + d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); QObject::connect(d->mSingleArtistProxyModel.get(), &SingleArtistProxyModel::albumToEnqueue, - d->mMediaPlayList.get(), static_cast &, + d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); QObject::connect(d->mSingleAlbumProxyModel.get(), &SingleAlbumProxyModel::trackToEnqueue, - d->mMediaPlayList.get(), static_cast &, + d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); #if defined KF5KIO_FOUND && KF5KIO_FOUND QObject::connect(d->mFileBrowserProxyModel.get(), &FileBrowserProxyModel::loadPlayListFromUrl, d->mMediaPlayList.get(), &MediaPlayList::loadPlaylist); QObject::connect(d->mFileBrowserProxyModel.get(), &FileBrowserProxyModel::filesToEnqueue, d->mMediaPlayList.get(), static_cast(&MediaPlayList::enqueue)); #endif } void ElisaApplication::initializePlayer() { d->mAudioWrapper = std::make_unique(); Q_EMIT audioPlayerChanged(); d->mAudioControl = std::make_unique(); Q_EMIT audioControlChanged(); d->mPlayerControl = std::make_unique(); Q_EMIT playerControlChanged(); d->mManageHeaderBar = std::make_unique(); Q_EMIT manageHeaderBarChanged(); d->mAudioControl->setAlbumNameRole(MediaPlayList::AlbumRole); d->mAudioControl->setArtistNameRole(MediaPlayList::ArtistRole); d->mAudioControl->setTitleRole(MediaPlayList::TitleRole); d->mAudioControl->setUrlRole(MediaPlayList::ResourceRole); d->mAudioControl->setIsPlayingRole(MediaPlayList::IsPlayingRole); d->mAudioControl->setPlayListModel(d->mMediaPlayList.get()); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerPlay, d->mAudioWrapper.get(), &AudioWrapper::play); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerPause, d->mAudioWrapper.get(), &AudioWrapper::pause); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerStop, d->mAudioWrapper.get(), &AudioWrapper::stop); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::seek, d->mAudioWrapper.get(), &AudioWrapper::seek); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::skipNextTrack, d->mMediaPlayList.get(), &MediaPlayList::skipNextTrack); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::sourceInError, d->mMediaPlayList.get(), &MediaPlayList::trackInError); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::sourceInError, d->mMusicManager.get(), &MusicListenersManager::playBackError); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerSourceChanged, d->mAudioWrapper.get(), &AudioWrapper::setSource); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::ensurePlay, d->mAudioControl.get(), &ManageAudioPlayer::ensurePlay); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::playListFinished, d->mAudioControl.get(), &ManageAudioPlayer::playListFinished); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mAudioControl.get(), &ManageAudioPlayer::setCurrentTrack); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::playbackStateChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerPlaybackState); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::statusChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerStatus); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::errorChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerError); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::durationChanged, d->mAudioControl.get(), &ManageAudioPlayer::setAudioDuration); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::seekableChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerIsSeekable); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::positionChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerPosition); d->mPlayerControl->setPlayListModel(d->mMediaPlayList.get()); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mPlayerControl.get(), &ManageMediaPlayerControl::setCurrentTrack); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::playing, d->mPlayerControl.get(), &ManageMediaPlayerControl::playerPlaying); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::paused, d->mPlayerControl.get(), &ManageMediaPlayerControl::playerPaused); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::stopped, d->mPlayerControl.get(), &ManageMediaPlayerControl::playerStopped); d->mManageHeaderBar->setTitleRole(MediaPlayList::TitleRole); d->mManageHeaderBar->setAlbumRole(MediaPlayList::AlbumRole); d->mManageHeaderBar->setArtistRole(MediaPlayList::ArtistRole); d->mManageHeaderBar->setImageRole(MediaPlayList::ImageUrlRole); d->mManageHeaderBar->setAlbumIdRole(MediaPlayList::AlbumIdRole); d->mManageHeaderBar->setIsValidRole(MediaPlayList::IsValidRole); d->mManageHeaderBar->setPlayListModel(d->mMediaPlayList.get()); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mManageHeaderBar.get(), &ManageHeaderBar::setCurrentTrack); if (!d->mArguments.isEmpty()) { Q_EMIT enqueue(d->mArguments, ElisaUtils::FileName, ElisaUtils::PlayListEnqueueMode::AppendPlayList, ElisaUtils::PlayListEnqueueTriggerPlay::TriggerPlay); } } QAction * ElisaApplication::action(const QString& name) { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND auto resultAction = d->mCollection.action(name); if (!resultAction) { setupActions(name); resultAction = d->mCollection.action(name); } return resultAction; #else Q_UNUSED(name); return new QAction(); #endif } QString ElisaApplication::iconName(const QIcon& icon) { return icon.name(); } const ElisaUtils::EntryDataList &ElisaApplication::arguments() const { return d->mArguments; } MusicListenersManager *ElisaApplication::musicManager() const { return d->mMusicManager.get(); } QSortFilterProxyModel *ElisaApplication::allAlbumsProxyModel() const { return d->mAllAlbumsProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::allArtistsProxyModel() const { return d->mAllArtistsProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::allGenresProxyModel() const { return d->mAllGenresProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::allComposersProxyModel() const { return d->mAllComposersProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::allLyricistsProxyModel() const { return d->mAllLyricistsProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::allTracksProxyModel() const { return d->mAllTracksProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::singleArtistProxyModel() const { return d->mSingleArtistProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::singleAlbumProxyModel() const { return d->mSingleAlbumProxyModel.get(); } QSortFilterProxyModel *ElisaApplication::fileBrowserProxyModel() const { #if defined KF5KIO_FOUND && KF5KIO_FOUND return d->mFileBrowserProxyModel.get(); #else return nullptr; #endif } MediaPlayList *ElisaApplication::mediaPlayList() const { return d->mMediaPlayList.get(); } AudioWrapper *ElisaApplication::audioPlayer() const { return d->mAudioWrapper.get(); } ManageAudioPlayer *ElisaApplication::audioControl() const { return d->mAudioControl.get(); } ManageMediaPlayerControl *ElisaApplication::playerControl() const { return d->mPlayerControl.get(); } ManageHeaderBar *ElisaApplication::manageHeaderBar() const { return d->mManageHeaderBar.get(); } #include "moc_elisaapplication.cpp" diff --git a/src/models/allalbumsproxymodel.cpp b/src/models/allalbumsproxymodel.cpp index b070e670..db557881 100644 --- a/src/models/allalbumsproxymodel.cpp +++ b/src/models/allalbumsproxymodel.cpp @@ -1,132 +1,124 @@ /* * Copyright 2016-2017 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 "allalbumsproxymodel.h" #include "genericdatamodel.h" #include "musicalbum.h" #include "databaseinterface.h" #include #include AllAlbumsProxyModel::AllAlbumsProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(DatabaseInterface::ColumnsRoles::TitleRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } -AllAlbumsProxyModel::~AllAlbumsProxyModel() -{ -} +AllAlbumsProxyModel::~AllAlbumsProxyModel() = default; bool AllAlbumsProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); const auto &genreValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::GenreRole); if (!genreFilterText().isNull() && !genreValue.isValid()) { continue; } if (!genreFilterText().isNull() && !genreValue.canConvert()) { continue; } if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { continue; } const auto &titleValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::TitleRole).toString(); const auto &artistValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::ArtistRole).toString(); const auto &allArtistsValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::AllArtistsRole).toStringList(); const auto maximumRatingValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::HighestTrackRating).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } if (mFilterExpression.match(artistValue).hasMatch()) { result = true; continue; } for (const auto &oneArtist : allArtistsValue) { if (mFilterExpression.match(oneArtist).hasMatch()) { result = true; break; } } if (result) { continue; } if (!result) { break; } } return result; } -void AllAlbumsProxyModel::enqueueToPlayList() +void AllAlbumsProxyModel::genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay) { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); - auto allAlbums = QList(); + auto allAlbums = ElisaUtils::EntryDataList{}; allAlbums.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); - allAlbums.push_back(data(currentIndex, DatabaseInterface::ColumnsRoles::ContainerDataRole). value()); + allAlbums.push_back({data(currentIndex, DatabaseInterface::ColumnsRoles::DatabaseIdRole).toULongLong(), + data(currentIndex, DatabaseInterface::ColumnsRoles::TitleRole).toString()}); } - Q_EMIT albumToEnqueue(allAlbums, - ElisaUtils::AppendPlayList, - ElisaUtils::DoNotTriggerPlay); + Q_EMIT albumToEnqueue(allAlbums, ElisaUtils::Album, enqueueMode, triggerPlay); }); } +void AllAlbumsProxyModel::enqueueToPlayList() +{ + genericEnqueueToPlayList(ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); +} + void AllAlbumsProxyModel::replaceAndPlayOfPlayList() { - QtConcurrent::run(&mThreadPool, [=] () { - QReadLocker locker(&mDataLock); - auto allAlbums = QList(); - allAlbums.reserve(rowCount()); - for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { - auto currentIndex = index(rowIndex, 0); - allAlbums.push_back(data(currentIndex, DatabaseInterface::ColumnsRoles::ContainerDataRole). value()); - } - Q_EMIT albumToEnqueue(allAlbums, - ElisaUtils::ReplacePlayList, - ElisaUtils::TriggerPlay); - }); + genericEnqueueToPlayList(ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); } #include "moc_allalbumsproxymodel.cpp" diff --git a/src/models/allalbumsproxymodel.h b/src/models/allalbumsproxymodel.h index a13b26e3..e1c5ed79 100644 --- a/src/models/allalbumsproxymodel.h +++ b/src/models/allalbumsproxymodel.h @@ -1,58 +1,64 @@ /* * Copyright 2016-2018 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 . */ #ifndef ALLALBUMSPROXYMODEL_H #define ALLALBUMSPROXYMODEL_H #include "elisaLib_export.h" #include "abstractmediaproxymodel.h" #include "elisautils.h" class MusicAlbum; class ELISALIB_EXPORT AllAlbumsProxyModel : public AbstractMediaProxyModel { Q_OBJECT public: explicit AllAlbumsProxyModel(QObject *parent = nullptr); ~AllAlbumsProxyModel() override; Q_SIGNALS: - void albumToEnqueue(QList newAlbums, + void albumToEnqueue(const ElisaUtils::EntryDataList &newEntries, + ElisaUtils::PlayListEntryType databaseIdType, ElisaUtils::PlayListEnqueueMode enqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); public Q_SLOTS: void enqueueToPlayList(); void replaceAndPlayOfPlayList(); protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +private: + + void genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); + }; #endif // ALLALBUMSPROXYMODEL_H diff --git a/src/models/alltracksproxymodel.cpp b/src/models/alltracksproxymodel.cpp index e23d85fb..f583593f 100644 --- a/src/models/alltracksproxymodel.cpp +++ b/src/models/alltracksproxymodel.cpp @@ -1,122 +1,114 @@ /* * Copyright 2017 Alexander Stippich * * 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 "alltracksproxymodel.h" #include "genericdatamodel.h" #include "databaseinterface.h" #include #include AllTracksProxyModel::AllTracksProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(Qt::DisplayRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } -AllTracksProxyModel::~AllTracksProxyModel() -{ -} +AllTracksProxyModel::~AllTracksProxyModel() = default; bool AllTracksProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); const auto &genreValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::GenreRole); if (!genreFilterText().isNull() && !genreValue.isValid()) { continue; } if (!genreFilterText().isNull() && !genreValue.canConvert()) { continue; } if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { continue; } const auto &titleValue = sourceModel()->data(currentIndex, Qt::DisplayRole).toString(); const auto &artistValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::ArtistRole).toString(); const auto maximumRatingValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::RatingRole).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } if (mFilterExpression.match(artistValue).hasMatch()) { result = true; continue; } if (result) { continue; } if (!result) { break; } } return result; } -void AllTracksProxyModel::enqueueToPlayList() +void AllTracksProxyModel::genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay) { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); - auto allTracks = QList(); + auto allTracks = ElisaUtils::EntryDataList(); allTracks.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); - allTracks.push_back(data(currentIndex, DatabaseInterface::ColumnsRoles::ContainerDataRole).value()); + allTracks.push_back({data(currentIndex, DatabaseInterface::ColumnsRoles::DatabaseIdRole).toULongLong(), + data(currentIndex, DatabaseInterface::ColumnsRoles::TitleRole).toString()}); } - Q_EMIT trackToEnqueue(allTracks, - ElisaUtils::AppendPlayList, - ElisaUtils::DoNotTriggerPlay); + Q_EMIT trackToEnqueue(allTracks, ElisaUtils::Track, enqueueMode, triggerPlay); }); } +void AllTracksProxyModel::enqueueToPlayList() +{ + genericEnqueueToPlayList(ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); +} + void AllTracksProxyModel::replaceAndPlayOfPlayList() { - QtConcurrent::run(&mThreadPool, [=] () { - QReadLocker locker(&mDataLock); - auto allTracks = QList(); - allTracks.reserve(rowCount()); - for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { - auto currentIndex = index(rowIndex, 0); - allTracks.push_back(data(currentIndex, DatabaseInterface::ColumnsRoles::ContainerDataRole).value()); - } - Q_EMIT trackToEnqueue(allTracks, - ElisaUtils::ReplacePlayList, - ElisaUtils::TriggerPlay); - }); + genericEnqueueToPlayList(ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); } #include "moc_alltracksproxymodel.cpp" diff --git a/src/models/alltracksproxymodel.h b/src/models/alltracksproxymodel.h index 13378c21..e6cf9680 100644 --- a/src/models/alltracksproxymodel.h +++ b/src/models/alltracksproxymodel.h @@ -1,56 +1,62 @@ /* * Copyright 2017 Alexander Stippich * Copyright 2018 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 . */ #ifndef ALLTRACKSPROXYMODEL_H #define ALLTRACKSPROXYMODEL_H #include "elisaLib_export.h" #include "abstractmediaproxymodel.h" #include "musicaudiotrack.h" #include "elisautils.h" class ELISALIB_EXPORT AllTracksProxyModel : public AbstractMediaProxyModel { Q_OBJECT public: explicit AllTracksProxyModel(QObject *parent = nullptr); ~AllTracksProxyModel() override; Q_SIGNALS: - void trackToEnqueue(QList newTracks, + void trackToEnqueue(const ElisaUtils::EntryDataList &newEntries, + ElisaUtils::PlayListEntryType databaseIdType, ElisaUtils::PlayListEnqueueMode enqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); public Q_SLOTS: void enqueueToPlayList(); void replaceAndPlayOfPlayList(); protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +private: + + void genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); + }; #endif // ALLTRACKSPROXYMODEL_H diff --git a/src/models/singlealbumproxymodel.cpp b/src/models/singlealbumproxymodel.cpp index 1cff9615..2e01dede 100644 --- a/src/models/singlealbumproxymodel.cpp +++ b/src/models/singlealbumproxymodel.cpp @@ -1,118 +1,111 @@ /* * Copyright 2017 Alexander Stippich * * 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 "singlealbumproxymodel.h" #include "albummodel.h" #include "databaseinterface.h" #include #include SingleAlbumProxyModel::SingleAlbumProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { } SingleAlbumProxyModel::~SingleAlbumProxyModel() = default; bool SingleAlbumProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); const auto &genreValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::GenreRole); if (!genreFilterText().isNull() && !genreValue.isValid()) { continue; } if (!genreFilterText().isNull() && !genreValue.canConvert()) { continue; } if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { continue; } const auto &titleValue = sourceModel()->data(currentIndex, AlbumModel::TitleRole).toString(); const auto maximumRatingValue = sourceModel()->data(currentIndex, AlbumModel::RatingRole).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } if (result) { continue; } if (!result) { break; } } return result; } -void SingleAlbumProxyModel::enqueueToPlayList() +void SingleAlbumProxyModel::genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay) { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); - auto allTracks = QList(); + auto allTracks = ElisaUtils::EntryDataList{}; allTracks.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); - allTracks.push_back(data(currentIndex, AlbumModel::ContainerDataRole).value()); + allTracks.push_back({data(currentIndex, AlbumModel::DatabaseIdRole).toULongLong(), + data(currentIndex, AlbumModel::TitleRole).toString()}); } - Q_EMIT trackToEnqueue(allTracks, - ElisaUtils::AppendPlayList, - ElisaUtils::DoNotTriggerPlay); + Q_EMIT trackToEnqueue(allTracks, ElisaUtils::Track, enqueueMode, triggerPlay); }); } +void SingleAlbumProxyModel::enqueueToPlayList() +{ + genericEnqueueToPlayList(ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); +} + void SingleAlbumProxyModel::replaceAndPlayOfPlayList() { - QtConcurrent::run(&mThreadPool, [=] () { - QReadLocker locker(&mDataLock); - auto allTracks = QList(); - allTracks.reserve(rowCount()); - for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { - auto currentIndex = index(rowIndex, 0); - allTracks.push_back(data(currentIndex, AlbumModel::ContainerDataRole).value()); - } - Q_EMIT trackToEnqueue(allTracks, - ElisaUtils::ReplacePlayList, - ElisaUtils::TriggerPlay); - }); + genericEnqueueToPlayList(ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); } void SingleAlbumProxyModel::loadAlbumData(qulonglong databaseId) { auto albumSourceModel = qobject_cast(this->sourceModel()); if(albumSourceModel) { albumSourceModel->loadAlbumData(databaseId); } } #include "moc_singlealbumproxymodel.cpp" diff --git a/src/models/singlealbumproxymodel.h b/src/models/singlealbumproxymodel.h index eec076a8..8868d1b3 100644 --- a/src/models/singlealbumproxymodel.h +++ b/src/models/singlealbumproxymodel.h @@ -1,59 +1,65 @@ /* * Copyright 2017 Alexander Stippich * Copyright 2018 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 . */ #ifndef SINGLEALBUMPROXYMODEL_H #define SINGLEALBUMPROXYMODEL_H #include "elisaLib_export.h" #include "abstractmediaproxymodel.h" #include "musicaudiotrack.h" #include "elisautils.h" #include "albummodel.h" class ELISALIB_EXPORT SingleAlbumProxyModel : public AbstractMediaProxyModel { Q_OBJECT public: explicit SingleAlbumProxyModel(QObject *parent = nullptr); ~SingleAlbumProxyModel() override; Q_SIGNALS: - void trackToEnqueue(QList newTracks, - ElisaUtils::PlayListEnqueueMode enqueueMode, - ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); + void trackToEnqueue(const ElisaUtils::EntryDataList&, + ElisaUtils::PlayListEntryType, + ElisaUtils::PlayListEnqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay); public Q_SLOTS: void enqueueToPlayList(); void replaceAndPlayOfPlayList(); void loadAlbumData(qulonglong databaseId); protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +private: + + void genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); + }; #endif // SINGLEALBUMPROXYMODEL_H diff --git a/src/models/singleartistproxymodel.cpp b/src/models/singleartistproxymodel.cpp index 780d1749..bbf52c1e 100644 --- a/src/models/singleartistproxymodel.cpp +++ b/src/models/singleartistproxymodel.cpp @@ -1,142 +1,135 @@ /* * Copyright 2016-2017 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 "singleartistproxymodel.h" #include "genericdatamodel.h" #include "musicalbum.h" #include "databaseinterface.h" #include #include SingleArtistProxyModel::SingleArtistProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(DatabaseInterface::ColumnsRoles::TitleRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } SingleArtistProxyModel::~SingleArtistProxyModel() = default; QString SingleArtistProxyModel::artistFilter() const { return mArtistFilter; } void SingleArtistProxyModel::setArtistFilterText(const QString &filterText) { if (mArtistFilter == filterText) return; mArtistFilter = filterText; mArtistExpression.setPattern(QStringLiteral(".*") + mArtistFilter + QStringLiteral(".*")); mArtistExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption); mArtistExpression.optimize(); invalidate(); Q_EMIT artistFilterTextChanged(mArtistFilter); } bool SingleArtistProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); const auto &genreValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::GenreRole); if (!genreFilterText().isNull() && !genreValue.isValid()) { continue; } if (!genreFilterText().isNull() && !genreValue.canConvert()) { continue; } if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { continue; } const auto &artistValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::TitleRole).toString(); const auto &allArtistsValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::AllArtistsRole).toStringList().join(QLatin1String(", ")); const auto maximumRatingValue = sourceModel()->data(currentIndex, DatabaseInterface::ColumnsRoles::HighestTrackRating).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mArtistExpression.match(artistValue).hasMatch()) { if (mFilterExpression.match(allArtistsValue).hasMatch()) { result = true; continue; } } if (result) { continue; } if (!result) { break; } } return result; } -void SingleArtistProxyModel::enqueueToPlayList() +void SingleArtistProxyModel::genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay) { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); - auto allAlbums = QList(); + auto allAlbums = ElisaUtils::EntryDataList{}; allAlbums.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); - allAlbums.push_back(data(currentIndex, DatabaseInterface::ColumnsRoles::ContainerDataRole). value()); + allAlbums.push_back({data(currentIndex, DatabaseInterface::ColumnsRoles::DatabaseIdRole).toULongLong(), + data(currentIndex, DatabaseInterface::ColumnsRoles::TitleRole).toString()}); } - Q_EMIT albumToEnqueue(allAlbums, - ElisaUtils::AppendPlayList, - ElisaUtils::DoNotTriggerPlay); + Q_EMIT albumToEnqueue(allAlbums, ElisaUtils::Album, enqueueMode, triggerPlay); }); } +void SingleArtistProxyModel::enqueueToPlayList() +{ + genericEnqueueToPlayList(ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); +} + void SingleArtistProxyModel::replaceAndPlayOfPlayList() { - QtConcurrent::run(&mThreadPool, [=] () { - QReadLocker locker(&mDataLock); - auto allAlbums = QList(); - allAlbums.reserve(rowCount()); - for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { - auto currentIndex = index(rowIndex, 0); - allAlbums.push_back(data(currentIndex, DatabaseInterface::ColumnsRoles::ContainerDataRole). value()); - } - Q_EMIT albumToEnqueue(allAlbums, - ElisaUtils::ReplacePlayList, - ElisaUtils::TriggerPlay); - }); + genericEnqueueToPlayList(ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); } #include "moc_singleartistproxymodel.cpp" diff --git a/src/models/singleartistproxymodel.h b/src/models/singleartistproxymodel.h index b610de86..1c5def28 100644 --- a/src/models/singleartistproxymodel.h +++ b/src/models/singleartistproxymodel.h @@ -1,74 +1,80 @@ /* * Copyright 2016-2018 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 . */ #ifndef SINGLEARTISTPROXYMODEL_H #define SINGLEARTISTPROXYMODEL_H #include "elisaLib_export.h" #include "abstractmediaproxymodel.h" #include "elisautils.h" class MusicAlbum; class ELISALIB_EXPORT SingleArtistProxyModel : public AbstractMediaProxyModel { Q_OBJECT Q_PROPERTY(QString artistFilter READ artistFilter WRITE setArtistFilterText NOTIFY artistFilterTextChanged) public: explicit SingleArtistProxyModel(QObject *parent = nullptr); ~SingleArtistProxyModel() override; QString artistFilter() const; Q_SIGNALS: - void albumToEnqueue(QList newAlbums, - ElisaUtils::PlayListEnqueueMode enqueueMode, - ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); + void albumToEnqueue(const ElisaUtils::EntryDataList&, + ElisaUtils::PlayListEntryType, + ElisaUtils::PlayListEnqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay); public Q_SLOTS: void enqueueToPlayList(); void replaceAndPlayOfPlayList(); void setArtistFilterText(const QString &filterText); Q_SIGNALS: void artistFilterTextChanged(const QString &filterText); protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +private: + QString mArtistFilter; QRegularExpression mArtistExpression; + void genericEnqueueToPlayList(ElisaUtils::PlayListEnqueueMode enqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); + }; #endif // SINGLEARTISTPROXYMODEL_H diff --git a/src/mpris2/mediaplayer2player.cpp b/src/mpris2/mediaplayer2player.cpp index b65c196c..6a8e8570 100644 --- a/src/mpris2/mediaplayer2player.cpp +++ b/src/mpris2/mediaplayer2player.cpp @@ -1,442 +1,442 @@ /*************************************************************************** * Copyright 2014 Sujith Haridasan * * Copyright 2014 Ashish Madeti * * Copyright 2016 Matthieu Gallien * * * * This program 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. * * * * 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "mediaplayer2player.h" #include "mpris2.h" #include "mediaplaylist.h" #include "manageaudioplayer.h" #include "managemediaplayercontrol.h" #include "manageheaderbar.h" #include "audiowrapper.h" #include #include #include #include #include #include static const double MAX_RATE = 1.0; static const double MIN_RATE = 1.0; MediaPlayer2Player::MediaPlayer2Player(MediaPlayList *playListControler, ManageAudioPlayer *manageAudioPlayer, ManageMediaPlayerControl *manageMediaPlayerControl, ManageHeaderBar *manageHeaderBar, AudioWrapper *audioPlayer, QObject* parent) : QDBusAbstractAdaptor(parent), m_playListControler(playListControler), m_manageAudioPlayer(manageAudioPlayer), m_manageMediaPlayerControl(manageMediaPlayerControl), m_manageHeaderBar(manageHeaderBar), m_audioPlayer(audioPlayer), mProgressIndicatorSignal(QDBusMessage::createSignal(QStringLiteral("/org/kde/elisa"), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update"))) { if (!m_playListControler) { return; } connect(m_manageAudioPlayer, &ManageAudioPlayer::playerSourceChanged, this, &MediaPlayer2Player::playerSourceChanged, Qt::QueuedConnection); connect(m_manageMediaPlayerControl, &ManageMediaPlayerControl::playControlEnabledChanged, this, &MediaPlayer2Player::playControlEnabledChanged); connect(m_manageMediaPlayerControl, &ManageMediaPlayerControl::skipBackwardControlEnabledChanged, this, &MediaPlayer2Player::skipBackwardControlEnabledChanged); connect(m_manageMediaPlayerControl, &ManageMediaPlayerControl::skipForwardControlEnabledChanged, this, &MediaPlayer2Player::skipForwardControlEnabledChanged); connect(m_manageAudioPlayer, &ManageAudioPlayer::playerPlaybackStateChanged, this, &MediaPlayer2Player::playerPlaybackStateChanged); connect(m_manageAudioPlayer, &ManageAudioPlayer::playerIsSeekableChanged, this, &MediaPlayer2Player::playerIsSeekableChanged); connect(m_manageAudioPlayer, &ManageAudioPlayer::playerPositionChanged, this, &MediaPlayer2Player::audioPositionChanged); connect(m_manageAudioPlayer, &ManageAudioPlayer::audioDurationChanged, this, &MediaPlayer2Player::audioDurationChanged); connect(m_audioPlayer, &AudioWrapper::volumeChanged, this, &MediaPlayer2Player::playerVolumeChanged); m_volume = m_audioPlayer->volume(); m_canPlay = m_manageMediaPlayerControl->playControlEnabled(); signalPropertiesChange(QStringLiteral("Volume"), Volume()); m_mediaPlayerPresent = 1; } MediaPlayer2Player::~MediaPlayer2Player() = default; QString MediaPlayer2Player::PlaybackStatus() const { QString result; if (!m_playListControler) { result = QStringLiteral("Stopped"); return result; } if (m_manageAudioPlayer->playerPlaybackState() == QMediaPlayer::StoppedState) { result = QStringLiteral("Stopped"); } else if (m_manageAudioPlayer->playerPlaybackState() == QMediaPlayer::PlayingState) { result = QStringLiteral("Playing"); } else { result = QStringLiteral("Paused"); } QVariantMap parameters; - if (m_manageAudioPlayer->playerPlaybackState() == QMediaPlayer::StoppedState) { + if (m_manageAudioPlayer->playerPlaybackState() == QMediaPlayer::StoppedState || m_audioPlayer->duration() == 0) { parameters.insert(QStringLiteral("progress-visible"), false); parameters.insert(QStringLiteral("progress"), 0); } else { parameters.insert(QStringLiteral("progress-visible"), true); parameters.insert(QStringLiteral("progress"), qRound(static_cast(m_position / m_audioPlayer->duration())) / 1000.0); } mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.kde.elisa.desktop"), parameters}); QDBusConnection::sessionBus().send(mProgressIndicatorSignal); return result; } bool MediaPlayer2Player::CanGoNext() const { return m_canGoNext; } void MediaPlayer2Player::Next() { emit next(); if (m_playListControler) { m_playListControler->skipNextTrack(); } } bool MediaPlayer2Player::CanGoPrevious() const { return m_canGoPrevious; } void MediaPlayer2Player::Previous() { emit previous(); if (m_playListControler) { m_playListControler->skipPreviousTrack(); } } bool MediaPlayer2Player::CanPause() const { return m_canPlay; } void MediaPlayer2Player::Pause() { if (m_playListControler) { m_manageAudioPlayer->ensurePause(); } } void MediaPlayer2Player::PlayPause() { emit playPause(); if (m_playListControler) { m_manageAudioPlayer->playPause(); } } void MediaPlayer2Player::Stop() { emit stop(); if (m_playListControler) { m_manageAudioPlayer->stop(); } } bool MediaPlayer2Player::CanPlay() const { return m_canPlay; } void MediaPlayer2Player::Play() { if (m_playListControler) { m_manageAudioPlayer->ensurePlay(); } } double MediaPlayer2Player::Volume() const { return m_volume; } void MediaPlayer2Player::setVolume(double volume) { m_volume= qBound(0.0, volume, 1.0); emit volumeChanged(m_volume); m_audioPlayer->setVolume(100 * m_volume); signalPropertiesChange(QStringLiteral("Volume"), Volume()); } QVariantMap MediaPlayer2Player::Metadata() const { return m_metadata; } qlonglong MediaPlayer2Player::Position() const { return m_position; } void MediaPlayer2Player::setPropertyPosition(int newPositionInMs) { m_position = qlonglong(newPositionInMs) * 1000; signalPropertiesChange(QStringLiteral("Position"), Position()); Q_EMIT Seeked(m_position); QVariantMap parameters; parameters.insert(QStringLiteral("progress-visible"), true); parameters.insert(QStringLiteral("progress"), static_cast(newPositionInMs) / m_audioPlayer->duration()); mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.kde.elisa.desktop"), parameters}); QDBusConnection::sessionBus().send(mProgressIndicatorSignal); } double MediaPlayer2Player::Rate() const { return m_rate; } void MediaPlayer2Player::setRate(double newRate) { if (newRate == 0) { Pause(); } else { m_rate = qBound(MinimumRate(), newRate, MaximumRate()); emit rateChanged(m_rate); signalPropertiesChange(QStringLiteral("Rate"), Rate()); } } double MediaPlayer2Player::MinimumRate() const { return MIN_RATE; } double MediaPlayer2Player::MaximumRate() const { return MAX_RATE; } bool MediaPlayer2Player::CanSeek() const { return m_playerIsSeekableChanged; } bool MediaPlayer2Player::CanControl() const { return true; } void MediaPlayer2Player::Seek(qlonglong Offset) { if (mediaPlayerPresent()) { auto offset = (m_position + Offset) / 1000; m_manageAudioPlayer->playerSeek(int(offset)); } } void MediaPlayer2Player::emitSeeked(int pos) { emit Seeked(qlonglong(pos) * 1000); } void MediaPlayer2Player::SetPosition(const QDBusObjectPath &trackId, qlonglong pos) { if (trackId.path() == m_currentTrackId) { m_manageAudioPlayer->playerSeek(int(pos / 1000)); } } void MediaPlayer2Player::OpenUri(const QString &uri) { Q_UNUSED(uri); } void MediaPlayer2Player::playerSourceChanged() { if (!m_playListControler) { return; } setCurrentTrack(m_manageAudioPlayer->playListPosition()); } void MediaPlayer2Player::playControlEnabledChanged() { if (!m_playListControler) { return; } m_canPlay = m_manageMediaPlayerControl->playControlEnabled(); signalPropertiesChange(QStringLiteral("CanPause"), CanPause()); signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay()); emit canPauseChanged(); emit canPlayChanged(); } void MediaPlayer2Player::skipBackwardControlEnabledChanged() { if (!m_playListControler) { return; } m_canGoPrevious = m_manageMediaPlayerControl->skipBackwardControlEnabled(); signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious()); emit canGoPreviousChanged(); } void MediaPlayer2Player::skipForwardControlEnabledChanged() { if (!m_playListControler) { return; } m_canGoNext = m_manageMediaPlayerControl->skipForwardControlEnabled(); signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext()); emit canGoNextChanged(); } void MediaPlayer2Player::playerPlaybackStateChanged() { signalPropertiesChange(QStringLiteral("PlaybackStatus"), PlaybackStatus()); emit playbackStatusChanged(); playerIsSeekableChanged(); } void MediaPlayer2Player::playerIsSeekableChanged() { m_playerIsSeekableChanged = m_manageAudioPlayer->playerIsSeekable(); signalPropertiesChange(QStringLiteral("CanSeek"), CanSeek()); emit canSeekChanged(); } void MediaPlayer2Player::audioPositionChanged() { setPropertyPosition(m_manageAudioPlayer->playerPosition()); } void MediaPlayer2Player::audioDurationChanged() { m_metadata = getMetadataOfCurrentTrack(); signalPropertiesChange(QStringLiteral("Metadata"), Metadata()); skipBackwardControlEnabledChanged(); skipForwardControlEnabledChanged(); playerPlaybackStateChanged(); playerIsSeekableChanged(); setPropertyPosition(m_manageAudioPlayer->playerPosition()); } void MediaPlayer2Player::playerVolumeChanged() { setVolume(m_audioPlayer->volume() / 100.0); } int MediaPlayer2Player::currentTrack() const { return m_manageAudioPlayer->playListPosition(); } void MediaPlayer2Player::setCurrentTrack(int newTrackPosition) { m_currentTrack = m_manageAudioPlayer->playerSource().toString(); m_currentTrackId = QDBusObjectPath(QStringLiteral("/org/kde/elisa/playlist/") + QString::number(newTrackPosition)).path(); emit currentTrackChanged(); } QVariantMap MediaPlayer2Player::getMetadataOfCurrentTrack() { auto result = QVariantMap(); result[QStringLiteral("mpris:trackid")] = QVariant::fromValue(QDBusObjectPath(m_currentTrackId)); result[QStringLiteral("mpris:length")] = qlonglong(m_manageAudioPlayer->audioDuration()) * 1000; //convert milli-seconds into micro-seconds result[QStringLiteral("xesam:title")] = m_manageHeaderBar->title(); result[QStringLiteral("xesam:url")] = m_manageAudioPlayer->playerSource().toString(); result[QStringLiteral("xesam:album")] = m_manageHeaderBar->album(); result[QStringLiteral("xesam:artist")] = QStringList{m_manageHeaderBar->artist().toString()}; result[QStringLiteral("mpris:artUrl")] = m_manageHeaderBar->image().toString(); return result; } int MediaPlayer2Player::mediaPlayerPresent() const { return m_mediaPlayerPresent; } void MediaPlayer2Player::setMediaPlayerPresent(int status) { if (m_mediaPlayerPresent != status) { m_mediaPlayerPresent = status; emit mediaPlayerPresentChanged(); signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext()); signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious()); signalPropertiesChange(QStringLiteral("CanPause"), CanPause()); signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay()); emit canGoNextChanged(); emit canGoPreviousChanged(); emit canPauseChanged(); emit canPlayChanged(); } } void MediaPlayer2Player::signalPropertiesChange(const QString &property, const QVariant &value) { QVariantMap properties; properties[property] = value; const int ifaceIndex = metaObject()->indexOfClassInfo("D-Bus Interface"); QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"), QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged")); msg << QLatin1String(metaObject()->classInfo(ifaceIndex).value()); msg << properties; msg << QStringList(); QDBusConnection::sessionBus().send(msg); } #include "moc_mediaplayer2player.cpp" diff --git a/src/trackslistener.cpp b/src/trackslistener.cpp index 3d0aa9c1..1948fe46 100644 --- a/src/trackslistener.cpp +++ b/src/trackslistener.cpp @@ -1,226 +1,226 @@ /* * Copyright 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 "trackslistener.h" #include "databaseinterface.h" #include "filescanner.h" #include #include #include #include #include #include class TracksListenerPrivate { public: QSet mTracksByIdSet; QList> mTracksByNameSet; QList mTracksByFileNameSet; DatabaseInterface *mDatabase = nullptr; FileScanner mFileScanner; QMimeDatabase mMimeDb; }; TracksListener::TracksListener(DatabaseInterface *database, QObject *parent) : QObject(parent), d(std::make_unique()) { d->mDatabase = database; } TracksListener::~TracksListener() = default; void TracksListener::tracksAdded(const ListTrackDataType &allTracks) { for (const auto &oneTrack : allTracks) { if (d->mTracksByIdSet.contains(oneTrack.databaseId())) { Q_EMIT trackHasChanged(oneTrack); } if (d->mTracksByNameSet.isEmpty()) { return; } for (auto itTrack = d->mTracksByNameSet.begin(); itTrack != d->mTracksByNameSet.end(); ) { if (std::get<0>(*itTrack) != oneTrack.title()) { ++itTrack; continue; } if (std::get<1>(*itTrack) != oneTrack.artist()) { ++itTrack; continue; } if (std::get<2>(*itTrack) != oneTrack.album()) { ++itTrack; continue; } if (std::get<3>(*itTrack) != oneTrack.trackNumber()) { ++itTrack; continue; } if (std::get<4>(*itTrack) != oneTrack.discNumber()) { ++itTrack; continue; } Q_EMIT trackHasChanged(TrackDataType(oneTrack)); d->mTracksByIdSet.insert(oneTrack.databaseId()); itTrack = d->mTracksByNameSet.erase(itTrack); } } } void TracksListener::trackRemoved(qulonglong id) { if (d->mTracksByIdSet.contains(id)) { Q_EMIT trackHasBeenRemoved(id); } } void TracksListener::trackModified(const TrackDataType &modifiedTrack) { if (d->mTracksByIdSet.contains(modifiedTrack.databaseId())) { Q_EMIT trackHasChanged(modifiedTrack); } } void TracksListener::trackByNameInList(const QString &title, const QString &artist, const QString &album, int trackNumber, int discNumber) { auto newTrackId = d->mDatabase->trackIdFromTitleAlbumTrackDiscNumber(title, artist, album, trackNumber, discNumber); if (newTrackId == 0) { auto newTrack = std::tuple(title, artist, album, trackNumber, discNumber); d->mTracksByNameSet.push_back(newTrack); return; } d->mTracksByIdSet.insert(newTrackId); auto newTrack = d->mDatabase->trackDataFromDatabaseId(newTrackId); if (!newTrack.isEmpty()) { Q_EMIT trackHasChanged(newTrack); } } void TracksListener::trackByFileNameInList(const QUrl &fileName) { auto newTrackId = d->mDatabase->trackIdFromFileName(fileName); if (newTrackId == 0) { auto newTrack = scanOneFile(fileName); if (newTrack.isValid()) { auto oneData = DatabaseInterface::TrackDataType{}; oneData[DatabaseInterface::TrackDataType::key_type::TitleRole] = newTrack.title(); oneData[DatabaseInterface::TrackDataType::key_type::ArtistRole] = newTrack.artist(); oneData[DatabaseInterface::TrackDataType::key_type::AlbumRole] = newTrack.albumName(); oneData[DatabaseInterface::TrackDataType::key_type::AlbumIdRole] = newTrack.albumId(); oneData[DatabaseInterface::TrackDataType::key_type::TrackNumberRole] = newTrack.trackNumber(); oneData[DatabaseInterface::TrackDataType::key_type::DiscNumberRole] = newTrack.discNumber(); oneData[DatabaseInterface::TrackDataType::key_type::DurationRole] = newTrack.duration(); oneData[DatabaseInterface::TrackDataType::key_type::MilliSecondsDurationRole] = newTrack.duration().msecsSinceStartOfDay(); oneData[DatabaseInterface::TrackDataType::key_type::ResourceRole] = newTrack.resourceURI(); oneData[DatabaseInterface::TrackDataType::key_type::ImageUrlRole] = newTrack.albumCover(); Q_EMIT trackHasChanged(oneData); return; } d->mTracksByFileNameSet.push_back(fileName); return; } d->mTracksByIdSet.insert(newTrackId); auto newTrack = d->mDatabase->trackDataFromDatabaseId(newTrackId); if (!newTrack.isEmpty()) { Q_EMIT trackHasChanged({newTrack}); } } void TracksListener::newAlbumInList(qulonglong newDatabaseId, const QString &entryTitle) { Q_EMIT tracksListAdded(newDatabaseId, entryTitle, ElisaUtils::Album, d->mDatabase->albumData(newDatabaseId)); } void TracksListener::newEntryInList(qulonglong newDatabaseId, const QString &entryTitle, ElisaUtils::PlayListEntryType databaseIdType) { switch (databaseIdType) { case ElisaUtils::Track: { d->mTracksByIdSet.insert(newDatabaseId); auto newTrack = d->mDatabase->trackDataFromDatabaseId(newDatabaseId); if (!newTrack.isEmpty()) { Q_EMIT trackHasChanged(newTrack); } break; } case ElisaUtils::Artist: - newArtistInList(entryTitle); + newArtistInList(newDatabaseId, entryTitle); break; case ElisaUtils::FileName: trackByFileNameInList(QUrl::fromLocalFile(entryTitle)); break; case ElisaUtils::Album: newAlbumInList(newDatabaseId, entryTitle); } } -void TracksListener::newArtistInList(const QString &artist) +void TracksListener::newArtistInList(qulonglong newDatabaseId, const QString &artist) { - auto newTracks = d->mDatabase->tracksFromAuthor(artist); + auto newTracks = d->mDatabase->tracksDataFromAuthor(artist); if (newTracks.isEmpty()) { return; } for (const auto &oneTrack : newTracks) { d->mTracksByIdSet.insert(oneTrack.databaseId()); } - Q_EMIT tracksListAdded(0, artist, ElisaUtils::Artist, newTracks); + Q_EMIT tracksListAdded(newDatabaseId, artist, ElisaUtils::Artist, newTracks); } MusicAudioTrack TracksListener::scanOneFile(const QUrl &scanFile) { return d->mFileScanner.scanOneFile(scanFile, d->mMimeDb); } #include "moc_trackslistener.cpp" diff --git a/src/trackslistener.h b/src/trackslistener.h index 360415e2..e5437a1d 100644 --- a/src/trackslistener.h +++ b/src/trackslistener.h @@ -1,87 +1,87 @@ /* * Copyright 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 . */ #ifndef TRACKSLISTENER_H #define TRACKSLISTENER_H #include "elisaLib_export.h" #include "databaseinterface.h" #include "musicaudiotrack.h" #include "elisautils.h" #include #include class TracksListenerPrivate; class ELISALIB_EXPORT TracksListener : public QObject { Q_OBJECT public: using ListTrackDataType = DatabaseInterface::ListTrackDataType; using TrackDataType = DatabaseInterface::TrackDataType; explicit TracksListener(DatabaseInterface *database, QObject *parent = nullptr); ~TracksListener() override; Q_SIGNALS: void trackHasChanged(const TrackDataType &audioTrack); void trackHasBeenRemoved(qulonglong id); void tracksListAdded(qulonglong newDatabaseId, const QString &entryTitle, ElisaUtils::PlayListEntryType databaseIdType, const ListTrackDataType &tracks); public Q_SLOTS: void tracksAdded(const ListTrackDataType &allTracks); void trackRemoved(qulonglong id); void trackModified(const TrackDataType &modifiedTrack); void trackByNameInList(const QString &title, const QString &artist, const QString &album, int trackNumber, int discNumber); void newEntryInList(qulonglong newDatabaseId, const QString &entryTitle, ElisaUtils::PlayListEntryType databaseIdType); private: MusicAudioTrack scanOneFile(const QUrl &scanFile); - void newArtistInList(const QString &artist); + void newArtistInList(qulonglong newDatabaseId, const QString &artist); void trackByFileNameInList(const QUrl &fileName); void newAlbumInList(qulonglong newDatabaseId, const QString &entryTitle); std::unique_ptr d; }; #endif // TRACKSLISTENER_H