aboutsummaryrefslogtreecommitdiffstats
path: root/src/templates/qquickpopup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/templates/qquickpopup.cpp')
-rw-r--r--src/templates/qquickpopup.cpp345
1 files changed, 188 insertions, 157 deletions
diff --git a/src/templates/qquickpopup.cpp b/src/templates/qquickpopup.cpp
index 36d98813..ff58ab83 100644
--- a/src/templates/qquickpopup.cpp
+++ b/src/templates/qquickpopup.cpp
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
\instantiates QQuickPopup
\inqmlmodule Qt.labs.controls
\ingroup qtlabscontrols-popups
- \brief A popup control.
+ \brief The base type of popup-like user interface controls.
Popup is the base type of popup-like user interface controls. It can be
used with Window or ApplicationWindow.
@@ -105,11 +105,14 @@ QQuickPopupPrivate::QQuickPopupPrivate()
: QObjectPrivate()
, focus(false)
, modal(false)
+ , visible(false)
, complete(false)
, hasTopMargin(false)
, hasLeftMargin(false)
, hasRightMargin(false)
, hasBottomMargin(false)
+ , x(0)
+ , y(0)
, margins(0)
, topMargin(0)
, leftMargin(0)
@@ -118,10 +121,10 @@ QQuickPopupPrivate::QQuickPopupPrivate()
, contentWidth(0)
, contentHeight(0)
, closePolicy(QQuickPopup::OnEscape)
- , parentItem(Q_NULLPTR)
- , enter(Q_NULLPTR)
- , exit(Q_NULLPTR)
- , popupItem(Q_NULLPTR)
+ , parentItem(nullptr)
+ , enter(nullptr)
+ , exit(nullptr)
+ , popupItem(nullptr)
, positioner(this)
, transitionManager(this)
{
@@ -158,17 +161,60 @@ bool QQuickPopupPrivate::tryClose(QQuickItem *item, QMouseEvent *event)
return false;
}
+void QQuickPopupPrivate::prepareEnterTransition(bool notify)
+{
+ Q_Q(QQuickPopup);
+ QQuickWindow *quickWindow = q->window();
+ if (!quickWindow) {
+ qmlInfo(q) << "cannot find any window to open popup in.";
+ return;
+ }
+
+ QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(quickWindow);
+ if (!applicationWindow) {
+ quickWindow->installEventFilter(q);
+ popupItem->setZ(10001); // DefaultWindowDecoration+1
+ popupItem->setParentItem(quickWindow->contentItem());
+ } else {
+ popupItem->setParentItem(applicationWindow->overlay());
+ }
+
+ if (notify)
+ emit q->aboutToShow();
+ visible = true;
+ popupItem->setVisible(true);
+ positioner.setParentItem(parentItem);
+ emit q->visibleChanged();
+}
+
+void QQuickPopupPrivate::prepareExitTransition()
+{
+ Q_Q(QQuickPopup);
+ QQuickWindow *quickWindow = q->window();
+ if (quickWindow && !qobject_cast<QQuickApplicationWindow *>(quickWindow))
+ quickWindow->removeEventFilter(q);
+ if (focus)
+ popupItem->setFocus(false);
+ emit q->aboutToHide();
+}
+
void QQuickPopupPrivate::finalizeEnterTransition()
{
if (focus)
popupItem->setFocus(true);
}
-void QQuickPopupPrivate::finalizeExitTransition()
+void QQuickPopupPrivate::finalizeExitTransition(bool hide)
{
- positioner.setParentItem(Q_NULLPTR);
- popupItem->setParentItem(Q_NULLPTR);
- popupItem->setVisible(false);
+ Q_Q(QQuickPopup);
+ positioner.setParentItem(nullptr);
+ if (hide) {
+ popupItem->setParentItem(nullptr);
+ popupItem->setVisible(false);
+ }
+
+ visible = false;
+ emit q->visibleChanged();
}
QMarginsF QQuickPopupPrivate::getMargins() const
@@ -236,8 +282,8 @@ class QQuickPopupItemPrivate : public QQuickControlPrivate
public:
QQuickPopupItemPrivate(QQuickPopup *popup);
- void implicitWidthChanged() Q_DECL_OVERRIDE;
- void implicitHeightChanged() Q_DECL_OVERRIDE;
+ void implicitWidthChanged() override;
+ void implicitHeightChanged() override;
QQuickPopup *popup;
};
@@ -260,7 +306,7 @@ void QQuickPopupItemPrivate::implicitHeightChanged()
}
QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) :
- QQuickControl(*(new QQuickPopupItemPrivate(popup)), Q_NULLPTR)
+ QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr)
{
setParent(popup);
setVisible(false);
@@ -268,6 +314,12 @@ QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) :
setAcceptedMouseButtons(Qt::AllButtons);
}
+bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ return d->popup->childMouseEventFilter(child, event);
+}
+
void QQuickPopupItem::focusInEvent(QFocusEvent *event)
{
Q_D(QQuickPopupItem);
@@ -347,9 +399,6 @@ void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
Q_D(QQuickPopupItem);
QQuickControl::itemChange(change, data);
switch (change) {
- case ItemVisibleHasChanged:
- emit d->popup->visibleChanged();
- break;
case ItemActiveFocusHasChanged:
emit d->popup->activeFocusChanged();
break;
@@ -377,9 +426,7 @@ QAccessible::Role QQuickPopupItem::accessibleRole() const
#endif // QT_NO_ACCESSIBILITY
QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopupPrivate *popup) :
- m_x(0),
- m_y(0),
- m_parentItem(Q_NULLPTR),
+ m_parentItem(nullptr),
m_popup(popup)
{
}
@@ -392,34 +439,6 @@ QQuickPopupPositioner::~QQuickPopupPositioner()
}
}
-qreal QQuickPopupPositioner::x() const
-{
- return m_x;
-}
-
-void QQuickPopupPositioner::setX(qreal x)
-{
- if (m_x != x) {
- m_x = x;
- if (m_popup->popupItem->isVisible())
- repositionPopup();
- }
-}
-
-qreal QQuickPopupPositioner::y() const
-{
- return m_y;
-}
-
-void QQuickPopupPositioner::setY(qreal y)
-{
- if (m_y != y) {
- m_y = y;
- if (m_popup->popupItem->isVisible())
- repositionPopup();
- }
-}
-
QQuickItem *QQuickPopupPositioner::parentItem() const
{
return m_parentItem;
@@ -444,13 +463,13 @@ void QQuickPopupPositioner::setParentItem(QQuickItem *parent)
addAncestorListeners(parent->parentItem());
if (m_popup->popupItem->isVisible())
- repositionPopup();
+ m_popup->reposition();
}
void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &)
{
if (m_popup->popupItem->isVisible())
- repositionPopup();
+ m_popup->reposition();
}
void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
@@ -468,29 +487,30 @@ void QQuickPopupPositioner::itemDestroyed(QQuickItem *item)
{
Q_ASSERT(m_parentItem == item);
- m_parentItem = Q_NULLPTR;
+ m_parentItem = nullptr;
QQuickItemPrivate::get(item)->removeItemChangeListener(this, ItemChangeTypes);
removeAncestorListeners(item->parentItem());
}
-void QQuickPopupPositioner::repositionPopup()
+void QQuickPopupPrivate::reposition()
{
- const qreal w = m_popup->popupItem->width();
- const qreal h = m_popup->popupItem->height();
- const qreal iw = m_popup->popupItem->implicitWidth();
- const qreal ih = m_popup->popupItem->implicitHeight();
+ Q_Q(QQuickPopup);
+ const qreal w = popupItem->width();
+ const qreal h = popupItem->height();
+ const qreal iw = popupItem->implicitWidth();
+ const qreal ih = popupItem->implicitHeight();
bool adjusted = false;
- QRectF rect(m_x, m_y, iw > 0 ? iw : w, ih > 0 ? ih : h);
- if (m_parentItem) {
- rect = m_parentItem->mapRectToScene(rect);
+ QRectF rect(x, y, iw > 0 ? iw : w, ih > 0 ? ih : h);
+ if (parentItem) {
+ rect = parentItem->mapRectToScene(rect);
- QQuickWindow *window = m_parentItem->window();
+ QQuickWindow *window = q->window();
if (window) {
- const QRectF bounds = QRectF(0, 0, window->width(), window->height()).marginsRemoved(m_popup->getMargins());
+ const QRectF bounds = QRectF(0, 0, window->width(), window->height()).marginsRemoved(getMargins());
if (rect.top() < bounds.top() || rect.bottom() > bounds.bottom()) {
// if the popup doesn't fit inside the window, try flipping it around (below <-> above)
- const QRectF flipped = m_parentItem->mapRectToScene(QRectF(m_x, m_parentItem->height() - m_y - rect.height(), rect.width(), rect.height()));
+ const QRectF flipped = parentItem->mapRectToScene(QRectF(x, parentItem->height() - y - rect.height(), rect.width(), rect.height()));
if (flipped.top() >= bounds.top() && flipped.bottom() < bounds.bottom()) {
adjusted = true;
rect = flipped;
@@ -513,9 +533,9 @@ void QQuickPopupPositioner::repositionPopup()
}
}
- m_popup->popupItem->setPosition(rect.topLeft());
+ popupItem->setPosition(rect.topLeft());
if (adjusted && ih > 0)
- m_popup->popupItem->setHeight(rect.height());
+ popupItem->setHeight(rect.height());
}
void QQuickPopupPositioner::removeAncestorListeners(QQuickItem *item)
@@ -568,18 +588,20 @@ void QQuickPopupTransitionManager::transitionEnter()
{
if (state == Enter && isRunning())
return;
- QList<QQuickStateAction> actions;
+
state = Enter;
- transition(actions, popup->enter, popup->popupItem);
+ popup->prepareEnterTransition();
+ transition(popup->enterActions, popup->enter, popup->q_func());
}
void QQuickPopupTransitionManager::transitionExit()
{
if (state == Exit && isRunning())
return;
- QList<QQuickStateAction> actions;
+
state = Exit;
- transition(actions, popup->exit, popup->popupItem);
+ popup->prepareExitTransition();
+ transition(popup->exitActions, popup->exit, popup->q_func());
}
void QQuickPopupTransitionManager::finished()
@@ -609,7 +631,7 @@ QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent)
QQuickPopup::~QQuickPopup()
{
Q_D(QQuickPopup);
- d->positioner.setParentItem(Q_NULLPTR);
+ d->positioner.setParentItem(nullptr);
delete d->popupItem;
}
@@ -621,30 +643,11 @@ QQuickPopup::~QQuickPopup()
void QQuickPopup::open()
{
Q_D(QQuickPopup);
- if (d->popupItem->isVisible())
+ if (d->visible)
return;
- QQuickWindow *window = Q_NULLPTR;
- if (d->parentItem)
- window = d->parentItem->window();
- if (!window) {
- qmlInfo(this) << "cannot find any window to open popup in.";
- return;
- }
-
- QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window);
- if (!applicationWindow) {
- window->installEventFilter(this);
- d->popupItem->setZ(10001); // DefaultWindowDecoration+1
- d->popupItem->setParentItem(window->contentItem());
- } else {
- d->popupItem->setParentItem(applicationWindow->overlay());
- }
-
- emit aboutToShow();
- d->popupItem->setVisible(true);
- d->positioner.setParentItem(d->parentItem);
- d->transitionManager.transitionEnter();
+ if (d->complete)
+ d->transitionManager.transitionEnter();
}
/*!
@@ -655,19 +658,11 @@ void QQuickPopup::open()
void QQuickPopup::close()
{
Q_D(QQuickPopup);
- if (!d->popupItem->isVisible())
+ if (!d->visible)
return;
- if (d->parentItem) {
- QQuickWindow *window = d->parentItem->window();
- if (!qobject_cast<QQuickApplicationWindow *>(window)) {
- window->removeEventFilter(this);
- }
- }
-
- d->popupItem->setFocus(false);
- emit aboutToHide();
- d->transitionManager.transitionExit();
+ if (d->complete)
+ d->transitionManager.transitionExit();
}
/*!
@@ -678,13 +673,19 @@ void QQuickPopup::close()
qreal QQuickPopup::x() const
{
Q_D(const QQuickPopup);
- return d->positioner.x();
+ return d->x;
}
void QQuickPopup::setX(qreal x)
{
Q_D(QQuickPopup);
- d->positioner.setX(x);
+ if (qFuzzyCompare(d->x, x))
+ return;
+
+ d->x = x;
+ if (d->popupItem->isVisible())
+ d->reposition();
+ emit xChanged();
}
/*!
@@ -695,13 +696,19 @@ void QQuickPopup::setX(qreal x)
qreal QQuickPopup::y() const
{
Q_D(const QQuickPopup);
- return d->positioner.y();
+ return d->y;
}
void QQuickPopup::setY(qreal y)
{
Q_D(QQuickPopup);
- d->positioner.setY(y);
+ if (qFuzzyCompare(d->y, y))
+ return;
+
+ d->y = y;
+ if (d->popupItem->isVisible())
+ d->reposition();
+ emit yChanged();
}
/*!
@@ -823,10 +830,11 @@ qreal QQuickPopup::contentWidth() const
void QQuickPopup::setContentWidth(qreal width)
{
Q_D(QQuickPopup);
- if (d->contentWidth != width) {
- d->contentWidth = width;
- emit contentWidthChanged();
- }
+ if (qFuzzyCompare(d->contentWidth, width))
+ return;
+
+ d->contentWidth = width;
+ emit contentWidthChanged();
}
/*!
@@ -847,10 +855,11 @@ qreal QQuickPopup::contentHeight() const
void QQuickPopup::setContentHeight(qreal height)
{
Q_D(QQuickPopup);
- if (d->contentHeight != height) {
- d->contentHeight = height;
- emit contentHeightChanged();
- }
+ if (qFuzzyCompare(d->contentHeight, height))
+ return;
+
+ d->contentHeight = height;
+ emit contentHeightChanged();
}
/*!
@@ -1152,6 +1161,15 @@ void QQuickPopup::resetBottomPadding()
d->popupItem->resetBottomPadding();
}
+QQuickWindow *QQuickPopup::window() const
+{
+ Q_D(const QQuickPopup);
+ if (!d->parentItem)
+ return nullptr;
+
+ return d->parentItem->window();
+}
+
QQuickItem *QQuickPopup::popupItem() const
{
Q_D(const QQuickPopup);
@@ -1172,16 +1190,17 @@ QQuickItem *QQuickPopup::parentItem() const
void QQuickPopup::setParentItem(QQuickItem *parent)
{
Q_D(QQuickPopup);
- if (d->parentItem != parent) {
- d->parentItem = parent;
- if (d->positioner.parentItem())
- d->positioner.setParentItem(parent);
- if (parent) {
- QQuickControlPrivate::updateFontRecur(d->popupItem, QQuickControlPrivate::naturalControlFont(parent));
- QQuickControlPrivate::updateLocaleRecur(d->popupItem, QQuickControlPrivate::calcLocale(parent));
- }
- emit parentChanged();
+ if (d->parentItem == parent)
+ return;
+
+ d->parentItem = parent;
+ if (d->positioner.parentItem())
+ d->positioner.setParentItem(parent);
+ if (parent) {
+ QQuickControlPrivate::updateFontRecur(d->popupItem, QQuickControlPrivate::naturalControlFont(parent));
+ QQuickControlPrivate::updateLocaleRecur(d->popupItem, QQuickControlPrivate::calcLocale(parent));
}
+ emit parentChanged();
}
/*!
@@ -1242,7 +1261,7 @@ void QQuickPopup::setContentItem(QQuickItem *item)
QQmlListProperty<QObject> QQuickPopup::contentData()
{
Q_D(QQuickPopup);
- return QQmlListProperty<QObject>(d->popupItem->contentItem(), Q_NULLPTR,
+ return QQmlListProperty<QObject>(d->popupItem->contentItem(), nullptr,
QQuickItemPrivate::data_append,
QQuickItemPrivate::data_count,
QQuickItemPrivate::data_at,
@@ -1259,7 +1278,7 @@ QQmlListProperty<QObject> QQuickPopup::contentData()
QQmlListProperty<QQuickItem> QQuickPopup::contentChildren()
{
Q_D(QQuickPopup);
- return QQmlListProperty<QQuickItem>(d->popupItem->contentItem(), Q_NULLPTR,
+ return QQmlListProperty<QQuickItem>(d->popupItem->contentItem(), nullptr,
QQuickItemPrivate::children_append,
QQuickItemPrivate::children_count,
QQuickItemPrivate::children_at,
@@ -1346,7 +1365,7 @@ void QQuickPopup::setModal(bool modal)
bool QQuickPopup::isVisible() const
{
Q_D(const QQuickPopup);
- return d->popupItem->isVisible();
+ return d->visible && d->popupItem->isVisible();
}
void QQuickPopup::setVisible(bool visible)
@@ -1492,18 +1511,16 @@ void QQuickPopup::setExit(QQuickTransition *transition)
emit exitChanged();
}
-/*!
- \qmlproperty list<Object> Qt.labs.controls::Popup::data
- \default
-
- This property holds the list of data.
+bool QQuickPopup::filtersChildMouseEvents() const
+{
+ Q_D(const QQuickPopup);
+ return d->popupItem->filtersChildMouseEvents();
+}
- \sa Item::data
-*/
-QQmlListProperty<QObject> QQuickPopup::data()
+void QQuickPopup::setFiltersChildMouseEvents(bool filter)
{
Q_D(QQuickPopup);
- return QQuickItemPrivate::get(d->popupItem)->data();
+ d->popupItem->setFiltersChildMouseEvents(filter);
}
void QQuickPopup::classBegin()
@@ -1516,6 +1533,8 @@ void QQuickPopup::componentComplete()
d->complete = true;
if (!parentItem())
setParentItem(qobject_cast<QQuickItem *>(parent()));
+ if (d->visible)
+ d->transitionManager.transitionEnter();
}
bool QQuickPopup::isComponentComplete() const
@@ -1526,28 +1545,16 @@ bool QQuickPopup::isComponentComplete() const
bool QQuickPopup::eventFilter(QObject *object, QEvent *event)
{
- Q_D(QQuickPopup);
- Q_UNUSED(object);
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonRelease:
- if (d->modal)
- event->setAccepted(true);
- if (QQuickWindow *window = qobject_cast<QQuickWindow *>(object)) {
- if (d->tryClose(window->contentItem(), static_cast<QMouseEvent *>(event)))
- return true;
- }
- return false;
- case QEvent::KeyPress:
- case QEvent::KeyRelease:
- case QEvent::MouseMove:
- case QEvent::Wheel:
- if (d->modal)
- event->setAccepted(true);
- return false;
- default:
- return false;
- }
+ if (QQuickWindow *window = qobject_cast<QQuickWindow *>(object))
+ return overlayEvent(window->contentItem(), event);
+ return false;
+}
+
+bool QQuickPopup::childMouseEventFilter(QQuickItem *child, QEvent *event)
+{
+ Q_UNUSED(child);
+ Q_UNUSED(event);
+ return false;
}
void QQuickPopup::focusInEvent(QFocusEvent *event)
@@ -1601,6 +1608,30 @@ void QQuickPopup::mouseUngrabEvent()
{
}
+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;
+
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ if (d->modal)
+ event->accept();
+ d->tryClose(item, static_cast<QMouseEvent *>(event));
+ return d->modal;
+
+ default:
+ return false;
+ }
+}
+
void QQuickPopup::wheelEvent(QWheelEvent *event)
{
event->accept();
@@ -1616,7 +1647,7 @@ void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
void QQuickPopup::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickPopup);
- d->positioner.repositionPopup();
+ d->reposition();
if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) {
emit widthChanged();
emit availableWidthChanged();
@@ -1632,7 +1663,7 @@ void QQuickPopup::marginsChange(const QMarginsF &newMargins, const QMarginsF &ol
Q_D(QQuickPopup);
Q_UNUSED(newMargins);
Q_UNUSED(oldMargins);
- d->positioner.repositionPopup();
+ d->reposition();
}
void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)