[vlc-devel] [PATCH 18/22] qml: split the music genre view

Pierre Lamot pierre at videolabs.io
Fri Feb 14 11:23:53 CET 2020


  the genre view can now either load the regular view presenting the genres
  or load a specialized album view for a defined genre
---
 modules/gui/qt/Makefile.am                    |   1 +
 .../gui/qt/medialibrary/qml/MusicGenres.qml   | 244 ++++++++++++++++++
 .../medialibrary/qml/MusicGenresDisplay.qml   | 209 ++++-----------
 modules/gui/qt/vlc.qrc                        |   1 +
 4 files changed, 298 insertions(+), 157 deletions(-)
 create mode 100644 modules/gui/qt/medialibrary/qml/MusicGenres.qml

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 947c712fb5..b116030404 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -561,6 +561,7 @@ libqt_plugin_la_QML = \
 	gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml \
 	gui/qt/medialibrary/qml/MusicArtistsDisplay.qml \
 	gui/qt/medialibrary/qml/MusicDisplay.qml \
+	gui/qt/medialibrary/qml/MusicGenres.qml \
 	gui/qt/medialibrary/qml/MusicGenresDisplay.qml \
 	gui/qt/medialibrary/qml/MusicTrackListDisplay.qml \
 	gui/qt/medialibrary/qml/MusicTracksDisplay.qml \
diff --git a/modules/gui/qt/medialibrary/qml/MusicGenres.qml b/modules/gui/qt/medialibrary/qml/MusicGenres.qml
new file mode 100644
index 0000000000..d0a8c3840f
--- /dev/null
+++ b/modules/gui/qt/medialibrary/qml/MusicGenres.qml
@@ -0,0 +1,244 @@
+/*****************************************************************************
+ * Copyright (C) 2019 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 2.11
+import QtQuick.Controls 2.4
+import QtQml.Models 2.2
+import org.videolan.vlc 0.1
+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: delegateModel.model
+    property var sortModel: [
+        { text: i18n.qtr("Alphabetic"), criteria: "title" }
+    ]
+
+    readonly property var currentIndex: view.currentItem.currentIndex
+    //the index to "go to" when the view is loaded
+    property var initialIndex: 0
+
+    onInitialIndexChanged:  resetFocus()
+
+    navigationCancel: function() {
+        if (view.currentItem.currentIndex <= 0)
+            defaultNavigationCancel()
+        else
+            view.currentItem.currentIndex = 0;
+    }
+
+    Component.onCompleted: loadView()
+
+    function loadView() {
+        if (medialib.gridView) {
+            view.replace(gridComponent)
+        } else {
+            view.replace(listComponent)
+        }
+    }
+
+    function showAlbumView( parent, name ) {
+        history.push([ "mc", "music", "genres", "albums", { parentId: parent, genreName: name } ])
+    }
+
+    function resetFocus() {
+        if (delegateModel.items.count === 0) {
+            return
+        }
+        var initialIndex = root.initialIndex
+        if (initialIndex >= delegateModel.items.count)
+            initialIndex = 0
+        delegateModel.selectNone()
+        delegateModel.items.get(initialIndex).inSelected = true
+        view.currentItem.currentIndex = initialIndex
+        view.currentItem.positionViewAtIndex(initialIndex, ItemView.Contain)
+    }
+
+    Connections {
+        target: medialib
+        onGridViewChanged: loadView()
+    }
+
+    Component {
+        id: headerComponent
+        Widgets.LabelSeparator {
+            text: i18n.qtr("Genres")
+            width: root.width
+        }
+    }
+
+    Util.SelectableDelegateModel {
+        id: delegateModel
+        model: MLGenreModel {
+            ml: medialib
+        }
+
+        delegate: Package {
+            Widgets.ListItem {
+                Package.name: "list"
+
+                width: root.width
+                height: VLCStyle.icon_normal + VLCStyle.margin_small
+
+                cover: Image {
+                    id: cover_obj
+                    fillMode: Image.PreserveAspectFit
+                    source: model.cover || VLCStyle.noArtAlbum
+                    sourceSize: Qt.size(width, height)
+                }
+
+                line1: (model.name || "Unknown genre")+" - "+model.nb_tracks+" tracks"
+
+                onItemClicked: {
+                    delegateModel.updateSelection( modifier, view.currentItem.currentIndex, index )
+                    view.currentItem.currentIndex = index
+                    this.forceActiveFocus()
+                }
+                onPlayClicked: {
+                    medialib.addAndPlay( model.id )
+                }
+                onItemDoubleClicked: {
+                    root.showAlbumView(model.id, model.name)
+                }
+                onAddToPlaylistClicked: {
+                    medialib.addToPlaylist( model.id );
+                }
+            }
+        }
+
+        onCountChanged: {
+            if (delegateModel.items.count > 0 && delegateModel.selectedGroup.count === 0) {
+                root.resetFocus()
+            }
+        }
+
+        function actionAtIndex(index) {
+            if (delegateModel.selectedGroup.count > 1) {
+                var list = []
+                for (var i = 0; i < delegateModel.selectedGroup.count; i++)
+                    list.push(delegateModel.selectedGroup.get(i).model.id)
+                medialib.addAndPlay( list )
+            } else if (delegateModel.selectedGroup.count === 1) {
+                showAlbumView(delegateModel.selectedGroup.get(0).model.id, delegateModel.selectedGroup.get(0).model.name)
+            }
+        }
+    }
+
+    /*
+     *define the intial position/selection
+     * This is done on activeFocus rather than Component.onCompleted because delegateModel.
+     * selectedGroup update itself after this event
+     */
+    onActiveFocusChanged: {
+        if (activeFocus && delegateModel.items.count > 0 && delegateModel.selectedGroup.count === 0) {
+            var initialIndex = 0
+            if (view.currentItem.currentIndex !== -1)
+                initialIndex = view.currentItem.currentIndex
+            delegateModel.items.get(initialIndex).inSelected = true
+            view.currentItem.currentIndex = initialIndex
+        }
+    }
+
+    /* Grid View */
+    Component {
+        id: gridComponent
+        Widgets.ExpandGridView {
+            id: gridView_id
+
+            model: delegateModel
+            modelCount: delegateModel.items.count
+
+            headerDelegate: headerComponent
+
+            delegate: AudioGridItem {
+                id: gridItem
+
+                image: model.cover || VLCStyle.noArtAlbum
+                title: model.name || "Unknown genre"
+                subtitle: ""
+                //selected: element.DelegateModel.inSelected
+
+                onItemClicked: {
+                    delegateModel.updateSelection( modifier , view.currentItem.currentIndex, index)
+                    view.currentItem.currentIndex = index
+                    view.currentItem.forceActiveFocus()
+                }
+
+                onItemDoubleClicked: root.showAlbumView(model.id, model.name)
+            }
+
+            focus: true
+
+            cellWidth: VLCStyle.gridItem_music_width
+            cellHeight: VLCStyle.gridItem_music_height
+
+            onSelectAll: delegateModel.selectAll()
+            onSelectionUpdated:  delegateModel.updateSelection( keyModifiers, oldIndex, newIndex )
+            onActionAtIndex: {
+                delegateModel.actionAtIndex(index)
+            }
+
+            navigationParent: root
+        }
+    }
+
+    Component {
+        id: listComponent
+        /* List View */
+        Widgets.KeyNavigableListView {
+            id: listView_id
+
+            model: delegateModel.parts.list
+            modelCount: delegateModel.items.count
+
+            header: headerComponent
+
+            focus: true
+            spacing: VLCStyle.margin_xxxsmall
+
+            onSelectAll: delegateModel.selectAll()
+            onSelectionUpdated: delegateModel.updateSelection( keyModifiers, oldIndex, newIndex )
+            onActionAtIndex: delegateModel.actionAtIndex(index)
+
+            navigationParent: root
+        }
+    }
+
+    Widgets.StackViewExt {
+        id: view
+
+        initialItem: medialib.gridView ? gridComponent : listComponent
+
+        anchors.fill: parent
+        focus: true
+    }
+
+    Label {
+        anchors.fill: parent
+        horizontalAlignment: Text.AlignHCenter
+        verticalAlignment: Text.AlignVCenter
+        visible: delegateModel.items.count === 0
+        font.pixelSize: VLCStyle.fontHeight_xxlarge
+        color: root.activeFocus ? VLCStyle.colors.accent : VLCStyle.colors.text
+        wrapMode: Text.WordWrap
+        text: i18n.qtr("No genres found\nPlease try adding sources, by going to the Network tab")
+    }
+}
diff --git a/modules/gui/qt/medialibrary/qml/MusicGenresDisplay.qml b/modules/gui/qt/medialibrary/qml/MusicGenresDisplay.qml
index 6763e6f743..05b6e930fc 100644
--- a/modules/gui/qt/medialibrary/qml/MusicGenresDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicGenresDisplay.qml
@@ -27,192 +27,87 @@ import "qrc:///style/"
 
 Widgets.NavigableFocusScope {
     id: root
-    property alias model: delegateModel.model
-    property var sortModel: [
-        { text: i18n.qtr("Alphabetic"), criteria: "title" }
-    ]
 
-    function showAlbumView( parent ) {
-        history.push([ "mc", "music", "albums", { parentId: parent } ])
+    //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: genresComponent
+    }, {
+        name: "albums",
+        component: albumGenreComponent
+    }]
+
+    Component.onCompleted: loadView()
+    onViewChanged: {
+        viewProperties = {}
+        loadView()
     }
+    onViewPropertiesChanged: loadView()
 
-    navigationCancel: function() {
-        if (view.currentItem.currentIndex <= 0)
-            defaultNavigationCancel()
-        else
-            view.currentItem.currentIndex = 0;
+    function loadDefaultView() {
+        root.view = "all"
+        root.viewProperties= ({})
     }
 
-    Component {
-        id: headerComponent
-        Widgets.LabelSeparator {
-            text: i18n.qtr("Genres")
-            width: root.width
-        }
+    function loadView() {
+        var found = stackView.loadView(root.pageModel, view, viewProperties)
+        if (!found)
+            stackView.replace(root.pageModel[0].component)
+        sortModel = stackView.currentItem.sortModel
+        contentModel = stackView.currentItem.model
     }
 
-    Util.SelectableDelegateModel {
-        id: delegateModel
-        model: MLGenreModel {
-            ml: medialib
-        }
-
-        delegate: Package {
-            Widgets.ListItem {
-                Package.name: "list"
-
-                width: root.width
-                height: VLCStyle.icon_normal + VLCStyle.margin_small
-
-                cover: Image {
-                    id: cover_obj
-                    fillMode: Image.PreserveAspectFit
-                    source: model.cover || VLCStyle.noArtAlbum
-                    sourceSize: Qt.size(width, height)
-                }
-
-                line1: (model.name || "Unknown genre")+" - "+model.nb_tracks+" tracks"
-
-                onItemClicked: {
-                    console.log("Clicked on : "+model.name);
-                    delegateModel.updateSelection( modifier, view.currentItem.currentIndex, index )
-                    view.currentItem.currentIndex = index
-                    this.forceActiveFocus()
-                }
-                onPlayClicked: {
-                    console.log('Clicked on play : '+model.name);
-                    medialib.addAndPlay( model.id )
-                }
-                onItemDoubleClicked: {
-                    root.showAlbumView(model.id)
-                }
-                onAddToPlaylistClicked: {
-                    console.log('Clicked on addToPlaylist : '+model.name);
-                    medialib.addToPlaylist( model.id );
-                }
-            }
-        }
-
-        function actionAtIndex(index) {
-            if (delegateModel.selectedGroup.count > 1) {
-                var list = []
-                for (var i = 0; i < delegateModel.selectedGroup.count; i++)
-                    list.push(delegateModel.selectedGroup.get(i).model.id)
-                medialib.addAndPlay( list )
-            } else if (delegateModel.selectedGroup.count === 1) {
-                showAlbumView(delegateModel.selectedGroup.get(0).model.id)
-            }
-        }
+    function _updateGenresAllHistory(currentIndex) {
+        history.update(["mc", "music", "genres", "all", { "initialIndex": currentIndex }])
     }
 
-    /*
-     *define the intial position/selection
-     * This is done on activeFocus rather than Component.onCompleted because delegateModel.
-     * selectedGroup update itself after this event
-     */
-    onActiveFocusChanged: {
-        if (activeFocus && delegateModel.items.count > 0 && delegateModel.selectedGroup.count === 0) {
-            var initialIndex = 0
-            if (view.currentItem.currentIndex !== -1)
-                initialIndex = view.currentItem.currentIndex
-            delegateModel.items.get(initialIndex).inSelected = true
-            view.currentItem.currentIndex = initialIndex
-        }
+    function _updateGenresAlbumsHistory(currentIndex, parentId, genreName) {
+        history.update(["mc","music", "genres", "albums", {
+            "initialIndex": currentIndex,
+            "parentId": parentId,
+            "genreName": genreName,
+        }])
     }
 
-    /* Grid View */
     Component {
-        id: gridComponent
-        Widgets.ExpandGridView {
-            id: gridView_id
-
-            model: delegateModel
-            modelCount: delegateModel.items.count
-
-            headerDelegate: headerComponent
-
-            delegate: AudioGridItem {
-                id: gridItem
-
-                image: model.cover || VLCStyle.noArtAlbum
-                title: model.name || "Unknown genre"
-                subtitle: ""
-                //selected: element.DelegateModel.inSelected
-
-                onItemClicked: {
-                    delegateModel.updateSelection( modifier , view.currentItem.currentIndex, index)
-                    view.currentItem.currentIndex = index
-                    view.currentItem.forceActiveFocus()
-                }
-
-                onItemDoubleClicked: {
-                    root.showAlbumView(model.id)
-                }
-            }
-
-            focus: true
-
-            cellWidth: VLCStyle.gridItem_music_width
-            cellHeight: VLCStyle.gridItem_music_height
-
-            onSelectAll: delegateModel.selectAll()
-            onSelectionUpdated:  delegateModel.updateSelection( keyModifiers, oldIndex, newIndex )
-            onActionAtIndex: delegateModel.actionAtIndex(index)
+        id: genresComponent
+        /* List View */
+        MusicGenres {
+            onCurrentIndexChanged: _updateGenresAllHistory(currentIndex)
 
             navigationParent: root
         }
     }
 
     Component {
-        id: listComponent
+        id: albumGenreComponent
         /* List View */
-        Widgets.KeyNavigableListView {
-            id: listView_id
+        MusicAlbums {
+            property string genreName: ""
 
-            model: delegateModel.parts.list
-            modelCount: delegateModel.items.count
-
-            header: headerComponent
-
-            focus: true
-            spacing: VLCStyle.margin_xxxsmall
+            header: Widgets.LabelSeparator {
+                text: i18n.qtr("Genres - %1").arg(genreName)
+                width: root.width
+            }
 
-            onSelectAll: delegateModel.selectAll()
-            onSelectionUpdated: delegateModel.updateSelection( keyModifiers, oldIndex, newIndex )
-            onActionAtIndex: delegateModel.actionAtIndex(index)
+            onParentIdChanged: _updateGenresAlbumsHistory(currentIndex, parentId, genreName)
+            onGenreNameChanged: _updateGenresAlbumsHistory(currentIndex, parentId, genreName)
+            onCurrentIndexChanged: _updateGenresAlbumsHistory(currentIndex, parentId, genreName)
 
             navigationParent: root
         }
     }
 
-
     Widgets.StackViewExt {
-        id: view
+        id: stackView
 
         anchors.fill: parent
         focus: true
-
-        initialItem: medialib.gridView ? gridComponent : listComponent
-
-        Connections {
-            target: medialib
-            onGridViewChanged: {
-                if (medialib.gridView)
-                    view.replace(gridComponent)
-                else
-                    view.replace(listComponent)
-            }
-        }
-    }
-
-    Label {
-        anchors.fill: parent
-        horizontalAlignment: Text.AlignHCenter
-        verticalAlignment: Text.AlignVCenter
-        visible: delegateModel.items.count === 0
-        font.pixelSize: VLCStyle.fontHeight_xxlarge
-        color: root.activeFocus ? VLCStyle.colors.accent : VLCStyle.colors.text
-        wrapMode: Text.WordWrap
-        text: i18n.qtr("No genres found\nPlease try adding sources, by going to the Network tab")
     }
 }
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index ec0b278d27..faf8f8ba74 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -225,6 +225,7 @@
     <qresource prefix="/medialibrary">
         <file alias="MusicAlbums.qml">medialibrary/qml/MusicAlbums.qml</file>
         <file alias="MusicDisplay.qml">medialibrary/qml/MusicDisplay.qml</file>
+        <file alias="MusicGenres.qml">medialibrary/qml/MusicGenres.qml</file>
         <file alias="VideoDisplay.qml">medialibrary/qml/VideoDisplay.qml</file>
         <file alias="MusicAlbumsDisplay.qml">medialibrary/qml/MusicAlbumsDisplay.qml</file>
         <file alias="MusicAlbumsGridExpandDelegate.qml">medialibrary/qml/MusicAlbumsGridExpandDelegate.qml</file>
-- 
2.17.1



More information about the vlc-devel mailing list