[vlc-commits] qml: split the music genre view
Pierre Lamot
git at videolan.org
Fri Feb 14 12:00:08 CET 2020
vlc | branch: master | Pierre Lamot <pierre at videolabs.io> | Thu Jan 30 18:21:25 2020 +0100| [2c539bcbbe44ccf68dbdc501f26d52aac9405baf] | committer: Jean-Baptiste Kempf
qml: split the music genre view
the genre view can now either load the regular view presenting the genres
or load a specialized album view for a defined genre
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2c539bcbbe44ccf68dbdc501f26d52aac9405baf
---
modules/gui/qt/Makefile.am | 1 +
modules/gui/qt/medialibrary/qml/MusicGenres.qml | 244 +++++++++++++++++++++
.../gui/qt/medialibrary/qml/MusicGenresDisplay.qml | 209 +++++-------------
modules/gui/qt/vlc.qrc | 1 +
4 files changed, 298 insertions(+), 157 deletions(-)
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>
More information about the vlc-commits
mailing list