File indexing completed on 2024-05-05 04:50:33
0001 /* 0002 SPDX-FileCopyrightText: 2015 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr> 0003 0004 SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #include "datamodel.h" 0008 0009 #include "modeldataloader.h" 0010 #include "musiclistenersmanager.h" 0011 0012 #include "models/modelLogging.h" 0013 0014 #include <algorithm> 0015 0016 class DataModelPrivate 0017 { 0018 public: 0019 0020 DataModel::ListTrackDataType mAllTrackData; 0021 0022 DataModel::ListRadioDataType mAllRadiosData; 0023 0024 DataModel::ListAlbumDataType mAllAlbumData; 0025 0026 DataModel::ListArtistDataType mAllArtistData; 0027 0028 DataModel::ListGenreDataType mAllGenreData; 0029 0030 ModelDataLoader *mDataLoader = nullptr; 0031 0032 ElisaUtils::PlayListEntryType mModelType = ElisaUtils::Unknown; 0033 0034 ElisaUtils::FilterType mFilterType = ElisaUtils::UnknownFilter; 0035 0036 QString mArtist; 0037 0038 QString mAlbumTitle; 0039 0040 QString mAlbumArtist; 0041 0042 QString mGenre; 0043 0044 qulonglong mDatabaseId = 0; 0045 0046 bool mIsBusy = false; 0047 0048 }; 0049 0050 DataModel::DataModel(QObject *parent) : QAbstractListModel(parent), d(std::make_unique<DataModelPrivate>()) 0051 { 0052 d->mDataLoader = new ModelDataLoader; 0053 connect(this, &DataModel::destroyed, d->mDataLoader, &ModelDataLoader::deleteLater); 0054 } 0055 0056 DataModel::~DataModel() 0057 = default; 0058 0059 int DataModel::rowCount(const QModelIndex &parent) const 0060 { 0061 auto dataCount = 0; 0062 0063 if (parent.isValid()) { 0064 return dataCount; 0065 } 0066 0067 dataCount = d->mAllTrackData.size() + d->mAllAlbumData.size() + d->mAllArtistData.size() + d->mAllGenreData.size(); 0068 0069 return dataCount; 0070 } 0071 0072 QHash<int, QByteArray> DataModel::roleNames() const 0073 { 0074 auto roles = QAbstractListModel::roleNames(); 0075 0076 roles[static_cast<int>(DataTypes::ColumnsRoles::TitleRole)] = "title"; 0077 roles[static_cast<int>(DataTypes::ColumnsRoles::SecondaryTextRole)] = "secondaryText"; 0078 roles[static_cast<int>(DataTypes::ColumnsRoles::ImageUrlRole)] = "imageUrl"; 0079 roles[static_cast<int>(DataTypes::ColumnsRoles::MultipleImageUrlsRole)] = "multipleImageUrls"; 0080 roles[static_cast<int>(DataTypes::ColumnsRoles::DatabaseIdRole)] = "databaseId"; 0081 roles[static_cast<int>(DataTypes::ColumnsRoles::ElementTypeRole)] = "dataType"; 0082 roles[static_cast<int>(DataTypes::ColumnsRoles::ResourceRole)] = "url"; 0083 0084 roles[static_cast<int>(DataTypes::ColumnsRoles::ArtistRole)] = "artist"; 0085 roles[static_cast<int>(DataTypes::ColumnsRoles::AllArtistsRole)] = "allArtists"; 0086 roles[static_cast<int>(DataTypes::ColumnsRoles::HighestTrackRating)] = "highestTrackRating"; 0087 roles[static_cast<int>(DataTypes::ColumnsRoles::GenreRole)] = "genre"; 0088 0089 roles[static_cast<int>(DataTypes::ColumnsRoles::AlbumRole)] = "album"; 0090 roles[static_cast<int>(DataTypes::ColumnsRoles::AlbumArtistRole)] = "albumArtist"; 0091 roles[static_cast<int>(DataTypes::ColumnsRoles::StringDurationRole)] = "duration"; 0092 roles[static_cast<int>(DataTypes::ColumnsRoles::TrackNumberRole)] = "trackNumber"; 0093 roles[static_cast<int>(DataTypes::ColumnsRoles::DiscNumberRole)] = "discNumber"; 0094 roles[static_cast<int>(DataTypes::ColumnsRoles::RatingRole)] = "rating"; 0095 roles[static_cast<int>(DataTypes::ColumnsRoles::YearRole)] = "year"; 0096 roles[static_cast<int>(DataTypes::ColumnsRoles::IsSingleDiscAlbumRole)] = "isSingleDiscAlbum"; 0097 roles[static_cast<int>(DataTypes::ColumnsRoles::FullDataRole)] = "fullData"; 0098 roles[static_cast<int>(DataTypes::ColumnsRoles::HasChildrenRole)] = "hasChildren"; 0099 0100 return roles; 0101 } 0102 0103 Qt::ItemFlags DataModel::flags(const QModelIndex &index) const 0104 { 0105 if (!index.isValid()) { 0106 return Qt::NoItemFlags; 0107 } 0108 0109 return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 0110 } 0111 0112 QVariant DataModel::data(const QModelIndex &index, int role) const 0113 { 0114 auto result = QVariant(); 0115 0116 if (!index.isValid()) { 0117 return result; 0118 } 0119 0120 const auto dataCount = d->mModelType == ElisaUtils::Radio ? d->mAllRadiosData.size() : d->mAllTrackData.size() + d->mAllAlbumData.size() + d->mAllArtistData.size() + d->mAllGenreData.size(); 0121 0122 Q_ASSERT(index.isValid()); 0123 Q_ASSERT(index.column() == 0); 0124 Q_ASSERT(!index.parent().isValid()); 0125 Q_ASSERT(index.model() == this); 0126 Q_ASSERT(index.internalId() == 0); 0127 Q_ASSERT(index.row() >= 0 && index.row() < dataCount); 0128 0129 switch(role) 0130 { 0131 case Qt::DisplayRole: 0132 switch(d->mModelType) 0133 { 0134 case ElisaUtils::Track: 0135 result = d->mAllTrackData[index.row()][TrackDataType::key_type::TitleRole]; 0136 if (result.toString().isEmpty()) { 0137 result = d->mAllTrackData[index.row()][TrackDataType::key_type::ResourceRole].toUrl().fileName(); 0138 } 0139 break; 0140 case ElisaUtils::Album: 0141 result = d->mAllAlbumData[index.row()][AlbumDataType::key_type::TitleRole]; 0142 break; 0143 case ElisaUtils::Artist: 0144 result = d->mAllArtistData[index.row()][ArtistDataType::key_type::TitleRole]; 0145 break; 0146 case ElisaUtils::Genre: 0147 result = d->mAllGenreData[index.row()][GenreDataType::key_type::TitleRole]; 0148 break; 0149 case ElisaUtils::Radio: 0150 result = d->mAllRadiosData[index.row()][GenreDataType::key_type::TitleRole]; 0151 break; 0152 case ElisaUtils::Lyricist: 0153 case ElisaUtils::Composer: 0154 case ElisaUtils::FileName: 0155 case ElisaUtils::Container: 0156 case ElisaUtils::Unknown: 0157 case ElisaUtils::PlayList: 0158 break; 0159 } 0160 break; 0161 case DataTypes::ColumnsRoles::StringDurationRole: 0162 { 0163 switch (d->mModelType) 0164 { 0165 case ElisaUtils::Track: 0166 { 0167 auto trackDuration = d->mAllTrackData[index.row()][TrackDataType::key_type::DurationRole].toTime(); 0168 if (trackDuration.hour() == 0) { 0169 result = trackDuration.toString(QStringLiteral("mm:ss")); 0170 } else { 0171 result = trackDuration.toString(); 0172 } 0173 break; 0174 } 0175 case ElisaUtils::Album: 0176 case ElisaUtils::Artist: 0177 case ElisaUtils::Genre: 0178 case ElisaUtils::Lyricist: 0179 case ElisaUtils::Composer: 0180 case ElisaUtils::FileName: 0181 case ElisaUtils::Radio: 0182 case ElisaUtils::Container: 0183 case ElisaUtils::Unknown: 0184 case ElisaUtils::PlayList: 0185 break; 0186 } 0187 break; 0188 } 0189 case DataTypes::ColumnsRoles::IsSingleDiscAlbumRole: 0190 { 0191 switch (d->mModelType) 0192 { 0193 case ElisaUtils::Track: 0194 result = d->mAllTrackData[index.row()][TrackDataType::key_type::IsSingleDiscAlbumRole]; 0195 break; 0196 case ElisaUtils::Radio: 0197 result = false; 0198 break; 0199 case ElisaUtils::Album: 0200 result = d->mAllAlbumData[index.row()][AlbumDataType::key_type::IsSingleDiscAlbumRole]; 0201 break; 0202 case ElisaUtils::Artist: 0203 case ElisaUtils::Genre: 0204 case ElisaUtils::Lyricist: 0205 case ElisaUtils::Composer: 0206 case ElisaUtils::FileName: 0207 case ElisaUtils::Container: 0208 case ElisaUtils::Unknown: 0209 case ElisaUtils::PlayList: 0210 break; 0211 } 0212 break; 0213 } 0214 case DataTypes::ColumnsRoles::ArtistRole: 0215 { 0216 switch (d->mModelType) 0217 { 0218 case ElisaUtils::Track: 0219 { 0220 auto itArtist = d->mAllTrackData[index.row()].find(TrackDataType::key_type::ArtistRole); 0221 if (itArtist != d->mAllTrackData[index.row()].end()) { 0222 result = d->mAllTrackData[index.row()][TrackDataType::key_type::ArtistRole]; 0223 } else { 0224 result = d->mAllTrackData[index.row()][TrackDataType::key_type::AlbumArtistRole]; 0225 } 0226 break; 0227 } 0228 case ElisaUtils::Album: 0229 result = d->mAllAlbumData[index.row()][static_cast<AlbumDataType::key_type>(role)]; 0230 break; 0231 case ElisaUtils::Artist: 0232 result = d->mAllArtistData[index.row()][static_cast<ArtistDataType::key_type>(role)]; 0233 break; 0234 case ElisaUtils::Genre: 0235 result = d->mAllGenreData[index.row()][static_cast<GenreDataType::key_type>(role)]; 0236 break; 0237 case ElisaUtils::Radio: 0238 result = d->mAllRadiosData[index.row()][static_cast<TrackDataType::key_type>(role)]; 0239 break; 0240 case ElisaUtils::Lyricist: 0241 case ElisaUtils::Composer: 0242 case ElisaUtils::FileName: 0243 case ElisaUtils::Container: 0244 case ElisaUtils::Unknown: 0245 case ElisaUtils::PlayList: 0246 break; 0247 } 0248 break; 0249 } 0250 case DataTypes::ColumnsRoles::FullDataRole: 0251 switch (d->mModelType) 0252 { 0253 case ElisaUtils::Track: 0254 result = QVariant::fromValue(static_cast<DataTypes::MusicDataType>(d->mAllTrackData[index.row()])); 0255 break; 0256 case ElisaUtils::Radio: 0257 result = QVariant::fromValue(static_cast<DataTypes::MusicDataType>(d->mAllRadiosData[index.row()])); 0258 break; 0259 case ElisaUtils::Album: 0260 result = QVariant::fromValue(static_cast<DataTypes::MusicDataType>(d->mAllAlbumData[index.row()])); 0261 break; 0262 case ElisaUtils::Artist: 0263 result = QVariant::fromValue(static_cast<DataTypes::MusicDataType>(d->mAllArtistData[index.row()])); 0264 break; 0265 case ElisaUtils::Genre: 0266 result = QVariant::fromValue(static_cast<DataTypes::MusicDataType>(d->mAllGenreData[index.row()])); 0267 break; 0268 case ElisaUtils::Lyricist: 0269 case ElisaUtils::Composer: 0270 case ElisaUtils::FileName: 0271 case ElisaUtils::Container: 0272 case ElisaUtils::Unknown: 0273 case ElisaUtils::PlayList: 0274 break; 0275 } 0276 break; 0277 case DataTypes::ColumnsRoles::ResourceRole: 0278 { 0279 switch (d->mModelType) 0280 { 0281 case ElisaUtils::Track: 0282 case ElisaUtils::FileName: 0283 result = d->mAllTrackData[index.row()][TrackDataType::key_type::ResourceRole]; 0284 break; 0285 case ElisaUtils::Radio: 0286 result = d->mAllRadiosData[index.row()][TrackDataType::key_type::ResourceRole]; 0287 break; 0288 case ElisaUtils::Album: 0289 case ElisaUtils::Artist: 0290 case ElisaUtils::Genre: 0291 case ElisaUtils::Lyricist: 0292 case ElisaUtils::Composer: 0293 case ElisaUtils::Container: 0294 case ElisaUtils::Unknown: 0295 case ElisaUtils::PlayList: 0296 result = QUrl{}; 0297 break; 0298 } 0299 break; 0300 } 0301 case DataTypes::ColumnsRoles::HasChildrenRole: 0302 { 0303 switch (d->mModelType) 0304 { 0305 case ElisaUtils::Track: 0306 case ElisaUtils::FileName: 0307 case ElisaUtils::Radio: 0308 case ElisaUtils::Unknown: 0309 result = false; 0310 break; 0311 case ElisaUtils::Album: 0312 case ElisaUtils::Artist: 0313 case ElisaUtils::Genre: 0314 case ElisaUtils::Lyricist: 0315 case ElisaUtils::Composer: 0316 case ElisaUtils::Container: 0317 case ElisaUtils::PlayList: 0318 result = true; 0319 break; 0320 } 0321 break; 0322 } 0323 default: 0324 switch(d->mModelType) 0325 { 0326 case ElisaUtils::Track: 0327 result = d->mAllTrackData[index.row()][static_cast<TrackDataType::key_type>(role)]; 0328 break; 0329 case ElisaUtils::Album: 0330 result = d->mAllAlbumData[index.row()][static_cast<AlbumDataType::key_type>(role)]; 0331 break; 0332 case ElisaUtils::Artist: 0333 result = d->mAllArtistData[index.row()][static_cast<ArtistDataType::key_type>(role)]; 0334 break; 0335 case ElisaUtils::Genre: 0336 result = d->mAllGenreData[index.row()][static_cast<GenreDataType::key_type>(role)]; 0337 break; 0338 case ElisaUtils::Radio: 0339 result = d->mAllRadiosData[index.row()][static_cast<TrackDataType::key_type>(role)]; 0340 break; 0341 case ElisaUtils::Lyricist: 0342 case ElisaUtils::Composer: 0343 case ElisaUtils::FileName: 0344 case ElisaUtils::Container: 0345 case ElisaUtils::Unknown: 0346 case ElisaUtils::PlayList: 0347 break; 0348 } 0349 } 0350 0351 return result; 0352 } 0353 0354 QModelIndex DataModel::index(int row, int column, const QModelIndex &parent) const 0355 { 0356 auto result = QModelIndex(); 0357 0358 if (column != 0) { 0359 return result; 0360 } 0361 0362 if (parent.isValid()) { 0363 return result; 0364 } 0365 0366 result = createIndex(row, column); 0367 0368 return result; 0369 } 0370 0371 QModelIndex DataModel::parent(const QModelIndex &child) const 0372 { 0373 Q_UNUSED(child) 0374 0375 auto result = QModelIndex(); 0376 0377 return result; 0378 } 0379 0380 QString DataModel::title() const 0381 { 0382 return d->mAlbumTitle; 0383 } 0384 0385 QString DataModel::author() const 0386 { 0387 return d->mAlbumArtist; 0388 } 0389 0390 bool DataModel::isBusy() const 0391 { 0392 return d->mIsBusy; 0393 } 0394 0395 void DataModel::initializeByData(MusicListenersManager *manager, DatabaseInterface *database, 0396 ElisaUtils::PlayListEntryType modelType, ElisaUtils::FilterType filter, 0397 const DataTypes::DataType &dataFilter) 0398 { 0399 qCDebug(orgKdeElisaModel()) << "DataModel::initialize" << modelType << filter << dataFilter; 0400 0401 d->mDatabaseId = dataFilter[DataTypes::DatabaseIdRole].toULongLong(); 0402 d->mGenre = dataFilter[DataTypes::GenreRole].toString(); 0403 d->mArtist = dataFilter[DataTypes::ArtistRole].toString(); 0404 0405 initializeModel(manager, database, modelType, filter); 0406 } 0407 0408 void DataModel::setBusy(bool value) 0409 { 0410 if (d->mIsBusy == value) { 0411 return; 0412 } 0413 0414 d->mIsBusy = value; 0415 Q_EMIT isBusyChanged(); 0416 } 0417 0418 void DataModel::initializeModel(MusicListenersManager *manager, DatabaseInterface *database, 0419 ElisaUtils::PlayListEntryType modelType, DataModel::FilterType type) 0420 { 0421 d->mModelType = modelType; 0422 d->mFilterType = type; 0423 0424 if (manager) { 0425 manager->connectModel(d->mDataLoader); 0426 } 0427 0428 if (manager) { 0429 connectModel(manager->viewDatabase()); 0430 } else if (database) { 0431 connectModel(database); 0432 } else { 0433 return; 0434 } 0435 0436 switch(d->mFilterType) 0437 { 0438 case ElisaUtils::NoFilter: 0439 connect(this, &DataModel::needData, 0440 d->mDataLoader, &ModelDataLoader::loadData); 0441 break; 0442 case ElisaUtils::FilterById: 0443 connect(this, &DataModel::needDataById, 0444 d->mDataLoader, &ModelDataLoader::loadDataByAlbumId); 0445 break; 0446 case ElisaUtils::FilterByGenre: 0447 connect(this, &DataModel::needDataByGenre, 0448 d->mDataLoader, &ModelDataLoader::loadDataByGenre); 0449 break; 0450 case ElisaUtils::FilterByArtist: 0451 connect(this, &DataModel::needDataByArtist, 0452 d->mDataLoader, &ModelDataLoader::loadDataByArtist); 0453 break; 0454 case ElisaUtils::FilterByGenreAndArtist: 0455 connect(this, &DataModel::needDataByGenreAndArtist, 0456 d->mDataLoader, &ModelDataLoader::loadDataByGenreAndArtist); 0457 break; 0458 case ElisaUtils::FilterByRecentlyPlayed: 0459 connect(this, &DataModel::needRecentlyPlayedData, 0460 d->mDataLoader, &ModelDataLoader::loadRecentlyPlayedData); 0461 break; 0462 case ElisaUtils::FilterByFrequentlyPlayed: 0463 connect(this, &DataModel::needFrequentlyPlayedData, 0464 d->mDataLoader, &ModelDataLoader::loadFrequentlyPlayedData); 0465 break; 0466 case ElisaUtils::FilterByPath: 0467 case ElisaUtils::UnknownFilter: 0468 break; 0469 } 0470 0471 setBusy(true); 0472 0473 askModelData(); 0474 } 0475 0476 void DataModel::askModelData() 0477 { 0478 switch(d->mFilterType) 0479 { 0480 case ElisaUtils::NoFilter: 0481 Q_EMIT needData(d->mModelType); 0482 break; 0483 case ElisaUtils::FilterById: 0484 Q_EMIT needDataById(d->mModelType, d->mDatabaseId); 0485 break; 0486 case ElisaUtils::FilterByGenre: 0487 Q_EMIT needDataByGenre(d->mModelType, d->mGenre); 0488 break; 0489 case ElisaUtils::FilterByArtist: 0490 Q_EMIT needDataByArtist(d->mModelType, d->mArtist); 0491 break; 0492 case ElisaUtils::FilterByGenreAndArtist: 0493 Q_EMIT needDataByGenreAndArtist(d->mModelType, d->mGenre, d->mArtist); 0494 break; 0495 case ElisaUtils::FilterByRecentlyPlayed: 0496 Q_EMIT needRecentlyPlayedData(d->mModelType); 0497 break; 0498 case ElisaUtils::FilterByFrequentlyPlayed: 0499 Q_EMIT needFrequentlyPlayedData(d->mModelType); 0500 break; 0501 case ElisaUtils::FilterByPath: 0502 case ElisaUtils::UnknownFilter: 0503 break; 0504 } 0505 } 0506 0507 int DataModel::indexFromId(qulonglong id) const 0508 { 0509 int result; 0510 DataModel::ListTrackDataType mAllData = d->mModelType == ElisaUtils::Radio ? d->mAllRadiosData: d->mAllTrackData; 0511 0512 for (result = 0; result < mAllData.size(); ++result) { 0513 if (mAllData[result].databaseId() == id) { 0514 return result; 0515 } 0516 } 0517 0518 result = -1; 0519 0520 return result; 0521 } 0522 0523 void DataModel::connectModel(DatabaseInterface *database) 0524 { 0525 d->mDataLoader->setDatabase(database); 0526 0527 connect(d->mDataLoader, &ModelDataLoader::allTracksData, 0528 this, &DataModel::tracksAdded); 0529 connect(d->mDataLoader, &ModelDataLoader::allRadiosData, 0530 this, &DataModel::radiosAdded); 0531 connect(d->mDataLoader, &ModelDataLoader::allAlbumsData, 0532 this, &DataModel::albumsAdded); 0533 connect(d->mDataLoader, &ModelDataLoader::allArtistsData, 0534 this, &DataModel::artistsAdded); 0535 connect(d->mDataLoader, &ModelDataLoader::allGenresData, 0536 this, &DataModel::genresAdded); 0537 connect(d->mDataLoader, &ModelDataLoader::genresAdded, 0538 this, &DataModel::genresAdded); 0539 connect(d->mDataLoader, &ModelDataLoader::albumsAdded, 0540 this, &DataModel::albumsAdded); 0541 connect(d->mDataLoader, &ModelDataLoader::albumModified, 0542 this, &DataModel::albumModified); 0543 connect(d->mDataLoader, &ModelDataLoader::albumRemoved, 0544 this, &DataModel::albumRemoved); 0545 connect(d->mDataLoader, &ModelDataLoader::tracksAdded, 0546 this, &DataModel::tracksAdded); 0547 connect(d->mDataLoader, &ModelDataLoader::trackModified, 0548 this, &DataModel::trackModified); 0549 connect(d->mDataLoader, &ModelDataLoader::trackRemoved, 0550 this, &DataModel::trackRemoved); 0551 connect(d->mDataLoader, &ModelDataLoader::artistsAdded, 0552 this, &DataModel::artistsAdded); 0553 connect(d->mDataLoader, &ModelDataLoader::artistRemoved, 0554 this, &DataModel::artistRemoved); 0555 connect(d->mDataLoader, &ModelDataLoader::radioAdded, 0556 this, &DataModel::radioAdded); 0557 connect(d->mDataLoader, &ModelDataLoader::radioModified, 0558 this, &DataModel::radioModified); 0559 connect(d->mDataLoader, &ModelDataLoader::radioRemoved, 0560 this, &DataModel::radioRemoved); 0561 connect(d->mDataLoader, &ModelDataLoader::clearedDatabase, 0562 this, &DataModel::cleanedDatabase); 0563 } 0564 0565 void DataModel::tracksAdded(ListTrackDataType newData) 0566 { 0567 if (newData.isEmpty() && d->mModelType == ElisaUtils::Track) { 0568 setBusy(false); 0569 } 0570 0571 if (newData.isEmpty() || d->mModelType != ElisaUtils::Track) { 0572 return; 0573 } 0574 0575 if (d->mFilterType == ElisaUtils::FilterById && !d->mAllTrackData.isEmpty()) { 0576 for (const auto &newTrack : newData) { 0577 auto trackIndex = indexFromId(newTrack.databaseId()); 0578 0579 if (trackIndex != -1) { 0580 continue; 0581 } 0582 0583 bool trackInserted = false; 0584 for (int trackIndex = 0; trackIndex < d->mAllTrackData.count(); ++trackIndex) { 0585 const auto &oneTrack = d->mAllTrackData[trackIndex]; 0586 0587 if (oneTrack.discNumber() >= newTrack.discNumber() && oneTrack.trackNumber() > newTrack.trackNumber()) { 0588 beginInsertRows({}, trackIndex, trackIndex); 0589 d->mAllTrackData.insert(trackIndex, newTrack); 0590 endInsertRows(); 0591 0592 if (d->mAllTrackData.size() == 1) { 0593 setBusy(false); 0594 } 0595 0596 trackInserted = true; 0597 break; 0598 } 0599 } 0600 0601 if (!trackInserted) { 0602 beginInsertRows({}, d->mAllTrackData.count(), d->mAllTrackData.count()); 0603 d->mAllTrackData.insert(d->mAllTrackData.count(), newTrack); 0604 endInsertRows(); 0605 0606 if (d->mAllTrackData.size() == 1) { 0607 setBusy(false); 0608 } 0609 } 0610 } 0611 } else { 0612 if (d->mAllTrackData.isEmpty()) { 0613 beginInsertRows({}, 0, newData.size() - 1); 0614 d->mAllTrackData.swap(newData); 0615 endInsertRows(); 0616 0617 setBusy(false); 0618 } else { 0619 beginInsertRows({}, d->mAllTrackData.size(), d->mAllTrackData.size() + newData.size() - 1); 0620 d->mAllTrackData.append(newData); 0621 endInsertRows(); 0622 } 0623 } 0624 } 0625 0626 void DataModel::radiosAdded(ListRadioDataType newData) 0627 { 0628 if (newData.isEmpty() && d->mModelType == ElisaUtils::Radio) { 0629 setBusy(false); 0630 } 0631 0632 if (newData.isEmpty() || d->mModelType != ElisaUtils::Radio) { 0633 return; 0634 } 0635 0636 if (d->mFilterType == ElisaUtils::FilterById && !d->mAllRadiosData.isEmpty()) { 0637 for (const auto &newTrack : newData) { 0638 auto trackIndex = indexFromId(newTrack.databaseId()); 0639 0640 if (trackIndex != -1) { 0641 continue; 0642 } 0643 0644 bool trackInserted = false; 0645 for (int trackIndex = 0; trackIndex < d->mAllRadiosData.count(); ++trackIndex) { 0646 const auto &oneTrack = d->mAllRadiosData[trackIndex]; 0647 0648 if (oneTrack.trackNumber() > newTrack.trackNumber()) { 0649 beginInsertRows({}, trackIndex, trackIndex); 0650 d->mAllRadiosData.insert(trackIndex, newTrack); 0651 endInsertRows(); 0652 0653 if (d->mAllRadiosData.size() == 1) { 0654 setBusy(false); 0655 } 0656 0657 trackInserted = true; 0658 break; 0659 } 0660 } 0661 0662 if (!trackInserted) { 0663 beginInsertRows({}, d->mAllRadiosData.count(), d->mAllRadiosData.count()); 0664 d->mAllRadiosData.insert(d->mAllRadiosData.count(), newTrack); 0665 endInsertRows(); 0666 0667 if (d->mAllRadiosData.size() == 1) { 0668 setBusy(false); 0669 } 0670 } 0671 } 0672 } else { 0673 if (d->mAllRadiosData.isEmpty()) { 0674 beginInsertRows({}, 0, newData.size() - 1); 0675 d->mAllRadiosData.swap(newData); 0676 endInsertRows(); 0677 0678 setBusy(false); 0679 } else { 0680 beginInsertRows({}, d->mAllRadiosData.size(), d->mAllRadiosData.size() + newData.size() - 1); 0681 d->mAllRadiosData.append(newData); 0682 endInsertRows(); 0683 } 0684 } 0685 } 0686 0687 void DataModel::trackModified(const TrackDataType &modifiedTrack) 0688 { 0689 if (d->mModelType != ElisaUtils::Track) { 0690 return; 0691 } 0692 0693 if (!d->mAlbumTitle.isEmpty() && !d->mAlbumArtist.isEmpty()) { 0694 if (modifiedTrack.album() != d->mAlbumTitle) { 0695 return; 0696 } 0697 0698 auto trackIndex = indexFromId(modifiedTrack.databaseId()); 0699 0700 if (trackIndex == -1) { 0701 return; 0702 } 0703 0704 d->mAllTrackData[trackIndex] = modifiedTrack; 0705 Q_EMIT dataChanged(index(trackIndex, 0), index(trackIndex, 0)); 0706 } else { 0707 auto itTrack = std::find_if(d->mAllTrackData.begin(), d->mAllTrackData.end(), 0708 [modifiedTrack](auto track) { 0709 return track.databaseId() == modifiedTrack.databaseId(); 0710 }); 0711 0712 if (itTrack == d->mAllTrackData.end()) { 0713 return; 0714 } 0715 0716 auto position = itTrack - d->mAllTrackData.begin(); 0717 0718 d->mAllTrackData[position] = modifiedTrack; 0719 0720 Q_EMIT dataChanged(index(position, 0), index(position, 0)); 0721 } 0722 } 0723 0724 void DataModel::radioModified(const TrackDataType &modifiedRadio) 0725 { 0726 if (d->mModelType != ElisaUtils::Radio) { 0727 return; 0728 } 0729 0730 auto trackIndex = indexFromId(modifiedRadio.databaseId()); 0731 0732 if (trackIndex == -1) { 0733 return; 0734 } 0735 0736 d->mAllRadiosData[trackIndex] = modifiedRadio; 0737 Q_EMIT dataChanged(index(trackIndex, 0), index(trackIndex, 0)); 0738 } 0739 0740 void DataModel::trackRemoved(qulonglong removedTrackId) 0741 { 0742 if (d->mModelType != ElisaUtils::Track) { 0743 return; 0744 } 0745 0746 if (!d->mAlbumTitle.isEmpty() && !d->mAlbumArtist.isEmpty()) { 0747 auto trackIndex = indexFromId(removedTrackId); 0748 0749 if (trackIndex == -1) { 0750 return; 0751 } 0752 0753 beginRemoveRows({}, trackIndex, trackIndex); 0754 d->mAllTrackData.removeAt(trackIndex); 0755 endRemoveRows(); 0756 } else { 0757 const auto itTrack = std::find_if(d->mAllTrackData.cbegin(), d->mAllTrackData.cend(), 0758 [removedTrackId](auto track) {return track.databaseId() == removedTrackId;}); 0759 0760 if (itTrack == d->mAllTrackData.cend()) { 0761 return; 0762 } 0763 0764 auto position = itTrack - d->mAllTrackData.cbegin(); 0765 0766 beginRemoveRows({}, position, position); 0767 d->mAllTrackData.erase(itTrack); 0768 endRemoveRows(); 0769 } 0770 } 0771 0772 void DataModel::radioRemoved(qulonglong removedRadioId) 0773 { 0774 if (d->mModelType != ElisaUtils::Radio) { 0775 return; 0776 } 0777 0778 0779 const auto itRadio = std::find_if(d->mAllRadiosData.cbegin(), d->mAllRadiosData.cend(), 0780 [removedRadioId](auto track) {return track.databaseId() == removedRadioId;}); 0781 0782 if (itRadio == d->mAllRadiosData.cend()) { 0783 return; 0784 } 0785 0786 auto position = itRadio - d->mAllRadiosData.cbegin(); 0787 0788 beginRemoveRows({}, position, position); 0789 d->mAllRadiosData.erase(itRadio); 0790 endRemoveRows(); 0791 } 0792 0793 void DataModel::radioAdded(const DataModel::TrackDataType &radioData) 0794 { 0795 if (d->mModelType != ElisaUtils::Radio) { 0796 return; 0797 } 0798 0799 ListRadioDataType list; 0800 list.append(radioData); 0801 radiosAdded(list); 0802 } 0803 0804 void DataModel::removeRadios() 0805 { 0806 if (d->mModelType != ElisaUtils::Radio) { 0807 return; 0808 } 0809 0810 beginRemoveRows({}, 0, d->mAllRadiosData.size()); 0811 d->mAllRadiosData.clear(); 0812 endRemoveRows(); 0813 } 0814 0815 void DataModel::genresAdded(DataModel::ListGenreDataType newData) 0816 { 0817 if (newData.isEmpty() && d->mModelType == ElisaUtils::Genre) { 0818 setBusy(false); 0819 } 0820 0821 if (newData.isEmpty() || d->mModelType != ElisaUtils::Genre) { 0822 return; 0823 } 0824 0825 if (d->mAllGenreData.isEmpty()) { 0826 beginInsertRows({}, d->mAllGenreData.size(), newData.size() - 1); 0827 d->mAllGenreData.swap(newData); 0828 endInsertRows(); 0829 0830 setBusy(false); 0831 } else { 0832 beginInsertRows({}, d->mAllGenreData.size(), d->mAllGenreData.size() + newData.size() - 1); 0833 d->mAllGenreData.append(newData); 0834 endInsertRows(); 0835 } 0836 } 0837 0838 void DataModel::artistsAdded(DataModel::ListArtistDataType newData) 0839 { 0840 if (newData.isEmpty() && d->mModelType == ElisaUtils::Artist) { 0841 setBusy(false); 0842 } 0843 0844 if (newData.isEmpty() || d->mModelType != ElisaUtils::Artist) { 0845 return; 0846 } 0847 0848 if (d->mAllArtistData.isEmpty()) { 0849 beginInsertRows({}, d->mAllArtistData.size(), newData.size() - 1); 0850 d->mAllArtistData.swap(newData); 0851 endInsertRows(); 0852 0853 setBusy(false); 0854 } else { 0855 beginInsertRows({}, d->mAllArtistData.size(), d->mAllArtistData.size() + newData.size() - 1); 0856 d->mAllArtistData.append(newData); 0857 endInsertRows(); 0858 } 0859 } 0860 0861 void DataModel::artistRemoved(qulonglong removedDatabaseId) 0862 { 0863 if (d->mModelType != ElisaUtils::Artist) { 0864 return; 0865 } 0866 0867 const auto removedDataIterator = std::find_if(d->mAllArtistData.cbegin(), d->mAllArtistData.cend(), 0868 [removedDatabaseId](auto album) {return album.databaseId() == removedDatabaseId;}); 0869 0870 if (removedDataIterator == d->mAllArtistData.cend()) { 0871 return; 0872 } 0873 0874 int dataIndex = removedDataIterator - d->mAllArtistData.cbegin(); 0875 0876 beginRemoveRows({}, dataIndex, dataIndex); 0877 0878 d->mAllArtistData.erase(removedDataIterator); 0879 0880 endRemoveRows(); 0881 } 0882 0883 void DataModel::albumsAdded(DataModel::ListAlbumDataType newData) 0884 { 0885 if (newData.isEmpty() && d->mModelType == ElisaUtils::Album) { 0886 setBusy(false); 0887 } 0888 0889 if (newData.isEmpty() || d->mModelType != ElisaUtils::Album) { 0890 return; 0891 } 0892 0893 if (d->mAllAlbumData.isEmpty()) { 0894 beginInsertRows({}, d->mAllAlbumData.size(), newData.size() - 1); 0895 d->mAllAlbumData.swap(newData); 0896 endInsertRows(); 0897 0898 setBusy(false); 0899 } else { 0900 beginInsertRows({}, d->mAllAlbumData.size(), d->mAllAlbumData.size() + newData.size() - 1); 0901 d->mAllAlbumData.append(newData); 0902 endInsertRows(); 0903 } 0904 } 0905 0906 void DataModel::albumRemoved(qulonglong removedDatabaseId) 0907 { 0908 if (d->mModelType != ElisaUtils::Album) { 0909 return; 0910 } 0911 0912 auto removedDataIterator = d->mAllAlbumData.cend(); 0913 0914 removedDataIterator = std::find_if(d->mAllAlbumData.cbegin(), d->mAllAlbumData.cend(), 0915 [removedDatabaseId](auto album) {return album.databaseId() == removedDatabaseId;}); 0916 0917 if (removedDataIterator == d->mAllAlbumData.cend()) { 0918 return; 0919 } 0920 0921 int dataIndex = removedDataIterator - d->mAllAlbumData.cbegin(); 0922 0923 beginRemoveRows({}, dataIndex, dataIndex); 0924 0925 d->mAllAlbumData.erase(removedDataIterator); 0926 0927 endRemoveRows(); 0928 } 0929 0930 void DataModel::albumModified(const DataModel::AlbumDataType &modifiedAlbum) 0931 { 0932 if (d->mModelType != ElisaUtils::Album) { 0933 return; 0934 } 0935 0936 auto modifiedAlbumIterator = std::find_if(d->mAllAlbumData.begin(), d->mAllAlbumData.end(), 0937 [modifiedAlbum](auto album) { 0938 return album.databaseId() == modifiedAlbum.databaseId(); 0939 }); 0940 0941 if (modifiedAlbumIterator == d->mAllAlbumData.end()) { 0942 return; 0943 } 0944 0945 auto albumIndex = modifiedAlbumIterator - d->mAllAlbumData.begin(); 0946 0947 Q_EMIT dataChanged(index(albumIndex, 0), index(albumIndex, 0)); 0948 } 0949 0950 void DataModel::initialize(MusicListenersManager *manager, DatabaseInterface *database, 0951 ElisaUtils::PlayListEntryType modelType, ElisaUtils::FilterType filter, 0952 const QString &genre, const QString &artist, qulonglong databaseId, 0953 const QUrl &pathFilter) 0954 { 0955 Q_UNUSED(pathFilter) 0956 0957 qCDebug(orgKdeElisaModel()) << "DataModel::initialize" << modelType << filter << databaseId << genre << artist; 0958 0959 d->mDatabaseId = databaseId; 0960 d->mGenre = genre; 0961 d->mArtist = artist; 0962 0963 initializeModel(manager, database, modelType, filter); 0964 } 0965 0966 void DataModel::cleanedDatabase() 0967 { 0968 beginResetModel(); 0969 d->mAllAlbumData.clear(); 0970 d->mAllGenreData.clear(); 0971 d->mAllTrackData.clear(); 0972 d->mAllArtistData.clear(); 0973 endResetModel(); 0974 } 0975 0976 #include "moc_datamodel.cpp"