src/declarative/qml/qdeclarativecomponent.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    51 #include "qdeclarativeengine.h"
    51 #include "qdeclarativeengine.h"
    52 #include "private/qdeclarativebinding_p.h"
    52 #include "private/qdeclarativebinding_p.h"
    53 #include "private/qdeclarativebinding_p_p.h"
    53 #include "private/qdeclarativebinding_p_p.h"
    54 #include "private/qdeclarativeglobal_p.h"
    54 #include "private/qdeclarativeglobal_p.h"
    55 #include "private/qdeclarativescriptparser_p.h"
    55 #include "private/qdeclarativescriptparser_p.h"
       
    56 #include "private/qdeclarativedebugtrace_p.h"
    56 
    57 
    57 #include <QStack>
    58 #include <QStack>
    58 #include <QStringList>
    59 #include <QStringList>
    59 #include <QFileInfo>
    60 #include <QFileInfo>
    60 #include <QtCore/qdebug.h>
    61 #include <QtCore/qdebug.h>
    61 #include <QApplication>
    62 #include <QApplication>
    62 #include <QGraphicsObject>
       
    63 
    63 
    64 QT_BEGIN_NAMESPACE
    64 QT_BEGIN_NAMESPACE
    65 
    65 
    66 class QByteArray;
    66 class QByteArray;
    67 
    67 
    68 /*!
    68 /*!
    69     \class QDeclarativeComponent
    69     \class QDeclarativeComponent
    70     \since 4.7
    70     \since 4.7
    71     \brief The QDeclarativeComponent class encapsulates a QML component description.
    71     \brief The QDeclarativeComponent class encapsulates a QML component definition.
    72     \mainclass
    72     \mainclass
       
    73 
       
    74     Components are reusable, encapsulated QML elements with well-defined interfaces.
       
    75     They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
       
    76 
       
    77     A QDeclarativeComponent instance can be created from a QML file.
       
    78     For example, if there is a \c main.qml file like this:
       
    79 
       
    80     \qml
       
    81     import Qt 4.7
       
    82 
       
    83     Item {
       
    84         width: 200
       
    85         height: 200
       
    86     }
       
    87     \endqml
       
    88 
       
    89     The following code loads this QML file as a component, creates an instance of
       
    90     this component using create(), and then queries the \l Item's \l {Item::}{width}
       
    91     value:
       
    92 
       
    93     \code
       
    94     QDeclarativeEngine *engine = new QDeclarativeEngine;
       
    95     QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
       
    96 
       
    97     QObject *myObject = component.create();
       
    98     QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(myObject);
       
    99     int width = item->width();  // width = 200
       
   100     \endcode
       
   101 
       
   102     \sa {Using QML in C++ Applications}, {Integrating QML with existing Qt UI code}
    73 */
   103 */
    74 
   104 
    75 /*!
   105 /*!
    76     \qmlclass Component QDeclarativeComponent
   106     \qmlclass Component QDeclarativeComponent
    77     \since 4.7
   107     \since 4.7
    78     \brief The Component element encapsulates a QML component description.
   108     \brief The Component element encapsulates a QML component definition.
    79 
   109 
    80     Components are reusable, encapsulated Qml element with a well-defined interface.
   110     Components are reusable, encapsulated QML elements with well-defined interfaces.
    81     They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
   111 
    82 
   112     Components are often defined by \l {qdeclarativedocuments.html}{component files} -
    83     The \e Component element allows defining components within a QML file.
   113     that is, \c .qml files. The \e Component element allows components to be defined
    84     This can be useful for reusing a small component within a single QML
   114     within QML items rather than in a separate file. This may be useful for reusing 
    85     file, or for defining a component that logically belongs with the
   115     a small component within a QML file, or for defining a component that logically 
    86     file containing it.
   116     belongs with other QML components within a file.
       
   117 
       
   118     For example, here is a component that is used by multiple \l Loader objects:
    87 
   119 
    88     \qml
   120     \qml
    89     Item {
   121     Item {
    90         Component {
   122         Component {
    91             id: redSquare
   123             id: redSquare
       
   124 
    92             Rectangle {
   125             Rectangle {
    93                 color: "red"
   126                 color: "red"
    94                 width: 10
   127                 width: 10
    95                 height: 10
   128                 height: 10
    96             }
   129             }
    97         }
   130         }
       
   131 
    98         Loader { sourceComponent: redSquare }
   132         Loader { sourceComponent: redSquare }
    99         Loader { sourceComponent: redSquare; x: 20 }
   133         Loader { sourceComponent: redSquare; x: 20 }
   100     }
   134     }
   101     \endqml
   135     \endqml
       
   136 
       
   137     Notice that while a \l Rectangle by itself would be automatically 
       
   138     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
       
   140     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
       
   142     two \l Loader objects).
       
   143 
       
   144     The Component element is commonly used to provide graphical components
       
   145     for views. For example, the ListView::delegate property requires a Component
       
   146     to specify how each list item is to be displayed.
       
   147 
       
   148     Component objects can also be dynamically generated using
       
   149     \l{Qt::createComponent}{Qt.createComponent()}.
   102 */
   150 */
   103 
   151 
   104 /*!
   152 /*!
   105     \qmlattachedsignal Component::onCompleted()
   153     \qmlattachedsignal Component::onCompleted()
   106 
   154 
   446 {
   494 {
   447     Q_D(QDeclarativeComponent);
   495     Q_D(QDeclarativeComponent);
   448 
   496 
   449     d->clear();
   497     d->clear();
   450 
   498 
   451     if (url.isRelative() && !url.isEmpty())
   499     if ((url.isRelative() && !url.isEmpty())
       
   500     || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
   452         d->url = d->engine->baseUrl().resolved(url);
   501         d->url = d->engine->baseUrl().resolved(url);
   453     else
   502     else
   454         d->url = url;
   503         d->url = url;
   455 
   504 
   456     if (url.isEmpty()) {
   505     if (url.isEmpty()) {
   544 {
   593 {
   545 }
   594 }
   546 
   595 
   547 /*!
   596 /*!
   548     \qmlmethod object Component::createObject(parent)
   597     \qmlmethod object Component::createObject(parent)
   549     Returns an object instance from this component, or null if object creation fails.
   598 
       
   599     Creates and returns an object instance of this component that will have the given 
       
   600     \a parent. Returns null if object creation fails.
   550 
   601 
   551     The object will be created in the same context as the one in which the component
   602     The object will be created in the same context as the one in which the component
   552     was created. This function will always return null when called on components
   603     was created. This function will always return null when called on components
   553     which were not created in QML.
   604     which were not created in QML.
   554 
   605 
   555     Note that if the returned object is to be displayed, its \c parent must be set to
   606     If you wish to create an object without setting a parent, specify \c null for
   556     an existing item in a scene, or else the object will not be visible. The parent
   607     the \a parent value. Note that if the returned object is to be displayed, you 
   557     argument is required to help you avoid this, you must explicitly pass in null if
   608     must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} 
   558     you wish to create an object without setting a parent.
   609     property, or else the object will not be visible.
   559 */
   610 */
   560 
   611 
   561 /*!
   612 /*!
   562     \internal
   613     \internal
   563     A version of create which returns a scriptObject, for use in script.
   614     A version of create which returns a scriptObject, for use in script.
   568 */
   619 */
   569 QScriptValue QDeclarativeComponent::createObject(QObject* parent)
   620 QScriptValue QDeclarativeComponent::createObject(QObject* parent)
   570 {
   621 {
   571     Q_D(QDeclarativeComponent);
   622     Q_D(QDeclarativeComponent);
   572     QDeclarativeContext* ctxt = creationContext();
   623     QDeclarativeContext* ctxt = creationContext();
   573     if(!ctxt)
   624     if(!ctxt && d->engine)
       
   625         ctxt = d->engine->rootContext();
       
   626     if (!ctxt)
   574         return QScriptValue(QScriptValue::NullValue);
   627         return QScriptValue(QScriptValue::NullValue);
   575     QObject* ret = create(ctxt);
   628     QObject* ret = create(ctxt);
   576     if (!ret)
   629     if (!ret)
   577         return QScriptValue(QScriptValue::NullValue);
   630         return QScriptValue(QScriptValue::NullValue);
   578 
   631 
   579     QGraphicsObject* gobj = qobject_cast<QGraphicsObject*>(ret);
   632 
   580     bool needParent = (gobj != 0);
   633     if (parent) {
   581     if(parent){
       
   582         ret->setParent(parent);
   634         ret->setParent(parent);
   583         if (gobj) {
   635         QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
   584             QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parent);
   636 
   585             if(gparent){
   637         bool needParent = false;
   586                 gobj->setParentItem(gparent);
   638 
       
   639         for (int ii = 0; ii < functions.count(); ++ii) {
       
   640             QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent);
       
   641             if (res == QDeclarativePrivate::Parented) {
   587                 needParent = false;
   642                 needParent = false;
       
   643                 break;
       
   644             } else if (res == QDeclarativePrivate::IncompatibleParent) {
       
   645                 needParent = true;
   588             }
   646             }
   589         }
   647         }
   590     }
   648 
   591     if(needParent)
   649         if (needParent) 
   592         qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
   650             qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
       
   651     }
   593 
   652 
   594     QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine);
   653     QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine);
   595     QDeclarativeData::get(ret, true)->setImplicitDestructible();
   654     QDeclarativeData::get(ret, true)->setImplicitDestructible();
   596     return priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
   655     return priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
   597 }
   656 }
   690         qWarning("QDeclarativeComponent: Component is not ready");
   749         qWarning("QDeclarativeComponent: Component is not ready");
   691         return 0;
   750         return 0;
   692     }
   751     }
   693 
   752 
   694     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
   753     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
       
   754 
       
   755     bool isRoot = !ep->inBeginCreate;
       
   756     if (isRoot) 
       
   757         QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
       
   758     QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, cc->url);
   695 
   759 
   696     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
   760     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
   697     ctxt->isInternal = true;
   761     ctxt->isInternal = true;
   698     ctxt->url = cc->url;
   762     ctxt->url = cc->url;
   699     ctxt->imports = cc->importCache;
   763     ctxt->imports = cc->importCache;
   837             while (enginePriv->erroredBindings) {
   901             while (enginePriv->erroredBindings) {
   838                 enginePriv->warning(enginePriv->erroredBindings->error);
   902                 enginePriv->warning(enginePriv->erroredBindings->error);
   839                 enginePriv->erroredBindings->removeError();
   903                 enginePriv->erroredBindings->removeError();
   840             }
   904             }
   841         }
   905         }
       
   906 
   842     }
   907     }
   843 }
   908 }
   844 
   909 
   845 /*!
   910 /*!
   846     This method provides more advanced control over component instance creation.
   911     This method provides more advanced control over component instance creation.
   858 void QDeclarativeComponentPrivate::completeCreate()
   923 void QDeclarativeComponentPrivate::completeCreate()
   859 {
   924 {
   860     if (state.completePending) {
   925     if (state.completePending) {
   861         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
   926         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
   862         complete(ep, &state);
   927         complete(ep, &state);
       
   928 
       
   929         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
   863     }
   930     }
   864 }
   931 }
   865 
   932 
   866 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
   933 QDeclarativeComponentAttached::QDeclarativeComponentAttached(QObject *parent)
   867 : QObject(parent), prev(0), next(0)
   934 : QObject(parent), prev(0), next(0)