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

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


---
 modules/gui/qt/maininterface/mainui.cpp       |   7 +
 .../gui/qt/medialibrary/qml/MusicAlbums.qml   |  41 +++---
 .../gui/qt/medialibrary/qml/MusicArtist.qml   |  41 +++---
 .../medialibrary/qml/MusicArtistsDisplay.qml  |  31 +----
 .../gui/qt/medialibrary/qml/MusicGenres.qml   |  36 ++---
 .../qml/MusicTrackListDisplay.qml             |   9 ++
 .../medialibrary/qml/MusicTracksDisplay.qml   |  28 ----
 .../gui/qt/medialibrary/qml/VideoDisplay.qml  |  86 +++---------
 .../qt/medialibrary/qml/VideoListDisplay.qml  |   7 -
 modules/gui/qt/menus/qml_menu_wrapper.cpp     | 131 ++++++++++++++++++
 modules/gui/qt/menus/qml_menu_wrapper.hpp     |  83 +++++++++++
 11 files changed, 300 insertions(+), 200 deletions(-)

diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp
index 51b5de9fde..fd2b19b4b4 100644
--- a/modules/gui/qt/maininterface/mainui.cpp
+++ b/modules/gui/qt/maininterface/mainui.cpp
@@ -173,6 +173,13 @@ void MainUI::registerQMLTypes()
         registerAnonymousType<MLAlbumTrack>("org.videolan.medialib", 1);
         registerAnonymousType<MLGenre>("org.videolan.medialib", 1);
         registerAnonymousType<MLVideo>("org.videolan.medialib", 1);
+
+        qmlRegisterType<AlbumContextMenu>( "org.videolan.medialib", 0, 1, "AlbumContextMenu" );
+        qmlRegisterType<ArtistContextMenu>( "org.videolan.medialib", 0, 1, "ArtistContextMenu" );
+        qmlRegisterType<GenreContextMenu>( "org.videolan.medialib", 0, 1, "GenreContextMenu" );
+        qmlRegisterType<AlbumTrackContextMenu>( "org.videolan.medialib", 0, 1, "AlbumTrackContextMenu" );
+        qmlRegisterType<VideoContextMenu>( "org.videolan.medialib", 0, 1, "VideoContextMenu" );
+        qmlRegisterType<VideoContextMenu>( "org.videolan.medialib", 0, 1, "VideoContextMenu" );
     }
 
     qmlRegisterUncreatableType<NavigationHistory>("org.videolan.vlc", 0, 1, "History", "Type of global variable history" );
diff --git a/modules/gui/qt/medialibrary/qml/MusicAlbums.qml b/modules/gui/qt/medialibrary/qml/MusicAlbums.qml
index aed8e25a1b..a918b0deea 100644
--- a/modules/gui/qt/medialibrary/qml/MusicAlbums.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicAlbums.qml
@@ -96,6 +96,11 @@ Widgets.NavigableFocusScope {
         model: albumModelId
     }
 
+    AlbumContextMenu {
+        id: contextMenu
+        model: albumModelId
+    }
+
     Component {
         id: gridComponent
 
@@ -127,6 +132,12 @@ Widgets.NavigableFocusScope {
                     if ( model.id !== undefined ) { medialib.addAndPlay( model.id ) }
                 }
 
+                onContextMenuButtonClicked: {
+                    contextMenu.popup(selectionModel.selectedIndexes, globalMousePos, {
+                        "information": index
+                    })
+                }
+
                 Behavior on opacity {
                     NumberAnimation {
                         duration: 100
@@ -155,30 +166,12 @@ Widgets.NavigableFocusScope {
             onSelectionUpdated: selectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
 
             navigationParent: root
-        }
-    }
 
-    Widgets.MenuExt {
-        id: contextMenu
-        property var model: ({})
-        closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
-
-        Widgets.MenuItemExt {
-            id: playMenuItem
-            text: "Play from start"
-            onTriggered: {
-                medialib.addAndPlay( contextMenu.model.id )
-                history.push(["player"])
+            Connections {
+                target: contextMenu
+                onShowMediaInformation: gridView_id.switchExpandItem( index )
             }
         }
-
-        Widgets.MenuItemExt {
-            text: "Enqueue"
-            onTriggered: medialib.addToPlaylist( contextMenu.model.id )
-        }
-
-        onClosed: contextMenu.parent.forceActiveFocus()
-
     }
 
     Component {
@@ -210,10 +203,8 @@ Widgets.NavigableFocusScope {
                     tableView_id.currentIndex = 0;
             }
 
-            onContextMenuButtonClicked: {
-                contextMenu.model = menuModel
-                contextMenu.popup(menuParent)
-            }
+            onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes,  menuParent.mapToGlobal(0,0))
+            onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
 
             Widgets.TableColumns {
                 id: tableColumns
diff --git a/modules/gui/qt/medialibrary/qml/MusicArtist.qml b/modules/gui/qt/medialibrary/qml/MusicArtist.qml
index c5a8125a63..4be675f22a 100644
--- a/modules/gui/qt/medialibrary/qml/MusicArtist.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicArtist.qml
@@ -224,6 +224,16 @@ Widgets.NavigableFocusScope {
         }
     }
 
+    AlbumContextMenu {
+        id: contextMenu
+        model: albumModel
+    }
+
+    AlbumTrackContextMenu {
+        id: trackContextMenu
+        model: trackModel
+    }
+
     Component {
         id: gridComponent
 
@@ -253,6 +263,8 @@ Widgets.NavigableFocusScope {
                     if ( model.id !== undefined ) { medialib.addAndPlay( model.id ) }
                 }
 
+                onContextMenuButtonClicked: contextMenu.popup(albumSelectionModel.selectedIndexes, globalMousePos, { "information" : index})
+
                 Behavior on opacity {
                     NumberAnimation {
                         duration: 100
@@ -281,30 +293,13 @@ Widgets.NavigableFocusScope {
             onSelectAll: albumSelectionModel.selectAll()
             onSelectionUpdated: albumSelectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
             navigationParent: root
-        }
-    }
-
-    Widgets.MenuExt {
-        id: contextMenu
-
-        property var model: ({})
-        closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
 
-        Widgets.MenuItemExt {
-            id: playMenuItem
-            text: i18n.qtr("Play from start")
-            onTriggered: {
-                medialib.addAndPlay( contextMenu.model.id )
-                history.push(["player"])
+            Connections {
+                target: contextMenu
+                onShowMediaInformation: gridView_id.switchExpandItem( index )
             }
         }
 
-        Widgets.MenuItemExt {
-            text: i18n.qtr("Enqueue")
-            onTriggered: medialib.addToPlaylist( contextMenu.model.id )
-        }
-
-        onClosed: contextMenu.parent.forceActiveFocus()
     }
 
     Component {
@@ -338,10 +333,8 @@ Widgets.NavigableFocusScope {
                     tableView_id.currentIndex = 0;
             }
 
-            onContextMenuButtonClicked: {
-                contextMenu.model = menuModel
-                contextMenu.popup(menuParent)
-            }
+            onContextMenuButtonClicked: trackContextMenu.popup(trackSelectionModel.selectedIndexes, menuParent.mapToGlobal(0,0))
+            onRightClick: trackContextMenu.popup(trackSelectionModel.selectedIndexes, globalMousePos)
 
             Widgets.TableColumns {
                 id: tableColumns
diff --git a/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml b/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
index afe183c1b8..e4f91490a2 100644
--- a/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
@@ -124,27 +124,9 @@ Widgets.NavigableFocusScope {
                 model: artistModel
             }
 
-            Widgets.MenuExt {
+            ArtistContextMenu {
                 id: contextMenu
-                property var model: ({})
-                closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
-
-                Widgets.MenuItemExt {
-                    id: playMenuItem
-                    text: i18n.qtr("Play")
-                    onTriggered: {
-                        medialib.addAndPlay( contextMenu.model.id )
-                        history.push(["player"])
-                    }
-                }
-
-                Widgets.MenuItemExt {
-                    text: "Enqueue"
-                    onTriggered: medialib.addToPlaylist( contextMenu.model.id )
-                }
-
-                onClosed: contextMenu.parent.forceActiveFocus()
-
+                model: artistModel
             }
 
             Component {
@@ -195,6 +177,8 @@ Widgets.NavigableFocusScope {
                         }
 
                         onItemDoubleClicked: artistAllView.showAlbumView(model)
+
+                        onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
                     }
                 }
             }
@@ -233,11 +217,8 @@ Widgets.NavigableFocusScope {
                     onItemDoubleClicked: {
                         artistAllView.showAlbumView(model)
                     }
-
-                    onContextMenuButtonClicked: {
-                        contextMenu.model = menuModel
-                        contextMenu.popup(menuParent)
-                    }
+                    onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, menuParent.mapToGlobal(0,0))
+                    onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
 
                     Widgets.TableColumns {
                         id: tableColumns
diff --git a/modules/gui/qt/medialibrary/qml/MusicGenres.qml b/modules/gui/qt/medialibrary/qml/MusicGenres.qml
index e8d67d7630..94c6594ff2 100644
--- a/modules/gui/qt/medialibrary/qml/MusicGenres.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicGenres.qml
@@ -87,27 +87,6 @@ Widgets.NavigableFocusScope {
         }
     }
 
-    Widgets.MenuExt {
-        id: contextMenu
-        property var model: ({})
-        closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
-        onClosed: contextMenu.parent.forceActiveFocus()
-
-        Widgets.MenuItemExt {
-            id: playMenuItem
-            text: "Play from start"
-            onTriggered: {
-                medialib.addAndPlay( contextMenu.model.id )
-                history.push(["player"])
-            }
-        }
-
-        Widgets.MenuItemExt {
-            text: "Enqueue"
-            onTriggered: medialib.addToPlaylist( contextMenu.model.id )
-        }
-    }
-
     function _actionAtIndex(index) {
         if (selectionModel.selectedIndexes.length > 1) {
             medialib.addAndPlay(model.getIdsForIndexes(selectionModel.selectedIndexes))
@@ -138,6 +117,11 @@ Widgets.NavigableFocusScope {
         }
     }
 
+    GenreContextMenu {
+        id: contextMenu
+        model: genreModel
+    }
+
     /* Grid View */
     Component {
         id: gridComponent
@@ -172,6 +156,10 @@ Widgets.NavigableFocusScope {
                         medialib.addAndPlay(model.id)
                 }
 
+                onContextMenuButtonClicked: {
+                    contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
+                }
+
                 Column {
                     anchors.centerIn: parent
                     opacity: item._highlighted ? .3 : 1
@@ -262,10 +250,8 @@ Widgets.NavigableFocusScope {
                 root.showAlbumView(model)
             }
 
-            onContextMenuButtonClicked: {
-                contextMenu.model = menuModel
-                contextMenu.popup(menuParent)
-            }
+            onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, menuParent.mapToGlobal(0,0))
+            onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
         }
     }
 
diff --git a/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml b/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml
index 593b7c86ec..12202fbe11 100644
--- a/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml
@@ -66,6 +66,10 @@ Widgets.KeyNavigableTableView {
 
     onActionForSelection:  medialib.addAndPlay(model.getIdsForIndexes( selection ))
 
+    onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, menuParent.mapToGlobal(0,0))
+    onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
+
+
     Widgets.TableColumns {
         id: tableColumns
     }
@@ -91,4 +95,9 @@ Widgets.KeyNavigableTableView {
 
         model: rootmodel
     }
+
+    AlbumTrackContextMenu {
+        id: contextMenu
+        model: rootmodel
+    }
 }
diff --git a/modules/gui/qt/medialibrary/qml/MusicTracksDisplay.qml b/modules/gui/qt/medialibrary/qml/MusicTracksDisplay.qml
index 9bf6a575d4..6a96b364ab 100644
--- a/modules/gui/qt/medialibrary/qml/MusicTracksDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicTracksDisplay.qml
@@ -27,29 +27,6 @@ Widgets.NavigableFocusScope {
     property alias sortModel: tracklistdisplay_id.sortModel
     property alias model: tracklistdisplay_id.model
 
-    Widgets.MenuExt {
-        id: contextMenu
-        property var model: ({})
-        closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
-
-        Widgets.MenuItemExt {
-            id: playMenuItem
-            text: "Play from start"
-            onTriggered: {
-                medialib.addAndPlay( contextMenu.model.id )
-                history.push(["player"])
-            }
-        }
-
-        Widgets.MenuItemExt {
-            text: "Enqueue"
-            onTriggered: medialib.addToPlaylist( contextMenu.model.id )
-        }
-
-        onClosed: contextMenu.parent.forceActiveFocus()
-
-    }
-
     MusicTrackListDisplay {
         id: tracklistdisplay_id
         anchors.fill: parent
@@ -62,11 +39,6 @@ Widgets.NavigableFocusScope {
             else
                 tracklistdisplay_id.currentIndex = 0;
         }
-
-        onContextMenuButtonClicked: {
-            contextMenu.model = menuModel
-            contextMenu.popup(menuParent)
-        }
     }
 
     EmptyLabel {
diff --git a/modules/gui/qt/medialibrary/qml/VideoDisplay.qml b/modules/gui/qt/medialibrary/qml/VideoDisplay.qml
index d277a61f74..cc2ef46566 100644
--- a/modules/gui/qt/medialibrary/qml/VideoDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/VideoDisplay.qml
@@ -67,58 +67,6 @@ Widgets.NavigableFocusScope {
         history.push(["player"])
     }
 
-    Widgets.MenuExt {
-        id: contextMenu
-        property var model: ({})
-        property int itemIndex: -1
-        closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
-
-        Widgets.MenuItemExt {
-            id: playMenuItem
-            text: "Play from start"
-            onTriggered: {
-                medialib.addAndPlay( contextMenu.model.id )
-                history.push(["player"])
-            }
-        }
-        Widgets.MenuItemExt {
-            text: "Play all"
-            onTriggered: console.log("not implemented")
-        }
-        Widgets.MenuItemExt {
-            text: "Play as audio"
-            onTriggered: console.log("not implemented")
-        }
-        Widgets.MenuItemExt {
-            text: "Enqueue"
-            onTriggered: medialib.addToPlaylist( contextMenu.model.id )
-        }
-        Widgets.MenuItemExt {
-            enabled: mainInterface.gridView
-            text: "Information"
-            onTriggered: {
-                view.currentItem.switchExpandItem(contextMenu.itemIndex)
-            }
-        }
-        Widgets.MenuItemExt {
-            text: "Download subtitles"
-            onTriggered: console.log("not implemented")
-        }
-        Widgets.MenuItemExt {
-            text: "Add to playlist"
-            onTriggered: console.log("not implemented")
-        }
-        Widgets.MenuItemExt {
-            text: "Delete"
-            onTriggered: g_dialogs.ask(i18n.qtr("Are you sure you want to delete?"), function() {
-                console.log("unimplemented")
-            })
-        }
-
-        onClosed: contextMenu.parent.forceActiveFocus()
-
-    }
-
     MLVideoModel {
         id: videoModel
         ml: medialib
@@ -135,6 +83,12 @@ Widgets.NavigableFocusScope {
         model: videoModel
     }
 
+    VideoContextMenu {
+        id: contextMenu
+        model: videoModel
+    }
+
+
     Component {
         id: gridComponent
 
@@ -159,11 +113,9 @@ Widgets.NavigableFocusScope {
 
                 opacity: videosGV.expandIndex !== -1 && videosGV.expandIndex !== videoGridItem.index ? .7 : 1
 
-                onContextMenuButtonClicked: {
-                    contextMenu.model = videoGridItem.model
-                    contextMenu.itemIndex = index
-                    contextMenu.popup()
-                }
+                onContextMenuButtonClicked:  contextMenu.popup(selectionModel.selectedIndexes, globalMousePos, {
+                    "information" : index
+                } )
 
                 onItemClicked : {
                     selectionModel.updateSelection( modifier , videosGV.currentIndex, index)
@@ -206,6 +158,11 @@ Widgets.NavigableFocusScope {
             onSelectAll:selectionModel.selectAll()
             onSelectionUpdated: selectionModel.updateSelection( keyModifiers, oldIndex, newIndex )
             onActionAtIndex: _actionAtIndex( index )
+
+            Connections {
+                target: contextMenu
+                onShowMediaInformation: videosGV.switchExpandItem(index)
+            }
         }
 
     }
@@ -217,17 +174,14 @@ Widgets.NavigableFocusScope {
             height: view.height
             width: view.width
             model: videoModel
-            onContextMenuButtonClicked:{
-                contextMenu.model = menuModel
-                contextMenu.popup(menuParent)
-            }
+            navigationParent: root
 
-            onRightClick:{
-                contextMenu.model = menuModel
-                contextMenu.popup()
-            }
+            selectionDelegateModel: selectionModel
+
+            onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, menuParent.mapToGlobal(0,0) )
+
+            onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos )
 
-            navigationParent: root
         }
     }
 
diff --git a/modules/gui/qt/medialibrary/qml/VideoListDisplay.qml b/modules/gui/qt/medialibrary/qml/VideoListDisplay.qml
index 63bc4fca34..6167fc0a39 100644
--- a/modules/gui/qt/medialibrary/qml/VideoListDisplay.qml
+++ b/modules/gui/qt/medialibrary/qml/VideoListDisplay.qml
@@ -28,13 +28,6 @@ import "qrc:///style/"
 Widgets.KeyNavigableTableView {
     id: listView_id
 
-    model: MLVideoModel {
-        ml: medialib
-    }
-    selectionDelegateModel: Util.SelectableDelegateModel {
-        model: listView_id.model
-    }
-
     property Component thumbnailHeader: Item {
         Widgets.IconLabel {
             height: VLCStyle.listAlbumCover_height
diff --git a/modules/gui/qt/menus/qml_menu_wrapper.cpp b/modules/gui/qt/menus/qml_menu_wrapper.cpp
index a0bac49b6e..006ff0bb3d 100644
--- a/modules/gui/qt/menus/qml_menu_wrapper.cpp
+++ b/modules/gui/qt/menus/qml_menu_wrapper.cpp
@@ -18,6 +18,12 @@
 #include "qml_menu_wrapper.hpp"
 #include "menus.hpp"
 #include "util/qml_main_context.hpp"
+#include "medialibrary/medialib.hpp"
+#include "medialibrary/mlvideomodel.hpp"
+#include "medialibrary/mlalbummodel.hpp"
+#include "medialibrary/mlartistmodel.hpp"
+#include "medialibrary/mlgenremodel.hpp"
+#include "medialibrary/mlalbumtrackmodel.hpp"
 
 
 #include <QSignalMapper>
@@ -75,3 +81,128 @@ void QmlGlobalMenu::popup(QPoint pos)
     menu->popup(pos);
 }
 
+BaseMedialibMenu::BaseMedialibMenu(QObject* parent)
+    : QObject(parent)
+{}
+
+void BaseMedialibMenu::medialibAudioContextMenu(MediaLib* ml, const QVariantList& mlId, const QPoint& pos, const QVariantMap& options)
+{
+    QMenu* menu = new QMenu();
+    QAction* action;
+
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+
+    action = menu->addAction( qtr("Add and play") );
+    connect(action, &QAction::triggered, [ml, mlId]( ) {
+        ml->addAndPlay(mlId);
+    });
+
+    action = menu->addAction( qtr("Enqueue") );
+    connect(action, &QAction::triggered, [ml, mlId]( ) {
+        ml->addToPlaylist(mlId);
+    });
+
+    if (options.contains("information") && options["information"].type() == QVariant::Int) {
+
+        action = menu->addAction( qtr("Information") );
+        QSignalMapper* sigmapper = new QSignalMapper(menu);
+        connect(action, &QAction::triggered, sigmapper, QOverload<>::of(&QSignalMapper::map));
+        sigmapper->setMapping(action, options["information"].toInt());
+#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
+        connect(sigmapper, &QSignalMapper::mappedInt, this, &BaseMedialibMenu   ::showMediaInformation);
+#else
+        connect(sigmapper, QOverload<int>::of(&QSignalMapper::mapped), this, &BaseMedialibMenu::showMediaInformation);
+#endif
+    }
+    menu->popup(pos);
+}
+
+AlbumContextMenu::AlbumContextMenu(QObject* parent)
+    : BaseMedialibMenu(parent)
+{}
+
+void AlbumContextMenu::popup(const QModelIndexList& selected, QPoint pos, QVariantMap options)
+{
+    BaseMedialibMenu::popup(m_model, MLAlbumModel::ALBUM_ID, selected, pos, options);
+}
+
+
+ArtistContextMenu::ArtistContextMenu(QObject* parent)
+    : BaseMedialibMenu(parent)
+{}
+
+void ArtistContextMenu::popup(const QModelIndexList &selected, QPoint pos, QVariantMap options)
+{
+    BaseMedialibMenu::popup(m_model, MLArtistModel::ARTIST_ID, selected, pos, options);
+}
+
+GenreContextMenu::GenreContextMenu(QObject* parent)
+    : BaseMedialibMenu(parent)
+{}
+
+void GenreContextMenu::popup(const QModelIndexList& selected, QPoint pos, QVariantMap options)
+{
+    BaseMedialibMenu::popup(m_model, MLGenreModel::GENRE_ID, selected, pos, options);
+}
+
+AlbumTrackContextMenu::AlbumTrackContextMenu(QObject* parent)
+    : BaseMedialibMenu(parent)
+{}
+
+void AlbumTrackContextMenu::popup(const QModelIndexList &selected, QPoint pos, QVariantMap options)
+{
+    BaseMedialibMenu::popup(m_model, MLAlbumTrackModel::TRACK_ID, selected, pos, options);
+}
+
+VideoContextMenu::VideoContextMenu(QObject* parent)
+    : QObject(parent)
+{}
+
+void VideoContextMenu::popup(const QModelIndexList& selected, QPoint pos, QVariantMap options)
+{
+    if (!m_model)
+        return;
+
+    QMenu* menu = new QMenu();
+    QAction* action;
+
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+
+    MediaLib* ml= m_model->ml();
+
+    QVariantList itemIdList;
+    for (const QModelIndex& modelIndex : selected)
+        itemIdList.push_back(m_model->data(modelIndex, MLVideoModel::VIDEO_ID));
+
+    action = menu->addAction( qtr("Add and play") );
+
+    connect(action, &QAction::triggered, [ml, itemIdList]( ) {
+        ml->addAndPlay(itemIdList);
+    });
+
+    action = menu->addAction( qtr("Enqueue") );
+    connect(action, &QAction::triggered, [ml, itemIdList]( ) {
+        ml->addToPlaylist(itemIdList);
+    });
+
+    action = menu->addAction( qtr("Play as audio") );
+    connect(action, &QAction::triggered, [ml, itemIdList]( ) {
+        QStringList options({":no-video"});
+        ml->addAndPlay(itemIdList, &options);
+    });
+
+    if (options.contains("information") && options["information"].type() == QVariant::Int) {
+        action = menu->addAction( qtr("Information") );
+        QSignalMapper* sigmapper = new QSignalMapper(menu);
+        connect(action, &QAction::triggered, sigmapper, QOverload<>::of(&QSignalMapper::map));
+        sigmapper->setMapping(action, options["information"].toInt());
+#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
+        connect(sigmapper, &QSignalMapper::mappedInt, this, &VideoContextMenu::showMediaInformation);
+#else
+        connect(sigmapper, QOverload<int>::of(&QSignalMapper::mapped), this, &VideoContextMenu::showMediaInformation);
+#endif
+    }
+
+    menu->popup(pos);
+}
+
diff --git a/modules/gui/qt/menus/qml_menu_wrapper.hpp b/modules/gui/qt/menus/qml_menu_wrapper.hpp
index 2640f2af5d..ba3e3d0ac9 100644
--- a/modules/gui/qt/menus/qml_menu_wrapper.hpp
+++ b/modules/gui/qt/menus/qml_menu_wrapper.hpp
@@ -25,6 +25,12 @@
 
 #include "menus.hpp"
 
+class MediaLib;
+class MLAlbumModel;
+class MLGenreModel;
+class MLArtistModel;
+class MLAlbumTrackModel;
+class MLVideoModel;
 class QmlMainContext;
 
 #define SIMPLE_MENU_PROPERTY(type, name, defaultValue) \
@@ -47,6 +53,83 @@ public slots:
     void popup( QPoint pos );
 };
 
+class BaseMedialibMenu : public QObject
+{
+    Q_OBJECT
+public:
+    BaseMedialibMenu(QObject* parent = nullptr);
+signals:
+    void showMediaInformation(int index);
+
+protected:
+    void medialibAudioContextMenu(MediaLib* ml, const QVariantList& mlId, const QPoint& pos, const QVariantMap& options);
+
+    template<typename ModelType>
+    void popup(ModelType* model, typename ModelType::Roles role,  const QModelIndexList &selected, const  QPoint& pos, const QVariantMap& options) {
+        if (!model)
+            return;
+
+        MediaLib* ml= model->ml();
+        if (!ml)
+            return;
+
+        QVariantList itemIdList;
+        for (const QModelIndex& modelIndex : selected)
+            itemIdList.push_back(model->data(modelIndex, role));
+        medialibAudioContextMenu(ml, itemIdList, pos, options);
+    }
+};
+
+class AlbumContextMenu : public BaseMedialibMenu {
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(MLAlbumModel*, model, nullptr)
+public:
+    AlbumContextMenu(QObject* parent = nullptr);
+public slots:
+    void popup(const QModelIndexList& selected, QPoint pos, QVariantMap options = {});
+};
+
+
+class ArtistContextMenu : public BaseMedialibMenu {
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(MLArtistModel*, model, nullptr)
+public:
+    ArtistContextMenu(QObject* parent = nullptr);
+public slots:
+    void popup(const QModelIndexList& selected, QPoint pos, QVariantMap options = {});
+};
+
+
+class GenreContextMenu : public BaseMedialibMenu {
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(MLGenreModel*, model, nullptr)
+public:
+    GenreContextMenu(QObject* parent = nullptr);
+public slots:
+    void popup(const QModelIndexList& selected, QPoint pos, QVariantMap options = {});
+};
+
+
+class AlbumTrackContextMenu : public BaseMedialibMenu {
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(MLAlbumTrackModel*, model, nullptr)
+public:
+    AlbumTrackContextMenu(QObject* parent = nullptr);
+public slots:
+    void popup(const QModelIndexList& selected, QPoint pos, QVariantMap options = {});
+};
+
+
+class VideoContextMenu : public QObject {
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(MLVideoModel*, model, nullptr)
+public:
+    VideoContextMenu(QObject* parent = nullptr);
+public slots:
+    void popup(const QModelIndexList& selected, QPoint pos, QVariantMap options = {} );
+signals:
+    void showMediaInformation(int index);
+};
 #undef SIMPLE_MENU_PROPERTY
 
 #endif // QMLMENUWRAPPER_HPP
-- 
2.25.1



More information about the vlc-devel mailing list