Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquicktooltip.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
9
10#include <QtCore/qbasictimer.h>
11#include <QtQml/qqmlinfo.h>
12#include <QtQml/qqmlengine.h>
13#include <QtQml/qqmlcontext.h>
14#include <QtQml/qqmlcomponent.h>
15#include <QtQuick/qquickwindow.h>
16
18
19/*!
20 \qmltype ToolTip
21 \inherits Popup
22//! \nativetype QQuickToolTip
23 \inqmlmodule QtQuick.Controls
24 \since 5.7
25 \ingroup qtquickcontrols-popups
26 \brief Provides tool tips for any control.
27
28 A tool tip is a short piece of text that informs the user of a control's
29 function. It is typically placed above or below the parent control. The
30 tip text can be any \l{Rich Text Processing}{rich text} formatted string.
31
32 \image qtquickcontrols-tooltip.png
33
34 \section2 Attached Tool Tips
35
36 The most straight-forward way to setup tool tips for controls is to
37 specify \l text and \l {visible}{visibility} via attached properties.
38 The following example illustrates this approach:
39
40 \snippet qtquickcontrols-tooltip.qml 1
41
42 Under normal circumstances, there is only one tool tip visible at a time.
43 In order to save resources, all items that use the ToolTip attached property
44 share the same visual tool tip label instance. Even though the visuals are
45 shared, \c text, \c timeout and \c delay are stored individually for each item
46 that uses the respective attached property. However, multiple items cannot
47 make the shared tool tip visible at the same time. The shared tool tip is only
48 shown for the last item that made it visible. The position of the shared tool
49 tip is determined by the framework.
50
51 \include qquicktooltip.qdocinc customize-note
52
53 \section2 Delay and Timeout
54
55 Tool tips are typically transient in a sense that they are shown as a
56 result of a certain external event or user interaction, and they usually
57 hide after a certain timeout. It is possible to control the delay when
58 a tool tip is shown, and the timeout when it is hidden. This makes it
59 possible to implement varying strategies for showing and hiding tool tips.
60
61 For example, on touch screens, it is a common pattern to show a tool tip
62 as a result of pressing and holding down a button. The following example
63 demonstrates how to delay showing a tool tip until the press-and-hold
64 interval is reached. In this example, the tool tip hides as soon as the
65 button is released.
66
67 \snippet qtquickcontrols-tooltip-pressandhold.qml 1
68
69 With pointer devices, however, it might be desired to show a tool tip as
70 a result of hovering a button for a while. The following example presents
71 how to show a tool tip after hovering a button for a second, and hide it
72 after a timeout of five seconds.
73
74 \snippet qtquickcontrols-tooltip-hover.qml 1
75
76 \section2 Custom Tool Tips
77
78 Should one need more fine-grained control over the tool tip position, or
79 multiple simultaneous tool tip instances are needed, it is also possible
80 to create local tool tip instances. This way, it is possible to
81 \l {Customizing ToolTip}{customize} the tool tip, and the whole \l Popup
82 API is available. The following example presents a tool tip that presents
83 the value of a slider when the handle is dragged.
84
85 \image qtquickcontrols-tooltip-slider.png
86
87 \snippet qtquickcontrols-tooltip-slider.qml 1
88
89 \sa {Customizing ToolTip}, {Popup Controls},
90 {QtQuick.Controls::Popup::closePolicy}{closePolicy}
91*/
92
94{
95 Q_DECLARE_PUBLIC(QQuickToolTip)
96
97public:
98 void startDelay();
99 void stopDelay();
100
103
105
106 Qt::WindowFlags popupWindowType() const override;
107
108 QPalette defaultPalette() const override { return QQuickTheme::palette(QQuickTheme::ToolTip); }
109
110 int delay = 0;
111 int timeout = -1;
115};
116
117void QQuickToolTipPrivate::startDelay()
118{
119 Q_Q(QQuickToolTip);
120 if (delay > 0)
121 delayTimer.start(delay, q);
122}
123
125{
126 delayTimer.stop();
127}
128
130{
131 Q_Q(QQuickToolTip);
132 if (timeout > 0)
133 timeoutTimer.start(timeout, q);
134}
135
137{
138 timeoutTimer.stop();
139}
140
142{
143 QQuickPopupPrivate::opened();
145}
146
148{
149 return Qt::ToolTip;
150}
151
152QQuickToolTip::QQuickToolTip(QQuickItem *parent)
153 : QQuickPopup(*(new QQuickToolTipPrivate), parent)
154{
155 Q_D(QQuickToolTip);
156 d->allowVerticalFlip = true;
157 d->allowHorizontalFlip = true;
158 d->popupItem->setHoverEnabled(false); // QTBUG-63644
159}
160
161/*!
162 \qmlproperty string QtQuick.Controls::ToolTip::text
163
164 This property holds the text shown on the tool tip.
165*/
166QString QQuickToolTip::text() const
167{
168 Q_D(const QQuickToolTip);
169 return d->text;
170}
171
172void QQuickToolTip::setText(const QString &text)
173{
174 Q_D(QQuickToolTip);
175 if (d->text == text)
176 return;
177
178 d->text = text;
179 maybeSetAccessibleName(text);
180 emit textChanged();
181}
182
183/*!
184 \qmlproperty int QtQuick.Controls::ToolTip::delay
185
186 This property holds the delay (milliseconds) after which the tool tip is
187 shown. A tooltip with a negative delay is shown immediately. The default
188 value is \c 0.
189
190 \sa {Delay and Timeout}
191*/
192int QQuickToolTip::delay() const
193{
194 Q_D(const QQuickToolTip);
195 return d->delay;
196}
197
198void QQuickToolTip::setDelay(int delay)
199{
200 Q_D(QQuickToolTip);
201 if (d->delay == delay)
202 return;
203
204 d->delay = delay;
205 emit delayChanged();
206}
207
208/*!
209 \qmlproperty int QtQuick.Controls::ToolTip::timeout
210
211 This property holds the timeout (milliseconds) after which the tool tip is
212 hidden. A tooltip with a negative timeout does not hide automatically. The
213 default value is \c -1.
214
215 \sa {Delay and Timeout}
216*/
217int QQuickToolTip::timeout() const
218{
219 Q_D(const QQuickToolTip);
220 return d->timeout;
221}
222
223void QQuickToolTip::setTimeout(int timeout)
224{
225 Q_D(QQuickToolTip);
226 if (d->timeout == timeout)
227 return;
228
229 d->timeout = timeout;
230
231 if (timeout <= 0)
232 d->stopTimeout();
233 else if (isOpened())
234 d->startTimeout();
235
236 emit timeoutChanged();
237}
238
239void QQuickToolTip::setVisible(bool visible)
240{
241 Q_D(QQuickToolTip);
242 if (visible) {
243 if (!d->visible) {
244 // We are being made visible, and we weren't before.
245 if (d->delay > 0) {
246 d->startDelay();
247 return;
248 }
249 }
250 } else {
251 d->stopDelay();
252 }
253 QQuickPopup::setVisible(visible);
254}
255
256QQuickToolTipAttached *QQuickToolTip::qmlAttachedProperties(QObject *object)
257{
258 QQuickItem *item = qobject_cast<QQuickItem *>(object);
259 if (!item)
260 qmlWarning(object) << "ToolTip attached property must be attached to an object deriving from Item";
261
262 return new QQuickToolTipAttached(object);
263}
264
265/*!
266 \since QtQuick.Controls 2.5 (Qt 5.12)
267 \qmlmethod void QtQuick.Controls::ToolTip::show(string text, int timeout)
268
269 This method shows the \a text as a tooltip, which times out in
270 \a timeout (milliseconds).
271*/
272void QQuickToolTip::show(const QString &text, int ms)
273{
274 if (ms >= 0)
275 setTimeout(ms);
276 setText(text);
277 open();
278}
279
280/*!
281 \since QtQuick.Controls 2.5 (Qt 5.12)
282 \qmlmethod void QtQuick.Controls::ToolTip::hide()
283
284 This method hides the tooltip.
285*/
286void QQuickToolTip::hide()
287{
288 close();
289}
290
291QFont QQuickToolTip::defaultFont() const
292{
293 return QQuickTheme::font(QQuickTheme::ToolTip);
294}
295
296void QQuickToolTip::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
297{
298 Q_D(QQuickToolTip);
299 QQuickPopup::itemChange(change, data);
300 if (change == QQuickItem::ItemVisibleHasChanged) {
301 if (!data.boolValue)
302 d->stopTimeout();
303
304 QQuickToolTipAttached *attached = qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(d->parentItem, false));
305 if (attached)
306 emit attached->visibleChanged();
307 }
308}
309
310void QQuickToolTip::timerEvent(QTimerEvent *event)
311{
312 Q_D(QQuickToolTip);
313 if (event->timerId() == d->timeoutTimer.timerId()) {
314 d->stopTimeout();
315 QQuickPopup::setVisible(false);
316 return;
317 }
318 if (event->timerId() == d->delayTimer.timerId()) {
319 d->stopDelay();
320 QQuickPopup::setVisible(true);
321 return;
322 }
323 QQuickPopup::timerEvent(event);
324}
325
326#if QT_CONFIG(accessibility)
327QAccessible::Role QQuickToolTip::accessibleRole() const
328{
329 return QAccessible::ToolTip;
330}
331
332void QQuickToolTip::accessibilityActiveChanged(bool active)
333{
334 Q_D(QQuickToolTip);
335 QQuickPopup::accessibilityActiveChanged(active);
336
337 if (active)
338 maybeSetAccessibleName(d->text);
339}
340#endif
341
343{
344 Q_DECLARE_PUBLIC(QQuickToolTipAttached)
345
346public:
348
349 int delay = 0;
350 int timeout = -1;
352};
353
354QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
355{
356 QQmlEngine *engine = qmlEngine(parent);
357 if (!engine)
358 return nullptr;
359
360 static const char *name = "_q_QQuickToolTip";
361
362 QQuickToolTip *tip = engine->property(name).value<QQuickToolTip *>();
363 if (!tip && create) {
364 // TODO: a cleaner way to create the instance? QQml(Meta)Type?
365 QQmlComponent component(engine);
366 component.setData("import QtQuick.Controls; ToolTip { }", QUrl());
367
368 QObject *object = component.create();
369 if (object)
370 object->setParent(engine);
371
372 tip = qobject_cast<QQuickToolTip *>(object);
373 if (!tip)
374 delete object;
375 else
376 engine->setProperty(name, QVariant::fromValue(object));
377 }
378 return tip;
379}
380
381QQuickToolTipAttached::QQuickToolTipAttached(QObject *parent)
382 : QObject(*(new QQuickToolTipAttachedPrivate), parent)
383{
384}
385
386/*!
387 \qmlattachedproperty string QtQuick.Controls::ToolTip::text
388
389 This attached property holds the text of the shared tool tip.
390 The property can be attached to any item.
391
392 \sa {Attached Tool Tips}
393*/
394QString QQuickToolTipAttached::text() const
395{
396 Q_D(const QQuickToolTipAttached);
397 return d->text;
398}
399
400void QQuickToolTipAttached::setText(const QString &text)
401{
402 Q_D(QQuickToolTipAttached);
403 if (d->text == text)
404 return;
405
406 d->text = text;
407 emit textChanged();
408
409 if (isVisible())
410 d->instance(true)->setText(text);
411}
412
413/*!
414 \qmlattachedproperty int QtQuick.Controls::ToolTip::delay
415
416 This attached property holds the delay (milliseconds) of the shared tool tip.
417 The property can be attached to any item.
418
419 \sa {Attached Tool Tips}, {Delay and Timeout}
420*/
421int QQuickToolTipAttached::delay() const
422{
423 Q_D(const QQuickToolTipAttached);
424 return d->delay;
425}
426
427void QQuickToolTipAttached::setDelay(int delay)
428{
429 Q_D(QQuickToolTipAttached);
430 if (d->delay == delay)
431 return;
432
433 d->delay = delay;
434 emit delayChanged();
435
436 if (isVisible())
437 d->instance(true)->setDelay(delay);
438}
439
440/*!
441 \qmlattachedproperty int QtQuick.Controls::ToolTip::timeout
442
443 This attached property holds the timeout (milliseconds) of the shared tool tip.
444 The property can be attached to any item.
445
446 \sa {Attached Tool Tips}, {Delay and Timeout}
447*/
448int QQuickToolTipAttached::timeout() const
449{
450 Q_D(const QQuickToolTipAttached);
451 return d->timeout;
452}
453
454void QQuickToolTipAttached::setTimeout(int timeout)
455{
456 Q_D(QQuickToolTipAttached);
457 if (d->timeout == timeout)
458 return;
459
460 d->timeout = timeout;
461 emit timeoutChanged();
462
463 if (isVisible())
464 d->instance(true)->setTimeout(timeout);
465}
466
467/*!
468 \qmlattachedproperty bool QtQuick.Controls::ToolTip::visible
469
470 This attached property holds whether the shared tool tip is visible.
471 The property can be attached to any item.
472
473 \sa {Attached Tool Tips}
474*/
475bool QQuickToolTipAttached::isVisible() const
476{
477 Q_D(const QQuickToolTipAttached);
478 QQuickToolTip *tip = d->instance(false);
479 if (!tip)
480 return false;
481
482 return tip->isVisible() && tip->parentItem() == parent();
483}
484
485void QQuickToolTipAttached::setVisible(bool visible)
486{
487 Q_D(QQuickToolTipAttached);
488 if (visible)
489 show(d->text);
490 else
491 hide();
492}
493
494/*!
495 \qmlattachedproperty ToolTip QtQuick.Controls::ToolTip::toolTip
496
497 This attached property holds the shared tool tip instance. The property
498 can be attached to any item.
499
500 \sa {Attached Tool Tips}
501*/
502QQuickToolTip *QQuickToolTipAttached::toolTip() const
503{
504 Q_D(const QQuickToolTipAttached);
505 return d->instance(true);
506}
507
508/*!
509 \qmlattachedmethod void QtQuick.Controls::ToolTip::show(string text, int timeout = -1)
510
511 This attached method shows the shared tooltip with \a text and \a timeout (milliseconds).
512 The method can be attached to any item.
513
514 \sa {Attached Tool Tips}
515*/
516void QQuickToolTipAttached::show(const QString &text, int ms)
517{
518 Q_D(QQuickToolTipAttached);
519 QQuickToolTip *tip = d->instance(true);
520 if (!tip)
521 return;
522
523 tip->resetWidth();
524 tip->resetHeight();
525 tip->setParentItem(qobject_cast<QQuickItem *>(parent()));
526 tip->setDelay(d->delay);
527 tip->setTimeout(ms >= 0 ? ms : d->timeout);
528 tip->show(text);
529}
530
531/*!
532 \qmlattachedmethod void QtQuick.Controls::ToolTip::hide()
533
534 This attached method hides the shared tooltip. The method can be attached to any item.
535
536 \sa {Attached Tool Tips}
537*/
538void QQuickToolTipAttached::hide()
539{
540 Q_D(QQuickToolTipAttached);
541 QQuickToolTip *tip = d->instance(false);
542 if (!tip)
543 return;
544 // check the parent item to prevent unexpectedly closing tooltip by new created invisible tooltip
545 if (parent() == tip->parentItem())
546 tip->close();
547}
548
549QT_END_NAMESPACE
550
551#include "moc_qquicktooltip_p.cpp"
Provides tool tips for any control.
QPalette defaultPalette() const override
void opened() override
Qt::WindowFlags popupWindowType() const override