1 | /* |
2 | This file is part of the KDE project |
3 | SPDX-FileCopyrightText: 2021 Felix Ernst <fe.a.ernst@gmail.com> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-2-Clause |
6 | */ |
7 | |
8 | #ifndef KTOOLTIPHELPER_P_H |
9 | #define KTOOLTIPHELPER_P_H |
10 | |
11 | #include <qobject.h> |
12 | |
13 | #include <QPointer> |
14 | #include <QRect> |
15 | #include <QTimer> |
16 | |
17 | class KToolTipHelper; |
18 | |
19 | class QAction; |
20 | class QHelpEvent; |
21 | class ; |
22 | |
23 | /*! |
24 | * \brief The private class of KToolTipHelper used for the PIMPL idiom. |
25 | * \inmodule KXmlGui |
26 | * \internal |
27 | */ |
28 | class KToolTipHelperPrivate : public QObject |
29 | { |
30 | Q_OBJECT |
31 | |
32 | public: |
33 | /*! |
34 | * \brief Singleton implementation for KToolTipHelper and |
35 | * NOT of this class (KToolTipHelperPrivate). |
36 | */ |
37 | static KToolTipHelper *instance(); |
38 | |
39 | explicit KToolTipHelperPrivate(KToolTipHelper *qq); |
40 | |
41 | ~KToolTipHelperPrivate() override; |
42 | |
43 | /*! \sa KToolTipHelper::eventFilter() */ |
44 | bool eventFilter(QObject *watched, QEvent *event) override; |
45 | |
46 | /*! \sa KToolTipHelper::whatsThisHintOnly() */ |
47 | static const QString whatsThisHintOnly(); |
48 | |
49 | /*! |
50 | * \brief Makes sure submenus that show up do not mess with tooltips appearing in menus. |
51 | * |
52 | * This is somewhat of a workaround for Qt not posting QEvent::ToolTips when the |
53 | * cursor wasn't moved *after* a submenu hides. |
54 | * |
55 | * Returns false. |
56 | */ |
57 | bool handleHideEvent(QObject *watched, QEvent *event); |
58 | |
59 | /*! |
60 | * \brief Returns \c true if the key press is used to |
61 | * expand a tooltip, \c false otherwise. |
62 | */ |
63 | bool handleKeyPressEvent(QEvent *event); |
64 | |
65 | /*! |
66 | * Is called from handleToolTipEvent() to handle a QEvent::ToolTip in a menu. |
67 | * This method will show the tooltip of the action that is hovered at a nice |
68 | * position. |
69 | * |
70 | * \a menu The menu that a tooltip is requested for. |
71 | * |
72 | * \a helpEvent The QEvent::ToolTip that was cast to a QHelpEvent. |
73 | */ |
74 | bool handleMenuToolTipEvent(QMenu *, QHelpEvent *helpEvent); |
75 | |
76 | /*! |
77 | * \brief Returns \c false if no special handling of the tooltip event |
78 | * seems necessary, \c true otherwise. |
79 | * |
80 | * \a watched The object that is receiving the QHelpEvent. |
81 | * |
82 | * \a helpEvent The QEvent::ToolTip that was cast to a QHelpEvent. |
83 | */ |
84 | bool handleToolTipEvent(QObject *watched, QHelpEvent *helpEvent); |
85 | |
86 | /*! |
87 | * \brief Handles links being clicked in whatsThis. |
88 | * |
89 | * Returns true. |
90 | */ |
91 | bool handleWhatsThisClickedEvent(QEvent *event); |
92 | |
93 | /*! |
94 | * \brief The name is slightly misleading because it will only post events for QMenus. |
95 | * \sa handleHideEvent() |
96 | */ |
97 | void postToolTipEventIfCursorDidntMove() const; |
98 | |
99 | /*! |
100 | * \brief Shows a tooltip that contains a whatsThisHint |
101 | * at the location \a globalPos. |
102 | * |
103 | * If \a tooltip is empty, only a whatsThisHint is shown. |
104 | * |
105 | * The parameter usage is identical to that of QToolTip::showText. The only difference |
106 | * is that this method doesn't need a QWidget *w parameter because that one is already |
107 | * retrieved in handleToolTipEvent() prior to calling this method. |
108 | * |
109 | * \sa QToolTip::showText() |
110 | */ |
111 | void showExpandableToolTip(const QPoint &globalPos, const QString &toolTip = QString(), const QRect &rect = QRect()); |
112 | |
113 | public: |
114 | KToolTipHelper *const q; |
115 | |
116 | private: |
117 | /*! \brief An action in a menu a tooltip was requested for. */ |
118 | QPointer<QAction> m_action; |
119 | /*! |
120 | * \brief The global position where the last tooltip |
121 | * that had a whatsThisHint was displayed. |
122 | */ |
123 | QPoint m_lastExpandableToolTipGlobalPos; |
124 | /*! \brief The last widget a QEvent::tooltip was sent for. */ |
125 | QPointer<QWidget> m_widget; |
126 | /*! \brief Whether or not the last tooltip was expandable. */ |
127 | bool m_lastToolTipWasExpandable = false; |
128 | |
129 | /*! |
130 | * \brief The global position of where the cursor was when the last |
131 | * QEvent::HideEvent for a menu occurred. |
132 | * |
133 | * \sa handleHideEvent() */ |
134 | QPoint ; |
135 | /*! |
136 | * \brief Calls postToolTipEventIfCursorDidntMove(). |
137 | * \sa handleHideEvent() |
138 | */ |
139 | QTimer m_toolTipTimeout; |
140 | |
141 | static KToolTipHelper *s_instance; |
142 | }; |
143 | |
144 | /* |
145 | * This method checks if string "a" is sufficiently different |
146 | * from string "b", barring characters like periods, ampersands |
147 | * and other characters. |
148 | * |
149 | * Used for determining if tooltips are different from their icon name counterparts. |
150 | * |
151 | * Returns true if the string "a" is similar to "b" and false otherwise. |
152 | */ |
153 | bool isTextSimilar(const QString &a, const QString &b); |
154 | |
155 | #endif // KTOOLTIPHELPER_P_H |
156 | |