42 #include "qdeclarativecomponent.h" |
42 #include "qdeclarativecomponent.h" |
43 #include "private/qdeclarativecomponent_p.h" |
43 #include "private/qdeclarativecomponent_p.h" |
44 |
44 |
45 #include "private/qdeclarativecompiler_p.h" |
45 #include "private/qdeclarativecompiler_p.h" |
46 #include "private/qdeclarativecontext_p.h" |
46 #include "private/qdeclarativecontext_p.h" |
47 #include "private/qdeclarativecompositetypedata_p.h" |
|
48 #include "private/qdeclarativeengine_p.h" |
47 #include "private/qdeclarativeengine_p.h" |
49 #include "private/qdeclarativevme_p.h" |
48 #include "private/qdeclarativevme_p.h" |
50 #include "qdeclarative.h" |
49 #include "qdeclarative.h" |
51 #include "qdeclarativeengine.h" |
50 #include "qdeclarativeengine.h" |
52 #include "private/qdeclarativebinding_p.h" |
51 #include "private/qdeclarativebinding_p.h" |
53 #include "private/qdeclarativebinding_p_p.h" |
52 #include "private/qdeclarativebinding_p_p.h" |
54 #include "private/qdeclarativeglobal_p.h" |
53 #include "private/qdeclarativeglobal_p.h" |
55 #include "private/qdeclarativescriptparser_p.h" |
54 #include "private/qdeclarativescriptparser_p.h" |
56 #include "private/qdeclarativedebugtrace_p.h" |
55 #include "private/qdeclarativedebugtrace_p.h" |
|
56 #include "private/qdeclarativeenginedebug_p.h" |
57 |
57 |
58 #include <QStack> |
58 #include <QStack> |
59 #include <QStringList> |
59 #include <QStringList> |
60 #include <QFileInfo> |
60 #include <QFileInfo> |
61 #include <QtCore/qdebug.h> |
61 #include <QtCore/qdebug.h> |
102 \sa {Using QML in C++ Applications}, {Integrating QML with existing Qt UI code} |
102 \sa {Using QML in C++ Applications}, {Integrating QML with existing Qt UI code} |
103 */ |
103 */ |
104 |
104 |
105 /*! |
105 /*! |
106 \qmlclass Component QDeclarativeComponent |
106 \qmlclass Component QDeclarativeComponent |
|
107 \ingroup qml-utility-elements |
107 \since 4.7 |
108 \since 4.7 |
108 \brief The Component element encapsulates a QML component definition. |
109 \brief The Component element encapsulates a QML component definition. |
109 |
110 |
110 Components are reusable, encapsulated QML elements with well-defined interfaces. |
111 Components are reusable, encapsulated QML elements with well-defined interfaces. |
111 |
112 |
113 that is, \c .qml files. The \e Component element allows components to be defined |
114 that is, \c .qml files. The \e Component element allows components to be defined |
114 within QML items rather than in a separate file. This may be useful for reusing |
115 within QML items rather than in a separate file. This may be useful for reusing |
115 a small component within a QML file, or for defining a component that logically |
116 a small component within a QML file, or for defining a component that logically |
116 belongs with other QML components within a file. |
117 belongs with other QML components within a file. |
117 |
118 |
118 For example, here is a component that is used by multiple \l Loader objects: |
119 For example, here is a component that is used by multiple \l Loader objects. |
119 |
120 It contains a top level \l Rectangle item: |
120 \qml |
121 |
121 Item { |
122 \snippet doc/src/snippets/declarative/component.qml 0 |
122 Component { |
|
123 id: redSquare |
|
124 |
|
125 Rectangle { |
|
126 color: "red" |
|
127 width: 10 |
|
128 height: 10 |
|
129 } |
|
130 } |
|
131 |
|
132 Loader { sourceComponent: redSquare } |
|
133 Loader { sourceComponent: redSquare; x: 20 } |
|
134 } |
|
135 \endqml |
|
136 |
123 |
137 Notice that while a \l Rectangle by itself would be automatically |
124 Notice that while a \l Rectangle by itself would be automatically |
138 rendered and displayed, this is not the case for the above rectangle |
125 rendered and displayed, this is not the case for the above rectangle |
139 because it is defined inside a \c Component. The component encapsulates the |
126 because it is defined inside a \c Component. The component encapsulates the |
140 QML elements within, as if they were defined in a separate \c .qml |
127 QML elements within, as if they were defined in a separate \c .qml |
141 file, and is not loaded until requested (in this case, by the |
128 file, and is not loaded until requested (in this case, by the |
142 two \l Loader objects). |
129 two \l Loader objects). |
143 |
130 |
|
131 A Component cannot contain anything other |
|
132 than an \c id and a single top level item. While the \c id is optional, |
|
133 the top level item is not; you cannot define an empty component. |
|
134 |
144 The Component element is commonly used to provide graphical components |
135 The Component element is commonly used to provide graphical components |
145 for views. For example, the ListView::delegate property requires a Component |
136 for views. For example, the ListView::delegate property requires a Component |
146 to specify how each list item is to be displayed. |
137 to specify how each list item is to be displayed. |
147 |
138 |
148 Component objects can also be dynamically generated using |
139 Component objects can also be dynamically created using |
149 \l{Qt::createComponent}{Qt.createComponent()}. |
140 \l{QML:Qt::createComponent()}{Qt.createComponent()}. |
150 */ |
141 */ |
151 |
142 |
152 /*! |
143 /*! |
153 \qmlattachedsignal Component::onCompleted() |
144 \qmlattachedsignal Component::onCompleted() |
154 |
145 |
200 Specifies the loading status of the QDeclarativeComponent. |
191 Specifies the loading status of the QDeclarativeComponent. |
201 |
192 |
202 \value Null This QDeclarativeComponent has no data. Call loadUrl() or setData() to add QML content. |
193 \value Null This QDeclarativeComponent has no data. Call loadUrl() or setData() to add QML content. |
203 \value Ready This QDeclarativeComponent is ready and create() may be called. |
194 \value Ready This QDeclarativeComponent is ready and create() may be called. |
204 \value Loading This QDeclarativeComponent is loading network data. |
195 \value Loading This QDeclarativeComponent is loading network data. |
205 \value Error An error has occured. Call errors() to retrieve a list of \{QDeclarativeError}{errors}. |
196 \value Error An error has occurred. Call errors() to retrieve a list of \{QDeclarativeError}{errors}. |
206 */ |
197 */ |
207 |
198 |
208 void QDeclarativeComponentPrivate::typeDataReady() |
199 void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *) |
209 { |
200 { |
210 Q_Q(QDeclarativeComponent); |
201 Q_Q(QDeclarativeComponent); |
211 |
202 |
212 Q_ASSERT(typeData); |
203 Q_ASSERT(typeData); |
213 |
204 |
215 typeData = 0; |
206 typeData = 0; |
216 |
207 |
217 emit q->statusChanged(q->status()); |
208 emit q->statusChanged(q->status()); |
218 } |
209 } |
219 |
210 |
220 void QDeclarativeComponentPrivate::updateProgress(qreal p) |
211 void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p) |
221 { |
212 { |
222 Q_Q(QDeclarativeComponent); |
213 Q_Q(QDeclarativeComponent); |
223 |
214 |
224 progress = p; |
215 progress = p; |
|
216 |
225 emit q->progressChanged(p); |
217 emit q->progressChanged(p); |
226 } |
218 } |
227 |
219 |
228 void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeCompositeTypeData *data) |
220 void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data) |
229 { |
221 { |
230 url = data->imports.baseUrl(); |
222 url = data->finalUrl(); |
231 QDeclarativeCompiledData *c = data->toCompiledComponent(engine); |
223 QDeclarativeCompiledData *c = data->compiledData(); |
232 |
224 |
233 if (!c) { |
225 if (!c) { |
234 Q_ASSERT(data->status == QDeclarativeCompositeTypeData::Error); |
226 Q_ASSERT(data->isError()); |
235 |
227 state.errors = data->errors(); |
236 state.errors = data->errors; |
|
237 |
|
238 } else { |
228 } else { |
239 |
|
240 cc = c; |
229 cc = c; |
241 |
|
242 } |
230 } |
243 |
231 |
244 data->release(); |
232 data->release(); |
245 } |
233 } |
246 |
234 |
247 void QDeclarativeComponentPrivate::clear() |
235 void QDeclarativeComponentPrivate::clear() |
248 { |
236 { |
249 if (typeData) { |
237 if (typeData) { |
250 typeData->remWaiter(this); |
238 typeData->unregisterCallback(this); |
251 typeData->release(); |
239 typeData->release(); |
252 typeData = 0; |
240 typeData = 0; |
253 } |
241 } |
254 |
242 |
255 if (cc) { |
243 if (cc) { |
449 |
437 |
450 d->clear(); |
438 d->clear(); |
451 |
439 |
452 d->url = url; |
440 d->url = url; |
453 |
441 |
454 QDeclarativeCompositeTypeData *typeData = |
442 QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url); |
455 QDeclarativeEnginePrivate::get(d->engine)->typeManager.getImmediate(data, url); |
|
456 |
443 |
457 if (typeData->status == QDeclarativeCompositeTypeData::Waiting |
444 if (typeData->isCompleteOrError()) { |
458 || typeData->status == QDeclarativeCompositeTypeData::WaitingResources) |
445 d->fromTypeData(typeData); |
459 { |
446 } else { |
460 d->typeData = typeData; |
447 d->typeData = typeData; |
461 d->typeData->addWaiter(d); |
448 d->typeData->registerCallback(d); |
462 |
|
463 } else { |
|
464 |
|
465 d->fromTypeData(typeData); |
|
466 |
|
467 } |
449 } |
468 |
450 |
469 d->progress = 1.0; |
451 d->progress = 1.0; |
470 emit statusChanged(status()); |
452 emit statusChanged(status()); |
471 emit progressChanged(d->progress); |
453 emit progressChanged(d->progress); |
507 error.setDescription(tr("Invalid empty URL")); |
489 error.setDescription(tr("Invalid empty URL")); |
508 d->state.errors << error; |
490 d->state.errors << error; |
509 return; |
491 return; |
510 } |
492 } |
511 |
493 |
512 QDeclarativeCompositeTypeData *data = |
494 QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url); |
513 QDeclarativeEnginePrivate::get(d->engine)->typeManager.get(d->url); |
495 |
514 |
496 if (data->isCompleteOrError()) { |
515 if (data->status == QDeclarativeCompositeTypeData::Waiting |
|
516 || data->status == QDeclarativeCompositeTypeData::WaitingResources) |
|
517 { |
|
518 d->typeData = data; |
|
519 d->typeData->addWaiter(d); |
|
520 d->progress = data->progress; |
|
521 } else { |
|
522 d->fromTypeData(data); |
497 d->fromTypeData(data); |
523 d->progress = 1.0; |
498 d->progress = 1.0; |
|
499 } else { |
|
500 d->typeData = data; |
|
501 d->typeData->registerCallback(d); |
|
502 d->progress = data->progress(); |
524 } |
503 } |
525 |
504 |
526 emit statusChanged(status()); |
505 emit statusChanged(status()); |
527 emit progressChanged(d->progress); |
506 emit progressChanged(d->progress); |
528 } |
507 } |
529 |
508 |
530 /*! |
509 /*! |
531 Return the list of errors that occured during the last compile or create |
510 Return the list of errors that occurred during the last compile or create |
532 operation. An empty list is returned if isError() is not set. |
511 operation. An empty list is returned if isError() is not set. |
533 */ |
512 */ |
534 QList<QDeclarativeError> QDeclarativeComponent::errors() const |
513 QList<QDeclarativeError> QDeclarativeComponent::errors() const |
535 { |
514 { |
536 Q_D(const QDeclarativeComponent); |
515 Q_D(const QDeclarativeComponent); |
605 |
584 |
606 If you wish to create an object without setting a parent, specify \c null for |
585 If you wish to create an object without setting a parent, specify \c null for |
607 the \a parent value. Note that if the returned object is to be displayed, you |
586 the \a parent value. Note that if the returned object is to be displayed, you |
608 must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} |
587 must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} |
609 property, or else the object will not be visible. |
588 property, or else the object will not be visible. |
|
589 |
|
590 Dynamically created instances can be deleted with the \c destroy() method. |
|
591 See \l {Dynamic Object Management in QML} for more information. |
610 */ |
592 */ |
611 |
593 |
612 /*! |
594 /*! |
613 \internal |
595 \internal |
614 A version of create which returns a scriptObject, for use in script. |
596 A version of create which returns a scriptObject, for use in script. |
623 QDeclarativeContext* ctxt = creationContext(); |
605 QDeclarativeContext* ctxt = creationContext(); |
624 if(!ctxt && d->engine) |
606 if(!ctxt && d->engine) |
625 ctxt = d->engine->rootContext(); |
607 ctxt = d->engine->rootContext(); |
626 if (!ctxt) |
608 if (!ctxt) |
627 return QScriptValue(QScriptValue::NullValue); |
609 return QScriptValue(QScriptValue::NullValue); |
628 QObject* ret = create(ctxt); |
610 QObject* ret = beginCreate(ctxt); |
629 if (!ret) |
611 if (!ret) { |
|
612 completeCreate(); |
630 return QScriptValue(QScriptValue::NullValue); |
613 return QScriptValue(QScriptValue::NullValue); |
631 |
614 } |
632 |
615 |
633 if (parent) { |
616 if (parent) { |
634 ret->setParent(parent); |
617 ret->setParent(parent); |
635 QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions(); |
618 QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions(); |
636 |
619 |
647 } |
630 } |
648 |
631 |
649 if (needParent) |
632 if (needParent) |
650 qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene."); |
633 qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene."); |
651 } |
634 } |
|
635 completeCreate(); |
652 |
636 |
653 QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine); |
637 QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine); |
654 QDeclarativeData::get(ret, true)->setImplicitDestructible(); |
638 QDeclarativeData::get(ret, true)->setImplicitDestructible(); |
655 return priv->objectClass->newQObject(ret, QMetaType::QObjectStar); |
639 return priv->objectClass->newQObject(ret, QMetaType::QObjectStar); |
656 } |
640 } |
769 cc->importCache->addref(); |
753 cc->importCache->addref(); |
770 ctxt->setParent(context); |
754 ctxt->setParent(context); |
771 |
755 |
772 QObject *rv = begin(ctxt, ep, cc, start, count, &state, bindings); |
756 QObject *rv = begin(ctxt, ep, cc, start, count, &state, bindings); |
773 |
757 |
774 if (rv && !context->isInternal && ep->isDebugging) |
758 if (ep->isDebugging && rv) { |
775 context->asQDeclarativeContextPrivate()->instances.append(rv); |
759 if (!context->isInternal) |
|
760 context->asQDeclarativeContextPrivate()->instances.append(rv); |
|
761 QDeclarativeEngineDebugServer::instance()->objectCreated(engine, rv); |
|
762 } |
776 |
763 |
777 return rv; |
764 return rv; |
778 } |
765 } |
779 |
766 |
780 QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv, |
767 QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv, |