[vlc-devel] [PATCH 28/29] qml: add new page to artist view with only artists

Prince Gupta guptaprince8832 at gmail.com
Tue Aug 4 13:35:01 CEST 2020


---
 modules/gui/qt/Makefile.am                    |   1 +
 .../medialibrary/qml/MusicArtistsAlbums.qml   | 205 +++++++++++
 .../medialibrary/qml/MusicArtistsDisplay.qml  | 342 +++++++++++-------
 .../gui/qt/medialibrary/qml/MusicGenres.qml   |   8 -
 modules/gui/qt/vlc.qrc                        |   1 +
 5 files changed, 417 insertions(+), 140 deletions(-)
 create mode 100644 modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 4ecf090159..6ce02865c6 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -599,6 +599,7 @@ libqt_plugin_la_QML = \
 	gui/qt/medialibrary/qml/MusicAlbumsDisplay.qml \
 	gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml \
 	gui/qt/medialibrary/qml/MusicArtist.qml \
+	gui/qt/medialibrary/qml/MusicArtistsAlbums.qml \
 	gui/qt/medialibrary/qml/MusicArtistsDisplay.qml \
 	gui/qt/medialibrary/qml/MusicDisplay.qml \
 	gui/qt/medialibrary/qml/MusicGenres.qml \
diff --git a/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml b/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
new file mode 100644
index 0000000000..56922c7f74
--- /dev/null
+++ b/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
@@ -0,0 +1,205 @@
+/*****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+import QtQuick.Controls 2.4
+import QtQuick 2.11
+import QtQml.Models 2.2
+import QtQuick.Layouts 1.3
+
+import org.videolan.medialib 0.1
+
+import "qrc:///util/" as Util
+import "qrc:///widgets/" as Widgets
+import "qrc:///style/"
+
+Widgets.NavigableFocusScope {
+    id: root
+    property alias model: artistModel
+    property var sortModel: [
+        { text: i18n.qtr("Alphabetic"),  criteria: "title" }
+    ]
+
+    property var artistId
+
+    property alias currentIndex: artistList.currentIndex
+    property alias currentAlbumIndex: albumSubView.currentIndex
+    property int initialIndex: 0
+    property int initialAlbumIndex: 0
+
+    onInitialAlbumIndexChanged: resetFocus()
+    onInitialIndexChanged: resetFocus()
+
+    function resetFocus() {
+        if (artistModel.count === 0) {
+            return
+        }
+        var initialIndex = root.initialIndex
+        if (initialIndex >= artistModel.count)
+            initialIndex = 0
+        if (initialIndex !== artistList.currentIndex) {
+            selectionModel.select(artistModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
+            artistList.currentIndex = initialIndex
+            artistList.positionViewAtIndex(initialIndex, ItemView.Contain)
+        }
+    }
+
+    function _actionAtIndex(index) {
+        albumSubView.forceActiveFocus()
+    }
+
+    MLArtistModel {
+        id: artistModel
+        ml: medialib
+
+        onCountChanged: {
+            if (artistModel.count > 0 && !selectionModel.hasSelection) {
+                var initialIndex = root.initialIndex
+                if (initialIndex >= artistModel.count)
+                    initialIndex = 0
+                artistList.currentIndex = initialIndex
+            }
+        }
+    }
+
+    Util.SelectableDelegateModel {
+        id: selectionModel
+        model: artistModel
+    }
+
+    FocusScope {
+        visible: artistModel.count > 0
+        focus: visible
+        anchors.fill: parent
+
+    Row {
+        anchors.fill: parent
+
+        Widgets.KeyNavigableListView {
+            id: artistList
+
+            width: parent.width * 0.25
+            height: parent.height
+
+            spacing: 4
+            model: artistModel
+            currentIndex: -1
+
+            focus: true
+
+            onCurrentIndexChanged: {
+                if (artistList.currentIndex < artistModel.count) {
+                    root.artistId =  artistModel.getIdForIndex(artistList.currentIndex)
+                } else {
+                    root.artistId = undefined
+                }
+            }
+
+            navigationParent: root
+            navigationRightItem: albumSubView
+            navigationCancel: function() {
+                if (artistList.currentIndex <= 0)
+                    defaultNavigationCancel()
+                else
+                    artistList.currentIndex = 0;
+            }
+
+            header: Widgets.SubtitleLabel {
+                text: i18n.qtr("Artists")
+                leftPadding: VLCStyle.margin_normal
+                bottomPadding: VLCStyle.margin_normal
+                topPadding: VLCStyle.margin_normal
+            }
+
+            delegate: Widgets.ListItem {
+                height: VLCStyle.play_cover_small + (VLCStyle.margin_xsmall * 2)
+                width: artistList.width
+
+                property bool selected: artistList.currentIndex === index
+                property bool _highlighted: selected || this.hovered || this.activeFocus
+
+                color: VLCStyle.colors.getBgColor(selected, this.hovered, this.activeFocus)
+
+                cover: Item {
+
+                    width: VLCStyle.play_cover_small
+                    height: VLCStyle.play_cover_small
+
+                    Widgets.RoundImage {
+                        source: model.cover || VLCStyle.noArtArtistSmall
+                        height: VLCStyle.play_cover_small
+                        width: VLCStyle.play_cover_small
+                        radius: VLCStyle.play_cover_small
+                        mipmap: true
+                    }
+
+                    Rectangle {
+                        height: VLCStyle.play_cover_small
+                        width: VLCStyle.play_cover_small
+                        radius: VLCStyle.play_cover_small
+                        color: 'transparent'
+                        border.width: VLCStyle.dp(1, scale)
+                        border.color: !_highlighted ? VLCStyle.colors.roundPlayCoverBorder : VLCStyle.colors.accent
+                    }
+                }
+
+                line1: model.name || i18n.qtr("Unknown artist")
+
+                actionButtons: []
+
+                onItemClicked: {
+                    artistId = model.id
+                    selectionModel.updateSelection( modifier , artistList.currentIndex, index)
+                    artistList.currentIndex = index
+                    artistList.forceActiveFocus()
+                }
+
+                onItemDoubleClicked: {
+                    if (keys === Qt.RightButton)
+                        medialib.addAndPlay( model.id )
+                    else
+                        albumSubView.forceActiveFocus()
+                }
+            }
+
+        }
+
+        MusicArtist {
+            id: albumSubView
+
+            height: parent.height
+            width: parent.width * .75
+            focus: true
+            parentId: root.artistId
+            initialIndex: root.initialAlbumIndex
+            navigationParent: root
+            navigationLeftItem: artistList
+            artist: (artistList.currentIndex >= 0)
+                    ? artistModel.getDataAt(artistList.currentIndex)
+                    : ({})
+        }
+
+    }
+    }
+
+    EmptyLabel {
+        anchors.fill: parent
+        visible: artistModel.count === 0
+        focus: visible
+        text: i18n.qtr("No artists found\nPlease try adding sources, by going to the Network tab")
+        navigationParent: root
+    }
+}
diff --git a/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml b/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
index ca385f3e87..bcb4b69df1 100644
--- a/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
@@ -26,187 +26,265 @@ import "qrc:///util/" as Util
 import "qrc:///widgets/" as Widgets
 import "qrc:///style/"
 
+
 Widgets.NavigableFocusScope {
     id: root
-    property alias model: artistModel
-    property var sortModel: [
-        { text: i18n.qtr("Alphabetic"),  criteria: "title" }
-    ]
-
-    property var artistId
-
-    property alias currentIndex: artistList.currentIndex
-    property int initialIndex: 0
-    property int initialAlbumIndex: 0
-
-    onInitialAlbumIndexChanged: resetFocus()
-    onInitialIndexChanged: resetFocus()
 
-    onCurrentIndexChanged: {
-        history.update([ "mc", "music", "artists", {"initialIndex": currentIndex}])
+    //name and properties of the tab to be initially loaded
+    property string view: "all"
+    property var viewProperties: ({})
+
+    property var sortModel
+    property var contentModel
+
+    readonly property var pageModel: [{
+        name: "all",
+        component: artistGridComponent
+    }, {
+        name: "albums",
+        component: artistAlbumsComponent
+    }]
+
+    Component.onCompleted: loadView()
+    onViewChanged: {
+        viewProperties = {}
+        loadView()
     }
+    onViewPropertiesChanged: loadView()
 
-    function resetFocus() {
-        if (artistModel.count === 0) {
-            return
-        }
-        var initialIndex = root.initialIndex
-        if (initialIndex >= artistModel.count)
-            initialIndex = 0
-        if (initialIndex !== artistList.currentIndex) {
-            selectionModel.select(artistModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
-            artistList.currentIndex = initialIndex
-            artistList.positionViewAtIndex(initialIndex, ItemView.Contain)
-        }
+    function loadDefaultView() {
+        root.view = "all"
+        root.viewProperties= ({})
     }
 
-    function _actionAtIndex(index) {
-        albumSubView.forceActiveFocus()
+    function loadView() {
+        var found = stackView.loadView(root.pageModel, view, viewProperties)
+        if (!found)
+            stackView.replace(root.pageModel[0].component)
+        stackView.currentItem.navigationParent = root
+        sortModel = stackView.currentItem.sortModel
+        contentModel = stackView.currentItem.model
     }
 
-    MLArtistModel {
-        id: artistModel
-        ml: medialib
-
-        onCountChanged: {
-            if (artistModel.count > 0 && !selectionModel.hasSelection) {
-                var initialIndex = root.initialIndex
-                if (initialIndex >= artistModel.count)
-                    initialIndex = 0
-                artistList.currentIndex = initialIndex
-            }
-        }
+    function _updateArtistsAllHistory(currentIndex) {
+        history.update(["mc", "music", "artists", "all", { "initialIndex": currentIndex }])
     }
 
-    Util.SelectableDelegateModel {
-        id: selectionModel
-        model: artistModel
+    function _updateArtistsAlbumsHistory(currentIndex, initialAlbumIndex) {
+        history.update(["mc","music", "artists", "albums", {
+            "initialIndex": currentIndex,
+            "initialAlbumIndex": initialAlbumIndex,
+        }])
     }
 
-    FocusScope {
-        visible: artistModel.count > 0
-        focus: visible
-        anchors.fill: parent
+    Component {
+        id: artistGridComponent
 
-    Row {
-        anchors.fill: parent
+        Widgets.NavigableFocusScope {
+            id: artistAllView
 
-        Widgets.KeyNavigableListView {
-            id: artistList
+            readonly property int currentIndex: view.currentItem.currentIndex
+            property int initialIndex: 0
 
-            width: parent.width * 0.25
-            height: parent.height
+            onCurrentIndexChanged: {
+                _updateArtistsAllHistory(currentIndex)
+            }
 
-            spacing: 4
-            model: artistModel
-            currentIndex: -1
+            onInitialIndexChanged: resetFocus()
 
-            focus: true
+            function showAlbumView() {
+                history.push([ "mc", "music", "artists", "albums", { initialIndex: artistAllView.currentIndex } ])
+            }
 
-            onCurrentIndexChanged: {
-                if (artistList.currentIndex < artistModel.count) {
-                    root.artistId =  artistModel.getIdForIndex(artistList.currentIndex)
-                } else {
-                    root.artistId = undefined
+            function resetFocus() {
+                if (artistModel.count === 0) {
+                    return
                 }
+                var initialIndex = artistAllView.initialIndex
+                if (initialIndex >= artistModel.count)
+                    initialIndex = 0
+                selectionModel.select(artistModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
+                view.currentItem.currentIndex = initialIndex
+                view.currentItem.positionViewAtIndex(initialIndex, ItemView.Contain)
             }
 
-            navigationParent: root
-            navigationRightItem: albumSubView
-            navigationCancel: function() {
-                if (artistList.currentIndex <= 0)
-                    defaultNavigationCancel()
-                else
-                    artistList.currentIndex = 0;
-            }
+            MLArtistModel {
+                id: artistModel
+                ml: medialib
 
-            header: Widgets.SubtitleLabel {
-                text: i18n.qtr("Artists")
-                leftPadding: VLCStyle.margin_normal
-                bottomPadding: VLCStyle.margin_normal
-                topPadding: VLCStyle.margin_normal
+                onCountChanged: {
+                    if (artistModel.count > 0 && !selectionModel.hasSelection) {
+                        artistAllView.resetFocus()
+                    }
+                }
             }
 
-            delegate: Widgets.ListItem {
-                height: VLCStyle.play_cover_small + (VLCStyle.margin_xsmall * 2)
-                width: artistList.width
+            Util.SelectableDelegateModel {
+                id: selectionModel
+                model: artistModel
+            }
 
-                property bool selected: artistList.currentIndex === index
-                property bool _highlighted: selected || this.hovered || this.activeFocus
+            Widgets.MenuExt {
+                id: contextMenu
+                property var model: ({})
+                closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
+
+                Widgets.MenuItemExt {
+                    id: playMenuItem
+                    text: i18n.qtr("Play")
+                    onTriggered: {
+                        medialib.addAndPlay( contextMenu.model.id )
+                        history.push(["player"])
+                    }
+                }
 
-                color: VLCStyle.colors.getBgColor(selected, this.hovered, this.activeFocus)
+                Widgets.MenuItemExt {
+                    text: "Enqueue"
+                    onTriggered: medialib.addToPlaylist( contextMenu.model.id )
+                }
 
-                cover: Item {
+                onClosed: contextMenu.parent.forceActiveFocus()
 
-                    width: VLCStyle.play_cover_small
-                    height: VLCStyle.play_cover_small
+            }
 
-                    Widgets.RoundImage {
-                        source: model.cover || VLCStyle.noArtArtistSmall
-                        height: VLCStyle.play_cover_small
-                        width: VLCStyle.play_cover_small
-                        radius: VLCStyle.play_cover_small
-                        mipmap: true
+            Component {
+                id: gridComponent
+
+                Widgets.ExpandGridView {
+                    id: artistGrid
+
+                    anchors.fill: parent
+                    topMargin: VLCStyle.margin_large
+                    delegateModel: selectionModel
+                    model: artistModel
+                    focus: true
+                    cellWidth: VLCStyle.colWidth(1)
+                    cellHeight: VLCStyle.gridItem_music_height
+                    onSelectAll: selectionModel.selectAll()
+                    onSelectionUpdated: selectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
+                    navigationParent: root
+
+                    onActionAtIndex: {
+                        if (selectionModel.selectedIndexes.length > 1) {
+                            medialib.addAndPlay( artistModel.getIdsForIndexes( selectionModel.selectedIndexes ) )
+                        } else {
+                            view.currentItem.currentIndex = index
+                            showAlbumView()
+                            medialib.addAndPlay( artistModel.getIdForIndex(index) )
+                        }
                     }
 
-                    Rectangle {
-                        height: VLCStyle.play_cover_small
-                        width: VLCStyle.play_cover_small
-                        radius: VLCStyle.play_cover_small
-                        color: 'transparent'
-                        border.width: VLCStyle.dp(1, scale)
-                        border.color: !_highlighted ? VLCStyle.colors.roundPlayCoverBorder : VLCStyle.colors.accent
+                    delegate: AudioGridItem {
+                        id: gridItem
+
+                        title: model.name
+                        subtitle: model.nb_tracks > 1 ? i18n.qtr("%1 songs").arg(model.nb_tracks) : i18n.qtr("%1 song").arg(model.nb_tracks)
+                        pictureRadius: VLCStyle.artistGridCover_radius
+                        pictureHeight: VLCStyle.artistGridCover_radius
+                        pictureWidth: VLCStyle.artistGridCover_radius
+                        playCoverBorder.width: VLCStyle.dp(3, VLCStyle.scale)
+                        titleMargin: VLCStyle.margin_xlarge
+                        playIconSize: VLCStyle.play_cover_small
+                        textHorizontalAlignment: Text.AlignHCenter
+                        width: VLCStyle.colWidth(1)
+
+                        onItemClicked: {
+                            selectionModel.updateSelection( modifier , view.currentItem.currentIndex, index )
+                            view.currentItem.currentIndex = index
+                            view.currentItem.forceActiveFocus()
+                        }
+
+                        onItemDoubleClicked: artistAllView.showAlbumView(model)
                     }
                 }
+            }
 
-                line1: model.name || i18n.qtr("Unknown artist")
 
-                actionButtons: []
 
-                onItemClicked: {
-                    artistId = model.id
-                    selectionModel.updateSelection( modifier , artistList.currentIndex, index)
-                    artistList.currentIndex = index
-                    artistList.forceActiveFocus()
-                }
+            Component {
+                id: tableComponent
+
+                Widgets.KeyNavigableTableView {
+                    id: artistTable
+
+                    readonly property int _nbCols: VLCStyle.gridColumnsForWidth(artistTable.availableRowWidth)
+
+                    anchors.fill: parent
+                    model: artistModel
+                    focus: true
+                    headerColor: VLCStyle.colors.bg
+                    navigationParent: root
 
-                onItemDoubleClicked: {
-                    if (keys === Qt.RightButton)
-                        medialib.addAndPlay( model.id )
-                    else
-                        albumSubView.forceActiveFocus()
+                    onActionForSelection: {
+                        if (selection.length > 1) {
+                            medialib.addAndPlay( artistModel.getIdsForIndexes( selection ) )
+                        } else {
+                            showAlbumView()
+                            medialib.addAndPlay( artistModel.getIdForIndex(index) )
+                        }
+                    }
+
+                    sortModel:  [
+                        { isPrimary: true, criteria: "name", width: VLCStyle.colWidth(Math.max(artistTable._nbCols - 1, 1)), text: i18n.qtr("Name"), headerDelegate: tableColumns.titleHeaderDelegate, colDelegate: tableColumns.titleDelegate },
+                        { criteria: "nb_tracks", width: VLCStyle.colWidth(1), text: i18n.qtr("Tracks") }
+                    ]
+
+                    onItemDoubleClicked: {
+                        artistAllView.showAlbumView(model)
+                    }
+
+                    onContextMenuButtonClicked: {
+                        contextMenu.model = menuModel
+                        contextMenu.popup(menuParent)
+                    }
+
+                    Widgets.TableColumns {
+                        id: tableColumns
+                    }
                 }
             }
 
-        }
+            Widgets.StackViewExt {
+                id: view
 
-        MusicArtist {
-            id: albumSubView
+                anchors.fill: parent
+                focus: true
+                initialItem: medialib.gridView ? gridComponent : tableComponent
+            }
 
-            height: parent.height
-            width: parent.width * .75
-            focus: true
-            parentId: root.artistId
-            initialIndex: root.initialAlbumIndex
-            navigationParent: root
-            navigationLeftItem: artistList
-            artist: (artistList.currentIndex >= 0)
-                    ? artistModel.getDataAt(artistList.currentIndex)
-                    : ({})
+            Connections {
+                target: medialib
+                onGridViewChanged: {
+                    if (medialib.gridView) {
+                        view.replace(gridComponent)
+                    } else {
+                        view.replace(tableComponent)
+                    }
+                }
+            }
 
-            onCurrentIndexChanged: {
-                history.update(["mc", "music", "artists", {"initialIndex" : root.currentIndex, "initialAlbumIndex": albumSubView.currentIndex  }])
+            EmptyLabel {
+                anchors.fill: parent
+                visible: artistModel.count === 0
+                text: i18n.qtr("No artists found\nPlease try adding sources, by going to the Network tab")
+                navigationParent: root
             }
         }
-
     }
+
+    Component {
+        id: artistAlbumsComponent
+        /* List View */
+        MusicArtistsAlbums {
+            onCurrentIndexChanged: _updateArtistsAlbumsHistory(currentIndex, currentAlbumIndex)
+            onCurrentAlbumIndexChanged: _updateArtistsAlbumsHistory(currentIndex, currentAlbumIndex)
+        }
     }
 
-    EmptyLabel {
+    Widgets.StackViewExt {
+        id: stackView
+
         anchors.fill: parent
-        visible: artistModel.count === 0
-        focus: visible
-        text: i18n.qtr("No artists found\nPlease try adding sources, by going to the Network tab")
-        navigationParent: root
+        focus: true
     }
 }
diff --git a/modules/gui/qt/medialibrary/qml/MusicGenres.qml b/modules/gui/qt/medialibrary/qml/MusicGenres.qml
index 78c74a09d6..c06eef1104 100644
--- a/modules/gui/qt/medialibrary/qml/MusicGenres.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicGenres.qml
@@ -227,12 +227,4 @@ Widgets.NavigableFocusScope {
         anchors.fill: parent
         focus: genreModel.count !== 0
     }
-
-    EmptyLabel {
-        anchors.fill: parent
-        visible: genreModel.count === 0
-        focus: visible
-        text: i18n.qtr("No genres found\nPlease try adding sources, by going to the Network tab")
-        navigationParent: root
-    }
 }
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index 51f3a61701..c6eaa47bf9 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -243,6 +243,7 @@
         <file alias="MusicAlbumsDisplay.qml">medialibrary/qml/MusicAlbumsDisplay.qml</file>
         <file alias="MusicAlbumsGridExpandDelegate.qml">medialibrary/qml/MusicAlbumsGridExpandDelegate.qml</file>
         <file alias="MusicArtist.qml">medialibrary/qml/MusicArtist.qml</file>
+        <file alias="MusicArtistsAlbums.qml">medialibrary/qml/MusicArtistsAlbums.qml</file>
         <file alias="MusicArtistsDisplay.qml">medialibrary/qml/MusicArtistsDisplay.qml</file>
         <file alias="MusicGenresDisplay.qml">medialibrary/qml/MusicGenresDisplay.qml</file>
         <file alias="MusicTracksDisplay.qml">medialibrary/qml/MusicTracksDisplay.qml</file>
-- 
2.25.1



More information about the vlc-devel mailing list