diff --git a/src/models/trackmetadatamodel.cpp b/src/models/trackmetadatamodel.cpp index 4a6e213a..d14aa694 100644 --- a/src/models/trackmetadatamodel.cpp +++ b/src/models/trackmetadatamodel.cpp @@ -1,326 +1,326 @@ /* * Copyright 2018 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 "trackmetadatamodel.h" #include "musiclistenersmanager.h" #include TrackMetadataModel::TrackMetadataModel(QObject *parent) : QAbstractListModel(parent) { } int TrackMetadataModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return mTrackData.count(); } QVariant TrackMetadataModel::data(const QModelIndex &index, int role) const { auto result = QVariant{}; const auto currentKey = mTrackKeys[index.row()]; switch (role) { case Qt::DisplayRole: result = mTrackData[currentKey]; break; case ItemNameRole: 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: case DatabaseInterface::ShadowForImageRole: case DatabaseInterface::ChildModelRole: case DatabaseInterface::StringDurationRole: case DatabaseInterface::MilliSecondsDurationRole: case DatabaseInterface::AllArtistsRole: case DatabaseInterface::HighestTrackRating: case DatabaseInterface::ResourceRole: case DatabaseInterface::IdRole: case DatabaseInterface::DatabaseIdRole: case DatabaseInterface::IsSingleDiscAlbumRole: case DatabaseInterface::ContainerDataRole: case DatabaseInterface::IsPartialDataRole: case DatabaseInterface::AlbumIdRole: case DatabaseInterface::HasEmbeddedCover: case DatabaseInterface::FileModificationTime: case DatabaseInterface::FirstPlayDate: case DatabaseInterface::PlayFrequency: case DatabaseInterface::ElementTypeRole: break; } break; case ItemTypeRole: switch (currentKey) { case DatabaseInterface::TitleRole: result = TextEntry; break; case DatabaseInterface::ArtistRole: result = TextEntry; break; case DatabaseInterface::AlbumRole: result = TextEntry; break; case DatabaseInterface::AlbumArtistRole: result = TextEntry; break; case DatabaseInterface::TrackNumberRole: result = IntegerEntry; break; case DatabaseInterface::DiscNumberRole: result = IntegerEntry; break; case DatabaseInterface::RatingRole: result = RatingEntry; break; case DatabaseInterface::GenreRole: result = TextEntry; break; case DatabaseInterface::LyricistRole: result = TextEntry; break; case DatabaseInterface::ComposerRole: result = TextEntry; break; case DatabaseInterface::CommentRole: result = TextEntry; break; case DatabaseInterface::YearRole: result = IntegerEntry; break; case DatabaseInterface::LastPlayDate: result = DateEntry; break; case DatabaseInterface::PlayCounter: result = IntegerEntry; break; case DatabaseInterface::DurationRole: case DatabaseInterface::SampleRateRole: case DatabaseInterface::BitRateRole: case DatabaseInterface::ChannelsRole: case DatabaseInterface::SecondaryTextRole: case DatabaseInterface::ImageUrlRole: case DatabaseInterface::ShadowForImageRole: case DatabaseInterface::ChildModelRole: case DatabaseInterface::StringDurationRole: case DatabaseInterface::MilliSecondsDurationRole: case DatabaseInterface::AllArtistsRole: case DatabaseInterface::HighestTrackRating: case DatabaseInterface::ResourceRole: case DatabaseInterface::IdRole: case DatabaseInterface::DatabaseIdRole: case DatabaseInterface::IsSingleDiscAlbumRole: case DatabaseInterface::ContainerDataRole: case DatabaseInterface::IsPartialDataRole: case DatabaseInterface::AlbumIdRole: case DatabaseInterface::HasEmbeddedCover: case DatabaseInterface::FileModificationTime: case DatabaseInterface::FirstPlayDate: case DatabaseInterface::PlayFrequency: case DatabaseInterface::ElementTypeRole: break; } break; } return result; } bool TrackMetadataModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (data(index, role) != value) { // FIXME: Implement me! emit dataChanged(index, index, QVector() << role); return true; } return false; } QHash TrackMetadataModel::roleNames() const { auto names = QAbstractListModel::roleNames(); names[ItemNameRole] = "name"; names[ItemTypeRole] = "type"; 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) { beginInsertRows(parent, row, row + count - 1); endInsertRows(); return true; } bool TrackMetadataModel::removeRows(int row, int count, const QModelIndex &parent) { beginRemoveRows(parent, row, row + count - 1); endRemoveRows(); return true; } const QUrl &TrackMetadataModel::coverUrl() const { return mCoverImage; } void TrackMetadataModel::trackData(const TrackMetadataModel::TrackDataType &trackData) { beginResetModel(); if (mTrackData.isValid()) { mTrackData.clear(); mTrackKeys.clear(); } for (auto role : {DatabaseInterface::TitleRole, DatabaseInterface::ArtistRole, DatabaseInterface::AlbumRole, DatabaseInterface::AlbumArtistRole, DatabaseInterface::TrackNumberRole, DatabaseInterface::DiscNumberRole, DatabaseInterface::RatingRole, DatabaseInterface::GenreRole, DatabaseInterface::LyricistRole, DatabaseInterface::ComposerRole, DatabaseInterface::CommentRole, DatabaseInterface::YearRole, DatabaseInterface::LastPlayDate, DatabaseInterface::PlayCounter}) { if (trackData.constFind(role) != trackData.constEnd()) { if (role == DatabaseInterface::RatingRole) { if (trackData[role].toInt() == 0) { continue; } } mTrackKeys.push_back(role); mTrackData[role] = trackData[role]; } } endResetModel(); mCoverImage = trackData[DatabaseInterface::ImageUrlRole].toUrl(); Q_EMIT coverUrlChanged(); auto rawFileUrl = trackData[DatabaseInterface::ResourceRole].toUrl(); if (rawFileUrl.isLocalFile()) { mFileUrl = rawFileUrl.toLocalFile(); } else { mFileUrl = rawFileUrl.toString(); } Q_EMIT fileUrlChanged(); } void TrackMetadataModel::initializeByTrackId(MusicListenersManager *manager, qulonglong databaseId) { mDataLoader.setDatabase(manager->viewDatabase()); manager->connectModel(&mDataLoader); connect(this, &TrackMetadataModel::needDataByDatabaseId, &mDataLoader, &ModelDataLoader::loadDataByDatabaseId); connect(&mDataLoader, &ModelDataLoader::allTrackData, this, &TrackMetadataModel::trackData); Q_EMIT needDataByDatabaseId(ElisaUtils::Track, databaseId); } void TrackMetadataModel::initializeByTrackFileName(MusicListenersManager *manager, const QUrl &fileName) { mDataLoader.setDatabase(manager->viewDatabase()); manager->connectModel(&mDataLoader); connect(this, &TrackMetadataModel::needDataByFileName, &mDataLoader, &ModelDataLoader::loadDataByFileName); connect(&mDataLoader, &ModelDataLoader::allTrackData, this, &TrackMetadataModel::trackData); Q_EMIT needDataByFileName(ElisaUtils::FileName, fileName); } #include "moc_trackmetadatamodel.cpp" diff --git a/src/qml/MediaTrackMetadataView.qml b/src/qml/MediaTrackMetadataView.qml index e8fb5955..2523f0b9 100644 --- a/src/qml/MediaTrackMetadataView.qml +++ b/src/qml/MediaTrackMetadataView.qml @@ -1,243 +1,243 @@ /* * Copyright 2017 Alexander Stippich * Copyright 2018 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.7 import QtQuick.Controls 2.2 import QtQuick.Window 2.2 import QtQml.Models 2.2 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 import org.kde.elisa 1.0 Window { id: trackMetadata property int databaseId: 0 property url fileName signal rejected() LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true title: i18nc("Window title for track metadata", "View Details") TrackMetadataModel { id: realModel } modality: Qt.NonModal flags: Qt.Dialog | Qt.WindowCloseButtonHint color: myPalette.window minimumHeight: elisaTheme.coverImageSize * 1.8 minimumWidth: elisaTheme.coverImageSize * 2.8 ColumnLayout { anchors.fill: parent anchors.margins: elisaTheme.layoutVerticalMargin spacing: elisaTheme.layoutVerticalMargin RowLayout { id: metadataView Layout.fillHeight: true Layout.fillWidth: true spacing: 0 Image { source: (realModel.coverUrl !== "" ? realModel.coverUrl : elisaTheme.tracksIcon) sourceSize.width: elisaTheme.coverImageSize sourceSize.height: elisaTheme.coverImageSize fillMode: Image.PreserveAspectFit Layout.alignment: Qt.AlignTop | Qt.AlignHCenter Layout.preferredHeight: elisaTheme.coverImageSize Layout.preferredWidth: elisaTheme.coverImageSize Layout.minimumHeight: elisaTheme.coverImageSize Layout.minimumWidth: elisaTheme.coverImageSize Layout.maximumHeight: elisaTheme.coverImageSize Layout.maximumWidth: elisaTheme.coverImageSize } ListView { id: trackData Layout.fillWidth: true Layout.fillHeight: true focus: true ScrollBar.vertical: ScrollBar { id: scrollBar } boundsBehavior: Flickable.StopAtBounds clip: true ScrollHelper { id: scrollHelper flickable: trackData anchors.fill: trackData } model: realModel delegate: metadataDelegate } } RowLayout { Layout.alignment: Qt.AlignLeft | Qt.AlignBottom Layout.topMargin: elisaTheme.layoutVerticalMargin Layout.bottomMargin: elisaTheme.layoutVerticalMargin spacing: elisaTheme.layoutHorizontalMargin Image { Layout.preferredWidth: fileNameLabel.height Layout.preferredHeight: fileNameLabel.height sourceSize.width: fileNameLabel.height sourceSize.height: fileNameLabel.height source: elisaTheme.folderIcon } LabelWithToolTip { id: fileNameLabel Layout.fillWidth: true text: realModel.fileUrl elide: Text.ElideRight } } DialogButtonBox { id: buttons Layout.fillWidth: true Layout.minimumHeight: implicitHeight standardButtons: DialogButtonBox.Close alignment: Qt.AlignRight onRejected: trackMetadata.rejected() } } Component { id: metadataDelegate RowLayout { id: delegateRow spacing: 0 width: scrollBar.visible ? trackData.width - scrollBar.width : trackData.width 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 Layout.preferredWidth: 0.8 * elisaTheme.coverImageSize Layout.rightMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0 Layout.leftMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin : 0 } Loader { active: 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 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 Layout.fillWidth: true sourceComponent: RatingStar { starRating: model.display starSize: elisaTheme.ratingStarSize readOnly: true anchors { left: parent.left top: parent.top bottom: parent.bottom } } } } } Connections { target: elisa onMusicManagerChanged: { if (databaseId !== 0) { realModel.initializeByTrackId(elisa.musicManager, databaseId) } else { realModel.initializeByTrackFileName(elisa.musicManager, fileName) } } } Component.onCompleted: { if (elisa.musicManager) { if (databaseId !== 0) { realModel.initializeByTrackId(elisa.musicManager, databaseId) } else { realModel.initializeByTrackFileName(elisa.musicManager, fileName) } } } }