vcl/inc/qt5/QtMenu.hxx     |    4 ++++
 vcl/inc/salmenu.hxx        |    1 +
 vcl/qt5/QtMenu.cxx         |   45 +++++++++++++++++++++++++++++++++++++++++++++
 vcl/source/window/menu.cxx |    3 +++
 4 files changed, 53 insertions(+)

New commits:
commit a108fce773d46441e30dcc14abe29751410ae4ed
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Fri Jan 17 14:18:30 2025 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Fri Jan 17 22:27:59 2025 +0100

    tdf#163186 qt: Show menu item tooltips
    
    So far, the qt VCL plugins were not handling/showing
    menu item tooltips, like showing the full path for
    entries in the "File" -> "Recent Documents" submenu.
    
    Implement handling so they are shown:
    
    * Set the tooltip for the menu entry's QAction in
      QtMenu::InsertMenuItem.
    
    * Introduce SalMenu::SetItemTooltip, override it
      in the QtMenu subclass and call it in Menu::SetTipHelpText so
      newly set tooltips are propagated to the native
      Qt menu, to keep them up to date (similar to what already
      happens e.g. for the menu entry's displayed text in
      Menu::SetItemText).
    
    * Since Qt doesn't by default show tooltips for
      QActions used in menus, install an event filter
      on the QMenu/QMenuBar objects that handles the QEvent::ToolTip
      event to manually show a tooltip. See [1] for
      more background and a similar example using custom
      QMenu/QMenuBar subclasses instead of the
      QObject::installEventFilter/QObject::eventFilter approach
      taken in this commit.
    
    Only show the tooltip if one was explicitly set.
    QToolTip::tooltip() [2] by default returns a text
    based on the action's text (with accelerator's etc.
    stripped), so only show the tooltip if QToolTip::tooltip()
    returns something that differs from what would be used
    based simply on the text.
    
    [1] https://forum.qt.io/topic/6821/solved-settooltip-in-qaction-menu/2
    [2] https://doc.qt.io/qt-6/qaction.html#toolTip-prop
    
    Change-Id: I1e2568d9d6e9e2baf7dcd7dffbaaabae7862b489
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180408
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Jenkins

diff --git a/vcl/inc/qt5/QtMenu.hxx b/vcl/inc/qt5/QtMenu.hxx
index 8042c67720ba..bbabb59e4ebd 100644
--- a/vcl/inc/qt5/QtMenu.hxx
+++ b/vcl/inc/qt5/QtMenu.hxx
@@ -73,6 +73,8 @@ private:
 public:
     QtMenu(bool bMenuBar);
 
+    bool eventFilter(QObject* pObject, QEvent* pEvent) override;
+
     virtual bool VisibleMenuBar() override; // must return TRUE to actually 
DISPLAY native menu bars
 
     virtual void InsertItem(SalMenuItem* pSalMenuItem, unsigned nPos) override;
@@ -89,6 +91,8 @@ public:
     virtual void ShowItem(unsigned nPos, bool bShow) override;
     virtual void SetItemText(unsigned nPos, SalMenuItem* pSalMenuItem,
                              const OUString& rText) override;
+
+    virtual void SetItemTooltip(SalMenuItem* pSalMenuItem, const OUString& 
rTooltip) override;
     virtual void SetItemImage(unsigned nPos, SalMenuItem* pSalMenuItem,
                               const Image& rImage) override;
     virtual void SetAccelerator(unsigned nPos, SalMenuItem* pSalMenuItem,
diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
index 84939574d447..7ecd220209bb 100644
--- a/vcl/inc/salmenu.hxx
+++ b/vcl/inc/salmenu.hxx
@@ -71,6 +71,7 @@ public:
     virtual void CheckItem( unsigned nPos, bool bCheck ) = 0;
     virtual void EnableItem( unsigned nPos, bool bEnable ) = 0;
     virtual void SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const 
OUString& rText )= 0;
+    virtual void SetItemTooltip(SalMenuItem* /*pSalMenuItem*/, const OUString& 
/*rTooltip*/) {};
     virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const 
Image& rImage ) = 0;
     virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, 
const vcl::KeyCode& rKeyCode, const OUString& rKeyName ) = 0;
     virtual void GetSystemMenuData(SystemMenuData& rData);
diff --git a/vcl/qt5/QtMenu.cxx b/vcl/qt5/QtMenu.cxx
index e90248a032e3..845d1940b185 100644
--- a/vcl/qt5/QtMenu.cxx
+++ b/vcl/qt5/QtMenu.cxx
@@ -32,6 +32,7 @@
 #include <QtWidgets/QShortcut>
 #endif
 #include <QtWidgets/QStyle>
+#include <QtWidgets/QToolTip>
 
 #include <o3tl/safeint.hxx>
 #include <vcl/svapp.hxx>
@@ -69,6 +70,37 @@ QtMenu::QtMenu(bool bMenuBar)
 {
 }
 
+bool QtMenu::eventFilter(QObject* pObject, QEvent* pEvent)
+{
+    // manually trigger tooltip if action's tooltip is set,
+    // Qt doesn't do that for menu entries
+    if (pEvent->type() != QEvent::ToolTip)
+        return false;
+
+    QAction* pAction = nullptr;
+    if (QMenu* pMenu = qobject_cast<QMenu*>(pObject))
+        pAction = pMenu->activeAction();
+    else if (QMenuBar* pMenuBar = qobject_cast<QMenuBar*>(pObject))
+        pAction = pMenuBar->activeAction();
+
+    if (!pAction)
+        return false;
+
+    // QAction::toolTip() is by default based on action's text, only display 
if it differs
+    const QString sToolTip = pAction->toolTip();
+    if (!sToolTip.isEmpty() && sToolTip != QAction(pAction->text()).toolTip())
+    {
+        QHelpEvent* pHelpEvent = static_cast<QHelpEvent*>(pEvent);
+        QToolTip::showText(pHelpEvent->globalPos(), pAction->toolTip());
+    }
+    else
+    {
+        QToolTip::hideText();
+    }
+
+    return false;
+}
+
 bool QtMenu::VisibleMenuBar() { return true; }
 
 void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, unsigned nPos)
@@ -175,6 +207,7 @@ void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, 
unsigned nPos)
             {
                 // leaf menu
                 QAction* pAction = new QAction(aText, nullptr);
+                pAction->setToolTip(toQString(mpVCLMenu->GetTipHelpText(nId)));
                 pSalMenuItem->mpAction.reset(pAction);
 
                 if ((nPos != MENU_APPEND)
@@ -457,6 +490,7 @@ void QtMenu::SetFrame(const SalFrame* pFrame)
         return;
 
     mpQMenuBar = new QMenuBar();
+    mpQMenuBar->installEventFilter(this);
     pMainWindow->setMenuBar(mpQMenuBar);
 
     // open menu bar on F10, as is common in KF 6 and other toolkits:
@@ -586,6 +620,14 @@ void QtMenu::SetItemImage(unsigned, SalMenuItem* pItem, 
const Image& rImage)
     pAction->setIcon(QPixmap::fromImage(toQImage(rImage)));
 }
 
+void QtMenu::SetItemTooltip(SalMenuItem* pItem, const OUString& rTooltip)
+{
+    QtMenuItem* pSalMenuItem = static_cast<QtMenuItem*>(pItem);
+
+    if (QAction* pAction = pSalMenuItem->getAction())
+        pAction->setToolTip(toQString(rTooltip));
+}
+
 void QtMenu::SetAccelerator(unsigned, SalMenuItem* pItem, const vcl::KeyCode&,
                             const OUString& rText)
 {
@@ -818,6 +860,9 @@ void QtMenu::connectHelpSignalSlots(QMenu* pMenu, 
QtMenuItem* pSalMenuItem)
 
     // connect slot to handle Help key (F1)
     connectHelpShortcut(pMenu);
+
+    // install event filter in order to show tooltip on tooltip event
+    pMenu->installEventFilter(this);
 }
 
 void QtMenu::RemoveMenuBarButton(sal_uInt16 nId) { 
ImplRemoveMenuBarButton(nId); }
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 7b3c2a78be62..f7032281f7b2 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -1138,6 +1138,9 @@ void Menu::SetTipHelpText( sal_uInt16 nItemId, const 
OUString& rStr )
 
     if ( pData )
         pData->aTipHelpText = rStr;
+
+    if (ImplGetSalMenu() && pData->pSalMenuItem)
+        ImplGetSalMenu()->SetItemTooltip(pData->pSalMenuItem.get(), rStr);
 }
 
 OUString Menu::GetTipHelpText( sal_uInt16 nItemId ) const

Reply via email to