diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dba839b4..652f0ea2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,491 +1,490 @@ include_directories(${elisa_BINARY_DIR}) set(elisaLib_SOURCES mediaplaylist.cpp musicaudiotrack.cpp progressindicator.cpp databaseinterface.cpp musiclistenersmanager.cpp managemediaplayercontrol.cpp manageheaderbar.cpp manageaudioplayer.cpp trackslistener.cpp elisaapplication.cpp modeldataloader.cpp notificationitem.cpp topnotificationmanager.cpp elisautils.cpp datatype.cpp abstractfile/abstractfilelistener.cpp abstractfile/abstractfilelisting.cpp filescanner.cpp viewmanager.cpp powermanagementinterface.cpp file/filelistener.cpp file/localfilelisting.cpp models/datamodel.cpp models/abstractmediaproxymodel.cpp models/gridviewproxymodel.cpp models/alltracksproxymodel.cpp models/singlealbumproxymodel.cpp models/trackmetadatamodel.cpp models/trackcontextmetadatamodel.cpp models/viewsmodel.cpp ) ecm_qt_declare_logging_category(elisaLib_SOURCES HEADER "indexersManager.h" IDENTIFIER "orgKdeElisaIndexersManager" CATEGORY_NAME "org.kde.elisa.indexers.manager" DEFAULT_SEVERITY Info ) ecm_qt_declare_logging_category(elisaLib_SOURCES HEADER "databaseLogging.h" IDENTIFIER "orgKdeElisaDatabase" CATEGORY_NAME "org.kde.elisa.database" DEFAULT_SEVERITY Info ) ecm_qt_declare_logging_category(elisaLib_SOURCES HEADER "abstractfile/indexercommon.h" IDENTIFIER "orgKdeElisaIndexer" CATEGORY_NAME "org.kde.elisa.indexer" DEFAULT_SEVERITY Info ) if (LIBVLC_FOUND) ecm_qt_declare_logging_category(elisaLib_SOURCES HEADER "vlcLogging.h" IDENTIFIER "orgKdeElisaPlayerVlc" CATEGORY_NAME "org.kde.elisa.player.vlc" DEFAULT_SEVERITY Info ) set(elisaLib_SOURCES ${elisaLib_SOURCES} audiowrapper_libvlc.cpp ) else() ecm_qt_declare_logging_category(elisaLib_SOURCES HEADER "qtMultimediaLogging.h" IDENTIFIER "orgKdeElisaPlayerQtMultimedia" CATEGORY_NAME "org.kde.elisa.player.qtMultimedia" DEFAULT_SEVERITY Info ) set(elisaLib_SOURCES ${elisaLib_SOURCES} audiowrapper_qtmultimedia.cpp ) endif() if (ANDROID) set(elisaLib_SOURCES ${elisaLib_SOURCES} android/androidmusiclistener.cpp ) endif() if (KF5KIO_FOUND) set(elisaLib_SOURCES ${elisaLib_SOURCES} models/filebrowsermodel.cpp models/filebrowserproxymodel.cpp ) endif() if (KF5Baloo_FOUND) if (Qt5DBus_FOUND) ecm_qt_declare_logging_category(elisaLib_SOURCES HEADER "baloo/baloocommon.h" IDENTIFIER "orgKdeElisaBaloo" CATEGORY_NAME "org.kde.elisa.baloo" DEFAULT_SEVERITY Info ) set(elisaLib_SOURCES ${elisaLib_SOURCES} baloo/localbaloofilelisting.cpp baloo/baloolistener.cpp baloo/baloodetector.cpp ) qt5_add_dbus_interface(elisaLib_SOURCES ${BALOO_DBUS_INTERFACES_DIR}/org.kde.baloo.main.xml baloo/main) qt5_add_dbus_interface(elisaLib_SOURCES ${BALOO_DBUS_INTERFACES_DIR}/org.kde.baloo.fileindexer.xml baloo/fileindexer) qt5_add_dbus_interface(elisaLib_SOURCES ${BALOO_DBUS_INTERFACES_DIR}/org.kde.baloo.scheduler.xml baloo/scheduler) qt5_add_dbus_adaptor(elisaLib_SOURCES ${BALOO_DBUS_INTERFACES_DIR}/org.kde.BalooWatcherApplication.xml baloo/localbaloofilelisting.h LocalBalooFileListing) endif() endif() if (Qt5DBus_FOUND) set(elisaLib_SOURCES ${elisaLib_SOURCES} mpris2/mpris2.cpp mpris2/mediaplayer2.cpp mpris2/mediaplayer2player.cpp ) endif() if (UPNPQT_FOUND) set(elisaLib_SOURCES ${elisaLib_SOURCES} upnp/upnpcontrolcontentdirectory.cpp upnp/upnpcontentdirectorymodel.cpp upnp/upnpcontrolconnectionmanager.cpp upnp/upnpcontrolmediaserver.cpp upnp/didlparser.cpp upnp/upnplistener.cpp upnp/upnpdiscoverallmusic.cpp ) endif() if (KF5Baloo_FOUND) if (Qt5DBus_FOUND) qt5_add_dbus_interface(elisaLib_SOURCES ${BALOO_DBUS_INTERFACES_DIR}/org.kde.baloo.fileindexer.xml baloo/fileindexer) qt5_add_dbus_interface(elisaLib_SOURCES ${BALOO_DBUS_INTERFACES_DIR}/org.kde.baloo.scheduler.xml baloo/scheduler) set(elisaLib_SOURCES ${elisaLib_SOURCES} ../src/baloo/baloolistener.cpp ../src/baloo/localbaloofilelisting.cpp ) endif() endif() kconfig_add_kcfg_files(elisaLib_SOURCES ../src/elisa_settings.kcfgc ) set(elisaLib_SOURCES ${elisaLib_SOURCES} ../src/elisa_core.kcfg ) add_library(elisaLib ${elisaLib_SOURCES}) target_link_libraries(elisaLib LINK_PUBLIC Qt5::Multimedia LINK_PRIVATE Qt5::Core Qt5::Sql Qt5::Widgets Qt5::Concurrent Qt5::Qml KF5::I18n KF5::CoreAddons KF5::ConfigCore KF5::ConfigGui) if (KF5FileMetaData_FOUND) target_link_libraries(elisaLib LINK_PRIVATE KF5::FileMetaData ) endif() if (KF5KIO_FOUND) target_link_libraries(elisaLib LINK_PUBLIC KF5::KIOCore KF5::KIOFileWidgets KF5::KIOWidgets ) endif() if (KF5XmlGui_FOUND) target_link_libraries(elisaLib LINK_PUBLIC KF5::XmlGui ) endif() if (KF5ConfigWidgets_FOUND) target_link_libraries(elisaLib LINK_PUBLIC KF5::ConfigWidgets ) endif() if (KF5KCMUtils_FOUND) target_link_libraries(elisaLib LINK_PUBLIC KF5::KCMUtils ) endif() if (KF5Baloo_FOUND) if (Qt5DBus_FOUND) target_link_libraries(elisaLib LINK_PUBLIC KF5::Baloo ) endif() endif() if (Qt5DBus_FOUND) target_link_libraries(elisaLib LINK_PUBLIC Qt5::DBus ) if (KF5DBusAddons_FOUND) target_link_libraries(elisaLib LINK_PUBLIC KF5::DBusAddons ) endif() endif() if (LIBVLC_FOUND) target_include_directories(elisaLib PRIVATE ${LIBVLC_INCLUDE_DIR} ) target_link_libraries(elisaLib LINK_PRIVATE ${LIBVLC_LIBRARY} ) endif() if (ANDROID) target_link_libraries(elisaLib LINK_PUBLIC Qt5::AndroidExtras ) endif() generate_export_header(elisaLib BASE_NAME ElisaLib EXPORT_FILE_NAME elisaLib_export.h) set_target_properties(elisaLib PROPERTIES VERSION 0.1 SOVERSION 0 EXPORT_NAME ElisaLib ) if (NOT APPLE AND NOT WIN32) install(TARGETS elisaLib LIBRARY DESTINATION ${KDE_INSTALL_FULL_LIBDIR}/elisa NAMELINK_SKIP RUNTIME DESTINATION ${KDE_INSTALL_FULL_LIBDIR}/elisa BUNDLE DESTINATION ${KDE_INSTALL_FULL_LIBDIR}/elisa ) else() install(TARGETS elisaLib ${INSTALL_TARGETS_DEFAULT_ARGS}) endif() set(elisaqmlplugin_SOURCES elisaqmlplugin.cpp datatype.cpp elisautils.cpp ) if (KF5FileMetaData_FOUND) set(elisaqmlplugin_SOURCES ${elisaqmlplugin_SOURCES} embeddedcoverageimageprovider.cpp ) endif() add_library(elisaqmlplugin SHARED ${elisaqmlplugin_SOURCES}) target_link_libraries(elisaqmlplugin LINK_PRIVATE Qt5::Quick Qt5::Widgets KF5::ConfigCore KF5::ConfigGui elisaLib ) if (KF5FileMetaData_FOUND) target_link_libraries(elisaqmlplugin LINK_PRIVATE KF5::FileMetaData ) endif() set_target_properties(elisaqmlplugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/org/kde/elisa ) if (NOT APPLE AND NOT WIN32) set_target_properties(elisaqmlplugin PROPERTIES INSTALL_RPATH "${KDE_INSTALL_FULL_LIBDIR}/elisa;${CMAKE_INSTALL_RPATH}" ) endif() install(TARGETS elisaqmlplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/elisa/) install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/elisa) add_custom_target(copy) add_custom_target(copy2) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/org/kde/elisa) add_custom_command(TARGET copy PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_BINARY_DIR}/bin/org/kde/elisa/) add_custom_command(TARGET copy2 PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/plugins.qmltypes ${CMAKE_BINARY_DIR}/bin/org/kde/elisa/) add_dependencies(elisaqmlplugin copy copy2) if (Qt5Quick_FOUND AND Qt5Widgets_FOUND) set(elisa_SOURCES main.cpp windows/WindowsTheme.qml windows/PlatformIntegration.qml android/ElisaMainWindow.qml android/AndroidTheme.qml android/PlatformIntegration.qml android/AlbumsView.qml android/ArtistsView.qml android/TracksView.qml android/GenresView.qml qml/ElisaMainWindow.qml qml/ApplicationMenu.qml qml/BaseTheme.qml qml/Theme.qml qml/PlatformIntegration.qml qml/LabelWithToolTip.qml qml/RatingStar.qml qml/DraggableItem.qml qml/PassiveNotification.qml qml/TopNotification.qml qml/TopNotificationItem.qml qml/TrackImportNotification.qml qml/HeaderBar.qml qml/NavigationActionBar.qml qml/MediaPlayerControl.qml qml/ContextView.qml qml/ContentView.qml qml/ViewSelector.qml qml/ViewSelectorDelegate.qml qml/DataGridView.qml qml/DataListView.qml qml/MediaPlayListView.qml qml/PlayListBasicView.qml qml/PlayListEntry.qml qml/SimplePlayListView.qml - qml/SimplePlayListEntry.qml qml/PlayListAlbumHeader.qml qml/BasicPlayListAlbumHeader.qml qml/MetaDataDelegate.qml qml/MediaTrackDelegate.qml qml/TracksDiscHeader.qml qml/MediaAlbumTrackDelegate.qml qml/MediaTrackMetadataView.qml qml/GridBrowserView.qml qml/GridBrowserDelegate.qml qml/ListBrowserView.qml qml/FileBrowserDelegate.qml qml/FileBrowserView.qml qml/ScrollHelper.qml qml/FlatButtonWithToolTip.qml qml/HeaderFooterToolbar.qml ) qt5_add_resources(elisa_SOURCES resources.qrc) set_property(SOURCE qrc_resources.cpp PROPERTY SKIP_AUTOMOC ON) set(elisa_ICONS_PNG ../icons/128-apps-elisa.png ../icons/64-apps-elisa.png ../icons/48-apps-elisa.png ../icons/32-apps-elisa.png ../icons/22-apps-elisa.png ../icons/16-apps-elisa.png ) # add icons to application sources, to have them bundled ecm_add_app_icon(elisa_SOURCES ICONS ${elisa_ICONS_PNG}) add_executable(elisa ${elisa_SOURCES}) target_include_directories(elisa PRIVATE ${KDSoap_INCLUDE_DIRS}) target_link_libraries(elisa LINK_PRIVATE elisaLib Qt5::Widgets Qt5::QuickControls2 KF5::I18n KF5::CoreAddons KF5::ConfigCore KF5::ConfigGui ) if (ANDROID) target_link_libraries(elisa LINK_PRIVATE Qt5::AndroidExtras Qt5::Svg Qt5::Sql Qt5::Concurrent KF5::Kirigami2 ) endif() if (KF5Crash_FOUND) target_link_libraries(elisa LINK_PRIVATE KF5::Crash ) endif() if (KF5Declarative_FOUND) target_link_libraries(elisa LINK_PRIVATE KF5::Declarative ) endif() if (NOT APPLE AND NOT WIN32) set_target_properties(elisa PROPERTIES INSTALL_RPATH "${KDE_INSTALL_FULL_LIBDIR}/elisa;${CMAKE_INSTALL_RPATH}" ) endif() install(TARGETS elisa ${INSTALL_TARGETS_DEFAULT_ARGS}) endif() if (KF5ConfigWidgets_FOUND AND KF5Declarative_FOUND) add_subdirectory(localFileConfiguration) endif() set(elisaImport_SOURCES elisaimport.cpp elisaimportapplication.cpp ) kconfig_add_kcfg_files(elisaImport_SOURCES ../src/elisa_settings.kcfgc ) set(elisaImport_SOURCES ${elisaImport_SOURCES} ../src/elisa_core.kcfg ) add_executable(elisaImport ${elisaImport_SOURCES}) target_link_libraries(elisaImport LINK_PRIVATE KF5::ConfigCore KF5::ConfigGui elisaLib ) if (KF5FileMetaData_FOUND) target_link_libraries(elisaImport LINK_PRIVATE KF5::FileMetaData ) endif() set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/bin CACHE INTERNAL "qml import path" FORCE) if (ANDROID) kirigami_package_breeze_icons(ICONS elisa) endif() diff --git a/src/qml/PlayListEntry.qml b/src/qml/PlayListEntry.qml index 5bf13f1b..7b76905e 100644 --- a/src/qml/PlayListEntry.qml +++ b/src/qml/PlayListEntry.qml @@ -1,533 +1,490 @@ /* * Copyright 2016-2017 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.Layouts 1.2 import QtQuick.Controls 2.3 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.elisa 1.0 FocusScope { id: playListEntry property var index property bool isSingleDiscAlbum property int isPlaying property bool isSelected property bool isValid property bool isAlternateColor property bool containsMouse property int databaseId: 0 property string title property string artist property string album property string albumArtist property string duration property url fileName property url imageUrl property int trackNumber property int discNumber property int rating property bool hasValidDiscNumber: true property int scrollBarWidth - property bool noBackground: false + property bool simpleMode: false signal startPlayback() signal pausePlayback() signal removeFromPlaylist(var trackIndex) signal switchToTrack(var trackIndex) Accessible.role: Accessible.ListItem Accessible.name: title + ' ' + album + ' ' + artist height: elisaTheme.playListDelegateHeight Action { id: removeFromPlayList text: i18nc("Remove current track from play list", "Remove") icon.name: "error" onTriggered: { playListEntry.removeFromPlaylist(playListEntry.index) } } Action { id: playNow text: i18nc("Play now current track from play list", "Play Now") icon.name: "media-playback-start" enabled: !(isPlaying === MediaPlayList.IsPlaying) && isValid onTriggered: { if (isPlaying === MediaPlayList.NotPlaying) { playListEntry.switchToTrack(playListEntry.index) } playListEntry.startPlayback() } } Action { id: pauseNow text: i18nc("Pause current track from play list", "Pause") icon.name: "media-playback-pause" enabled: isPlaying === MediaPlayList.IsPlaying && isValid onTriggered: playListEntry.pausePlayback() } Action { id: showInfo text: i18nc("Show track metadata", "View Details") icon.name: "help-about" enabled: isValid onTriggered: { if (metadataLoader.active === false) { metadataLoader.active = true } else { metadataLoader.item.close(); metadataLoader.active = false } } } Loader { id: metadataLoader active: false onLoaded: item.show() sourceComponent: MediaTrackMetadataView { databaseId: playListEntry.databaseId fileName: playListEntry.fileName onRejected: metadataLoader.active = false; } } Rectangle { id: entryBackground anchors.fill: parent anchors.rightMargin: LayoutMirroring.enabled ? scrollBarWidth : 0 z: 1 - color: myPalette.base + color: simpleMode ? "transparent" : myPalette.base height: elisaTheme.playListDelegateHeight } RowLayout { id: trackRow z: 2 anchors.fill: parent anchors.leftMargin: elisaTheme.layoutHorizontalMargin anchors.rightMargin: LayoutMirroring.enabled ? scrollBarWidth : 0 spacing: elisaTheme.layoutHorizontalMargin / 4 Item { id: playIconItem implicitHeight: elisaTheme.playListDelegateHeight implicitWidth: elisaTheme.playListDelegateHeight Layout.maximumWidth: elisaTheme.playListDelegateHeight Layout.maximumHeight: elisaTheme.playListDelegateHeight Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0 Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0 Image { id: playIcon anchors.centerIn: parent - opacity: 0 + opacity: (isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused ? 1.0 : 0.0) source: (isPlaying === MediaPlayList.IsPlaying ? Qt.resolvedUrl(elisaTheme.playingIndicatorIcon) : Qt.resolvedUrl(elisaTheme.pausedIndicatorIcon)) width: elisaTheme.smallControlButtonSize height: elisaTheme.smallControlButtonSize sourceSize.width: elisaTheme.smallControlButtonSize sourceSize.height: elisaTheme.smallControlButtonSize fillMode: Image.PreserveAspectFit mirror: LayoutMirroring.enabled visible: opacity > 0.0 + + layer.enabled: simpleMode + layer.effect: ColorOverlay { + cached: true + + color: myPalette.highlightedText + } } } Item { id: fakeDiscNumberItem visible: isValid && (!hasValidDiscNumber || isSingleDiscAlbum) Layout.preferredWidth: (fakeDiscNumberSize.boundingRect.width - fakeDiscNumberSize.boundingRect.x) + (elisaTheme.layoutHorizontalMargin / 4) Layout.minimumWidth: (fakeDiscNumberSize.boundingRect.width - fakeDiscNumberSize.boundingRect.x) + (elisaTheme.layoutHorizontalMargin / 4) Layout.maximumWidth: (fakeDiscNumberSize.boundingRect.width - fakeDiscNumberSize.boundingRect.x) + (elisaTheme.layoutHorizontalMargin / 4) TextMetrics { id: fakeDiscNumberSize text: '/9' } } Label { id: trackNumberLabel horizontalAlignment: Text.AlignRight text: trackNumber !== -1 ? Number(trackNumber).toLocaleString(Qt.locale(), 'f', 0) : '' font.weight: (isPlaying ? Font.Bold : Font.Light) - color: myPalette.text + color: simpleMode ? myPalette.highlightedText : myPalette.text Layout.alignment: Qt.AlignVCenter | Qt.AlignRight visible: isValid Layout.preferredWidth: ((trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) > (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x) ? (trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) : (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x)) Layout.minimumWidth: ((trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) > (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x) ? (trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) : (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x)) Layout.maximumWidth: ((trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) > (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x) ? (trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) : (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x)) Layout.rightMargin: !LayoutMirroring.enabled ? (discNumber !== 0 && !isSingleDiscAlbum ? 0 : elisaTheme.layoutHorizontalMargin / 2) : 0 Layout.leftMargin: LayoutMirroring.enabled ? (discNumber !== 0 && !isSingleDiscAlbum ? 0 : elisaTheme.layoutHorizontalMargin / 2) : 0 TextMetrics { id: trackNumberSize text: (99).toLocaleString(Qt.locale(), 'f', 0) } TextMetrics { id: realTrackNumberSize text: Number(trackNumber).toLocaleString(Qt.locale(), 'f', 0) } } Label { horizontalAlignment: Text.AlignCenter text: '/' visible: isValid && discNumber !== 0 && !isSingleDiscAlbum font.weight: (isPlaying ? Font.Bold : Font.Light) - color: myPalette.text + color: simpleMode ? myPalette.highlightedText : myPalette.text Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Layout.preferredWidth: (numberSeparatorSize.boundingRect.width - numberSeparatorSize.boundingRect.x) Layout.minimumWidth: (numberSeparatorSize.boundingRect.width - numberSeparatorSize.boundingRect.x) Layout.maximumWidth: (numberSeparatorSize.boundingRect.width - numberSeparatorSize.boundingRect.x) TextMetrics { id: numberSeparatorSize text: '/' } } Label { horizontalAlignment: Text.AlignRight font.weight: (isPlaying ? Font.Bold : Font.Light) - color: myPalette.text + color: simpleMode ? myPalette.highlightedText : myPalette.text text: Number(discNumber).toLocaleString(Qt.locale(), 'f', 0) visible: isValid && discNumber !== 0 && !isSingleDiscAlbum Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.preferredWidth: ((discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) > (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x) ? (discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) : (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x)) Layout.minimumWidth: ((discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) > (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x) ? (discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) : (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x)) Layout.maximumWidth: ((discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) > (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x) ? (discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) : (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x)) Layout.rightMargin: !LayoutMirroring.enabled ? (elisaTheme.layoutHorizontalMargin / 2) : 0 Layout.leftMargin: LayoutMirroring.enabled ? (elisaTheme.layoutHorizontalMargin / 2) : 0 TextMetrics { id: discNumberSize text: '9' } TextMetrics { id: realDiscNumberSize text: Number(discNumber).toLocaleString(Qt.locale(), 'f', 0) } } LabelWithToolTip { id: mainCompactLabel text: title font.weight: (isPlaying ? Font.Bold : Font.Normal) - color: myPalette.text + color: simpleMode ? myPalette.highlightedText : myPalette.text Layout.maximumWidth: mainCompactLabel.implicitWidth + 1 Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft visible: isValid elide: Text.ElideRight horizontalAlignment: Text.AlignLeft } LabelWithToolTip { id: mainInvalidCompactLabel text: title font.weight: Font.Normal - color: myPalette.text + color: simpleMode ? myPalette.highlightedText : myPalette.text Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft visible: !isValid elide: Text.ElideRight } Item { Layout.fillWidth: true Layout.preferredWidth: 0 } - FlatButtonWithToolTip { - id: infoButton - objectName: 'infoButton' - - implicitHeight: elisaTheme.playListDelegateHeight - implicitWidth: elisaTheme.playListDelegateHeight - icon.height: elisaTheme.smallControlButtonSize - icon.width: elisaTheme.smallControlButtonSize - - opacity: 0 - - visible: opacity > 0.1 - - action: showInfo + Loader { + id: hoverLoader + active: false + visible: active Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - FlatButtonWithToolTip { - id: playPauseButton - objectName: 'playPauseButton' + sourceComponent: Row { + anchors.centerIn: parent + FlatButtonWithToolTip { + id: infoButton + objectName: 'infoButton' - implicitHeight: elisaTheme.playListDelegateHeight - implicitWidth: elisaTheme.playListDelegateHeight - icon.height: elisaTheme.smallControlButtonSize - icon.width: elisaTheme.smallControlButtonSize + implicitHeight: elisaTheme.playListDelegateHeight + implicitWidth: elisaTheme.playListDelegateHeight + icon.height: elisaTheme.smallControlButtonSize + icon.width: elisaTheme.smallControlButtonSize - opacity: 0 + action: showInfo + } - scale: LayoutMirroring.enabled ? -1 : 1 // We can mirror the symmetrical pause icon + FlatButtonWithToolTip { + id: playPauseButton + objectName: 'playPauseButton' - visible: opacity > 0.1 - action: !(isPlaying === MediaPlayList.IsPlaying) ? playNow : pauseNow + implicitHeight: elisaTheme.playListDelegateHeight + implicitWidth: elisaTheme.playListDelegateHeight + icon.height: elisaTheme.smallControlButtonSize + icon.width: elisaTheme.smallControlButtonSize - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } + scale: LayoutMirroring.enabled ? -1 : 1 // We can mirror the symmetrical pause icon - FlatButtonWithToolTip { - id: removeButton - objectName: 'removeButton' + action: !(isPlaying === MediaPlayList.IsPlaying) ? playNow : pauseNow + } - opacity: 0 + FlatButtonWithToolTip { + id: removeButton + objectName: 'removeButton' - visible: opacity > 0.1 - action: removeFromPlayList + action: removeFromPlayList - implicitHeight: elisaTheme.playListDelegateHeight - implicitWidth: elisaTheme.playListDelegateHeight - icon.height: elisaTheme.smallControlButtonSize - icon.width: elisaTheme.smallControlButtonSize + implicitHeight: elisaTheme.playListDelegateHeight + implicitWidth: elisaTheme.playListDelegateHeight + icon.height: elisaTheme.smallControlButtonSize + icon.width: elisaTheme.smallControlButtonSize + } + + } } RatingStar { id: ratingWidget starRating: rating starSize: elisaTheme.ratingStarSize visible: rating > 0 } LabelWithToolTip { id: durationLabel text: duration font.weight: (isPlaying ? Font.Bold : Font.Normal) - color: myPalette.text + color: simpleMode ? myPalette.highlightedText : myPalette.text Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.leftMargin: elisaTheme.layoutHorizontalMargin Layout.rightMargin: elisaTheme.layoutHorizontalMargin horizontalAlignment: Text.AlignRight } } states: [ State { name: 'notSelected' - when: !containsMouse && !isSelected && !playListEntry.activeFocus - PropertyChanges { - target: removeButton - opacity: 0 - } + when: !containsMouse && !isSelected && !playListEntry.activeFocus && !simpleMode PropertyChanges { - target: infoButton - opacity: 0 - } - PropertyChanges { - target: playPauseButton - opacity: 0 - } - PropertyChanges { - target: playIcon - opacity: (isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused ? 1.0 : 0.0) + target: hoverLoader + active: false } PropertyChanges { target: entryBackground color: (isAlternateColor ? myPalette.alternateBase : myPalette.base) } PropertyChanges { target: entryBackground opacity: 1. } PropertyChanges { target: ratingWidget hoverWidgetOpacity: 0.0 } }, State { name: 'hovered' - when: containsMouse && !playListEntry.activeFocus - PropertyChanges { - target: removeButton - opacity: 1 - } - PropertyChanges { - target: playPauseButton - opacity: 1 - } + when: containsMouse && !playListEntry.activeFocus && !simpleMode PropertyChanges { - target: infoButton - opacity: 1 - } - PropertyChanges { - target: playIcon - opacity: (isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused ? 1.0 : 0.0) + target: hoverLoader + active: true } PropertyChanges { target: entryBackground color: myPalette.highlight } PropertyChanges { target: entryBackground opacity: 0.2 } PropertyChanges { target: ratingWidget hoverWidgetOpacity: 1.0 } }, State { name: 'selected' - when: !playListEntry.activeFocus && isSelected + when: !playListEntry.activeFocus && isSelected && !simpleMode PropertyChanges { - target: removeButton - opacity: 0 - } - PropertyChanges { - target: playPauseButton - opacity: 0 - } - PropertyChanges { - target: infoButton - opacity: 0 - } - PropertyChanges { - target: playIcon - opacity: (isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused ? 1.0 : 0.0) + target: hoverLoader + active: false } PropertyChanges { target: entryBackground color: myPalette.mid } PropertyChanges { target: entryBackground opacity: 1. } PropertyChanges { target: ratingWidget hoverWidgetOpacity: 1.0 } }, State { name: 'focused' - when: playListEntry.activeFocus - PropertyChanges { - target: removeButton - opacity: 1 - } + when: playListEntry.activeFocus && !simpleMode PropertyChanges { - target: playPauseButton - opacity: 1 - } - PropertyChanges { - target: infoButton - opacity: 1 - } - PropertyChanges { - target: playIcon - opacity: (isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused ? 1.0 : 0.0) + target: hoverLoader + active: true } PropertyChanges { target: entryBackground color: myPalette.highlight } PropertyChanges { target: entryBackground opacity: 0.6 } PropertyChanges { target: ratingWidget hoverWidgetOpacity: 1.0 } } ] } diff --git a/src/qml/SimplePlayListEntry.qml b/src/qml/SimplePlayListEntry.qml deleted file mode 100644 index 2dcb59ac..00000000 --- a/src/qml/SimplePlayListEntry.qml +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright 2016-2017 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.Layouts 1.2 -import QtQuick.Controls 2.3 -import QtQuick.Window 2.2 -import QtGraphicalEffects 1.0 -import org.kde.elisa 1.0 - -FocusScope { - id: playListEntry - - property var index - property bool isSingleDiscAlbum - property int isPlaying - property bool isValid - property int databaseId: 0 - property string title - property string artist - property string album - property string albumArtist - property string duration - property url fileName - property url imageUrl - property int trackNumber - property int discNumber - property int rating - property bool hasValidDiscNumber: true - property int scrollBarWidth - - signal switchToTrack(var trackIndex) - - Accessible.role: Accessible.ListItem - Accessible.name: title + ' ' + album + ' ' + artist - - height: elisaTheme.playListDelegateHeight - - Action { - id: playNow - text: i18nc("Play now current track from play list", "Play Now") - icon.name: "media-playback-start" - enabled: !(isPlaying === MediaPlayList.IsPlaying) && isValid - onTriggered: { - playListEntry.switchToTrack(playListEntry.index) - } - } - - MouseArea { - anchors.fill: parent - - onClicked: playNow.trigger(this) - } - - RowLayout { - id: trackRow - - anchors.fill: parent - - spacing: elisaTheme.layoutHorizontalMargin / 4 - - Item { - id: playIconItem - - implicitHeight: elisaTheme.playListDelegateHeight - implicitWidth: elisaTheme.playListDelegateHeight - Layout.maximumWidth: elisaTheme.playListDelegateHeight - Layout.maximumHeight: elisaTheme.playListDelegateHeight - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - Layout.leftMargin: !LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0 - Layout.rightMargin: LayoutMirroring.enabled ? elisaTheme.layoutHorizontalMargin / 2 : 0 - - Image { - id: playIcon - - anchors.centerIn: parent - - opacity: ((isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused) ? 1.0 : 0.0) - - source: (isPlaying === MediaPlayList.IsPlaying ? - Qt.resolvedUrl(elisaTheme.playingIndicatorIcon) : Qt.resolvedUrl(elisaTheme.pausedIndicatorIcon)) - - width: elisaTheme.smallControlButtonSize - height: elisaTheme.smallControlButtonSize - - sourceSize.width: elisaTheme.smallControlButtonSize - sourceSize.height: elisaTheme.smallControlButtonSize - fillMode: Image.PreserveAspectFit - mirror: LayoutMirroring.enabled - visible: opacity > 0.0 - - layer.enabled: true - layer.effect: ColorOverlay { - cached: true - - color: myPalette.highlightedText - } - - Behavior on opacity { - NumberAnimation { - easing.type: Easing.InOutQuad - duration: 250 - } - } - } - } - - Item { - id: fakeDiscNumberItem - - visible: isValid && (!hasValidDiscNumber || isSingleDiscAlbum) - - Layout.preferredWidth: (fakeDiscNumberSize.boundingRect.width - fakeDiscNumberSize.boundingRect.x) + (elisaTheme.layoutHorizontalMargin / 4) - Layout.minimumWidth: (fakeDiscNumberSize.boundingRect.width - fakeDiscNumberSize.boundingRect.x) + (elisaTheme.layoutHorizontalMargin / 4) - Layout.maximumWidth: (fakeDiscNumberSize.boundingRect.width - fakeDiscNumberSize.boundingRect.x) + (elisaTheme.layoutHorizontalMargin / 4) - - TextMetrics { - id: fakeDiscNumberSize - - text: '/9' - } - } - - Label { - id: trackNumberLabel - - horizontalAlignment: Text.AlignRight - - text: trackNumber !== -1 ? Number(trackNumber).toLocaleString(Qt.locale(), 'f', 0) : '' - - font.weight: (isPlaying ? Font.Bold : Font.Light) - color: myPalette.highlightedText - - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - - visible: isValid - - Layout.preferredWidth: ((trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) > (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x) ? - (trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) : - (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x)) - Layout.minimumWidth: ((trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) > (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x) ? - (trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) : - (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x)) - Layout.maximumWidth: ((trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) > (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x) ? - (trackNumberSize.boundingRect.width - trackNumberSize.boundingRect.x) : - (realTrackNumberSize.boundingRect.width - realTrackNumberSize.boundingRect.x)) - - Layout.rightMargin: !LayoutMirroring.enabled ? (discNumber !== 0 && !isSingleDiscAlbum ? - 0 : elisaTheme.layoutHorizontalMargin / 2) : 0 - Layout.leftMargin: LayoutMirroring.enabled ? (discNumber !== 0 && !isSingleDiscAlbum ? - 0 : elisaTheme.layoutHorizontalMargin / 2) : 0 - - TextMetrics { - id: trackNumberSize - - text: (99).toLocaleString(Qt.locale(), 'f', 0) - } - - TextMetrics { - id: realTrackNumberSize - - text: Number(trackNumber).toLocaleString(Qt.locale(), 'f', 0) - } - } - - Label { - horizontalAlignment: Text.AlignCenter - - text: '/' - - visible: isValid && discNumber !== 0 && !isSingleDiscAlbum - - font.weight: (isPlaying ? Font.Bold : Font.Light) - color: myPalette.highlightedText - - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - - Layout.preferredWidth: (numberSeparatorSize.boundingRect.width - numberSeparatorSize.boundingRect.x) - Layout.minimumWidth: (numberSeparatorSize.boundingRect.width - numberSeparatorSize.boundingRect.x) - Layout.maximumWidth: (numberSeparatorSize.boundingRect.width - numberSeparatorSize.boundingRect.x) - - TextMetrics { - id: numberSeparatorSize - - text: '/' - } - } - - Label { - horizontalAlignment: Text.AlignRight - - font.weight: (isPlaying ? Font.Bold : Font.Light) - color: myPalette.highlightedText - - text: Number(discNumber).toLocaleString(Qt.locale(), 'f', 0) - - visible: isValid && discNumber !== 0 && !isSingleDiscAlbum - - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - - Layout.preferredWidth: ((discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) > (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x) ? - (discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) : - (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x)) - Layout.minimumWidth: ((discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) > (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x) ? - (discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) : - (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x)) - Layout.maximumWidth: ((discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) > (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x) ? - (discNumberSize.boundingRect.width - discNumberSize.boundingRect.x) : - (realDiscNumberSize.boundingRect.width - realDiscNumberSize.boundingRect.x)) - - Layout.rightMargin: !LayoutMirroring.enabled ? (elisaTheme.layoutHorizontalMargin / 2) : 0 - Layout.leftMargin: LayoutMirroring.enabled ? (elisaTheme.layoutHorizontalMargin / 2) : 0 - - TextMetrics { - id: discNumberSize - - text: '9' - } - - TextMetrics { - id: realDiscNumberSize - - text: Number(discNumber).toLocaleString(Qt.locale(), 'f', 0) - } - } - - LabelWithToolTip { - id: mainCompactLabel - - text: title - - font.weight: (isPlaying ? Font.Bold : Font.Normal) - color: myPalette.highlightedText - - Layout.maximumWidth: mainCompactLabel.implicitWidth + 1 - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - - visible: isValid - - elide: Text.ElideRight - horizontalAlignment: Text.AlignLeft - } - - LabelWithToolTip { - id: mainInvalidCompactLabel - - text: title - - font.weight: Font.Normal - color: myPalette.highlightedText - - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - - visible: !isValid - - elide: Text.ElideRight - } - - Item { - Layout.fillWidth: true - Layout.preferredWidth: 0 - } - - RatingStar { - id: ratingWidget - - starRating: rating - - starSize: elisaTheme.ratingStarSize - } - - LabelWithToolTip { - id: durationLabel - - text: duration - - font.weight: (isPlaying ? Font.Bold : Font.Normal) - color: myPalette.highlightedText - - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - Layout.leftMargin: elisaTheme.layoutHorizontalMargin / 2 - Layout.rightMargin: elisaTheme.layoutHorizontalMargin / 2 - - horizontalAlignment: Text.AlignRight - } - } - - -} - diff --git a/src/qml/SimplePlayListView.qml b/src/qml/SimplePlayListView.qml index 659a1842..7a9bbb28 100644 --- a/src/qml/SimplePlayListView.qml +++ b/src/qml/SimplePlayListView.qml @@ -1,119 +1,127 @@ /* * Copyright 2016-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.10 import QtQuick.Controls 2.2 import QtQml.Models 2.1 import org.kde.elisa 1.0 ListView { id: playListView property alias playListModel: playListModelDelegate.model signal startPlayback() signal pausePlayback() signal displayError(var errorText) focus: true activeFocusOnTab: true keyNavigationEnabled: true section.property: 'albumSection' section.criteria: ViewSection.FullString section.labelPositioning: ViewSection.InlineLabels section.delegate: BasicPlayListAlbumHeader { headerData: JSON.parse(section) width: scrollBar.visible ? (!LayoutMirroring.enabled ? playListView.width - scrollBar.width : playListView.width) : playListView.width height: elisaTheme.playListHeaderHeight - 3 * elisaTheme.layoutVerticalMargin textColor: myPalette.highlightedText } ScrollBar.vertical: ScrollBar { id: scrollBar } boundsBehavior: Flickable.StopAtBounds clip: true add: Transition { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 100 } } populate: Transition { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 100 } } remove: Transition { NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 100 } } displaced: Transition { NumberAnimation { properties: "x,y"; duration: 100; easing.type: Easing.InOutQuad} } model: DelegateModel { id: playListModelDelegate groups: [ DelegateModelGroup { name: "selected" } ] - delegate: SimplePlayListEntry { - id: entry - - focus: true - + delegate: MouseArea { + id: item + height: elisaTheme.playListDelegateHeight width: scrollBar.visible ? (!LayoutMirroring.enabled ? playListView.width - scrollBar.width : playListView.width) : playListView.width - scrollBarWidth: scrollBar.visible ? scrollBar.width : 0 - - index: model.index - - databaseId: model.databaseId ? model.databaseId : 0 - title: model.title ? model.title : '' - artist: model.artist ? model.artist : '' - album: model.album ? model.album : '' - albumArtist: model.albumArtist ? model.albumArtist : '' - duration: model.duration ? model.duration : '' - fileName: model.trackResource ? model.trackResource : '' - imageUrl: model.imageUrl ? model.imageUrl : '' - trackNumber: model.trackNumber ? model.trackNumber : -1 - discNumber: model.discNumber ? model.discNumber : -1 - rating: model.rating ? model.rating : 0 - isSingleDiscAlbum: model.isSingleDiscAlbum - isValid: model.isValid - isPlaying: model.isPlaying - - onSwitchToTrack: playListView.playListModel.switchTo(trackIndex) + + onClicked: playListView.playListModel.switchTo(index) + + PlayListEntry { + id: entry + + focus: true + + width: scrollBar.visible ? (!LayoutMirroring.enabled ? playListView.width - scrollBar.width : playListView.width) : playListView.width + scrollBarWidth: scrollBar.visible ? scrollBar.width : 0 + + index: model.index + containsMouse: item.containsMouse + simpleMode: true + + databaseId: model.databaseId ? model.databaseId : 0 + title: model.title ? model.title : '' + artist: model.artist ? model.artist : '' + album: model.album ? model.album : '' + albumArtist: model.albumArtist ? model.albumArtist : '' + duration: model.duration ? model.duration : '' + fileName: model.trackResource ? model.trackResource : '' + imageUrl: model.imageUrl ? model.imageUrl : '' + trackNumber: model.trackNumber ? model.trackNumber : -1 + discNumber: model.discNumber ? model.discNumber : -1 + rating: model.rating ? model.rating : 0 + isSingleDiscAlbum: model.isSingleDiscAlbum + isValid: model.isValid + isPlaying: model.isPlaying + } } } } diff --git a/src/resources.qrc b/src/resources.qrc index 6423dc47..5a7c85b9 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -1,61 +1,60 @@ qml/MediaPlayerControl.qml qml/RatingStar.qml qml/MediaPlayListView.qml qml/ElisaMainWindow.qml qml/ApplicationMenu.qml qml/HeaderBar.qml qml/ContextView.qml qml/ContentView.qml qml/DraggableItem.qml qml/PassiveNotification.qml qml/NavigationActionBar.qml qml/PlayListEntry.qml qml/Theme.qml qml/PlatformIntegration.qml qml/LabelWithToolTip.qml qml/TopNotification.qml qml/TrackImportNotification.qml qml/TopNotificationItem.qml qml/MediaTrackDelegate.qml qml/MediaAlbumTrackDelegate.qml qml/MediaTrackMetadataView.qml qml/GridBrowserView.qml qml/GridBrowserDelegate.qml qml/ListBrowserView.qml qml/FileBrowserDelegate.qml qml/FileBrowserView.qml qtquickcontrols2.conf background.png qml/BaseTheme.qml qml/ScrollHelper.qml qml/FlatButtonWithToolTip.qml qml/DataGridView.qml qml/DataListView.qml qml/PlayListBasicView.qml qml/SimplePlayListView.qml - qml/SimplePlayListEntry.qml qml/ViewSelector.qml qml/PlayListAlbumHeader.qml qml/BasicPlayListAlbumHeader.qml qml/MetaDataDelegate.qml qml/ViewSelectorDelegate.qml qml/HeaderFooterToolbar.qml qml/TracksDiscHeader.qml windows/WindowsTheme.qml windows/PlatformIntegration.qml windows/LabelWithToolTip.qml android/ElisaMainWindow.qml android/AndroidTheme.qml android/PlatformIntegration.qml android/AlbumsView.qml android/ArtistsView.qml android/TracksView.qml android/GenresView.qml