[vlc-devel] [PATCH 02/55] qml: use exported OverlayMenu in Playlist

Fatih Uzunoglu fuzun54 at outlook.com
Thu Jan 7 21:36:15 UTC 2021


---
 modules/gui/qt/Makefile.am                    |   2 +-
 .../gui/qt/playlist/qml/PlaylistListView.qml  | 161 +--------
 modules/gui/qt/playlist/qml/PlaylistMenu.qml  | 275 ----------------
 .../qt/playlist/qml/PlaylistOverlayMenu.qml   | 306 ++++++++++++++++++
 modules/gui/qt/vlc.qrc                        |   2 +-
 5 files changed, 321 insertions(+), 425 deletions(-)
 delete mode 100644 modules/gui/qt/playlist/qml/PlaylistMenu.qml
 create mode 100644 modules/gui/qt/playlist/qml/PlaylistOverlayMenu.qml

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index af4758f88c..3f5d7cd419 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -681,7 +681,7 @@ libqt_plugin_la_QML = \
 	gui/qt/playlist/qml/PLItem.qml \
 	gui/qt/playlist/qml/PlaylistDroppable.qml \
 	gui/qt/playlist/qml/PlaylistListView.qml \
-	gui/qt/playlist/qml/PlaylistMenu.qml \
+	gui/qt/playlist/qml/PlaylistOverlayMenu.qml \
 	gui/qt/playlist/qml/PlaylistToolbar.qml \
 	gui/qt/playlist/qml/PlaylistDetachedWindow.qml \
 	gui/qt/style/VLCColors.qml \
diff --git a/modules/gui/qt/playlist/qml/PlaylistListView.qml b/modules/gui/qt/playlist/qml/PlaylistListView.qml
index 91474986ed..5e902d4876 100644
--- a/modules/gui/qt/playlist/qml/PlaylistListView.qml
+++ b/modules/gui/qt/playlist/qml/PlaylistListView.qml
@@ -76,11 +76,24 @@ Widgets.NavigableFocusScope {
         mainPlaylistController.sort()
     }
 
+    PlaylistOverlayMenu {
+        id: overlayMenu
+        anchors.fill: parent
+        z: 1
+
+        backgroundItem: parentRect
+    }
+
     Rectangle {
         id: parentRect
         anchors.fill: parent
         color: _colors.banner
 
+        onActiveFocusChanged: {
+            if (activeFocus)
+                view.forceActiveFocus()
+        }
+
         //label for DnD
         Widgets.DNDLabel {
             id: dragItem
@@ -151,154 +164,6 @@ Widgets.NavigableFocusScope {
             controler: mainPlaylistController
         }
 
-        PlaylistMenu {
-            id: overlayMenu
-            anchors.fill: parent
-            z: 2
-
-            navigationParent: root
-            navigationLeftItem: view
-
-            leftPadding: root.leftPadding
-            rightPadding: root.rightPadding
-
-            isPLEmpty: (root.plmodel.count === 0)
-            isItemNotSelected: (root.plmodel.selectedCount === 0)
-
-            //rootmenu
-            Action { id:playAction;         text: i18n.qtr("Play");                      onTriggered: mainPlaylistController.goTo(root.plmodel.getSelection()[0], true); icon.source: "qrc:///toolbar/play_b.svg"                   }
-            Action { id:streamAction;       text: i18n.qtr("Stream");                    onTriggered: dialogProvider.streamingDialog(root.plmodel.getSelection().map(function(i) { return root.plmodel.itemAt(i).url; }), false); icon.source: "qrc:/menu/stream.svg" }
-            Action { id:saveAction;         text: i18n.qtr("Save");                      onTriggered: dialogProvider.streamingDialog(root.plmodel.getSelection().map(function(i) { return root.plmodel.itemAt(i).url; }));          }
-            Action { id:infoAction;         text: i18n.qtr("Information");               onTriggered: dialogProvider.mediaInfoDialog(root.plmodel.itemAt(root.plmodel.getSelection()[0])); icon.source: "qrc:/menu/info.svg"        }
-            Action { id:exploreAction;      text: i18n.qtr("Show Containing Directory"); onTriggered: mainPlaylistController.explore(root.plmodel.itemAt(root.plmodel.getSelection()[0])); icon.source: "qrc:/type/folder-grey.svg" }
-            Action { id:addFileAction;      text: i18n.qtr("Add File...");               onTriggered: dialogProvider.simpleOpenDialog(false);                             icon.source: "qrc:/buttons/playlist/playlist_add.svg"     }
-            Action { id:addDirAction;       text: i18n.qtr("Add Directory...");          onTriggered: dialogProvider.PLAppendDir();                                       icon.source: "qrc:/buttons/playlist/playlist_add.svg"     }
-            Action { id:addAdvancedAction;  text: i18n.qtr("Advanced Open...");          onTriggered: dialogProvider.PLAppendDialog();                                    icon.source: "qrc:/buttons/playlist/playlist_add.svg"     }
-            Action { id:savePlAction;       text: i18n.qtr("Save Playlist to File...");  onTriggered: dialogProvider.savePlayingToPlaylist();                                                                                       }
-            Action { id:clearAllAction;     text: i18n.qtr("Clear Playlist");            onTriggered: mainPlaylistController.clear();                                     icon.source: "qrc:/toolbar/clear.svg"                     }
-            Action { id:selectAllAction;    text: i18n.qtr("Select All");                onTriggered: root.plmodel.selectAll();                                                                                                     }
-            Action { id:shuffleAction;      text: i18n.qtr("Shuffle Playlist");          onTriggered: mainPlaylistController.shuffle();                                   icon.source: "qrc:///buttons/playlist/shuffle_on.svg"     }
-            Action { id:sortAction;         text: i18n.qtr("Sort");                      property string subMenu: "sortmenu";                                                                                                       }
-            Action { id:selectTracksAction; text: i18n.qtr("Select Tracks");             onTriggered: view.mode = "select";                                                                                                         }
-            Action { id:moveTracksAction;   text: i18n.qtr("Move Selection");            onTriggered: view.mode = "move";                                                                                                           }
-            Action { id:deleteAction;       text: i18n.qtr("Remove Selected");           onTriggered: view.onDelete();                                                                                                              }
-
-            readonly property var sortList: [sortTitleAction,
-                                            sortDurationAction,
-                                            sortArtistAction,
-                                            sortAlbumAction,
-                                            sortGenreAction,
-                                            sortDateAction,
-                                            sortTrackAction,
-                                            sortURLAction,
-                                            sortRatingAction]
-
-            Connections {
-                id: plControllerConnections
-                target: mainPlaylistController
-
-                property alias sortList: overlayMenu.sortList
-
-                function setMark() {
-                    for (var i = 0; i < sortList.length; i++) {
-                        if(sortList[i].key === mainPlaylistController.sortKey) {
-                            sortList[i].sortActiveMark = "✓"
-                            sortList[i].sortOrderMark  = (mainPlaylistController.sortOrder === PlaylistControllerModel.SORT_ORDER_ASC ? "↓" : "↑")
-                            continue
-                        }
-
-                        sortList[i].sortActiveMark = ""
-                        sortList[i].sortOrderMark  = ""
-                    }
-                }
-
-                onSortOrderChanged: {
-                    plControllerConnections.setMark()
-                }
-
-                onSortKeyChanged: {
-                    plControllerConnections.setMark()
-                }
-            }
-
-            // sortmenu
-            Action { id: sortTitleAction;   text: i18n.qtr("Title"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_TITLE;
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortDurationAction; text: i18n.qtr("Duration"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_DURATION
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortArtistAction;  text: i18n.qtr("Artist"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_ARTIST
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortAlbumAction;   text: i18n.qtr("Album"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_ALBUM
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortGenreAction;   text: i18n.qtr("Genre"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_GENRE
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortDateAction;    text: i18n.qtr("Date"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_DATE
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortTrackAction;   text: i18n.qtr("Track Number"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_TRACK_NUMBER
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortURLAction;     text: i18n.qtr("URL"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_URL
-                property string sortActiveMark; property string sortOrderMark }
-            Action { id: sortRatingAction;  text: i18n.qtr("Rating"); onTriggered: root.sortPL(key);
-                readonly property int key: PlaylistControllerModel.SORT_KEY_RATING
-                property string sortActiveMark; property string sortOrderMark }
-
-            models: {
-                "rootmenu" : {
-                    title: i18n.qtr("Playlist"),
-                    entries: [
-                        playAction,
-                        streamAction,
-                        saveAction,
-                        infoAction,
-                        exploreAction,
-                        addFileAction,
-                        addDirAction,
-                        addAdvancedAction,
-                        savePlAction,
-                        clearAllAction,
-                        selectAllAction,
-                        shuffleAction,
-                        sortAction,
-                        selectTracksAction,
-                        moveTracksAction,
-                        deleteAction
-                    ]
-                },
-                "rootmenu_plempty" : {
-                    title: i18n.qtr("Playlist"),
-                    entries: [
-                        addFileAction,
-                        addDirAction,
-                        addAdvancedAction
-                    ]
-                },
-                "rootmenu_noselection" : {
-                    title: i18n.qtr("Playlist"),
-                    entries: [
-                        addFileAction,
-                        addDirAction,
-                        addAdvancedAction,
-                        savePlAction,
-                        clearAllAction,
-                        sortAction,
-                        selectTracksAction
-                    ]
-                },
-                "sortmenu" :{
-                    title: i18n.qtr("Sort Playlist"),
-                    entries: sortList
-                }
-            }
-        }
-
         ColumnLayout {
             anchors.fill: parent
             anchors.bottomMargin: VLCStyle.margin_normal
diff --git a/modules/gui/qt/playlist/qml/PlaylistMenu.qml b/modules/gui/qt/playlist/qml/PlaylistMenu.qml
deleted file mode 100644
index a19de35b65..0000000000
--- a/modules/gui/qt/playlist/qml/PlaylistMenu.qml
+++ /dev/null
@@ -1,275 +0,0 @@
-/*****************************************************************************
- * 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 QtQuick.Controls.impl 2.4
-import QtQuick.Layouts 1.3
-
-import "qrc:///widgets/" as Widgets
-import "qrc:///util/KeyHelper.js" as KeyHelper
-import "qrc:///style/"
-
-Widgets.NavigableFocusScope {
-    id: overlayMenu
-    visible: false
-
-    property alias models: playlistMenu.models
-    property alias currentModel: playlistMenu.currentModel
-
-    property int leftPadding: 0
-    property int rightPadding: 0
-
-    property bool isPLEmpty: false
-    property bool isItemNotSelected: false
-
-    onActiveFocusChanged: {
-        if (!activeFocus) {
-            overlayMenu.close()
-        }
-    }
-
-    function close() {
-        overlayMenu.visible = false
-        view.forceActiveFocus()
-    }
-
-    function open() {
-        playlistMenu.currentModel = isPLEmpty ? "rootmenu_plempty" : (isItemNotSelected ? "rootmenu_noselection" : "rootmenu")
-        playlistMenu.menuHierachy = []
-        overlayMenu.visible = true
-        overlayMenu.forceActiveFocus()
-    }
-
-    function pushMenu(menu) {
-        playlistMenu.menuHierachy.push(playlistMenu.currentModel)
-        playlistMenu.currentModel = menu
-    }
-
-    property real drawerRatio: 0
-    Behavior on drawerRatio {
-        NumberAnimation {
-            duration: 150
-        }
-    }
-    onVisibleChanged: {
-        drawerRatio = visible ? 0.9 : 0
-    }
-
-    Rectangle {
-        color: "black"
-        anchors {
-            left: parent.left
-            top: parent.top
-            bottom: parent.bottom
-        }
-        width: parent.width * (1 - drawerRatio)
-        opacity: 0.4
-    }
-
-    Item {
-        id: parentItem
-
-        anchors {
-            right: parent.right
-            top: parent.top
-            bottom: parent.bottom
-        }
-        width: parent.width * drawerRatio
-
-        Widgets.FrostedGlassEffect {
-            id: glassEffect
-            source: view
-
-            anchors.fill: parent
-
-            readonly property point overlayLocalPos: view.mapFromItem(overlayMenu, parentItem.x, parentItem.y)
-            sourceRect: Qt.rect(overlayLocalPos.x, overlayLocalPos.y, glassEffect.width, glassEffect.height)
-
-            tint: VLCStyle.colors.blendColors(VLCStyle.colors.black, VLCStyle.colors.banner, 0.85)
-            tintStrength: 0.6
-        }
-
-        //avoid mouse event to be propagated to the widget below
-        MouseArea {
-            anchors.fill: parent
-            hoverEnabled: true
-        }
-
-        Widgets.KeyNavigableListView {
-            id: playlistMenu
-            anchors.fill: parent
-            focus: true
-            keyNavigationWraps: true
-
-            property var models: {
-                "rootmenu" : {
-                    "title" : "",
-                    "entries" : []
-                }
-            }
-            property string currentModel: "rootmenu"
-            property var menuHierachy: []
-
-            model: models[currentModel]["entries"]
-            modelCount: models[currentModel]["entries"].length
-
-            header: Label {
-                text: models[currentModel]["title"]
-                color: "white"
-                font.pixelSize: VLCStyle.fontSize_xlarge
-                font.bold: true
-
-                leftPadding: VLCStyle.margin_small
-                rightPadding: VLCStyle.margin_small
-                topPadding: VLCStyle.margin_xsmall
-                bottomPadding: VLCStyle.margin_xsmall
-                height: VLCStyle.fontHeight_xlarge + topPadding + bottomPadding
-            }
-
-            delegate: Button {
-                id: control
-                text: modelData.text
-                width: playlistMenu.width
-
-                leftPadding: VLCStyle.margin_small + root.leftPadding
-                rightPadding: VLCStyle.margin_small + root.rightPadding
-
-                icon.width: VLCStyle.fontHeight_normal
-                icon.height: VLCStyle.fontHeight_normal
-
-                contentItem: RowLayout {
-                    width: control.width
-
-                    Label {
-                        Layout.fillWidth: true
-
-                        text: control.text
-                        color: "white"
-                        font.pixelSize: VLCStyle.fontSize_normal
-                        leftPadding: VLCStyle.icon_small
-                    }
-
-                    Loader {
-                        active: currentModel === "sortmenu"
-
-                        sourceComponent: Label {
-                            text: modelData.sortOrderMark
-                            color: "white"
-                            font.pixelSize: VLCStyle.fontSize_normal
-                        }
-                    }
-                }
-
-                background: Rectangle {
-                    implicitWidth: 100
-                    implicitHeight: VLCStyle.fontHeight_normal
-                    color: control.activeFocus ? VLCStyle.colors.accent : "transparent"
-                    opacity: 0.8
-
-                    Item {
-                        id: leftSide
-                        width: control.icon.width
-                        height: control.icon.height
-
-                        x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding
-                        y: control.topPadding + (control.availableHeight - height) / 2
-
-                        Loader {
-                            id: leftTextLoader
-                            active: currentModel === "sortmenu"
-
-                            anchors.fill: parent
-
-                            sourceComponent: Label {
-                                text: modelData.sortActiveMark
-                                color: "white"
-                                font.pixelSize: VLCStyle.fontSize_normal
-                            }
-                        }
-
-                        Loader {
-                            active: !leftTextLoader.active
-                            anchors.fill: parent
-
-                            sourceComponent: ColorImage {
-                                width: leftSide.width
-                                height: leftSide.height
-
-                                source: control.checked ? "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png"
-                                    : modelData.icon.source ? modelData.icon.source
-                                    : ""
-                                visible: true
-                                color: control.enabled ? VLCStyle.colors.playerFg : VLCStyle.colors.playerFgInactive
-                            }
-                        }
-                    }
-
-                    ColorImage {
-                        x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
-                        y: control.topPadding + (control.availableHeight - height) / 2
-
-                        width: VLCStyle.icon_xsmall
-                        height: VLCStyle.icon_xsmall
-
-                        visible: !!modelData["subMenu"]
-                        mirror: control.mirrored
-                        color: control.enabled ? VLCStyle.colors.playerFg : VLCStyle.colors.playerFgInactive
-                        source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/arrow-indicator.png"
-                    }
-                }
-
-                onClicked: {
-
-                    if (!!modelData["subMenu"]) {
-                        pushMenu(modelData["subMenu"])
-                    } else {
-                        modelData.trigger()
-                        overlayMenu.close()
-                    }
-                }
-
-                Keys.onPressed:  {
-                    if (KeyHelper.matchRight(event)) {
-                        if (!!modelData["subMenu"]) {
-                            pushMenu(modelData["subMenu"])
-                            event.accepted = true
-                        }
-                    } else if (KeyHelper.matchLeft(event)) {
-                        if (playlistMenu.menuHierachy.length > 0) {
-                            playlistMenu.currentModel = playlistMenu.menuHierachy.pop()
-                            event.accepted = true
-                        } else {
-                            overlayMenu.close()
-                        }
-                    }
-                }
-
-                Keys.onReleased: {
-                    if (KeyHelper.matchCancel(event)) {
-                        event.accepted = true
-                        if (playlistMenu.menuHierachy.length > 0) {
-                            playlistMenu.currentModel = playlistMenu.menuHierachy.pop()
-                        } else {
-                            overlayMenu.close()
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/modules/gui/qt/playlist/qml/PlaylistOverlayMenu.qml b/modules/gui/qt/playlist/qml/PlaylistOverlayMenu.qml
new file mode 100644
index 0000000000..01d3f89bff
--- /dev/null
+++ b/modules/gui/qt/playlist/qml/PlaylistOverlayMenu.qml
@@ -0,0 +1,306 @@
+/*****************************************************************************
+ * 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 2.11
+import QtQuick.Controls 2.4
+
+import org.videolan.vlc 0.1
+
+import "qrc:///widgets/" as Widgets
+import "qrc:///style/"
+
+Widgets.OverlayMenu {
+    id: overlayMenu
+
+    Action {
+        id: playAction
+        text: i18n.qtr("Play")
+        onTriggered: mainPlaylistController.goTo(root.plmodel.getSelection()[0], true)
+        property string fontIcon: VLCIcons.play
+    }
+
+    Action {
+        id: streamAction
+        text: i18n.qtr("Stream")
+        onTriggered: dialogProvider.streamingDialog(root.plmodel.getSelection().map(function(i) { return root.plmodel.itemAt(i).url; }), false)
+        property string fontIcon: VLCIcons.stream
+    }
+
+    Action {
+        id: saveAction
+        text: i18n.qtr("Save")
+        onTriggered: dialogProvider.streamingDialog(root.plmodel.getSelection().map(function(i) { return root.plmodel.itemAt(i).url; }))
+    }
+
+    Action {
+        id: infoAction
+        text: i18n.qtr("Information")
+        onTriggered: dialogProvider.mediaInfoDialog(root.plmodel.itemAt(root.plmodel.getSelection()[0]))
+        icon.source: "qrc:/menu/info.svg"
+    }
+
+    Action {
+        id: exploreAction
+        text: i18n.qtr("Show Containing Directory")
+        onTriggered: mainPlaylistController.explore(root.plmodel.itemAt(root.plmodel.getSelection()[0]))
+        icon.source: "qrc:/type/folder-grey.svg"
+    }
+
+    Action {
+        id: addFileAction
+        text: i18n.qtr("Add File...")
+        onTriggered: dialogProvider.simpleOpenDialog(false)
+        icon.source: "qrc:/buttons/playlist/playlist_add.svg"
+    }
+
+    Action {
+        id: addDirAction
+        text: i18n.qtr("Add Directory...")
+        onTriggered: dialogProvider.PLAppendDir()
+        icon.source: "qrc:/buttons/playlist/playlist_add.svg"
+    }
+
+    Action {
+        id: addAdvancedAction
+        text: i18n.qtr("Advanced Open...")
+        onTriggered: dialogProvider.PLAppendDialog()
+        icon.source: "qrc:/buttons/playlist/playlist_add.svg"
+    }
+
+    Action {
+        id: savePlAction
+        text: i18n.qtr("Save Playlist to File...")
+        onTriggered: dialogProvider.savePlayingToPlaylist();
+    }
+
+    Action {
+        id: clearAllAction
+        text: i18n.qtr("Clear Playlist")
+        onTriggered: mainPlaylistController.clear()
+        icon.source: "qrc:/toolbar/clear.svg"
+    }
+
+    Action {
+        id: selectAllAction
+        text: i18n.qtr("Select All")
+        onTriggered: root.plmodel.selectAll()
+    }
+
+    Action {
+        id: shuffleAction
+        text: i18n.qtr("Shuffle Playlist")
+        onTriggered: mainPlaylistController.shuffle()
+        icon.source: "qrc:/buttons/playlist/shuffle_on.svg"
+    }
+
+    Action {
+        id: sortAction
+        text: i18n.qtr("Sort")
+        property alias model: overlayMenu.sortMenu
+    }
+
+    Action {
+        id: selectTracksAction
+        text: i18n.qtr("Select Tracks")
+        onTriggered: view.mode = "select"
+    }
+
+    Action {
+        id: moveTracksAction
+        text: i18n.qtr("Move Selection")
+        onTriggered: view.mode = "move"
+    }
+
+    Action {
+        id: deleteAction
+        text: i18n.qtr("Remove Selected")
+        onTriggered: view.onDelete()
+    }
+
+    property var rootMenu: ({
+
+                                title: i18n.qtr("Playlist Menu"),
+                                entries: [
+                                    playAction,
+                                    streamAction,
+                                    saveAction,
+                                    infoAction,
+                                    exploreAction,
+                                    addFileAction,
+                                    addDirAction,
+                                    addAdvancedAction,
+                                    savePlAction,
+                                    clearAllAction,
+                                    selectAllAction,
+                                    shuffleAction,
+                                    sortAction,
+                                    selectTracksAction,
+                                    moveTracksAction,
+                                    deleteAction
+                                ]
+                            })
+
+    property var rootMenu_PLEmpty: ({
+                                        title: i18n.qtr("Playlist Menu"),
+                                        entries: [
+                                            addFileAction,
+                                            addDirAction,
+                                            addAdvancedAction
+                                        ]
+                                    })
+
+    property var rootMenu_noSelection: ({
+                                            title: i18n.qtr("Playlist Menu"),
+                                            entries: [
+                                                addFileAction,
+                                                addDirAction,
+                                                addAdvancedAction,
+                                                savePlAction,
+                                                clearAllAction,
+                                                sortAction,
+                                                selectTracksAction
+                                            ]
+                                        })
+
+    model: {
+        if (root.plmodel.count === 0)
+            rootMenu_PLEmpty
+        else if (root.plmodel.selectedCount === 0)
+            rootMenu_noSelection
+        else
+            rootMenu
+    }
+
+    // Sort menu:
+
+    function sortOrderMarkRetriever(key) {
+        if (key === mainPlaylistController.sortKey) {
+            return (mainPlaylistController.sortOrder === PlaylistControllerModel.SORT_ORDER_ASC ? "↓" : "↑")
+        }
+        else {
+            return null
+        }
+    }
+
+    Action {
+        id: sortTitleAction
+        text: i18n.qtr("Title")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_TITLE
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortDurationAction
+        text: i18n.qtr("Duration")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_DURATION
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortArtistAction
+        text: i18n.qtr("Artist")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_ARTIST
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortAlbumAction
+        text: i18n.qtr("Album")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_ALBUM
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortAlbumArtistAction
+        text: i18n.qtr("Album Artist")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_ALBUM_ARTIST
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortGenreAction
+        text: i18n.qtr("Genre")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_GENRE
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortDateAction
+        text: i18n.qtr("Date")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_DATE
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortTrackNumberAction
+        text: i18n.qtr("Track Number")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_TRACK_NUMBER
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortURLAction
+        text: i18n.qtr("URL")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_URL
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    Action {
+        id: sortRatingAction
+        text: i18n.qtr("Rating")
+        onTriggered: root.sortPL(key)
+        readonly property int key: PlaylistControllerModel.SORT_KEY_RATING
+        readonly property string marking: sortOrderMarkRetriever(key)
+        readonly property bool tickMark: (key === mainPlaylistController.sortKey)
+    }
+
+    property var sortMenu: ({
+                                title: i18n.qtr("Sort Menu"),
+                                entries: [
+                                    sortTitleAction,
+                                    sortDurationAction,
+                                    sortArtistAction,
+                                    sortAlbumAction,
+                                    sortAlbumArtistAction,
+                                    sortGenreAction,
+                                    sortDateAction,
+                                    sortTrackNumberAction,
+                                    sortURLAction,
+                                    sortRatingAction
+                                ]
+                            })
+
+
+}
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index d836a59a45..eee7cb049a 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -292,7 +292,7 @@
         <file alias="PLItem.qml">playlist/qml/PLItem.qml</file>
         <file alias="PlaylistDroppable.qml">playlist/qml/PlaylistDroppable.qml</file>
         <file alias="PlaylistListView.qml">playlist/qml/PlaylistListView.qml</file>
-        <file alias="PlaylistMenu.qml">playlist/qml/PlaylistMenu.qml</file>
+        <file alias="PlaylistOverlayMenu.qml">playlist/qml/PlaylistOverlayMenu.qml</file>
         <file alias="PlaylistToolbar.qml">playlist/qml/PlaylistToolbar.qml</file>
         <file alias="PlaylistDetachedWindow.qml">playlist/qml/PlaylistDetachedWindow.qml</file>
     </qresource>
-- 
2.27.0



More information about the vlc-devel mailing list