File indexing completed on 2024-04-14 04:44:02

0001 /*
0002    SPDX-FileCopyrightText: 2018 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003 
0004    SPDX-License-Identifier: LGPL-3.0-or-later
0005  */
0006 
0007 #include "modeldataloader.h"
0008 
0009 #include "filescanner.h"
0010 #include "filewriter.h"
0011 
0012 #include <QFileInfo>
0013 
0014 class ModelDataLoaderPrivate
0015 {
0016 public:
0017 
0018     DatabaseInterface *mDatabase = nullptr;
0019 
0020     ElisaUtils::PlayListEntryType mModelType = ElisaUtils::Unknown;
0021 
0022     ModelDataLoader::FilterType mFilterType = ModelDataLoader::FilterType::UnknownFilter;
0023 
0024     QString mArtist;
0025 
0026     QString mAlbumTitle;
0027 
0028     QString mAlbumArtist;
0029 
0030     QString mGenre;
0031 
0032     qulonglong mDatabaseId = 0;
0033 
0034     FileScanner mFileScanner;
0035 
0036     FileWriter mFileWriter;
0037 };
0038 
0039 ModelDataLoader::ModelDataLoader(QObject *parent) : QObject(parent), d(std::make_unique<ModelDataLoaderPrivate>())
0040 {
0041 }
0042 
0043 ModelDataLoader::~ModelDataLoader() = default;
0044 
0045 void ModelDataLoader::setDatabase(DatabaseInterface *database)
0046 {
0047     d->mDatabase = database;
0048 
0049     connect(database, &DatabaseInterface::genresAdded,
0050             this, &ModelDataLoader::genresAdded);
0051     connect(database, &DatabaseInterface::albumsAdded,
0052             this, &ModelDataLoader::databaseAlbumsAdded);
0053     connect(database, &DatabaseInterface::albumModified,
0054             this, &ModelDataLoader::albumModified);
0055     connect(database, &DatabaseInterface::albumRemoved,
0056             this, &ModelDataLoader::albumRemoved);
0057     connect(database, &DatabaseInterface::tracksAdded,
0058             this, &ModelDataLoader::databaseTracksAdded);
0059     connect(database, &DatabaseInterface::trackModified,
0060             this, &ModelDataLoader::trackModified);
0061     connect(database, &DatabaseInterface::trackRemoved,
0062             this, &ModelDataLoader::trackRemoved);
0063     connect(database, &DatabaseInterface::artistsAdded,
0064             this, &ModelDataLoader::databaseArtistsAdded);
0065     connect(database, &DatabaseInterface::artistRemoved,
0066             this, &ModelDataLoader::artistRemoved);
0067     connect(this, &ModelDataLoader::saveTrackModified,
0068             database, &DatabaseInterface::insertTracksList);
0069     connect(this, &ModelDataLoader::removeRadio,
0070             database, &DatabaseInterface::removeRadio);
0071     connect(database, &DatabaseInterface::radioAdded,
0072             this, &ModelDataLoader::radioAdded);
0073     connect(database, &DatabaseInterface::radioModified,
0074             this, &ModelDataLoader::radioModified);
0075     connect(database, &DatabaseInterface::radioRemoved,
0076             this, &ModelDataLoader::radioRemoved);
0077     connect(database, &DatabaseInterface::cleanedDatabase,
0078             this, &ModelDataLoader::clearedDatabase);
0079 }
0080 
0081 void ModelDataLoader::loadData(ElisaUtils::PlayListEntryType dataType)
0082 {
0083     if (!d->mDatabase) {
0084         return;
0085     }
0086 
0087     d->mFilterType = ModelDataLoader::FilterType::NoFilter;
0088 
0089     switch (dataType)
0090     {
0091     case ElisaUtils::Album:
0092         Q_EMIT allAlbumsData(d->mDatabase->allAlbumsData());
0093         break;
0094     case ElisaUtils::Artist:
0095         Q_EMIT allArtistsData(d->mDatabase->allArtistsData());
0096         break;
0097     case ElisaUtils::Composer:
0098         break;
0099     case ElisaUtils::Genre:
0100         Q_EMIT allGenresData(d->mDatabase->allGenresData());
0101         break;
0102     case ElisaUtils::Lyricist:
0103         break;
0104     case ElisaUtils::Track:
0105         Q_EMIT allTracksData(d->mDatabase->allTracksData());
0106         break;
0107     case ElisaUtils::FileName:
0108     case ElisaUtils::Unknown:
0109     case ElisaUtils::Container:
0110     case ElisaUtils::PlayList:
0111         break;
0112     case ElisaUtils::Radio:
0113         Q_EMIT allRadiosData(d->mDatabase->allRadiosData());
0114         break;
0115     }
0116 }
0117 
0118 void ModelDataLoader::loadDataByAlbumId(ElisaUtils::PlayListEntryType dataType, qulonglong databaseId)
0119 {
0120     if (!d->mDatabase) {
0121         return;
0122     }
0123 
0124     d->mFilterType = ModelDataLoader::FilterType::FilterById;
0125     d->mDatabaseId = databaseId;
0126 
0127     switch (dataType)
0128     {
0129     case ElisaUtils::Album:
0130         break;
0131     case ElisaUtils::Artist:
0132         break;
0133     case ElisaUtils::Composer:
0134         break;
0135     case ElisaUtils::Genre:
0136         break;
0137     case ElisaUtils::Lyricist:
0138         break;
0139     case ElisaUtils::Track:
0140         Q_EMIT allTracksData(d->mDatabase->albumData(databaseId));
0141         break;
0142     case ElisaUtils::FileName:
0143     case ElisaUtils::Unknown:
0144     case ElisaUtils::Radio:
0145     case ElisaUtils::Container:
0146     case ElisaUtils::PlayList:
0147         break;
0148     }
0149 }
0150 
0151 void ModelDataLoader::loadDataByGenre(ElisaUtils::PlayListEntryType dataType, const QString &genre)
0152 {
0153     if (!d->mDatabase) {
0154         return;
0155     }
0156 
0157     d->mFilterType = ModelDataLoader::FilterType::FilterByGenre;
0158     d->mGenre = genre;
0159 
0160     switch (dataType)
0161     {
0162     case ElisaUtils::Artist:
0163         Q_EMIT allArtistsData(d->mDatabase->allArtistsDataByGenre(genre));
0164         break;
0165     case ElisaUtils::Album:
0166     case ElisaUtils::Composer:
0167     case ElisaUtils::Track:
0168     case ElisaUtils::Genre:
0169     case ElisaUtils::Lyricist:
0170     case ElisaUtils::FileName:
0171     case ElisaUtils::Unknown:
0172     case ElisaUtils::Radio:
0173     case ElisaUtils::Container:
0174     case ElisaUtils::PlayList:
0175         break;
0176     }
0177 }
0178 
0179 void ModelDataLoader::loadDataByArtist(ElisaUtils::PlayListEntryType dataType, const QString &artist)
0180 {
0181     if (!d->mDatabase) {
0182         return;
0183     }
0184 
0185     d->mFilterType = ModelDataLoader::FilterType::FilterByArtist;
0186     d->mArtist = artist;
0187 
0188     switch (dataType)
0189     {
0190     case ElisaUtils::Album:
0191         Q_EMIT allAlbumsData(d->mDatabase->allAlbumsDataByArtist(artist));
0192         break;
0193     case ElisaUtils::Artist:
0194     case ElisaUtils::Composer:
0195     case ElisaUtils::Track:
0196     case ElisaUtils::Genre:
0197     case ElisaUtils::Lyricist:
0198     case ElisaUtils::FileName:
0199     case ElisaUtils::Unknown:
0200     case ElisaUtils::Radio:
0201     case ElisaUtils::Container:
0202     case ElisaUtils::PlayList:
0203         break;
0204     }
0205 }
0206 
0207 void ModelDataLoader::loadDataByGenreAndArtist(ElisaUtils::PlayListEntryType dataType, const QString &genre, const QString &artist)
0208 {
0209     if (!d->mDatabase) {
0210         return;
0211     }
0212 
0213     d->mFilterType = ModelDataLoader::FilterType::FilterByGenreAndArtist;
0214     d->mArtist = artist;
0215     d->mGenre = genre;
0216 
0217     switch (dataType)
0218     {
0219     case ElisaUtils::Album:
0220         Q_EMIT allAlbumsData(d->mDatabase->allAlbumsDataByGenreAndArtist(genre, artist));
0221         break;
0222     case ElisaUtils::Artist:
0223     case ElisaUtils::Composer:
0224     case ElisaUtils::Genre:
0225     case ElisaUtils::Lyricist:
0226     case ElisaUtils::Track:
0227     case ElisaUtils::FileName:
0228     case ElisaUtils::Unknown:
0229     case ElisaUtils::Radio:
0230     case ElisaUtils::Container:
0231     case ElisaUtils::PlayList:
0232         break;
0233     }
0234 }
0235 
0236 void ModelDataLoader::loadDataByDatabaseIdAndUrl(ElisaUtils::PlayListEntryType dataType,
0237                                                  qulonglong databaseId, const QUrl &url)
0238 {
0239     if (!d->mDatabase) {
0240         return;
0241     }
0242 
0243     d->mFilterType = ModelDataLoader::FilterType::FilterById;
0244     d->mDatabaseId = databaseId;
0245 
0246     switch (dataType)
0247     {
0248     case ElisaUtils::FileName:
0249     case ElisaUtils::Track:
0250         Q_EMIT allTrackData(d->mDatabase->trackDataFromDatabaseIdAndUrl(databaseId, url));
0251         break;
0252     case ElisaUtils::Radio:
0253         Q_EMIT allRadioData(d->mDatabase->radioDataFromDatabaseId(databaseId));
0254         break;
0255     case ElisaUtils::Album:
0256     case ElisaUtils::Artist:
0257     case ElisaUtils::Composer:
0258     case ElisaUtils::Genre:
0259     case ElisaUtils::Lyricist:
0260     case ElisaUtils::Unknown:
0261     case ElisaUtils::Container:
0262     case ElisaUtils::PlayList:
0263         break;
0264     }
0265 }
0266 
0267 void ModelDataLoader::loadDataByUrl(ElisaUtils::PlayListEntryType dataType, const QUrl &url)
0268 {
0269     if (!d->mDatabase) {
0270         return;
0271     }
0272 
0273     d->mFilterType = ModelDataLoader::FilterType::UnknownFilter;
0274 
0275     switch (dataType)
0276     {
0277     case ElisaUtils::FileName:
0278     case ElisaUtils::Track:
0279     {
0280         auto databaseId = d->mDatabase->trackIdFromFileName(url);
0281         if (databaseId != 0) {
0282             Q_EMIT allTrackData(d->mDatabase->trackDataFromDatabaseIdAndUrl(databaseId, url));
0283         } else {
0284             auto result = d->mFileScanner.scanOneFile(url);
0285             Q_EMIT allTrackData(result);
0286         }
0287         break;
0288     }
0289     case ElisaUtils::Radio:
0290     {
0291         auto databaseId = d->mDatabase->radioIdFromFileName(url);
0292         if (databaseId != 0) {
0293             Q_EMIT allRadioData(d->mDatabase->radioDataFromDatabaseId(databaseId));
0294         } else {
0295             auto result = d->mFileScanner.scanOneFile(url);
0296             Q_EMIT allRadioData(result);
0297         }
0298         break;
0299     }
0300     case ElisaUtils::Album:
0301     case ElisaUtils::Artist:
0302     case ElisaUtils::Composer:
0303     case ElisaUtils::Genre:
0304     case ElisaUtils::Lyricist:
0305     case ElisaUtils::Unknown:
0306     case ElisaUtils::Container:
0307     case ElisaUtils::PlayList:
0308         break;
0309     }
0310 }
0311 
0312 void ModelDataLoader::loadRecentlyPlayedData(ElisaUtils::PlayListEntryType dataType)
0313 {
0314     if (!d->mDatabase) {
0315         return;
0316     }
0317 
0318     d->mFilterType = ModelDataLoader::FilterType::FilterByRecentlyPlayed;
0319 
0320     switch (dataType)
0321     {
0322     case ElisaUtils::Track:
0323         Q_EMIT allTracksData(d->mDatabase->recentlyPlayedTracksData(50));
0324         break;
0325     case ElisaUtils::Album:
0326     case ElisaUtils::Artist:
0327     case ElisaUtils::Composer:
0328     case ElisaUtils::Genre:
0329     case ElisaUtils::Lyricist:
0330     case ElisaUtils::FileName:
0331     case ElisaUtils::Unknown:
0332     case ElisaUtils::Radio:
0333     case ElisaUtils::Container:
0334     case ElisaUtils::PlayList:
0335         break;
0336     }
0337 }
0338 
0339 void ModelDataLoader::loadFrequentlyPlayedData(ElisaUtils::PlayListEntryType dataType)
0340 {
0341     if (!d->mDatabase) {
0342         return;
0343     }
0344 
0345     d->mFilterType = ModelDataLoader::FilterType::FilterByFrequentlyPlayed;
0346 
0347     switch (dataType)
0348     {
0349     case ElisaUtils::Track:
0350         Q_EMIT allTracksData(d->mDatabase->frequentlyPlayedTracksData(50));
0351         break;
0352     case ElisaUtils::Album:
0353     case ElisaUtils::Artist:
0354     case ElisaUtils::Composer:
0355     case ElisaUtils::Genre:
0356     case ElisaUtils::Lyricist:
0357     case ElisaUtils::FileName:
0358     case ElisaUtils::Unknown:
0359     case ElisaUtils::Radio:
0360     case ElisaUtils::Container:
0361     case ElisaUtils::PlayList:
0362         break;
0363     }
0364 }
0365 
0366 void ModelDataLoader::databaseTracksAdded(const ListTrackDataType &newData)
0367 {
0368     switch(d->mFilterType) {
0369     case ModelDataLoader::FilterType::NoFilter:
0370         Q_EMIT tracksAdded(newData);
0371         break;
0372     case ModelDataLoader::FilterType::FilterById:
0373     {
0374         auto filteredData = newData;
0375 
0376         auto new_end = std::remove_if(filteredData.begin(), filteredData.end(),
0377                                       [&](const auto &oneTrack) { return oneTrack.albumId() != d->mDatabaseId; });
0378         filteredData.erase(new_end, filteredData.end());
0379 
0380         Q_EMIT tracksAdded(filteredData);
0381         break;
0382     }
0383     case ModelDataLoader::FilterType::FilterByGenre:
0384     case ModelDataLoader::FilterType::FilterByGenreAndArtist:
0385     case ModelDataLoader::FilterType::FilterByArtist:
0386     case ModelDataLoader::FilterType::FilterByRecentlyPlayed:
0387     case ModelDataLoader::FilterType::FilterByFrequentlyPlayed:
0388     case ModelDataLoader::FilterType::FilterByPath:
0389     case ModelDataLoader::FilterType::UnknownFilter:
0390         break;
0391     }
0392 }
0393 
0394 void ModelDataLoader::databaseArtistsAdded(const ListArtistDataType &newData)
0395 {
0396     switch(d->mFilterType) {
0397     case ModelDataLoader::FilterType::FilterByGenre:
0398     {
0399         auto filteredData = newData;
0400         auto new_end = std::remove_if(filteredData.begin(), filteredData.end(),
0401                                       [&](const auto &oneArtist){return !d->mDatabase->internalArtistMatchGenre(oneArtist.databaseId(), d->mGenre);});
0402         filteredData.erase(new_end, filteredData.end());
0403 
0404         Q_EMIT artistsAdded(filteredData);
0405 
0406         break;
0407     }
0408     case ModelDataLoader::FilterType::NoFilter:
0409         Q_EMIT artistsAdded(newData);
0410         break;
0411     case ModelDataLoader::FilterType::FilterByGenreAndArtist:
0412     case ModelDataLoader::FilterType::FilterByArtist:
0413     case ModelDataLoader::FilterType::FilterById:
0414     case ModelDataLoader::FilterType::FilterByRecentlyPlayed:
0415     case ModelDataLoader::FilterType::FilterByFrequentlyPlayed:
0416     case ModelDataLoader::FilterType::FilterByPath:
0417     case ModelDataLoader::FilterType::UnknownFilter:
0418         break;
0419     }
0420 }
0421 
0422 void ModelDataLoader::databaseAlbumsAdded(const ListAlbumDataType &newData)
0423 {
0424     switch(d->mFilterType) {
0425     case ModelDataLoader::FilterType::FilterByArtist:
0426     {
0427         auto filteredData = newData;
0428         auto new_end = std::remove_if(filteredData.begin(), filteredData.end(),
0429                                       [&](const auto &oneAlbum){return oneAlbum.artist() != d->mArtist;});
0430         filteredData.erase(new_end, filteredData.end());
0431 
0432         Q_EMIT albumsAdded(filteredData);
0433 
0434         break;
0435     }
0436     case ModelDataLoader::FilterType::NoFilter:
0437         Q_EMIT albumsAdded(newData);
0438         break;
0439     case ModelDataLoader::FilterType::FilterByGenreAndArtist:
0440     {
0441         auto filteredData = newData;
0442         auto new_end = std::remove_if(filteredData.begin(), filteredData.end(),
0443                                       [&](const auto &oneAlbum){
0444                                         const auto &allGenres = oneAlbum.genres();
0445                                         return oneAlbum.artist() != d->mArtist || !allGenres.contains(d->mGenre);
0446                                       });
0447         filteredData.erase(new_end, filteredData.end());
0448 
0449         Q_EMIT albumsAdded(filteredData);
0450 
0451         break;
0452     }
0453     case ModelDataLoader::FilterType::FilterByGenre:
0454     case ModelDataLoader::FilterType::FilterById:
0455     case ModelDataLoader::FilterType::FilterByRecentlyPlayed:
0456     case ModelDataLoader::FilterType::FilterByFrequentlyPlayed:
0457     case ModelDataLoader::FilterType::FilterByPath:
0458     case ModelDataLoader::FilterType::UnknownFilter:
0459         break;
0460     }
0461 }
0462 
0463 void ModelDataLoader::trackHasBeenModified(ModelDataLoader::ListTrackDataType trackDataType, const QHash<QString, QUrl> &covers)
0464 {
0465     for(auto &oneTrack : trackDataType) {
0466         if (oneTrack.elementType() == ElisaUtils::Track) {
0467             d->mFileWriter.writeAllMetaDataToFile(oneTrack.resourceURI(), oneTrack);
0468 
0469             QFileInfo trackFile{oneTrack.resourceURI().toLocalFile()};
0470 
0471             oneTrack[DataTypes::FileModificationTime] = trackFile.fileTime(QFileDevice::FileModificationTime);
0472 
0473             erase_if(oneTrack, [](const auto &trackDataItr) {return trackDataItr->isNull();});
0474         }
0475     }
0476 
0477     Q_EMIT saveTrackModified(trackDataType, covers);
0478 }
0479 
0480 void ModelDataLoader::updateFileMetaData(const DataTypes::TrackDataType &trackDataType, const QUrl &url)
0481 {
0482     d->mFileWriter.writeAllMetaDataToFile(url, trackDataType);
0483 }
0484 
0485 void ModelDataLoader::updateSingleFileMetaData(const QUrl &url, DataTypes::ColumnsRoles role, const QVariant &data)
0486 {
0487     d->mFileWriter.writeSingleMetaDataToFile(url, role, data);
0488 }
0489 
0490 #include "moc_modeldataloader.cpp"