diff options
Diffstat (limited to 'src/templates/qquickpopup.cpp')
-rw-r--r-- | src/templates/qquickpopup.cpp | 345 |
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) |