diff options
Diffstat (limited to 'src/quicktemplates2')
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton.cpp | 30 | ||||
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton_p.h | 3 | ||||
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton_p_p.h | 6 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol.cpp | 25 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol_p_p.h | 8 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdeferredexecute.cpp | 110 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdeferredexecute_p_p.h | 79 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdeferredpointer_p_p.h | 189 | ||||
-rw-r--r-- | src/quicktemplates2/quicktemplates2.pri | 3 |
9 files changed, 442 insertions, 11 deletions
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index efd06bd0..f87ee0ef 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -37,6 +37,7 @@ #include "qquickabstractbutton_p.h" #include "qquickabstractbutton_p_p.h" #include "qquickbuttongroup_p.h" +#include "qquickdeferredexecute_p_p.h" #include <QtGui/qstylehints.h> #include <QtGui/qguiapplication.h> @@ -130,6 +131,12 @@ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() { } +QQuickItem *QQuickAbstractButtonPrivate::getContentItem() +{ + executeContentItem(); + return QQuickControlPrivate::getContentItem(); +} + void QQuickAbstractButtonPrivate::handlePress(const QPointF &point) { Q_Q(QQuickAbstractButton); @@ -258,6 +265,12 @@ void QQuickAbstractButtonPrivate::toggle(bool value) emit q->toggled(); } +void QQuickAbstractButtonPrivate::executeIndicator() +{ + Q_Q(QQuickAbstractButton); + quickExecuteDeferred(q, QStringLiteral("indicator"), indicator); +} + QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const { Q_Q(const QQuickAbstractButton); @@ -545,7 +558,8 @@ void QQuickAbstractButton::setAutoRepeat(bool repeat) */ QQuickItem *QQuickAbstractButton::indicator() const { - Q_D(const QQuickAbstractButton); + QQuickAbstractButtonPrivate *d = const_cast<QQuickAbstractButtonPrivate *>(d_func()); + d->executeIndicator(); return d->indicator; } @@ -555,14 +569,15 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator) if (d->indicator == indicator) return; - QQuickControlPrivate::destroyDelegate(d->indicator, this); + delete d->indicator; d->indicator = indicator; if (indicator) { if (!indicator->parentItem()) indicator->setParentItem(this); indicator->setAcceptedMouseButtons(Qt::LeftButton); } - emit indicatorChanged(); + if (!d->indicator.isExecuting()) + emit indicatorChanged(); } /*! @@ -576,6 +591,15 @@ void QQuickAbstractButton::toggle() setChecked(!d->checked); } +void QQuickAbstractButton::componentComplete() +{ + Q_D(QQuickAbstractButton); + d->executeIndicator(); + d->executeBackground(); + d->executeContentItem(); + QQuickControl::componentComplete(); +} + void QQuickAbstractButton::focusOutEvent(QFocusEvent *event) { Q_D(QQuickAbstractButton); diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h index 71884bf6..a1210567 100644 --- a/src/quicktemplates2/qquickabstractbutton_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p.h @@ -64,6 +64,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickContr Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) Q_PROPERTY(bool autoExclusive READ autoExclusive WRITE setAutoExclusive NOTIFY autoExclusiveChanged FINAL) Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL) + Q_CLASSINFO("DeferredPropertyNames", "background,contentItem,indicator") public: explicit QQuickAbstractButton(QQuickItem *parent = nullptr); @@ -117,6 +118,8 @@ Q_SIGNALS: protected: QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent); + void componentComplete() override; + void focusOutEvent(QFocusEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index 39af6896..5a2a52c7 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -67,6 +67,8 @@ public: return button->d_func(); } + QQuickItem *getContentItem() override; + void handlePress(const QPointF &point) override; void handleMove(const QPointF &point) override; void handleRelease(const QPointF &point) override; @@ -85,6 +87,8 @@ public: void toggle(bool value); + void executeIndicator(); + QString text; bool down; bool explicitDown; @@ -100,7 +104,7 @@ public: int repeatTimer; QPointF pressPoint; Qt::MouseButtons pressButtons; - QQuickItem *indicator; + QQuickDeferredPointer<QQuickItem> indicator; QQuickButtonGroup *group; }; diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 908c0f42..51248745 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -48,6 +48,7 @@ #include "qquickpopup_p.h" #include "qquickpopupitem_p_p.h" #include "qquickapplicationwindow_p.h" +#include "qquickdeferredexecute_p_p.h" #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpa/qplatformtheme.h> @@ -290,7 +291,7 @@ void QQuickControlPrivate::setContentItem_helper(QQuickItem *item, bool notify) return; q->contentItemChange(item, contentItem); - destroyDelegate(contentItem, q); + delete contentItem; contentItem = item; if (item) { @@ -300,7 +301,7 @@ void QQuickControlPrivate::setContentItem_helper(QQuickItem *item, bool notify) resizeContent(); } - if (notify) + if (notify && !contentItem.isExecuting()) emit q->contentItemChanged(); } @@ -933,6 +934,18 @@ QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item) return QLocale(); } +void QQuickControlPrivate::executeContentItem() +{ + Q_Q(QQuickControl); + quickExecuteDeferred(q, QStringLiteral("contentItem"), contentItem); +} + +void QQuickControlPrivate::executeBackground() +{ + Q_Q(QQuickControl); + quickExecuteDeferred(q, QStringLiteral("background"), background); +} + /* Cancels incubation recursively to avoid "Object destroyed during incubation" (QTBUG-50992) */ @@ -1214,7 +1227,8 @@ void QQuickControl::setWheelEnabled(bool enabled) */ QQuickItem *QQuickControl::background() const { - Q_D(const QQuickControl); + QQuickControlPrivate *d = const_cast<QQuickControlPrivate *>(d_func()); + d->executeBackground(); return d->background; } @@ -1224,7 +1238,7 @@ void QQuickControl::setBackground(QQuickItem *background) if (d->background == background) return; - QQuickControlPrivate::destroyDelegate(d->background, this); + delete d->background; d->background = background; if (background) { background->setParentItem(this); @@ -1233,7 +1247,8 @@ void QQuickControl::setBackground(QQuickItem *background) if (isComponentComplete()) d->resizeBackground(); } - emit backgroundChanged(); + if (!d->background.isExecuting()) + emit backgroundChanged(); } /*! diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index 73e1b44c..84a42fa5 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -49,6 +49,7 @@ // #include "qquickcontrol_p.h" +#include "qquickdeferredpointer_p_p.h" #include <QtQuick/private/qquickitem_p.h> #include <QtQml/private/qlazilyallocated_p.h> @@ -126,6 +127,9 @@ public: static bool calcHoverEnabled(const QQuickItem *item); #endif + void executeContentItem(); + void executeBackground(); + static void destroyDelegate(QObject *object, QObject *parent); struct ExtraData { @@ -155,8 +159,8 @@ public: QLocale locale; Qt::FocusPolicy focusPolicy; Qt::FocusReason focusReason; - QQuickItem *background; - QQuickItem *contentItem; + QQuickDeferredPointer<QQuickItem> background; + QQuickDeferredPointer<QQuickItem> contentItem; QQuickAccessibleAttached *accessibleAttached; }; diff --git a/src/quicktemplates2/qquickdeferredexecute.cpp b/src/quicktemplates2/qquickdeferredexecute.cpp new file mode 100644 index 00000000..7ec4e8e8 --- /dev/null +++ b/src/quicktemplates2/qquickdeferredexecute.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** 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 "qquickdeferredexecute_p_p.h" + +#include <QtQml/qqmlengine.h> +#include <QtQml/private/qqmldata_p.h> +#include <QtQml/private/qqmlcomponent_p.h> +#include <QtQml/private/qqmlobjectcreator_p.h> + +QT_BEGIN_NAMESPACE + +namespace QtQuickPrivate { + +static void beginDeferred(QQmlEnginePrivate *enginePriv, const QQmlProperty &property, QQmlComponentPrivate::DeferredState *deferredState) +{ + QObject *object = property.object(); + QQmlData *ddata = QQmlData::get(object); + Q_ASSERT(!ddata->deferredData.isEmpty()); + + int propertyIndex = property.index(); + + for (auto dit = ddata->deferredData.rbegin(); dit != ddata->deferredData.rend(); ++dit) { + QQmlData::DeferredData *deferData = *dit; + + auto range = deferData->bindings.equal_range(propertyIndex); + if (range.first == deferData->bindings.end()) + continue; + + QQmlComponentPrivate::ConstructionState *state = new QQmlComponentPrivate::ConstructionState; + state->completePending = true; + + QQmlContextData *creationContext = nullptr; + state->creator.reset(new QQmlObjectCreator(deferData->context->parent, deferData->compilationUnit, creationContext)); + + enginePriv->inProgressCreations++; + + typedef QMultiHash<int, const QV4::CompiledData::Binding *> QV4PropertyBindingHash; + auto it = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.second); + auto last = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.first); + while (it != last) { + if (!state->creator->populateDeferredBinding(property, deferData, *it)) + state->errors << state->creator->errors; + ++it; + } + + deferredState->constructionStates += state; + + // Cleanup any remaining deferred bindings for this property, also in inner contexts, + // to avoid executing them later and overriding the property that was just populated. + while (dit != ddata->deferredData.rend()) { + (*dit)->bindings.remove(propertyIndex); + ++dit; + } + break; + } +} + +void executeDeferred(QObject *object, const QString &property) +{ + QQmlData *data = QQmlData::get(object); + if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); + + QQmlComponentPrivate::DeferredState state; + beginDeferred(ep, QQmlProperty(object, property), &state); + + // Release deferred data for those compilation units that no longer have deferred bindings + data->releaseDeferredData(); + + QQmlComponentPrivate::completeDeferred(ep, &state); + } +} + +} // QtQuickPrivate + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickdeferredexecute_p_p.h b/src/quicktemplates2/qquickdeferredexecute_p_p.h new file mode 100644 index 00000000..2157d7ef --- /dev/null +++ b/src/quicktemplates2/qquickdeferredexecute_p_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKDEFERREDEXECUTE_P_P_H +#define QQUICKDEFERREDEXECUTE_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h> + +QT_BEGIN_NAMESPACE + +class QString; +class QObject; + +namespace QtQuickPrivate { + void executeDeferred(QObject *object, const QString &property); +} + +template<typename T> +void quickExecuteDeferred(QObject *object, const QString &property, QQuickDeferredPointer<T> &delegate) +{ + if (!delegate.isNull() || delegate.wasExecuted()) + return; + + delegate.setExecuting(true); + QtQuickPrivate::executeDeferred(object, property); + delegate.setExecuting(false); + + if (!delegate.isNull()) + delegate.setExecuted(); +} + +QT_END_NAMESPACE + +#endif // QQUICKDEFERREDEXECUTE_P_P_H diff --git a/src/quicktemplates2/qquickdeferredpointer_p_p.h b/src/quicktemplates2/qquickdeferredpointer_p_p.h new file mode 100644 index 00000000..c793964f --- /dev/null +++ b/src/quicktemplates2/qquickdeferredpointer_p_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKDEFERREDPOINTER_P_P_H +#define QQUICKDEFERREDPOINTER_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +template<typename T> +class QQuickDeferredPointer +{ +public: + inline QQuickDeferredPointer(); + inline QQuickDeferredPointer(T *); + inline QQuickDeferredPointer(const QQuickDeferredPointer<T> &o); + + inline bool isNull() const; + + inline bool wasExecuted() const; + inline void setExecuted(); + + inline bool isExecuting() const; + inline void setExecuting(bool); + + inline operator T*() const; + inline operator bool() const; + + inline T *data() const; + inline T *operator*() const; + inline T *operator->() const; + + inline QQuickDeferredPointer<T> &operator=(T *); + inline QQuickDeferredPointer<T> &operator=(const QQuickDeferredPointer &o); + +private: + quintptr ptr_value; + + static const quintptr WasExecutedBit = 0x1; + static const quintptr IsExecutingBit = 0x2; + static const quintptr FlagsMask = WasExecutedBit | IsExecutingBit; +}; + +template<typename T> +QQuickDeferredPointer<T>::QQuickDeferredPointer() +: ptr_value(0) +{ +} + +template<typename T> +QQuickDeferredPointer<T>::QQuickDeferredPointer(T *v) +: ptr_value(quintptr(v)) +{ + Q_ASSERT((ptr_value & FlagsMask) == 0); +} + +template<typename T> +QQuickDeferredPointer<T>::QQuickDeferredPointer(const QQuickDeferredPointer<T> &o) +: ptr_value(o.ptr_value) +{ +} + +template<typename T> +bool QQuickDeferredPointer<T>::isNull() const +{ + return 0 == (ptr_value & (~FlagsMask)); +} + +template<typename T> +bool QQuickDeferredPointer<T>::wasExecuted() const +{ + return ptr_value & WasExecutedBit; +} + +template<typename T> +void QQuickDeferredPointer<T>::setExecuted() +{ + ptr_value |= WasExecutedBit; +} + +template<typename T> +bool QQuickDeferredPointer<T>::isExecuting() const +{ + return ptr_value & IsExecutingBit; +} + +template<typename T> +void QQuickDeferredPointer<T>::setExecuting(bool b) +{ + if (b) + ptr_value |= IsExecutingBit; + else + ptr_value &= ~IsExecutingBit; +} + +template<typename T> +QQuickDeferredPointer<T>::operator T*() const +{ + return data(); +} + +template<typename T> +QQuickDeferredPointer<T>::operator bool() const +{ + return !isNull(); +} + +template<typename T> +T *QQuickDeferredPointer<T>::data() const +{ + return (T *)(ptr_value & ~FlagsMask); +} + +template<typename T> +T *QQuickDeferredPointer<T>::operator*() const +{ + return (T *)(ptr_value & ~FlagsMask); +} + +template<typename T> +T *QQuickDeferredPointer<T>::operator->() const +{ + return (T *)(ptr_value & ~FlagsMask); +} + +template<typename T> +QQuickDeferredPointer<T> &QQuickDeferredPointer<T>::operator=(T *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagsMask); + return *this; +} + +template<typename T> +QQuickDeferredPointer<T> &QQuickDeferredPointer<T>::operator=(const QQuickDeferredPointer &o) +{ + ptr_value = o.ptr_value; + return *this; +} + +QT_END_NAMESPACE + +#endif // QQUICKDEFERREDPOINTER_P_P_H diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index a7570ec5..95039681 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -15,6 +15,8 @@ HEADERS += \ $$PWD/qquickcontainer_p_p.h \ $$PWD/qquickcontrol_p.h \ $$PWD/qquickcontrol_p_p.h \ + $$PWD/qquickdeferredexecute_p_p.h \ + $$PWD/qquickdeferredpointer_p_p.h \ $$PWD/qquickdelaybutton_p.h \ $$PWD/qquickdial_p.h \ $$PWD/qquickdialog_p.h \ @@ -91,6 +93,7 @@ SOURCES += \ $$PWD/qquickcombobox.cpp \ $$PWD/qquickcontainer.cpp \ $$PWD/qquickcontrol.cpp \ + $$PWD/qquickdeferredexecute.cpp \ $$PWD/qquickdelaybutton.cpp \ $$PWD/qquickdial.cpp \ $$PWD/qquickdialog.cpp \ |