File indexing completed on 2024-04-21 04:48:57

0001 /*
0002    SPDX-FileCopyrightText: 2016 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003 
0004    SPDX-License-Identifier: LGPL-3.0-or-later
0005  */
0006 
0007 #ifndef DATABASEINTERFACE_H
0008 #define DATABASEINTERFACE_H
0009 
0010 #include "elisaLib_export.h"
0011 
0012 #include "elisautils.h"
0013 #include "datatypes.h"
0014 
0015 #include <QObject>
0016 #include <QString>
0017 #include <QHash>
0018 #include <QList>
0019 #include <QUrl>
0020 #include <QDateTime>
0021 
0022 #include <memory>
0023 #include <optional>
0024 
0025 class DatabaseInterfacePrivate;
0026 class QSqlRecord;
0027 class QSqlQuery;
0028 
0029 class ELISALIB_EXPORT DatabaseInterface : public QObject
0030 {
0031     Q_OBJECT
0032 
0033 public:
0034 
0035     enum DatabaseVersion {
0036         V9 = 9,
0037         V11 = 11,
0038         V12 = 12,
0039         V13 = 13,
0040         V14 = 14,
0041         V15 = 15,
0042         V16 = 16,
0043         V17 = 17,
0044     };
0045 
0046     explicit DatabaseInterface(QObject *parent = nullptr);
0047 
0048     ~DatabaseInterface() override;
0049 
0050     Q_INVOKABLE void init(const QString &dbName, const QString &databaseFileName = {});
0051 
0052     qulonglong albumIdFromTitleAndArtist(const QString &title, const QString &artist, const QString &albumPath);
0053 
0054     DataTypes::ListTrackDataType allTracksData();
0055 
0056     DataTypes::ListRadioDataType allRadiosData();
0057 
0058     DataTypes::ListTrackDataType recentlyPlayedTracksData(int count);
0059 
0060     DataTypes::ListTrackDataType frequentlyPlayedTracksData(int count);
0061 
0062     DataTypes::ListAlbumDataType allAlbumsData();
0063 
0064     DataTypes::ListAlbumDataType allAlbumsDataByGenreAndArtist(const QString &genre, const QString &artist);
0065 
0066     DataTypes::ListAlbumDataType allAlbumsDataByArtist(const QString &artist);
0067 
0068     DataTypes::AlbumDataType albumDataFromDatabaseId(qulonglong id);
0069 
0070     DataTypes::ListTrackDataType albumData(qulonglong databaseId);
0071 
0072     DataTypes::ListArtistDataType allArtistsData();
0073 
0074     DataTypes::ListArtistDataType allArtistsDataByGenre(const QString &genre);
0075 
0076     DataTypes::ArtistDataType artistDataFromDatabaseId(qulonglong id);
0077 
0078     qulonglong artistIdFromName(const QString &name);
0079 
0080     DataTypes::ListGenreDataType allGenresData();
0081 
0082     bool internalArtistMatchGenre(qulonglong databaseId, const QString &genre);
0083 
0084     DataTypes::ListTrackDataType tracksDataFromAuthor(const QString &artistName);
0085 
0086     DataTypes::ListTrackDataType tracksDataFromGenre(const QString &genre);
0087 
0088     DataTypes::TrackDataType trackDataFromDatabaseId(qulonglong id);
0089 
0090     DataTypes::TrackDataType trackDataFromDatabaseIdAndUrl(qulonglong id, const QUrl &trackUrl);
0091 
0092     DataTypes::TrackDataType radioDataFromDatabaseId(qulonglong id);
0093 
0094     qulonglong trackIdFromTitleAlbumTrackDiscNumber(const QString &title, const QString &artist, const std::optional<QString> &album, std::optional<int> trackNumber, std::optional<int> discNumber);
0095 
0096     qulonglong trackIdFromFileName(const QUrl &fileName);
0097 
0098     qulonglong radioIdFromFileName(const QUrl &fileName);
0099 
0100     void applicationAboutToQuit();
0101 
0102 Q_SIGNALS:
0103 
0104     void artistsAdded(const DataTypes::ListArtistDataType &newArtists);
0105 
0106     void composersAdded(const DataTypes::ListArtistDataType &newComposers);
0107 
0108     void lyricistsAdded(const DataTypes::ListArtistDataType &newLyricists);
0109 
0110     void albumsAdded(const DataTypes::ListAlbumDataType &newAlbums);
0111 
0112     void tracksAdded(const DataTypes::ListTrackDataType &allTracks);
0113 
0114     void genresAdded(const DataTypes::ListGenreDataType &allGenres);
0115 
0116     void artistRemoved(qulonglong removedArtistId);
0117 
0118     void albumRemoved(qulonglong removedAlbumId);
0119 
0120     void trackRemoved(qulonglong id);
0121 
0122     void albumModified(const DataTypes::AlbumDataType &modifiedAlbum, qulonglong modifiedAlbumId);
0123 
0124     void trackModified(const DataTypes::TrackDataType &modifiedTrack);
0125 
0126     void requestsInitDone();
0127 
0128     void databaseError();
0129 
0130     void restoredTracks(const QHash<QUrl, QDateTime> &allFiles);
0131 
0132     void cleanedDatabase();
0133 
0134     void finishInsertingTracksList();
0135 
0136     void finishRemovingTracksList();
0137 
0138     void radioAdded(const DataTypes::TrackDataType &radio);
0139 
0140     void radioModified(const DataTypes::TrackDataType &radio);
0141 
0142     void radioRemoved(qulonglong radioId);
0143 
0144 public Q_SLOTS:
0145 
0146     void insertTracksList(const DataTypes::ListTrackDataType &tracks, const QHash<QString, QUrl> &covers);
0147 
0148     void removeTracksList(const QList<QUrl> &removedTracks);
0149 
0150     void askRestoredTracks();
0151 
0152     void trackHasStartedPlaying(const QUrl &fileName, const QDateTime &time);
0153 
0154     void trackHasFinishedPlaying(const QUrl &fileName, const QDateTime &time);
0155 
0156     void clearData();
0157 
0158     void removeRadio(qulonglong radioId);
0159 
0160 private:
0161 
0162     enum class DatabaseState {
0163         GoodState,
0164         BadState,
0165     };
0166 
0167     /********* Init and upgrade methods *********/
0168 
0169     void initConnection(const QString &connectionName, const QString &databaseFileName);
0170 
0171     bool initDatabase();
0172 
0173     void createDatabaseV9();
0174 
0175     void upgradeDatabaseV9();
0176 
0177     void upgradeDatabaseV11();
0178 
0179     void upgradeDatabaseV12();
0180 
0181     void upgradeDatabaseV13();
0182 
0183     void upgradeDatabaseV14();
0184 
0185     void upgradeDatabaseV15();
0186 
0187     void upgradeDatabaseV16();
0188 
0189     void upgradeDatabaseV17();
0190 
0191     [[nodiscard]] DatabaseState checkDatabaseSchema() const;
0192 
0193     [[nodiscard]] DatabaseState checkTable(const QString &tableName, const QStringList &expectedColumns) const;
0194 
0195     bool resetDatabase();
0196 
0197     DatabaseVersion currentDatabaseVersion();
0198 
0199     bool upgradeDatabaseToLatestVersion();
0200 
0201     void dropTable(const QString &table);
0202 
0203     void setDatabaseVersionInTable(int version);
0204 
0205     void createDatabaseVersionTable();
0206 
0207     void initDatabaseVersionQueries();
0208 
0209     void callUpgradeFunctionForVersion(DatabaseVersion databaseVersion);
0210 
0211     /********* Data query methods *********/
0212 
0213     bool startTransaction();
0214 
0215     bool finishTransaction();
0216 
0217     bool rollBackTransaction();
0218 
0219     bool prepareQuery(QSqlQuery &query, const QString &queryText) const;
0220 
0221     bool execQuery(QSqlQuery &query);
0222 
0223     void initDataQueries();
0224 
0225     void initChangesTrackers();
0226 
0227     void recordModifiedTrack(qulonglong trackId);
0228 
0229     void recordModifiedAlbum(qulonglong albumId);
0230 
0231     QList<qulonglong> fetchTrackIds(qulonglong albumId);
0232 
0233     qulonglong internalAlbumIdFromTitleAndArtist(const QString &title, const QString &artist, const QString &albumPath);
0234 
0235     DataTypes::TrackDataType internalTrackFromDatabaseId(qulonglong id);
0236 
0237     qulonglong internalTrackIdFromTitleAlbumTracDiscNumber(const QString &title, const QString &artist, const std::optional<QString> &album,
0238                                                            std::optional<int> trackNumber, std::optional<int> discNumber);
0239 
0240     qulonglong getDuplicateTrackIdFromTitleAlbumTrackDiscNumber(const QString &title, const QString &trackArtist, const QString &album,
0241                                                                 const QString &albumArtist, const QString &trackPath, int trackNumber,
0242                                                                 int discNumber, int priority);
0243 
0244     qulonglong internalTrackIdFromFileName(const QUrl &fileName);
0245 
0246     qulonglong internalRadioIdFromHttpAddress(const QString &httpAddress);
0247 
0248     DataTypes::ListTrackDataType internalTracksFromAuthor(const QString &artistName);
0249 
0250     DataTypes::ListTrackDataType internalTracksFromGenre(const QString &genre);
0251 
0252     QList<qulonglong> internalAlbumIdsFromAuthor(const QString &artistName);
0253 
0254     qulonglong insertAlbum(const QString &title, const QString &albumArtist,
0255                            const QString &trackPath, const QUrl &albumArtURI);
0256 
0257     bool updateAlbumFromId(qulonglong albumId, const QUrl &albumArtUri,
0258                            const DataTypes::TrackDataType &currentTrack, const QString &albumPath);
0259 
0260     qulonglong insertArtist(const QString &name);
0261 
0262     qulonglong internalArtistIdFromName(const QString &name);
0263 
0264     qulonglong insertGenre(const QString &name);
0265 
0266     void removeTrackInDatabase(qulonglong trackId);
0267 
0268     void updateTrackInDatabase(const DataTypes::TrackDataType &oneTrack, const QString &albumPath);
0269 
0270     void removeAlbumInDatabase(qulonglong albumId);
0271 
0272     void removeArtistInDatabase(qulonglong artistId);
0273 
0274     void reloadExistingDatabase();
0275 
0276     qulonglong genericInitialId(QSqlQuery &request);
0277 
0278     void insertTrackOrigin(const QUrl &fileNameURI, const QDateTime &fileModifiedTime, const QDateTime &importDate);
0279 
0280     void updateTrackOrigin(const QUrl &fileName, const QDateTime &fileModifiedTime);
0281 
0282     qulonglong internalInsertTrack(const DataTypes::TrackDataType &oneModifiedTrack,
0283                                    const QHash<QString, QUrl> &covers, bool &isInserted);
0284 
0285     [[nodiscard]] DataTypes::TrackDataType buildTrackDataFromDatabaseRecord(const QSqlRecord &trackRecord) const;
0286 
0287     [[nodiscard]] DataTypes::TrackDataType buildRadioDataFromDatabaseRecord(const QSqlRecord &trackRecord) const;
0288 
0289     void internalRemoveTracksList(const QList<QUrl> &removedTracks);
0290 
0291     void internalRemoveTracksList(const QHash<QUrl, QDateTime> &removedTracks, qulonglong sourceId);
0292 
0293     QUrl internalAlbumArtUriFromAlbumId(qulonglong albumId);
0294 
0295     bool isValidArtist(qulonglong albumId);
0296 
0297     qulonglong insertComposer(const QString &name);
0298 
0299     qulonglong insertLyricist(const QString &name);
0300 
0301     QHash<QUrl, QDateTime> internalAllFileName();
0302 
0303     bool internalGenericPartialData(QSqlQuery &query);
0304 
0305     DataTypes::ListArtistDataType internalAllArtistsPartialData(QSqlQuery &artistsQuery);
0306 
0307     DataTypes::ListAlbumDataType internalAllAlbumsPartialData(QSqlQuery &query);
0308 
0309     DataTypes::ListTrackDataType internalOneAlbumData(qulonglong databaseId);
0310 
0311     DataTypes::AlbumDataType internalOneAlbumPartialData(qulonglong databaseId);
0312 
0313     DataTypes::ArtistDataType internalOneArtistPartialData(qulonglong databaseId);
0314 
0315     DataTypes::ListTrackDataType internalAllTracksPartialData();
0316 
0317     DataTypes::ListRadioDataType internalAllRadiosPartialData();
0318 
0319     DataTypes::ListTrackDataType internalRecentlyPlayedTracksData(int count);
0320 
0321     DataTypes::ListTrackDataType internalFrequentlyPlayedTracksData(int count);
0322 
0323     DataTypes::TrackDataType internalOneTrackPartialData(qulonglong databaseId);
0324 
0325     DataTypes::TrackDataType internalOneTrackPartialDataByIdAndUrl(qulonglong databaseId, const QUrl &trackUrl);
0326 
0327     DataTypes::TrackDataType internalOneRadioPartialData(qulonglong databaseId);
0328 
0329     DataTypes::ListGenreDataType internalAllGenresPartialData();
0330 
0331     DataTypes::ListArtistDataType internalAllComposersPartialData();
0332 
0333     DataTypes::ListArtistDataType internalAllLyricistsPartialData();
0334 
0335     void updateAlbumArtist(qulonglong albumId, const QString &title, const QString &albumPath,
0336                            const QString &artistName);
0337 
0338     bool updateAlbumCover(qulonglong albumId, const QUrl &albumArtUri);
0339 
0340     QVariantList internalGetLatestFourCoversForArtist(const QString& artistName);
0341 
0342     void updateTrackStartedStatistics(const QUrl &fileName, const QDateTime &time);
0343 
0344     void updateTrackFinishedStatistics(const QUrl &fileName, const QDateTime &time);
0345 
0346     void internalInsertOneTrack(const DataTypes::TrackDataType &oneTrack, const QHash<QString, QUrl> &covers);
0347 
0348     void internalInsertOneRadio(const DataTypes::TrackDataType &oneTrack);
0349 
0350     std::unique_ptr<DatabaseInterfacePrivate> d;
0351 
0352 };
0353 
0354 #endif // DATABASEINTERFACE_H