Changeset View
Changeset View
Standalone View
Standalone View
src/models/trackmetadatamodel.cpp
Show All 15 Lines | |||||
16 | */ | 16 | */ | ||
17 | 17 | | |||
18 | #include "trackmetadatamodel.h" | 18 | #include "trackmetadatamodel.h" | ||
19 | 19 | | |||
20 | #include "musiclistenersmanager.h" | 20 | #include "musiclistenersmanager.h" | ||
21 | 21 | | |||
22 | #include <KI18n/KLocalizedString> | 22 | #include <KI18n/KLocalizedString> | ||
23 | 23 | | |||
24 | #include <QtConcurrent/QtConcurrentRun> | ||||
25 | | ||||
24 | TrackMetadataModel::TrackMetadataModel(QObject *parent) | 26 | TrackMetadataModel::TrackMetadataModel(QObject *parent) | ||
25 | : QAbstractListModel(parent) | 27 | : QAbstractListModel(parent) | ||
26 | { | 28 | { | ||
29 | connect(&mLyricsValueWatcher, &QFutureWatcher<QString>::finished, | ||||
30 | this, &TrackMetadataModel::lyricsValueIsReady); | ||||
31 | } | ||||
32 | | ||||
33 | TrackMetadataModel::~TrackMetadataModel() | ||||
34 | { | ||||
35 | if (mLyricsValueWatcher.isRunning() && !mLyricsValueWatcher.isFinished()) { | ||||
36 | mLyricsValueWatcher.waitForFinished(); | ||||
37 | } | ||||
27 | } | 38 | } | ||
28 | 39 | | |||
29 | int TrackMetadataModel::rowCount(const QModelIndex &parent) const | 40 | int TrackMetadataModel::rowCount(const QModelIndex &parent) const | ||
30 | { | 41 | { | ||
31 | if (parent.isValid()) { | 42 | if (parent.isValid()) { | ||
32 | return 0; | 43 | return 0; | ||
33 | } | 44 | } | ||
34 | 45 | | |||
Show All 10 Lines | 50 | { | |||
45 | { | 56 | { | ||
46 | case Qt::DisplayRole: | 57 | case Qt::DisplayRole: | ||
47 | result = mTrackData[currentKey]; | 58 | result = mTrackData[currentKey]; | ||
48 | break; | 59 | break; | ||
49 | case ItemNameRole: | 60 | case ItemNameRole: | ||
50 | switch (currentKey) | 61 | switch (currentKey) | ||
51 | { | 62 | { | ||
52 | case DatabaseInterface::TitleRole: | 63 | case DatabaseInterface::TitleRole: | ||
53 | result = i18nc("Track title for track metadata view", "Title:"); | 64 | result = i18nc("Track title for track metadata view", "Title"); | ||
54 | break; | 65 | break; | ||
55 | case DatabaseInterface::DurationRole: | 66 | case DatabaseInterface::DurationRole: | ||
56 | result = i18nc("Duration label for track metadata view", "Duration:"); | 67 | result = i18nc("Duration label for track metadata view", "Duration"); | ||
57 | break; | 68 | break; | ||
58 | case DatabaseInterface::ArtistRole: | 69 | case DatabaseInterface::ArtistRole: | ||
59 | result = i18nc("Track artist for track metadata view", "Artist:"); | 70 | result = i18nc("Track artist for track metadata view", "Artist"); | ||
60 | break; | 71 | break; | ||
61 | case DatabaseInterface::AlbumRole: | 72 | case DatabaseInterface::AlbumRole: | ||
62 | result = i18nc("Album name for track metadata view", "Album:"); | 73 | result = i18nc("Album name for track metadata view", "Album"); | ||
63 | break; | 74 | break; | ||
64 | case DatabaseInterface::AlbumArtistRole: | 75 | case DatabaseInterface::AlbumArtistRole: | ||
65 | result = i18nc("Album artist for track metadata view", "Album Artist:"); | 76 | result = i18nc("Album artist for track metadata view", "Album Artist"); | ||
66 | break; | 77 | break; | ||
67 | case DatabaseInterface::TrackNumberRole: | 78 | case DatabaseInterface::TrackNumberRole: | ||
68 | result = i18nc("Track number for track metadata view", "Track Number:"); | 79 | result = i18nc("Track number for track metadata view", "Track Number"); | ||
69 | break; | 80 | break; | ||
70 | case DatabaseInterface::DiscNumberRole: | 81 | case DatabaseInterface::DiscNumberRole: | ||
71 | result = i18nc("Disc number for track metadata view", "Disc Number:"); | 82 | result = i18nc("Disc number for track metadata view", "Disc Number"); | ||
72 | break; | 83 | break; | ||
73 | case DatabaseInterface::RatingRole: | 84 | case DatabaseInterface::RatingRole: | ||
74 | result = i18nc("Rating label for information panel", "Rating:"); | 85 | result = i18nc("Rating label for information panel", "Rating"); | ||
75 | break; | 86 | break; | ||
76 | case DatabaseInterface::GenreRole: | 87 | case DatabaseInterface::GenreRole: | ||
77 | result = i18nc("Genre label for track metadata view", "Genre:"); | 88 | result = i18nc("Genre label for track metadata view", "Genre"); | ||
78 | break; | 89 | break; | ||
79 | case DatabaseInterface::LyricistRole: | 90 | case DatabaseInterface::LyricistRole: | ||
80 | result = i18nc("Lyricist label for track metadata view", "Lyricist:"); | 91 | result = i18nc("Lyricist label for track metadata view", "Lyricist"); | ||
81 | break; | 92 | break; | ||
82 | case DatabaseInterface::ComposerRole: | 93 | case DatabaseInterface::ComposerRole: | ||
83 | result = i18nc("Composer name for track metadata view", "Composer:"); | 94 | result = i18nc("Composer name for track metadata view", "Composer"); | ||
84 | break; | 95 | break; | ||
85 | case DatabaseInterface::CommentRole: | 96 | case DatabaseInterface::CommentRole: | ||
86 | result = i18nc("Comment label for track metadata view", "Comment:"); | 97 | result = i18nc("Comment label for track metadata view", "Comment"); | ||
87 | break; | 98 | break; | ||
88 | case DatabaseInterface::YearRole: | 99 | case DatabaseInterface::YearRole: | ||
89 | result = i18nc("Year label for track metadata view", "Year:"); | 100 | result = i18nc("Year label for track metadata view", "Year"); | ||
90 | break; | 101 | break; | ||
91 | case DatabaseInterface::ChannelsRole: | 102 | case DatabaseInterface::ChannelsRole: | ||
92 | result = i18nc("Channels label for track metadata view", "Channels:"); | 103 | result = i18nc("Channels label for track metadata view", "Channels"); | ||
93 | break; | 104 | break; | ||
94 | case DatabaseInterface::BitRateRole: | 105 | case DatabaseInterface::BitRateRole: | ||
95 | result = i18nc("Bit rate label for track metadata view", "Bit Rate:"); | 106 | result = i18nc("Bit rate label for track metadata view", "Bit Rate"); | ||
96 | break; | 107 | break; | ||
97 | case DatabaseInterface::SampleRateRole: | 108 | case DatabaseInterface::SampleRateRole: | ||
98 | result = i18nc("Sample Rate label for track metadata view", "Sample Rate:"); | 109 | result = i18nc("Sample Rate label for track metadata view", "Sample Rate"); | ||
99 | break; | 110 | break; | ||
100 | case DatabaseInterface::LastPlayDate: | 111 | case DatabaseInterface::LastPlayDate: | ||
101 | result = i18nc("Last play date label for track metadata view", "Last played:"); | 112 | result = i18nc("Last play date label for track metadata view", "Last played"); | ||
102 | break; | 113 | break; | ||
103 | case DatabaseInterface::PlayCounter: | 114 | case DatabaseInterface::PlayCounter: | ||
104 | result = i18nc("Play counter label for track metadata view", "Play count:"); | 115 | result = i18nc("Play counter label for track metadata view", "Play count"); | ||
116 | break; | ||||
117 | case DatabaseInterface::LyricsRole: | ||||
118 | result = i18nc("Lyrics label for track metadata view", "Lyrics"); | ||||
105 | break; | 119 | break; | ||
106 | case DatabaseInterface::SecondaryTextRole: | 120 | case DatabaseInterface::SecondaryTextRole: | ||
107 | case DatabaseInterface::ImageUrlRole: | 121 | case DatabaseInterface::ImageUrlRole: | ||
108 | case DatabaseInterface::ShadowForImageRole: | 122 | case DatabaseInterface::ShadowForImageRole: | ||
109 | case DatabaseInterface::ChildModelRole: | 123 | case DatabaseInterface::ChildModelRole: | ||
110 | case DatabaseInterface::StringDurationRole: | 124 | case DatabaseInterface::StringDurationRole: | ||
111 | case DatabaseInterface::MilliSecondsDurationRole: | 125 | case DatabaseInterface::MilliSecondsDurationRole: | ||
112 | case DatabaseInterface::AllArtistsRole: | 126 | case DatabaseInterface::AllArtistsRole: | ||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | 179 | case DatabaseInterface::YearRole: | |||
166 | result = IntegerEntry; | 180 | result = IntegerEntry; | ||
167 | break; | 181 | break; | ||
168 | case DatabaseInterface::LastPlayDate: | 182 | case DatabaseInterface::LastPlayDate: | ||
169 | result = DateEntry; | 183 | result = DateEntry; | ||
170 | break; | 184 | break; | ||
171 | case DatabaseInterface::PlayCounter: | 185 | case DatabaseInterface::PlayCounter: | ||
172 | result = IntegerEntry; | 186 | result = IntegerEntry; | ||
173 | break; | 187 | break; | ||
188 | case DatabaseInterface::LyricsRole: | ||||
189 | result = LongTextEntry; | ||||
190 | break; | ||||
174 | case DatabaseInterface::DurationRole: | 191 | case DatabaseInterface::DurationRole: | ||
175 | case DatabaseInterface::SampleRateRole: | 192 | case DatabaseInterface::SampleRateRole: | ||
176 | case DatabaseInterface::BitRateRole: | 193 | case DatabaseInterface::BitRateRole: | ||
177 | case DatabaseInterface::ChannelsRole: | 194 | case DatabaseInterface::ChannelsRole: | ||
178 | case DatabaseInterface::SecondaryTextRole: | 195 | case DatabaseInterface::SecondaryTextRole: | ||
179 | case DatabaseInterface::ImageUrlRole: | 196 | case DatabaseInterface::ImageUrlRole: | ||
180 | case DatabaseInterface::ShadowForImageRole: | 197 | case DatabaseInterface::ShadowForImageRole: | ||
181 | case DatabaseInterface::ChildModelRole: | 198 | case DatabaseInterface::ChildModelRole: | ||
Show All 36 Lines | 234 | { | |||
218 | auto names = QAbstractListModel::roleNames(); | 235 | auto names = QAbstractListModel::roleNames(); | ||
219 | 236 | | |||
220 | names[ItemNameRole] = "name"; | 237 | names[ItemNameRole] = "name"; | ||
221 | names[ItemTypeRole] = "type"; | 238 | names[ItemTypeRole] = "type"; | ||
222 | 239 | | |||
223 | return names; | 240 | return names; | ||
224 | } | 241 | } | ||
225 | 242 | | |||
226 | Qt::ItemFlags TrackMetadataModel::flags(const QModelIndex &index) const | | |||
227 | { | | |||
228 | if (!index.isValid()) | | |||
229 | return Qt::NoItemFlags; | | |||
230 | | ||||
231 | return Qt::ItemIsEditable | QAbstractListModel::flags(index); | | |||
232 | } | | |||
233 | | ||||
234 | QString TrackMetadataModel::fileUrl() const | 243 | QString TrackMetadataModel::fileUrl() const | ||
235 | { | 244 | { | ||
236 | return mFileUrl; | 245 | return mFileUrl; | ||
237 | } | 246 | } | ||
238 | 247 | | |||
239 | bool TrackMetadataModel::insertRows(int row, int count, const QModelIndex &parent) | 248 | const QUrl &TrackMetadataModel::coverUrl() const | ||
240 | { | 249 | { | ||
241 | beginInsertRows(parent, row, row + count - 1); | 250 | return mCoverImage; | ||
242 | endInsertRows(); | | |||
243 | | ||||
244 | return true; | | |||
245 | } | 251 | } | ||
246 | 252 | | |||
247 | bool TrackMetadataModel::removeRows(int row, int count, const QModelIndex &parent) | 253 | MusicListenersManager *TrackMetadataModel::manager() const | ||
248 | { | 254 | { | ||
249 | beginRemoveRows(parent, row, row + count - 1); | 255 | return mManager; | ||
250 | endRemoveRows(); | | |||
251 | | ||||
252 | return true; | | |||
253 | } | 256 | } | ||
254 | 257 | | |||
255 | const QUrl &TrackMetadataModel::coverUrl() const | 258 | void TrackMetadataModel::trackData(const TrackMetadataModel::TrackDataType &trackData) | ||
256 | { | 259 | { | ||
257 | return mCoverImage; | 260 | if (!mFullData.isEmpty() && trackData.databaseId() != mFullData.databaseId()) { | ||
261 | return; | ||||
258 | } | 262 | } | ||
259 | 263 | | |||
260 | void TrackMetadataModel::trackData(const TrackMetadataModel::TrackDataType &trackData) | 264 | fillDataFromTrackData(trackData); | ||
265 | } | ||||
266 | | ||||
267 | void TrackMetadataModel::fillDataFromTrackData(const TrackMetadataModel::TrackDataType &trackData) | ||||
261 | { | 268 | { | ||
262 | beginResetModel(); | 269 | beginResetModel(); | ||
263 | if (mTrackData.isValid()) { | 270 | mFullData = trackData; | ||
264 | mTrackData.clear(); | 271 | mTrackData.clear(); | ||
265 | mTrackKeys.clear(); | 272 | mTrackKeys.clear(); | ||
266 | } | | |||
267 | 273 | | |||
268 | for (auto role : {DatabaseInterface::TitleRole, DatabaseInterface::ArtistRole, DatabaseInterface::AlbumRole, | 274 | for (auto role : {DatabaseInterface::TitleRole, DatabaseInterface::ArtistRole, DatabaseInterface::AlbumRole, | ||
269 | DatabaseInterface::AlbumArtistRole, DatabaseInterface::TrackNumberRole, DatabaseInterface::DiscNumberRole, | 275 | DatabaseInterface::AlbumArtistRole, DatabaseInterface::TrackNumberRole, DatabaseInterface::DiscNumberRole, | ||
270 | DatabaseInterface::RatingRole, DatabaseInterface::GenreRole, DatabaseInterface::LyricistRole, | 276 | DatabaseInterface::RatingRole, DatabaseInterface::GenreRole, DatabaseInterface::LyricistRole, | ||
271 | DatabaseInterface::ComposerRole, DatabaseInterface::CommentRole, DatabaseInterface::YearRole, | 277 | DatabaseInterface::ComposerRole, DatabaseInterface::CommentRole, DatabaseInterface::YearRole, | ||
272 | DatabaseInterface::LastPlayDate, DatabaseInterface::PlayCounter}) { | 278 | DatabaseInterface::LastPlayDate, DatabaseInterface::PlayCounter}) { | ||
273 | if (trackData.constFind(role) != trackData.constEnd()) { | 279 | if (trackData.constFind(role) != trackData.constEnd()) { | ||
274 | if (role == DatabaseInterface::RatingRole) { | 280 | if (role == DatabaseInterface::RatingRole) { | ||
275 | if (trackData[role].toInt() == 0) { | 281 | if (trackData[role].toInt() == 0) { | ||
276 | continue; | 282 | continue; | ||
277 | } | 283 | } | ||
278 | } | 284 | } | ||
279 | 285 | | |||
280 | mTrackKeys.push_back(role); | 286 | mTrackKeys.push_back(role); | ||
281 | mTrackData[role] = trackData[role]; | 287 | mTrackData[role] = trackData[role]; | ||
282 | } | 288 | } | ||
283 | } | 289 | } | ||
290 | filterDataFromTrackData(); | ||||
284 | endResetModel(); | 291 | endResetModel(); | ||
285 | 292 | | |||
293 | fetchLyrics(); | ||||
294 | | ||||
286 | mCoverImage = trackData[DatabaseInterface::ImageUrlRole].toUrl(); | 295 | mCoverImage = trackData[DatabaseInterface::ImageUrlRole].toUrl(); | ||
287 | Q_EMIT coverUrlChanged(); | 296 | Q_EMIT coverUrlChanged(); | ||
288 | 297 | | |||
289 | auto rawFileUrl = trackData[DatabaseInterface::ResourceRole].toUrl(); | 298 | auto rawFileUrl = trackData[DatabaseInterface::ResourceRole].toUrl(); | ||
290 | 299 | | |||
291 | if (rawFileUrl.isLocalFile()) { | 300 | if (rawFileUrl.isLocalFile()) { | ||
292 | mFileUrl = rawFileUrl.toLocalFile(); | 301 | mFileUrl = rawFileUrl.toLocalFile(); | ||
293 | } else { | 302 | } else { | ||
294 | mFileUrl = rawFileUrl.toString(); | 303 | mFileUrl = rawFileUrl.toString(); | ||
295 | } | 304 | } | ||
296 | Q_EMIT fileUrlChanged(); | 305 | Q_EMIT fileUrlChanged(); | ||
297 | } | 306 | } | ||
298 | 307 | | |||
299 | void TrackMetadataModel::initializeByTrackId(MusicListenersManager *manager, qulonglong databaseId) | 308 | void TrackMetadataModel::filterDataFromTrackData() | ||
300 | { | 309 | { | ||
301 | mDataLoader.setDatabase(manager->viewDatabase()); | 310 | } | ||
302 | manager->connectModel(&mDataLoader); | | |||
303 | 311 | | |||
304 | connect(this, &TrackMetadataModel::needDataByDatabaseId, | 312 | void TrackMetadataModel::removeMetaData(DatabaseInterface::ColumnsRoles metaData) | ||
305 | &mDataLoader, &ModelDataLoader::loadDataByDatabaseId); | 313 | { | ||
306 | connect(&mDataLoader, &ModelDataLoader::allTrackData, | 314 | auto itMetaData = std::find(mTrackKeys.begin(), mTrackKeys.end(), metaData); | ||
307 | this, &TrackMetadataModel::trackData); | 315 | if (itMetaData == mTrackKeys.end()) { | ||
316 | return; | ||||
317 | } | ||||
308 | 318 | | |||
309 | Q_EMIT needDataByDatabaseId(ElisaUtils::Track, databaseId); | 319 | mTrackKeys.erase(itMetaData); | ||
320 | mTrackData.remove(metaData); | ||||
321 | } | ||||
322 | | ||||
323 | TrackMetadataModel::TrackDataType::mapped_type TrackMetadataModel::dataFromType(TrackDataType::key_type metaData) const | ||||
324 | { | ||||
325 | return mFullData[metaData]; | ||||
310 | } | 326 | } | ||
311 | 327 | | |||
312 | void TrackMetadataModel::initializeByTrackFileName(MusicListenersManager *manager, const QUrl &fileName) | 328 | void TrackMetadataModel::lyricsValueIsReady() | ||
313 | { | 329 | { | ||
314 | mDataLoader.setDatabase(manager->viewDatabase()); | 330 | if (!mLyricsValueWatcher.result().isEmpty()) { | ||
315 | manager->connectModel(&mDataLoader); | 331 | beginInsertRows({}, mTrackData.size(), mTrackData.size()); | ||
332 | mTrackKeys.push_back(DatabaseInterface::LyricsRole); | ||||
333 | mTrackData[DatabaseInterface::LyricsRole] = mLyricsValueWatcher.result(); | ||||
334 | mFullData[DatabaseInterface::LyricsRole] = mLyricsValueWatcher.result(); | ||||
335 | endInsertRows(); | ||||
336 | } | ||||
337 | } | ||||
338 | | ||||
339 | void TrackMetadataModel::initialize(MusicListenersManager *newManager, DatabaseInterface *trackDatabase) | ||||
340 | { | ||||
341 | mManager = newManager; | ||||
342 | Q_EMIT managerChanged(); | ||||
343 | | ||||
344 | if (mManager) { | ||||
345 | mDataLoader.setDatabase(mManager->viewDatabase()); | ||||
346 | } else if (trackDatabase) { | ||||
347 | mDataLoader.setDatabase(trackDatabase); | ||||
348 | } | ||||
316 | 349 | | |||
350 | if (mManager) { | ||||
351 | mManager->connectModel(&mDataLoader); | ||||
352 | } | ||||
353 | | ||||
354 | connect(this, &TrackMetadataModel::needDataByDatabaseId, | ||||
355 | &mDataLoader, &ModelDataLoader::loadDataByDatabaseId); | ||||
317 | connect(this, &TrackMetadataModel::needDataByFileName, | 356 | connect(this, &TrackMetadataModel::needDataByFileName, | ||
318 | &mDataLoader, &ModelDataLoader::loadDataByFileName); | 357 | &mDataLoader, &ModelDataLoader::loadDataByFileName); | ||
319 | connect(&mDataLoader, &ModelDataLoader::allTrackData, | 358 | connect(&mDataLoader, &ModelDataLoader::allTrackData, | ||
320 | this, &TrackMetadataModel::trackData); | 359 | this, &TrackMetadataModel::trackData); | ||
360 | connect(&mDataLoader, &ModelDataLoader::trackModified, | ||||
361 | this, &TrackMetadataModel::trackData); | ||||
362 | } | ||||
363 | | ||||
364 | void TrackMetadataModel::fetchLyrics() | ||||
365 | { | ||||
366 | auto lyricicsValue = QtConcurrent::run(QThreadPool::globalInstance(), [=]() { | ||||
367 | auto trackData = mFileScanner.scanOneFile(mFullData[DatabaseInterface::ResourceRole].toUrl(), mMimeDatabase); | ||||
368 | if (!trackData.lyrics().isEmpty()) { | ||||
369 | return trackData.lyrics(); | ||||
370 | } | ||||
371 | return QString{}; | ||||
372 | }); | ||||
373 | | ||||
374 | mLyricsValueWatcher.setFuture(lyricicsValue); | ||||
375 | } | ||||
376 | | ||||
377 | void TrackMetadataModel::initializeByTrackId(qulonglong databaseId) | ||||
378 | { | ||||
379 | mFullData.clear(); | ||||
380 | mTrackData.clear(); | ||||
381 | mCoverImage.clear(); | ||||
382 | mFileUrl.clear(); | ||||
383 | | ||||
384 | Q_EMIT needDataByDatabaseId(ElisaUtils::Track, databaseId); | ||||
385 | } | ||||
386 | | ||||
387 | void TrackMetadataModel::initializeByTrackFileName(const QUrl &fileName) | ||||
388 | { | ||||
389 | mFullData.clear(); | ||||
390 | mTrackData.clear(); | ||||
391 | mCoverImage.clear(); | ||||
392 | mFileUrl.clear(); | ||||
321 | 393 | | |||
322 | Q_EMIT needDataByFileName(ElisaUtils::FileName, fileName); | 394 | Q_EMIT needDataByFileName(ElisaUtils::FileName, fileName); | ||
323 | } | 395 | } | ||
324 | 396 | | |||
397 | void TrackMetadataModel::setManager(MusicListenersManager *newManager) | ||||
398 | { | ||||
399 | initialize(newManager, nullptr); | ||||
400 | } | ||||
401 | | ||||
402 | void TrackMetadataModel::setDatabase(DatabaseInterface *trackDatabase) | ||||
403 | { | ||||
404 | initialize(nullptr, trackDatabase); | ||||
405 | } | ||||
406 | | ||||
325 | 407 | | |||
326 | #include "moc_trackmetadatamodel.cpp" | 408 | #include "moc_trackmetadatamodel.cpp" |