vcl/inc/qt5/QtMenu.hxx |    8 ++++++++
 vcl/qt5/QtMenu.cxx     |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

New commits:
commit 2ef9880f97de6629ddef12eb788123ab4be1ec83
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Sun Jul 30 01:59:31 2023 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Aug 1 08:21:22 2023 +0200

    tdf#156376 qt: Open help for focused native menu entry on F1
    
    In order to allow have pressing F1 (`QKeySequence::HelpContents`)
    open the corresponding help entry for the currently selected
    menu entry, connect to the signal that gets emitted when
    a menu entry is selected (`QAction::hovered`) and remember
    its help ID. Register the F1 shortcut for the menu
    and connect its `activated`/`activatedAmbiguously`
    signal with a slot that opens the help for the current/
    last selected menu entry.
    
    Change-Id: I24eec4806e5a202052a49c239e4836b92c9f0228
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155055
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/inc/qt5/QtMenu.hxx b/vcl/inc/qt5/QtMenu.hxx
index 3e43272b6212..bd704507f69c 100644
--- a/vcl/inc/qt5/QtMenu.hxx
+++ b/vcl/inc/qt5/QtMenu.hxx
@@ -53,6 +53,9 @@ private:
     QMenu* mpQMenu;
     QButtonGroup* m_pButtonGroup;
 
+    // help ID of currently/last selected item
+    static OUString m_sCurrentHelpId;
+
     void DoFullMenuUpdate(Menu* pMenuBar);
     static void NativeItemText(OUString& rItemText);
 
@@ -64,6 +67,9 @@ private:
     bool validateQMenuBar() const;
     QPushButton* ImplAddMenuBarButton(const QIcon& rIcon, const QString& 
rToolTip, int nId);
     void ImplRemoveMenuBarButton(int nId);
+    void connectHelpShortcut(QMenu* pMenu);
+    // set slots that handle signals relevent for help menu
+    void connectHelpSignalSlots(QMenu* pMenu, QtMenuItem* pSalMenuItem);
 
 public:
     QtMenu(bool bMenuBar);
@@ -102,6 +108,8 @@ public:
     QtMenuItem* GetItemAtPos(unsigned nPos) { return maItems[nPos]; }
 
 private slots:
+    static void slotShowHelp();
+    static void slotMenuHovered(QtMenuItem* pItem);
     static void slotMenuTriggered(QtMenuItem* pQItem);
     static void slotMenuAboutToShow(QtMenuItem* pQItem);
     static void slotMenuAboutToHide(QtMenuItem* pQItem);
diff --git a/vcl/qt5/QtMenu.cxx b/vcl/qt5/QtMenu.cxx
index b976fa3f5739..b1e62bc09475 100644
--- a/vcl/qt5/QtMenu.cxx
+++ b/vcl/qt5/QtMenu.cxx
@@ -24,6 +24,11 @@
 #include <QtWidgets/QHBoxLayout>
 #include <QtWidgets/QMenuBar>
 #include <QtWidgets/QPushButton>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtGui/QShortcut>
+#else
+#include <QtWidgets/QShortcut>
+#endif
 #include <QtWidgets/QStyle>
 
 #include <o3tl/safeint.hxx>
@@ -48,6 +53,8 @@ static inline void lcl_force_menubar_layout_update(QMenuBar& 
rMenuBar)
     rMenuBar.adjustSize();
 }
 
+OUString QtMenu::m_sCurrentHelpId = u"";
+
 QtMenu::QtMenu(bool bMenuBar)
     : mpVCLMenu(nullptr)
     , mpParentSalMenu(nullptr)
@@ -77,6 +84,7 @@ void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, 
unsigned nPos)
         if (validateQMenuBar())
         {
             QMenu* pQMenu = new QMenu(toQString(aText), nullptr);
+            connectHelpSignalSlots(pQMenu, pSalMenuItem);
             pSalMenuItem->mpMenu.reset(pQMenu);
 
             if ((nPos != MENU_APPEND)
@@ -108,12 +116,14 @@ void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, 
unsigned nPos)
             // no QMenu set, instantiate own one
             mpOwnedQMenu.reset(new QMenu);
             mpQMenu = mpOwnedQMenu.get();
+            connectHelpSignalSlots(mpQMenu, pSalMenuItem);
         }
 
         if (pSalMenuItem->mpSubMenu)
         {
             // submenu
             QMenu* pQMenu = new QMenu(toQString(aText), nullptr);
+            connectHelpSignalSlots(pQMenu, pSalMenuItem);
             pSalMenuItem->mpMenu.reset(pQMenu);
 
             if ((nPos != MENU_APPEND)
@@ -183,6 +193,8 @@ void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, 
unsigned nPos)
 
                 connect(pAction, &QAction::triggered, this,
                         [pSalMenuItem] { slotMenuTriggered(pSalMenuItem); });
+                connect(pAction, &QAction::hovered, this,
+                        [pSalMenuItem] { slotMenuHovered(pSalMenuItem); });
             }
         }
     }
@@ -618,6 +630,22 @@ const QtFrame* QtMenu::GetFrame() const
     return pMenu ? pMenu->mpFrame : nullptr;
 }
 
+void QtMenu::slotMenuHovered(QtMenuItem* pItem)
+{
+    const OUString sHelpId = 
pItem->mpParentMenu->GetMenu()->GetHelpId(pItem->mnId);
+    m_sCurrentHelpId = sHelpId;
+}
+
+void QtMenu::slotShowHelp()
+{
+    SolarMutexGuard aGuard;
+    Help* pHelp = Application::GetHelp();
+    if (pHelp && !m_sCurrentHelpId.isEmpty())
+    {
+        pHelp->Start(m_sCurrentHelpId);
+    }
+}
+
 void QtMenu::slotMenuTriggered(QtMenuItem* pQItem)
 {
     if (!pQItem)
@@ -772,6 +800,26 @@ void QtMenu::ImplRemoveMenuBarButton(int nId)
     lcl_force_menubar_layout_update(*mpQMenuBar);
 }
 
+void QtMenu::connectHelpShortcut(QMenu* pMenu)
+{
+    assert(pMenu);
+    QKeySequence sequence(QKeySequence::HelpContents);
+    QShortcut* pQShortcut = new QShortcut(sequence, pMenu);
+    connect(pQShortcut, &QShortcut::activated, this, QtMenu::slotShowHelp);
+    connect(pQShortcut, &QShortcut::activatedAmbiguously, this, 
QtMenu::slotShowHelp);
+}
+
+void QtMenu::connectHelpSignalSlots(QMenu* pMenu, QtMenuItem* pSalMenuItem)
+{
+    // connect hovered signal of the menu's own action
+    QAction* pAction = pMenu->menuAction();
+    assert(pAction);
+    connect(pAction, &QAction::hovered, this, [pSalMenuItem] { 
slotMenuHovered(pSalMenuItem); });
+
+    // connect slot to handle Help key (F1)
+    connectHelpShortcut(pMenu);
+}
+
 void QtMenu::RemoveMenuBarButton(sal_uInt16 nId) { 
ImplRemoveMenuBarButton(nId); }
 
 tools::Rectangle QtMenu::GetMenuBarButtonRectPixel(sal_uInt16 nId, SalFrame* 
pFrame)

Reply via email to