summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2009-10-22 03:01:04 (GMT)
committerMartin Jones <martin.jones@nokia.com>2009-10-22 03:01:04 (GMT)
commit6425ab5e2392584a0bf6455d426163bf6f257e82 (patch)
treedc7c283f3ae4a9142d070b534ab9d69e728a80e8 /src
parent42849ecec82fb289fd337fb9dc591bd48ba89b56 (diff)
parent6c9ac788a60fcd2f946787a5297d7c2f71ad1968 (diff)
downloadQt-6425ab5e2392584a0bf6455d426163bf6f257e82.zip
Qt-6425ab5e2392584a0bf6455d426163bf6f257e82.tar.gz
Qt-6425ab5e2392584a0bf6455d426163bf6f257e82.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src')
-rw-r--r--src/declarative/fx/qfxanchors.cpp8
-rw-r--r--src/declarative/qml/qml.pri2
-rw-r--r--src/declarative/qml/qmlcompiler.cpp32
-rw-r--r--src/declarative/qml/qmlcompiler_p.h3
-rw-r--r--src/declarative/qml/qmlengine.cpp70
-rw-r--r--src/declarative/qml/qmlengine_p.h3
-rw-r--r--src/declarative/qml/qmlexpression.cpp4
-rw-r--r--src/declarative/qml/qmlinstruction_p.h6
-rw-r--r--src/declarative/qml/qmlparser.cpp10
-rw-r--r--src/declarative/qml/qmlparser_p.h2
-rw-r--r--src/declarative/qml/qmlscriptstring.cpp154
-rw-r--r--src/declarative/qml/qmlscriptstring.h87
-rw-r--r--src/declarative/qml/qmlvme.cpp16
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp3
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h1
-rw-r--r--src/declarative/util/qmlopenmetaobject.cpp8
-rw-r--r--src/declarative/util/qmlopenmetaobject.h1
-rw-r--r--src/declarative/util/qmlpropertymap.cpp115
-rw-r--r--src/declarative/util/qmlpropertymap.h14
19 files changed, 502 insertions, 37 deletions
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
index 09776e5..085bbc7 100644
--- a/src/declarative/fx/qfxanchors.cpp
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -181,6 +181,9 @@ void QFxAnchorsPrivate::centerInChanged()
void QFxAnchorsPrivate::clearItem(QFxItem *item)
{
+ Q_Q(QFxAnchors);
+ if (!item)
+ return;
if (fill == item)
fill = 0;
if (centerIn == item)
@@ -213,6 +216,9 @@ void QFxAnchorsPrivate::clearItem(QFxItem *item)
baseline.item = 0;
usedAnchors &= ~QFxAnchors::HasBaselineAnchor;
}
+ QFxItemPrivate *p =
+ static_cast<QFxItemPrivate *>(QGraphicsItemPrivate::get(item));
+ p->dependantAnchors.removeAll(q);
}
void QFxAnchorsPrivate::addDepend(QFxItem *item)
@@ -232,7 +238,7 @@ void QFxAnchorsPrivate::remDepend(QFxItem *item)
return;
QFxItemPrivate *p =
static_cast<QFxItemPrivate *>(QGraphicsItemPrivate::get(item));
- p->dependantAnchors.removeAll(q);
+ p->dependantAnchors.removeOne(q);
}
bool QFxAnchorsPrivate::isItemComplete() const
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 58a18a2..b6e86a8 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -40,6 +40,7 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlpropertycache.cpp \
qml/qmlintegercache.cpp \
qml/qmltypenamecache.cpp \
+ qml/qmlscriptstring.cpp \
qml/qmlobjectscriptclass.cpp \
qml/qmlcontextscriptclass.cpp \
qml/qmlglobalscriptclass.cpp \
@@ -102,6 +103,7 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlpropertycache_p.h \
qml/qmlintegercache_p.h \
qml/qmltypenamecache_p.h \
+ qml/qmlscriptstring.h \
qml/qmlobjectscriptclass_p.h \
qml/qmlcontextscriptclass_p.h \
qml/qmlglobalscriptclass_p.h \
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index e2fd7cb..726051e 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -69,6 +69,7 @@
#include <private/qmlexpression_p.h>
#include "qmlmetaproperty_p.h"
#include "qmlrewrite_p.h"
+#include <QtDeclarative/qmlscriptstring.h>
#include "qmlscriptparser_p.h"
@@ -860,6 +861,17 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
void QmlCompiler::genObjectBody(QmlParser::Object *obj)
{
+ typedef QPair<Property *, int> PropPair;
+ foreach(const PropPair &prop, obj->scriptStringProperties) {
+ QmlInstruction ss;
+ ss.type = QmlInstruction::StoreScriptString;
+ ss.storeScriptString.propertyIndex = prop.first->index;
+ ss.storeScriptString.value =
+ output->indexForString(prop.first->values.at(0)->value.asScript());
+ ss.storeScriptString.scope = prop.second;
+ output->bytecode << ss;
+ }
+
bool seenDefer = false;
foreach(Property *prop, obj->valueProperties) {
if (prop->isDeferred) {
@@ -1371,6 +1383,10 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop,
COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
+ } else if (prop->type == qMetaTypeId<QmlScriptString>()) {
+
+ COMPILE_CHECK(buildScriptStringProperty(prop, obj, ctxt));
+
} else {
COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
@@ -1823,6 +1839,22 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop,
return true;
}
+// Compiles an assignment to a QmlScriptString property
+bool QmlCompiler::buildScriptStringProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (prop->values.count() > 1)
+ COMPILE_EXCEPTION(prop->values.at(1), qApp->translate("QmlCompiler", "Cannot assign multiple values to a script property"));
+
+ if (prop->values.at(0)->object || !prop->values.at(0)->value.isScript())
+ COMPILE_EXCEPTION(prop->values.at(0), qApp->translate("QmlCompiler", "Invalid property assignment: script expected"));
+
+ obj->addScriptStringProperty(prop, ctxt.stack);
+
+ return true;
+}
+
// Compile regular property assignments of the form "property: <value>"
//
// ### The following problems exist
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index cff4937..8a9ca9c 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -197,6 +197,9 @@ private:
bool buildListProperty(QmlParser::Property *prop,
QmlParser::Object *obj,
const BindingContext &ctxt);
+ bool buildScriptStringProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
bool buildPropertyAssignment(QmlParser::Property *prop,
QmlParser::Object *obj,
const BindingContext &ctxt);
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 528e8c9..9fad80b 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -76,9 +76,10 @@
#include <QtCore/qdir.h>
#include <QtGui/qcolor.h>
#include <QtGui/qvector3d.h>
+#include <QtGui/qsound.h>
#include <qmlcomponent.h>
-#include "private/qmlcomponentjs_p.h"
-#include "private/qmlmetaproperty_p.h"
+#include <private/qmlcomponentjs_p.h>
+#include <private/qmlmetaproperty_p.h>
#include <private/qmlbinding_p.h>
#include <private/qmlvme_p.h>
#include <private/qmlenginedebug_p.h>
@@ -87,6 +88,7 @@
#include <private/qmlsqldatabase_p.h>
#include <private/qmltypenamescriptclass_p.h>
#include <private/qmllistscriptclass_p.h>
+#include <QtDeclarative/qmlscriptstring.h>
#ifdef Q_OS_WIN // for %APPDATA%
#include "qt_windows.h"
@@ -153,12 +155,14 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
qtObject.setProperty(QLatin1String("darker"), scriptEngine.newFunction(QmlEnginePrivate::darker, 1));
qtObject.setProperty(QLatin1String("tint"), scriptEngine.newFunction(QmlEnginePrivate::tint, 2));
+ //misc methods
+ qtObject.setProperty(QLatin1String("playSound"), scriptEngine.newFunction(QmlEnginePrivate::playSound, 1));
+
scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"),
scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1));
scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1));
- //scriptEngine.globalObject().setScriptClass(new QmlGlobalScriptClass(&scriptEngine));
globalClass = new QmlGlobalScriptClass(&scriptEngine);
}
@@ -216,6 +220,9 @@ Q_GLOBAL_STATIC(QmlEngineDebugServer, qmlEngineDebugServer);
void QmlEnginePrivate::init()
{
Q_Q(QmlEngine);
+ qRegisterMetaType<QVariant>("QVariant");
+ qRegisterMetaType<QmlScriptString>("QmlScriptString");
+
scriptEngine.installTranslatorFunctions();
contextClass = new QmlContextScriptClass(q);
objectClass = new QmlObjectScriptClass(q);
@@ -281,8 +288,6 @@ QmlEngine::QmlEngine(QObject *parent)
{
Q_D(QmlEngine);
d->init();
-
- qRegisterMetaType<QVariant>("QVariant");
}
/*!
@@ -401,7 +406,12 @@ QmlContext *QmlEngine::contextForObject(const QObject *object)
QmlDeclarativeData *data =
static_cast<QmlDeclarativeData *>(priv->declarativeData);
- return data?data->context:0;
+ if (!data)
+ return 0;
+ else if (data->outerContext)
+ return data->outerContext;
+ else
+ return data->context;
}
/*!
@@ -565,6 +575,17 @@ QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object,
}
/*!
+ Returns the QmlContext for the executing QScript \a ctxt.
+*/
+QmlContext *QmlEnginePrivate::getContext(QScriptContext *ctxt)
+{
+ QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
+ return contextClass->contextFromValue(scopeNode);
+}
+
+/*!
This function is intended for use inside QML only. In C++ just create a
component object as usual.
@@ -626,7 +647,7 @@ QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt,
static_cast<QmlScriptEngine*>(engine)->p;
QmlEngine* activeEngine = activeEnginePriv->q_func();
- QmlContext* context = activeEnginePriv->currentExpression->context();
+ QmlContext* context = activeEnginePriv->getContext(ctxt);
if(ctxt->argumentCount() != 1) {
c = new QmlComponentJS(activeEngine);
}else{
@@ -647,7 +668,7 @@ QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt,
Example (where targetItem is the id of an existing QML item):
\code
- newObject = createQmlObject('Rectangle {color: "red"; width: 20; height: 20}',
+ newObject = createQmlObject('import Qt 4.6; Rectangle {color: "red"; width: 20; height: 20}',
targetItem, "dynamicSnippet1");
\endcode
@@ -677,9 +698,16 @@ QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngi
QUrl url;
if(ctxt->argumentCount() > 2)
url = QUrl(ctxt->argument(2).toString());
+ else
+ url = QUrl(QLatin1String("DynamicQML"));
QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
QmlContext *qmlCtxt = qmlContext(parentArg);
- url = qmlCtxt->resolvedUrl(url);
+ if (url.isEmpty()) {
+ url = qmlCtxt->resolvedUrl(QUrl(QLatin1String("<Unknown File>")));
+ } else {
+ url = qmlCtxt->resolvedUrl(url);
+ }
+
QmlComponent component(activeEngine, qml.toUtf8(), url);
if(component.isError()) {
QList<QmlError> errors = component.errors();
@@ -836,6 +864,30 @@ QScriptValue QmlEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engin
return qScriptValueFromValue(engine, qVariantFromValue(color));
}
+QScriptValue QmlEnginePrivate::playSound(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if (ctxt->argumentCount() < 1)
+ return engine->undefinedValue();
+
+ QUrl url(ctxt->argument(0).toString());
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ if (url.isRelative()) {
+ QmlContext *context = enginePriv->getContext(ctxt);
+ if (!context)
+ return engine->undefinedValue();
+
+ url = context->resolvedUrl(url);
+ }
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QSound::play(url.toLocalFile());
+
+ }
+ return engine->undefinedValue();
+}
+
/*!
This function allows tinting one color with another.
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index a85ac55..a74854d 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -259,10 +259,13 @@ public:
static QScriptValue darker(QScriptContext*, QScriptEngine*);
static QScriptValue tint(QScriptContext*, QScriptEngine*);
+ static QScriptValue playSound(QScriptContext*, QScriptEngine*);
+
static QScriptEngine *getScriptEngine(QmlEngine *e) { return &e->d_func()->scriptEngine; }
static QmlEngine *getEngine(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p->q_func(); }
static QmlEnginePrivate *get(QmlEngine *e) { return e->d_func(); }
static QmlEnginePrivate *get(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p; }
+ QmlContext *getContext(QScriptContext *);
};
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index b07ee4c..d2bf4a8 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -109,7 +109,7 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
QmlEngine *engine = ctxt->engine();
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
-#ifndef Q_OS_SYMBIAN //XXX Why doesn't this work?
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WIN32) //XXX Why doesn't this work?
if (!dd->programs.at(progIdx)) {
dd->programs[progIdx] =
new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line));
@@ -119,7 +119,7 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
QScriptContext *scriptContext = scriptEngine->pushCleanContext();
scriptContext->pushScope(ep->contextClass->newContext(ctxt, me));
-#ifndef Q_OS_SYMBIAN
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WIN32)
data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
#else
data->expressionFunction = scriptEngine->evaluate(data->expression);
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 5265d42..dc18b05 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -119,6 +119,7 @@ public:
StoreSignal, /* storeSignal */
StoreScript, /* storeScript */
+ StoreScriptString, /* storeScriptString */
//
// Unresolved single assignment
@@ -245,6 +246,11 @@ public:
int value;
} storeString;
struct {
+ int propertyIndex;
+ int value;
+ int scope;
+ } storeScriptString;
+ struct {
int value;
int fileName;
int lineNumber;
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index bae263a..f9e3c50 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -80,6 +80,9 @@ QmlParser::Object::~Object()
prop->release();
foreach(Property *prop, valueTypeProperties)
prop->release();
+ typedef QPair<Property *, int> PropPair;
+ foreach(const PropPair &prop, scriptStringProperties)
+ prop.first->release();
foreach(const DynamicProperty &prop, dynamicProperties)
if (prop.defaultValue) prop.defaultValue->release();
foreach(Object *obj, scriptBlockObjects)
@@ -142,6 +145,13 @@ void QmlParser::Object::addValueTypeProperty(Property *p)
valueTypeProperties << p;
}
+void QmlParser::Object::addScriptStringProperty(Property *p, int stack)
+{
+ p->addref();
+ scriptStringProperties << qMakePair(p, stack);
+}
+
+
Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
{
if (!properties.contains(name)) {
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index 88d7d77..f0867ea 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -160,11 +160,13 @@ namespace QmlParser
void addAttachedProperty(Property *);
void addGroupedProperty(Property *);
void addValueTypeProperty(Property *);
+ void addScriptStringProperty(Property *, int = 0);
QList<Property *> valueProperties;
QList<Property *> signalProperties;
QList<Property *> attachedProperties;
QList<Property *> groupedProperties;
QList<Property *> valueTypeProperties;
+ QList<QPair<Property *, int> > scriptStringProperties;
// Script blocks that were nested under this object
QStringList scriptBlocks;
diff --git a/src/declarative/qml/qmlscriptstring.cpp b/src/declarative/qml/qmlscriptstring.cpp
new file mode 100644
index 0000000..8a6afcc
--- /dev/null
+++ b/src/declarative/qml/qmlscriptstring.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlscriptstring.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlScriptStringPrivate : public QSharedData
+{
+public:
+ QmlScriptStringPrivate() : context(0), scope(0) {}
+
+ QmlContext *context;
+ QObject *scope;
+ QString script;
+};
+
+/*!
+\class QmlScriptString
+\brief The QmlScriptString class encapsulates a script and its context.
+
+The QmlScriptString is used by properties that want to accept a script "assignment" from QML.
+
+Normally, the following code would result in a binding being established for the \c script
+property. If the property had a type of QmlScriptString, the script - \e {print(1921)} - itself
+would be passed to the property and it could choose how to handle it.
+
+\code
+MyType {
+ script: print(1921)
+}
+\endcode
+*/
+
+/*!
+Construct an empty instance.
+*/
+QmlScriptString::QmlScriptString()
+: d(new QmlScriptStringPrivate)
+{
+}
+
+/*!
+Copy \a other.
+*/
+QmlScriptString::QmlScriptString(const QmlScriptString &other)
+: d(other.d)
+{
+}
+
+/*!
+\internal
+*/
+QmlScriptString::~QmlScriptString()
+{
+}
+
+/*!
+Assign \a other to this.
+*/
+QmlScriptString &QmlScriptString::operator=(const QmlScriptString &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+Return the context for the script.
+*/
+QmlContext *QmlScriptString::context() const
+{
+ return d->context;
+}
+
+/*!
+Sets the \a context for the script.
+*/
+void QmlScriptString::setContext(QmlContext *context)
+{
+ d->context = context;
+}
+
+/*!
+Returns the scope object for the script.
+*/
+QObject *QmlScriptString::scopeObject() const
+{
+ return d->scope;
+}
+
+/*!
+Sets the scope \a object for the script.
+*/
+void QmlScriptString::setScopeObject(QObject *object)
+{
+ d->scope = object;
+}
+
+/*!
+Returns the script text.
+*/
+QString QmlScriptString::script() const
+{
+ return d->script;
+}
+
+/*!
+Sets the \a script text.
+*/
+void QmlScriptString::setScript(const QString &script)
+{
+ d->script = script;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlscriptstring.h b/src/declarative/qml/qmlscriptstring.h
new file mode 100644
index 0000000..c6067ce
--- /dev/null
+++ b/src/declarative/qml/qmlscriptstring.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSCRIPTSTRING_H
+#define QMLSCRIPTSTRING_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlContext;
+class QmlScriptStringPrivate;
+class Q_DECLARATIVE_EXPORT QmlScriptString
+{
+public:
+ QmlScriptString();
+ QmlScriptString(const QmlScriptString &);
+ ~QmlScriptString();
+
+ QmlScriptString &operator=(const QmlScriptString &);
+
+ QmlContext *context() const;
+ void setContext(QmlContext *);
+
+ QObject *scopeObject() const;
+ void setScopeObject(QObject *);
+
+ QString script() const;
+ void setScript(const QString &);
+
+private:
+ QSharedDataPointer<QmlScriptStringPrivate> d;
+};
+
+Q_DECLARE_METATYPE(QmlScriptString);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSCRIPTSTRING_H
+
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 1f3903d..7f673a2 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -67,6 +67,7 @@
#include <private/qmlbinding_p.h>
#include <private/qmlcontext_p.h>
#include <private/qmlbindingoptimizations_p.h>
+#include <QtDeclarative/qmlscriptstring.h>
QT_BEGIN_NAMESPACE
@@ -552,6 +553,21 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
}
break;
+ case QmlInstruction::StoreScriptString:
+ {
+ QObject *target = stack.top();
+ QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
+ QmlScriptString ss;
+ ss.setContext(ctxt);
+ ss.setScopeObject(scope);
+ ss.setScript(primitives.at(instr.storeScriptString.value));
+
+ void *a[] = { &ss, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeScriptString.propertyIndex, a);
+ }
+ break;
+
case QmlInstruction::BeginObject:
{
QObject *target = stack.top();
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
index e5acc51..62a2a6b 100644
--- a/src/declarative/qml/qmlvmemetaobject.cpp
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -55,7 +55,7 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
const QMetaObject *other,
const QmlVMEMetaData *meta,
QmlRefCount *rc)
-: object(obj), ref(rc), metaData(meta), parent(0)
+: object(obj), ref(rc), ctxt(qmlContext(obj)), metaData(meta), parent(0)
{
if (ref)
ref->addref();
@@ -251,7 +251,6 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
(const QChar *)(((const char*)metaData) + data->bodyOffset);
QString code = QString::fromRawData(body, data->bodyLength);
- QmlContext *ctxt = qmlContext(object);
if (0 == (metaData->methodData() + id)->parameterCount) {
QmlExpression expr(ctxt, code, object);
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
index d376f4c..de46853 100644
--- a/src/declarative/qml/qmlvmemetaobject_p.h
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -112,6 +112,7 @@ protected:
private:
QObject *object;
QmlRefCount *ref;
+ QGuard<QmlContext> ctxt;
const QmlVMEMetaData *metaData;
int propOffset;
diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp
index 7305362..11648f6 100644
--- a/src/declarative/util/qmlopenmetaobject.cpp
+++ b/src/declarative/util/qmlopenmetaobject.cpp
@@ -136,6 +136,14 @@ QVariant QmlOpenMetaObject::value(const QByteArray &name) const
return d->data.at(*iter);
}
+QVariant &QmlOpenMetaObject::operator[](const QByteArray &name)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->names.find(name);
+ Q_ASSERT(iter != d->names.end());
+
+ return d->data[*iter];
+}
+
void QmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
{
QHash<QByteArray, int>::ConstIterator iter = d->names.find(name);
diff --git a/src/declarative/util/qmlopenmetaobject.h b/src/declarative/util/qmlopenmetaobject.h
index f65660d..be0490d 100644
--- a/src/declarative/util/qmlopenmetaobject.h
+++ b/src/declarative/util/qmlopenmetaobject.h
@@ -64,6 +64,7 @@ public:
void setValue(const QByteArray &, const QVariant &);
QVariant value(int) const;
void setValue(int, const QVariant &);
+ QVariant &operator[](const QByteArray &);
int count() const;
QByteArray name(int) const;
diff --git a/src/declarative/util/qmlpropertymap.cpp b/src/declarative/util/qmlpropertymap.cpp
index e23eebf..a587af3 100644
--- a/src/declarative/util/qmlpropertymap.cpp
+++ b/src/declarative/util/qmlpropertymap.cpp
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-//QBindableMapMetaObject lets us listen for changes coming from QML
+//QmlPropertyMapMetaObject lets us listen for changes coming from QML
//so we can emit the changed signal.
class QmlPropertyMapMetaObject : public QmlOpenMetaObject
{
@@ -72,7 +72,7 @@ public:
void QmlPropertyMapPrivate::emitChanged(const QString &key)
{
Q_Q(QmlPropertyMap);
- emit q->changed(key);
+ emit q->valueChanged(key);
}
QmlPropertyMapMetaObject::QmlPropertyMapMetaObject(QmlPropertyMap *obj, QmlPropertyMapPrivate *objPriv) : QmlOpenMetaObject(obj)
@@ -87,19 +87,19 @@ void QmlPropertyMapMetaObject::propertyWrite(int index)
}
/*!
- \class QBindableMap
- \brief The QBindableMap class allows you to set key-value pairs that can be used in bindings.
+ \class QmlPropertyMap
+ \brief The QmlPropertyMap class allows you to set key-value pairs that can be used in bindings.
- QBindableMap provides a convenient way to expose domain data to the UI layer.
+ QmlPropertyMap provides a convenient way to expose domain data to the UI layer.
The following example shows how you might declare data in C++ and then
access it in QML.
Setup in C++:
\code
//create our data
- QBindableMap ownerData;
- ownerData.setValue("name", QVariant(QString("John Smith")));
- ownerData.setValue("phone", QVariant(QString("555-5555")));
+ QmlPropertyMap ownerData;
+ ownerData.insert("name", QVariant(QString("John Smith")));
+ ownerData.insert("phone", QVariant(QString("555-5555")));
//expose it to the UI layer
QmlContext *ctxt = view->bindContext();
@@ -115,16 +115,13 @@ void QmlPropertyMapMetaObject::propertyWrite(int index)
The binding is dynamic - whenever a key's value is updated, anything bound to that
key will be updated as well.
- To detect value changes made in the UI layer you can connect to the changed() signal.
- However, note that changed() is \b NOT emitted when changes are made by calling setValue()
- or clearValue() - it is only emitted when a value is updated from QML.
-*/
+ To detect value changes made in the UI layer you can connect to the valueChanged() signal.
+ However, note that valueChanged() is \b NOT emitted when changes are made by calling insert()
+ or clear() - it is only emitted when a value is updated from QML.
-// is there a more efficient way to store/return keys?
-// (or should we just provide an iterator or something else instead?)
-// can we provide a way to clear keys?
-// do we want to make any claims regarding key ordering?
-// should we have signals for insertion and and deletion -- becoming more model like
+ \note It is not possible to remove keys from the map; once a key has been added, you can only
+ modify or clear its associated value.
+*/
/*!
Constructs a bindable map with parent object \a parent.
@@ -146,7 +143,7 @@ QmlPropertyMap::~QmlPropertyMap()
/*!
Clears the value (if any) associated with \a key.
*/
-void QmlPropertyMap::clearValue(const QString &key)
+void QmlPropertyMap::clear(const QString &key)
{
Q_D(QmlPropertyMap);
d->mo->setValue(key.toUtf8(), QVariant());
@@ -169,7 +166,7 @@ QVariant QmlPropertyMap::value(const QString &key) const
If the key doesn't exist, it is automatically created.
*/
-void QmlPropertyMap::setValue(const QString &key, const QVariant &value)
+void QmlPropertyMap::insert(const QString &key, const QVariant &value)
{
Q_D(QmlPropertyMap);
if (!d->keys.contains(key))
@@ -190,7 +187,85 @@ QStringList QmlPropertyMap::keys() const
}
/*!
- \fn void QBindableMap::changed(const QString &key)
+ \overload
+
+ Same as size().
+*/
+int QmlPropertyMap::count() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.count();
+}
+
+/*!
+ Returns the number of keys in the map.
+
+ \sa isEmpty(), count()
+*/
+int QmlPropertyMap::size() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.size();
+}
+
+/*!
+ Returns true if the map contains no keys; otherwise returns
+ false.
+
+ \sa size()
+*/
+bool QmlPropertyMap::isEmpty() const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.isEmpty();
+}
+
+/*!
+ Returns true if the map contains \a key.
+
+ \sa size()
+*/
+bool QmlPropertyMap::contains(const QString &key) const
+{
+ Q_D(const QmlPropertyMap);
+ return d->keys.contains(key);
+}
+
+/*!
+ Returns the value associated with the key \a key as a modifiable
+ reference.
+
+ If the map contains no item with key \a key, the function inserts
+ an invalid QVariant into the map with key \a key, and
+ returns a reference to it.
+
+ \sa insert(), value()
+*/
+QVariant &QmlPropertyMap::operator[](const QString &key)
+{
+ //### optimize
+ Q_D(QmlPropertyMap);
+ QByteArray utf8key = key.toUtf8();
+ if (!d->keys.contains(key)) {
+ d->keys.append(key);
+ d->mo->setValue(utf8key, QVariant()); //force creation -- needed below
+ }
+
+ return (*(d->mo))[utf8key];
+}
+
+/*!
+ \overload
+
+ Same as value().
+*/
+const QVariant QmlPropertyMap::operator[](const QString &key) const
+{
+ return value(key);
+}
+
+/*!
+ \fn void QmlPropertyMap::valueChanged(const QString &key)
This signal is emitted whenever one of the values in the map is changed. \a key
is the key corresponding to the value that was changed.
*/
diff --git a/src/declarative/util/qmlpropertymap.h b/src/declarative/util/qmlpropertymap.h
index 295f4b7..24b4395 100644
--- a/src/declarative/util/qmlpropertymap.h
+++ b/src/declarative/util/qmlpropertymap.h
@@ -63,13 +63,21 @@ public:
virtual ~QmlPropertyMap();
QVariant value(const QString &key) const;
- void setValue(const QString &key, const QVariant &value);
- void clearValue(const QString &key);
+ void insert(const QString &key, const QVariant &value);
+ void clear(const QString &key);
Q_INVOKABLE QStringList keys() const;
+ int count() const;
+ int size() const;
+ bool isEmpty() const;
+ bool contains(const QString &key) const;
+
+ QVariant &operator[](const QString &key);
+ const QVariant operator[](const QString &key) const;
+
Q_SIGNALS:
- void changed(const QString &key);
+ void valueChanged(const QString &key);
private:
Q_DECLARE_PRIVATE(QmlPropertyMap)