1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qdeclarativecomponent.h"
43 #include "private/qdeclarativecomponent_p.h"
45 #include "private/qdeclarativecompiler_p.h"
46 #include "private/qdeclarativecontext_p.h"
47 #include "private/qdeclarativeengine_p.h"
48 #include "private/qdeclarativevme_p.h"
49 #include "qdeclarative.h"
50 #include "qdeclarativeengine.h"
51 #include "private/qdeclarativebinding_p.h"
52 #include "private/qdeclarativebinding_p_p.h"
53 #include "private/qdeclarativeglobal_p.h"
54 #include "private/qdeclarativescriptparser_p.h"
55 #include "private/qdeclarativedebugtrace_p.h"
56 #include "private/qdeclarativeenginedebug_p.h"
57 #include <QtScript/qscriptvalueiterator.h>
60 #include <QStringList>
61 #include <QtCore/qdebug.h>
62 #include <QApplication>
63 #include <qdeclarativeinfo.h>
70 \class QDeclarativeComponent
72 \brief The QDeclarativeComponent class encapsulates a QML component definition.
75 Components are reusable, encapsulated QML elements with well-defined interfaces.
76 They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
78 A QDeclarativeComponent instance can be created from a QML file.
79 For example, if there is a \c main.qml file like this:
90 The following code loads this QML file as a component, creates an instance of
91 this component using create(), and then queries the \l Item's \l {Item::}{width}
95 QDeclarativeEngine *engine = new QDeclarativeEngine;
96 QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
98 QObject *myObject = component.create();
99 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(myObject);
100 int width = item->width(); // width = 200
104 \section2 Network Components
106 If the URL passed to QDeclarativeComponent is a network resource, or if the QML document references a
107 network resource, the QDeclarativeComponent has to fetch the network data before it is able to create
108 objects. In this case, the QDeclarativeComponent will have a \l {QDeclarativeComponent::Loading}{Loading}
109 \l {QDeclarativeComponent::status()}{status}. An application will have to wait until the component
110 is \l {QDeclarativeComponent::Ready}{Ready} before calling \l {QDeclarativeComponent::create()}.
112 The following example shows how to load a QML file from a network resource. After creating
113 the QDeclarativeComponent, it tests whether the component is loading. If it is, it connects to the
114 QDeclarativeComponent::statusChanged() signal and otherwise calls the \c {continueLoading()} method
115 directly. Note that QDeclarativeComponent::isLoading() may be false for a network component if the
116 component has been cached and is ready immediately.
119 MyApplication::MyApplication()
122 component = new QDeclarativeComponent(engine, QUrl("http://www.example.com/main.qml"));
123 if (component->isLoading())
124 QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
125 this, SLOT(continueLoading()));
130 void MyApplication::continueLoading()
132 if (component->isError()) {
133 qWarning() << component->errors();
135 QObject *myObject = component->create();
140 \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code}
144 \qmlclass Component QDeclarativeComponent
145 \ingroup qml-utility-elements
147 \brief The Component element encapsulates a QML component definition.
149 Components are reusable, encapsulated QML elements with well-defined interfaces.
151 Components are often defined by \l {qdeclarativedocuments.html}{component files} -
152 that is, \c .qml files. The \e Component element essentially allows QML components
153 to be defined inline, within a \l {QML Document}{QML document}, rather than as a separate QML file.
154 This may be useful for reusing a small component within a QML file, or for defining
155 a component that logically belongs with other QML components within a file.
157 For example, here is a component that is used by multiple \l Loader objects.
158 It contains a single item, a \l Rectangle:
160 \snippet doc/src/snippets/declarative/component.qml 0
162 Notice that while a \l Rectangle by itself would be automatically
163 rendered and displayed, this is not the case for the above rectangle
164 because it is defined inside a \c Component. The component encapsulates the
165 QML elements within, as if they were defined in a separate QML
166 file, and is not loaded until requested (in this case, by the
167 two \l Loader objects).
169 Defining a \c Component is similar to defining a \l {QML Document}{QML document}.
170 A QML document has a single top-level item that defines the behaviors and
171 properties of that component, and cannot define properties or behaviors outside
172 of that top-level item. In the same way, a \c Component definition contains a single
173 top level item (which in the above example is a \l Rectangle) and cannot define any
174 data outside of this item, with the exception of an \e id (which in the above example
177 The \c Component element is commonly used to provide graphical components
178 for views. For example, the ListView::delegate property requires a \c Component
179 to specify how each list item is to be displayed.
181 \c Component objects can also be created dynamically using
182 \l{QML:Qt::createComponent()}{Qt.createComponent()}.
186 \qmlattachedsignal Component::onCompleted()
188 Emitted after component "startup" has completed. This can be used to
189 execute script code at startup, once the full QML environment has been
192 The \c {Component::onCompleted} attached property can be applied to
193 any element. The order of running the \c onCompleted scripts is
198 Component.onCompleted: console.log("Completed Running!")
200 Component.onCompleted: console.log("Nested Completed Running!")
207 \qmlattachedsignal Component::onDestruction()
209 Emitted as the component begins destruction. This can be used to undo
210 work done in the onCompleted signal, or other imperative code in your
213 The \c {Component::onDestruction} attached property can be applied to
214 any element. However, it applies to the destruction of the component as
215 a whole, and not the destruction of the specific object. The order of
216 running the \c onDestruction scripts is undefined.
220 Component.onDestruction: console.log("Destruction Beginning!")
222 Component.onDestruction: console.log("Nested Destruction Beginning!")
231 \enum QDeclarativeComponent::Status
233 Specifies the loading status of the QDeclarativeComponent.
235 \value Null This QDeclarativeComponent has no data. Call loadUrl() or setData() to add QML content.
236 \value Ready This QDeclarativeComponent is ready and create() may be called.
237 \value Loading This QDeclarativeComponent is loading network data.
238 \value Error An error has occurred. Call errors() to retrieve a list of \{QDeclarativeError}{errors}.
241 void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *)
243 Q_Q(QDeclarativeComponent);
247 fromTypeData(typeData);
250 emit q->statusChanged(q->status());
253 void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p)
255 Q_Q(QDeclarativeComponent);
259 emit q->progressChanged(p);
262 void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data)
264 url = data->finalUrl();
265 QDeclarativeCompiledData *c = data->compiledData();
268 Q_ASSERT(data->isError());
269 state.errors = data->errors();
277 void QDeclarativeComponentPrivate::clear()
280 typeData->unregisterCallback(this);
294 QDeclarativeComponent::QDeclarativeComponent(QObject *parent)
295 : QObject(*(new QDeclarativeComponentPrivate), parent)
300 Destruct the QDeclarativeComponent.
302 QDeclarativeComponent::~QDeclarativeComponent()
304 Q_D(QDeclarativeComponent);
306 if (d->state.completePending) {
307 qWarning("QDeclarativeComponent: Component destroyed while completion pending");
312 d->typeData->unregisterCallback(d);
313 d->typeData->release();
320 \qmlproperty enumeration Component::status
321 This property holds the status of component loading. It can be one of:
323 \o Component.Null - no data is available for the component
324 \o Component.Ready - the component has been loaded, and can be used to create instances.
325 \o Component.Loading - the component is currently being loaded
326 \o Component.Error - an error occurred while loading the component.
327 Calling errorString() will provide a human-readable description of any errors.
332 \property QDeclarativeComponent::status
333 The component's current \l{QDeclarativeComponent::Status} {status}.
335 QDeclarativeComponent::Status QDeclarativeComponent::status() const
337 Q_D(const QDeclarativeComponent);
341 else if (!d->state.errors.isEmpty())
343 else if (d->engine && d->cc)
350 Returns true if status() == QDeclarativeComponent::Null.
352 bool QDeclarativeComponent::isNull() const
354 return status() == Null;
358 Returns true if status() == QDeclarativeComponent::Ready.
360 bool QDeclarativeComponent::isReady() const
362 return status() == Ready;
366 Returns true if status() == QDeclarativeComponent::Error.
368 bool QDeclarativeComponent::isError() const
370 return status() == Error;
374 Returns true if status() == QDeclarativeComponent::Loading.
376 bool QDeclarativeComponent::isLoading() const
378 return status() == Loading;
382 \qmlproperty real Component::progress
383 The progress of loading the component, from 0.0 (nothing loaded)
388 \property QDeclarativeComponent::progress
389 The progress of loading the component, from 0.0 (nothing loaded)
392 qreal QDeclarativeComponent::progress() const
394 Q_D(const QDeclarativeComponent);
399 \fn void QDeclarativeComponent::progressChanged(qreal progress)
401 Emitted whenever the component's loading progress changes. \a progress will be the
402 current progress between 0.0 (nothing loaded) and 1.0 (finished).
406 \fn void QDeclarativeComponent::statusChanged(QDeclarativeComponent::Status status)
408 Emitted whenever the component's status changes. \a status will be the
413 Create a QDeclarativeComponent with no data and give it the specified
414 \a engine and \a parent. Set the data with setData().
416 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QObject *parent)
417 : QObject(*(new QDeclarativeComponentPrivate), parent)
419 Q_D(QDeclarativeComponent);
424 Create a QDeclarativeComponent from the given \a url and give it the
425 specified \a parent and \a engine.
427 Ensure that the URL provided is full and correct, in particular, use
428 \l QUrl::fromLocalFile() when loading a file from the local filesystem.
432 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QUrl &url, QObject *parent)
433 : QObject(*(new QDeclarativeComponentPrivate), parent)
435 Q_D(QDeclarativeComponent);
441 Create a QDeclarativeComponent from the given \a fileName and give it the specified
442 \a parent and \a engine.
446 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QString &fileName,
448 : QObject(*(new QDeclarativeComponentPrivate), parent)
450 Q_D(QDeclarativeComponent);
452 loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)));
458 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclarativeCompiledData *cc, int start, int count, QObject *parent)
459 : QObject(*(new QDeclarativeComponentPrivate), parent)
461 Q_D(QDeclarativeComponent);
472 Sets the QDeclarativeComponent to use the given QML \a data. If \a url
473 is provided, it is used to set the component name and to provide
474 a base path for items resolved by this component.
476 void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url)
478 Q_D(QDeclarativeComponent);
484 QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url);
486 if (typeData->isCompleteOrError()) {
487 d->fromTypeData(typeData);
489 d->typeData = typeData;
490 d->typeData->registerCallback(d);
494 emit statusChanged(status());
495 emit progressChanged(d->progress);
499 Returns the QDeclarativeContext the component was created in. This is only
500 valid for components created directly from QML.
502 QDeclarativeContext *QDeclarativeComponent::creationContext() const
504 Q_D(const QDeclarativeComponent);
505 if(d->creationContext)
506 return d->creationContext->asQDeclarativeContext();
508 return qmlContext(this);
512 Load the QDeclarativeComponent from the provided \a url.
514 Ensure that the URL provided is full and correct, in particular, use
515 \l QUrl::fromLocalFile() when loading a file from the local filesystem.
517 void QDeclarativeComponent::loadUrl(const QUrl &url)
519 Q_D(QDeclarativeComponent);
523 if ((url.isRelative() && !url.isEmpty())
524 || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
525 d->url = d->engine->baseUrl().resolved(url);
530 QDeclarativeError error;
531 error.setDescription(tr("Invalid empty URL"));
532 d->state.errors << error;
536 QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url);
538 if (data->isCompleteOrError()) {
539 d->fromTypeData(data);
543 d->typeData->registerCallback(d);
544 d->progress = data->progress();
547 emit statusChanged(status());
548 emit progressChanged(d->progress);
552 Return the list of errors that occurred during the last compile or create
553 operation. An empty list is returned if isError() is not set.
555 QList<QDeclarativeError> QDeclarativeComponent::errors() const
557 Q_D(const QDeclarativeComponent);
559 return d->state.errors;
561 return QList<QDeclarativeError>();
565 \qmlmethod string Component::errorString()
567 Returns a human-readable description of any errors.
569 The string includes the file, location, and description of each error.
570 If multiple errors are present they are separated by a newline character.
572 If no errors are present, an empty string is returned.
577 errorString is only meant as a way to get the errors in script
579 QString QDeclarativeComponent::errorString() const
581 Q_D(const QDeclarativeComponent);
585 foreach(const QDeclarativeError &e, d->state.errors) {
586 ret += e.url().toString() + QLatin1Char(':') +
587 QString::number(e.line()) + QLatin1Char(' ') +
588 e.description() + QLatin1Char('\n');
594 \qmlproperty url Component::url
595 The component URL. This is the URL that was used to construct the component.
599 \property QDeclarativeComponent::url
600 The component URL. This is the URL passed to either the constructor,
601 or the loadUrl() or setData() methods.
603 QUrl QDeclarativeComponent::url() const
605 Q_D(const QDeclarativeComponent);
612 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject *parent)
613 : QObject(dd, parent)
618 \qmlmethod object Component::createObject(Item parent, object properties)
620 Creates and returns an object instance of this component that will have
621 the given \a parent and \a properties. The \a properties argument is optional.
622 Returns null if object creation fails.
624 The object will be created in the same context as the one in which the component
625 was created. This function will always return null when called on components
626 which were not created in QML.
628 If you wish to create an object without setting a parent, specify \c null for
629 the \a parent value. Note that if the returned object is to be displayed, you
630 must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent}
631 property, or else the object will not be visible.
633 If a \a parent is not provided to createObject(), a reference to the returned object must be held so that
634 it is not destroyed by the garbage collector. This is true regardless of whether \l{Item::parent} is set afterwards,
635 since setting the Item parent does not change object ownership; only the graphical parent is changed.
637 As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a
638 map of initial property values for the created object. These values are applied before object
639 creation is finalized. (This is more efficient than setting property values after object creation,
640 particularly where large sets of property values are defined, and also allows property bindings
641 to be set up before the object is created.)
643 The \a properties argument is specified as a map of property-value items. For example, the code
644 below creates an object with initial \c x and \c y values of 100 and 200, respectively:
647 var component = Qt.createComponent("Button.qml");
648 if (component.status == Component.Ready)
649 component.createObject(parent, {"x": 100, "y": 100});
652 Dynamically created instances can be deleted with the \c destroy() method.
653 See \l {Dynamic Object Management in QML} for more information.
658 A version of create which returns a scriptObject, for use in script.
659 This function will only work on components created in QML.
661 Sets graphics object parent because forgetting to do this is a frequent
664 QScriptValue QDeclarativeComponent::createObject(QObject* parent)
666 Q_D(QDeclarativeComponent);
667 return d->createObject(parent, QScriptValue(QScriptValue::NullValue));
672 Overloadable method allows properties to be set during creation
674 QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap)
676 Q_D(QDeclarativeComponent);
678 if (!valuemap.isObject() || valuemap.isArray()) {
679 qmlInfo(this) << tr("createObject: value is not an object");
680 return QScriptValue(QScriptValue::NullValue);
682 return d->createObject(parent, valuemap);
685 QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap)
687 Q_Q(QDeclarativeComponent);
688 QDeclarativeContext* ctxt = q->creationContext();
690 ctxt = engine->rootContext();
692 return QScriptValue(QScriptValue::NullValue);
693 QObject* ret = q->beginCreate(ctxt);
696 return QScriptValue(QScriptValue::NullValue);
700 ret->setParent(publicParent);
701 QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
703 bool needParent = false;
705 for (int ii = 0; ii < functions.count(); ++ii) {
706 QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent);
707 if (res == QDeclarativePrivate::Parented) {
710 } else if (res == QDeclarativePrivate::IncompatibleParent) {
716 qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
719 QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
720 QDeclarativeData::get(ret, true)->setImplicitDestructible();
721 QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
723 if (valuemap.isObject() && !valuemap.isArray()) {
724 //Iterate through and assign properties
725 QScriptValueIterator it(valuemap);
726 while (it.hasNext()) {
728 QScriptValue prop = newObject;
729 QString propName = it.name();
730 int index = propName.indexOf(QLatin1Char('.'));
732 QString subProp = propName;
735 subProp = propName.mid(lastIndex, index - lastIndex);
736 prop = prop.property(subProp);
737 lastIndex = index + 1;
738 index = propName.indexOf(QLatin1Char('.'), index + 1);
740 prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value());
742 newObject.setProperty(propName, it.value());
753 Create an object instance from this component. Returns 0 if creation
754 failed. \a context specifies the context within which to create the object
757 If \a context is 0 (the default), it will create the instance in the
758 engine' s \l {QDeclarativeEngine::rootContext()}{root context}.
760 QObject *QDeclarativeComponent::create(QDeclarativeContext *context)
762 Q_D(QDeclarativeComponent);
765 context = d->engine->rootContext();
767 QObject *rv = beginCreate(context);
773 This method provides more advanced control over component instance creation.
774 In general, programmers should use QDeclarativeComponent::create() to create a
777 Create an object instance from this component. Returns 0 if creation
778 failed. \a context specifies the context within which to create the object
781 When QDeclarativeComponent constructs an instance, it occurs in three steps:
783 \i The object hierarchy is created, and constant values are assigned.
784 \i Property bindings are evaluated for the the first time.
785 \i If applicable, QDeclarativeParserStatus::componentComplete() is called on objects.
787 QDeclarativeComponent::beginCreate() differs from QDeclarativeComponent::create() in that it
788 only performs step 1. QDeclarativeComponent::completeCreate() must be called to
789 complete steps 2 and 3.
791 This breaking point is sometimes useful when using attached properties to
792 communicate information to an instantiated component, as it allows their
793 initial values to be configured before property bindings take effect.
795 QObject *QDeclarativeComponent::beginCreate(QDeclarativeContext *context)
797 Q_D(QDeclarativeComponent);
798 QObject *rv = d->beginCreate(context?QDeclarativeContextData::get(context):0, QBitField());
800 QDeclarativeData *ddata = QDeclarativeData::get(rv);
802 ddata->indestructible = true;
808 QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, const QBitField &bindings)
810 Q_Q(QDeclarativeComponent);
812 qWarning("QDeclarativeComponent: Cannot create a component in a null context");
816 if (!context->isValid()) {
817 qWarning("QDeclarativeComponent: Cannot create a component in an invalid context");
821 if (context->engine != engine) {
822 qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine");
826 if (state.completePending) {
827 qWarning("QDeclarativeComponent: Cannot create new component instance before completing the previous");
832 qWarning("QDeclarativeComponent: Component is not ready");
836 return begin(context, creationContext, cc, start, count, &state, 0, bindings);
839 QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentContext,
840 QDeclarativeContextData *componentCreationContext,
841 QDeclarativeCompiledData *component, int start, int count,
842 ConstructionState *state, QList<QDeclarativeError> *errors,
843 const QBitField &bindings)
845 QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentContext->engine);
846 bool isRoot = !enginePriv->inBeginCreate;
848 Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided
849 Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided
852 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
853 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, component->url);
856 QDeclarativeContextData *ctxt = new QDeclarativeContextData;
857 ctxt->isInternal = true;
858 ctxt->url = component->url;
859 ctxt->imports = component->importCache;
861 // Nested global imports
862 if (componentCreationContext && start != -1)
863 ctxt->importedScripts = componentCreationContext->importedScripts;
865 component->importCache->addref();
866 ctxt->setParent(parentContext);
868 enginePriv->inBeginCreate = true;
871 QObject *rv = vme.run(ctxt, component, start, count, bindings);
874 if(errors) *errors = vme.errors();
875 else state->errors = vme.errors();
879 enginePriv->inBeginCreate = false;
881 state->bindValues = enginePriv->bindValues;
882 state->parserStatus = enginePriv->parserStatus;
883 state->finalizedParserStatus = enginePriv->finalizedParserStatus;
884 state->componentAttached = enginePriv->componentAttached;
885 if (state->componentAttached)
886 state->componentAttached->prev = &state->componentAttached;
888 enginePriv->componentAttached = 0;
889 enginePriv->bindValues.clear();
890 enginePriv->parserStatus.clear();
891 enginePriv->finalizedParserStatus.clear();
892 state->completePending = true;
893 enginePriv->inProgressCreations++;
896 if (enginePriv->isDebugging && rv) {
897 if (!parentContext->isInternal)
898 parentContext->asQDeclarativeContextPrivate()->instances.append(rv);
899 QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv);
905 void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *enginePriv,
906 QObject *object, ConstructionState *state)
908 bool isRoot = !enginePriv->inBeginCreate;
909 enginePriv->inBeginCreate = true;
912 vme.runDeferred(object);
915 state->errors = vme.errors();
918 enginePriv->inBeginCreate = false;
920 state->bindValues = enginePriv->bindValues;
921 state->parserStatus = enginePriv->parserStatus;
922 state->finalizedParserStatus = enginePriv->finalizedParserStatus;
923 state->componentAttached = enginePriv->componentAttached;
924 if (state->componentAttached)
925 state->componentAttached->prev = &state->componentAttached;
927 enginePriv->componentAttached = 0;
928 enginePriv->bindValues.clear();
929 enginePriv->parserStatus.clear();
930 enginePriv->finalizedParserStatus.clear();
931 state->completePending = true;
932 enginePriv->inProgressCreations++;
936 void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state)
938 if (state->completePending) {
940 for (int ii = 0; ii < state->bindValues.count(); ++ii) {
941 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bv =
942 state->bindValues.at(ii);
943 for (int jj = 0; jj < bv.count; ++jj) {
946 bv.at(jj)->m_mePtr = 0;
947 bv.at(jj)->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor |
948 QDeclarativePropertyPrivate::DontRemoveBinding);
951 QDeclarativeEnginePrivate::clear(bv);
954 for (int ii = 0; ii < state->parserStatus.count(); ++ii) {
955 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> ps =
956 state->parserStatus.at(ii);
958 for (int jj = ps.count - 1; jj >= 0; --jj) {
959 QDeclarativeParserStatus *status = ps.at(jj);
960 if (status && status->d) {
962 status->componentComplete();
965 QDeclarativeEnginePrivate::clear(ps);
968 for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) {
969 QPair<QDeclarativeGuard<QObject>, int> status = state->finalizedParserStatus.at(ii);
970 QObject *obj = status.first;
972 void *args[] = { 0 };
973 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
974 status.second, args);
978 //componentComplete() can register additional finalization objects
979 //that are then never handled. Handle them manually here.
980 if (1 == enginePriv->inProgressCreations) {
981 for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) {
982 QPair<QDeclarativeGuard<QObject>, int> status = enginePriv->finalizedParserStatus.at(ii);
983 QObject *obj = status.first;
985 void *args[] = { 0 };
986 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
987 status.second, args);
990 enginePriv->finalizedParserStatus.clear();
993 while (state->componentAttached) {
994 QDeclarativeComponentAttached *a = state->componentAttached;
996 QDeclarativeData *d = QDeclarativeData::get(a->parent());
998 Q_ASSERT(d->context);
999 a->add(&d->context->componentAttached);
1000 emit a->completed();
1003 state->bindValues.clear();
1004 state->parserStatus.clear();
1005 state->finalizedParserStatus.clear();
1006 state->completePending = false;
1008 enginePriv->inProgressCreations--;
1009 if (0 == enginePriv->inProgressCreations) {
1010 while (enginePriv->erroredBindings) {
1011 enginePriv->warning(enginePriv->erroredBindings->error);
1012 enginePriv->erroredBindings->removeError();
1019 This method provides more advanced control over component instance creation.
1020 In general, programmers should use QDeclarativeComponent::create() to create a
1023 Complete a component creation begin with QDeclarativeComponent::beginCreate().
1025 void QDeclarativeComponent::completeCreate()
1027 Q_D(QDeclarativeComponent);
1028 d->completeCreate();
1031 void QDeclarativeComponentPrivate::completeCreate()
1033 if (state.completePending) {
1034 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1035 complete(ep, &state);
1037 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
1041 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
1042 : QObject(parent), prev(0), next(0)
1046 QDeclarativeComponentAttached::~QDeclarativeComponentAttached()
1048 if (prev) *prev = next;
1049 if (next) next->prev = prev;
1057 QDeclarativeComponentAttached *QDeclarativeComponent::qmlAttachedProperties(QObject *obj)
1059 QDeclarativeComponentAttached *a = new QDeclarativeComponentAttached(obj);
1061 QDeclarativeEngine *engine = qmlEngine(obj);
1065 if (QDeclarativeEnginePrivate::get(engine)->inBeginCreate) {
1066 QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
1067 a->add(&p->componentAttached);
1069 QDeclarativeData *d = QDeclarativeData::get(obj);
1071 Q_ASSERT(d->context);
1072 a->add(&d->context->componentAttached);