diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-08-31 14:03:16 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2011-08-31 14:03:16 +0200 |
commit | 20c3575fc39004d6a556820543982f4a6ebef0be (patch) | |
tree | 9d8be9faae42972c85f0e296cc6dcaf27c3fcc4e /src | |
parent | 71478352376022faa9be6d79f2a760c289945ff5 (diff) | |
parent | 3108a36914d59d8a0d15bfdb2b5bbb09aa6e54a2 (diff) |
Merge remote-tracking branch 'origin/master' into refactor
Conflicts:
src/declarative/declarative.pro
Change-Id: I9c6d8447e1254c6acd32fa0775ff6a79d0d66acd
Diffstat (limited to 'src')
-rw-r--r-- | src/declarative/declarative.pro | 1 | ||||
-rw-r--r-- | src/declarative/items/qsgloader.cpp | 237 | ||||
-rw-r--r-- | src/declarative/items/qsgloader_p.h | 10 | ||||
-rw-r--r-- | src/declarative/items/qsgloader_p_p.h | 11 | ||||
-rw-r--r-- | src/declarative/particles/qsgimageparticle.cpp | 4 | ||||
-rw-r--r-- | src/declarative/particles/qsgpointattractor_p.h | 22 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativecomponent.cpp | 58 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativecomponent_p.h | 6 |
8 files changed, 307 insertions, 42 deletions
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro index 5db77a79dd..d0a3f01148 100644 --- a/src/declarative/declarative.pro +++ b/src/declarative/declarative.pro @@ -8,7 +8,6 @@ MODULE_PRI += ../../modules/qt_declarative.pri QT = core-private gui gui-private network widgets-private sql v8-private -contains(QT_CONFIG, svg): QT += svg DEFINES += QT_BUILD_DECLARATIVE_LIB QT_NO_URL_CAST_FROM_STRING win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000 solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 diff --git a/src/declarative/items/qsgloader.cpp b/src/declarative/items/qsgloader.cpp index 999c174ee9..0a0a3b9cc5 100644 --- a/src/declarative/items/qsgloader.cpp +++ b/src/declarative/items/qsgloader.cpp @@ -46,16 +46,21 @@ #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativecomponent_p.h> + +#include <private/qv8_p.h> + QT_BEGIN_NAMESPACE QSGLoaderPrivate::QSGLoaderPrivate() : item(0), component(0), ownComponent(false), updatingSize(false), - itemWidthValid(false), itemHeightValid(false) + itemWidthValid(false), itemHeightValid(false), active(true) { } QSGLoaderPrivate::~QSGLoaderPrivate() { + disposeInitialPropertyValues(); } void QSGLoaderPrivate::itemGeometryChanged(QSGItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) @@ -72,6 +77,8 @@ void QSGLoaderPrivate::itemGeometryChanged(QSGItem *resizeItem, const QRectF &ne void QSGLoaderPrivate::clear() { + disposeInitialPropertyValues(); + if (ownComponent) { component->deleteLater(); component = 0; @@ -228,6 +235,59 @@ QSGLoader::~QSGLoader() } /*! + \qmlproperty bool QtQuick2::Loader::active + This property is \c true if the Loader is currently active. + The default value for the \l active property is \c true. + + If the Loader is inactive, changing the \l source or \l sourceComponent + will not cause the item to be instantiated until the Loader is made active. + + Setting the value to inactive will cause any \l item loaded by the loader + to be released, but will not affect the \l source or \l sourceComponent. + + The \l status of an inactive loader is always \c Null. + + \sa source, sourceComponent + */ +bool QSGLoader::active() const +{ + Q_D(const QSGLoader); + return d->active; +} + +void QSGLoader::setActive(bool newVal) +{ + Q_D(QSGLoader); + if (d->active != newVal) { + d->active = newVal; + if (newVal == true) { + if (d->loadingFromSource) { + loadFromSource(); + } else { + loadFromSourceComponent(); + } + d->disposeInitialPropertyValues(); // release persistent handles + } else { + if (d->item) { + QSGItemPrivate *p = QSGItemPrivate::get(d->item); + p->removeItemChangeListener(d, QSGItemPrivate::Geometry); + + // We can't delete immediately because our item may have triggered + // the Loader to load a different item. + d->item->setParentItem(0); + d->item->setVisible(false); + d->item->deleteLater(); + d->item = 0; + emit itemChanged(); + } + emit statusChanged(); + } + emit activeChanged(); + } +} + + +/*! \qmlproperty url QtQuick2::Loader::source This property holds the URL of the QML component to instantiate. @@ -248,13 +308,30 @@ QUrl QSGLoader::source() const void QSGLoader::setSource(const QUrl &url) { + setSource(url, true); // clear previous values +} + +void QSGLoader::setSource(const QUrl &url, bool needsClear) +{ Q_D(QSGLoader); if (d->source == url) return; - d->clear(); + if (needsClear) + d->clear(); d->source = url; + d->loadingFromSource = true; + + if (d->active) + loadFromSource(); + else + emit sourceChanged(); +} + +void QSGLoader::loadFromSource() +{ + Q_D(QSGLoader); if (d->source.isEmpty()) { emit sourceChanged(); emit statusChanged(); @@ -308,6 +385,22 @@ void QSGLoader::setSourceComponent(QDeclarativeComponent *comp) d->component = comp; d->ownComponent = false; + d->loadingFromSource = false; + + if (d->active) + loadFromSourceComponent(); + else + emit sourceComponentChanged(); +} + +void QSGLoader::resetSourceComponent() +{ + setSourceComponent(0); +} + +void QSGLoader::loadFromSourceComponent() +{ + Q_D(QSGLoader); if (!d->component) { emit sourceComponentChanged(); emit statusChanged(); @@ -320,9 +413,95 @@ void QSGLoader::setSourceComponent(QDeclarativeComponent *comp) d->load(); } -void QSGLoader::resetSourceComponent() +/*! + \qmlmethod object QtQuick2::Loader::setSource(url source, object properties) + + Creates an object instance of the given \a source component that will have + the given \a properties. The \a properties argument is optional. The instance + will be accessible via the \l item property once loading and instantiation + is complete. + + If the \l active property is \c false at the time when this function is called, + the given \a source component will not be loaded but the \a source and initial + \a properties will be cached. When the loader is made \l active, an instance of + the \a source component will be created with the initial \a properties set. + + Setting the initial property values of an instance of a component in this manner + will \e not trigger any associated \l{Behavior}s. + + Note that the cached \a properties will be cleared if the \l source or \l sourceComponent + is changed after calling this function but prior to setting the loader \l active. + + Example: + \table + \row + \o + \qml + // ExampleComponent.qml + import QtQuick 2.0 + Rectangle { + id: rect + color: "red" + width: 10 + height: 10 + + Behavior on color { + NumberAnimation { + target: rect + property: "width" + to: (rect.width + 20) + duration: 0 + } + } + } + \endqml + \o + \qml + // example.qml + import QtQuick 2.0 + Item { + Loader { + id: squareLoader + onLoaded: console.log(squareLoader.item.width); // prints [10], not [30] + } + + Component.onCompleted: { + squareLoader.setSource("ExampleComponent.qml", { "color": "blue" }); + // will trigger the onLoaded code when complete. + } + } + \endqml + \endtable + + \sa source, active +*/ +void QSGLoader::setSource(QDeclarativeV8Function *args) { - setSourceComponent(0); + Q_ASSERT(args); + Q_D(QSGLoader); + + bool ipvError = false; + args->returnValue(v8::Undefined()); + v8::Handle<v8::Object> ipv = d->extractInitialPropertyValues(args, this, &ipvError); + if (ipvError) + return; + + d->clear(); + QUrl sourceUrl = d->resolveSourceUrl(args); + if (!ipv.IsEmpty()) { + d->initialPropertyValues = qPersistentNew(ipv); + d->qmlGlobalForIpv = qPersistentNew(args->qmlGlobal()); + } + + setSource(sourceUrl, false); // already cleared and set ipv above. +} + +void QSGLoaderPrivate::disposeInitialPropertyValues() +{ + if (!initialPropertyValues.IsEmpty()) + qPersistentDispose(initialPropertyValues); + if (!qmlGlobalForIpv.IsEmpty()) + qPersistentDispose(qmlGlobalForIpv); } void QSGLoaderPrivate::load() @@ -377,7 +556,7 @@ void QSGLoaderPrivate::_q_sourceLoaded() // component to be set to something else. In that case we just // need to cleanup. if (c) - c->completeCreate(); + completeCreateWithInitialPropertyValues(c, obj, initialPropertyValues, qmlGlobalForIpv); delete obj; delete ctxt; return; @@ -402,7 +581,7 @@ void QSGLoaderPrivate::_q_sourceLoaded() delete ctxt; source = QUrl(); } - component->completeCreate(); + completeCreateWithInitialPropertyValues(component, obj, initialPropertyValues, qmlGlobalForIpv); if (ownComponent) emit q->sourceChanged(); else @@ -419,7 +598,7 @@ void QSGLoaderPrivate::_q_sourceLoaded() This property holds the status of QML loading. It can be one of: \list - \o Loader.Null - no QML source has been set + \o Loader.Null - the loader is inactive or no QML source has been set \o Loader.Ready - the QML source has been loaded \o Loader.Loading - the QML source is currently being loaded \o Loader.Error - an error occurred while loading the QML source @@ -458,6 +637,9 @@ QSGLoader::Status QSGLoader::status() const { Q_D(const QSGLoader); + if (!d->active) + return Null; + if (d->component) return static_cast<QSGLoader::Status>(d->component->status()); @@ -548,6 +730,47 @@ void QSGLoader::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeom QSGItem::geometryChanged(newGeometry, oldGeometry); } +QUrl QSGLoaderPrivate::resolveSourceUrl(QDeclarativeV8Function *args) +{ + QV8Engine *v8engine = args->engine(); + QString arg = v8engine->toString((*args)[0]->ToString()); + if (arg.isEmpty()) + return QUrl(); + + QDeclarativeContextData *context = args->context(); + Q_ASSERT(context); + return context->resolvedUrl(QUrl(arg)); +} + +v8::Handle<v8::Object> QSGLoaderPrivate::extractInitialPropertyValues(QDeclarativeV8Function *args, QObject *loader, bool *error) +{ + v8::Local<v8::Object> valuemap; + if (args->Length() >= 2) { + v8::Local<v8::Value> v = (*args)[1]; + if (!v->IsObject() || v->IsArray()) { + *error = true; + qmlInfo(loader) << loader->tr("setSource: value is not an object"); + } else { + *error = false; + valuemap = v8::Local<v8::Object>::Cast(v); + } + } + + return valuemap; +} + +void QSGLoaderPrivate::completeCreateWithInitialPropertyValues(QDeclarativeComponent *component, QObject *object, v8::Handle<v8::Object> initialPropertyValues, v8::Handle<v8::Object> qmlGlobal) +{ + if (initialPropertyValues.IsEmpty()) { + component->completeCreate(); + return; + } + + QDeclarativeComponentPrivate *d = QDeclarativeComponentPrivate::get(component); + Q_ASSERT(d && d->engine); + d->completeCreateObjectWithInitialProperties(qmlGlobal, initialPropertyValues, object); +} + #include <moc_qsgloader_p.cpp> QT_END_NAMESPACE diff --git a/src/declarative/items/qsgloader_p.h b/src/declarative/items/qsgloader_p.h index 832d3a6138..c3ce1607e0 100644 --- a/src/declarative/items/qsgloader_p.h +++ b/src/declarative/items/qsgloader_p.h @@ -57,6 +57,7 @@ class Q_AUTOTEST_EXPORT QSGLoader : public QSGImplicitSizeItem Q_OBJECT Q_ENUMS(Status) + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(QDeclarativeComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceComponentChanged) Q_PROPERTY(QSGItem *item READ item NOTIFY itemChanged) @@ -67,6 +68,11 @@ public: QSGLoader(QSGItem *parent = 0); virtual ~QSGLoader(); + bool active() const; + void setActive(bool newVal); + + Q_INVOKABLE void setSource(QDeclarativeV8Function *); + QUrl source() const; void setSource(const QUrl &); @@ -82,6 +88,7 @@ public: Q_SIGNALS: void itemChanged(); + void activeChanged(); void sourceChanged(); void sourceComponentChanged(); void statusChanged(); @@ -93,6 +100,9 @@ protected: void componentComplete(); private: + void setSource(const QUrl &sourceUrl, bool needsClear); + void loadFromSource(); + void loadFromSourceComponent(); Q_DISABLE_COPY(QSGLoader) Q_DECLARE_PRIVATE(QSGLoader) Q_PRIVATE_SLOT(d_func(), void _q_sourceLoaded()) diff --git a/src/declarative/items/qsgloader_p_p.h b/src/declarative/items/qsgloader_p_p.h index 306e5ea732..732ec8679d 100644 --- a/src/declarative/items/qsgloader_p_p.h +++ b/src/declarative/items/qsgloader_p_p.h @@ -58,6 +58,8 @@ #include "qsgimplicitsizeitem_p_p.h" #include "qsgitemchangelistener_p.h" +#include <private/qv8_p.h> + QT_BEGIN_NAMESPACE class QDeclarativeContext; @@ -74,13 +76,22 @@ public: void initResize(); void load(); + void disposeInitialPropertyValues(); + QUrl resolveSourceUrl(QDeclarativeV8Function *args); + v8::Handle<v8::Object> extractInitialPropertyValues(QDeclarativeV8Function *args, QObject *loader, bool *error); + void completeCreateWithInitialPropertyValues(QDeclarativeComponent *component, QObject *object, v8::Handle<v8::Object> initialPropertyValues, v8::Handle<v8::Object> qmlGlobal); + QUrl source; QSGItem *item; QDeclarativeComponent *component; + v8::Persistent<v8::Object> initialPropertyValues; + v8::Persistent<v8::Object> qmlGlobalForIpv; bool ownComponent : 1; bool updatingSize: 1; bool itemWidthValid : 1; bool itemHeightValid : 1; + bool active : 1; + bool loadingFromSource : 1; void _q_sourceLoaded(); void _q_updateSize(bool loaderGeometryChanged = true); diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp index 853a08a890..f269895536 100644 --- a/src/declarative/particles/qsgimageparticle.cpp +++ b/src/declarative/particles/qsgimageparticle.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE //###Switch to define later, for now user-friendly (no compilation) debugging is worth it DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG) -#ifdef Q_WS_MAC +#ifndef QT_OPENGL_ES_2 #define SHADER_DEFINES "#version 120\n" #else #define SHADER_DEFINES "" @@ -864,7 +864,7 @@ QSGGeometryNode* QSGImageParticle::buildParticleNodes() } else if (m_autoRotation || m_rotation || m_rotationVariation || m_rotationSpeed || m_rotationSpeedVariation) { perfLevel = Deformable; - } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid() + } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid() || m_color_variation || m_redVariation || m_blueVariation || m_greenVariation) { perfLevel = Colored; } else { diff --git a/src/declarative/particles/qsgpointattractor_p.h b/src/declarative/particles/qsgpointattractor_p.h index 298965a5c9..e2cdd0fdca 100644 --- a/src/declarative/particles/qsgpointattractor_p.h +++ b/src/declarative/particles/qsgpointattractor_p.h @@ -52,11 +52,9 @@ QT_MODULE(Declarative) class QSGPointAttractorAffector : public QSGParticleAffector { Q_OBJECT - //Like Gravitational singularity, but linear to distance instead of quadratic - //And affects ds/dt, not da/dt Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) - Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)//TODO: Change to pointX, pointY - Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged) + Q_PROPERTY(qreal pointX READ pointX WRITE setPointX NOTIFY pointXChanged) + Q_PROPERTY(qreal pointY READ pointY WRITE setPointY NOTIFY pointYChanged) Q_PROPERTY(PhysicsAffects physics READ physics WRITE setPhysics NOTIFY physicsChanged) Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged) Q_ENUMS(PhysicsAffects) @@ -84,12 +82,12 @@ public: return m_strength; } - qreal x() const + qreal pointX() const { return m_x; } - qreal y() const + qreal pointY() const { return m_y; } @@ -108,9 +106,9 @@ signals: void strengthChanged(qreal arg); - void xChanged(qreal arg); + void pointXChanged(qreal arg); - void yChanged(qreal arg); + void pointYChanged(qreal arg); void physicsChanged(PhysicsAffects arg); @@ -125,19 +123,19 @@ void setStrength(qreal arg) } } -void setX(qreal arg) +void setPointX(qreal arg) { if (m_x != arg) { m_x = arg; - emit xChanged(arg); + emit pointXChanged(arg); } } -void setY(qreal arg) +void setPointY(qreal arg) { if (m_y != arg) { m_y = arg; - emit yChanged(arg); + emit pointYChanged(arg); } } void setPhysics(PhysicsAffects arg) diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index eea94cef3e..49aa6d99b6 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -55,6 +55,9 @@ #include "private/qdeclarativedebugtrace_p.h" #include "private/qdeclarativeenginedebug_p.h" +#include "private/qv8engine_p.h" +#include "private/qv8include_p.h" + #include <QStack> #include <QStringList> #include <QtCore/qdebug.h> @@ -663,35 +666,45 @@ void QDeclarativeComponent::createObject(QDeclarativeV8Function *args) { Q_ASSERT(args); -#define RETURN(result) { args->returnValue((result)); return; } - Q_D(QDeclarativeComponent); Q_ASSERT(d->engine); - QDeclarativeEngine *engine = d->engine; - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QV8Engine *v8engine = ep->v8engine(); - - QDeclarativeContext *ctxt = creationContext(); - if (!ctxt) ctxt = engine->rootContext(); + QObject *parent = args->Length()?QDeclarativeEnginePrivate::get(d->engine)->v8engine()->toQObject((*args)[0]):0; v8::Local<v8::Object> valuemap; if (args->Length() >= 2) { v8::Local<v8::Value> v = (*args)[1]; if (!v->IsObject() || v->IsArray()) { qmlInfo(this) << tr("createObject: value is not an object"); - RETURN(v8::Null()); + args->returnValue(v8::Null()); + return; } valuemap = v8::Local<v8::Object>::Cast(v); } - QObject *parent = args->Length()?v8engine->toQObject((*args)[0]):0; + QV8Engine *v8engine = QDeclarativeEnginePrivate::get(d->engine)->v8engine(); + QObject *retn = d->createObjectWithInitialProperties(args->qmlGlobal(), valuemap, parent); + if (!retn) + args->returnValue(v8::Null()); + else + args->returnValue(v8engine->newQObject(retn)); +} + +QObject *QDeclarativeComponentPrivate::createObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *parentObject) +{ + Q_Q(QDeclarativeComponent); + Q_ASSERT(engine); - QObject *ret = beginCreate(ctxt); + QDeclarativeContext *ctxt = q->creationContext(); + if (!ctxt) ctxt = engine->rootContext(); + + QObject *parent = parentObject; + + QObject *ret = q->beginCreate(ctxt); if (!ret) { - completeCreate(); - RETURN(v8::Null()); + q->completeCreate(); + return 0; } if (parent) { @@ -715,7 +728,14 @@ void QDeclarativeComponent::createObject(QDeclarativeV8Function *args) qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene."); } - v8::Handle<v8::Value> ov = v8engine->newQObject(ret); + return completeCreateObjectWithInitialProperties(qmlGlobal, valuemap, ret); +} + +QObject *QDeclarativeComponentPrivate::completeCreateObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *toCreate) +{ + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + QV8Engine *v8engine = ep->v8engine(); + v8::Handle<v8::Value> ov = v8engine->newQObject(toCreate); Q_ASSERT(ov->IsObject()); v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov); @@ -738,7 +758,7 @@ void QDeclarativeComponent::createObject(QDeclarativeV8Function *args) "})" v8::Local<v8::Script> script = v8engine->qmlModeCompile(SET_ARGS_SOURCE); - v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(script->Run(args->qmlGlobal())); + v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(script->Run(qmlGlobal)); // Try catch isn't needed as the function itself is loaded with try/catch v8::Handle<v8::Value> args[] = { object, valuemap }; @@ -746,14 +766,12 @@ void QDeclarativeComponent::createObject(QDeclarativeV8Function *args) } completeCreate(); - - QDeclarativeData *ddata = QDeclarativeData::get(ret); + + QDeclarativeData *ddata = QDeclarativeData::get(toCreate); Q_ASSERT(ddata); ddata->setImplicitDestructible(); - RETURN(object); - -#undef RETURN + return v8engine->toQObject(object); } /*! diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 7677f305e2..ba937491b7 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -55,6 +55,7 @@ #include "qdeclarativecomponent.h" +#include "private/qv8_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativetypeloader_p.h" #include "private/qbitfield_p.h" @@ -69,6 +70,8 @@ QT_BEGIN_NAMESPACE +class QV8Engine; + class QDeclarativeComponent; class QDeclarativeEngine; class QDeclarativeCompiledData; @@ -83,6 +86,8 @@ public: QObject *beginCreate(QDeclarativeContextData *, const QBitField &); void completeCreate(); + QObject *createObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *parentObject); + QObject *completeCreateObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *toCreate); QDeclarativeTypeData *typeData; virtual void typeDataReady(QDeclarativeTypeData *); @@ -115,6 +120,7 @@ public: ConstructionState *state); static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state); + QDeclarativeEngine *engine; QDeclarativeGuardedContextData creationContext; |