Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qtdeclarative
[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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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, 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->url = cc->url;
467     d->progress = 1.0;
468 }
469
470 /*!
471     Sets the QDeclarativeComponent to use the given QML \a data.  If \a url
472     is provided, it is used to set the component name and to provide
473     a base path for items resolved by this component.
474 */
475 void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url)
476 {
477     Q_D(QDeclarativeComponent);
478
479     d->clear();
480
481     d->url = url;
482
483     QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url);
484     
485     if (typeData->isCompleteOrError()) {
486         d->fromTypeData(typeData);
487     } else {
488         d->typeData = typeData;
489         d->typeData->registerCallback(d);
490     }
491
492     d->progress = 1.0;
493     emit statusChanged(status());
494     emit progressChanged(d->progress);
495 }
496
497 /*!
498 Returns the QDeclarativeContext the component was created in.  This is only
499 valid for components created directly from QML.
500 */
501 QDeclarativeContext *QDeclarativeComponent::creationContext() const
502 {
503     Q_D(const QDeclarativeComponent);
504     if(d->creationContext)
505         return d->creationContext->asQDeclarativeContext();
506
507     return qmlContext(this);
508 }
509
510 /*!
511     Load the QDeclarativeComponent from the provided \a url.
512
513     Ensure that the URL provided is full and correct, in particular, use
514     \l QUrl::fromLocalFile() when loading a file from the local filesystem.
515 */
516 void QDeclarativeComponent::loadUrl(const QUrl &url)
517 {
518     Q_D(QDeclarativeComponent);
519
520     d->clear();
521
522     if ((url.isRelative() && !url.isEmpty())
523     || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
524         d->url = d->engine->baseUrl().resolved(url);
525     else
526         d->url = url;
527
528     if (url.isEmpty()) {
529         QDeclarativeError error;
530         error.setDescription(tr("Invalid empty URL"));
531         d->state.errors << error;
532         return;
533     }
534
535     QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url);
536
537     if (data->isCompleteOrError()) {
538         d->fromTypeData(data);
539         d->progress = 1.0;
540     } else {
541         d->typeData = data;
542         d->typeData->registerCallback(d);
543         d->progress = data->progress();
544     }
545
546     emit statusChanged(status());
547     emit progressChanged(d->progress);
548 }
549
550 /*!
551     Return the list of errors that occurred during the last compile or create
552     operation.  An empty list is returned if isError() is not set.
553 */
554 QList<QDeclarativeError> QDeclarativeComponent::errors() const
555 {
556     Q_D(const QDeclarativeComponent);
557     if (isError())
558         return d->state.errors;
559     else
560         return QList<QDeclarativeError>();
561 }
562
563 /*!
564     \qmlmethod string Component::errorString()
565
566     Returns a human-readable description of any errors.
567
568     The string includes the file, location, and description of each error.
569     If multiple errors are present they are separated by a newline character.
570
571     If no errors are present, an empty string is returned.
572 */
573
574 /*!
575     \internal
576     errorString is only meant as a way to get the errors in script
577 */
578 QString QDeclarativeComponent::errorString() const
579 {
580     Q_D(const QDeclarativeComponent);
581     QString ret;
582     if(!isError())
583         return ret;
584     foreach(const QDeclarativeError &e, d->state.errors) {
585         ret += e.url().toString() + QLatin1Char(':') +
586                QString::number(e.line()) + QLatin1Char(' ') +
587                e.description() + QLatin1Char('\n');
588     }
589     return ret;
590 }
591
592 /*!
593     \qmlproperty url Component::url
594     The component URL.  This is the URL that was used to construct the component.
595 */
596
597 /*!
598     \property QDeclarativeComponent::url
599     The component URL.  This is the URL passed to either the constructor,
600     or the loadUrl() or setData() methods.
601 */
602 QUrl QDeclarativeComponent::url() const
603 {
604     Q_D(const QDeclarativeComponent);
605     return d->url;
606 }
607
608 /*!
609     \internal
610 */
611 QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject *parent)
612     : QObject(dd, parent)
613 {
614 }
615
616 /*!
617     \qmlmethod object Component::createObject(Item parent, object properties)
618
619     Creates and returns an object instance of this component that will have
620     the given \a parent and \a properties. The \a properties argument is optional.
621     Returns null if object creation fails.
622
623     The object will be created in the same context as the one in which the component
624     was created. This function will always return null when called on components
625     which were not created in QML.
626
627     If you wish to create an object without setting a parent, specify \c null for
628     the \a parent value. Note that if the returned object is to be displayed, you 
629     must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} 
630     property, or else the object will not be visible.
631
632     If a \a parent is not provided to createObject(), a reference to the returned object must be held so that
633     it is not destroyed by the garbage collector.  This is true regardless of whether \l{Item::parent} is set afterwards,
634     since setting the Item parent does not change object ownership; only the graphical parent is changed.
635
636     As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a
637     map of initial property values for the created object. These values are applied before object
638     creation is finalized. (This is more efficient than setting property values after object creation,
639     particularly where large sets of property values are defined, and also allows property bindings
640     to be set up before the object is created.)
641
642     The \a properties argument is specified as a map of property-value items. For example, the code
643     below creates an object with initial \c x and \c y values of 100 and 200, respectively:
644
645     \js
646         var component = Qt.createComponent("Button.qml");
647         if (component.status == Component.Ready)
648             component.createObject(parent, {"x": 100, "y": 100});
649     \endjs
650
651     Dynamically created instances can be deleted with the \c destroy() method.
652     See \l {Dynamic Object Management in QML} for more information.
653 */
654
655 /*!
656     \internal
657     A version of create which returns a scriptObject, for use in script.
658     This function will only work on components created in QML.
659
660     Sets graphics object parent because forgetting to do this is a frequent
661     and serious problem.
662 */
663 QScriptValue QDeclarativeComponent::createObject(QObject* parent)
664 {
665     Q_D(QDeclarativeComponent);
666     return d->createObject(parent, QScriptValue(QScriptValue::NullValue));
667 }
668
669 /*!
670     \internal
671     Overloadable method allows properties to be set during creation
672 */
673 QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap)
674 {
675     Q_D(QDeclarativeComponent);
676
677     if (!valuemap.isObject() || valuemap.isArray()) {
678         qmlInfo(this) << tr("createObject: value is not an object");
679         return QScriptValue(QScriptValue::NullValue);
680     }
681     return d->createObject(parent, valuemap);
682 }
683
684 QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap)
685 {
686     Q_Q(QDeclarativeComponent);
687     QDeclarativeContext* ctxt = q->creationContext();
688     if(!ctxt && engine)
689         ctxt = engine->rootContext();
690     if (!ctxt)
691         return QScriptValue(QScriptValue::NullValue);
692     QObject* ret = q->beginCreate(ctxt);
693     if (!ret) {
694         q->completeCreate();
695         return QScriptValue(QScriptValue::NullValue);
696     }
697
698     if (publicParent) {
699         ret->setParent(publicParent);
700         QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
701
702         bool needParent = false;
703
704         for (int ii = 0; ii < functions.count(); ++ii) {
705             QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent);
706             if (res == QDeclarativePrivate::Parented) {
707                 needParent = false;
708                 break;
709             } else if (res == QDeclarativePrivate::IncompatibleParent) {
710                 needParent = true;
711             }
712         }
713
714         if (needParent)
715             qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
716     }
717
718     QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
719     QDeclarativeData::get(ret, true)->setImplicitDestructible();
720     QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
721
722     if (valuemap.isObject() && !valuemap.isArray()) {
723         //Iterate through and assign properties
724         QScriptValueIterator it(valuemap);
725         while (it.hasNext()) {
726             it.next();
727             QScriptValue prop = newObject;
728             QString propName = it.name();
729             int index = propName.indexOf(QLatin1Char('.'));
730             if (index > 0) {
731                 QString subProp = propName;
732                 int lastIndex = 0;
733                 while (index > 0) {
734                     subProp = propName.mid(lastIndex, index - lastIndex);
735                     prop = prop.property(subProp);
736                     lastIndex = index + 1;
737                     index = propName.indexOf(QLatin1Char('.'), index + 1);
738                 }
739                 prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value());
740             } else {
741                 newObject.setProperty(propName, it.value());
742             }
743         }
744     }
745
746     q->completeCreate();
747
748     return newObject;
749 }
750
751 /*!
752     Create an object instance from this component.  Returns 0 if creation
753     failed.  \a context specifies the context within which to create the object
754     instance.  
755
756     If \a context is 0 (the default), it will create the instance in the
757     engine' s \l {QDeclarativeEngine::rootContext()}{root context}.
758 */
759 QObject *QDeclarativeComponent::create(QDeclarativeContext *context)
760 {
761     Q_D(QDeclarativeComponent);
762
763     if (!context)
764         context = d->engine->rootContext();
765
766     QObject *rv = beginCreate(context);
767     completeCreate();
768     return rv;
769 }
770
771 /*!
772     This method provides more advanced control over component instance creation.
773     In general, programmers should use QDeclarativeComponent::create() to create a 
774     component.
775
776     Create an object instance from this component.  Returns 0 if creation
777     failed.  \a context specifies the context within which to create the object
778     instance.  
779
780     When QDeclarativeComponent constructs an instance, it occurs in three steps:
781     \list 1
782     \i The object hierarchy is created, and constant values are assigned.
783     \i Property bindings are evaluated for the the first time.
784     \i If applicable, QDeclarativeParserStatus::componentComplete() is called on objects.
785     \endlist 
786     QDeclarativeComponent::beginCreate() differs from QDeclarativeComponent::create() in that it
787     only performs step 1.  QDeclarativeComponent::completeCreate() must be called to 
788     complete steps 2 and 3.
789
790     This breaking point is sometimes useful when using attached properties to
791     communicate information to an instantiated component, as it allows their
792     initial values to be configured before property bindings take effect.
793 */
794 QObject *QDeclarativeComponent::beginCreate(QDeclarativeContext *context)
795 {
796     Q_D(QDeclarativeComponent);
797     QObject *rv = d->beginCreate(context?QDeclarativeContextData::get(context):0, QBitField());
798     if (rv) {
799         QDeclarativeData *ddata = QDeclarativeData::get(rv);
800         Q_ASSERT(ddata);
801         ddata->indestructible = true;
802     }
803     return rv;
804 }
805
806 QObject *
807 QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, const QBitField &bindings)
808 {
809     Q_Q(QDeclarativeComponent);
810     if (!context) {
811         qWarning("QDeclarativeComponent: Cannot create a component in a null context");
812         return 0;
813     }
814
815     if (!context->isValid()) {
816         qWarning("QDeclarativeComponent: Cannot create a component in an invalid context");
817         return 0;
818     }
819
820     if (context->engine != engine) {
821         qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine");
822         return 0;
823     }
824
825     if (state.completePending) {
826         qWarning("QDeclarativeComponent: Cannot create new component instance before completing the previous");
827         return 0;
828     }
829
830     if (!q->isReady()) {
831         qWarning("QDeclarativeComponent: Component is not ready");
832         return 0;
833     }
834
835     return begin(context, creationContext, cc, start, &state, 0, bindings);
836 }
837
838 /*
839     Try to do what's necessary for a reasonable display of the type
840     name, but no more (just enough for the client to do more extensive cleanup).
841
842     Should only be called when debugging is enabled.
843 */
844 static inline QString buildTypeNameForDebug(const QMetaObject *metaObject)
845 {
846     static const QString qmlMarker(QLatin1String("_QML"));
847     static const QChar underscore(QLatin1Char('_'));
848     static const QChar asterisk(QLatin1Char('*'));
849     QDeclarativeType *type = QDeclarativeMetaType::qmlType(metaObject);
850     QString typeName = type ? QLatin1String(type->qmlTypeName()) : QLatin1String(metaObject->className());
851     if (!type) {
852         //### optimize further?
853         int marker = typeName.indexOf(qmlMarker);
854         if (marker != -1 && marker < typeName.count() - 1) {
855             if (typeName[marker + 1] == underscore) {
856                 const QString className = typeName.left(marker) + asterisk;
857                 type = QDeclarativeMetaType::qmlType(QMetaType::type(className.toLatin1()));
858                 if (type)
859                     typeName = QLatin1String(type->qmlTypeName());
860             }
861         }
862     }
863     return typeName;
864 }
865
866 QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentContext, 
867                                               QDeclarativeContextData *componentCreationContext,
868                                               QDeclarativeCompiledData *component, int start, 
869                                               ConstructionState *state, QList<QDeclarativeError> *errors,
870                                               const QBitField &bindings)
871 {
872     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentContext->engine);
873     bool isRoot = !enginePriv->inBeginCreate;
874
875     Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided
876     Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided
877
878     if (isRoot)
879         QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
880
881     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
882     ctxt->isInternal = true;
883     ctxt->url = component->url;
884     ctxt->imports = component->importCache;
885
886     // Nested global imports
887     if (componentCreationContext && start != -1) 
888         ctxt->importedScripts = componentCreationContext->importedScripts;
889
890     component->importCache->addref();
891     ctxt->setParent(parentContext);
892
893     enginePriv->inBeginCreate = true;
894
895     QDeclarativeVME vme;
896     enginePriv->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
897     QObject *rv = vme.run(ctxt, component, start, bindings);
898     enginePriv->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
899
900     if (vme.isError()) {
901        if(errors) *errors = vme.errors();
902        else state->errors = vme.errors();
903     }
904
905     if (isRoot) {
906         enginePriv->inBeginCreate = false;
907
908         state->bindValues = enginePriv->bindValues;
909         state->parserStatus = enginePriv->parserStatus;
910         state->finalizedParserStatus = enginePriv->finalizedParserStatus;
911         state->componentAttached = enginePriv->componentAttached;
912         if (state->componentAttached)
913             state->componentAttached->prev = &state->componentAttached;
914
915         enginePriv->componentAttached = 0;
916         enginePriv->bindValues.clear();
917         enginePriv->parserStatus.clear();
918         enginePriv->finalizedParserStatus.clear();
919         state->completePending = true;
920         enginePriv->inProgressCreations++;
921     }
922
923     if (enginePriv->isDebugging && rv) {
924         if  (!parentContext->isInternal)
925             parentContext->asQDeclarativeContextPrivate()->instances.append(rv);
926         QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv);
927         if (isRoot) {
928             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, buildTypeNameForDebug(rv->metaObject()));
929             QDeclarativeData *data = QDeclarativeData::get(rv);
930             QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, component->url, data ? data->lineNumber : -1);
931         }
932     }
933
934     return rv;
935 }
936
937 void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *enginePriv,
938                                                  QObject *object, ConstructionState *state)
939 {
940     bool isRoot = !enginePriv->inBeginCreate;
941     enginePriv->inBeginCreate = true;
942
943     QDeclarativeVME vme;
944     vme.runDeferred(object);
945
946     if (vme.isError()) 
947         state->errors = vme.errors();
948
949     if (isRoot) {
950         enginePriv->inBeginCreate = false;
951
952         state->bindValues = enginePriv->bindValues;
953         state->parserStatus = enginePriv->parserStatus;
954         state->finalizedParserStatus = enginePriv->finalizedParserStatus;
955         state->componentAttached = enginePriv->componentAttached;
956         if (state->componentAttached)
957             state->componentAttached->prev = &state->componentAttached;
958
959         enginePriv->componentAttached = 0;
960         enginePriv->bindValues.clear();
961         enginePriv->parserStatus.clear();
962         enginePriv->finalizedParserStatus.clear();
963         state->completePending = true;
964         enginePriv->inProgressCreations++;
965     }
966 }
967
968 void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state)
969 {
970     if (state->completePending) {
971
972         for (int ii = 0; ii < state->bindValues.count(); ++ii) {
973             QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bv = 
974                 state->bindValues.at(ii);
975             for (int jj = 0; jj < bv.count; ++jj) {
976                 if(bv.at(jj)) {
977                     // XXX akennedy
978                     bv.at(jj)->m_mePtr = 0;
979                     bv.at(jj)->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor | 
980                                                 QDeclarativePropertyPrivate::DontRemoveBinding);
981                 }
982             }
983             QDeclarativeEnginePrivate::clear(bv);
984         }
985
986         for (int ii = 0; ii < state->parserStatus.count(); ++ii) {
987             QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> ps = 
988                 state->parserStatus.at(ii);
989
990             for (int jj = ps.count - 1; jj >= 0; --jj) {
991                 QDeclarativeParserStatus *status = ps.at(jj);
992                 if (status && status->d) {
993                     status->d = 0;
994                     status->componentComplete();
995                 }
996             }
997             QDeclarativeEnginePrivate::clear(ps);
998         }
999
1000         for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) {
1001             QPair<QDeclarativeGuard<QObject>, int> status = state->finalizedParserStatus.at(ii);
1002             QObject *obj = status.first;
1003             if (obj) {
1004                 void *args[] = { 0 };
1005                 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
1006                                       status.second, args);
1007             }
1008         }
1009
1010         //componentComplete() can register additional finalization objects
1011         //that are then never handled. Handle them manually here.
1012         if (1 == enginePriv->inProgressCreations) {
1013             for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) {
1014                 QPair<QDeclarativeGuard<QObject>, int> status = enginePriv->finalizedParserStatus.at(ii);
1015                 QObject *obj = status.first;
1016                 if (obj) {
1017                     void *args[] = { 0 };
1018                     QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
1019                                           status.second, args);
1020                 }
1021             }
1022             enginePriv->finalizedParserStatus.clear();
1023         }
1024
1025         while (state->componentAttached) {
1026             QDeclarativeComponentAttached *a = state->componentAttached;
1027             a->rem();
1028             QDeclarativeData *d = QDeclarativeData::get(a->parent());
1029             Q_ASSERT(d);
1030             Q_ASSERT(d->context);
1031             a->add(&d->context->componentAttached);
1032             emit a->completed();
1033         }
1034
1035         state->bindValues.clear();
1036         state->parserStatus.clear();
1037         state->finalizedParserStatus.clear();
1038         state->completePending = false;
1039
1040         enginePriv->inProgressCreations--;
1041         if (0 == enginePriv->inProgressCreations) {
1042             while (enginePriv->erroredBindings) {
1043                 enginePriv->warning(enginePriv->erroredBindings->error);
1044                 enginePriv->erroredBindings->removeError();
1045             }
1046         }
1047     }
1048 }
1049
1050 /*!
1051     This method provides more advanced control over component instance creation.
1052     In general, programmers should use QDeclarativeComponent::create() to create a 
1053     component.
1054
1055     Complete a component creation begin with QDeclarativeComponent::beginCreate().
1056 */
1057 void QDeclarativeComponent::completeCreate()
1058 {
1059     Q_D(QDeclarativeComponent);
1060     d->completeCreate();
1061 }
1062
1063 void QDeclarativeComponentPrivate::completeCreate()
1064 {
1065     if (state.completePending) {
1066         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1067         complete(ep, &state);
1068
1069         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
1070     }
1071 }
1072
1073 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
1074 : QObject(parent), prev(0), next(0)
1075 {
1076 }
1077
1078 QDeclarativeComponentAttached::~QDeclarativeComponentAttached()
1079 {
1080     if (prev) *prev = next;
1081     if (next) next->prev = prev;
1082     prev = 0;
1083     next = 0;
1084 }
1085
1086 /*!
1087     \internal
1088 */
1089 QDeclarativeComponentAttached *QDeclarativeComponent::qmlAttachedProperties(QObject *obj)
1090 {
1091     QDeclarativeComponentAttached *a = new QDeclarativeComponentAttached(obj);
1092
1093     QDeclarativeEngine *engine = qmlEngine(obj);
1094     if (!engine)
1095         return a;
1096
1097     if (QDeclarativeEnginePrivate::get(engine)->inBeginCreate) {
1098         QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
1099         a->add(&p->componentAttached);
1100     } else {
1101         QDeclarativeData *d = QDeclarativeData::get(obj);
1102         Q_ASSERT(d);
1103         Q_ASSERT(d->context);
1104         a->add(&d->context->componentAttached);
1105     }
1106
1107     return a;
1108 }
1109
1110 QT_END_NAMESPACE