[vlc-commits] qml: infoWin using expandableGridView

Abel Tesfaye git at videolan.org
Tue Jul 30 17:57:15 CEST 2019


vlc | branch: master | Abel Tesfaye <Abeltesfaye45 at gmail.com> | Mon Jul 22 15:48:14 2019 +0300| [8b2f4237cce3cf04fd25872adff1667a823b012d] | committer: Jean-Baptiste Kempf

qml: infoWin using expandableGridView

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8b2f4237cce3cf04fd25872adff1667a823b012d
---

 modules/gui/qt/Makefile.am                         |   1 +
 modules/gui/qt/qml/mediacenter/MCVideoDisplay.qml  | 227 ++++++-------
 .../gui/qt/qml/mediacenter/VideoExpandableGrid.qml | 355 +++++++++++++++++++++
 modules/gui/qt/qml/utils/ExpandGridView.qml        |  27 +-
 modules/gui/qt/qml/utils/GridItem.qml              |  13 +-
 modules/gui/qt/vlc.qrc                             |   1 +
 6 files changed, 506 insertions(+), 118 deletions(-)

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 1a343f405c..bdf5dcd5cf 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -610,6 +610,7 @@ libqt_plugin_la_QML = \
 	gui/qt/qml/mediacenter/NetworkDriveDisplay.qml \
 	gui/qt/qml/mediacenter/NetworkFileDisplay.qml \
 	gui/qt/qml/mediacenter/NetworkListItem.qml \
+	gui/qt/qml/mediacenter/VideoExpandableGrid.qml \
 	gui/qt/qml/playlist/PlaylistListView.qml \
 	gui/qt/qml/playlist/PlaylistMainView.qml \
 	gui/qt/qml/playlist/PLItem.qml \
diff --git a/modules/gui/qt/qml/mediacenter/MCVideoDisplay.qml b/modules/gui/qt/qml/mediacenter/MCVideoDisplay.qml
index 5c955a6063..6a2d0a799c 100644
--- a/modules/gui/qt/qml/mediacenter/MCVideoDisplay.qml
+++ b/modules/gui/qt/qml/mediacenter/MCVideoDisplay.qml
@@ -27,9 +27,8 @@ import "qrc:///style/"
 
 Utils.NavigableFocusScope {
     id: root
-
-    property alias model: delegateModel.model
-
+    property Item videosGridView: Item{}
+    property Item currentGridView: Item{}
     DG.ModalDialog {
         id: deleteDialog
         rootWindow: root
@@ -64,7 +63,9 @@ Utils.NavigableFocusScope {
            }
            Utils.MenuItemExt {
                text: "Information"
-               onTriggered: console.log("not implemented")
+               onTriggered: {
+                   root.currentGridView.switchExpandItem(contextMenu.model.index,root.currentGridView.currentItem)
+                }
            }
            Utils.MenuItemExt {
                text: "Download subtitles"
@@ -83,52 +84,18 @@ Utils.NavigableFocusScope {
 
        }
     Utils.SelectableDelegateModel {
-        id: delegateModel
+        id: videosDelegate
+
         model: MLVideoModel {
             ml: medialib
         }
 
         delegate: Package {
             id: element
-            Utils.GridItem {
-                Package.name: "grid"
-                focus: true
-                image: model.thumbnail || VLCStyle.noArtCover
-                title: model.title || qsTr("Unknown title")
-                selected: element.DelegateModel.inSelected
-                shiftX: view.currentItem.shiftX(model.index)
-                infoLeft: model.duration
-                resolution: model.resolution_name
-                channel: model.channel
-                isVideo: true
-                isNew: model.playcount < 1
-                progress: Math.max(model.saved_position,0)
-
-                onItemClicked : {
-                    if (key == Qt.RightButton){
-                        contextMenu.model = model
-                        contextMenu.popup()
-                    }
-                    else {
-                        delegateModel.updateSelection( modifier , view.currentItem.currentIndex, index)
-                        view.currentItem.currentIndex = index
-                        view.currentItem.forceActiveFocus()
-                    }
-                }
-                onPlayClicked: medialib.addAndPlay( model.id )
-                onAddToPlaylistClicked : medialib.addToPlaylist( model.id )
-                onContextMenuButtonClicked:{
-                    contextMenu.model = model;
-                    contextMenu.popup(menuParent,contextMenu.width,0,playMenuItem)
-                }
-
-         }
             Utils.ListItem {
                 Package.name: "list"
                 width: root.width
                 height: VLCStyle.icon_normal
-                focus: true
-
                 color: VLCStyle.colors.getBgColor(element.DelegateModel.inSelected, this.hovered, this.activeFocus)
 
                 cover: Image {
@@ -139,8 +106,8 @@ Utils.NavigableFocusScope {
                 line1: (model.title || qsTr("Unknown title"))+" ["+model.duration+"]"
 
                 onItemClicked : {
-                    delegateModel.updateSelection( modifier, view.currentItem.currentIndex, index )
-                    view.currentItem.currentIndex = index
+                    videosDelegate.updateSelection( modifier, view.currentItem.currentIndexVideos, index )
+                    view.currentItem.currentIndexVideos = index
                     this.forceActiveFocus()
                 }
                 onPlayClicked: medialib.addAndPlay( model.id )
@@ -149,86 +116,125 @@ Utils.NavigableFocusScope {
         }
         function actionAtIndex(index) {
             var list = []
-            for (var i = 0; i < delegateModel.selectedGroup.count; i++)
-                list.push(delegateModel.selectedGroup.get(i).model.id)
+            for (var i = 0; i < videosDelegate.selectedGroup.count; i++)
+                list.push(videosDelegate.selectedGroup.get(i).model.id)
             medialib.addAndPlay( list )
         }
     }
 
-    /*
-     *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
-        }
-    }
-
     Component {
         id: gridComponent
-        Utils.KeyNavigableGridView {
-            id: gridView_id
-
-            model: delegateModel.parts.grid
-            modelCount: delegateModel.items.count
-
-            focus: true
-
-            cellWidth: (VLCStyle.video_normal_width) + VLCStyle.margin_large
-            cellHeight: (VLCStyle.video_normal_height) + VLCStyle.margin_xlarge + VLCStyle.margin_normal
+        Flickable{
+            id: flickable
+            anchors.fill: parent
+            contentHeight: allSections.implicitHeight
+            ScrollBar.vertical: ScrollBar{}
+            onActiveFocusChanged: {
+            if(activeFocus)
+                videosGV.forceActiveFocus()
+            }
 
-            onSelectAll: delegateModel.selectAll()
-            onSelectionUpdated: delegateModel.updateSelection( keyModifiers, oldIndex, newIndex )
-            onActionAtIndex: delegateModel.actionAtIndex(index)
 
-            onActionLeft: root.actionLeft(index)
-            onActionRight: root.actionRight(index)
-            onActionDown: root.actionDown(index)
-            onActionUp: root.actionUp(index)
-            onActionCancel: root.actionCancel(index)
+            property int currentIndexVideos: -1
 
-            header:Item {
-                id: videosHeader
-                height: childrenRect.height + VLCStyle.margin_normal
-                anchors{
+            Rectangle {
+                id: allSections
+                color: "transparent"
+                implicitHeight: childrenRect.height
+                implicitWidth: view.width
+                anchors {
                     left: parent.left
                     right: parent.right
                 }
 
-                Label {
-                    id: videosTxt
-
-                    anchors.top: videosHeader.top
-                    anchors.left: videosHeader.left
-                    anchors.topMargin: VLCStyle.margin_normal
-                    anchors.leftMargin: VLCStyle.margin_large
+            Rectangle {
+                id: videosSection
+                anchors {
+                    left: parent.left
+                    right: parent.right
+                }
+                implicitHeight: childrenRect.height
+                color: "transparent"
 
-                    font.pixelSize: VLCStyle.fontSize_xxlarge
-                    color: VLCStyle.colors.text
+                Utils.LabelSeparator {
+                    id: videosSeparator
                     text: qsTr("Videos")
-                    font.weight: Font.Bold
                 }
-
                 Rectangle {
-                    id: videosSeparator
-                    height: VLCStyle.heightBar_xxxsmall
-                    radius: 2
+                    color: VLCStyle.colors.bg
+                    anchors.top: videosSeparator.bottom
+                    anchors.left: parent.left
+                    anchors.right: parent.right
+                    height: videosGV.contentHeight
+                    VideoExpandableGrid {
+                        id: videosGV
+                        Component.onCompleted: root.videosGridView = videosGV
+                        property Item currentItem: Item{}
+
+                        activeFocusOnTab:true
+                        anchors.fill: parent
+                        flickableDirection:  Flickable.VerticalFlick
+                        model: videosDelegate
+                        modelTop: videosDelegate.parts.gridTop
+                        modelCount: videosDelegate.items.count
+
+                        expandDelegateImplicitHeight: view.height/3
+                        expandDelegateWidth: view.width
+
+
+                        onGridItemClicked: {
+                            if (key == Qt.RightButton){
+                                contextMenu.model = delegateModelItem.model
+                                contextMenu.popup()
+                }
+                            videosDelegate.updateSelection( modifier , view.currentItem.currentIndexVideos, delegateModelItem.itemsIndex)
+                            view.currentItem.currentIndexVideos = delegateModelItem.itemsIndex
+                            root.currentGridView = videosGV
+                            root.currentGridView.currentIndex = delegateModelItem.itemsIndex
+                            root.currentGridView.forceActiveFocus()
+
+                            videosGV.renderLayout()
+                        }
+                        onGridItemContextButtonClicked: {
+                            contextMenu.model = delegateModelItem.model;
+                            contextMenu.popup(menuParent,contextMenu.width,0,contextMenu.playMenuItem)
+                        }
+                        onGridItemSelectedChanged: {
+                            if(selected){
+                                root.currentGridView = videosGV
+                                videosGV.currentItem = item
+
+                                if (videosSection.y + videosGV.currentItem.y + videosGV.currentItem.height > flickable.contentY + flickable.height - videosSection.y ||
+                                       videosSection.y + videosGV.currentItem.y < flickable.contentY)
+
+                                    flickable.contentY = ((view.height + videosGV.currentItem.y) > flickable.contentHeight) ?
+                                                flickable.contentHeight-view.height : videosSection.y + videosGV.currentItem.y
+                            }
+                }
+
+                        onActionLeft: root.actionLeft(index)
+                        onActionRight: root.actionRight(index)
+                        onActionDown: root.actionDown(index)
+                        onActionCancel: root.actionCancel(index)
+
+                        /*
+                         *define the intial position/selection
+                         * This is done on activeFocus rather than Component.onCompleted because videosDelegate.
+                         * selectedGroup update itself after this event
+                         */
+                        onActiveFocusChanged: {
+                            if (activeFocus && videosDelegate.items.count > 0 && videosDelegate.selectedGroup.count === 0) {
+                                var initialIndex = 0
+                                if (view.currentItem.currentIndexVideos !== -1)
+                                    initialIndex = view.currentItem.currentIndexVideos
+                                videosDelegate.items.get(initialIndex).inSelected = true
+                                view.currentItem.currentIndexVideos = initialIndex
+                            }
+                        }
 
-                    anchors{
-                        left: videosHeader.left
-                        right: videosHeader.right
-                        top: videosTxt.bottom
-                        topMargin: VLCStyle.margin_small
-                        leftMargin: VLCStyle.margin_large
+                    }
 
                     }
-                    color: VLCStyle.colors.bgAlt
                 }
             }
         }
@@ -240,15 +246,15 @@ Utils.NavigableFocusScope {
         Utils.KeyNavigableListView {
             id: listView_id
 
-            model: delegateModel.parts.list
-            modelCount: delegateModel.items.count
+            model: videosDelegate.parts.list
+            modelCount: videosDelegate.items.count
 
             focus: true
             spacing: VLCStyle.margin_xxxsmall
 
-            onSelectAll: delegateModel.selectAll()
-            onSelectionUpdated: delegateModel.updateSelection( keyModifiers, oldIndex, newIndex )
-            onActionAtIndex: delegateModel.actionAtIndex(index)
+            onSelectAll: videosDelegate.selectAll()
+            onSelectionUpdated: videosDelegate.updateSelection( keyModifiers, oldIndex, newIndex )
+            onActionAtIndex: videosDelegate.actionAtIndex(index)
 
             onActionLeft: root.actionLeft(index)
             onActionRight: root.actionRight(index)
@@ -260,9 +266,8 @@ Utils.NavigableFocusScope {
 
         Utils.StackViewExt {
             id: view
-
-            anchors.fill: root
-
+            anchors.fill:parent
+            clip: true
             focus: true
             initialItem: medialib.gridView ? gridComponent : listComponent
             Connections {
@@ -278,7 +283,7 @@ Utils.NavigableFocusScope {
     }
     Label {
         anchors.centerIn: parent
-        visible: delegateModel.items.count === 0
+        visible: videosDelegate.items.count === 0
         font.pixelSize: VLCStyle.fontHeight_xxlarge
         color: root.activeFocus ? VLCStyle.colors.accent : VLCStyle.colors.text
         text: qsTr("No tracks found")
diff --git a/modules/gui/qt/qml/mediacenter/VideoExpandableGrid.qml b/modules/gui/qt/qml/mediacenter/VideoExpandableGrid.qml
new file mode 100644
index 0000000000..c731b368f1
--- /dev/null
+++ b/modules/gui/qt/qml/mediacenter/VideoExpandableGrid.qml
@@ -0,0 +1,355 @@
+/*****************************************************************************
+ * 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 org.videolan.medialib 0.1
+
+import "qrc:///utils/" as Utils
+import "qrc:///dialogs/" as DG
+import "qrc:///style/"
+
+Utils.ExpandGridView {
+    id: expandableGV
+    signal gridItemClicked(int key,int modifier,variant delegateModelItem)
+    signal gridItemContextButtonClicked(Item menuParent,variant delegateModelItem)
+    signal gridItemSelectedChanged(bool selected,Item item)
+
+    property Item currentItem: Item{}
+
+    activeFocusOnTab:true
+    anchors.fill: parent
+
+    property real expandDelegateImplicitHeight: parent.height
+    property real expandDelegateWidth: parent.width
+
+    property real gridDelegatePictureWidth: VLCStyle.video_normal_width
+    property real gridDelegatePictureHeight: VLCStyle.video_normal_height
+
+
+    gridDelegate: Utils.GridItem {
+        property variant delegateModelItem: ({
+                                                 model: ({}),
+                                                 itemsIndex: 0,
+                                                 inSelected: false
+                                             })
+
+        image: delegateModelItem.model.thumbnail || VLCStyle.noArtCover
+        title: delegateModelItem.model.title || qsTr("Unknown title")
+        selected: expandableGV.activeFocus && (delegateModelItem.inSelected || contextButtonDown )
+        infoLeft: delegateModelItem.model.duration || ""
+        resolution: delegateModelItem.model.resolution_name || ""
+        channel: delegateModelItem.model.channel || ""
+        isVideo: true
+        isNew: delegateModelItem.model.playcount < 1
+        progress: Math.max(0, delegateModelItem.model.saved_position)
+        shiftX: expandableGV.isSingleRow ? 0 : expandableGV.shiftX(delegateModelItem.model.index)
+        pictureWidth: expandableGV.gridDelegatePictureWidth
+        pictureHeight: expandableGV.gridDelegatePictureHeight
+
+        onItemClicked : expandableGV.gridItemClicked(key,modifier, delegateModelItem)
+
+        onPlayClicked: medialib.addAndPlay( delegateModelItem.model.id )
+        onAddToPlaylistClicked : medialib.addToPlaylist( delegateModelItem.model.id )
+        onContextMenuButtonClicked: expandableGV.gridItemContextButtonClicked(menuParent,delegateModelItem)
+        onSelectedChanged:expandableGV.gridItemSelectedChanged(selected,this)
+    }
+    expandDelegate:  Rectangle {
+        id: expandRect
+        property int currentId: -1
+        property var model : ({})
+        property alias currentItemY: expandRect.y
+        property alias currentItemHeight: expandRect.height
+        implicitHeight: expandableGV.expandDelegateImplicitHeight
+        width: expandableGV.expandDelegateWidth
+
+        color: "transparent"
+        Rectangle{
+            id:arrowRect
+            x: expandableGV.expanderItem.x + (expandableGV.expanderItem.shiftX/2) + (expandableGV.cellWidth/2)
+            y: -(width/2)
+            width: VLCStyle.icon_normal
+            height: VLCStyle.icon_normal
+            color: VLCStyle.colors.text
+            rotation: 45
+            visible: !expandableGV.isAnimating
+        }
+        Rectangle{
+            height: parent.height
+            width: parent.width
+            clip: true
+            color: VLCStyle.colors.text
+            x: expandableGV.contentX
+
+            Rectangle {
+                color: "transparent"
+                height: parent.height
+                anchors {
+                    left:parent.left
+                    right:parent.right
+                }
+
+
+                Image {
+                    id: img
+                    anchors.left: parent.left
+                    anchors.leftMargin: VLCStyle.margin_large
+                    anchors.verticalCenter: parent.verticalCenter
+                    width: VLCStyle.cover_large
+                    height: VLCStyle.cover_large
+                    fillMode:Image.PreserveAspectFit
+
+                    source: model.thumbnail || ""
+                }
+                Column{
+                    id: infoCol
+                    height: childrenRect.height
+                    anchors.left:img.right
+                    anchors.leftMargin: VLCStyle.margin_normal
+                    anchors.verticalCenter: parent.verticalCenter
+                    spacing: VLCStyle.margin_small
+                    width: 300 * VLCStyle.scale
+                    Text{
+                        id: newtxt
+                        font.pixelSize: VLCStyle.fontSize_normal
+                        font.weight: Font.ExtraBold
+                        text: "NEW"
+                        color: VLCStyle.colors.accent
+                        visible: model.playcount < 1
+                    }
+                    Column{
+                        width: parent.width
+                        spacing: VLCStyle.margin_xsmall
+                        Text{
+                            id: title
+                            wrapMode: Text.Wrap
+                            font.pixelSize: VLCStyle.fontSize_large
+                            font.weight: Font.ExtraBold
+                            text: model.title || ""
+                            color: VLCStyle.colors.bg
+                            width: parent.width
+                        }
+                        Text {
+                            id: time
+                            text: model.duration || ""
+                            color: VLCStyle.colors.textInactive
+                            font.pixelSize: VLCStyle.fontSize_small
+                        }
+                    }
+
+                    Button {
+                        id: playBtn
+                        hoverEnabled: true
+                        width: VLCStyle.icon_xlarge
+                        height: VLCStyle.icon_medium
+                        background: Rectangle{
+                            color: playBtn.pressed? VLCStyle.colors.textInactive: VLCStyle.colors.accent
+                            width: parent.width
+                            height: parent.height
+                            radius: playBtn.width/3
+                        }
+                        contentItem:Item{
+                            implicitWidth: childrenRect.width
+                            implicitHeight: childrenRect.height
+                            anchors.centerIn: playBtn
+
+                            Label {
+                                anchors.verticalCenter: parent.verticalCenter
+                                id: icon
+                                text:  playBtn.fontIcon
+                                font.family: VLCIcons.fontFamily
+                                font.pixelSize: parent.height
+                                color: playBtn.pressed || playBtn.hovered?  VLCStyle.colors.bg : VLCStyle.colors.bgAlt
+                            }
+
+
+                            Label {
+                                anchors.verticalCenter: parent.verticalCenter
+                                anchors.left: icon.right
+                                text: playBtn.text
+                                font: playBtn.font
+                                color: playBtn.pressed || playBtn.hovered? VLCStyle.colors.bg : VLCStyle.colors.bgAlt
+
+                            }
+                        }
+
+
+                        property string fontIcon: VLCIcons.play
+
+                        text: qsTr("Play Video")
+                        onClicked: medialib.addAndPlay( model.id )
+                    }
+                }
+                Flickable{
+                    anchors{
+                        left: infoCol.right
+                        right: controlCol.left
+                        top: parent.top
+                        bottom: parent.bottom
+                        topMargin: VLCStyle.margin_small
+                        bottomMargin: VLCStyle.margin_small
+                    }
+                    width: parent.width
+                    contentHeight: infoInnerCol.height
+                    Column{
+                        id: infoInnerCol
+                        height: childrenRect.height
+                        anchors{
+                            left: parent.left
+                            right: parent.right
+                        }
+                        anchors.verticalCenter: parent.verticalCenter
+                        spacing: VLCStyle.margin_xsmall
+                        Repeater {
+                            model: [
+                                {text: qsTr("File Name"),    data: expandRect.model.title, bold: true},
+                                {text: qsTr("Path"),         data: expandRect.model.mrl},
+                                {text: qsTr("Length"),       data: expandRect.model.duration},
+                                {text: qsTr("File size"),    data: ""},
+                                {text: qsTr("Times played"), data: expandRect.model.playcount},
+                                {text: qsTr("Video track"),  data: expandRect.model.videoDesc},
+                                {text: qsTr("Audio track"),  data: expandRect.model.audioDesc},
+                            ]
+                            delegate: Label {
+                                font.bold: Boolean(modelData.bold)
+                                text: modelData.text + ": " + modelData.data
+                                color: VLCStyle.colors.textInactive
+                                width: parent.width
+                                wrapMode: Label.Wrap
+                            }
+                        }
+                    }
+                }
+
+                Rectangle{
+                    id: controlCol
+                    anchors.right: parent.right
+                    width: 300 * VLCStyle.scale
+                    height: parent.height
+                    color: VLCStyle.colors.text
+
+                    Column{
+                        anchors {
+                            left: parent.left
+                            right: parent.right
+                            verticalCenter: parent.verticalCenter
+                        }
+
+                        spacing: VLCStyle.margin_normal
+                        Repeater {
+                            id:reptr
+                            anchors.fill: parent
+                            model: [
+                                    {label: qsTr("Rename Video"), ic: VLCIcons.rename},
+                                    {label: qsTr("Enqueue"), ic: VLCIcons.add},
+                                    {label: qsTr("Share"), ic: VLCIcons.lan},
+                                    {label: qsTr("Delete"), ic: VLCIcons.del}
+                                ]
+                            
+                            delegate: Button {
+                                id: reptrBtn
+                                hoverEnabled: true
+                                width: reptr.width
+                                background: Rectangle{
+                                    color: pressed? "#000": VLCStyle.colors.text
+                                    width: parent.width
+                                    height: parent.height
+                                    radius: 3
+                                }
+                                contentItem: Item{
+                                    implicitWidth: childrenRect.width
+                                    implicitHeight: childrenRect.height
+
+                                    Label {
+                                        id: icon
+                                        text:  reptrBtn.fontIcon
+                                        font.family: VLCIcons.fontFamily
+                                        font.pixelSize: VLCStyle.icon_normal
+                                        verticalAlignment: Text.AlignVCenter
+                                        color: pressed || hovered? VLCStyle.colors.accent : VLCStyle.colors.bgAlt
+                                    }
+
+
+                                    Label {
+                                        anchors.left: icon.right
+                                        anchors.leftMargin: VLCStyle.margin_normal
+                                        text: reptrBtn.text
+                                        font: reptrBtn.font
+                                        verticalAlignment: Text.AlignVCenter
+                                        color: pressed || hovered? VLCStyle.colors.accent : VLCStyle.colors.bgAlt
+                                    }
+                                }
+
+
+                                text: modelData.label
+                                property string fontIcon: modelData.ic
+                                onClicked: reptr.handleClick(index)
+                            }
+                            function handleClick(index){
+                                switch(index){
+                                case 1:medialib.addToPlaylist( expandRect.model.id )
+                                    break
+
+                                default:
+                                    console.log("you clicked on an unhandled index:",index)
+                                }
+                            }
+                        }
+                    }
+                }
+
+
+            }
+            Button {
+                id: closeBtn
+                hoverEnabled: true
+                width: VLCStyle.icon_medium
+                height: VLCStyle.icon_medium
+                anchors.right: parent.right
+                background: Rectangle{
+                    color: closeBtn.pressed? "#000": VLCStyle.colors.text
+                    width: parent.width
+                    height: parent.height
+                    radius: 3
+                }
+                contentItem:Label {
+                    text: closeBtn.text
+                    font: VLCIcons.fontFamily
+                    verticalAlignment: Text.AlignVCenter
+                    horizontalAlignment: Text.AlignHCenter
+                    color: closeBtn.pressed || closeBtn.hovered? VLCStyle.colors.accent : VLCStyle.colors.bgAlt
+                }
+
+                text: VLCIcons.close
+                font.pixelSize: VLCStyle.icon_normal
+                font.family: VLCIcons.fontFamily
+                onClicked: expandableGV.retract()
+            }
+
+        }
+
+    }
+
+    cellWidth: (VLCStyle.video_normal_width) + VLCStyle.margin_large
+    cellHeight: (VLCStyle.video_normal_height) + VLCStyle.margin_xlarge + VLCStyle.margin_normal
+
+    onSelectAll: expandableGV.model.selectAll()
+    onSelectionUpdated: expandableGV.model.updateSelection( keyModifiers, oldIndex, newIndex )
+    onActionAtIndex: expandableGV.model.actionAtIndex(index)
+
+}
diff --git a/modules/gui/qt/qml/utils/ExpandGridView.qml b/modules/gui/qt/qml/utils/ExpandGridView.qml
index 92e2eef682..2af03ce865 100644
--- a/modules/gui/qt/qml/utils/ExpandGridView.qml
+++ b/modules/gui/qt/qml/utils/ExpandGridView.qml
@@ -36,6 +36,12 @@ NavigableFocusScope {
     property int modelCount: 0
 
     property int currentIndex: 0
+    property real contentHeight: flickable.contentHeight
+    property real contentWidth: flickable.contentWidth
+    property alias contentX: flickable.contentX
+    property bool isSingleRow: false
+    property bool isAnimating: animateRetractItem.running || animateExpandItem.running
+    property alias flickableDirection: flickable.flickableDirection
 
     /// the id of the item to be expanded
     property int _expandIndex: -1
@@ -44,6 +50,7 @@ NavigableFocusScope {
     //delegate to display the extended item
     property Component gridDelegate: Item{}
     property Component expandDelegate: Item{}
+    property Item expanderItem: Item{}
 
     //signals emitted when selected items is updated from keyboard
     signal selectionUpdated( int keyModifiers, int oldIndex,int newIndex )
@@ -52,13 +59,20 @@ NavigableFocusScope {
 
     property double _expandRetractSpeed: 1.
 
+    function renderLayout() {
+        flickable.layout()
+    }
+
     function shiftX(index) {
         var colCount = flickable.getNbItemsPerRow()
         var rightSpace = width - colCount * root.cellWidth
         return ((index % colCount) + 1) * (rightSpace / (colCount + 1))
     }
 
-    function switchExpandItem(index) {
+    function switchExpandItem(index,item) {
+        if (item)
+            root.expanderItem = item
+
         if (index === _expandIndex)
             _newExpandIndex = -1
         else
@@ -79,17 +93,21 @@ NavigableFocusScope {
     Flickable {
         id: flickable
         clip: true
+        ScrollBar.horizontal: ScrollBar{
+            anchors.bottom: flickable.bottom
+            anchors.left: flickable.left
+        }
 
         property variant model
         property Item expandItem: root.expandDelegate.createObject(contentItem, {"height": 0})
-
         anchors.fill: parent
-
         onWidthChanged: { layout() }
         onHeightChanged: { layout() }
         onContentYChanged: { layout() }
 
         function getNbItemsPerRow() {
+            if (isSingleRow)
+                return model.count
             return Math.max(Math.floor(width / root.cellWidth), 1)
         }
 
@@ -220,6 +238,7 @@ NavigableFocusScope {
             if (root._expandIndex !== -1)
                 newContentHeight += expandItem.height
             contentHeight = newContentHeight
+            contentWidth = root.cellWidth * getNbItemsPerRow()
             setCurrentItemFocus()
         }
 
@@ -392,7 +411,7 @@ NavigableFocusScope {
                 newIndex = Math.max(0, currentIndex - 1)
             }
         } else if (event.key === Qt.Key_Down || event.matches(StandardKey.MoveToNextLine) ||event.matches(StandardKey.SelectNextLine) ) {
-            if (Math.floor(currentIndex / colCount) !== Math.floor(root.modelCount / colCount)) { //we are not on the last line
+            if (!isSingleRow && Math.floor(currentIndex / colCount) !== Math.floor(root.modelCount / colCount)) { //we are not on the last line
                 newIndex = Math.min(root.modelCount - 1, currentIndex + colCount)
             }
         } else if (event.key === Qt.Key_PageDown || event.matches(StandardKey.MoveToNextPage) ||event.matches(StandardKey.SelectNextPage)) {
diff --git a/modules/gui/qt/qml/utils/GridItem.qml b/modules/gui/qt/qml/utils/GridItem.qml
index ab3f5aacd1..7c0c41c0b4 100644
--- a/modules/gui/qt/qml/utils/GridItem.qml
+++ b/modules/gui/qt/qml/utils/GridItem.qml
@@ -28,6 +28,7 @@ import "qrc:///style/"
 Rectangle {
     id: root
 
+    color: "transparent"
     property url image
     property string title: ""
     property string subtitle: ""
@@ -42,6 +43,11 @@ Rectangle {
     property bool isNew: false
     property double progress: 0.5
     property string channel: ""
+    property real pictureWidth: isVideo ? VLCStyle.video_normal_width : VLCStyle.cover_small
+    property real pictureHeight: isVideo ? VLCStyle.video_normal_height : VLCStyle.cover_small
+    property alias contextButtonDown: contextButton.down
+    width: gridItem.width
+    height: gridItem.height
 
     signal playClicked
     signal addToPlaylistClicked
@@ -56,7 +62,7 @@ Rectangle {
         width: childrenRect.width
         height: childrenRect.height
         color: "transparent"
-
+        
         MouseArea {
             id: mouseArea
             hoverEnabled: true
@@ -70,8 +76,8 @@ Rectangle {
 
             Item {
                 id: picture
-                width: isVideo ? VLCStyle.video_normal_width : VLCStyle.cover_small
-                height: isVideo ? VLCStyle.video_normal_height : VLCStyle.cover_small
+                width: root.pictureWidth
+                height: root.pictureHeight
                 anchors.top: mouseArea.top
                 property bool highlighted: selected || root.activeFocus
 
@@ -509,6 +515,7 @@ Rectangle {
                     }
                 }
             }
+
         }
     }
 }
\ No newline at end of file
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index 2a71cf830e..1325024318 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -216,6 +216,7 @@
         <file alias="NetworkDriveDisplay.qml">qml/mediacenter/NetworkDriveDisplay.qml</file>
         <file alias="NetworkFileDisplay.qml">qml/mediacenter/NetworkFileDisplay.qml</file>
         <file alias="NetworkListItem.qml">qml/mediacenter/NetworkListItem.qml</file>
+        <file alias="VideoExpandableGrid.qml">qml/mediacenter/VideoExpandableGrid.qml</file>
     </qresource>
     <qresource prefix="/style">
         <file alias="qmldir">qml/style/qmldir</file>



More information about the vlc-commits mailing list