src/declarative/qml/qdeclarativecomponent.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    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) { 
   277         qWarning("QDeclarativeComponent: Component destroyed while completion pending");
   265         qWarning("QDeclarativeComponent: Component destroyed while completion pending");
   278         d->completeCreate();
   266         d->completeCreate();
   279     }
   267     }
   280 
   268 
   281     if (d->typeData) {
   269     if (d->typeData) {
   282         d->typeData->remWaiter(d);
   270         d->typeData->unregisterCallback(d);
   283         d->typeData->release();
   271         d->typeData->release();
   284     }
   272     }
   285     if (d->cc)
   273     if (d->cc)
   286         d->cc->release();
   274         d->cc->release();
   287 }
   275 }
   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,