qt: playlist: use item title if available
[vlc.git] / modules / gui / qt / medialibrary / qml / MusicArtistsDisplay.qml
blob861073172c614619be3a9e2122546a9c0f648bae
1 /*****************************************************************************
2  * Copyright (C) 2019 VLC authors and VideoLAN
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * ( at your option ) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17  *****************************************************************************/
18 import QtQuick.Controls 2.4
19 import QtQuick 2.11
20 import QtQml.Models 2.2
21 import QtQuick.Layouts 1.3
23 import org.videolan.medialib 0.1
25 import "qrc:///util/" as Util
26 import "qrc:///widgets/" as Widgets
27 import "qrc:///main/" as MainInterface
28 import "qrc:///style/"
31 Widgets.PageLoader {
32     id: root
34     property var model
36     defaultPage: "all"
37     pageModel: [{
38         name: "all",
39         component: artistGridComponent
40     }, {
41         name: "albums",
42         component: artistAlbumsComponent
43     }]
45     onCurrentItemChanged: {
46         model = currentItem.model
47     }
49     function _updateArtistsAllHistory(currentIndex) {
50         history.update(["mc", "music", "artists", "all", { "initialIndex": currentIndex }])
51     }
53     function _updateArtistsAlbumsHistory(currentIndex, initialAlbumIndex) {
54         history.update(["mc","music", "artists", "albums", {
55             "initialIndex": currentIndex,
56             "initialAlbumIndex": initialAlbumIndex,
57         }])
58     }
60     Component {
61         id: artistGridComponent
63         Widgets.NavigableFocusScope {
64             id: artistAllView
66             readonly property int currentIndex: view.currentItem.currentIndex
67             property int initialIndex: 0
68             property alias model: artistModel
70             onCurrentIndexChanged: {
71                 _updateArtistsAllHistory(currentIndex)
72             }
74             onInitialIndexChanged: resetFocus()
76             function showAlbumView() {
77                 history.push([ "mc", "music", "artists", "albums", { initialIndex: artistAllView.currentIndex } ])
78             }
80             function resetFocus() {
81                 if (artistModel.count === 0) {
82                     return
83                 }
84                 var initialIndex = artistAllView.initialIndex
85                 if (initialIndex >= artistModel.count)
86                     initialIndex = 0
87                 selectionModel.select(artistModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
88                 if (view.currentItem) {
89                     view.currentItem.currentIndex = initialIndex
90                     view.currentItem.positionViewAtIndex(initialIndex, ItemView.Contain)
91                 }
92             }
94             MLArtistModel {
95                 id: artistModel
96                 ml: medialib
98                 onCountChanged: {
99                     if (artistModel.count > 0 && !selectionModel.hasSelection) {
100                         artistAllView.resetFocus()
101                     }
102                 }
103             }
105             Util.SelectableDelegateModel {
106                 id: selectionModel
107                 model: artistModel
108             }
110             Widgets.DragItem {
111                 id: artistsDragItem
113                 function updateComponents(maxCovers) {
114                   var items = selectionModel.selectedIndexes.slice(0, maxCovers).map(function (x){
115                     return artistModel.getDataAt(x.row)
116                   })
117                   var title = items.map(function (item){ return item.name}).join(", ")
118                   var covers = items.map(function (item) { return {artwork: item.cover || VLCStyle.noArtArtistSmall}})
119                   return {
120                     covers: covers,
121                     title: title,
122                     count: selectionModel.selectedIndexes.length
123                   }
124                 }
126                 function getSelectedInputItem() {
127                     return artistModel.getItemsForIndexes(selectionModel.selectedIndexes);
128                 }
129             }
131             ArtistContextMenu {
132                 id: contextMenu
133                 model: artistModel
134             }
136             Component {
137                 id: gridComponent
139                 MainInterface.MainGridView {
140                     id: artistGrid
142                     anchors.fill: parent
143                     topMargin: VLCStyle.margin_large
144                     delegateModel: selectionModel
145                     model: artistModel
146                     focus: true
147                     cellWidth: VLCStyle.colWidth(1)
148                     cellHeight: VLCStyle.gridItem_music_height
149                     onSelectAll: selectionModel.selectAll()
150                     onSelectionUpdated: selectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
151                     navigationParent: root
153                     onActionAtIndex: {
154                         if (selectionModel.selectedIndexes.length > 1) {
155                             medialib.addAndPlay( artistModel.getIdsForIndexes( selectionModel.selectedIndexes ) )
156                         } else {
157                             view.currentItem.currentIndex = index
158                             showAlbumView()
159                             medialib.addAndPlay( artistModel.getIdForIndex(index) )
160                         }
161                     }
163                     Widgets.GridShadows {
164                         id: shadows
166                         leftPadding: (VLCStyle.colWidth(1) - shadows.coverWidth) / 2 // GridItem's rect is horizontally centered
167                         coverWidth: VLCStyle.artistGridCover_radius
168                         coverHeight: VLCStyle.artistGridCover_radius
169                         coverRadius: VLCStyle.artistGridCover_radius
170                     }
172                     delegate: AudioGridItem {
173                         id: gridItem
175                         title: model.name || i18n.qtr("Unknown artist")
176                         subtitle: model.nb_tracks > 1 ? i18n.qtr("%1 songs").arg(model.nb_tracks) : i18n.qtr("%1 song").arg(model.nb_tracks)
177                         pictureRadius: VLCStyle.artistGridCover_radius
178                         pictureHeight: VLCStyle.artistGridCover_radius
179                         pictureWidth: VLCStyle.artistGridCover_radius
180                         playCoverBorder.width: VLCStyle.dp(3, VLCStyle.scale)
181                         titleMargin: VLCStyle.margin_xlarge
182                         playIconSize: VLCStyle.play_cover_small
183                         textHorizontalAlignment: Text.AlignHCenter
184                         width: VLCStyle.colWidth(1)
185                         dragItem: artistsDragItem
186                         unselectedUnderlay: shadows.unselected
187                         selectedUnderlay: shadows.selected
190                         onItemClicked: artistGrid.leftClickOnItem(modifier, index)
192                         onItemDoubleClicked: artistAllView.showAlbumView(model)
194                         onContextMenuButtonClicked: {
195                             artistGrid.rightClickOnItem(index)
196                             contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
197                         }
198                     }
199                 }
200             }
204             Component {
205                 id: tableComponent
207                 MainInterface.MainTableView {
208                     id: artistTable
210                     readonly property int _nbCols: VLCStyle.gridColumnsForWidth(artistTable.availableRowWidth)
212                     anchors.fill: parent
213                     selectionDelegateModel: selectionModel
214                     model: artistModel
215                     focus: true
216                     headerColor: VLCStyle.colors.bg
217                     navigationParent: root
218                     dragItem: artistsDragItem
219                     rowHeight: VLCStyle.tableCoverRow_height
220                     headerTopPadding: VLCStyle.margin_normal
222                     onActionForSelection: {
223                         if (selection.length > 1) {
224                             medialib.addAndPlay( artistModel.getIdsForIndexes( selection ) )
225                         } else {
226                             showAlbumView()
227                             medialib.addAndPlay( artistModel.getIdForIndex(index) )
228                         }
229                     }
231                     sortModel:  [
232                         { isPrimary: true, criteria: "name", width: VLCStyle.colWidth(Math.max(artistTable._nbCols - 1, 1)), text: i18n.qtr("Name"), headerDelegate: tableColumns.titleHeaderDelegate, colDelegate: tableColumns.titleDelegate },
233                         { criteria: "nb_tracks", width: VLCStyle.colWidth(1), text: i18n.qtr("Tracks") }
234                     ]
236                     onItemDoubleClicked: {
237                         artistAllView.showAlbumView(model)
238                     }
239                     onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, menuParent.mapToGlobal(0,0))
240                     onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
242                     Widgets.TableColumns {
243                         id: tableColumns
244                     }
245                 }
246             }
248             Widgets.StackViewExt {
249                 id: view
251                 anchors.fill: parent
252                 visible: artistModel.count > 0
253                 focus: artistModel.count > 0
254                 initialItem: mainInterface.gridView ? gridComponent : tableComponent
255             }
257             Connections {
258                 target: mainInterface
259                 onGridViewChanged: {
260                     if (mainInterface.gridView) {
261                         view.replace(gridComponent)
262                     } else {
263                         view.replace(tableComponent)
264                     }
265                 }
266             }
268             EmptyLabel {
269                 anchors.fill: parent
270                 visible: artistModel.count === 0
271                 focus: artistModel.count === 0
272                 text: i18n.qtr("No artists found\nPlease try adding sources, by going to the Network tab")
273                 navigationParent: root
274                 cover: VLCStyle.noArtArtistCover
275             }
276         }
277     }
279     Component {
280         id: artistAlbumsComponent
281         /* List View */
282         MusicArtistsAlbums {
283             onCurrentIndexChanged: _updateArtistsAlbumsHistory(currentIndex, currentAlbumIndex)
284             onCurrentAlbumIndexChanged: _updateArtistsAlbumsHistory(currentIndex, currentAlbumIndex)
285         }
286     }