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