diff options
Diffstat (limited to 'src/templates')
-rw-r--r-- | src/templates/qquickoverlay.cpp | 6 | ||||
-rw-r--r-- | src/templates/qquickpopup.cpp | 448 | ||||
-rw-r--r-- | src/templates/qquickpopup_p.h | 71 | ||||
-rw-r--r-- | src/templates/qquickpopup_p_p.h | 44 |
4 files changed, 554 insertions, 15 deletions
diff --git a/src/templates/qquickoverlay.cpp b/src/templates/qquickoverlay.cpp index ecee2767..bef6193d 100644 --- a/src/templates/qquickoverlay.cpp +++ b/src/templates/qquickoverlay.cpp @@ -261,11 +261,11 @@ bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event) const QQuickItemPrivate *priv = QQuickItemPrivate::get(this); const QList<QQuickItem *> &sortedChildren = priv->paintOrderChildItems(); for (int i = sortedChildren.count() - 1; i >= 0; --i) { - QQuickItem *contentItem = sortedChildren[i]; - if (contentItem == item) + QQuickItem *popupItem = sortedChildren[i]; + if (popupItem == item) break; - QQuickPopup *popup = d->popups.value(contentItem); + QQuickPopup *popup = d->popups.value(popupItem); if (popup) { emit popup->pressedOutside(); diff --git a/src/templates/qquickpopup.cpp b/src/templates/qquickpopup.cpp index 1b8c5611..6ebdffda 100644 --- a/src/templates/qquickpopup.cpp +++ b/src/templates/qquickpopup.cpp @@ -63,28 +63,136 @@ QQuickPopupPrivate::QQuickPopupPrivate() : QObjectPrivate() , focus(false) , modal(false) + , hasTopPadding(false) + , hasLeftPadding(false) + , hasRightPadding(false) + , hasBottomPadding(false) + , padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , background(Q_NULLPTR) , contentItem(Q_NULLPTR) , overlay(Q_NULLPTR) , enter(Q_NULLPTR) , exit(Q_NULLPTR) + , popupItem(Q_NULLPTR) , transitionManager(this) { } +void QQuickPopupPrivate::init() +{ + Q_Q(QQuickPopup); + popupItem = new QQuickPopupItem(q); + popupItem->setParent(q); +} + void QQuickPopupPrivate::finalizeEnterTransition() { if (focus) - contentItem->setFocus(true); + popupItem->setFocus(true); } void QQuickPopupPrivate::finalizeExitTransition() { Q_Q(QQuickPopup); overlay = Q_NULLPTR; - contentItem->setParentItem(Q_NULLPTR); + popupItem->setParentItem(Q_NULLPTR); emit q->visibleChanged(); } +void QQuickPopupPrivate::resizeBackground() +{ + Q_Q(QQuickPopup); + if (background) { + QQuickItemPrivate *p = QQuickItemPrivate::get(background); + if (!p->widthValid && qFuzzyIsNull(background->x())) { + background->setWidth(q->width()); + p->widthValid = false; + } + if (!p->heightValid && qFuzzyIsNull(background->y())) { + background->setHeight(q->height()); + p->heightValid = false; + } + } +} + +void QQuickPopupPrivate::resizeContent() +{ + Q_Q(QQuickPopup); + if (contentItem) { + contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding())); + contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight())); + } +} + +void QQuickPopupPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickPopup); + qreal oldPadding = q->topPadding(); + topPadding = value; + hasTopPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + emit q->topPaddingChanged(); + emit q->availableHeightChanged(); + q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), + QMarginsF(leftPadding, oldPadding, rightPadding, bottomPadding)); + } +} + +void QQuickPopupPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickPopup); + qreal oldPadding = q->leftPadding(); + leftPadding = value; + hasLeftPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + emit q->leftPaddingChanged(); + emit q->availableWidthChanged(); + q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), + QMarginsF(oldPadding, topPadding, rightPadding, bottomPadding)); + } +} + +void QQuickPopupPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickPopup); + qreal oldPadding = q->rightPadding(); + rightPadding = value; + hasRightPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + emit q->rightPaddingChanged(); + emit q->availableWidthChanged(); + q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), + QMarginsF(leftPadding, topPadding, oldPadding, bottomPadding)); + } +} + +void QQuickPopupPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickPopup); + qreal oldPadding = q->bottomPadding(); + bottomPadding = value; + hasBottomPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + emit q->bottomPaddingChanged(); + emit q->availableHeightChanged(); + q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), + QMarginsF(leftPadding, topPadding, rightPadding, oldPadding)); + } +} + +QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) : popup(popup) +{ +} + +void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + popup->geometryChanged(newGeometry, oldGeometry); +} + QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup) : QQuickTransitionManager() , state(Off) @@ -98,7 +206,7 @@ void QQuickPopupTransitionManager::transitionEnter() return; QList<QQuickStateAction> actions; state = Enter; - transition(actions, popup->enter, popup->contentItem); + transition(actions, popup->enter, popup->popupItem); } void QQuickPopupTransitionManager::transitionExit() @@ -107,7 +215,7 @@ void QQuickPopupTransitionManager::transitionExit() return; QList<QQuickStateAction> actions; state = Exit; - transition(actions, popup->exit, popup->contentItem); + transition(actions, popup->exit, popup->popupItem); } void QQuickPopupTransitionManager::finished() @@ -123,11 +231,15 @@ void QQuickPopupTransitionManager::finished() 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(); } /*! @@ -138,10 +250,6 @@ QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent) void QQuickPopup::open() { Q_D(QQuickPopup); - if (!d->contentItem) { - qmlInfo(this) << "no popup content to show."; - return; - } if (d->overlay) { // popup already open return; @@ -173,7 +281,10 @@ void QQuickPopup::open() } d->overlay = static_cast<QQuickOverlay *>(applicationWindow->overlay()); - d->contentItem->setParentItem(d->overlay); + d->popupItem->setParentItem(d->overlay); + // TODO: add Popup::transformOrigin? + if (d->contentItem) + d->popupItem->setTransformOrigin(d->contentItem->transformOrigin()); emit aboutToShow(); d->transitionManager.transitionEnter(); emit visibleChanged(); @@ -193,12 +304,286 @@ void QQuickPopup::close() return; } - d->contentItem->setFocus(false); + d->popupItem->setFocus(false); emit aboutToHide(); d->transitionManager.transitionExit(); } /*! + \qmlproperty real Qt.labs.controls::Popup::x + + This property holds the x-coordinate of the popup. +*/ +qreal QQuickPopup::x() const +{ + Q_D(const QQuickPopup); + return d->popupItem->x(); +} + +void QQuickPopup::setX(qreal x) +{ + Q_D(QQuickPopup); + d->popupItem->setX(x); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::y + + This property holds the y-coordinate of the popup. +*/ +qreal QQuickPopup::y() const +{ + Q_D(const QQuickPopup); + return d->popupItem->y(); +} + +void QQuickPopup::setY(qreal y) +{ + Q_D(QQuickPopup); + d->popupItem->setY(y); +} + +/*! + \qmlproperty real Qt.labs.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->popupItem->setWidth(width); +} + +/*! + \qmlproperty real Qt.labs.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->popupItem->setHeight(height); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::availableWidth + + This property holds the width available after deducting horizontal padding. + + \sa padding, leftPadding, rightPadding +*/ +qreal QQuickPopup::availableWidth() const +{ + return qMax<qreal>(0.0, width() - leftPadding() - rightPadding()); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::availableHeight + + This property holds the height available after deducting vertical padding. + + \sa padding, topPadding, bottomPadding +*/ +qreal QQuickPopup::availableHeight() const +{ + return qMax<qreal>(0.0, height() - topPadding() - bottomPadding()); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::padding + + This property holds the default padding. + + \sa availableWidth, availableHeight, topPadding, leftPadding, rightPadding, bottomPadding +*/ +qreal QQuickPopup::padding() const +{ + Q_D(const QQuickPopup); + return d->padding; +} + +void QQuickPopup::setPadding(qreal padding) +{ + Q_D(QQuickPopup); + if (qFuzzyCompare(d->padding, padding)) + return; + QMarginsF oldPadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); + d->padding = padding; + emit paddingChanged(); + QMarginsF newPadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); + if (!qFuzzyCompare(newPadding.top(), oldPadding.top())) + emit topPaddingChanged(); + if (!qFuzzyCompare(newPadding.left(), oldPadding.left())) + emit leftPaddingChanged(); + if (!qFuzzyCompare(newPadding.right(), oldPadding.right())) + emit rightPaddingChanged(); + if (!qFuzzyCompare(newPadding.bottom(), oldPadding.bottom())) + emit bottomPaddingChanged(); + if (!qFuzzyCompare(newPadding.top(), oldPadding.top()) || !qFuzzyCompare(newPadding.bottom(), oldPadding.bottom())) + emit availableHeightChanged(); + if (!qFuzzyCompare(newPadding.left(), oldPadding.left()) || !qFuzzyCompare(newPadding.right(), oldPadding.right())) + emit availableWidthChanged(); + paddingChange(newPadding, oldPadding); +} + +void QQuickPopup::resetPadding() +{ + setPadding(0); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::topPadding + + This property holds the top padding. + + \sa padding, bottomPadding, availableHeight +*/ +qreal QQuickPopup::topPadding() const +{ + Q_D(const QQuickPopup); + if (d->hasTopPadding) + return d->topPadding; + return d->padding; +} + +void QQuickPopup::setTopPadding(qreal padding) +{ + Q_D(QQuickPopup); + d->setTopPadding(padding); +} + +void QQuickPopup::resetTopPadding() +{ + Q_D(QQuickPopup); + d->setTopPadding(0, true); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::leftPadding + + This property holds the left padding. + + \sa padding, rightPadding, availableWidth +*/ +qreal QQuickPopup::leftPadding() const +{ + Q_D(const QQuickPopup); + if (d->hasLeftPadding) + return d->leftPadding; + return d->padding; +} + +void QQuickPopup::setLeftPadding(qreal padding) +{ + Q_D(QQuickPopup); + d->setLeftPadding(padding); +} + +void QQuickPopup::resetLeftPadding() +{ + Q_D(QQuickPopup); + d->setLeftPadding(0, true); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::rightPadding + + This property holds the right padding. + + \sa padding, leftPadding, availableWidth +*/ +qreal QQuickPopup::rightPadding() const +{ + Q_D(const QQuickPopup); + if (d->hasRightPadding) + return d->rightPadding; + return d->padding; +} + +void QQuickPopup::setRightPadding(qreal padding) +{ + Q_D(QQuickPopup); + d->setRightPadding(padding); +} + +void QQuickPopup::resetRightPadding() +{ + Q_D(QQuickPopup); + d->setRightPadding(0, true); +} + +/*! + \qmlproperty real Qt.labs.controls::Popup::bottomPadding + + This property holds the bottom padding. + + \sa padding, topPadding, availableHeight +*/ +qreal QQuickPopup::bottomPadding() const +{ + Q_D(const QQuickPopup); + if (d->hasBottomPadding) + return d->bottomPadding; + return d->padding; +} + +void QQuickPopup::setBottomPadding(qreal padding) +{ + Q_D(QQuickPopup); + d->setBottomPadding(padding); +} + +void QQuickPopup::resetBottomPadding() +{ + Q_D(QQuickPopup); + d->setBottomPadding(0, true); +} + +/*! + \qmlproperty Item Qt.labs.popups::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. +*/ +QQuickItem *QQuickPopup::background() const +{ + Q_D(const QQuickPopup); + return d->background; +} + +void QQuickPopup::setBackground(QQuickItem *background) +{ + Q_D(QQuickPopup); + if (d->background != background) { + delete d->background; + d->background = background; + if (background) { + background->setParentItem(d->popupItem); + if (qFuzzyIsNull(background->z())) + background->setZ(-1); + if (isComponentComplete()) + d->resizeBackground(); + } + emit backgroundChanged(); + } +} + +/*! \qmlproperty Item Qt.labs.controls::Popup::contentItem This property holds the content item of the popup. @@ -226,8 +611,12 @@ void QQuickPopup::setContentItem(QQuickItem *item) contentItemChange(item, d->contentItem); delete d->contentItem; d->contentItem = item; - if (item) + if (item) { + item->setParentItem(d->popupItem); QQuickItemPrivate::get(item)->isTabFence = true; + if (isComponentComplete()) + d->resizeContent(); + } emit contentItemChanged(); } } @@ -325,6 +714,20 @@ void QQuickPopup::setExit(QQuickTransition *transition) emit exitChanged(); } +/*! + \qmlproperty list<Object> Qt.labs.controls::Popup::data + \default + + This property holds the list of data. + + \sa Item::data +*/ +QQmlListProperty<QObject> QQuickPopup::data() +{ + Q_D(QQuickPopup); + return QQuickItemPrivate::get(d->popupItem)->data(); +} + void QQuickPopup::classBegin() { } @@ -347,6 +750,29 @@ void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) Q_UNUSED(oldItem); } +void QQuickPopup::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickPopup); + d->resizeBackground(); + d->resizeContent(); + if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) { + emit widthChanged(); + emit availableWidthChanged(); + } + if (!qFuzzyCompare(newGeometry.height(), oldGeometry.height())) { + emit heightChanged(); + emit availableHeightChanged(); + } +} + +void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) +{ + Q_D(QQuickPopup); + Q_UNUSED(newPadding); + Q_UNUSED(oldPadding); + d->resizeContent(); +} + QT_END_NAMESPACE #include "moc_qquickpopup_p.cpp" diff --git a/src/templates/qquickpopup_p.h b/src/templates/qquickpopup_p.h index fe485d12..675c43c7 100644 --- a/src/templates/qquickpopup_p.h +++ b/src/templates/qquickpopup_p.h @@ -49,8 +49,10 @@ // #include <QtCore/qobject.h> +#include <QtCore/qmargins.h> #include <QtLabsTemplates/private/qtlabstemplatesglobal_p.h> #include <QtQml/qqml.h> +#include <QtQml/qqmllist.h> #include <QtQml/qqmlparserstatus.h> QT_BEGIN_NAMESPACE @@ -63,16 +65,68 @@ class Q_LABSTEMPLATES_EXPORT QQuickPopup : public QObject, public QQmlParserStat { Q_OBJECT Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL) + Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL) + Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged FINAL) + Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged FINAL) + Q_PROPERTY(qreal availableWidth READ availableWidth NOTIFY availableWidthChanged FINAL) + Q_PROPERTY(qreal availableHeight READ availableHeight NOTIFY availableHeightChanged FINAL) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged FINAL) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged FINAL) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged FINAL) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged FINAL) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged FINAL) + Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL) Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged) Q_PROPERTY(bool modal READ isModal WRITE setModal NOTIFY modalChanged) Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged) Q_PROPERTY(QQuickTransition *enter READ enter WRITE setEnter NOTIFY enterChanged FINAL) Q_PROPERTY(QQuickTransition *exit READ exit WRITE setExit NOTIFY exitChanged FINAL) + Q_PROPERTY(QQmlListProperty<QObject> data READ data FINAL) + Q_CLASSINFO("DefaultProperty", "data") public: explicit QQuickPopup(QObject *parent = Q_NULLPTR); + qreal x() const; + void setX(qreal x); + + qreal y() const; + void setY(qreal y); + + qreal width() const; + void setWidth(qreal width); + + qreal height() const; + void setHeight(qreal height); + + qreal availableWidth() const; + qreal availableHeight() const; + + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + + QQuickItem *background() const; + void setBackground(QQuickItem *background); + QQuickItem *contentItem() const; void setContentItem(QQuickItem *item); @@ -90,11 +144,25 @@ public: QQuickTransition *exit() const; void setExit(QQuickTransition *transition); + QQmlListProperty<QObject> data(); + public Q_SLOTS: void open(); void close(); Q_SIGNALS: + void xChanged(); + void yChanged(); + void widthChanged(); + void heightChanged(); + void availableWidthChanged(); + void availableHeightChanged(); + void paddingChanged(); + void topPaddingChanged(); + void leftPaddingChanged(); + void rightPaddingChanged(); + void bottomPaddingChanged(); + void backgroundChanged(); void contentItemChanged(); void focusChanged(); void modalChanged(); @@ -117,10 +185,13 @@ protected: bool isComponentComplete() const; virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem); + virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding); private: Q_DISABLE_COPY(QQuickPopup) Q_DECLARE_PRIVATE(QQuickPopup) + friend class QQuickPopupItem; }; QT_END_NAMESPACE diff --git a/src/templates/qquickpopup_p_p.h b/src/templates/qquickpopup_p_p.h index 807c8cd9..77366207 100644 --- a/src/templates/qquickpopup_p_p.h +++ b/src/templates/qquickpopup_p_p.h @@ -48,12 +48,14 @@ // We mean it. // +#include "qquickpopup_p.h" + #include <QtCore/private/qobject_p.h> +#include <QtQuick/qquickitem.h> #include <QtQuick/private/qquicktransitionmanager_p_p.h> QT_BEGIN_NAMESPACE -class QQuickItem; class QQuickTransition; class QQuickTransitionManager; class QQuickPopup; @@ -80,6 +82,20 @@ private: QQuickPopupPrivate *popup; }; +class QQuickPopupItem : public QQuickItem +{ + Q_OBJECT + +public: + explicit QQuickPopupItem(QQuickPopup *popup); + +protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + +private: + QQuickPopup *popup; +}; + class QQuickPopupPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QQuickPopup) @@ -87,16 +103,42 @@ class QQuickPopupPrivate : public QObjectPrivate public: QQuickPopupPrivate(); + static QQuickPopupPrivate *get(QQuickPopup *popup) + { + return popup->d_func(); + } + + void init(); + void finalizeEnterTransition(); void finalizeExitTransition(); + void resizeBackground(); + void resizeContent(); + + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + bool focus; bool modal; bool complete; + bool hasTopPadding; + bool hasLeftPadding; + bool hasRightPadding; + bool hasBottomPadding; + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + QQuickItem *background; QQuickItem *contentItem; QQuickOverlay *overlay; QQuickTransition *enter; QQuickTransition *exit; + QQuickPopupItem *popupItem; QQuickPopupTransitionManager transitionManager; }; |