diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ models/alltracksproxymodel.cpp models/singlealbumproxymodel.cpp models/trackmetadatamodel.cpp + models/trackcontextmetadatamodel.cpp models/viewsmodel.cpp ) @@ -340,6 +341,7 @@ qml/PlayListAlbumHeader.qml qml/BasicPlayListAlbumHeader.qml + qml/MetaDataDelegate.qml qml/MediaTrackDelegate.qml qml/MediaAlbumTrackDelegate.qml qml/MediaTrackMetadataView.qml diff --git a/src/databaseinterface.h b/src/databaseinterface.h --- a/src/databaseinterface.h +++ b/src/databaseinterface.h @@ -181,6 +181,31 @@ return operator[](key_type::LyricistRole).toString(); } + QString comment() const + { + return operator[](key_type::CommentRole).toString(); + } + + int year() const + { + return operator[](key_type::YearRole).toInt(); + } + + int channels() const + { + return operator[](key_type::ChannelsRole).toInt(); + } + + int bitRate() const + { + return operator[](key_type::BitRateRole).toInt(); + } + + int sampleRate() const + { + return operator[](key_type::SampleRateRole).toInt(); + } + bool hasEmbeddedCover() const { return operator[](key_type::HasEmbeddedCover).toBool(); diff --git a/src/databaseinterface.cpp b/src/databaseinterface.cpp --- a/src/databaseinterface.cpp +++ b/src/databaseinterface.cpp @@ -4317,19 +4317,34 @@ isSameTrack = isSameTrack && (oldTrack.albumName() == oneTrack.albumName()); isSameTrack = isSameTrack && (oldTrack.artist() == oneTrack.artist()); isSameTrack = isSameTrack && (oldTrack.albumArtist() == oneTrack.albumArtist()); - isSameTrack = isSameTrack && (oldTrack.trackNumber() == oneTrack.trackNumber()); - isSameTrack = isSameTrack && (oldTrack.discNumber() == oneTrack.discNumber()); + isSameTrack = isSameTrack && (oldTrack.trackNumberIsValid() == oneTrack.trackNumberIsValid()); + if (isSameTrack && oldTrack.trackNumberIsValid()) { + isSameTrack = isSameTrack && (oldTrack.trackNumber() == oneTrack.trackNumber()); + } + isSameTrack = isSameTrack && (oldTrack.discNumberIsValid() == oneTrack.discNumberIsValid()); + if (isSameTrack && oldTrack.discNumberIsValid()) { + isSameTrack = isSameTrack && (oldTrack.discNumber() == oneTrack.discNumber()); + } isSameTrack = isSameTrack && (oldTrack.duration() == oneTrack.duration()); isSameTrack = isSameTrack && (oldTrack.rating() == oneTrack.rating()); isSameTrack = isSameTrack && (oldTrack.resourceURI() == oneTrack.resourceURI()); isSameTrack = isSameTrack && (oldTrack.genre() == oneTrack.genre()); isSameTrack = isSameTrack && (oldTrack.composer() == oneTrack.composer()); isSameTrack = isSameTrack && (oldTrack.lyricist() == oneTrack.lyricist()); isSameTrack = isSameTrack && (oldTrack.comment() == oneTrack.comment()); isSameTrack = isSameTrack && (oldTrack.year() == oneTrack.year()); - isSameTrack = isSameTrack && (oldTrack.channels() == oneTrack.channels()); - isSameTrack = isSameTrack && (oldTrack.bitRate() == oneTrack.bitRate()); - isSameTrack = isSameTrack && (oldTrack.sampleRate() == oneTrack.sampleRate()); + isSameTrack = isSameTrack && (oldTrack.channelsIsValid() == oneTrack.channelsIsValid()); + if (isSameTrack && oldTrack.channelsIsValid()) { + isSameTrack = isSameTrack && (oldTrack.channels() == oneTrack.channels()); + } + isSameTrack = isSameTrack && (oldTrack.bitRateIsValid() == oneTrack.bitRateIsValid()); + if (isSameTrack && oldTrack.bitRateIsValid()) { + isSameTrack = isSameTrack && (oldTrack.bitRate() == oneTrack.bitRate()); + } + isSameTrack = isSameTrack && (oldTrack.sampleRateIsValid() == oneTrack.sampleRateIsValid()); + if (isSameTrack && oldTrack.sampleRateIsValid()) { + isSameTrack = isSameTrack && (oldTrack.sampleRate() == oneTrack.sampleRate()); + } if (isSameTrack) { return resultId; @@ -4485,8 +4500,12 @@ result.setResourceURI(trackRecord.value(5).toUrl()); result.setFileModificationTime(trackRecord.value(6).toDateTime()); - result.setTrackNumber(trackRecord.value(7).toInt()); - result.setDiscNumber(trackRecord.value(8).toInt()); + if (trackRecord.value(7).isValid()) { + result.setTrackNumber(trackRecord.value(7).toInt()); + } + if (trackRecord.value(8).isValid()) { + result.setDiscNumber(trackRecord.value(8).toInt()); + } result.setDuration(QTime::fromMSecsSinceStartOfDay(trackRecord.value(9).toInt())); result.setAlbumName(trackRecord.value(10).toString()); result.setRating(trackRecord.value(11).toInt()); @@ -4497,9 +4516,27 @@ result.setLyricist(trackRecord.value(16).toString()); result.setComment(trackRecord.value(17).toString()); result.setYear(trackRecord.value(18).toInt()); - result.setChannels(trackRecord.value(19).toInt()); - result.setBitRate(trackRecord.value(20).toInt()); - result.setSampleRate(trackRecord.value(21).toInt()); + if (trackRecord.value(19).isValid()) { + bool isValid; + auto value = trackRecord.value(19).toInt(&isValid); + if (isValid) { + result.setChannels(value); + } + } + if (trackRecord.value(20).isValid()) { + bool isValid; + auto value = trackRecord.value(20).toInt(&isValid); + if (isValid) { + result.setBitRate(value); + } + } + if (trackRecord.value(21).isValid()) { + bool isValid; + auto value = trackRecord.value(21).toInt(&isValid); + if (isValid) { + result.setSampleRate(value); + } + } result.setAlbumId(trackRecord.value(2).toULongLong()); result.setHasEmbeddedCover(trackRecord.value(22).toBool()); @@ -4514,25 +4551,47 @@ result[TrackDataType::key_type::DatabaseIdRole] = trackRecord.value(0); result[TrackDataType::key_type::TitleRole] = trackRecord.value(1); - result[TrackDataType::key_type::AlbumRole] = trackRecord.value(10); - result[TrackDataType::key_type::AlbumIdRole] = trackRecord.value(2); - result[TrackDataType::key_type::ArtistRole] = trackRecord.value(3); - result[TrackDataType::key_type::AlbumArtistRole] = trackRecord.value(4); + if (!trackRecord.value(10).isNull()) { + result[TrackDataType::key_type::AlbumRole] = trackRecord.value(10); + result[TrackDataType::key_type::AlbumIdRole] = trackRecord.value(2); + } + if (!trackRecord.value(3).isNull()) { + result[TrackDataType::key_type::ArtistRole] = trackRecord.value(3); + } + if (!trackRecord.value(4).isNull()) { + result[TrackDataType::key_type::AlbumArtistRole] = trackRecord.value(4); + } result[TrackDataType::key_type::ResourceRole] = trackRecord.value(5); - result[TrackDataType::key_type::TrackNumberRole] = trackRecord.value(7); - result[TrackDataType::key_type::DiscNumberRole] = trackRecord.value(8); + if (!trackRecord.value(7).isNull()) { + result[TrackDataType::key_type::TrackNumberRole] = trackRecord.value(7); + } + if (!trackRecord.value(8).isNull()) { + result[TrackDataType::key_type::DiscNumberRole] = trackRecord.value(8); + } result[TrackDataType::key_type::DurationRole] = QTime::fromMSecsSinceStartOfDay(trackRecord.value(9).toInt()); result[TrackDataType::key_type::MilliSecondsDurationRole] = trackRecord.value(9).toInt(); result[TrackDataType::key_type::RatingRole] = trackRecord.value(11); - result[TrackDataType::key_type::ImageUrlRole] = QUrl(trackRecord.value(12).toString()); + if (!trackRecord.value(12).isNull()) { + result[TrackDataType::key_type::ImageUrlRole] = QUrl(trackRecord.value(12).toString()); + } result[TrackDataType::key_type::IsSingleDiscAlbumRole] = trackRecord.value(13); - result[TrackDataType::key_type::GenreRole] = trackRecord.value(14); - result[TrackDataType::key_type::ComposerRole] = trackRecord.value(15); - result[TrackDataType::key_type::LyricistRole] = trackRecord.value(16); + if (!trackRecord.value(14).isNull()) { + result[TrackDataType::key_type::GenreRole] = trackRecord.value(14); + } + if (!trackRecord.value(15).isNull()) { + result[TrackDataType::key_type::ComposerRole] = trackRecord.value(15); + } + if (!trackRecord.value(16).isNull()) { + result[TrackDataType::key_type::LyricistRole] = trackRecord.value(16); + } result[TrackDataType::key_type::HasEmbeddedCover] = trackRecord.value(22); result[TrackDataType::key_type::FileModificationTime] = trackRecord.value(6); - result[TrackDataType::key_type::FirstPlayDate] = trackRecord.value(24); - result[TrackDataType::key_type::LastPlayDate] = trackRecord.value(25); + if (!trackRecord.value(24).isNull()) { + result[TrackDataType::key_type::FirstPlayDate] = trackRecord.value(24); + } + if (!trackRecord.value(25).isNull()) { + result[TrackDataType::key_type::LastPlayDate] = trackRecord.value(25); + } result[TrackDataType::key_type::PlayCounter] = trackRecord.value(26); result[TrackDataType::key_type::PlayFrequency] = trackRecord.value(27); result[DataType::key_type::ElementTypeRole] = ElisaUtils::Track; @@ -4902,8 +4961,16 @@ d->mUpdateTrackQuery.bindValue(QStringLiteral(":albumArtistName"), {}); } d->mUpdateTrackQuery.bindValue(QStringLiteral(":albumPath"), albumPath); - d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackNumber"), oneTrack.trackNumber()); - d->mUpdateTrackQuery.bindValue(QStringLiteral(":discNumber"), oneTrack.discNumber()); + if (oneTrack.trackNumberIsValid()) { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackNumber"), oneTrack.trackNumber()); + } else { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackNumber"), {}); + } + if (oneTrack.discNumberIsValid()) { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":discNumber"), oneTrack.discNumber()); + } else { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":discNumber"), {}); + } d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackDuration"), QVariant::fromValue(oneTrack.duration().msecsSinceStartOfDay())); d->mUpdateTrackQuery.bindValue(QStringLiteral(":trackRating"), oneTrack.rating()); if (insertGenre(oneTrack.genre()) != 0) { @@ -4923,9 +4990,21 @@ } d->mUpdateTrackQuery.bindValue(QStringLiteral(":comment"), oneTrack.comment()); d->mUpdateTrackQuery.bindValue(QStringLiteral(":year"), oneTrack.year()); - d->mUpdateTrackQuery.bindValue(QStringLiteral(":channels"), oneTrack.channels()); - d->mUpdateTrackQuery.bindValue(QStringLiteral(":bitRate"), oneTrack.bitRate()); - d->mUpdateTrackQuery.bindValue(QStringLiteral(":sampleRate"), oneTrack.sampleRate()); + if (oneTrack.channelsIsValid()) { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":channels"), oneTrack.channels()); + } else { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":channels"), {}); + } + if (oneTrack.bitRateIsValid()) { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":bitRate"), oneTrack.bitRate()); + } else { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":bitRate"), {}); + } + if (oneTrack.sampleRateIsValid()) { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":sampleRate"), oneTrack.sampleRate()); + } else { + d->mUpdateTrackQuery.bindValue(QStringLiteral(":sampleRate"), {}); + } auto result = d->mUpdateTrackQuery.exec(); diff --git a/src/elisaapplication.cpp b/src/elisaapplication.cpp --- a/src/elisaapplication.cpp +++ b/src/elisaapplication.cpp @@ -381,7 +381,9 @@ d->mManageHeaderBar->setTitleRole(MediaPlayList::TitleRole); d->mManageHeaderBar->setAlbumRole(MediaPlayList::AlbumRole); d->mManageHeaderBar->setArtistRole(MediaPlayList::ArtistRole); + d->mManageHeaderBar->setFileNameRole(MediaPlayList::ResourceRole); d->mManageHeaderBar->setImageRole(MediaPlayList::ImageUrlRole); + d->mManageHeaderBar->setDatabaseIdRole(MediaPlayList::DatabaseIdRole); d->mManageHeaderBar->setAlbumIdRole(MediaPlayList::AlbumIdRole); d->mManageHeaderBar->setIsValidRole(MediaPlayList::IsValidRole); d->mManageHeaderBar->setPlayListModel(d->mMediaPlayList.get()); diff --git a/src/elisaqmlplugin.cpp b/src/elisaqmlplugin.cpp --- a/src/elisaqmlplugin.cpp +++ b/src/elisaqmlplugin.cpp @@ -47,6 +47,7 @@ #include "databaseinterface.h" #include "models/datamodel.h" #include "models/trackmetadatamodel.h" +#include "models/trackcontextmetadatamodel.h" #include "models/viewsmodel.h" #include "models/gridviewproxymodel.h" #include "models/alltracksproxymodel.h" @@ -123,6 +124,7 @@ qmlRegisterType(uri, 1, 0, "ViewManager"); qmlRegisterType(uri, 1, 0, "DataModel"); qmlRegisterType(uri, 1, 0, "TrackMetadataModel"); + qmlRegisterType(uri, 1, 0, "TrackContextMetaDataModel"); qmlRegisterType(uri, 1, 0, "ViewsModel"); qmlRegisterType(uri, 1, 0, "GridViewProxyModel"); qmlRegisterType(uri, 1, 0, "AllTracksProxyModel"); diff --git a/src/filescanner.cpp b/src/filescanner.cpp --- a/src/filescanner.cpp +++ b/src/filescanner.cpp @@ -154,8 +154,6 @@ if (discNumberProperty != d->mAllProperties.end()) { trackData.setDiscNumber(discNumberProperty->toInt()); - } else { - trackData.setDiscNumber(1); } if (albumArtistProperty != d->mAllProperties.end()) { diff --git a/src/manageheaderbar.h b/src/manageheaderbar.h --- a/src/manageheaderbar.h +++ b/src/manageheaderbar.h @@ -56,11 +56,21 @@ WRITE setAlbumRole NOTIFY albumRoleChanged) + Q_PROPERTY(int fileNameRole + READ fileNameRole + WRITE setFileNameRole + NOTIFY fileNameRoleChanged) + Q_PROPERTY(int imageRole READ imageRole WRITE setImageRole NOTIFY imageRoleChanged) + Q_PROPERTY(int databaseIdRole + READ databaseIdRole + WRITE setDatabaseIdRole + NOTIFY databaseIdRoleChanged) + Q_PROPERTY(int albumIdRole READ albumIdRole WRITE setAlbumIdRole @@ -83,10 +93,18 @@ READ album NOTIFY albumChanged) + Q_PROPERTY(QString fileName + READ fileName + NOTIFY fileNameChanged) + Q_PROPERTY(QUrl image READ image NOTIFY imageChanged) + Q_PROPERTY(qulonglong databaseId + READ databaseId + NOTIFY databaseIdChanged) + Q_PROPERTY(qulonglong albumId READ albumId NOTIFY albumIdChanged) @@ -113,8 +131,12 @@ int albumRole() const; + int fileNameRole() const; + int imageRole() const; + int databaseIdRole() const; + int albumIdRole() const; int isValidRole() const; @@ -125,8 +147,12 @@ QVariant album() const; + QString fileName() const; + QUrl image() const; + qulonglong databaseId() const; + qulonglong albumId() const; bool isValid() const; @@ -145,8 +171,12 @@ void albumRoleChanged(); + void fileNameRoleChanged(); + void imageRoleChanged(); + void databaseIdRoleChanged(); + void albumIdRoleChanged(); void isValidRoleChanged(); @@ -157,10 +187,14 @@ void albumChanged(); + void fileNameChanged(); + void imageChanged(); void remainingTracksChanged(); + void databaseIdChanged(); + void albumIdChanged(); void isValidChanged(); @@ -177,8 +211,12 @@ void setAlbumRole(int value); + void setFileNameRole(int value); + void setImageRole(int value); + void setDatabaseIdRole(int databaseIdRole); + void setAlbumIdRole(int albumIdRole); void setIsValidRole(int isValidRole); @@ -203,8 +241,12 @@ void notifyAlbumProperty(); + void notifyFileNameProperty(); + void notifyImageProperty(); + void notifyDatabaseIdProperty(); + void notifyAlbumIdProperty(); void notifyIsValidProperty(); @@ -221,8 +263,12 @@ int mAlbumRole = Qt::DisplayRole; + int mFileNameRole = Qt::DisplayRole; + int mImageRole = Qt::DisplayRole; + int mDatabaseIdRole = Qt::DisplayRole; + int mAlbumIdRole = Qt::DisplayRole; int mIsValidRole = Qt::DisplayRole; @@ -233,8 +279,12 @@ QVariant mOldAlbum; + QVariant mOldFileName; + QVariant mOldImage; + qulonglong mOldDatabaseId = 0; + qulonglong mOldAlbumId = 0; bool mOldIsValid = false; diff --git a/src/manageheaderbar.cpp b/src/manageheaderbar.cpp --- a/src/manageheaderbar.cpp +++ b/src/manageheaderbar.cpp @@ -56,22 +56,44 @@ Q_EMIT albumRoleChanged(); } +void ManageHeaderBar::setFileNameRole(int value) +{ + mFileNameRole = value; + Q_EMIT fileNameRoleChanged(); +} + int ManageHeaderBar::albumRole() const { return mAlbumRole; } +int ManageHeaderBar::fileNameRole() const +{ + return mFileNameRole; +} + void ManageHeaderBar::setImageRole(int value) { mImageRole = value; Q_EMIT imageRoleChanged(); } +void ManageHeaderBar::setDatabaseIdRole(int databaseIdRole) +{ + mDatabaseIdRole = databaseIdRole; + Q_EMIT databaseIdRoleChanged(); +} + int ManageHeaderBar::imageRole() const { return mImageRole; } +int ManageHeaderBar::databaseIdRole() const +{ + return mDatabaseIdRole; +} + void ManageHeaderBar::setAlbumIdRole(int albumIdRole) { mAlbumIdRole = albumIdRole; @@ -92,6 +114,24 @@ return mCurrentTrack.data(mAlbumRole); } +QString ManageHeaderBar::fileName() const +{ + QString result; + + if (!mCurrentTrack.isValid()) { + return result; + } + + auto fileNameUrl = mCurrentTrack.data(mFileNameRole).toUrl(); + if (fileNameUrl.isLocalFile()) { + result = fileNameUrl.toLocalFile(); + } else { + result = fileNameUrl.toString(); + } + + return result; +} + QVariant ManageHeaderBar::title() const { if (!mCurrentTrack.isValid()) { @@ -119,6 +159,15 @@ return mCurrentTrack.data(mImageRole).toUrl(); } +qulonglong ManageHeaderBar::databaseId() const +{ + if (!mCurrentTrack.isValid()) { + return 0; + } + + return mCurrentTrack.data(mDatabaseIdRole).toULongLong(); +} + qulonglong ManageHeaderBar::albumId() const { if (!mCurrentTrack.isValid()) { @@ -200,7 +249,9 @@ notifyArtistProperty(); notifyTitleProperty(); notifyAlbumProperty(); + notifyFileNameProperty(); notifyImageProperty(); + notifyDatabaseIdProperty(); notifyAlbumIdProperty(); notifyIsValidProperty(); } else { @@ -214,9 +265,15 @@ if (oneRole == mAlbumRole) { notifyAlbumProperty(); } + if (oneRole == mFileNameRole) { + notifyFileNameProperty(); + } if (oneRole == mImageRole) { notifyImageProperty(); } + if (oneRole == mDatabaseIdRole) { + notifyDatabaseIdProperty(); + } if (oneRole == mAlbumIdRole) { notifyAlbumIdProperty(); } @@ -262,7 +319,9 @@ notifyArtistProperty(); notifyTitleProperty(); notifyAlbumProperty(); + notifyFileNameProperty(); notifyImageProperty(); + notifyDatabaseIdProperty(); notifyAlbumIdProperty(); notifyIsValidProperty(); notifyRemainingTracksProperty(); @@ -303,6 +362,16 @@ } } +void ManageHeaderBar::notifyFileNameProperty() +{ + auto newFileNameValue = mCurrentTrack.data(mFileNameRole); + if (mOldFileName != newFileNameValue) { + Q_EMIT fileNameChanged(); + + mOldFileName = newFileNameValue; + } +} + void ManageHeaderBar::notifyImageProperty() { auto newImageValue = mCurrentTrack.data(mImageRole); @@ -313,6 +382,21 @@ } } +void ManageHeaderBar::notifyDatabaseIdProperty() +{ + bool conversionOk; + auto newDatabaseIdValue = mCurrentTrack.data(mDatabaseIdRole).toULongLong(&conversionOk); + if (conversionOk && mOldDatabaseId != newDatabaseIdValue) { + Q_EMIT databaseIdChanged(); + + mOldDatabaseId = newDatabaseIdValue; + } else if (!conversionOk && mOldDatabaseId != 0) { + Q_EMIT databaseIdChanged(); + + mOldDatabaseId = 0; + } +} + void ManageHeaderBar::notifyAlbumIdProperty() { bool conversionOk; @@ -373,7 +457,9 @@ notifyArtistProperty(); notifyTitleProperty(); notifyAlbumProperty(); + notifyFileNameProperty(); notifyImageProperty(); + notifyDatabaseIdProperty(); notifyAlbumIdProperty(); notifyIsValidProperty(); } diff --git a/src/models/trackcontextmetadatamodel.h b/src/models/trackcontextmetadatamodel.h new file mode 100644 --- /dev/null +++ b/src/models/trackcontextmetadatamodel.h @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Matthieu Gallien + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef TRACKCONTEXTMETADATAMODEL_H +#define TRACKCONTEXTMETADATAMODEL_H + +#include "elisaLib_export.h" + +#include "trackmetadatamodel.h" + +class ELISALIB_EXPORT TrackContextMetaDataModel : public TrackMetadataModel +{ + + Q_OBJECT + +public: + + TrackContextMetaDataModel(QObject *parent = nullptr); + +protected: + + void filterDataFromTrackData() override; + +}; + +#endif // TRACKCONTEXTMETADATAMODEL_H diff --git a/src/models/trackcontextmetadatamodel.cpp b/src/models/trackcontextmetadatamodel.cpp new file mode 100644 --- /dev/null +++ b/src/models/trackcontextmetadatamodel.cpp @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Matthieu Gallien + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "trackcontextmetadatamodel.h" + +TrackContextMetaDataModel::TrackContextMetaDataModel(QObject *parent) : TrackMetadataModel(parent) +{ +} + +void TrackContextMetaDataModel::filterDataFromTrackData() +{ + removeMetaData(DatabaseInterface::TitleRole); + removeMetaData(DatabaseInterface::ArtistRole); + removeMetaData(DatabaseInterface::AlbumRole); +} + + +#include "moc_trackcontextmetadatamodel.cpp" diff --git a/src/models/trackmetadatamodel.h b/src/models/trackmetadatamodel.h --- a/src/models/trackmetadatamodel.h +++ b/src/models/trackmetadatamodel.h @@ -41,6 +41,11 @@ READ fileUrl NOTIFY fileUrlChanged) + Q_PROPERTY(MusicListenersManager* manager + READ manager + WRITE setManager + NOTIFY managerChanged) + public: enum ColumnRoles @@ -72,16 +77,12 @@ QHash roleNames() const override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - - bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - const QUrl& coverUrl() const; QString fileUrl() const; + MusicListenersManager* manager() const; + Q_SIGNALS: void needDataByDatabaseId(ElisaUtils::PlayListEntryType dataType, qulonglong databaseId); @@ -92,13 +93,25 @@ void fileUrlChanged(); + void managerChanged(); + public Q_SLOTS: void trackData(const TrackMetadataModel::TrackDataType &trackData); - void initializeByTrackId(MusicListenersManager *manager, qulonglong databaseId); + void initializeByTrackId(qulonglong databaseId); - void initializeByTrackFileName(MusicListenersManager *manager, const QUrl &fileName); + void initializeByTrackFileName(const QUrl &fileName); + + void setManager(MusicListenersManager *newManager); + +protected: + + void fillDataFromTrackData(const TrackMetadataModel::TrackDataType &trackData); + + virtual void filterDataFromTrackData(); + + void removeMetaData(DatabaseInterface::ColumnsRoles metaData); private: @@ -112,6 +125,8 @@ ModelDataLoader mDataLoader; + MusicListenersManager *mManager = nullptr; + }; #endif // TRACKMETADATAMODEL_H diff --git a/src/models/trackmetadatamodel.cpp b/src/models/trackmetadatamodel.cpp --- a/src/models/trackmetadatamodel.cpp +++ b/src/models/trackmetadatamodel.cpp @@ -50,58 +50,58 @@ switch (currentKey) { case DatabaseInterface::TitleRole: - result = i18nc("Track title for track metadata view", "Title:"); + result = i18nc("Track title for track metadata view", "Title"); break; case DatabaseInterface::DurationRole: - result = i18nc("Duration label for track metadata view", "Duration:"); + result = i18nc("Duration label for track metadata view", "Duration"); break; case DatabaseInterface::ArtistRole: - result = i18nc("Track artist for track metadata view", "Artist:"); + result = i18nc("Track artist for track metadata view", "Artist"); break; case DatabaseInterface::AlbumRole: - result = i18nc("Album name for track metadata view", "Album:"); + result = i18nc("Album name for track metadata view", "Album"); break; case DatabaseInterface::AlbumArtistRole: - result = i18nc("Album artist for track metadata view", "Album Artist:"); + result = i18nc("Album artist for track metadata view", "Album Artist"); break; case DatabaseInterface::TrackNumberRole: - result = i18nc("Track number for track metadata view", "Track Number:"); + result = i18nc("Track number for track metadata view", "Track Number"); break; case DatabaseInterface::DiscNumberRole: - result = i18nc("Disc number for track metadata view", "Disc Number:"); + result = i18nc("Disc number for track metadata view", "Disc Number"); break; case DatabaseInterface::RatingRole: - result = i18nc("Rating label for information panel", "Rating:"); + result = i18nc("Rating label for information panel", "Rating"); break; case DatabaseInterface::GenreRole: - result = i18nc("Genre label for track metadata view", "Genre:"); + result = i18nc("Genre label for track metadata view", "Genre"); break; case DatabaseInterface::LyricistRole: - result = i18nc("Lyricist label for track metadata view", "Lyricist:"); + result = i18nc("Lyricist label for track metadata view", "Lyricist"); break; case DatabaseInterface::ComposerRole: - result = i18nc("Composer name for track metadata view", "Composer:"); + result = i18nc("Composer name for track metadata view", "Composer"); break; case DatabaseInterface::CommentRole: - result = i18nc("Comment label for track metadata view", "Comment:"); + result = i18nc("Comment label for track metadata view", "Comment"); break; case DatabaseInterface::YearRole: - result = i18nc("Year label for track metadata view", "Year:"); + result = i18nc("Year label for track metadata view", "Year"); break; case DatabaseInterface::ChannelsRole: - result = i18nc("Channels label for track metadata view", "Channels:"); + result = i18nc("Channels label for track metadata view", "Channels"); break; case DatabaseInterface::BitRateRole: - result = i18nc("Bit rate label for track metadata view", "Bit Rate:"); + result = i18nc("Bit rate label for track metadata view", "Bit Rate"); break; case DatabaseInterface::SampleRateRole: - result = i18nc("Sample Rate label for track metadata view", "Sample Rate:"); + result = i18nc("Sample Rate label for track metadata view", "Sample Rate"); break; case DatabaseInterface::LastPlayDate: - result = i18nc("Last play date label for track metadata view", "Last played:"); + result = i18nc("Last play date label for track metadata view", "Last played"); break; case DatabaseInterface::PlayCounter: - result = i18nc("Play counter label for track metadata view", "Play count:"); + result = i18nc("Play counter label for track metadata view", "Play count"); break; case DatabaseInterface::SecondaryTextRole: case DatabaseInterface::ImageUrlRole: @@ -223,47 +223,31 @@ return names; } -Qt::ItemFlags TrackMetadataModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - - return Qt::ItemIsEditable | QAbstractListModel::flags(index); -} - QString TrackMetadataModel::fileUrl() const { return mFileUrl; } -bool TrackMetadataModel::insertRows(int row, int count, const QModelIndex &parent) +const QUrl &TrackMetadataModel::coverUrl() const { - beginInsertRows(parent, row, row + count - 1); - endInsertRows(); - - return true; + return mCoverImage; } -bool TrackMetadataModel::removeRows(int row, int count, const QModelIndex &parent) +MusicListenersManager *TrackMetadataModel::manager() const { - beginRemoveRows(parent, row, row + count - 1); - endRemoveRows(); - - return true; + return mManager; } -const QUrl &TrackMetadataModel::coverUrl() const +void TrackMetadataModel::trackData(const TrackMetadataModel::TrackDataType &trackData) { - return mCoverImage; + fillDataFromTrackData(trackData); } -void TrackMetadataModel::trackData(const TrackMetadataModel::TrackDataType &trackData) +void TrackMetadataModel::fillDataFromTrackData(const TrackMetadataModel::TrackDataType &trackData) { beginResetModel(); - if (mTrackData.isValid()) { - mTrackData.clear(); - mTrackKeys.clear(); - } + mTrackData.clear(); + mTrackKeys.clear(); for (auto role : {DatabaseInterface::TitleRole, DatabaseInterface::ArtistRole, DatabaseInterface::AlbumRole, DatabaseInterface::AlbumArtistRole, DatabaseInterface::TrackNumberRole, DatabaseInterface::DiscNumberRole, @@ -281,6 +265,7 @@ mTrackData[role] = trackData[role]; } } + filterDataFromTrackData(); endResetModel(); mCoverImage = trackData[DatabaseInterface::ImageUrlRole].toUrl(); @@ -296,28 +281,54 @@ Q_EMIT fileUrlChanged(); } -void TrackMetadataModel::initializeByTrackId(MusicListenersManager *manager, qulonglong databaseId) +void TrackMetadataModel::filterDataFromTrackData() { - manager->connectModel(&mDataLoader); +} - connect(this, &TrackMetadataModel::needDataByDatabaseId, - &mDataLoader, &ModelDataLoader::loadDataByDatabaseId); - connect(&mDataLoader, &ModelDataLoader::allTrackData, - this, &TrackMetadataModel::trackData); +void TrackMetadataModel::removeMetaData(DatabaseInterface::ColumnsRoles metaData) +{ + auto itMetaData = std::find(mTrackKeys.begin(), mTrackKeys.end(), metaData); + if (itMetaData == mTrackKeys.end()) { + return; + } + + mTrackKeys.erase(itMetaData); + mTrackData.remove(metaData); +} +void TrackMetadataModel::initializeByTrackId(qulonglong databaseId) +{ Q_EMIT needDataByDatabaseId(ElisaUtils::Track, databaseId); } -void TrackMetadataModel::initializeByTrackFileName(MusicListenersManager *manager, const QUrl &fileName) +void TrackMetadataModel::initializeByTrackFileName(const QUrl &fileName) +{ + Q_EMIT needDataByFileName(ElisaUtils::FileName, fileName); +} + +void TrackMetadataModel::setManager(MusicListenersManager *newManager) { - manager->connectModel(&mDataLoader); + if (mManager == newManager) { + return; + } - connect(this, &TrackMetadataModel::needDataByFileName, - &mDataLoader, &ModelDataLoader::loadDataByFileName); - connect(&mDataLoader, &ModelDataLoader::allTrackData, - this, &TrackMetadataModel::trackData); + if (mManager) { + disconnect(mManager); + } - Q_EMIT needDataByFileName(ElisaUtils::FileName, fileName); + mManager = newManager; + Q_EMIT managerChanged(); + + if (mManager) { + mManager->connectModel(&mDataLoader); + + connect(this, &TrackMetadataModel::needDataByDatabaseId, + &mDataLoader, &ModelDataLoader::loadDataByDatabaseId); + connect(this, &TrackMetadataModel::needDataByFileName, + &mDataLoader, &ModelDataLoader::loadDataByFileName); + connect(&mDataLoader, &ModelDataLoader::allTrackData, + this, &TrackMetadataModel::trackData); + } } diff --git a/src/musicaudiotrack.h b/src/musicaudiotrack.h --- a/src/musicaudiotrack.h +++ b/src/musicaudiotrack.h @@ -127,26 +127,36 @@ int trackNumber() const; + bool trackNumberIsValid() const; + void setDiscNumber(int value); int discNumber() const; + bool discNumberIsValid() const; + void setYear(int value); int year() const; void setChannels(int value); int channels() const; + bool channelsIsValid() const; + void setBitRate(int value); int bitRate() const; + bool bitRateIsValid() const; + void setSampleRate(int value); int sampleRate() const; + bool sampleRateIsValid() const; + void setDuration(QTime value); QTime duration() const; diff --git a/src/musicaudiotrack.cpp b/src/musicaudiotrack.cpp --- a/src/musicaudiotrack.cpp +++ b/src/musicaudiotrack.cpp @@ -38,11 +38,11 @@ mTitle(std::move(aTitle)), mArtist(std::move(aArtist)), mAlbumName(std::move(aAlbumName)), mAlbumArtist(std::move(aAlbumArtist)), mGenre(std::move(aGenre)), mComposer(std::move(aComposer)), mLyricist(std::move(aLyricist)), - mResourceURI(std::move(aResourceURI)), - mAlbumCover(std::move(aAlbumCover)), + mResourceURI(std::move(aResourceURI)), mAlbumCover(std::move(aAlbumCover)), mFileModificationTime(std::move(fileModificationTime)), mDuration(aDuration), mTrackNumber(aTrackNumber), mDiscNumber(aDiscNumber), mRating(rating), - mIsValid(aValid), mIsSingleDiscAlbum(aIsSingleDiscAlbum), mHasBooleanCover(aHasEmbeddedCover) + mIsValid(aValid), mIsSingleDiscAlbum(aIsSingleDiscAlbum), mHasBooleanCover(aHasEmbeddedCover), + mTrackNumberIsValid(true), mDiscNumberIsValid(true) { } @@ -98,6 +98,16 @@ bool mHasBooleanCover = false; + bool mTrackNumberIsValid = false; + + bool mDiscNumberIsValid = false; + + bool mChannelsIsValid = false; + + bool mBitRateIsValid = false; + + bool mSampleRateIsValid = false; + }; MusicAudioTrack::MusicAudioTrack() : d(new MusicAudioTrackPrivate()) @@ -177,14 +187,14 @@ result.setGenre(data.genre()); result.setComposer(data.composer()); result.setLyricist(data.lyricist()); - //result.setComment(data.comment()); + result.setComment(data.comment()); result.setAlbumCover(data.albumCover()); result.setTrackNumber(data.trackNumber()); result.setDiscNumber(data.discNumber()); - //result.setYear(data.year()); - //result.setChannels(data.channels()); - //result.setBitRate(data.bitRate()); - //result.setSampleRate(data.sampleRate()); + result.setYear(data.year()); + result.setChannels(data.channels()); + result.setBitRate(data.bitRate()); + result.setSampleRate(data.sampleRate()); result.setResourceURI(data.resourceURI()); result.setRating(data.rating()); result.setDuration(data[MusicAudioTrack::TrackDataType::key_type::DurationRole].toTime()); @@ -345,23 +355,35 @@ void MusicAudioTrack::setTrackNumber(int value) { d->mTrackNumber = value; + d->mTrackNumberIsValid = true; } int MusicAudioTrack::trackNumber() const { return d->mTrackNumber; } +bool MusicAudioTrack::trackNumberIsValid() const +{ + return d->mTrackNumberIsValid; +} + void MusicAudioTrack::setDiscNumber(int value) { d->mDiscNumber = value; + d->mDiscNumberIsValid = true; } int MusicAudioTrack::discNumber() const { return d->mDiscNumber; } +bool MusicAudioTrack::discNumberIsValid() const +{ + return d->mDiscNumberIsValid; +} + void MusicAudioTrack::setYear(int value) { d->mYear = value; @@ -375,33 +397,51 @@ void MusicAudioTrack::setChannels(int value) { d->mChannels = value; + d->mChannelsIsValid = true; } int MusicAudioTrack::channels() const { return d->mChannels; } +bool MusicAudioTrack::channelsIsValid() const +{ + return d->mChannelsIsValid; +} + void MusicAudioTrack::setBitRate(int value) { d->mBitRate = value; + d->mBitRateIsValid = true; } int MusicAudioTrack::bitRate() const { return d->mBitRate; } +bool MusicAudioTrack::bitRateIsValid() const +{ + return d->mBitRateIsValid; +} + void MusicAudioTrack::setSampleRate(int value) { d->mSampleRate = value; + d->mSampleRateIsValid = true; } int MusicAudioTrack::sampleRate() const { return d->mSampleRate; } +bool MusicAudioTrack::sampleRateIsValid() const +{ + return d->mSampleRateIsValid; +} + void MusicAudioTrack::setDuration(QTime value) { d->mDuration = value; diff --git a/src/qml/BaseTheme.qml b/src/qml/BaseTheme.qml --- a/src/qml/BaseTheme.qml +++ b/src/qml/BaseTheme.qml @@ -65,17 +65,15 @@ } property int playListDelegateHeight: (playListTrackTextHeight.height > dp(28)) ? playListTrackTextHeight.height : dp(28) - property int playListDelegateWithHeaderHeight: playListDelegateHeight + - elisaTheme.layoutVerticalMargin * 5 + - playListAuthorTextHeight.height + - playListAlbumTextHeight.height + property int playListHeaderHeight: elisaTheme.layoutVerticalMargin * 5 + playListAuthorTextHeight.height + playListAlbumTextHeight.height property int trackDelegateHeight: dp(45) property int coverImageSize: dp(180) + property int contextCoverImageSize: dp(100) property int smallImageSize: dp(32) property int maximumMetadataWidth: dp(300) diff --git a/src/qml/ContentView.qml b/src/qml/ContentView.qml --- a/src/qml/ContentView.qml +++ b/src/qml/ContentView.qml @@ -345,7 +345,6 @@ Layout.fillHeight: true Layout.leftMargin: elisaTheme.layoutHorizontalMargin - Layout.rightMargin: elisaTheme.layoutHorizontalMargin Layout.minimumWidth: contentZone.width Layout.maximumWidth: contentZone.width @@ -378,20 +377,31 @@ Layout.maximumWidth: 1 } - ContextView { + Loader { id: albumContext + active: Layout.minimumWidth != 0 + + sourceComponent: ContextView { + + anchors.fill: parent + + databaseId: elisa.manageHeaderBar.databaseId + title: elisa.manageHeaderBar.title + artistName: elisa.manageHeaderBar.artist + albumName: elisa.manageHeaderBar.album + albumArtUrl: elisa.manageHeaderBar.image + fileUrl: elisa.manageHeaderBar.fileName + } + Layout.fillHeight: true - Layout.minimumWidth: contentZone.width - Layout.maximumWidth: contentZone.width - Layout.preferredWidth: contentZone.width + Layout.minimumWidth: 0 + Layout.maximumWidth: 0 + Layout.preferredWidth: 0 + Layout.leftMargin: elisaTheme.layoutHorizontalMargin * 1.5 visible: Layout.minimumWidth != 0 - - artistName: elisa.manageHeaderBar.artist - albumName: elisa.manageHeaderBar.album - albumArtUrl: elisa.manageHeaderBar.image } } } @@ -414,9 +424,9 @@ } PropertyChanges { target: playList - Layout.minimumWidth: contentZone.width / 2 - Layout.maximumWidth: contentZone.width / 2 - Layout.preferredWidth: contentZone.width / 2 + Layout.minimumWidth: contentZone.width * 2 / 5 + elisaTheme.layoutHorizontalMargin + Layout.maximumWidth: contentZone.width * 2 / 5 + elisaTheme.layoutHorizontalMargin + Layout.preferredWidth: contentZone.width * 2 / 5 + elisaTheme.layoutHorizontalMargin } PropertyChanges { target: viewSeparatorItem @@ -426,9 +436,9 @@ } PropertyChanges { target: albumContext - Layout.minimumWidth: contentZone.width / 2 - Layout.maximumWidth: contentZone.width / 2 - Layout.preferredWidth: contentZone.width / 2 + Layout.minimumWidth: contentZone.width * 3 / 5 - 2 - 3.5 * elisaTheme.layoutHorizontalMargin + Layout.maximumWidth: contentZone.width * 3 / 5 - 2 - 3.5 * elisaTheme.layoutHorizontalMargin + Layout.preferredWidth: contentZone.width * 3 / 5 - 2 - 3.5 * elisaTheme.layoutHorizontalMargin } }, State { diff --git a/src/qml/ContextView.qml b/src/qml/ContextView.qml --- a/src/qml/ContextView.qml +++ b/src/qml/ContextView.qml @@ -15,154 +15,185 @@ * along with this program. If not, see . */ -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Window 2.2 import QtQuick.Controls 2.2 import QtQml.Models 2.2 -import org.kde.elisa 1.0 import QtQuick.Layouts 1.2 -Item { +import org.kde.elisa 1.0 + +FocusScope { id: topItem - property var albumName - property var artistName - property var tracksCount - property var albumArtUrl + property int databaseId: 0 + property alias title: titleLabel.text + property string albumName: '' + property string artistName: '' + property url albumArtUrl: '' + property string fileUrl: '' + + TrackContextMetaDataModel { + id: metaDataModel + + manager: elisa.musicManager + } ColumnLayout { anchors.fill: parent spacing: 0 - Item { - Layout.fillHeight: true + TextMetrics { + id: titleHeight + text: viewTitleHeight.text + font + { + pointSize: viewTitleHeight.font.pointSize + bold: viewTitleHeight.font.bold + } + } + + LabelWithToolTip { + id: viewTitleHeight + text: i18nc("Title of the context view related to the currently playing track", "Now Playing") + + font.pointSize: elisaTheme.defaultFontPointSize * 2 + + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.topMargin: elisaTheme.layoutVerticalMargin * 3 + Layout.bottomMargin: titleHeight.height } Image { id: albumIcon source: albumArtUrl.toString() === '' ? Qt.resolvedUrl(elisaTheme.defaultAlbumImage) : albumArtUrl - Layout.preferredWidth: elisaTheme.coverImageSize - Layout.preferredHeight: elisaTheme.coverImageSize - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - Layout.maximumWidth: elisaTheme.coverImageSize - Layout.maximumHeight: elisaTheme.coverImageSize + + Layout.fillWidth: true + Layout.maximumHeight: elisaTheme.contextCoverImageSize + Layout.preferredHeight: elisaTheme.contextCoverImageSize + Layout.bottomMargin: elisaTheme.layoutVerticalMargin - width: elisaTheme.coverImageSize - height: elisaTheme.coverImageSize + width: elisaTheme.contextCoverImageSize + height: elisaTheme.contextCoverImageSize - sourceSize.width: elisaTheme.coverImageSize - sourceSize.height: elisaTheme.coverImageSize + sourceSize.width: parent.width + sourceSize.height: elisaTheme.contextCoverImageSize asynchronous: true - fillMode: Image.PreserveAspectFit + fillMode: Image.PreserveAspectCrop } LabelWithToolTip { id: titleLabel - text: if (albumName !== undefined) - albumName - else - '' - + font.pointSize: elisaTheme.defaultFontPointSize * 2 font.weight: Font.Bold - color: myPalette.text - horizontalAlignment: Text.AlignHCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.topMargin: elisaTheme.layoutVerticalMargin - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + elide: Text.ElideRight + } + + LabelWithToolTip { + id: albumArtistLabel + + text: i18nc('display of artist and album in context view', 'by %1 from %2', artistName, albumName) + + font.pointSize: elisaTheme.defaultFontPointSize * 1.4 + + visible: artistName !== '' && albumName !== '' + + Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.bottomMargin: elisaTheme.layoutVerticalMargin elide: Text.ElideRight } LabelWithToolTip { - id: artistLabel + id: albumLabel - text: if (artistName !== undefined) - artistName - else - '' + text: i18nc('display of album in context view', 'from %2', albumName) - font.weight: Font.Normal - color: myPalette.text + font.pointSize: elisaTheme.defaultFontPointSize * 1.4 - horizontalAlignment: Text.AlignHCenter + visible: artistName === '' && albumName !== '' - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.bottomMargin: elisaTheme.layoutVerticalMargin elide: Text.ElideRight } LabelWithToolTip { - id: numberLabel - - text: i18np("1 track", "%1 track", tracksCount) + id: artistLabel - visible: tracksCount !== undefined + text: i18nc('display of artist in context view', 'by %1', artistName) - font.weight: Font.Light - color: myPalette.text + font.pointSize: elisaTheme.defaultFontPointSize * 1.4 - horizontalAlignment: Text.AlignHCenter + visible: artistName !== '' && albumName === '' - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.bottomMargin: elisaTheme.layoutVerticalMargin elide: Text.ElideRight } + Repeater { + model: metaDataModel + + delegate: MetaDataDelegate { + } + } + Item { Layout.fillHeight: true } - RowLayout { - Layout.fillWidth: true - Layout.bottomMargin: elisaTheme.layoutVerticalMargin * 2 + Row { + Layout.alignment: Qt.AlignLeft | Qt.AlignBottom + Layout.topMargin: elisaTheme.layoutVerticalMargin + Layout.bottomMargin: elisaTheme.layoutVerticalMargin - spacing: 0 + spacing: elisaTheme.layoutHorizontalMargin Image { - id: artistJumpIcon - - source: Qt.resolvedUrl(elisaTheme.defaultArtistImage) + sourceSize.width: fileNameLabel.height + sourceSize.height: fileNameLabel.height - Layout.preferredWidth: elisaTheme.smallImageSize - Layout.preferredHeight: elisaTheme.smallImageSize - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - Layout.maximumWidth: elisaTheme.smallImageSize - Layout.maximumHeight: elisaTheme.smallImageSize - Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0 - Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0 + source: elisaTheme.folderIcon + } - visible: artistName !== undefined - width: elisaTheme.smallImageSize - height: elisaTheme.smallImageSize + LabelWithToolTip { + id: fileNameLabel - sourceSize.width: elisaTheme.smallImageSize - sourceSize.height: elisaTheme.smallImageSize + text: fileUrl - fillMode: Image.PreserveAspectFit + elide: Text.ElideRight } + } + } - LabelWithToolTip { - text: if (artistName !== undefined) - artistName - else - '' + onDatabaseIdChanged: { + metaDataModel.initializeByTrackId(databaseId) + } - font.weight: Font.Normal - color: myPalette.text + Connections { + target: elisa - horizontalAlignment: Text.AlignLeft - } + onMusicManagerChanged: { + metaDataModel.initializeByTrackId(databaseId) + } + } + + Component.onCompleted: { + if (elisa.musicManager) { + metaDataModel.initializeByTrackId(databaseId) } } } diff --git a/src/qml/MediaTrackMetadataView.qml b/src/qml/MediaTrackMetadataView.qml --- a/src/qml/MediaTrackMetadataView.qml +++ b/src/qml/MediaTrackMetadataView.qml @@ -39,6 +39,8 @@ TrackMetadataModel { id: realModel + + manager: elisa.musicManager } modality: Qt.NonModal @@ -157,7 +159,7 @@ Label { id: metaDataLabels - text: model.name + text: i18nc('name of a property for the track metadata detailled view', '%1:', model.name) color: myPalette.text horizontalAlignment: Text.AlignRight @@ -224,19 +226,19 @@ onMusicManagerChanged: { if (databaseId !== 0) { - realModel.initializeByTrackId(elisa.musicManager, databaseId) + realModel.initializeByTrackId(databaseId) } else { - realModel.initializeByTrackFileName(elisa.musicManager, fileName) + realModel.initializeByTrackFileName(fileName) } } } Component.onCompleted: { if (elisa.musicManager) { if (databaseId !== 0) { - realModel.initializeByTrackId(elisa.musicManager, databaseId) + realModel.initializeByTrackId(databaseId) } else { - realModel.initializeByTrackFileName(elisa.musicManager, fileName) + realModel.initializeByTrackFileName(fileName) } } } diff --git a/src/qml/MetaDataDelegate.qml b/src/qml/MetaDataDelegate.qml new file mode 100644 --- /dev/null +++ b/src/qml/MetaDataDelegate.qml @@ -0,0 +1,106 @@ +/* + * Copyright 2016 Matthieu Gallien + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.10 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.2 + +import org.kde.elisa 1.0 + +RowLayout { + id: delegateRow + spacing: 0 + + width: topItem.width + height: metaDataLabelMetric.height * 1.5 + + TextMetrics { + id: metaDataLabelMetric + + text: model.name + + font.weight: Font.Bold + } + + Label { + id: metaDataLabels + + text: model.name + + font.weight: Font.Bold + + horizontalAlignment: Text.AlignLeft + + Layout.preferredWidth: 0.8 * elisaTheme.coverImageSize + Layout.rightMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin * 2 : 0 + Layout.leftMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin * 2 : 0 + } + + Loader { + active: model.type === TrackMetadataModel.TextEntry || model.type === TrackMetadataModel.IntegerEntry + visible: model.type === TrackMetadataModel.TextEntry || model.type === TrackMetadataModel.IntegerEntry + + Layout.fillWidth: true + + sourceComponent: LabelWithToolTip { + text: model.display + + horizontalAlignment: Text.AlignLeft + elide: Text.ElideRight + + anchors.fill: parent + } + } + + Loader { + active: model.type === TrackMetadataModel.DateEntry + visible: model.type === TrackMetadataModel.DateEntry + + Layout.fillWidth: true + + sourceComponent: LabelWithToolTip { + text: rawDate.toLocaleDateString() + + horizontalAlignment: Text.AlignLeft + elide: Text.ElideRight + + anchors.fill: parent + + property date rawDate: new Date(model.display) + } + } + + Loader { + active: model.type === TrackMetadataModel.RatingEntry + visible: model.type === TrackMetadataModel.RatingEntry + + Layout.fillWidth: true + + sourceComponent: RatingStar { + starRating: model.display + starSize: elisaTheme.ratingStarSize + + readOnly: true + + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + } + } + } +} diff --git a/src/resources.qrc b/src/resources.qrc --- a/src/resources.qrc +++ b/src/resources.qrc @@ -42,6 +42,7 @@ qml/ViewSelector.qml qml/PlayListAlbumHeader.qml qml/BasicPlayListAlbumHeader.qml + qml/MetaDataDelegate.qml windows/WindowsTheme.qml