diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-10-22 03:01:04 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-10-22 03:01:04 (GMT) |
commit | 6425ab5e2392584a0bf6455d426163bf6f257e82 (patch) | |
tree | dc7c283f3ae4a9142d070b534ab9d69e728a80e8 /src | |
parent | 42849ecec82fb289fd337fb9dc591bd48ba89b56 (diff) | |
parent | 6c9ac788a60fcd2f946787a5297d7c2f71ad1968 (diff) | |
download | Qt-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.cpp | 8 | ||||
-rw-r--r-- | src/declarative/qml/qml.pri | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 32 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 3 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 70 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 3 | ||||
-rw-r--r-- | src/declarative/qml/qmlexpression.cpp | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlinstruction_p.h | 6 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser.cpp | 10 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlscriptstring.cpp | 154 | ||||
-rw-r--r-- | src/declarative/qml/qmlscriptstring.h | 87 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 16 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject.cpp | 3 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject_p.h | 1 | ||||
-rw-r--r-- | src/declarative/util/qmlopenmetaobject.cpp | 8 | ||||
-rw-r--r-- | src/declarative/util/qmlopenmetaobject.h | 1 | ||||
-rw-r--r-- | src/declarative/util/qmlpropertymap.cpp | 115 | ||||
-rw-r--r-- | src/declarative/util/qmlpropertymap.h | 14 |
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) |