File indexing completed on 2024-05-05 04:50:33

0001 /*
0002    SPDX-FileCopyrightText: 2020 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003 
0004    SPDX-License-Identifier: LGPL-3.0-or-later
0005  */
0006 
0007 #include "editabletrackmetadatamodel.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 
0012 EditableTrackMetadataModel::EditableTrackMetadataModel(QObject *parent)
0013     : TrackMetadataModel(parent)
0014 {
0015 }
0016 
0017 QVariant EditableTrackMetadataModel::data(const QModelIndex &index, int role) const
0018 {
0019     auto result = QVariant{};
0020 
0021     const auto currentKey = trackKey(index.row());
0022 
0023     switch (role)
0024     {
0025     case ReadOnlyRole:
0026         switch (currentKey)
0027         {
0028         case DataTypes::TitleRole:
0029             result = false;
0030             break;
0031         case DataTypes::ResourceRole:
0032             switch (allTrackData().elementType())
0033             {
0034             case ElisaUtils::Track:
0035                 result = true;
0036                 break;
0037             case ElisaUtils::Radio:
0038                 result = false;
0039                 break;
0040             case ElisaUtils::PlayList:
0041                 result = false;
0042                 break;
0043             case ElisaUtils::Album:
0044             case ElisaUtils::Artist:
0045             case ElisaUtils::Composer:
0046             case ElisaUtils::Container:
0047             case ElisaUtils::FileName:
0048             case ElisaUtils::Genre:
0049             case ElisaUtils::Lyricist:
0050             case ElisaUtils::Unknown:
0051                 result = true;
0052                 break;
0053             }
0054             break;
0055         case DataTypes::ImageUrlRole:
0056         case DataTypes::ArtistRole:
0057         case DataTypes::AlbumRole:
0058         case DataTypes::AlbumArtistRole:
0059         case DataTypes::TrackNumberRole:
0060         case DataTypes::DiscNumberRole:
0061         case DataTypes::RatingRole:
0062         case DataTypes::GenreRole:
0063         case DataTypes::LyricistRole:
0064         case DataTypes::ComposerRole:
0065         case DataTypes::CommentRole:
0066         case DataTypes::YearRole:
0067         case DataTypes::LyricsRole:
0068             result = false;
0069             break;
0070         case DataTypes::LastPlayDate:
0071         case DataTypes::PlayCounter:
0072         case DataTypes::DurationRole:
0073         case DataTypes::SampleRateRole:
0074         case DataTypes::BitRateRole:
0075         case DataTypes::ChannelsRole:
0076         case DataTypes::FirstPlayDate:
0077             result = true;
0078             break;
0079         case DataTypes::SecondaryTextRole:
0080         case DataTypes::ShadowForImageRole:
0081         case DataTypes::ChildModelRole:
0082         case DataTypes::StringDurationRole:
0083         case DataTypes::IsValidAlbumArtistRole:
0084         case DataTypes::AllArtistsRole:
0085         case DataTypes::HighestTrackRating:
0086         case DataTypes::IdRole:
0087         case DataTypes::ParentIdRole:
0088         case DataTypes::DatabaseIdRole:
0089         case DataTypes::IsSingleDiscAlbumRole:
0090         case DataTypes::ContainerDataRole:
0091         case DataTypes::IsPartialDataRole:
0092         case DataTypes::AlbumIdRole:
0093         case DataTypes::HasEmbeddedCover:
0094         case DataTypes::FileModificationTime:
0095         case DataTypes::ElementTypeRole:
0096         case DataTypes::FullDataRole:
0097         case DataTypes::IsDirectoryRole:
0098         case DataTypes::IsPlayListRole:
0099         case DataTypes::FilePathRole:
0100         case DataTypes::HasChildrenRole:
0101         case DataTypes::MultipleImageUrlsRole:
0102             break;
0103         }
0104         break;
0105     case RemovableFieldRole:
0106         switch (allTrackData().elementType())
0107         {
0108         case ElisaUtils::Track:
0109             switch (currentKey)
0110             {
0111             case DataTypes::TitleRole:
0112             case DataTypes::BitRateRole:
0113             case DataTypes::ChannelsRole:
0114             case DataTypes::ArtistRole:
0115             case DataTypes::AlbumRole:
0116             case DataTypes::AlbumArtistRole:
0117             case DataTypes::TrackNumberRole:
0118             case DataTypes::DiscNumberRole:
0119             case DataTypes::RatingRole:
0120             case DataTypes::GenreRole:
0121             case DataTypes::LyricistRole:
0122             case DataTypes::ComposerRole:
0123             case DataTypes::CommentRole:
0124             case DataTypes::YearRole:
0125             case DataTypes::LyricsRole:
0126             case DataTypes::SampleRateRole:
0127                 result = true;
0128                 break;
0129             case DataTypes::LastPlayDate:
0130             case DataTypes::PlayCounter:
0131             case DataTypes::ImageUrlRole:
0132             case DataTypes::DurationRole:
0133             case DataTypes::SecondaryTextRole:
0134             case DataTypes::ShadowForImageRole:
0135             case DataTypes::ChildModelRole:
0136             case DataTypes::StringDurationRole:
0137             case DataTypes::IsValidAlbumArtistRole:
0138             case DataTypes::AllArtistsRole:
0139             case DataTypes::HighestTrackRating:
0140             case DataTypes::IdRole:
0141             case DataTypes::ParentIdRole:
0142             case DataTypes::DatabaseIdRole:
0143             case DataTypes::IsSingleDiscAlbumRole:
0144             case DataTypes::ContainerDataRole:
0145             case DataTypes::IsPartialDataRole:
0146             case DataTypes::AlbumIdRole:
0147             case DataTypes::HasEmbeddedCover:
0148             case DataTypes::FileModificationTime:
0149             case DataTypes::FirstPlayDate:
0150             case DataTypes::ElementTypeRole:
0151             case DataTypes::FullDataRole:
0152             case DataTypes::IsDirectoryRole:
0153             case DataTypes::IsPlayListRole:
0154             case DataTypes::FilePathRole:
0155             case DataTypes::ResourceRole:
0156             case DataTypes::HasChildrenRole:
0157             case DataTypes::MultipleImageUrlsRole:
0158                 result = false;
0159                 break;
0160             }
0161             break;
0162         case ElisaUtils::Radio:
0163         case ElisaUtils::Album:
0164         case ElisaUtils::Artist:
0165         case ElisaUtils::Composer:
0166         case ElisaUtils::Container:
0167         case ElisaUtils::FileName:
0168         case ElisaUtils::Genre:
0169         case ElisaUtils::Lyricist:
0170         case ElisaUtils::Unknown:
0171         case ElisaUtils::PlayList:
0172             result = false;
0173             break;
0174         }
0175         break;
0176     default:
0177         result = TrackMetadataModel::data(index, role);
0178     }
0179 
0180     return result;
0181 }
0182 
0183 QHash<int, QByteArray> EditableTrackMetadataModel::roleNames() const
0184 {
0185     auto names = TrackMetadataModel::roleNames();
0186 
0187     names[EditableColumnRoles::ReadOnlyRole] = "isReadOnly";
0188     names[EditableColumnRoles::RemovableFieldRole] = "isRemovable";
0189 
0190     return names;
0191 }
0192 
0193 bool EditableTrackMetadataModel::setData(const QModelIndex &index, const QVariant &value, int role)
0194 {
0195     auto result = TrackMetadataModel::setData(index, value, role);
0196 
0197     if (result) {
0198         modelHasBeenModified();
0199         validData();
0200     }
0201 
0202     return result;
0203 }
0204 
0205 void EditableTrackMetadataModel::saveData()
0206 {
0207     saveChanges();
0208     mIsNewRadio = false;
0209     mIsDirty = false;
0210     Q_EMIT isDirtyChanged();
0211 
0212     auto newTrackData = allTrackData();
0213 
0214     newTrackData[DataTypes::ResourceRole] = QUrl::fromUserInput(newTrackData[DataTypes::ResourceRole].toString());
0215 
0216     QString imageUrl = dataFromType(DataTypes::ImageUrlRole).toString();
0217     if (!imageUrl.isEmpty()
0218             && !imageUrl.startsWith(QStringLiteral("http://"))
0219             && !imageUrl.startsWith(QStringLiteral("https://"))
0220             && !imageUrl.startsWith(QStringLiteral("file://"))) {
0221         newTrackData[DataTypes::ImageUrlRole] = QUrl::fromUserInput(QStringLiteral("file:/").append(imageUrl));
0222     }
0223 
0224     Q_EMIT saveTrackModified({newTrackData}, {});
0225 }
0226 
0227 void EditableTrackMetadataModel::resetData()
0228 {
0229     undoChanges();
0230     mIsDirty = false;
0231     Q_EMIT isDirtyChanged();
0232 }
0233 
0234 void EditableTrackMetadataModel::deleteRadio()
0235 {
0236     auto &track = displayedTrackData();
0237     if (track[DataTypes::DatabaseIdRole].toULongLong()) {
0238         Q_EMIT deleteRadioData(track[DataTypes::DatabaseIdRole].toULongLong());
0239     }
0240 }
0241 
0242 void EditableTrackMetadataModel::removeData(int index)
0243 {
0244     beginRemoveRows({}, index, index);
0245     removeDataByIndex(index);
0246     endRemoveRows();
0247 
0248     modelHasBeenModified();
0249 
0250     validData();
0251 
0252     updateExtraMetadata();
0253 }
0254 
0255 void EditableTrackMetadataModel::addData(const QString &name)
0256 {
0257     beginInsertRows({}, rowCount(), rowCount());
0258     addDataByName(name);
0259     endInsertRows();
0260 
0261     modelHasBeenModified();
0262     validData();
0263 
0264     updateExtraMetadata();
0265 }
0266 
0267 void EditableTrackMetadataModel::fillDataFromTrackData(const TrackMetadataModel::TrackDataType &trackData)
0268 {
0269     if (mIsNewRadio) {
0270         return;
0271     }
0272 
0273     TrackMetadataModel::fillDataFromTrackData(trackData);
0274 
0275     updateExtraMetadata();
0276 }
0277 
0278 void EditableTrackMetadataModel::filterDataFromTrackData()
0279 {
0280     TrackMetadataModel::filterDataFromTrackData();
0281     validData();
0282 }
0283 
0284 void EditableTrackMetadataModel::fillLyricsDataFromTrack()
0285 {
0286     TrackMetadataModel::fillLyricsDataFromTrack();
0287     validData();
0288 
0289     updateExtraMetadata();
0290 }
0291 
0292 void EditableTrackMetadataModel::fillDataForNewRadio()
0293 {
0294     mIsNewRadio = true;
0295     TrackMetadataModel::fillDataForNewRadio();
0296 }
0297 
0298 void EditableTrackMetadataModel::initialize(MusicListenersManager *newManager, DatabaseInterface *trackDatabase)
0299 {
0300     TrackMetadataModel::initialize(newManager, trackDatabase);
0301 
0302     connect(this, &EditableTrackMetadataModel::saveTrackModified,
0303             &modelDataLoader(), &ModelDataLoader::trackHasBeenModified);
0304     connect(this, &EditableTrackMetadataModel::deleteRadioData,
0305             &modelDataLoader(), &ModelDataLoader::removeRadio);
0306 }
0307 
0308 void EditableTrackMetadataModel::validData()
0309 {
0310     bool newValidState = true;
0311 
0312     const auto &resourceData = dataFromType(TrackDataType::key_type::ResourceRole);
0313     if (resourceData.canConvert<QUrl>()) {
0314         const auto resourceUrl = resourceData.toUrl();
0315 
0316         newValidState = !resourceUrl.scheme().isEmpty() && resourceUrl.isValid() && !resourceUrl.isRelative();
0317     } else {
0318         newValidState = false;
0319     }
0320 
0321     if (!newValidState) {
0322         mErrorMessage = i18nc("@info:status Error message when track URL is invalid", "Invalid URL.");
0323         Q_EMIT errorMessageChanged();
0324     }
0325 
0326     if (newValidState) {
0327         const auto &titleData = dataFromType(TrackDataType::key_type::TitleRole);
0328 
0329         newValidState = newValidState && !titleData.toString().isEmpty();
0330 
0331         if (!newValidState) {
0332             mErrorMessage = i18nc("@info:status Error message when track title is empty", "Empty title.");
0333             Q_EMIT errorMessageChanged();
0334         }
0335     }
0336 
0337     if (mIsDataValid != newValidState) {
0338         mIsDataValid = newValidState;
0339 
0340         Q_EMIT isDataValidChanged();
0341     }
0342 }
0343 
0344 void EditableTrackMetadataModel::updateExtraMetadata()
0345 {
0346     mExtraMetadata.clear();
0347     for(auto metadataRole : {DataTypes::TitleRole, DataTypes::ArtistRole,
0348                              DataTypes::AlbumRole, DataTypes::AlbumArtistRole, DataTypes::TrackNumberRole,
0349                              DataTypes::DiscNumberRole, DataTypes::RatingRole, DataTypes::GenreRole,
0350                              DataTypes::LyricistRole, DataTypes::ComposerRole, DataTypes::CommentRole,
0351                              DataTypes::YearRole, DataTypes::ChannelsRole, DataTypes::BitRateRole,
0352                              DataTypes::SampleRateRole, DataTypes::LyricsRole}) {
0353         if (!metadataExists(metadataRole)) {
0354             mExtraMetadata.push_back(nameFromRole(metadataRole));
0355         }
0356     }
0357 
0358     Q_EMIT extraMetadataChanged();
0359 }
0360 
0361 void EditableTrackMetadataModel::modelHasBeenModified()
0362 {
0363     if (!mIsDirty) {
0364         mIsDirty = true;
0365         Q_EMIT isDirtyChanged();
0366     }
0367 }
0368 
0369 
0370 #include "moc_editabletrackmetadatamodel.cpp"