blob: ecb2568edef45b532e8b0304f0c4d8372efc35da [file] [log] [blame]
/****************************************************************************
**
** 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 "qquickpopup_p.h"
#include "qquickpopup_p_p.h"
#include "qquickpopupanchors_p.h"
#include "qquickpopupitem_p_p.h"
#include "qquickpopuppositioner_p_p.h"
#include "qquickapplicationwindow_p.h"
#include "qquickoverlay_p_p.h"
#include "qquickcontrol_p_p.h"
#include "qquickdialog_p.h"
#include <QtQml/qqmlinfo.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquicktransition_p.h>
#include <QtQuick/private/qquickitem_p.h>
QT_BEGIN_NAMESPACE
/*!
\qmltype Popup
\inherits QtObject
//! \instantiates QQuickPopup
\inqmlmodule QtQuick.Controls
\since 5.7
\ingroup qtquickcontrols2-popups
\ingroup qtquickcontrols2-focusscopes
\brief Base type of popup-like user interface controls.
Popup is the base type of popup-like user interface controls. It can be
used with \l Window or \l ApplicationWindow.
\qml
import QtQuick.Window 2.2
import QtQuick.Controls 2.12
ApplicationWindow {
id: window
width: 400
height: 400
visible: true
Button {
text: "Open"
onClicked: popup.open()
}
Popup {
id: popup
x: 100
y: 100
width: 200
height: 300
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
}
}
\endqml
In order to ensure that a popup is displayed above other items in the
scene, it is recommended to use ApplicationWindow. ApplicationWindow also
provides background dimming effects.
Popup does not provide a layout of its own, but requires you to position
its contents, for instance by creating a \l RowLayout or a \l ColumnLayout.
Items declared as children of a Popup are automatically parented to the
Popups's \l contentItem. Items created dynamically need to be explicitly
parented to the contentItem.
\section1 Popup Layout
The following diagram illustrates the layout of a popup within a window:
\image qtquickcontrols2-popup.png
The \l implicitWidth and \l implicitHeight of a popup are typically based
on the implicit sizes of the background and the content item plus any insets
and paddings. These properties determine how large the popup will be when no
explicit \l width or \l height is specified.
The geometry of the \l contentItem is determined by the padding. The following
example reserves 10px padding between the boundaries of the popup and its content:
\code
Popup {
padding: 10
contentItem: Text {
text: "Content"
}
}
\endcode
The \l background item fills the entire width and height of the popup,
unless insets or an explicit size have been given for it.
Negative insets can be used to make the background larger than the popup.
The following example uses negative insets to place a shadow outside the
popup's boundaries:
\code
Popup {
topInset: -2
leftInset: -2
rightInset: -6
bottomInset: -6
background: BorderImage {
source: ":/images/shadowed-background.png"
}
}
\endcode
\section1 Popup Sizing
If only a single item is used within a Popup, it will resize to fit the
implicit size of its contained item. This makes it particularly suitable
for use together with layouts.
\code
Popup {
ColumnLayout {
anchors.fill: parent
CheckBox { text: qsTr("E-mail") }
CheckBox { text: qsTr("Calendar") }
CheckBox { text: qsTr("Contacts") }
}
}
\endcode
Sometimes there might be two items within the popup:
\code
Popup {
SwipeView {
// ...
}
PageIndicator {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
}
}
\endcode
In this case, Popup cannot calculate a sensible implicit size. Since we're
anchoring the \l PageIndicator over the \l SwipeView, we can simply set the
content size to the view's implicit size:
\code
Popup {
contentWidth: view.implicitWidth
contentHeight: view.implicitHeight
SwipeView {
id: view
// ...
}
PageIndicator {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
}
}
\endcode
\section1 Popup Positioning
Similar to items in Qt Quick, Popup's \l x and \l y coordinates are
relative to its parent. This means that opening a popup that is a
child of a \l Button, for example, will cause the popup to be positioned
relative to the button.
\include qquickoverlay-popup-parent.qdocinc
Another way to center a popup in the window regardless of its parent item
is to use \l {anchors.centerIn}:
\snippet qtquickcontrols2-popup.qml centerIn
To ensure that the popup is positioned within the bounds of the enclosing
window, the \l margins property can be set to a non-negative value.
\sa {Popup Controls}, {Customizing Popup}, ApplicationWindow
*/
/*!
\qmlsignal void QtQuick.Controls::Popup::opened()
This signal is emitted when the popup is opened.
\sa aboutToShow()
*/
/*!
\qmlsignal void QtQuick.Controls::Popup::closed()
This signal is emitted when the popup is closed.
\sa aboutToHide()
*/
/*!
\qmlsignal void QtQuick.Controls::Popup::aboutToShow()
This signal is emitted when the popup is about to show.
\sa opened()
*/
/*!
\qmlsignal void QtQuick.Controls::Popup::aboutToHide()
This signal is emitted when the popup is about to hide.
\sa closed()
*/
const QQuickPopup::ClosePolicy QQuickPopupPrivate::DefaultClosePolicy = QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside;
QQuickPopupPrivate::QQuickPopupPrivate()
: transitionManager(this)
{
}
void QQuickPopupPrivate::init()
{
Q_Q(QQuickPopup);
popupItem = new QQuickPopupItem(q);
popupItem->setVisible(false);
q->setParentItem(qobject_cast<QQuickItem *>(parent));
QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged);
QObject::connect(popupItem, &QQuickControl::backgroundChanged, q, &QQuickPopup::backgroundChanged);
QObject::connect(popupItem, &QQuickControl::contentItemChanged, q, &QQuickPopup::contentItemChanged);
QObject::connect(popupItem, &QQuickControl::implicitContentWidthChanged, q, &QQuickPopup::implicitContentWidthChanged);
QObject::connect(popupItem, &QQuickControl::implicitContentHeightChanged, q, &QQuickPopup::implicitContentHeightChanged);
QObject::connect(popupItem, &QQuickControl::implicitBackgroundWidthChanged, q, &QQuickPopup::implicitBackgroundWidthChanged);
QObject::connect(popupItem, &QQuickControl::implicitBackgroundHeightChanged, q, &QQuickPopup::implicitBackgroundHeightChanged);
}
void QQuickPopupPrivate::closeOrReject()
{
Q_Q(QQuickPopup);
if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(q))
dialog->reject();
else
q->close();
}
bool QQuickPopupPrivate::tryClose(const QPointF &pos, QQuickPopup::ClosePolicy flags)
{
if (!interactive)
return false;
static const QQuickPopup::ClosePolicy outsideFlags = QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnReleaseOutside;
static const QQuickPopup::ClosePolicy outsideParentFlags = QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent;
const bool onOutside = closePolicy & (flags & outsideFlags);
const bool onOutsideParent = closePolicy & (flags & outsideParentFlags);
if (onOutside || onOutsideParent) {
if (!contains(pos)) {
if (!onOutsideParent || !parentItem || !parentItem->contains(parentItem->mapFromScene(pos))) {
closeOrReject();
return true;
}
}
}
return false;
}
bool QQuickPopupPrivate::contains(const QPointF &scenePos) const
{
return popupItem->contains(popupItem->mapFromScene(scenePos));
}
#if QT_CONFIG(quicktemplates2_multitouch)
bool QQuickPopupPrivate::acceptTouch(const QTouchEvent::TouchPoint &point)
{
if (point.id() == touchId)
return true;
if (touchId == -1 && point.state() != Qt::TouchPointReleased) {
touchId = point.id();
return true;
}
return false;
}
#endif
bool QQuickPopupPrivate::blockInput(QQuickItem *item, const QPointF &point) const
{
// don't block presses and releases
// a) outside a non-modal popup,
// b) to popup children/content, or
// b) outside a modal popups's background dimming
return modal && !popupItem->isAncestorOf(item) && (!dimmer || dimmer->contains(dimmer->mapFromScene(point)));
}
bool QQuickPopupPrivate::handlePress(QQuickItem *item, const QPointF &point, ulong timestamp)
{
Q_UNUSED(timestamp);
pressPoint = point;
tryClose(point, QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
return blockInput(item, point);
}
bool QQuickPopupPrivate::handleMove(QQuickItem *item, const QPointF &point, ulong timestamp)
{
Q_UNUSED(timestamp);
return blockInput(item, point);
}
bool QQuickPopupPrivate::handleRelease(QQuickItem *item, const QPointF &point, ulong timestamp)
{
Q_UNUSED(timestamp);
if (item != popupItem && !contains(pressPoint))
tryClose(point, QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
pressPoint = QPointF();
touchId = -1;
return blockInput(item, point);
}
void QQuickPopupPrivate::handleUngrab()
{
Q_Q(QQuickPopup);
QQuickOverlay *overlay = QQuickOverlay::overlay(window);
if (overlay) {
QQuickOverlayPrivate *p = QQuickOverlayPrivate::get(overlay);
if (p->mouseGrabberPopup == q)
p->mouseGrabberPopup = nullptr;
}
pressPoint = QPointF();
touchId = -1;
}
bool QQuickPopupPrivate::handleMouseEvent(QQuickItem *item, QMouseEvent *event)
{
switch (event->type()) {
case QEvent::MouseButtonPress:
return handlePress(item, event->windowPos(), event->timestamp());
case QEvent::MouseMove:
return handleMove(item, event->windowPos(), event->timestamp());
case QEvent::MouseButtonRelease:
return handleRelease(item, event->windowPos(), event->timestamp());
default:
Q_UNREACHABLE();
return false;
}
}
#if QT_CONFIG(quicktemplates2_multitouch)
bool QQuickPopupPrivate::handleTouchEvent(QQuickItem *item, QTouchEvent *event)
{
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
if (!acceptTouch(point))
return blockInput(item, point.pos());
switch (point.state()) {
case Qt::TouchPointPressed:
return handlePress(item, item->mapToScene(point.pos()), event->timestamp());
case Qt::TouchPointMoved:
return handleMove(item, item->mapToScene(point.pos()), event->timestamp());
case Qt::TouchPointReleased:
return handleRelease(item, item->mapToScene(point.pos()), event->timestamp());
default:
break;
}
}
break;
case QEvent::TouchCancel:
handleUngrab();
break;
default:
break;
}
return false;
}
#endif
bool QQuickPopupPrivate::prepareEnterTransition()
{
Q_Q(QQuickPopup);
if (!window) {
qmlWarning(q) << "cannot find any window to open popup in.";
return false;
}
if (transitionState == EnterTransition && transitionManager.isRunning())
return false;
if (transitionState != EnterTransition) {
popupItem->setParentItem(QQuickOverlay::overlay(window));
if (dim)
createOverlay();
showOverlay();
emit q->aboutToShow();
visible = true;
transitionState = EnterTransition;
popupItem->setVisible(true);
getPositioner()->setParentItem(parentItem);
emit q->visibleChanged();
}
return true;
}
bool QQuickPopupPrivate::prepareExitTransition()
{
Q_Q(QQuickPopup);
if (transitionState == ExitTransition && transitionManager.isRunning())
return false;
if (transitionState != ExitTransition) {
// The setFocus(false) call below removes any active focus before we're
// able to check it in finalizeExitTransition.
hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus();
if (focus)
popupItem->setFocus(false);
transitionState = ExitTransition;
hideOverlay();
emit q->aboutToHide();
emit q->openedChanged();
}
return true;
}
void QQuickPopupPrivate::finalizeEnterTransition()
{
Q_Q(QQuickPopup);
if (focus)
popupItem->setFocus(true);
transitionState = NoTransition;
emit q->openedChanged();
emit q->opened();
}
void QQuickPopupPrivate::finalizeExitTransition()
{
Q_Q(QQuickPopup);
getPositioner()->setParentItem(nullptr);
popupItem->setParentItem(nullptr);
popupItem->setVisible(false);
destroyOverlay();
if (hadActiveFocusBeforeExitTransition && window) {
// restore focus to the next popup in chain, or to the window content if there are no other popups open
QQuickPopup *nextFocusPopup = nullptr;
if (QQuickOverlay *overlay = QQuickOverlay::overlay(window)) {
const auto stackingOrderPopups = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups();
for (auto popup : stackingOrderPopups) {
if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition) {
nextFocusPopup = popup;
break;
}
}
}
if (nextFocusPopup && nextFocusPopup->hasFocus()) {
nextFocusPopup->forceActiveFocus();
} else {
QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window);
if (applicationWindow)
applicationWindow->contentItem()->setFocus(true);
else
window->contentItem()->setFocus(true);
}
}
visible = false;
transitionState = NoTransition;
hadActiveFocusBeforeExitTransition = false;
emit q->visibleChanged();
emit q->closed();
}
QMarginsF QQuickPopupPrivate::getMargins() const
{
Q_Q(const QQuickPopup);
return QMarginsF(q->leftMargin(), q->topMargin(), q->rightMargin(), q->bottomMargin());
}
void QQuickPopupPrivate::setTopMargin(qreal value, bool reset)
{
Q_Q(QQuickPopup);
qreal oldMargin = q->topMargin();
topMargin = value;
hasTopMargin = !reset;
if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
emit q->topMarginChanged();
q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
QMarginsF(leftMargin, oldMargin, rightMargin, bottomMargin));
}
}
void QQuickPopupPrivate::setLeftMargin(qreal value, bool reset)
{
Q_Q(QQuickPopup);
qreal oldMargin = q->leftMargin();
leftMargin = value;
hasLeftMargin = !reset;
if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
emit q->leftMarginChanged();
q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
QMarginsF(oldMargin, topMargin, rightMargin, bottomMargin));
}
}
void QQuickPopupPrivate::setRightMargin(qreal value, bool reset)
{
Q_Q(QQuickPopup);
qreal oldMargin = q->rightMargin();
rightMargin = value;
hasRightMargin = !reset;
if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
emit q->rightMarginChanged();
q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
QMarginsF(leftMargin, topMargin, oldMargin, bottomMargin));
}
}
void QQuickPopupPrivate::setBottomMargin(qreal value, bool reset)
{
Q_Q(QQuickPopup);
qreal oldMargin = q->bottomMargin();
bottomMargin = value;
hasBottomMargin = !reset;
if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
emit q->bottomMarginChanged();
q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
QMarginsF(leftMargin, topMargin, rightMargin, oldMargin));
}
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlpropertygroup QtQuick.Controls::Popup::anchors
\qmlproperty Object QtQuick.Controls::Popup::anchors.centerIn
Anchors provide a way to position an item by specifying its
relationship with other items.
A common use case is to center a popup within its parent. One way to do
this is with the \l[QtQuick]{Item::}{x} and \l[QtQuick]{Item::}{y} properties. Anchors offer
a more convenient approach:
\qml
Pane {
// ...
Popup {
anchors.centerIn: parent
}
}
\endqml
It is also possible to center the popup in the window by using \l Overlay:
\snippet qtquickcontrols2-popup.qml centerIn
This makes it easy to center a popup in the window from any component.
\note Popups can only be centered within their immediate parent or
the window overlay; trying to center in other items will produce a warning.
\sa {Popup Positioning}, {QtQuick::Item::anchors}{anchors}
*/
QQuickPopupAnchors *QQuickPopupPrivate::getAnchors()
{
Q_Q(QQuickPopup);
if (!anchors)
anchors = new QQuickPopupAnchors(q);
return anchors;
}
QQuickPopupPositioner *QQuickPopupPrivate::getPositioner()
{
Q_Q(QQuickPopup);
if (!positioner)
positioner = new QQuickPopupPositioner(q);
return positioner;
}
void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
{
Q_Q(QQuickPopup);
if (window == newWindow)
return;
if (window) {
QQuickOverlay *overlay = QQuickOverlay::overlay(window);
if (overlay)
QQuickOverlayPrivate::get(overlay)->removePopup(q);
}
window = newWindow;
if (newWindow) {
QQuickOverlay *overlay = QQuickOverlay::overlay(newWindow);
if (overlay)
QQuickOverlayPrivate::get(overlay)->addPopup(q);
QQuickControlPrivate *p = QQuickControlPrivate::get(popupItem);
p->resolveFont();
p->resolvePalette();
if (QQuickApplicationWindow *appWindow = qobject_cast<QQuickApplicationWindow *>(newWindow))
p->updateLocale(appWindow->locale(), false); // explicit=false
}
emit q->windowChanged(newWindow);
if (complete && visible && window)
transitionManager.transitionEnter();
}
void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
{
Q_Q(QQuickPopup);
if (item == parentItem)
q->setParentItem(nullptr);
}
void QQuickPopupPrivate::reposition()
{
getPositioner()->reposition();
}
static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent)
{
QQuickItem *item = nullptr;
if (component) {
QQmlContext *creationContext = component->creationContext();
if (!creationContext)
creationContext = qmlContext(popup);
QQmlContext *context = new QQmlContext(creationContext, popup);
context->setContextObject(popup);
item = qobject_cast<QQuickItem*>(component->beginCreate(context));
}
// when there is no overlay component available (with plain QQuickWindow),
// use a plain QQuickItem as a fallback to block hover events
if (!item && popup->isModal())
item = new QQuickItem;
if (item) {
item->setOpacity(popup->isVisible() ? 1.0 : 0.0);
item->setParentItem(parent);
item->stackBefore(popup->popupItem());
item->setZ(popup->z());
if (popup->isModal()) {
item->setAcceptedMouseButtons(Qt::AllButtons);
#if QT_CONFIG(cursor)
item->setCursor(Qt::ArrowCursor);
#endif
#if QT_CONFIG(quicktemplates2_hover)
// TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
item->setAcceptHoverEvents(true);
// item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
// connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents);
#endif
}
if (component)
component->completeCreate();
}
return item;
}
void QQuickPopupPrivate::createOverlay()
{
Q_Q(QQuickPopup);
QQuickOverlay *overlay = QQuickOverlay::overlay(window);
if (!overlay)
return;
QQmlComponent *component = nullptr;
QQuickOverlayAttached *overlayAttached = qobject_cast<QQuickOverlayAttached *>(qmlAttachedPropertiesObject<QQuickOverlay>(q, false));
if (overlayAttached)
component = modal ? overlayAttached->modal() : overlayAttached->modeless();
if (!component)
component = modal ? overlay->modal() : overlay->modeless();
if (!dimmer)
dimmer = createDimmer(component, q, overlay);
resizeOverlay();
}
void QQuickPopupPrivate::destroyOverlay()
{
if (dimmer) {
dimmer->setParentItem(nullptr);
dimmer->deleteLater();
dimmer = nullptr;
}
}
void QQuickPopupPrivate::toggleOverlay()
{
destroyOverlay();
if (dim)
createOverlay();
}
void QQuickPopupPrivate::showOverlay()
{
// use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
if (dim && dimmer)
QQmlProperty::write(dimmer, QStringLiteral("opacity"), 1.0);
}
void QQuickPopupPrivate::hideOverlay()
{
// use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
if (dim && dimmer)
QQmlProperty::write(dimmer, QStringLiteral("opacity"), 0.0);
}
void QQuickPopupPrivate::resizeOverlay()
{
if (!dimmer)
return;
qreal w = window ? window->width() : 0;
qreal h = window ? window->height() : 0;
dimmer->setSize(QSizeF(w, h));
}
QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup)
: popup(popup)
{
}
void QQuickPopupTransitionManager::transitionEnter()
{
if (popup->transitionState == QQuickPopupPrivate::ExitTransition)
cancel();
if (!popup->prepareEnterTransition())
return;
if (popup->window)
transition(popup->enterActions, popup->enter, popup->q_func());
else
finished();
}
void QQuickPopupTransitionManager::transitionExit()
{
if (!popup->prepareExitTransition())
return;
if (popup->window)
transition(popup->exitActions, popup->exit, popup->q_func());
else
finished();
}
void QQuickPopupTransitionManager::finished()
{
if (popup->transitionState == QQuickPopupPrivate::EnterTransition)
popup->finalizeEnterTransition();
else if (popup->transitionState == QQuickPopupPrivate::ExitTransition)
popup->finalizeExitTransition();
}
QQuickPopup::QQuickPopup(QObject *parent)
: QObject(*(new QQuickPopupPrivate), parent)
{
Q_D(QQuickPopup);
d->init();
}
QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent)
: QObject(dd, parent)
{
Q_D(QQuickPopup);
d->init();
}
QQuickPopup::~QQuickPopup()
{
Q_D(QQuickPopup);
setParentItem(nullptr);
d->popupItem->ungrabShortcut();
delete d->popupItem;
d->popupItem = nullptr;
delete d->positioner;
d->positioner = nullptr;
}
/*!
\qmlmethod void QtQuick.Controls::Popup::open()
Opens the popup.
\sa visible
*/
void QQuickPopup::open()
{
setVisible(true);
}
/*!
\qmlmethod void QtQuick.Controls::Popup::close()
Closes the popup.
\sa visible
*/
void QQuickPopup::close()
{
setVisible(false);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::x
This property holds the x-coordinate of the popup.
\sa y, z
*/
qreal QQuickPopup::x() const
{
Q_D(const QQuickPopup);
return d->effectiveX;
}
void QQuickPopup::setX(qreal x)
{
Q_D(QQuickPopup);
setPosition(QPointF(x, d->y));
}
/*!
\qmlproperty real QtQuick.Controls::Popup::y
This property holds the y-coordinate of the popup.
\sa x, z
*/
qreal QQuickPopup::y() const
{
Q_D(const QQuickPopup);
return d->effectiveY;
}
void QQuickPopup::setY(qreal y)
{
Q_D(QQuickPopup);
setPosition(QPointF(d->x, y));
}
QPointF QQuickPopup::position() const
{
Q_D(const QQuickPopup);
return QPointF(d->effectiveX, d->effectiveY);
}
void QQuickPopup::setPosition(const QPointF &pos)
{
Q_D(QQuickPopup);
const bool xChange = !qFuzzyCompare(d->x, pos.x());
const bool yChange = !qFuzzyCompare(d->y, pos.y());
if (!xChange && !yChange)
return;
d->x = pos.x();
d->y = pos.y();
if (d->popupItem->isVisible()) {
d->reposition();
} else {
if (xChange)
emit xChanged();
if (yChange)
emit yChanged();
}
}
/*!
\qmlproperty real QtQuick.Controls::Popup::z
This property holds the z-value of the popup. Z-value determines
the stacking order of popups.
If two visible popups have the same z-value, the last one that
was opened will be on top.
The default z-value is \c 0.
\sa x, y
*/
qreal QQuickPopup::z() const
{
Q_D(const QQuickPopup);
return d->popupItem->z();
}
void QQuickPopup::setZ(qreal z)
{
Q_D(QQuickPopup);
if (qFuzzyCompare(z, d->popupItem->z()))
return;
d->popupItem->setZ(z);
emit zChanged();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::width
This property holds the width of the popup.
*/
qreal QQuickPopup::width() const
{
Q_D(const QQuickPopup);
return d->popupItem->width();
}
void QQuickPopup::setWidth(qreal width)
{
Q_D(QQuickPopup);
d->hasWidth = true;
d->popupItem->setWidth(width);
}
void QQuickPopup::resetWidth()
{
Q_D(QQuickPopup);
if (!d->hasWidth)
return;
d->hasWidth = false;
d->popupItem->resetWidth();
if (d->popupItem->isVisible())
d->reposition();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::height
This property holds the height of the popup.
*/
qreal QQuickPopup::height() const
{
Q_D(const QQuickPopup);
return d->popupItem->height();
}
void QQuickPopup::setHeight(qreal height)
{
Q_D(QQuickPopup);
d->hasHeight = true;
d->popupItem->setHeight(height);
}
void QQuickPopup::resetHeight()
{
Q_D(QQuickPopup);
if (!d->hasHeight)
return;
d->hasHeight = false;
d->popupItem->resetHeight();
if (d->popupItem->isVisible())
d->reposition();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::implicitWidth
This property holds the implicit width of the popup.
*/
qreal QQuickPopup::implicitWidth() const
{
Q_D(const QQuickPopup);
return d->popupItem->implicitWidth();
}
void QQuickPopup::setImplicitWidth(qreal width)
{
Q_D(QQuickPopup);
d->popupItem->setImplicitWidth(width);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::implicitHeight
This property holds the implicit height of the popup.
*/
qreal QQuickPopup::implicitHeight() const
{
Q_D(const QQuickPopup);
return d->popupItem->implicitHeight();
}
void QQuickPopup::setImplicitHeight(qreal height)
{
Q_D(QQuickPopup);
d->popupItem->setImplicitHeight(height);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::contentWidth
This property holds the content width. It is used for calculating the
total implicit width of the Popup.
For more information, see \l {Popup Sizing}.
\sa contentHeight
*/
qreal QQuickPopup::contentWidth() const
{
Q_D(const QQuickPopup);
return d->popupItem->contentWidth();
}
void QQuickPopup::setContentWidth(qreal width)
{
Q_D(QQuickPopup);
d->popupItem->setContentWidth(width);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::contentHeight
This property holds the content height. It is used for calculating the
total implicit height of the Popup.
For more information, see \l {Popup Sizing}.
\sa contentWidth
*/
qreal QQuickPopup::contentHeight() const
{
Q_D(const QQuickPopup);
return d->popupItem->contentHeight();
}
void QQuickPopup::setContentHeight(qreal height)
{
Q_D(QQuickPopup);
d->popupItem->setContentHeight(height);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::availableWidth
\readonly
This property holds the width available to the \l contentItem after
deducting horizontal padding from the \l {Item::}{width} of the popup.
\sa padding, leftPadding, rightPadding
*/
qreal QQuickPopup::availableWidth() const
{
Q_D(const QQuickPopup);
return d->popupItem->availableWidth();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::availableHeight
\readonly
This property holds the height available to the \l contentItem after
deducting vertical padding from the \l {Item::}{height} of the popup.
\sa padding, topPadding, bottomPadding
*/
qreal QQuickPopup::availableHeight() const
{
Q_D(const QQuickPopup);
return d->popupItem->availableHeight();
}
/*!
\since QtQuick.Controls 2.1 (Qt 5.8)
\qmlproperty real QtQuick.Controls::Popup::spacing
This property holds the spacing.
Spacing is useful for popups that have multiple or repetitive building
blocks. For example, some styles use spacing to determine the distance
between the header, content, and footer of \l Dialog. Spacing is not
enforced by Popup, so each style may interpret it differently, and some
may ignore it altogether.
*/
qreal QQuickPopup::spacing() const
{
Q_D(const QQuickPopup);
return d->popupItem->spacing();
}
void QQuickPopup::setSpacing(qreal spacing)
{
Q_D(QQuickPopup);
d->popupItem->setSpacing(spacing);
}
void QQuickPopup::resetSpacing()
{
setSpacing(0);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::margins
This property holds the distance between the edges of the popup and the
edges of its window.
A popup with negative margins is not pushed within the bounds
of the enclosing window. The default value is \c -1.
\sa topMargin, leftMargin, rightMargin, bottomMargin, {Popup Layout}
*/
qreal QQuickPopup::margins() const
{
Q_D(const QQuickPopup);
return d->margins;
}
void QQuickPopup::setMargins(qreal margins)
{
Q_D(QQuickPopup);
if (qFuzzyCompare(d->margins, margins))
return;
QMarginsF oldMargins(leftMargin(), topMargin(), rightMargin(), bottomMargin());
d->margins = margins;
emit marginsChanged();
QMarginsF newMargins(leftMargin(), topMargin(), rightMargin(), bottomMargin());
if (!qFuzzyCompare(newMargins.top(), oldMargins.top()))
emit topMarginChanged();
if (!qFuzzyCompare(newMargins.left(), oldMargins.left()))
emit leftMarginChanged();
if (!qFuzzyCompare(newMargins.right(), oldMargins.right()))
emit rightMarginChanged();
if (!qFuzzyCompare(newMargins.bottom(), oldMargins.bottom()))
emit bottomMarginChanged();
marginsChange(newMargins, oldMargins);
}
void QQuickPopup::resetMargins()
{
setMargins(-1);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::topMargin
This property holds the distance between the top edge of the popup and
the top edge of its window.
A popup with a negative top margin is not pushed within the top edge
of the enclosing window. The default value is \c -1.
\sa margins, bottomMargin, {Popup Layout}
*/
qreal QQuickPopup::topMargin() const
{
Q_D(const QQuickPopup);
if (d->hasTopMargin)
return d->topMargin;
return d->margins;
}
void QQuickPopup::setTopMargin(qreal margin)
{
Q_D(QQuickPopup);
d->setTopMargin(margin);
}
void QQuickPopup::resetTopMargin()
{
Q_D(QQuickPopup);
d->setTopMargin(-1, true);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::leftMargin
This property holds the distance between the left edge of the popup and
the left edge of its window.
A popup with a negative left margin is not pushed within the left edge
of the enclosing window. The default value is \c -1.
\sa margins, rightMargin, {Popup Layout}
*/
qreal QQuickPopup::leftMargin() const
{
Q_D(const QQuickPopup);
if (d->hasLeftMargin)
return d->leftMargin;
return d->margins;
}
void QQuickPopup::setLeftMargin(qreal margin)
{
Q_D(QQuickPopup);
d->setLeftMargin(margin);
}
void QQuickPopup::resetLeftMargin()
{
Q_D(QQuickPopup);
d->setLeftMargin(-1, true);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::rightMargin
This property holds the distance between the right edge of the popup and
the right edge of its window.
A popup with a negative right margin is not pushed within the right edge
of the enclosing window. The default value is \c -1.
\sa margins, leftMargin, {Popup Layout}
*/
qreal QQuickPopup::rightMargin() const
{
Q_D(const QQuickPopup);
if (d->hasRightMargin)
return d->rightMargin;
return d->margins;
}
void QQuickPopup::setRightMargin(qreal margin)
{
Q_D(QQuickPopup);
d->setRightMargin(margin);
}
void QQuickPopup::resetRightMargin()
{
Q_D(QQuickPopup);
d->setRightMargin(-1, true);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::bottomMargin
This property holds the distance between the bottom edge of the popup and
the bottom edge of its window.
A popup with a negative bottom margin is not pushed within the bottom edge
of the enclosing window. The default value is \c -1.
\sa margins, topMargin, {Popup Layout}
*/
qreal QQuickPopup::bottomMargin() const
{
Q_D(const QQuickPopup);
if (d->hasBottomMargin)
return d->bottomMargin;
return d->margins;
}
void QQuickPopup::setBottomMargin(qreal margin)
{
Q_D(QQuickPopup);
d->setBottomMargin(margin);
}
void QQuickPopup::resetBottomMargin()
{
Q_D(QQuickPopup);
d->setBottomMargin(-1, true);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::padding
This property holds the default padding.
\include qquickpopup-padding.qdocinc
\sa availableWidth, availableHeight, topPadding, leftPadding, rightPadding, bottomPadding
*/
qreal QQuickPopup::padding() const
{
Q_D(const QQuickPopup);
return d->popupItem->padding();
}
void QQuickPopup::setPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setPadding(padding);
}
void QQuickPopup::resetPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetPadding();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::topPadding
This property holds the top padding. Unless explicitly set, the value
is equal to \c verticalPadding.
\include qquickpopup-padding.qdocinc
\sa padding, bottomPadding, verticalPadding, availableHeight
*/
qreal QQuickPopup::topPadding() const
{
Q_D(const QQuickPopup);
return d->popupItem->topPadding();
}
void QQuickPopup::setTopPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setTopPadding(padding);
}
void QQuickPopup::resetTopPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetTopPadding();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::leftPadding
This property holds the left padding. Unless explicitly set, the value
is equal to \c horizontalPadding.
\include qquickpopup-padding.qdocinc
\sa padding, rightPadding, horizontalPadding, availableWidth
*/
qreal QQuickPopup::leftPadding() const
{
Q_D(const QQuickPopup);
return d->popupItem->leftPadding();
}
void QQuickPopup::setLeftPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setLeftPadding(padding);
}
void QQuickPopup::resetLeftPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetLeftPadding();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::rightPadding
This property holds the right padding. Unless explicitly set, the value
is equal to \c horizontalPadding.
\include qquickpopup-padding.qdocinc
\sa padding, leftPadding, horizontalPadding, availableWidth
*/
qreal QQuickPopup::rightPadding() const
{
Q_D(const QQuickPopup);
return d->popupItem->rightPadding();
}
void QQuickPopup::setRightPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setRightPadding(padding);
}
void QQuickPopup::resetRightPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetRightPadding();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::bottomPadding
This property holds the bottom padding. Unless explicitly set, the value
is equal to \c verticalPadding.
\include qquickpopup-padding.qdocinc
\sa padding, topPadding, verticalPadding, availableHeight
*/
qreal QQuickPopup::bottomPadding() const
{
Q_D(const QQuickPopup);
return d->popupItem->bottomPadding();
}
void QQuickPopup::setBottomPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setBottomPadding(padding);
}
void QQuickPopup::resetBottomPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetBottomPadding();
}
/*!
\qmlproperty Locale QtQuick.Controls::Popup::locale
This property holds the locale of the popup.
\sa mirrored, {LayoutMirroring}{LayoutMirroring}
*/
QLocale QQuickPopup::locale() const
{
Q_D(const QQuickPopup);
return d->popupItem->locale();
}
void QQuickPopup::setLocale(const QLocale &locale)
{
Q_D(QQuickPopup);
d->popupItem->setLocale(locale);
}
void QQuickPopup::resetLocale()
{
Q_D(QQuickPopup);
d->popupItem->resetLocale();
}
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\qmlproperty bool QtQuick.Controls::Popup::mirrored
\readonly
This property holds whether the popup is mirrored.
This property is provided for convenience. A popup is considered mirrored
when its visual layout direction is right-to-left; that is, when using a
right-to-left locale.
\sa locale, {Right-to-left User Interfaces}
*/
bool QQuickPopup::isMirrored() const
{
Q_D(const QQuickPopup);
return d->popupItem->isMirrored();
}
/*!
\qmlproperty font QtQuick.Controls::Popup::font
This property holds the font currently set for the popup.
Popup propagates explicit font properties to its children. If you change a specific
property on a popup's font, that property propagates to all of the popup's children,
overriding any system defaults for that property.
\code
Popup {
font.family: "Courier"
Column {
Label {
text: qsTr("This will use Courier...")
}
Switch {
text: qsTr("... and so will this")
}
}
}
\endcode
\sa Control::font, ApplicationWindow::font
*/
QFont QQuickPopup::font() const
{
Q_D(const QQuickPopup);
return d->popupItem->font();
}
void QQuickPopup::setFont(const QFont &font)
{
Q_D(QQuickPopup);
d->popupItem->setFont(font);
}
void QQuickPopup::resetFont()
{
Q_D(QQuickPopup);
d->popupItem->resetFont();
}
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\qmlproperty palette QtQuick.Controls::Popup::palette
This property holds the palette currently set for the popup.
Popup propagates explicit palette properties to its children. If you change a specific
property on a popup's palette, that property propagates to all of the popup's children,
overriding any system defaults for that property.
\code
Popup {
palette.text: "red"
Column {
Label {
text: qsTr("This will use red color...")
}
Switch {
text: qsTr("... and so will this")
}
}
}
\endcode
\sa Control::palette, ApplicationWindow::palette, {qtquickcontrols2-palette}{palette QML Basic Type}
*/
QPalette QQuickPopup::palette() const
{
Q_D(const QQuickPopup);
return d->popupItem->palette();
}
void QQuickPopup::setPalette(const QPalette &palette)
{
Q_D(QQuickPopup);
d->popupItem->setPalette(palette);
}
void QQuickPopup::resetPalette()
{
Q_D(QQuickPopup);
d->popupItem->resetPalette();
}
QQuickWindow *QQuickPopup::window() const
{
Q_D(const QQuickPopup);
return d->window;
}
QQuickItem *QQuickPopup::popupItem() const
{
Q_D(const QQuickPopup);
return d->popupItem;
}
/*!
\qmlproperty Item QtQuick.Controls::Popup::parent
This property holds the parent item.
*/
QQuickItem *QQuickPopup::parentItem() const
{
Q_D(const QQuickPopup);
return d->parentItem;
}
void QQuickPopup::setParentItem(QQuickItem *parent)
{
Q_D(QQuickPopup);
if (d->parentItem == parent)
return;
if (d->parentItem) {
QObjectPrivate::disconnect(d->parentItem, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
QQuickItemPrivate::get(d->parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
}
d->parentItem = parent;
QQuickPopupPositioner *positioner = d->getPositioner();
if (positioner->parentItem())
positioner->setParentItem(parent);
if (parent) {
QObjectPrivate::connect(parent, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
QQuickItemPrivate::get(d->parentItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
} else {
close();
}
d->setWindow(parent ? parent->window() : nullptr);
emit parentChanged();
}
void QQuickPopup::resetParentItem()
{
if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent()))
setParentItem(window->contentItem());
else
setParentItem(qobject_cast<QQuickItem *>(parent()));
}
/*!
\qmlproperty Item QtQuick.Controls::Popup::background
This property holds the background item.
\note If the background item has no explicit size specified, it automatically
follows the popup's size. In most cases, there is no need to specify
width or height for a background item.
\note Most popups use the implicit size of the background item to calculate
the implicit size of the popup itself. If you replace the background item
with a custom one, you should also consider providing a sensible implicit
size for it (unless it is an item like \l Image which has its own implicit
size).
\sa {Customizing Popup}
*/
QQuickItem *QQuickPopup::background() const
{
Q_D(const QQuickPopup);
return d->popupItem->background();
}
void QQuickPopup::setBackground(QQuickItem *background)
{
Q_D(QQuickPopup);
d->popupItem->setBackground(background);
}
/*!
\qmlproperty Item QtQuick.Controls::Popup::contentItem
This property holds the content item of the popup.
The content item is the visual implementation of the popup. When the
popup is made visible, the content item is automatically reparented to
the \l {Overlay::overlay}{overlay item}.
\note The content item is automatically resized to fit within the
\l padding of the popup.
\note Most popups use the implicit size of the content item to calculate
the implicit size of the popup itself. If you replace the content item
with a custom one, you should also consider providing a sensible implicit
size for it (unless it is an item like \l Text which has its own implicit
size).
\sa {Customizing Popup}
*/
QQuickItem *QQuickPopup::contentItem() const
{
Q_D(const QQuickPopup);
return d->popupItem->contentItem();
}
void QQuickPopup::setContentItem(QQuickItem *item)
{
Q_D(QQuickPopup);
d->popupItem->setContentItem(item);
}
/*!
\qmlproperty list<Object> QtQuick.Controls::Popup::contentData
\default
This property holds the list of content data.
The list contains all objects that have been declared in QML as children
of the popup.
\note Unlike \c contentChildren, \c contentData does include non-visual QML
objects.
\sa Item::data, contentChildren
*/
QQmlListProperty<QObject> QQuickPopupPrivate::contentData()
{
QQuickControlPrivate *p = QQuickControlPrivate::get(popupItem);
if (!p->contentItem)
p->executeContentItem();
return QQmlListProperty<QObject>(popupItem->contentItem(), nullptr,
QQuickItemPrivate::data_append,
QQuickItemPrivate::data_count,
QQuickItemPrivate::data_at,
QQuickItemPrivate::data_clear);
}
/*!
\qmlproperty list<Item> QtQuick.Controls::Popup::contentChildren
This property holds the list of content children.
The list contains all items that have been declared in QML as children
of the popup.
\note Unlike \c contentData, \c contentChildren does not include non-visual
QML objects.
\sa Item::children, contentData
*/
QQmlListProperty<QQuickItem> QQuickPopupPrivate::contentChildren()
{
return QQmlListProperty<QQuickItem>(popupItem->contentItem(), nullptr,
QQuickItemPrivate::children_append,
QQuickItemPrivate::children_count,
QQuickItemPrivate::children_at,
QQuickItemPrivate::children_clear);
}
/*!
\qmlproperty bool QtQuick.Controls::Popup::clip
This property holds whether clipping is enabled. The default value is \c false.
*/
bool QQuickPopup::clip() const
{
Q_D(const QQuickPopup);
return d->popupItem->clip();
}
void QQuickPopup::setClip(bool clip)
{
Q_D(QQuickPopup);
if (clip == d->popupItem->clip())
return;
d->popupItem->setClip(clip);
emit clipChanged();
}
/*!
\qmlproperty bool QtQuick.Controls::Popup::focus
This property holds whether the popup wants focus.
When the popup actually receives focus, \l activeFocus will be \c true.
For more information, see \l {Keyboard Focus in Qt Quick}.
The default value is \c false.
\sa activeFocus
*/
bool QQuickPopup::hasFocus() const
{
Q_D(const QQuickPopup);
return d->focus;
}
void QQuickPopup::setFocus(bool focus)
{
Q_D(QQuickPopup);
if (d->focus == focus)
return;
d->focus = focus;
emit focusChanged();
}
/*!
\qmlproperty bool QtQuick.Controls::Popup::activeFocus
\readonly
This property holds whether the popup has active focus.
\sa focus, {Keyboard Focus in Qt Quick}
*/
bool QQuickPopup::hasActiveFocus() const
{
Q_D(const QQuickPopup);
return d->popupItem->hasActiveFocus();
}
/*!
\qmlproperty bool QtQuick.Controls::Popup::modal
This property holds whether the popup is modal.
Modal popups often have a distinctive background dimming effect defined
in \l {Overlay::modal}{Overlay.modal}, and do not allow press
or release events through to items beneath them. For example, if the user
accidentally clicks outside of a popup, any item beneath that popup at
the location of the click will not receive the event.
On desktop platforms, it is common for modal popups to be closed only when
the escape key is pressed. To achieve this behavior, set
\l closePolicy to \c Popup.CloseOnEscape. By default, \c closePolicy
is set to \c {Popup.CloseOnEscape | Popup.CloseOnPressOutside}, which
means that clicking outside of a modal popup will close it.
The default value is \c false.
\sa dim
*/
bool QQuickPopup::isModal() const
{
Q_D(const QQuickPopup);
return d->modal;
}
void QQuickPopup::setModal(bool modal)
{
Q_D(QQuickPopup);
if (d->modal == modal)
return;
d->modal = modal;
if (d->complete && d->visible)
d->toggleOverlay();
emit modalChanged();
if (!d->hasDim) {
setDim(modal);
d->hasDim = false;
}
}
/*!
\qmlproperty bool QtQuick.Controls::Popup::dim
This property holds whether the popup dims the background.
Unless explicitly set, this property follows the value of \l modal. To
return to the default value, set this property to \c undefined.
\sa modal, {Overlay::modeless}{Overlay.modeless}
*/
bool QQuickPopup::dim() const
{
Q_D(const QQuickPopup);
return d->dim;
}
void QQuickPopup::setDim(bool dim)
{
Q_D(QQuickPopup);
d->hasDim = true;
if (d->dim == dim)
return;
d->dim = dim;
if (d->complete && d->visible)
d->toggleOverlay();
emit dimChanged();
}
void QQuickPopup::resetDim()
{
Q_D(QQuickPopup);
if (!d->hasDim)
return;
setDim(d->modal);
d->hasDim = false;
}
/*!
\qmlproperty bool QtQuick.Controls::Popup::visible
This property holds whether the popup is visible. The default value is \c false.
\sa open(), close(), opened
*/
bool QQuickPopup::isVisible() const
{
Q_D(const QQuickPopup);
return d->visible && d->popupItem->isVisible();
}
void QQuickPopup::setVisible(bool visible)
{
Q_D(QQuickPopup);
if (d->visible == visible && d->transitionState != QQuickPopupPrivate::ExitTransition)
return;
if (d->complete) {
if (visible)
d->transitionManager.transitionEnter();
else
d->transitionManager.transitionExit();
} else {
d->visible = visible;
}
}
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\qmlproperty bool QtQuick.Controls::Popup::enabled
This property holds whether the popup is enabled. The default value is \c true.
\sa visible, Item::enabled
*/
bool QQuickPopup::isEnabled() const
{
Q_D(const QQuickPopup);
return d->popupItem->isEnabled();
}
void QQuickPopup::setEnabled(bool enabled)
{
Q_D(QQuickPopup);
d->popupItem->setEnabled(enabled);
}
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\qmlproperty bool QtQuick.Controls::Popup::opened
This property holds whether the popup is fully open. The popup is considered opened
when it's visible and neither the \l enter nor \l exit transitions are running.
\sa open(), close(), visible
*/
bool QQuickPopup::isOpened() const
{
Q_D(const QQuickPopup);
return d->transitionState == QQuickPopupPrivate::NoTransition && isVisible();
}
/*!
\qmlproperty real QtQuick.Controls::Popup::opacity
This property holds the opacity of the popup. Opacity is specified as a number between
\c 0.0 (fully transparent) and \c 1.0 (fully opaque). The default value is \c 1.0.
\sa visible
*/
qreal QQuickPopup::opacity() const
{
Q_D(const QQuickPopup);
return d->popupItem->opacity();
}
void QQuickPopup::setOpacity(qreal opacity)
{
Q_D(QQuickPopup);
d->popupItem->setOpacity(opacity);
}
/*!
\qmlproperty real QtQuick.Controls::Popup::scale
This property holds the scale factor of the popup. The default value is \c 1.0.
A scale of less than \c 1.0 causes the popup to be rendered at a smaller size,
and a scale greater than \c 1.0 renders the popup at a larger size. Negative
scales are not supported.
*/
qreal QQuickPopup::scale() const
{
Q_D(const QQuickPopup);
return d->popupItem->scale();
}
void QQuickPopup::setScale(qreal scale)
{
Q_D(QQuickPopup);
if (qFuzzyCompare(scale, d->popupItem->scale()))
return;
d->popupItem->setScale(scale);
emit scaleChanged();
}
/*!
\qmlproperty enumeration QtQuick.Controls::Popup::closePolicy
This property determines the circumstances under which the popup closes.
The flags can be combined to allow several ways of closing the popup.
The available values are:
\value Popup.NoAutoClose The popup will only close when manually instructed to do so.
\value Popup.CloseOnPressOutside The popup will close when the mouse is pressed outside of it.
\value Popup.CloseOnPressOutsideParent The popup will close when the mouse is pressed outside of its parent.
\value Popup.CloseOnReleaseOutside The popup will close when the mouse is released outside of it.
\value Popup.CloseOnReleaseOutsideParent The popup will close when the mouse is released outside of its parent.
\value Popup.CloseOnEscape The popup will close when the escape key is pressed while the popup
has active focus.
The default value is \c {Popup.CloseOnEscape | Popup.CloseOnPressOutside}.
\note There is a known limitation that the \c Popup.CloseOnReleaseOutside
and \c Popup.CloseOnReleaseOutsideParent policies only work with
\l modal popups.
*/
QQuickPopup::ClosePolicy QQuickPopup::closePolicy() const
{
Q_D(const QQuickPopup);
return d->closePolicy;
}
void QQuickPopup::setClosePolicy(ClosePolicy policy)
{
Q_D(QQuickPopup);
d->hasClosePolicy = true;
if (d->closePolicy == policy)
return;
d->closePolicy = policy;
if (isVisible()) {
if (policy & QQuickPopup::CloseOnEscape)
d->popupItem->grabShortcut();
else
d->popupItem->ungrabShortcut();
}
emit closePolicyChanged();
}
void QQuickPopup::resetClosePolicy()
{
Q_D(QQuickPopup);
setClosePolicy(QQuickPopupPrivate::DefaultClosePolicy);
d->hasClosePolicy = false;
}
/*!
\qmlproperty enumeration QtQuick.Controls::Popup::transformOrigin
This property holds the origin point for transformations in enter and exit transitions.
Nine transform origins are available, as shown in the image below.
The default transform origin is \c Popup.Center.
\image qtquickcontrols2-popup-transformorigin.png
\sa enter, exit, Item::transformOrigin
*/
QQuickPopup::TransformOrigin QQuickPopup::transformOrigin() const
{
Q_D(const QQuickPopup);
return static_cast<TransformOrigin>(d->popupItem->transformOrigin());
}
void QQuickPopup::setTransformOrigin(TransformOrigin origin)
{
Q_D(QQuickPopup);
d->popupItem->setTransformOrigin(static_cast<QQuickItem::TransformOrigin>(origin));
}
/*!
\qmlproperty Transition QtQuick.Controls::Popup::enter
This property holds the transition that is applied to the popup item
when the popup is opened and enters the screen.
The following example animates the opacity of the popup when it enters
the screen:
\code
Popup {
enter: Transition {
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 }
}
}
\endcode
\sa exit
*/
QQuickTransition *QQuickPopup::enter() const
{
Q_D(const QQuickPopup);
return d->enter;
}
void QQuickPopup::setEnter(QQuickTransition *transition)
{
Q_D(QQuickPopup);
if (d->enter == transition)
return;
d->enter = transition;
emit enterChanged();
}
/*!
\qmlproperty Transition QtQuick.Controls::Popup::exit
This property holds the transition that is applied to the popup item
when the popup is closed and exits the screen.
The following example animates the opacity of the popup when it exits
the screen:
\code
Popup {
exit: Transition {
NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 }
}
}
\endcode
\sa enter
*/
QQuickTransition *QQuickPopup::exit() const
{
Q_D(const QQuickPopup);
return d->exit;
}
void QQuickPopup::setExit(QQuickTransition *transition)
{
Q_D(QQuickPopup);
if (d->exit == transition)
return;
d->exit = transition;
emit exitChanged();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::horizontalPadding
This property holds the horizontal padding. Unless explicitly set, the value
is equal to \c padding.
\include qquickpopup-padding.qdocinc
\sa padding, leftPadding, rightPadding, verticalPadding
*/
qreal QQuickPopup::horizontalPadding() const
{
Q_D(const QQuickPopup);
return d->popupItem->horizontalPadding();
}
void QQuickPopup::setHorizontalPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setHorizontalPadding(padding);
}
void QQuickPopup::resetHorizontalPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetHorizontalPadding();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::verticalPadding
This property holds the vertical padding. Unless explicitly set, the value
is equal to \c padding.
\include qquickpopup-padding.qdocinc
\sa padding, topPadding, bottomPadding, horizontalPadding
*/
qreal QQuickPopup::verticalPadding() const
{
Q_D(const QQuickPopup);
return d->popupItem->verticalPadding();
}
void QQuickPopup::setVerticalPadding(qreal padding)
{
Q_D(QQuickPopup);
d->popupItem->setVerticalPadding(padding);
}
void QQuickPopup::resetVerticalPadding()
{
Q_D(QQuickPopup);
d->popupItem->resetVerticalPadding();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::implicitContentWidth
\readonly
This property holds the implicit content width.
The value is calculated based on the content children.
\sa implicitContentHeight, implicitBackgroundWidth
*/
qreal QQuickPopup::implicitContentWidth() const
{
Q_D(const QQuickPopup);
return d->popupItem->implicitContentWidth();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::implicitContentHeight
\readonly
This property holds the implicit content height.
The value is calculated based on the content children.
\sa implicitContentWidth, implicitBackgroundHeight
*/
qreal QQuickPopup::implicitContentHeight() const
{
Q_D(const QQuickPopup);
return d->popupItem->implicitContentHeight();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::implicitBackgroundWidth
\readonly
This property holds the implicit background width.
The value is equal to \c {background ? background.implicitWidth : 0}.
\sa implicitBackgroundHeight, implicitContentWidth
*/
qreal QQuickPopup::implicitBackgroundWidth() const
{
Q_D(const QQuickPopup);
return d->popupItem->implicitBackgroundWidth();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::implicitBackgroundHeight
\readonly
This property holds the implicit background height.
The value is equal to \c {background ? background.implicitHeight : 0}.
\sa implicitBackgroundWidth, implicitContentHeight
*/
qreal QQuickPopup::implicitBackgroundHeight() const
{
Q_D(const QQuickPopup);
return d->popupItem->implicitBackgroundHeight();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::topInset
This property holds the top inset for the background.
\sa {Popup Layout}, bottomInset
*/
qreal QQuickPopup::topInset() const
{
Q_D(const QQuickPopup);
return d->popupItem->topInset();
}
void QQuickPopup::setTopInset(qreal inset)
{
Q_D(QQuickPopup);
d->popupItem->setTopInset(inset);
}
void QQuickPopup::resetTopInset()
{
Q_D(QQuickPopup);
d->popupItem->resetTopInset();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::leftInset
This property holds the left inset for the background.
\sa {Popup Layout}, rightInset
*/
qreal QQuickPopup::leftInset() const
{
Q_D(const QQuickPopup);
return d->popupItem->leftInset();
}
void QQuickPopup::setLeftInset(qreal inset)
{
Q_D(QQuickPopup);
d->popupItem->setLeftInset(inset);
}
void QQuickPopup::resetLeftInset()
{
Q_D(QQuickPopup);
d->popupItem->resetLeftInset();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::rightInset
This property holds the right inset for the background.
\sa {Popup Layout}, leftInset
*/
qreal QQuickPopup::rightInset() const
{
Q_D(const QQuickPopup);
return d->popupItem->rightInset();
}
void QQuickPopup::setRightInset(qreal inset)
{
Q_D(QQuickPopup);
d->popupItem->setRightInset(inset);
}
void QQuickPopup::resetRightInset()
{
Q_D(QQuickPopup);
d->popupItem->resetRightInset();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Popup::bottomInset
This property holds the bottom inset for the background.
\sa {Popup Layout}, topInset
*/
qreal QQuickPopup::bottomInset() const
{
Q_D(const QQuickPopup);
return d->popupItem->bottomInset();
}
void QQuickPopup::setBottomInset(qreal inset)
{
Q_D(QQuickPopup);
d->popupItem->setBottomInset(inset);
}
void QQuickPopup::resetBottomInset()
{
Q_D(QQuickPopup);
d->popupItem->resetBottomInset();
}
bool QQuickPopup::filtersChildMouseEvents() const
{
Q_D(const QQuickPopup);
return d->popupItem->filtersChildMouseEvents();
}
void QQuickPopup::setFiltersChildMouseEvents(bool filter)
{
Q_D(QQuickPopup);
d->popupItem->setFiltersChildMouseEvents(filter);
}
/*!
\qmlmethod QtQuick.Controls::Popup::forceActiveFocus(enumeration reason = Qt.OtherFocusReason)
Forces active focus on the popup with the given \a reason.
This method sets focus on the popup and ensures that all ancestor
\l FocusScope objects in the object hierarchy are also given \l focus.
\sa activeFocus, Qt::FocusReason
*/
void QQuickPopup::forceActiveFocus(Qt::FocusReason reason)
{
Q_D(QQuickPopup);
d->popupItem->forceActiveFocus(reason);
}
void QQuickPopup::classBegin()
{
Q_D(QQuickPopup);
d->complete = false;
QQmlContext *context = qmlContext(this);
if (context)
QQmlEngine::setContextForObject(d->popupItem, context);
d->popupItem->classBegin();
}
void QQuickPopup::componentComplete()
{
Q_D(QQuickPopup);
if (!parentItem())
resetParentItem();
if (d->visible && d->window)
d->transitionManager.transitionEnter();
d->complete = true;
d->popupItem->componentComplete();
if (isVisible()) {
if (d->closePolicy & QQuickPopup::CloseOnEscape)
d->popupItem->grabShortcut();
else
d->popupItem->ungrabShortcut();
}
}
bool QQuickPopup::isComponentComplete() const
{
Q_D(const QQuickPopup);
return d->complete;
}
bool QQuickPopup::childMouseEventFilter(QQuickItem *child, QEvent *event)
{
Q_UNUSED(child);
Q_UNUSED(event);
return false;
}
void QQuickPopup::focusInEvent(QFocusEvent *event)
{
event->accept();
}
void QQuickPopup::focusOutEvent(QFocusEvent *event)
{
event->accept();
}
void QQuickPopup::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickPopup);
event->accept();
if (hasActiveFocus() && (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab))
QQuickItemPrivate::focusNextPrev(d->popupItem, event->key() == Qt::Key_Tab);
}
void QQuickPopup::keyReleaseEvent(QKeyEvent *event)
{
event->accept();
}
void QQuickPopup::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickPopup);
d->handleMouseEvent(d->popupItem, event);
event->accept();
}
void QQuickPopup::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickPopup);
d->handleMouseEvent(d->popupItem, event);
event->accept();
}
void QQuickPopup::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickPopup);
d->handleMouseEvent(d->popupItem, event);
event->accept();
}
void QQuickPopup::mouseDoubleClickEvent(QMouseEvent *event)
{
event->accept();
}
void QQuickPopup::mouseUngrabEvent()
{
Q_D(QQuickPopup);
d->handleUngrab();
}
bool QQuickPopup::overlayEvent(QQuickItem *item, QEvent *event)
{
Q_D(QQuickPopup);
switch (event->type()) {
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::MouseMove:
case QEvent::Wheel:
if (d->modal)
event->accept();
return d->modal;
#if QT_CONFIG(quicktemplates2_multitouch)
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
return d->handleTouchEvent(item, static_cast<QTouchEvent *>(event));
#endif
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
return d->handleMouseEvent(item, static_cast<QMouseEvent *>(event));
default:
return false;
}
}
#if QT_CONFIG(quicktemplates2_multitouch)
void QQuickPopup::touchEvent(QTouchEvent *event)
{
Q_D(QQuickPopup);
d->handleTouchEvent(d->popupItem, event);
}
void QQuickPopup::touchUngrabEvent()
{
Q_D(QQuickPopup);
d->handleUngrab();
}
#endif
#if QT_CONFIG(wheelevent)
void QQuickPopup::wheelEvent(QWheelEvent *event)
{
event->accept();
}
#endif
void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
Q_UNUSED(newItem);
Q_UNUSED(oldItem);
}
void QQuickPopup::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
{
if (!qFuzzyCompare(newSize.width(), oldSize.width()))
emit contentWidthChanged();
if (!qFuzzyCompare(newSize.height(), oldSize.height()))
emit contentHeightChanged();
}
void QQuickPopup::fontChange(const QFont &newFont, const QFont &oldFont)
{
Q_UNUSED(newFont);
Q_UNUSED(oldFont);
emit fontChanged();
}
void QQuickPopup::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickPopup);
d->reposition();
if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) {
emit widthChanged();
emit availableWidthChanged();
}
if (!qFuzzyCompare(newGeometry.height(), oldGeometry.height())) {
emit heightChanged();
emit availableHeightChanged();
}
}
void QQuickPopup::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
{
Q_D(QQuickPopup);
switch (change) {
case QQuickItem::ItemActiveFocusHasChanged:
emit activeFocusChanged();
break;
case QQuickItem::ItemOpacityHasChanged:
emit opacityChanged();
break;
case QQuickItem::ItemVisibleHasChanged:
if (isComponentComplete() && d->closePolicy & CloseOnEscape) {
if (data.boolValue)
d->popupItem->grabShortcut();
else
d->popupItem->ungrabShortcut();
}
break;
default:
break;
}
}
void QQuickPopup::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
{
Q_UNUSED(newLocale);
Q_UNUSED(oldLocale);
emit localeChanged();
}
void QQuickPopup::marginsChange(const QMarginsF &newMargins, const QMarginsF &oldMargins)
{
Q_D(QQuickPopup);
Q_UNUSED(newMargins);
Q_UNUSED(oldMargins);
d->reposition();
}
void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
{
const bool tp = !qFuzzyCompare(newPadding.top(), oldPadding.top());
const bool lp = !qFuzzyCompare(newPadding.left(), oldPadding.left());
const bool rp = !qFuzzyCompare(newPadding.right(), oldPadding.right());
const bool bp = !qFuzzyCompare(newPadding.bottom(), oldPadding.bottom());
if (tp)
emit topPaddingChanged();
if (lp)
emit leftPaddingChanged();
if (rp)
emit rightPaddingChanged();
if (bp)
emit bottomPaddingChanged();
if (lp || rp) {
emit horizontalPaddingChanged();
emit availableWidthChanged();
}
if (tp || bp) {
emit verticalPaddingChanged();
emit availableHeightChanged();
}
}
void QQuickPopup::paletteChange(const QPalette &newPalette, const QPalette &oldPalette)
{
Q_UNUSED(newPalette);
Q_UNUSED(oldPalette);
emit paletteChanged();
}
void QQuickPopup::spacingChange(qreal newSpacing, qreal oldSpacing)
{
Q_UNUSED(newSpacing);
Q_UNUSED(oldSpacing);
emit spacingChanged();
}
void QQuickPopup::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
{
if (!qFuzzyCompare(newInset.top(), oldInset.top()))
emit topInsetChanged();
if (!qFuzzyCompare(newInset.left(), oldInset.left()))
emit leftInsetChanged();
if (!qFuzzyCompare(newInset.right(), oldInset.right()))
emit rightInsetChanged();
if (!qFuzzyCompare(newInset.bottom(), oldInset.bottom()))
emit bottomInsetChanged();
}
QFont QQuickPopup::defaultFont() const
{
return QQuickTheme::font(QQuickTheme::System);
}
QPalette QQuickPopup::defaultPalette() const
{
return QQuickTheme::palette(QQuickTheme::System);
}
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPopup::accessibleRole() const
{
return QAccessible::Dialog;
}
void QQuickPopup::accessibilityActiveChanged(bool active)
{
Q_UNUSED(active);
}
#endif
QString QQuickPopup::accessibleName() const
{
Q_D(const QQuickPopup);
return d->popupItem->accessibleName();
}
void QQuickPopup::maybeSetAccessibleName(const QString &name)
{
Q_D(QQuickPopup);
d->popupItem->maybeSetAccessibleName(name);
}
QVariant QQuickPopup::accessibleProperty(const char *propertyName)
{
Q_D(const QQuickPopup);
return d->popupItem->accessibleProperty(propertyName);
}
bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant &value)
{
Q_D(QQuickPopup);
return d->popupItem->setAccessibleProperty(propertyName, value);
}
QT_END_NAMESPACE
#include "moc_qquickpopup_p.cpp"