1/* 2 SPDX-FileCopyrightText: 2018 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr> 3 4 SPDX-License-Identifier: LGPL-3.0-or-later 5 */ 6 7import QtQuick 2.10 8import QtQuick.Controls 2.3 9import org.kde.kirigami 2.5 as Kirigami 10import org.kde.elisa 1.0 11 12FocusScope { 13 id: viewHeader 14 15 property var filterType 16 property alias isSubPage: listView.isSubPage 17 property alias mainTitle: listView.mainTitle 18 property alias secondaryTitle: listView.secondaryTitle 19 property alias showSection: listView.showSection 20 property alias expandedFilterView: listView.expandedFilterView 21 property alias haveTreeModel: listView.haveTreeModel 22 property var filter 23 property alias image: listView.image 24 property var modelType 25 property AbstractItemModel realModel 26 property AbstractProxyModel proxyModel 27 property alias sortRole: listView.sortRole 28 property alias sortRoles: listView.sortRoles 29 property alias sortRoleNames: listView.sortRoleNames 30 property alias sortOrderNames: listView.sortOrderNames 31 property alias sortOrder: listView.sortOrder 32 property bool displaySingleAlbum: false 33 property alias radioCase: listView.showCreateRadioButton 34 property bool modelIsInitialized: false 35 property alias viewManager: listView.viewManager 36 37 function openMetaDataView(databaseId, url, entryType) { 38 metadataLoader.setSource(Kirigami.Settings.isMobile ? "mobile/MobileMediaTrackMetadataView.qml" : "MediaTrackMetadataView.qml", 39 { 40 "fileName": url, 41 "modelType": entryType, 42 "showImage": entryType !== ElisaUtils.Radio, 43 "showTrackFileName": entryType !== ElisaUtils.Radio, 44 "showDeleteButton": entryType === ElisaUtils.Radio, 45 "editableMetadata": true, 46 "canAddMoreMetadata": entryType !== ElisaUtils.Radio, 47 }); 48 metadataLoader.active = true 49 } 50 function openCreateRadioView() 51 { 52 metadataLoader.setSource(Kirigami.Settings.isMobile ? "mobile/MobileMediaTrackMetadataView.qml" : "MediaTrackMetadataView.qml", 53 { 54 "modelType": ElisaUtils.Radio, 55 "isCreating": true, 56 "showImage": false, 57 "showTrackFileName": false, 58 "showDeleteButton": true, 59 "editableMetadata": true, 60 "canAddMoreMetadata": false, 61 }); 62 metadataLoader.active = true 63 } 64 65 function initializeModel() 66 { 67 if (!proxyModel) { 68 return 69 } 70 71 if (!realModel) { 72 return 73 } 74 75 if (!ElisaApplication.musicManager) { 76 return 77 } 78 79 if (modelIsInitialized) { 80 return 81 } 82 83 proxyModel.sourceModel = realModel 84 proxyModel.dataType = modelType 85 proxyModel.playList = Qt.binding(function() { return ElisaApplication.mediaPlayListProxyModel }) 86 listView.contentModel = proxyModel 87 88 if (!displaySingleAlbum) { 89 proxyModel.sortModel(sortOrder) 90 } 91 92 realModel.initializeByData(ElisaApplication.musicManager, ElisaApplication.musicManager.viewDatabase, 93 modelType, filterType, filter) 94 } 95 96 function goToBack() { 97 listView.goToBack() 98 } 99 100 Loader { 101 id: metadataLoader 102 active: false 103 onLoaded: { 104 // on mobile, the metadata loader is a page 105 // on desktop, it's a window 106 if (Kirigami.Settings.isMobile) { 107 mainWindow.pageStack.layers.push(item); 108 } else { 109 item.show(); 110 } 111 } 112 } 113 114 // desktop delegates 115 Component { 116 id: trackDelegate 117 118 ListBrowserDelegate { 119 id: entry 120 121 width: listView.delegateWidth 122 123 focus: true 124 125 trackUrl: model.url 126 dataType: model.dataType 127 title: model.display ? model.display : '' 128 artist: model.artist ? model.artist : '' 129 album: model.album ? model.album : '' 130 albumArtist: model.albumArtist ? model.albumArtist : '' 131 duration: model.duration ? model.duration : '' 132 imageUrl: model.imageUrl ? model.imageUrl : '' 133 trackNumber: model.trackNumber ? model.trackNumber : -1 134 discNumber: model.discNumber ? model.discNumber : -1 135 rating: model.rating 136 hideDiscNumber: !viewHeader.displaySingleAlbum && model.isSingleDiscAlbum 137 isSelected: listView.currentIndex === index 138 isAlternateColor: (index % 2) === 1 139 detailedView: !viewHeader.displaySingleAlbum 140 141 onTrackRatingChanged: { 142 ElisaApplication.musicManager.updateSingleFileMetaData(url, DataTypes.RatingRole, rating) 143 } 144 145 onEnqueue: ElisaApplication.mediaPlayListProxyModel.enqueue(model.fullData, model.display, 146 ElisaUtils.AppendPlayList, 147 ElisaUtils.DoNotTriggerPlay) 148 149 onReplaceAndPlay: ElisaApplication.mediaPlayListProxyModel.enqueue(model.fullData, model.display, 150 ElisaUtils.ReplacePlayList, 151 ElisaUtils.TriggerPlay) 152 153 onClicked: { 154 listView.currentIndex = index; 155 entry.forceActiveFocus(); 156 } 157 158 onActiveFocusChanged: { 159 if (activeFocus && listView.currentIndex !== index) { 160 listView.currentIndex = index 161 } 162 } 163 164 onCallOpenMetaDataView: { 165 openMetaDataView(databaseId, url, entryType) 166 } 167 } 168 } 169 170 ListBrowserView { 171 id: listView 172 173 focus: true 174 175 anchors.fill: parent 176 177 contentModel: proxyModel 178 179 delegate: trackDelegate 180 181 enableSorting: !displaySingleAlbum 182 183 allowArtistNavigation: isSubPage 184 185 showCreateRadioButton: modelType === ElisaUtils.Radio 186 showEnqueueButton: modelType !== ElisaUtils.Radio 187 188 onShowArtist: { 189 viewManager.openArtistView(secondaryTitle) 190 } 191 192 onGoBackRequested: viewManager.goBack() 193 194 suppressNoDataPlaceholderMessage: busyIndicatorLoader.active 195 196 Loader { 197 id: busyIndicatorLoader 198 anchors.centerIn: parent 199 height: Kirigami.Units.gridUnit * 5 200 width: height 201 202 visible: realModel ? realModel.isBusy : true 203 active: realModel ? realModel.isBusy : true 204 205 sourceComponent: BusyIndicator { 206 anchors.centerIn: parent 207 } 208 } 209 } 210 211 Connections { 212 target: ElisaApplication 213 214 function onMusicManagerChanged() { 215 initializeModel() 216 } 217 } 218 219 Connections { 220 target: listView.navigationBar 221 222 function onCreateRadio() { 223 openCreateRadioView() 224 } 225 } 226 227 Component.onCompleted: { 228 initializeModel() 229 } 230} 231