File indexing completed on 2024-04-14 03:57:14

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2021 Felix Ernst <fe.a.ernst@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-2-Clause
0006 */
0007 
0008 #ifndef KTOOLTIPHELPER_P_H
0009 #define KTOOLTIPHELPER_P_H
0010 
0011 #include <qobject.h>
0012 
0013 #include <QPointer>
0014 #include <QRect>
0015 #include <QTimer>
0016 
0017 class KToolTipHelper;
0018 
0019 class QAction;
0020 class QHelpEvent;
0021 class QMenu;
0022 
0023 /**
0024  * The private class of KToolTipHelper used for the PIMPL idiom.
0025  * \internal
0026  */
0027 class KToolTipHelperPrivate : public QObject
0028 {
0029     Q_OBJECT
0030 
0031 public:
0032     /**
0033      * Singleton implementation for KToolTipHelper and
0034      * NOT of this class (KToolTipHelperPrivate).
0035      */
0036     static KToolTipHelper *instance();
0037 
0038     explicit KToolTipHelperPrivate(KToolTipHelper *qq);
0039 
0040     ~KToolTipHelperPrivate() override;
0041 
0042     /** @see KToolTipHelper::eventFilter() */
0043     virtual bool eventFilter(QObject *watched, QEvent *event) override;
0044 
0045     /** @see KToolTipHelper::whatsThisHintOnly() */
0046     static const QString whatsThisHintOnly();
0047 
0048     /**
0049      * Makes sure submenus that show up do not mess with tooltips appearing in menus.
0050      * This is somewhat of a workaround for Qt not posting QEvent::ToolTips when the
0051      * cursor wasn't moved *after* a submenu hides.
0052      * @return false.
0053      */
0054     bool handleHideEvent(QObject *watched, QEvent *event);
0055 
0056     /**
0057      * @return true if the key press is used to expand a tooltip. false otherwise.
0058      */
0059     bool handleKeyPressEvent(QEvent *event);
0060 
0061     /**
0062      * Is called from handleToolTipEvent() to handle a QEvent::ToolTip in a menu.
0063      * This method will show the tooltip of the action that is hovered at a nice
0064      * position.
0065      * @param menu      The menu that a tooltip is requested for
0066      * @param helpEvent The QEvent::ToolTip that was cast to a QHelpEvent
0067      */
0068     bool handleMenuToolTipEvent(QMenu *menu, QHelpEvent *helpEvent);
0069 
0070     /**
0071      * @param watched       The object that is receiving the QHelpEvent
0072      * @param helpEvent     The QEvent::ToolTip that was cast to a QHelpEvent
0073      * @return false if no special handling of the tooltip event seems necessary. true otherwise.
0074      */
0075     bool handleToolTipEvent(QObject *watched, QHelpEvent *helpEvent);
0076 
0077     /**
0078      * Handles links being clicked in whatsThis.
0079      * @return true.
0080      */
0081     bool handleWhatsThisClickedEvent(QEvent *event);
0082 
0083     /** @see handleHideEvent()
0084      * The name is slightly misleading because it will only post events for QMenus. */
0085     void postToolTipEventIfCursorDidntMove() const;
0086 
0087     /**
0088      * Shows a tooltip that contains a whatsThisHint at the location \p globalPos.
0089      * If \p tooltip is empty, only a whatsThisHint is shown.
0090      *
0091      * The parameter usage is identical to that of QToolTip::showText. The only difference
0092      * is that this method doesn't need a QWidget *w parameter because that one is already
0093      * retrieved in handleToolTipEvent() prior to calling this method.
0094      *
0095      * @see QToolTip::showText()
0096      */
0097     void showExpandableToolTip(const QPoint &globalPos, const QString &toolTip = QString(), const QRect &rect = QRect());
0098 
0099 public:
0100     KToolTipHelper *const q;
0101 
0102 private:
0103     /** An action in a menu a tooltip was requested for. */
0104     QPointer<QAction> m_action;
0105     /** The global position where the last tooltip which had a whatsThisHint was displayed. */
0106     QPoint m_lastExpandableToolTipGlobalPos;
0107     /** The last widget a QEvent::tooltip was sent for. */
0108     QPointer<QWidget> m_widget;
0109     /** Whether or not the last tooltip was expandable */
0110     bool m_lastToolTipWasExpandable = false;
0111 
0112     /** The global position of where the cursor was when the last QEvent::HideEvent for a
0113      * menu occurred. @see handleHideEvent() */
0114     QPoint m_cursorGlobalPosWhenLastMenuHid;
0115     /** Calls postToolTipEventIfCursorDidntMove().  @see handleHideEvent() */
0116     QTimer m_toolTipTimeout;
0117 
0118     static KToolTipHelper *s_instance;
0119 };
0120 
0121 /**
0122  * This method checks if string "a" is sufficiently different from string "b", barring characters
0123  * like periods, ampersands and other characters. Used for determining if tooltips are different from
0124  * their icon name counterparts.
0125  *
0126  * @return true if the string "a" is similar to "b" and false otherwise.
0127  */
0128 bool isTextSimilar(const QString &a, const QString &b);
0129 
0130 #endif // KTOOLTIPHELPER_P_H