[vlc-devel] [PATCH 15/29] qml: don't base MusicArtist to MusicAlbums, create it separately

Prince Gupta guptaprince8832 at gmail.com
Tue Aug 4 13:34:48 CEST 2020


qml: add grid type view for albums in artist view
---
 .../gui/qt/medialibrary/qml/MusicArtist.qml   | 346 +++++++++++++++++-
 1 file changed, 333 insertions(+), 13 deletions(-)

diff --git a/modules/gui/qt/medialibrary/qml/MusicArtist.qml b/modules/gui/qt/medialibrary/qml/MusicArtist.qml
index 32f0d87221..366ee04b87 100644
--- a/modules/gui/qt/medialibrary/qml/MusicArtist.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicArtist.qml
@@ -1,4 +1,4 @@
-/*****************************************************************************
+/*****************************************************************************
  * Copyright (C) 2020 VLC authors and VideoLAN
  *
  * This program is free software; you can redistribute it and/or modify
@@ -26,25 +26,345 @@ import "qrc:///util/" as Util
 import "qrc:///widgets/" as Widgets
 import "qrc:///style/"
 
-MusicAlbums {
+Widgets.NavigableFocusScope {
     id: root
 
+    property alias parentId: albumModel.parentId
     property var artist: ({})
+    readonly property var currentIndex: headerItem.albumsListView.currentIndex || view.currentItem.currentIndex
+    property Item headerItem: view.currentItem.headerItem
+    //the index to "go to" when the view is loaded
+    property var initialIndex: 0
+
+    property Component header: FocusScope {
+        property Item albumsListView: albumsLoader.item.albumsListView
+        property Item focusItem: albumsLoader.active ? albumsLoader.item.albumsListView : artistBanner
+
+        focus: true
+        height: col.height
+        width: root.width
+
+        Column {
+            id: col
+
+            height: childrenRect.height + VLCStyle.margin_normal
+            width: root.width
+
+            ArtistTopBanner {
+                id: artistBanner
+
+                focus: true
+                width: root.width
+                artist: root.artist
+                navigationParent: root.navigationParent
+                navigationLeftItem: root.navigationLeftItem
+                navigationDown: function() {
+                    artistBanner.focus = false
+                    if (albumsListView)
+                        albumsListView.forceActiveFocus()
+                    else
+                        view.currentItem.setCurrentItemFocus()
+
+                }
+            }
+
+            Loader {
+                id: albumsLoader
+
+                active: !medialib.gridView
+                focus: true
+                sourceComponent: Column {
+                    property alias albumsListView: albumsList
+
+                    width: root.width
+                    height: childrenRect.height
+
+                    Widgets.SubtitleLabel {
+                        id: albumsText
+
+                        text: i18n.qtr("Albums")
+                        leftPadding: VLCStyle.margin_xlarge
+                        topPadding: VLCStyle.margin_normal
+                        bottomPadding: VLCStyle.margin_xsmall
+                    }
+
+                    Widgets.KeyNavigableListView {
+                        id: albumsList
+
+                        focus: true
+                        height: VLCStyle.gridItem_music_height + VLCStyle.margin_normal
+                        width: root.width
+                        leftMargin: VLCStyle.margin_xlarge
+                        topMargin: VLCStyle.margin_xsmall
+                        bottomMargin: VLCStyle.margin_xsmall
+                        model: albumModel
+                        orientation: ListView.Horizontal
+                        spacing: VLCStyle.column_margin_width
+                        navigationLeftItem: root.navigationLeftItem
+                        navigationUpItem: artistBanner
+                        navigationDown: function() {
+                            albumsList.focus = false
+                            view.currentItem.setCurrentItemFocus()
+                        }
+
+                        delegate: Widgets.GridItem {
+                            image: model.cover || VLCStyle.noArtAlbum
+                            title: model.title || i18n.qtr("Unknown title")
+                            subtitle: model.release_year || i18n.qtr("")
+                            textHorizontalAlignment: Text.AlignHCenter
+                            x: selectedBorderWidth
+                            y: selectedBorderWidth
+                            pictureWidth: VLCStyle.gridCover_music_width
+                            pictureHeight: VLCStyle.gridCover_music_height
+                            playCoverBorder.width: VLCStyle.gridCover_music_border
+
+                            onPlayClicked: play()
+                            onItemDoubleClicked: play()
+
+                            onItemClicked: {
+                                albumSelectionModel.updateSelection( modifier , albumsList.currentIndex, index )
+                                albumsList.currentIndex = index
+                                albumsList.forceActiveFocus()
+                            }
+
+                            Connections {
+                                target: albumSelectionModel
+
+                                onSelectionChanged: selected = albumSelectionModel.isSelected(albumModel.index(index, 0))
+                            }
+
+                            function play() {
+                                if ( model.id !== undefined ) {
+                                    medialib.addAndPlay( model.id )
+                                }
+                            }
+                        }
+
+                        onSelectAll: albumSelectionModel.selectAll()
+                        onSelectionUpdated: albumSelectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
+                        onActionAtIndex: medialib.addAndPlay( albumModel.getIdForIndex( index ) )
+                    }
+
+                    Widgets.SubtitleLabel {
+                        id: tracksText
+
+                        text: i18n.qtr("Tracks")
+                        leftPadding: VLCStyle.margin_xlarge
+                        topPadding: VLCStyle.margin_large
+                    }
+                }
+            }
+        }
+    }
 
-    gridViewMarginTop: 0
     focus: true
-    navigationUpItem: headerItem
+    navigationUpItem: headerItem.focusItem
 
-    header: ArtistTopBanner {
-        id: artistBanner
+    onInitialIndexChanged: resetFocus()
+    onActiveFocusChanged: {
+        if (activeFocus && albumModel.count > 0 && !albumSelectionModel.hasSelection) {
+            var initialIndex = 0
+            var albumsListView = medialib.gridView ? view.currentItem : headerItem.albumsListView
+            if (albumsListView.currentIndex !== -1)
+                initialIndex = albumsListView.currentIndex
+            albumSelectionModel.select(albumModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
+            albumsListView.currentIndex = initialIndex
+        }
+    }
 
-        width: root.width
-        artist: root.artist
-        navigationParent: root.navigationParent
-        navigationLeftItem: root.navigationLeftItem
-        navigationDown: function() {
-            artistBanner.focus = false
-            root.forceActiveFocus()
+    function resetFocus() {
+        if (albumModel.count === 0) {
+            return
+        }
+        var initialIndex = root.initialIndex
+        if (initialIndex >= albumModel.count)
+            initialIndex = 0
+        albumSelectionModel.select(albumModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
+        var albumsListView = medialib.gridView ? view.currentItem : headerItem.albumsListView
+        albumsListView.currentIndex = initialIndex
+        albumsListView.positionViewAtIndex(initialIndex, ItemView.Contain)
+    }
+
+    function _actionAtIndex(index, model, selectionModel) {
+        if (selectionModel.selectedIndexes.length > 1) {
+            medialib.addAndPlay( model.getIdsForIndexes( selectionModel.selectedIndexes ) )
+        } else {
+            medialib.addAndPlay( model.getIdForIndex(index) )
+        }
+    }
+
+    MLAlbumModel {
+        id: albumModel
+        ml: medialib
+
+        onCountChanged: {
+            if (albumModel.count > 0 && !albumSelectionModel.hasSelection) {
+                root.resetFocus()
+            }
+        }
+    }
+
+    Util.SelectableDelegateModel {
+        id: albumSelectionModel
+        model: albumModel
+    }
+
+    MLAlbumTrackModel {
+        id: trackModel
+
+        ml: medialib
+        parentId: root.parentId
+
+        onCountChanged: {
+            if (trackModel.count > 0) {
+                root.resetFocus()
+            }
+        }
+    }
+
+    Component {
+        id: gridComponent
+
+        Widgets.ExpandGridView {
+            id: gridView_id
+
+            focus: true
+            activeFocusOnTab:true
+            cellWidth: VLCStyle.gridItem_music_width
+            cellHeight: VLCStyle.gridItem_music_height
+            headerDelegate: root.header
+            delegateModel: albumSelectionModel
+            model: albumModel
+
+            delegate: AudioGridItem {
+                id: audioGridItem
+
+                opacity: gridView_id.expandIndex !== -1 && gridView_id.expandIndex !== audioGridItem.index ? .7 : 1
+
+                onItemClicked : {
+                    albumSelectionModel.updateSelection( modifier , gridView_id.currentIndex, index )
+                    gridView_id.currentIndex = index
+                    gridView_id.forceActiveFocus()
+                }
+
+                onItemDoubleClicked: {
+                    if ( model.id !== undefined ) { medialib.addAndPlay( model.id ) }
+                }
+
+                Behavior on opacity {
+                    NumberAnimation {
+                        duration: 100
+                    }
+                }
+            }
+
+            expandDelegate: MusicAlbumsGridExpandDelegate {
+                id: expandDelegateId
+
+                onRetract: gridView_id.retract()
+                navigationParent: root
+                navigationCancel:  function() {  gridView_id.retract() }
+                navigationUp: function() {  gridView_id.retract() }
+                navigationDown: function() {}
+            }
+
+            onActionAtIndex: {
+                if (albumSelectionModel.selectedIndexes.length <= 1) {
+                    gridView_id.switchExpandItem( index )
+                } else {
+                    root._actionAtIndex( index, albumModel, albumSelectionModel )
+                }
+            }
+
+            onSelectAll: albumSelectionModel.selectAll()
+            onSelectionUpdated: albumSelectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
+            navigationParent: root
+        }
+    }
+
+    Widgets.MenuExt {
+        id: contextMenu
+
+        property var model: ({})
+        closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
+
+        Widgets.MenuItemExt {
+            id: playMenuItem
+            text: i18n.qtr("Play from start")
+            onTriggered: {
+                medialib.addAndPlay( contextMenu.model.id )
+                history.push(["player"])
+            }
+        }
+
+        Widgets.MenuItemExt {
+            text: i18n.qtr("Enqueue")
+            onTriggered: medialib.addToPlaylist( contextMenu.model.id )
+        }
+
+        onClosed: contextMenu.parent.forceActiveFocus()
+    }
+
+    Component {
+        id: tableComponent
+
+        Widgets.KeyNavigableTableView {
+            id: tableView_id
+
+            readonly property int _nbCols: VLCStyle.gridColumnsForWidth(tableView_id.availableRowWidth)
+
+            model: trackModel
+            headerColor: VLCStyle.colors.bg
+            onActionForSelection: {
+                medialib.addAndPlay( model.getIdsForIndexes( selection ) )
+            }
+            navigationParent: root
+            header: root.header
+
+            sortModel:  [
+                { isPrimary: true, criteria: "title", width: VLCStyle.colWidth(2), text: i18n.qtr("Title"), headerDelegate: tableColumns.titleHeaderDelegate, colDelegate: tableColumns.titleDelegate },
+                { criteria: "album_title", width: VLCStyle.colWidth(Math.max(tableView_id._nbCols - 3, 1)), text: i18n.qtr("Album") },
+                { criteria: "durationShort", width:VLCStyle.colWidth(1), showSection: "", headerDelegate: tableColumns.timeHeaderDelegate, colDelegate: tableColumns.timeColDelegate },
+            ]
+
+            navigationCancel: function() {
+                if (tableView_id.currentIndex <= 0)
+                    defaultNavigationCancel()
+                else
+                    tableView_id.currentIndex = 0;
+            }
+
+            onContextMenuButtonClicked: {
+                contextMenu.model = menuModel
+                contextMenu.popup(menuParent)
+            }
+
+            Widgets.TableColumns {
+                id: tableColumns
+            }
+
+            function setCurrentItemFocus() {
+                positionViewAtIndex(currentIndex, ItemView.Contain)
+                currentItem.forceActiveFocus()
+            }
+        }
+    }
+
+    Widgets.StackViewExt {
+        id: view
+
+        anchors.fill: parent
+        focus: albumModel.count !== 0
+        initialItem: medialib.gridView ? gridComponent : tableComponent
+
+        Connections {
+            target: medialib
+            onGridViewChanged: {
+                if (medialib.gridView)
+                    view.replace(gridComponent)
+                else
+                    view.replace(tableComponent)
+            }
         }
     }
 }
-- 
2.25.1



More information about the vlc-devel mailing list