summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2009-06-09 02:46:10 (GMT)
committerAlan Alpert <alan.alpert@nokia.com>2009-06-09 02:46:10 (GMT)
commitdb4addcf3408140bb34fa8884c7192c1d9667be8 (patch)
tree3895f60a7c24d05082120c68d8d8fcd4972b2aaf
parent991b41aa407b5a8740e6899a3efdc724276dcb95 (diff)
downloadQt-db4addcf3408140bb34fa8884c7192c1d9667be8.zip
Qt-db4addcf3408140bb34fa8884c7192c1d9667be8.tar.gz
Qt-db4addcf3408140bb34fa8884c7192c1d9667be8.tar.bz2
Add dynamic object creation from Script.
Can now create, inside script, objects from qml snippets and files. These objects can then be manipulated from script. Deleting these items is still being looked into.
-rw-r--r--src/declarative/qml/qmlcomponent.cpp18
-rw-r--r--src/declarative/qml/qmlcomponent.h11
-rw-r--r--src/declarative/qml/qmlengine.cpp122
-rw-r--r--src/declarative/qml/qmlengine.h9
4 files changed, 156 insertions, 4 deletions
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index 78137e8..267fba8 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -387,6 +387,24 @@ QmlComponent::QmlComponent(QmlComponentPrivate &dd, QObject *parent)
}
/*!
+ Create a script object instance from this component. Returns a null
+ script object if creation failed. It will create the instance in the
+ engine's \l {QmlEngine::rootContext()}{root context}.
+
+ Similar to QmlComponent::create(), but creates an object suitable
+ for usage within scripts.
+*/
+QScriptValue QmlComponent::createObject()
+{
+ Q_D(QmlComponent);
+ QObject* ret = create();
+ if(ret)
+ return QmlEngine::qmlScriptObject(ret, d->engine);
+ else
+ return d->engine->scriptEngine()->nullValue();
+}
+
+/*!
Create an object instance from this component. Returns 0 if creation
failed. \a context specifies the context within which to create the object
instance.
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
index e7386d9..bb76c8b 100644
--- a/src/declarative/qml/qmlcomponent.h
+++ b/src/declarative/qml/qmlcomponent.h
@@ -44,6 +44,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
+#include <QtScript/qscriptvalue.h>
#include <QtDeclarative/qfxglobal.h>
#include <QtDeclarative/qml.h>
#include <QtDeclarative/qmlerror.h>
@@ -70,18 +71,20 @@ public:
const QUrl &baseUrl=QUrl(), QObject *parent=0);
virtual ~QmlComponent();
+ Q_ENUMS( Status );
enum Status { Null, Ready, Loading, Error };
Status status() const;
- bool isNull() const;
- bool isReady() const;
- bool isError() const;
- bool isLoading() const;
+ Q_INVOKABLE bool isNull() const;
+ Q_INVOKABLE bool isReady() const;
+ Q_INVOKABLE bool isError() const;
+ Q_INVOKABLE bool isLoading() const;
QList<QmlError> errors() const;
QUrl url() const;
+ Q_INVOKABLE QScriptValue createObject();
virtual QObject *create(QmlContext *context = 0);
virtual QObject *beginCreate(QmlContext *);
virtual void completeCreate();
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 18f28ed..d8ca809 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -203,6 +203,13 @@ void QmlEnginePrivate::init()
debugger->attachTo(&scriptEngine);
}
#endif
+ //###needed for the other funcs, but should it be exposed?
+ scriptEngine.globalObject().setProperty(QLatin1String("qmlEngine"),
+ scriptEngine.newQObject(q));
+ scriptEngine.globalObject().setProperty(QLatin1String("evalQml"),
+ scriptEngine.newFunction(QmlEngine::createQMLObject, 1));
+ scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
+ scriptEngine.newFunction(QmlEngine::createComponent, 1));
}
QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
@@ -808,7 +815,122 @@ QmlEngine *QmlEngine::activeEngine()
return engines->top();
}
+/*!
+ Creates a QScriptValue allowing you to use \a object in QML script.
+ \a engine is the QmlEngine it is to be created in.
+
+ The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
+ to the special needs of QML requiring more functionality than a standard
+ QtScript QObject.
+
+ You'll want to use this function if you are writing C++ code which
+ dynamically creates and returns objects when called from QtScript,
+ and these objects are visual items in the QML tree.
+
+ \sa QmlEngine::newQObject()
+*/
+QScriptValue QmlEngine::qmlScriptObject(QObject* object, QmlEngine* engine)
+{
+ return engine->scriptEngine()->newObject(new QmlObjectScriptClass(engine),
+ engine->scriptEngine()->newQObject(object));
+}
+
+/*!
+ This function is intended for use inside QML only. In C++ just create a
+ component object as usual.
+
+ This function takes the URL of a QML file as its only argument. It returns
+ a component object which can be used to create and load that QML file.
+
+ Example JavaScript:
+ \code
+ component = createComponent("Sprite.qml");
+ if(component.isReady()){
+ sprite = component.create();
+ if(sprite == 0){
+ // Error Handling
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ }else{
+ // The finishCreation function does the same thing as the above
+ // if(component.isReady()) branch
+ component.statusChanged.connect(finishCreation);
+ }
+ \endcode
+
+ Remember that QML files that might be loaded over the network cannot be
+ expected to be ready immediately.
+*/
+QScriptValue QmlEngine::createComponent(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ QmlComponent* c;
+ QmlEngine* activeEngine = qobject_cast<QmlEngine*>(
+ engine->globalObject().property(QLatin1String("qmlEngine")).toQObject());
+ if(ctxt->argumentCount() != 1 || !activeEngine){
+ c = new QmlComponent(activeEngine);
+ }else{
+ c = new QmlComponent(activeEngine, QUrl(ctxt->argument(0).toString()),
+ activeEngine);
+ }
+ return engine->newQObject(c);
+}
+/*!
+ Creates a new object from the specified string of qml. If a second argument
+ is provided, this is treated as the filepath that the qml came from.
+
+ This function is intended for use inside QML only. It is intended to behave
+ similarly to eval, but for creating QML elements. Thus, it is called as
+ evalQml() in QtScript.
+
+ Returns the created object, or null if there is an error. In the case of an
+ error, details of the error are output using qWarning().
+*/
+QScriptValue QmlEngine::createQMLObject(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ QmlEngine* activeEngine = qobject_cast<QmlEngine*>(
+ engine->globalObject().property(QLatin1String("qmlEngine")).toQObject());
+ if(ctxt->argumentCount() < 1 || !activeEngine){
+ if(ctxt->argumentCount() < 1){
+ qWarning() << "createQMLObject requires a string argument.";
+ }else{
+ qWarning() << "createQMLObject failed inexplicably.";
+ }
+ return engine->nullValue();
+ }
+
+ QString qml = ctxt->argument(0).toString();
+ QUrl url;
+ if(ctxt->argumentCount() > 1)
+ url = QUrl(ctxt->argument(1).toString());
+ QmlComponent component(activeEngine, qml.toUtf8(), url);
+ if(component.isError()) {
+ QList<QmlError> errors = component.errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return engine->nullValue();
+ }
+
+ QObject *obj = component.create();
+ if(component.isError()) {
+ QList<QmlError> errors = component.errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return engine->nullValue();
+ }
+
+ if(obj){
+ return qmlScriptObject(obj, activeEngine);
+ }
+ return engine->nullValue();
+}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), line(-1), id(0), log(0)
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
index 9382389..ca66097 100644
--- a/src/declarative/qml/qmlengine.h
+++ b/src/declarative/qml/qmlengine.h
@@ -44,6 +44,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qmap.h>
+#include <QtScript/qscriptvalue.h>
QT_BEGIN_HEADER
@@ -57,6 +58,7 @@ class QmlExpression;
class QmlContext;
class QUrl;
class QScriptEngine;
+class QScriptContext;
class QNetworkAccessManager;
class Q_DECLARATIVE_EXPORT QmlEngine : public QObject
{
@@ -85,6 +87,13 @@ public:
static QmlContext *contextForObject(const QObject *);
static void setContextForObject(QObject *, QmlContext *);
+
+ static QScriptValue qmlScriptObject(QObject*, QmlEngine*);
+
+ // Below two functions provide a way to dynamically create objects from JS
+ static QScriptValue createComponent(QScriptContext*, QScriptEngine*);
+ static QScriptValue createQMLObject(QScriptContext*, QScriptEngine*);
+
private:
// LK: move to the private class
QScriptEngine *scriptEngine();