aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2/qquicktooltip.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2/qquicktooltip.cpp')
-rw-r--r--src/quicktemplates2/qquicktooltip.cpp585
1 files changed, 585 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp
new file mode 100644
index 0000000000..a6ad371a5e
--- /dev/null
+++ b/src/quicktemplates2/qquicktooltip.cpp
@@ -0,0 +1,585 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicktooltip_p.h"
+#include "qquickpopup_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickcontrol_p_p.h"
+#include "qquicktooltippopupitem_p_p.h"
+
+#include <QtCore/qbasictimer.h>
+#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQuick/qquickwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ToolTip
+ \inherits Popup
+//! \instantiates QQuickToolTip
+ \inqmlmodule QtQuick.Controls
+ \since 5.7
+ \ingroup qtquickcontrols2-popups
+ \brief Provides tool tips for any control.
+
+ A tool tip is a short piece of text that informs the user of a control's
+ function. It is typically placed above or below the parent control. The
+ tip text can be any \l{Rich Text Processing}{rich text} formatted string.
+
+ \image qtquickcontrols2-tooltip.png
+
+ \section2 Attached Tool Tips
+
+ The most straight-forward way to setup tool tips for controls is to
+ specify \l text and \l {visible}{visibility} via attached properties.
+ The following example illustrates this approach:
+
+ \snippet qtquickcontrols2-tooltip.qml 1
+
+ Under normal circumstances, there is only one tool tip visible at a time.
+ In order to save resources, all items that use the ToolTip attached property
+ share the same visual tool tip label instance. Even though the visuals are
+ shared, \c text, \c timeout and \c delay are stored individually for each item
+ that uses the respective attached property. However, multiple items cannot
+ make the shared tool tip visible at the same time. The shared tool tip is only
+ shown for the last item that made it visible. The position of the shared tool
+ tip is determined by the framework.
+
+ \section2 Delay and Timeout
+
+ Tool tips are typically transient in a sense that they are shown as a
+ result of a certain external event or user interaction, and they usually
+ hide after a certain timeout. It is possible to control the delay when
+ a tool tip is shown, and the timeout when it is hidden. This makes it
+ possible to implement varying strategies for showing and hiding tool tips.
+
+ For example, on touch screens, it is a common pattern to show a tool tip
+ as a result of pressing and holding down a button. The following example
+ demonstrates how to delay showing a tool tip until the press-and-hold
+ interval is reached. In this example, the tool tip hides as soon as the
+ button is released.
+
+ \snippet qtquickcontrols2-tooltip-pressandhold.qml 1
+
+ With pointer devices, however, it might be desired to show a tool tip as
+ a result of hovering a button for a while. The following example presents
+ how to show a tool tip after hovering a button for a second, and hide it
+ after a timeout of five seconds.
+
+ \snippet qtquickcontrols2-tooltip-hover.qml 1
+
+ \section2 Custom Tool Tips
+
+ Should one need more fine-grained control over the tool tip position, or
+ multiple simultaneous tool tip instances are needed, it is also possible
+ to create local tool tip instances. This way, it is possible to
+ \l {Customizing ToolTip}{customize} the tool tip, and the whole \l Popup
+ API is available. The following example presents a tool tip that presents
+ the value of a slider when the handle is dragged.
+
+ \image qtquickcontrols2-tooltip-slider.png
+
+ \snippet qtquickcontrols2-tooltip-slider.qml 1
+
+ \sa {Customizing ToolTip}, {Popup Controls}
+*/
+
+class QQuickToolTipPrivate : public QQuickPopupPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickToolTip)
+
+public:
+ void init() override;
+
+ void startDelay();
+ void stopDelay();
+
+ void startTimeout();
+ void stopTimeout();
+
+ void opened() override;
+
+ QPalette defaultPalette() const override { return QQuickTheme::palette(QQuickTheme::ToolTip); }
+
+ int delay = 0;
+ int timeout = -1;
+ QString text;
+ QBasicTimer delayTimer;
+ QBasicTimer timeoutTimer;
+};
+
+void QQuickToolTipPrivate::init()
+{
+ Q_Q(QQuickToolTip);
+ popupItem = new QQuickToolTipPopupItem(q);
+ popupItem->setVisible(false);
+ q->setParentItem(qobject_cast<QQuickItem *>(parent));
+ connectToPopupItem();
+
+ allowVerticalFlip = true;
+ allowHorizontalFlip = true;
+ popupItem->setHoverEnabled(false); // QTBUG-63644
+}
+
+void QQuickToolTipPrivate::startDelay()
+{
+ Q_Q(QQuickToolTip);
+ if (delay > 0)
+ delayTimer.start(delay, q);
+}
+
+void QQuickToolTipPrivate::stopDelay()
+{
+ delayTimer.stop();
+}
+
+void QQuickToolTipPrivate::startTimeout()
+{
+ Q_Q(QQuickToolTip);
+ if (timeout > 0)
+ timeoutTimer.start(timeout, q);
+}
+
+void QQuickToolTipPrivate::stopTimeout()
+{
+ timeoutTimer.stop();
+}
+
+void QQuickToolTipPrivate::opened()
+{
+ QQuickPopupPrivate::opened();
+ startTimeout();
+}
+
+QQuickToolTip::QQuickToolTip(QQuickItem *parent)
+ : QQuickPopup(*(new QQuickToolTipPrivate), parent)
+{
+ Q_D(QQuickToolTip);
+ d->init();
+}
+
+/*!
+ \qmlproperty string QtQuick.Controls::ToolTip::text
+
+ This property holds the text shown on the tool tip.
+*/
+QString QQuickToolTip::text() const
+{
+ Q_D(const QQuickToolTip);
+ return d->text;
+}
+
+void QQuickToolTip::setText(const QString &text)
+{
+ Q_D(QQuickToolTip);
+ if (d->text == text)
+ return;
+
+ d->text = text;
+ maybeSetAccessibleName(text);
+ emit textChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick.Controls::ToolTip::delay
+
+ This property holds the delay (milliseconds) after which the tool tip is
+ shown. A tooltip with a negative delay is shown immediately. The default
+ value is \c 0.
+
+ \sa {Delay and Timeout}
+*/
+int QQuickToolTip::delay() const
+{
+ Q_D(const QQuickToolTip);
+ return d->delay;
+}
+
+void QQuickToolTip::setDelay(int delay)
+{
+ Q_D(QQuickToolTip);
+ if (d->delay == delay)
+ return;
+
+ d->delay = delay;
+ emit delayChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick.Controls::ToolTip::timeout
+
+ This property holds the timeout (milliseconds) after which the tool tip is
+ hidden. A tooltip with a negative timeout does not hide automatically. The
+ default value is \c -1.
+
+ \sa {Delay and Timeout}
+*/
+int QQuickToolTip::timeout() const
+{
+ Q_D(const QQuickToolTip);
+ return d->timeout;
+}
+
+void QQuickToolTip::setTimeout(int timeout)
+{
+ Q_D(QQuickToolTip);
+ if (d->timeout == timeout)
+ return;
+
+ d->timeout = timeout;
+
+ if (timeout <= 0)
+ d->stopTimeout();
+ else if (isOpened())
+ d->startTimeout();
+
+ emit timeoutChanged();
+}
+
+void QQuickToolTip::setVisible(bool visible)
+{
+ Q_D(QQuickToolTip);
+ if (visible) {
+ if (!d->visible) {
+ // We are being made visible, and we weren't before.
+ if (d->delay > 0) {
+ d->startDelay();
+ return;
+ }
+ }
+ } else {
+ d->stopDelay();
+ }
+ QQuickPopup::setVisible(visible);
+}
+
+QQuickToolTipAttached *QQuickToolTip::qmlAttachedProperties(QObject *object)
+{
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
+ if (!item)
+ qmlWarning(object) << "ToolTip must be attached to an Item";
+
+ return new QQuickToolTipAttached(object);
+}
+
+/*!
+ \since QtQuick.Controls 2.5 (Qt 5.12)
+ \qmlmethod void QtQuick.Controls::ToolTip::show(string text, int timeout)
+
+ This method shows the \a text as a tooltip, which times out in
+ \a timeout (milliseconds).
+*/
+void QQuickToolTip::show(const QString &text, int ms)
+{
+ if (ms >= 0)
+ setTimeout(ms);
+ setText(text);
+ open();
+}
+
+/*!
+ \since QtQuick.Controls 2.5 (Qt 5.12)
+ \qmlmethod void QtQuick.Controls::ToolTip::hide()
+
+ This method hides the tooltip.
+*/
+void QQuickToolTip::hide()
+{
+ close();
+}
+
+QFont QQuickToolTip::defaultFont() const
+{
+ return QQuickTheme::font(QQuickTheme::ToolTip);
+}
+
+void QQuickToolTip::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ Q_D(QQuickToolTip);
+ QQuickPopup::itemChange(change, data);
+ if (change == QQuickItem::ItemVisibleHasChanged) {
+ if (!data.boolValue)
+ d->stopTimeout();
+
+ QQuickToolTipAttached *attached = qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(d->parentItem, false));
+ if (attached)
+ emit attached->visibleChanged();
+ }
+}
+
+void QQuickToolTip::timerEvent(QTimerEvent *event)
+{
+ Q_D(QQuickToolTip);
+ if (event->timerId() == d->timeoutTimer.timerId()) {
+ d->stopTimeout();
+ QQuickPopup::setVisible(false);
+ return;
+ }
+ if (event->timerId() == d->delayTimer.timerId()) {
+ d->stopDelay();
+ QQuickPopup::setVisible(true);
+ return;
+ }
+ QQuickPopup::timerEvent(event);
+}
+
+#if QT_CONFIG(accessibility)
+QAccessible::Role QQuickToolTip::accessibleRole() const
+{
+ return QAccessible::ToolTip;
+}
+
+void QQuickToolTip::accessibilityActiveChanged(bool active)
+{
+ Q_D(QQuickToolTip);
+ QQuickPopup::accessibilityActiveChanged(active);
+
+ if (active)
+ maybeSetAccessibleName(d->text);
+}
+#endif
+
+class QQuickToolTipAttachedPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickToolTipAttached)
+
+public:
+ QQuickToolTip *instance(bool create) const;
+
+ int delay = 0;
+ int timeout = -1;
+ QString text;
+};
+
+QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
+{
+ QQmlEngine *engine = qmlEngine(parent);
+ if (!engine)
+ return nullptr;
+
+ static const char *name = "_q_QQuickToolTip";
+
+ QQuickToolTip *tip = engine->property(name).value<QQuickToolTip *>();
+ if (!tip && create) {
+ // TODO: a cleaner way to create the instance? QQml(Meta)Type?
+ QQmlComponent component(engine);
+ component.setData("import QtQuick.Controls; ToolTip { }", QUrl());
+
+ QObject *object = component.create();
+ if (object)
+ object->setParent(engine);
+
+ tip = qobject_cast<QQuickToolTip *>(object);
+ if (!tip)
+ delete object;
+ else
+ engine->setProperty(name, QVariant::fromValue(object));
+ }
+ return tip;
+}
+
+QQuickToolTipAttached::QQuickToolTipAttached(QObject *parent)
+ : QObject(*(new QQuickToolTipAttachedPrivate), parent)
+{
+}
+
+/*!
+ \qmlattachedproperty string QtQuick.Controls::ToolTip::text
+
+ This attached property holds the text of the shared tool tip.
+ The property can be attached to any item.
+
+ \sa {Attached Tool Tips}
+*/
+QString QQuickToolTipAttached::text() const
+{
+ Q_D(const QQuickToolTipAttached);
+ return d->text;
+}
+
+void QQuickToolTipAttached::setText(const QString &text)
+{
+ Q_D(QQuickToolTipAttached);
+ if (d->text == text)
+ return;
+
+ d->text = text;
+ emit textChanged();
+
+ if (isVisible())
+ d->instance(true)->setText(text);
+}
+
+/*!
+ \qmlattachedproperty int QtQuick.Controls::ToolTip::delay
+
+ This attached property holds the delay (milliseconds) of the shared tool tip.
+ The property can be attached to any item.
+
+ \sa {Attached Tool Tips}, {Delay and Timeout}
+*/
+int QQuickToolTipAttached::delay() const
+{
+ Q_D(const QQuickToolTipAttached);
+ return d->delay;
+}
+
+void QQuickToolTipAttached::setDelay(int delay)
+{
+ Q_D(QQuickToolTipAttached);
+ if (d->delay == delay)
+ return;
+
+ d->delay = delay;
+ emit delayChanged();
+
+ if (isVisible())
+ d->instance(true)->setDelay(delay);
+}
+
+/*!
+ \qmlattachedproperty int QtQuick.Controls::ToolTip::timeout
+
+ This attached property holds the timeout (milliseconds) of the shared tool tip.
+ The property can be attached to any item.
+
+ \sa {Attached Tool Tips}, {Delay and Timeout}
+*/
+int QQuickToolTipAttached::timeout() const
+{
+ Q_D(const QQuickToolTipAttached);
+ return d->timeout;
+}
+
+void QQuickToolTipAttached::setTimeout(int timeout)
+{
+ Q_D(QQuickToolTipAttached);
+ if (d->timeout == timeout)
+ return;
+
+ d->timeout = timeout;
+ emit timeoutChanged();
+
+ if (isVisible())
+ d->instance(true)->setTimeout(timeout);
+}
+
+/*!
+ \qmlattachedproperty bool QtQuick.Controls::ToolTip::visible
+
+ This attached property holds whether the shared tool tip is visible.
+ The property can be attached to any item.
+
+ \sa {Attached Tool Tips}
+*/
+bool QQuickToolTipAttached::isVisible() const
+{
+ Q_D(const QQuickToolTipAttached);
+ QQuickToolTip *tip = d->instance(false);
+ if (!tip)
+ return false;
+
+ return tip->isVisible() && tip->parentItem() == parent();
+}
+
+void QQuickToolTipAttached::setVisible(bool visible)
+{
+ Q_D(QQuickToolTipAttached);
+ if (visible)
+ show(d->text);
+ else
+ hide();
+}
+
+/*!
+ \qmlattachedproperty ToolTip QtQuick.Controls::ToolTip::toolTip
+
+ This attached property holds the shared tool tip instance. The property
+ can be attached to any item.
+
+ \sa {Attached Tool Tips}
+*/
+QQuickToolTip *QQuickToolTipAttached::toolTip() const
+{
+ Q_D(const QQuickToolTipAttached);
+ return d->instance(true);
+}
+
+/*!
+ \qmlattachedmethod void QtQuick.Controls::ToolTip::show(string text, int timeout = -1)
+
+ This attached method shows the shared tooltip with \a text and \a timeout (milliseconds).
+ The method can be attached to any item.
+
+ \sa {Attached Tool Tips}
+*/
+void QQuickToolTipAttached::show(const QString &text, int ms)
+{
+ Q_D(QQuickToolTipAttached);
+ QQuickToolTip *tip = d->instance(true);
+ if (!tip)
+ return;
+
+ tip->resetWidth();
+ tip->resetHeight();
+ tip->setParentItem(qobject_cast<QQuickItem *>(parent()));
+ tip->setDelay(d->delay);
+ tip->setTimeout(ms >= 0 ? ms : d->timeout);
+ tip->show(text);
+}
+
+/*!
+ \qmlattachedmethod void QtQuick.Controls::ToolTip::hide()
+
+ This attached method hides the shared tooltip. The method can be attached to any item.
+
+ \sa {Attached Tool Tips}
+*/
+void QQuickToolTipAttached::hide()
+{
+ Q_D(QQuickToolTipAttached);
+ QQuickToolTip *tip = d->instance(false);
+ if (!tip)
+ return;
+ // check the parent item to prevent unexpectedly closing tooltip by new created invisible tooltip
+ if (parent() == tip->parentItem())
+ tip->close();
+}
+
+QT_END_NAMESPACE