Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecomponent.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
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
14 ** this package.
15 **
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.
23 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativecomponent.h"
43 #include "private/qdeclarativecomponent_p.h"
44
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>
58
59 #include <QStack>
60 #include <QStringList>
61 #include <QtCore/qdebug.h>
62 #include <QApplication>
63 #include <qdeclarativeinfo.h>
64
65 QT_BEGIN_NAMESPACE
66
67 class QByteArray;
68
69 /*!
70     \class QDeclarativeComponent
71     \since 4.7
72     \brief The QDeclarativeComponent class encapsulates a QML component definition.
73     \mainclass
74
75     Components are reusable, encapsulated QML elements with well-defined interfaces.
76     They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
77
78     A QDeclarativeComponent instance can be created from a QML file.
79     For example, if there is a \c main.qml file like this:
80
81     \qml
82     import QtQuick 1.0
83
84     Item {
85         width: 200
86         height: 200
87     }
88     \endqml
89
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}
92     value:
93
94     \code
95     QDeclarativeEngine *engine = new QDeclarativeEngine;
96     QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
97
98     QObject *myObject = component.create();
99     QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(myObject);
100     int width = item->width();  // width = 200
101     \endcode
102
103
104     \section2 Network Components
105
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()}.
111
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.
117
118     \code
119     MyApplication::MyApplication()
120     {
121         // ...
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()));
126         else
127             continueLoading();
128     }
129
130     void MyApplication::continueLoading()
131     {
132         if (component->isError()) {
133             qWarning() << component->errors();
134         } else {
135             QObject *myObject = component->create();
136         }
137     }
138     \endcode
139
140     \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code}
141 */
142
143 /*!
144     \qmlclass Component QDeclarativeComponent
145     \ingroup qml-utility-elements
146     \since 4.7
147     \brief The Component element encapsulates a QML component definition.
148
149     Components are reusable, encapsulated QML elements with well-defined interfaces.
150
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.
156
157     For example, here is a component that is used by multiple \l Loader objects.
158     It contains a single item, a \l Rectangle:
159
160     \snippet doc/src/snippets/declarative/component.qml 0
161
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).
168
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
175     is \e redSquare).
176
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.
180
181     \c Component objects can also be created dynamically using
182     \l{QML:Qt::createComponent()}{Qt.createComponent()}.
183 */
184
185 /*!
186     \qmlattachedsignal Component::onCompleted()
187
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
190     established.
191
192     The \c {Component::onCompleted} attached property can be applied to
193     any element.  The order of running the \c onCompleted scripts is
194     undefined.
195
196     \qml
197     Rectangle {
198         Component.onCompleted: console.log("Completed Running!")
199         Rectangle {
200             Component.onCompleted: console.log("Nested Completed Running!")
201         }
202     }
203     \endqml
204 */
205
206 /*!
207     \qmlattachedsignal Component::onDestruction()
208
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
211     application.
212
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.
217
218     \qml
219     Rectangle {
220         Component.onDestruction: console.log("Destruction Beginning!")
221         Rectangle {
222             Component.onDestruction: console.log("Nested Destruction Beginning!")
223         }
224     }
225     \endqml
226
227     \sa QtDeclarative
228 */
229
230 /*!
231     \enum QDeclarativeComponent::Status
232     
233     Specifies the loading status of the QDeclarativeComponent.
234
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}.
239 */
240
241 void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *)
242 {
243     Q_Q(QDeclarativeComponent);
244
245     Q_ASSERT(typeData);
246
247     fromTypeData(typeData);
248     typeData = 0;
249
250     emit q->statusChanged(q->status());
251 }
252
253 void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p)
254 {
255     Q_Q(QDeclarativeComponent);
256
257     progress = p;
258
259     emit q->progressChanged(p);
260 }
261
262 void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data)
263 {
264     url = data->finalUrl();
265     QDeclarativeCompiledData *c = data->compiledData();
266
267     if (!c) {
268         Q_ASSERT(data->isError());
269         state.errors = data->errors();
270     } else {
271         cc = c;
272     }
273
274     data->release();
275 }
276
277 void QDeclarativeComponentPrivate::clear()
278 {
279     if (typeData) {
280         typeData->unregisterCallback(this);
281         typeData->release();
282         typeData = 0;
283     }
284         
285     if (cc) { 
286         cc->release();
287         cc = 0;
288     }
289 }
290
291 /*!
292     \internal
293 */
294 QDeclarativeComponent::QDeclarativeComponent(QObject *parent)
295     : QObject(*(new QDeclarativeComponentPrivate), parent)
296 {
297 }
298
299 /*!
300     Destruct the QDeclarativeComponent.
301 */
302 QDeclarativeComponent::~QDeclarativeComponent()
303 {
304     Q_D(QDeclarativeComponent);
305
306     if (d->state.completePending) {
307         qWarning("QDeclarativeComponent: Component destroyed while completion pending");
308         d->completeCreate();
309     }
310
311     if (d->typeData) {
312         d->typeData->unregisterCallback(d);
313         d->typeData->release();
314     }
315     if (d->cc)
316         d->cc->release();
317 }
318
319 /*!
320     \qmlproperty enumeration Component::status
321     This property holds the status of component loading.  It can be one of:
322     \list
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.
328     \endlist
329  */
330
331 /*!
332     \property QDeclarativeComponent::status
333     The component's current \l{QDeclarativeComponent::Status} {status}.
334  */
335 QDeclarativeComponent::Status QDeclarativeComponent::status() const
336 {
337     Q_D(const QDeclarativeComponent);
338
339     if (d->typeData)
340         return Loading;
341     else if (!d->state.errors.isEmpty())
342         return Error;
343     else if (d->engine && d->cc)
344         return Ready;
345     else
346         return Null;
347 }
348
349 /*!
350     Returns true if status() == QDeclarativeComponent::Null.
351 */
352 bool QDeclarativeComponent::isNull() const
353 {
354     return status() == Null;
355 }
356
357 /*!
358     Returns true if status() == QDeclarativeComponent::Ready.
359 */
360 bool QDeclarativeComponent::isReady() const
361 {
362     return status() == Ready;
363 }
364
365 /*!
366     Returns true if status() == QDeclarativeComponent::Error.
367 */
368 bool QDeclarativeComponent::isError() const
369 {
370     return status() == Error;
371 }
372
373 /*!
374     Returns true if status() == QDeclarativeComponent::Loading.
375 */
376 bool QDeclarativeComponent::isLoading() const
377 {
378     return status() == Loading;
379 }
380
381 /*!
382     \qmlproperty real Component::progress
383     The progress of loading the component, from 0.0 (nothing loaded)
384     to 1.0 (finished).
385 */
386
387 /*!
388     \property QDeclarativeComponent::progress
389     The progress of loading the component, from 0.0 (nothing loaded)
390     to 1.0 (finished).
391 */
392 qreal QDeclarativeComponent::progress() const
393 {
394     Q_D(const QDeclarativeComponent);
395     return d->progress;
396 }
397
398 /*!
399     \fn void QDeclarativeComponent::progressChanged(qreal progress)
400
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).
403 */
404
405 /*!
406     \fn void QDeclarativeComponent::statusChanged(QDeclarativeComponent::Status status)
407
408     Emitted whenever the component's status changes.  \a status will be the
409     new status.
410 */
411
412 /*!
413     Create a QDeclarativeComponent with no data and give it the specified
414     \a engine and \a parent. Set the data with setData().
415 */
416 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QObject *parent)
417     : QObject(*(new QDeclarativeComponentPrivate), parent)
418 {
419     Q_D(QDeclarativeComponent);
420     d->engine = engine;
421 }
422
423 /*!
424     Create a QDeclarativeComponent from the given \a url and give it the
425     specified \a parent and \a engine.
426
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.
429
430     \sa loadUrl()
431 */
432 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QUrl &url, QObject *parent)
433 : QObject(*(new QDeclarativeComponentPrivate), parent)
434 {
435     Q_D(QDeclarativeComponent);
436     d->engine = engine;
437     loadUrl(url);
438 }
439
440 /*!
441     Create a QDeclarativeComponent from the given \a fileName and give it the specified 
442     \a parent and \a engine.
443
444     \sa loadUrl()
445 */
446 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const QString &fileName, 
447                            QObject *parent)
448 : QObject(*(new QDeclarativeComponentPrivate), parent)
449 {
450     Q_D(QDeclarativeComponent);
451     d->engine = engine;
452     loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)));
453 }
454
455 /*!
456     \internal
457 */
458 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclarativeCompiledData *cc, int start, int count, QObject *parent)
459     : QObject(*(new QDeclarativeComponentPrivate), parent)
460 {
461     Q_D(QDeclarativeComponent);
462     d->engine = engine;
463     d->cc = cc;
464     cc->addref();
465     d->start = start;
466     d->count = count;
467     d->url = cc->url;
468     d->progress = 1.0;
469 }
470
471 /*!
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.
475 */
476 void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url)
477 {
478     Q_D(QDeclarativeComponent);
479
480     d->clear();
481
482     d->url = url;
483
484     QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url);
485     
486     if (typeData->isCompleteOrError()) {
487         d->fromTypeData(typeData);
488     } else {
489         d->typeData = typeData;
490         d->typeData->registerCallback(d);
491     }
492
493     d->progress = 1.0;
494     emit statusChanged(status());
495     emit progressChanged(d->progress);
496 }
497
498 /*!
499 Returns the QDeclarativeContext the component was created in.  This is only
500 valid for components created directly from QML.
501 */
502 QDeclarativeContext *QDeclarativeComponent::creationContext() const
503 {
504     Q_D(const QDeclarativeComponent);
505     if(d->creationContext)
506         return d->creationContext->asQDeclarativeContext();
507
508     return qmlContext(this);
509 }
510
511 /*!
512     Load the QDeclarativeComponent from the provided \a url.
513
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.
516 */
517 void QDeclarativeComponent::loadUrl(const QUrl &url)
518 {
519     Q_D(QDeclarativeComponent);
520
521     d->clear();
522
523     if ((url.isRelative() && !url.isEmpty())
524     || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
525         d->url = d->engine->baseUrl().resolved(url);
526     else
527         d->url = url;
528
529     if (url.isEmpty()) {
530         QDeclarativeError error;
531         error.setDescription(tr("Invalid empty URL"));
532         d->state.errors << error;
533         return;
534     }
535
536     QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url);
537
538     if (data->isCompleteOrError()) {
539         d->fromTypeData(data);
540         d->progress = 1.0;
541     } else {
542         d->typeData = data;
543         d->typeData->registerCallback(d);
544         d->progress = data->progress();
545     }
546
547     emit statusChanged(status());
548     emit progressChanged(d->progress);
549 }
550
551 /*!
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.
554 */
555 QList<QDeclarativeError> QDeclarativeComponent::errors() const
556 {
557     Q_D(const QDeclarativeComponent);
558     if (isError())
559         return d->state.errors;
560     else
561         return QList<QDeclarativeError>();
562 }
563
564 /*!
565     \qmlmethod string Component::errorString()
566
567     Returns a human-readable description of any errors.
568
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.
571
572     If no errors are present, an empty string is returned.
573 */
574
575 /*!
576     \internal
577     errorString is only meant as a way to get the errors in script
578 */
579 QString QDeclarativeComponent::errorString() const
580 {
581     Q_D(const QDeclarativeComponent);
582     QString ret;
583     if(!isError())
584         return ret;
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');
589     }
590     return ret;
591 }
592
593 /*!
594     \qmlproperty url Component::url
595     The component URL.  This is the URL that was used to construct the component.
596 */
597
598 /*!
599     \property QDeclarativeComponent::url
600     The component URL.  This is the URL passed to either the constructor,
601     or the loadUrl() or setData() methods.
602 */
603 QUrl QDeclarativeComponent::url() const
604 {
605     Q_D(const QDeclarativeComponent);
606     return d->url;
607 }
608
609 /*!
610     \internal
611 */
612 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject *parent)
613     : QObject(dd, parent)
614 {
615 }
616
617 /*!
618     \qmlmethod object Component::createObject(Item parent, object properties)
619
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.
623
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.
627
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.
632
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.
636
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.)
642
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:
645
646     \js
647         var component = Qt.createComponent("Button.qml");
648         if (component.status == Component.Ready)
649             component.createObject(parent, {"x": 100, "y": 100});
650     \endjs
651
652     Dynamically created instances can be deleted with the \c destroy() method.
653     See \l {Dynamic Object Management in QML} for more information.
654 */
655
656 /*!
657     \internal
658     A version of create which returns a scriptObject, for use in script.
659     This function will only work on components created in QML.
660
661     Sets graphics object parent because forgetting to do this is a frequent
662     and serious problem.
663 */
664 QScriptValue QDeclarativeComponent::createObject(QObject* parent)
665 {
666     Q_D(QDeclarativeComponent);
667     return d->createObject(parent, QScriptValue(QScriptValue::NullValue));
668 }
669
670 /*!
671     \internal
672     Overloadable method allows properties to be set during creation
673 */
674 QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap)
675 {
676     Q_D(QDeclarativeComponent);
677
678     if (!valuemap.isObject() || valuemap.isArray()) {
679         qmlInfo(this) << tr("createObject: value is not an object");
680         return QScriptValue(QScriptValue::NullValue);
681     }
682     return d->createObject(parent, valuemap);
683 }
684
685 QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap)
686 {
687     Q_Q(QDeclarativeComponent);
688     QDeclarativeContext* ctxt = q->creationContext();
689     if(!ctxt && engine)
690         ctxt = engine->rootContext();
691     if (!ctxt)
692         return QScriptValue(QScriptValue::NullValue);
693     QObject* ret = q->beginCreate(ctxt);
694     if (!ret) {
695         q->completeCreate();
696         return QScriptValue(QScriptValue::NullValue);
697     }
698
699     if (publicParent) {
700         ret->setParent(publicParent);
701         QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
702
703         bool needParent = false;
704
705         for (int ii = 0; ii < functions.count(); ++ii) {
706             QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent);
707             if (res == QDeclarativePrivate::Parented) {
708                 needParent = false;
709                 break;
710             } else if (res == QDeclarativePrivate::IncompatibleParent) {
711                 needParent = true;
712             }
713         }
714
715         if (needParent)
716             qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
717     }
718
719     QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
720     QDeclarativeData::get(ret, true)->setImplicitDestructible();
721     QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
722
723     if (valuemap.isObject() && !valuemap.isArray()) {
724         //Iterate through and assign properties
725         QScriptValueIterator it(valuemap);
726         while (it.hasNext()) {
727             it.next();
728             QScriptValue prop = newObject;
729             QString propName = it.name();
730             int index = propName.indexOf(QLatin1Char('.'));
731             if (index > 0) {
732                 QString subProp = propName;
733                 int lastIndex = 0;
734                 while (index > 0) {
735                     subProp = propName.mid(lastIndex, index - lastIndex);
736                     prop = prop.property(subProp);
737                     lastIndex = index + 1;
738                     index = propName.indexOf(QLatin1Char('.'), index + 1);
739                 }
740                 prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value());
741             } else {
742                 newObject.setProperty(propName, it.value());
743             }
744         }
745     }
746
747     q->completeCreate();
748
749     return newObject;
750 }
751
752 /*!
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
755     instance.  
756
757     If \a context is 0 (the default), it will create the instance in the
758     engine' s \l {QDeclarativeEngine::rootContext()}{root context}.
759 */
760 QObject *QDeclarativeComponent::create(QDeclarativeContext *context)
761 {
762     Q_D(QDeclarativeComponent);
763
764     if (!context)
765         context = d->engine->rootContext();
766
767     QObject *rv = beginCreate(context);
768     completeCreate();
769     return rv;
770 }
771
772 /*!
773     This method provides more advanced control over component instance creation.
774     In general, programmers should use QDeclarativeComponent::create() to create a 
775     component.
776
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
779     instance.  
780
781     When QDeclarativeComponent constructs an instance, it occurs in three steps:
782     \list 1
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.
786     \endlist 
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.
790
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.
794 */
795 QObject *QDeclarativeComponent::beginCreate(QDeclarativeContext *context)
796 {
797     Q_D(QDeclarativeComponent);
798     QObject *rv = d->beginCreate(context?QDeclarativeContextData::get(context):0, QBitField());
799     if (rv) {
800         QDeclarativeData *ddata = QDeclarativeData::get(rv);
801         Q_ASSERT(ddata);
802         ddata->indestructible = true;
803     }
804     return rv;
805 }
806
807 QObject *
808 QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, const QBitField &bindings)
809 {
810     Q_Q(QDeclarativeComponent);
811     if (!context) {
812         qWarning("QDeclarativeComponent: Cannot create a component in a null context");
813         return 0;
814     }
815
816     if (!context->isValid()) {
817         qWarning("QDeclarativeComponent: Cannot create a component in an invalid context");
818         return 0;
819     }
820
821     if (context->engine != engine) {
822         qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine");
823         return 0;
824     }
825
826     if (state.completePending) {
827         qWarning("QDeclarativeComponent: Cannot create new component instance before completing the previous");
828         return 0;
829     }
830
831     if (!q->isReady()) {
832         qWarning("QDeclarativeComponent: Component is not ready");
833         return 0;
834     }
835
836     return begin(context, creationContext, cc, start, count, &state, 0, bindings);
837 }
838
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)
844 {
845     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentContext->engine);
846     bool isRoot = !enginePriv->inBeginCreate;
847
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
850
851     if (isRoot) {
852         QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
853         QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, component->url);
854     }
855
856     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
857     ctxt->isInternal = true;
858     ctxt->url = component->url;
859     ctxt->imports = component->importCache;
860
861     // Nested global imports
862     if (componentCreationContext && start != -1) 
863         ctxt->importedScripts = componentCreationContext->importedScripts;
864
865     component->importCache->addref();
866     ctxt->setParent(parentContext);
867
868     enginePriv->inBeginCreate = true;
869
870     QDeclarativeVME vme;
871     QObject *rv = vme.run(ctxt, component, start, count, bindings);
872
873     if (vme.isError()) {
874        if(errors) *errors = vme.errors();
875        else state->errors = vme.errors();
876     }
877
878     if (isRoot) {
879         enginePriv->inBeginCreate = false;
880
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;
887
888         enginePriv->componentAttached = 0;
889         enginePriv->bindValues.clear();
890         enginePriv->parserStatus.clear();
891         enginePriv->finalizedParserStatus.clear();
892         state->completePending = true;
893         enginePriv->inProgressCreations++;
894     }
895
896     if (enginePriv->isDebugging && rv) {
897         if  (!parentContext->isInternal)
898             parentContext->asQDeclarativeContextPrivate()->instances.append(rv);
899         QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv);
900     }
901
902     return rv;
903 }
904
905 void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *enginePriv,
906                                                  QObject *object, ConstructionState *state)
907 {
908     bool isRoot = !enginePriv->inBeginCreate;
909     enginePriv->inBeginCreate = true;
910
911     QDeclarativeVME vme;
912     vme.runDeferred(object);
913
914     if (vme.isError()) 
915         state->errors = vme.errors();
916
917     if (isRoot) {
918         enginePriv->inBeginCreate = false;
919
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;
926
927         enginePriv->componentAttached = 0;
928         enginePriv->bindValues.clear();
929         enginePriv->parserStatus.clear();
930         enginePriv->finalizedParserStatus.clear();
931         state->completePending = true;
932         enginePriv->inProgressCreations++;
933     }
934 }
935
936 void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state)
937 {
938     if (state->completePending) {
939
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) {
944                 if(bv.at(jj)) {
945                     // XXX akennedy
946                     bv.at(jj)->m_mePtr = 0;
947                     bv.at(jj)->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor | 
948                                                 QDeclarativePropertyPrivate::DontRemoveBinding);
949                 }
950             }
951             QDeclarativeEnginePrivate::clear(bv);
952         }
953
954         for (int ii = 0; ii < state->parserStatus.count(); ++ii) {
955             QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> ps = 
956                 state->parserStatus.at(ii);
957
958             for (int jj = ps.count - 1; jj >= 0; --jj) {
959                 QDeclarativeParserStatus *status = ps.at(jj);
960                 if (status && status->d) {
961                     status->d = 0;
962                     status->componentComplete();
963                 }
964             }
965             QDeclarativeEnginePrivate::clear(ps);
966         }
967
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;
971             if (obj) {
972                 void *args[] = { 0 };
973                 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
974                                       status.second, args);
975             }
976         }
977
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;
984                 if (obj) {
985                     void *args[] = { 0 };
986                     QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
987                                           status.second, args);
988                 }
989             }
990             enginePriv->finalizedParserStatus.clear();
991         }
992
993         while (state->componentAttached) {
994             QDeclarativeComponentAttached *a = state->componentAttached;
995             a->rem();
996             QDeclarativeData *d = QDeclarativeData::get(a->parent());
997             Q_ASSERT(d);
998             Q_ASSERT(d->context);
999             a->add(&d->context->componentAttached);
1000             emit a->completed();
1001         }
1002
1003         state->bindValues.clear();
1004         state->parserStatus.clear();
1005         state->finalizedParserStatus.clear();
1006         state->completePending = false;
1007
1008         enginePriv->inProgressCreations--;
1009         if (0 == enginePriv->inProgressCreations) {
1010             while (enginePriv->erroredBindings) {
1011                 enginePriv->warning(enginePriv->erroredBindings->error);
1012                 enginePriv->erroredBindings->removeError();
1013             }
1014         }
1015     }
1016 }
1017
1018 /*!
1019     This method provides more advanced control over component instance creation.
1020     In general, programmers should use QDeclarativeComponent::create() to create a 
1021     component.
1022
1023     Complete a component creation begin with QDeclarativeComponent::beginCreate().
1024 */
1025 void QDeclarativeComponent::completeCreate()
1026 {
1027     Q_D(QDeclarativeComponent);
1028     d->completeCreate();
1029 }
1030
1031 void QDeclarativeComponentPrivate::completeCreate()
1032 {
1033     if (state.completePending) {
1034         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1035         complete(ep, &state);
1036
1037         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
1038     }
1039 }
1040
1041 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
1042 : QObject(parent), prev(0), next(0)
1043 {
1044 }
1045
1046 QDeclarativeComponentAttached::~QDeclarativeComponentAttached()
1047 {
1048     if (prev) *prev = next;
1049     if (next) next->prev = prev;
1050     prev = 0;
1051     next = 0;
1052 }
1053
1054 /*!
1055     \internal
1056 */
1057 QDeclarativeComponentAttached *QDeclarativeComponent::qmlAttachedProperties(QObject *obj)
1058 {
1059     QDeclarativeComponentAttached *a = new QDeclarativeComponentAttached(obj);
1060
1061     QDeclarativeEngine *engine = qmlEngine(obj);
1062     if (!engine)
1063         return a;
1064
1065     if (QDeclarativeEnginePrivate::get(engine)->inBeginCreate) {
1066         QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
1067         a->add(&p->componentAttached);
1068     } else {
1069         QDeclarativeData *d = QDeclarativeData::get(obj);
1070         Q_ASSERT(d);
1071         Q_ASSERT(d->context);
1072         a->add(&d->context->componentAttached);
1073     }
1074
1075     return a;
1076 }
1077
1078 QT_END_NAMESPACE