[vlc-devel] [PATCH 16/18] qml: use a native implementation for playlist contextual menu

Pierre Lamot pierre at videolabs.io
Wed Sep 23 14:27:50 CEST 2020


---
 modules/gui/qt/maininterface/mainui.cpp       |   1 +
 modules/gui/qt/menus/qml_menu_wrapper.cpp     | 111 +++++++++++++
 modules/gui/qt/menus/qml_menu_wrapper.hpp     |  17 ++
 modules/gui/qt/playlist/qml/PLItem.qml        |   8 +-
 .../gui/qt/playlist/qml/PlaylistListView.qml  | 155 +-----------------
 5 files changed, 142 insertions(+), 150 deletions(-)

diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp
index 9137e5682a..c30e5e4c82 100644
--- a/modules/gui/qt/maininterface/mainui.cpp
+++ b/modules/gui/qt/maininterface/mainui.cpp
@@ -207,6 +207,7 @@ void MainUI::registerQMLTypes()
 
     qmlRegisterType<QmlGlobalMenu>( "org.videolan.vlc", 0, 1, "QmlGlobalMenu" );
     qmlRegisterType<NetworkMediaContextMenu>( "org.videolan.vlc", 0, 1, "NetworkMediaContextMenu" );
+    qmlRegisterType<PlaylistContextMenu>( "org.videolan.vlc", 0, 1, "PlaylistContextMenu" );
 }
 
 void MainUI::onQmlWarning(const QList<QQmlError>& qmlErrors)
diff --git a/modules/gui/qt/menus/qml_menu_wrapper.cpp b/modules/gui/qt/menus/qml_menu_wrapper.cpp
index 6f964e62e0..e48548b6b9 100644
--- a/modules/gui/qt/menus/qml_menu_wrapper.cpp
+++ b/modules/gui/qt/menus/qml_menu_wrapper.cpp
@@ -25,6 +25,9 @@
 #include "medialibrary/mlgenremodel.hpp"
 #include "medialibrary/mlalbumtrackmodel.hpp"
 #include "network/networkmediamodel.hpp"
+#include "playlist/playlist_controller.hpp"
+#include "playlist/playlist_model.hpp"
+#include "dialogs/dialogs_provider.hpp"
 
 
 #include <QSignalMapper>
@@ -264,3 +267,111 @@ void NetworkMediaContextMenu::popup(const QModelIndexList& selected, QPoint pos)
     menu->popup(pos);
 }
 
+PlaylistContextMenu::PlaylistContextMenu(QObject* parent)
+    : QObject(parent)
+{}
+
+void PlaylistContextMenu::popup(int currentIndex, QPoint pos )
+{
+    if (!m_controler || !m_model)
+        return;
+
+    QMenu* menu = new QMenu();
+    QAction* action;
+
+    QList<QUrl> selectedUrlList;
+    for (const int modelIndex : m_model->getSelection())
+        selectedUrlList.push_back(m_model->itemAt(modelIndex).getUrl());
+
+    PlaylistItem currentItem;
+    if (currentIndex >= 0)
+        currentItem = m_model->itemAt(currentIndex);
+
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+
+    if (currentItem)
+    {
+        action = menu->addAction( qtr("Play") );
+        connect(action, &QAction::triggered, [this, currentIndex]( ) {
+            m_controler->goTo(currentIndex, true);
+        });
+
+        menu->addSeparator();
+    }
+
+    if (m_model->getSelectedCount() > 0) {
+        action = menu->addAction( qtr("Stream") );
+        connect(action, &QAction::triggered, [selectedUrlList]( ) {
+            DialogsProvider::getInstance()->streamingDialog(selectedUrlList, false);
+        });
+
+        action = menu->addAction( qtr("Save") );
+        connect(action, &QAction::triggered, [selectedUrlList]( ) {
+            DialogsProvider::getInstance()->streamingDialog(selectedUrlList, true);
+        });
+
+        menu->addSeparator();
+    }
+
+    if (currentItem) {
+        action = menu->addAction( qtr("Information") );
+        action->setIcon(QIcon(":/menu/info.svg"));
+        connect(action, &QAction::triggered, [currentItem]( ) {
+            DialogsProvider::getInstance()->mediaInfoDialog(currentItem);
+        });
+
+        menu->addSeparator();
+
+        action = menu->addAction( qtr("Show Containing Directory...") );
+        action->setIcon(QIcon(":/type/folder-grey.svg"));
+        connect(action, &QAction::triggered, [currentItem]( ) {
+            DialogsProvider::getInstance()->mediaInfoDialog(currentItem);
+        });
+
+        menu->addSeparator();
+    }
+
+    action = menu->addAction( qtr("Add File...") );
+    action->setIcon(QIcon(":/buttons/playlist/playlist_add.svg"));
+    connect(action, &QAction::triggered, []( ) {
+        DialogsProvider::getInstance()->simpleOpenDialog(false);
+    });
+
+    action = menu->addAction( qtr("Add Directory...") );
+    action->setIcon(QIcon(":/buttons/playlist/playlist_add.svg"));
+    connect(action, &QAction::triggered, []( ) {
+        DialogsProvider::getInstance()->PLAppendDir();
+    });
+
+    action = menu->addAction( qtr("Advanced Open...") );
+    action->setIcon(QIcon(":/buttons/playlist/playlist_add.svg"));
+    connect(action, &QAction::triggered, []( ) {
+        DialogsProvider::getInstance()->PLAppendDialog();
+    });
+
+    menu->addSeparator();
+
+    if (m_model->getSelectedCount() > 0)
+    {
+        action = menu->addAction( qtr("Save Playlist to File...") );
+        connect(action, &QAction::triggered, []( ) {
+            DialogsProvider::getInstance()->savePlayingToPlaylist();
+        });
+
+        menu->addSeparator();
+
+        action = menu->addAction( qtr("Remove Selected") );
+        action->setIcon(QIcon(":/buttons/playlist/playlist_remove.svg"));
+        connect(action, &QAction::triggered, [this]( ) {
+            m_model->removeItems(m_model->getSelection());
+        });
+    }
+
+    action = menu->addAction( qtr("Clear the playlist") );
+    action->setIcon(QIcon(":/toolbar/clear.svg"));
+    connect(action, &QAction::triggered, [this]( ) {
+        m_controler->clear();
+    });
+
+    menu->popup(pos);
+}
diff --git a/modules/gui/qt/menus/qml_menu_wrapper.hpp b/modules/gui/qt/menus/qml_menu_wrapper.hpp
index 4a5a87668d..9af03a4a6b 100644
--- a/modules/gui/qt/menus/qml_menu_wrapper.hpp
+++ b/modules/gui/qt/menus/qml_menu_wrapper.hpp
@@ -33,6 +33,12 @@ class MLAlbumTrackModel;
 class MLVideoModel;
 class NetworkMediaModel;
 class QmlMainContext;
+namespace vlc {
+namespace playlist {
+class PlaylistControllerModel;
+class PlaylistListModel;
+}
+}
 
 #define SIMPLE_MENU_PROPERTY(type, name, defaultValue) \
     Q_PROPERTY(type name READ get##name WRITE set##name) \
@@ -141,6 +147,17 @@ public slots:
     void popup(const QModelIndexList& selected, QPoint pos );
 };
 
+
+class PlaylistContextMenu : public QObject {
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(vlc::playlist::PlaylistListModel*, model, nullptr)
+    SIMPLE_MENU_PROPERTY(vlc::playlist::PlaylistControllerModel*, controler, nullptr)
+public:
+    PlaylistContextMenu(QObject* parent = nullptr);
+public slots:
+    void popup(int currentIndex, QPoint pos );
+};
+
 #undef SIMPLE_MENU_PROPERTY
 
 #endif // QMLMENUWRAPPER_HPP
diff --git a/modules/gui/qt/playlist/qml/PLItem.qml b/modules/gui/qt/playlist/qml/PLItem.qml
index 4c08acf164..e056774679 100644
--- a/modules/gui/qt/playlist/qml/PLItem.qml
+++ b/modules/gui/qt/playlist/qml/PLItem.qml
@@ -32,8 +32,8 @@ Rectangle {
 
     property var plmodel
 
-    signal itemClicked(int button, int modifier)
-    signal itemDoubleClicked(int keys, int modifier)
+    signal itemClicked(int button, int modifier, var globalMousePos)
+    signal itemDoubleClicked(int keys, int modifier, var globalMousePos)
     signal dragStarting()
 
     property alias hovered: mouse.containsMouse
@@ -113,11 +113,11 @@ Rectangle {
         acceptedButtons: acceptedButtons | Qt.RightButton
 
         onClicked:{
-            plitem.itemClicked(mouse.button, mouse.modifiers);
+            plitem.itemClicked(mouse.button, mouse.modifiers, this.mapToGlobal(mouse.x, mouse.y));
         }
         onDoubleClicked: {
             if (mouse.button !== Qt.RightButton)
-                plitem.itemDoubleClicked(mouse.buttons, mouse.modifiers);
+                plitem.itemDoubleClicked(mouse.buttons, mouse.modifiers, this.mapToGlobal(mouse.x, mouse.y));
         }
 
         drag.target: dragItem
diff --git a/modules/gui/qt/playlist/qml/PlaylistListView.qml b/modules/gui/qt/playlist/qml/PlaylistListView.qml
index ac7af1a892..c49b30bc8a 100644
--- a/modules/gui/qt/playlist/qml/PlaylistListView.qml
+++ b/modules/gui/qt/playlist/qml/PlaylistListView.qml
@@ -37,7 +37,6 @@ Widgets.NavigableFocusScope {
     property int leftPadding: 0
     property int rightPadding: 0
     property alias backgroundColor: parentRect.color
-    property alias mediaLibAvailable: contextMenu.medialibAvailable
 
     property bool forceDark: false
     property VLCColors _colors: forceDark ? vlcNightColors : VLCStyle.colors
@@ -58,6 +57,12 @@ Widgets.NavigableFocusScope {
             color: parent.color
         }
 
+        PlaylistContextMenu {
+            id: contextMenu
+            model: root.plmodel
+            controler: mainPlaylistController
+        }
+
         PlaylistMenu {
             id: overlayMenu
             anchors.fill: parent
@@ -130,138 +135,6 @@ Widgets.NavigableFocusScope {
             }
         }
 
-        Widgets.MenuExt {
-            id: contextMenu
-            property alias model: root.plmodel
-            property int itemIndex: -1
-            property bool medialibAvailable: false
-            closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Play")
-                icon.source: "qrc:/toolbar/play_b.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    mainPlaylistController.goTo(contextMenu.itemIndex, true)
-                }
-            }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Stream")
-                icon.source: "qrc:/menu/stream.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    var selection = contextMenu.model.getSelection()
-                    if (selection.length === 0)
-                        return
-
-                    dialogProvider.streamingDialog(selection.map(function(i) { return contextMenu.model.itemAt(i).url; }), false)
-                }
-            }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Save")
-                onTriggered: {
-                    var selection = contextMenu.model.getSelection()
-                    if (selection.length === 0)
-                        return
-
-                    dialogProvider.streamingDialog(selection.map(function(i) { return contextMenu.model.itemAt(i).url; }))
-                }
-            }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Information...")
-                icon.source: "qrc:/menu/info.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    dialogProvider.mediaInfoDialog(contextMenu.model.itemAt(contextMenu.itemIndex))
-                }
-            }
-
-            MenuSeparator { }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Show Containing Directory...")
-                icon.source: "qrc:/type/folder-grey.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    mainPlaylistController.explore(contextMenu.model.itemAt(contextMenu.itemIndex))
-                }
-            }
-
-            MenuSeparator { }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Add File...")
-                icon.source: "qrc:/buttons/playlist/playlist_add.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    dialogProvider.simpleOpenDialog(false)
-                }
-            }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Add Directory...")
-                icon.source: "qrc:/buttons/playlist/playlist_add.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    dialogProvider.PLAppendDir()
-                }
-            }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Advanced Open...")
-                icon.source: "qrc:/buttons/playlist/playlist_add.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    dialogProvider.PLAppendDialog()
-                }
-            }
-
-            MenuSeparator { }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Save Playlist to File...")
-                onTriggered: {
-                    dialogProvider.savePlayingToPlaylist();
-                }
-            }
-
-            MenuSeparator { }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Remove Selected")
-                icon.source: "qrc:/buttons/playlist/playlist_remove.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    contextMenu.model.removeItems(contextMenu.model.getSelection())
-                }
-            }
-
-            Widgets.MenuItemExt {
-                text: i18n.qtr("Clear the playlist")
-                icon.source: "qrc:/toolbar/clear.svg"
-                icon.width: VLCStyle.icon_small
-                icon.height: VLCStyle.icon_small
-                onTriggered: {
-                    mainPlaylistController.clear()
-                }
-            }
-
-            MenuSeparator { }
-
-            onClosed: contextMenu.parent.forceActiveFocus()
-        }
-
         ColumnLayout {
             anchors.fill: parent
             anchors.bottomMargin: VLCStyle.margin_normal
@@ -383,18 +256,11 @@ Widgets.NavigableFocusScope {
                         acceptedButtons: Qt.RightButton | Qt.LeftButton
 
                         onClicked: {
+                            view.forceActiveFocus()
                             if( mouse.button === Qt.RightButton )
-                            {
-                                view.forceActiveFocus()
-                                root.plmodel.deselectAll()
-                                contextMenu.itemIndex = -1
-                                contextMenu.popup()
-                            }
+                                contextMenu.popup(-1, this.mapToGlobal(mouse.x, mouse.y))
                             else if ( mouse.button === Qt.LeftButton )
-                            {
-                                view.forceActiveFocus()
                                 root.plmodel.deselectAll()
-                            }
                         }
                     }
 
@@ -479,10 +345,7 @@ Widgets.NavigableFocusScope {
                             }
 
                             if (button === Qt.RightButton)
-                            {
-                                contextMenu.itemIndex = index
-                                contextMenu.popup()
-                            }
+                                contextMenu.popup(index, globalMousePos)
                         }
                         onItemDoubleClicked: mainPlaylistController.goTo(index, true)
                         color: _colors.getBgColor(model.selected, plitem.hovered, plitem.activeFocus)
-- 
2.25.1



More information about the vlc-devel mailing list