[vlc-devel] [PATCH 13/18] qml: use a native implementation for the main dropdown menu

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


  fixes: #22166 #22167 #22604
---
 modules/gui/qt/Makefile.am                    |  3 +
 modules/gui/qt/maininterface/mainui.cpp       |  4 +
 .../qt/maininterface/qml/BannerSources.qml    | 12 ++-
 modules/gui/qt/menus/menus.cpp                | 15 ++++
 modules/gui/qt/menus/menus.hpp                |  4 +-
 modules/gui/qt/menus/qml_menu_wrapper.cpp     | 77 +++++++++++++++++++
 modules/gui/qt/menus/qml_menu_wrapper.hpp     | 52 +++++++++++++
 modules/gui/qt/player/qml/ControlButtons.qml  | 18 ++---
 8 files changed, 165 insertions(+), 20 deletions(-)
 create mode 100644 modules/gui/qt/menus/qml_menu_wrapper.cpp
 create mode 100644 modules/gui/qt/menus/qml_menu_wrapper.hpp

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 17796729d5..10b204f8b4 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -163,6 +163,8 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/medialibrary/mlvideomodel.hpp \
 	gui/qt/menus/custom_menus.cpp \
 	gui/qt/menus/custom_menus.hpp \
+	gui/qt/menus/qml_menu_wrapper.cpp \
+	gui/qt/menus/qml_menu_wrapper.hpp \
 	gui/qt/menus/menus.cpp gui/qt/menus/menus.hpp \
 	gui/qt/network/networkdevicemodel.cpp \
 	gui/qt/network/networkdevicemodel.hpp \
@@ -312,6 +314,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/medialibrary/mlvideo.moc.cpp \
 	gui/qt/medialibrary/mlvideomodel.moc.cpp \
 	gui/qt/menus/custom_menus.moc.cpp \
+	gui/qt/menus/qml_menu_wrapper.moc.cpp \
 	gui/qt/menus/menus.moc.cpp \
 	gui/qt/network/networkdevicemodel.moc.cpp \
 	gui/qt/network/networkmediamodel.moc.cpp \
diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp
index 7dad487c13..51b5de9fde 100644
--- a/modules/gui/qt/maininterface/mainui.cpp
+++ b/modules/gui/qt/maininterface/mainui.cpp
@@ -34,6 +34,8 @@
 
 #include "maininterface/main_interface.hpp"
 
+#include "menus/qml_menu_wrapper.hpp"
+
 #include "videosurface.hpp"
 
 #include <QQuickWindow>
@@ -195,6 +197,8 @@ void MainUI::registerQMLTypes()
     qmlRegisterType<QmlEventFilter>( "org.videolan.vlc", 0, 1, "EventFilter" );
 
     qmlRegisterType<PlayerControlBarModel>( "org.videolan.vlc", 0, 1, "PlayerControlBarModel");
+
+    qmlRegisterType<QmlGlobalMenu>( "org.videolan.vlc", 0, 1, "QmlGlobalMenu" );
 }
 
 void MainUI::onQmlWarning(const QList<QQmlError>& qmlErrors)
diff --git a/modules/gui/qt/maininterface/qml/BannerSources.qml b/modules/gui/qt/maininterface/qml/BannerSources.qml
index b2115c3f6c..a3289a34bf 100644
--- a/modules/gui/qt/maininterface/qml/BannerSources.qml
+++ b/modules/gui/qt/maininterface/qml/BannerSources.qml
@@ -295,15 +295,13 @@ Widgets.NavigableFocusScope {
                             text: i18n.qtr("Menu")
                             height: playlistGroup.height
 
-                            onClicked: mainMenu.openBelow(this)
+                            onClicked: contextMenu.popup(this.mapToGlobal(0, height))
 
-                            Menus.MainDropdownMenu {
-                                id: mainMenu
-                                onClosed: {
-                                    if (mainMenu.activeFocus)
-                                        menu_selector.forceActiveFocus()
-                                }
+                            QmlGlobalMenu {
+                                id: contextMenu
+                                ctx: mainctx
                             }
+
                         }
 
                         Widgets.IconToolButton {
diff --git a/modules/gui/qt/menus/menus.cpp b/modules/gui/qt/menus/menus.cpp
index fa244bdc5e..aceeb6dade 100644
--- a/modules/gui/qt/menus/menus.cpp
+++ b/modules/gui/qt/menus/menus.cpp
@@ -45,6 +45,8 @@
 #include "dialogs/extensions/extensions_manager.hpp"                 /* Extensions menu */
 #include "dialogs/extended/extended_panels.hpp"
 #include "util/varchoicemodel.hpp"
+#include "medialibrary/medialib.hpp"
+
 
 #include <QMenu>
 #include <QMenuBar>
@@ -166,6 +168,10 @@ static inline void addMenuToMainbar( QMenu *func, QString title, QMenuBar *bar )
 /**
  * Main Menu Bar Creation
  **/
+VLCMenuBar::VLCMenuBar(QObject* parent)
+    : QObject(parent)
+{}
+
 void VLCMenuBar::createMenuBar( MainInterface *mi,
                               intf_thread_t *p_intf )
 {
@@ -362,6 +368,15 @@ QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterfac
     connect( mi, &MainInterface::fullscreenInterfaceToggled,
              action, &QAction::setChecked );
 
+    action = menu->addAction( qtr( "&View Items as Grid" ), mi,
+            &MainInterface::setGridView );
+    action->setCheckable( true );
+    action->setChecked( mi->hasGridView() );
+    connect( mi, &MainInterface::gridViewChanged,
+             action, &QAction::setChecked );
+
+    menu->addMenu( new CheckableListMenu(qtr( "&Color Scheme" ), mi->getColorScheme(), CheckableListMenu::GROUPED, current) );
+
     menu->addSeparator();
 
     InterfacesMenu( p_intf, menu );
diff --git a/modules/gui/qt/menus/menus.hpp b/modules/gui/qt/menus/menus.hpp
index eaf5bf129d..9af7c349b7 100644
--- a/modules/gui/qt/menus/menus.hpp
+++ b/modules/gui/qt/menus/menus.hpp
@@ -40,6 +40,8 @@ class VLCMenuBar : public QObject
     friend class MenuFunc;
 
 public:
+    VLCMenuBar(QObject* parent = nullptr);
+
     /* Main bar creation */
     static void createMenuBar( MainInterface *mi, intf_thread_t * );
 
@@ -57,7 +59,7 @@ public:
     static void freeRendererMenu(){ delete rendererMenu; rendererMenu = NULL; }
     static void freeRecentsMenu(){ delete recentsMenu; recentsMenu = NULL; }
 
-private:
+protected:
     /* All main Menus */
     static QMenu *FileMenu( intf_thread_t *, QWidget *, MainInterface * mi = NULL );
 
diff --git a/modules/gui/qt/menus/qml_menu_wrapper.cpp b/modules/gui/qt/menus/qml_menu_wrapper.cpp
new file mode 100644
index 0000000000..a0bac49b6e
--- /dev/null
+++ b/modules/gui/qt/menus/qml_menu_wrapper.cpp
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+#include "qml_menu_wrapper.hpp"
+#include "menus.hpp"
+#include "util/qml_main_context.hpp"
+
+
+#include <QSignalMapper>
+
+
+static inline void addSubMenu( QMenu *func, QString title, QMenu *bar ) {
+    func->setTitle( title );
+    bar->addMenu( func);
+}
+
+QmlGlobalMenu::QmlGlobalMenu(QObject *parent)
+    : VLCMenuBar(parent)
+{
+}
+
+void QmlGlobalMenu::popup(QPoint pos)
+{
+    if (!m_ctx)
+        return;
+
+    intf_thread_t* p_intf = m_ctx->getIntf();
+    if (!p_intf)
+        return;
+
+    QMenu* menu = new QMenu();
+    menu->setAttribute(Qt::WA_DeleteOnClose);
+    QMenu* submenu;
+
+    QAction* fileMenu = menu->addMenu(FileMenu( p_intf, menu, p_intf->p_sys->p_mi ));
+    fileMenu->setText(qtr( "&Media" ));
+
+    /* Dynamic menus, rebuilt before being showed */
+    submenu = menu->addMenu(qtr( "P&layback" ));
+    NavigMenu( p_intf, submenu );
+
+    submenu = menu->addMenu(qtr( "&Audio" ));
+    AudioMenu( p_intf, submenu );
+
+    submenu = menu->addMenu(qtr( "&Video" ));
+    VideoMenu( p_intf, submenu );
+
+    submenu = menu->addMenu(qtr( "Subti&tle" ));
+    SubtitleMenu( p_intf, submenu );
+
+    submenu = menu->addMenu(qtr( "Tool&s" ));
+    ToolsMenu( p_intf, submenu );
+
+    /* View menu, a bit different */
+    submenu = menu->addMenu(qtr( "V&iew" ));
+    ViewMenu( p_intf, submenu, p_intf->p_sys->p_mi );
+
+    QAction* helpMenu = menu->addMenu( HelpMenu(menu) );
+    helpMenu->setText(qtr( "&Help" ));
+
+    menu->popup(pos);
+}
+
diff --git a/modules/gui/qt/menus/qml_menu_wrapper.hpp b/modules/gui/qt/menus/qml_menu_wrapper.hpp
new file mode 100644
index 0000000000..2640f2af5d
--- /dev/null
+++ b/modules/gui/qt/menus/qml_menu_wrapper.hpp
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+#ifndef QMLMENUWRAPPER_HPP
+#define QMLMENUWRAPPER_HPP
+
+#include "qt.hpp"
+
+#include <QObject>
+#include <QPoint>
+
+#include "menus.hpp"
+
+class QmlMainContext;
+
+#define SIMPLE_MENU_PROPERTY(type, name, defaultValue) \
+    Q_PROPERTY(type name READ get##name WRITE set##name) \
+    public: \
+    inline void set##name( type data) { m_##name = data; } \
+    inline type get##name() const { return m_##name; } \
+    private: \
+    type m_##name = defaultValue;
+
+//inherit VLCMenuBar so we can access menu creation functions
+class QmlGlobalMenu : public VLCMenuBar
+{
+    Q_OBJECT
+    SIMPLE_MENU_PROPERTY(QmlMainContext*, ctx, nullptr)
+public:
+    explicit QmlGlobalMenu(QObject *parent = nullptr);
+
+public slots:
+    void popup( QPoint pos );
+};
+
+#undef SIMPLE_MENU_PROPERTY
+
+#endif // QMLMENUWRAPPER_HPP
diff --git a/modules/gui/qt/player/qml/ControlButtons.qml b/modules/gui/qt/player/qml/ControlButtons.qml
index 864ab7ec14..e7c9f370f7 100644
--- a/modules/gui/qt/player/qml/ControlButtons.qml
+++ b/modules/gui/qt/player/qml/ControlButtons.qml
@@ -525,20 +525,14 @@ Item{
             id: menuBtn
             size: VLCStyle.icon_medium
             iconText: VLCIcons.menu
-            onClicked: {
-                root._lockAutoHide += 1
-                mainMenu.openAbove(this)
-            }
-            property alias mainMenuExt: mainMenu
-            Menus.MainDropdownMenu {
-                id: mainMenu
-                onClosed: {
-                    root._lockAutoHide -= 1
-                    menuBtn.forceActiveFocus()
-                }
-            }
+            onClicked: contextMenu.popup(this.mapToGlobal(0, 0))
             property bool acceptFocus: true
             text: i18n.qtr("Menu")
+
+            QmlGlobalMenu {
+                id: contextMenu
+                ctx: mainctx
+            }
         }
     }
 
-- 
2.25.1



More information about the vlc-devel mailing list