diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/declarative/fx/qfxrect.cpp | 61 | ||||
-rw-r--r-- | src/declarative/fx/qfxrect.h | 4 | ||||
-rw-r--r-- | src/declarative/fx/qfxrect_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 11 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcomponent.cpp | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmldeclarativedata_p.h | 5 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 414 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 56 | ||||
-rw-r--r-- | src/declarative/qml/qmlenginedebug.cpp | 11 | ||||
-rw-r--r-- | src/declarative/qml/qmlinfo.cpp | 16 | ||||
-rw-r--r-- | src/declarative/qml/qmlinstruction_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 14 | ||||
-rw-r--r-- | src/declarative/util/qmlanimation.h | 10 |
15 files changed, 443 insertions, 166 deletions
diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index f8223f2..fbd7ee8 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -328,63 +328,6 @@ void QFxRect::setColor(const QColor &c) update(); } -/*! - \qmlproperty color Rectangle::tintColor - This property holds The color to tint the rectangle. - - This color will be drawn over the rectangle's color when the rectangle is painted. The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque. - - \qml - Rectangle { x: 0; width: 80; height: 80; color: "lightsteelblue" } - Rectangle { x: 100; width: 80; height: 80; color: "lightsteelblue"; tintColor: "#10FF0000" } - \endqml - \image declarative-rect_tint.png - - This attribute is not intended to be used with a single color over the lifetime of an user interface. It is most useful when a subtle change is intended to be conveyed due to some event; you can then use the tint color to more effectively tune the visible color. -*/ -QColor QFxRect::tintColor() const -{ - Q_D(const QFxRect); - return d->tintColor; -} - -void QFxRect::setTintColor(const QColor &c) -{ - Q_D(QFxRect); - if (d->tintColor == c) - return; - - d->tintColor = c; - update(); -} - -QColor QFxRectPrivate::getColor() -{ - if (tintColor.isValid()) { - int a = tintColor.alpha(); - if (a == 0xFF) - return tintColor; - else if (a == 0x00) - return color; - else { - uint src = tintColor.rgba(); - uint dest = color.rgba(); - - uint res = (((a * (src & 0xFF00FF)) + - ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF; - res |= (((a * ((src >> 8) & 0xFF00FF)) + - ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00; - if ((src & 0xFF000000) == 0xFF000000) - res |= 0xFF000000; - - return QColor::fromRgba(res); - } - } else { - return color; - } -} - - void QFxRect::generateRoundedRect() { Q_D(QFxRect); @@ -443,7 +386,7 @@ void QFxRect::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) bool oldAA = p->testRenderHint(QPainter::Antialiasing); if (d->smooth) p->setRenderHints(QPainter::Antialiasing, true); - p->fillRect(QRectF(0, 0, width(), height()), d->getColor()); + p->fillRect(QRectF(0, 0, width(), height()), d->color); if (d->smooth) p->setRenderHint(QPainter::Antialiasing, oldAA); } @@ -527,7 +470,7 @@ void QFxRect::drawRect(QPainter &p) // Middle if (xMiddles && yMiddles) // XXX paint errors in animation example - //p.fillRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw, d->getColor()); + //p.fillRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw, d->color); p.drawPixmap(QRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw), d->rectImage, QRect(d->rectImage.width()/2, d->rectImage.height()/2, 1, 1)); // Middle right diff --git a/src/declarative/fx/qfxrect.h b/src/declarative/fx/qfxrect.h index 359e8fc..439cc65 100644 --- a/src/declarative/fx/qfxrect.h +++ b/src/declarative/fx/qfxrect.h @@ -136,7 +136,6 @@ class Q_DECLARATIVE_EXPORT QFxRect : public QFxItem Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor) - Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor) Q_PROPERTY(QFxGradient *gradient READ gradient WRITE setGradient) Q_PROPERTY(QFxPen * border READ border) Q_PROPERTY(qreal radius READ radius WRITE setRadius) @@ -146,9 +145,6 @@ public: QColor color() const; void setColor(const QColor &); - QColor tintColor() const; - void setTintColor(const QColor &); - QFxPen *border(); QFxGradient *gradient() const; diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index 25fa38d..8eb074a 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -81,7 +81,6 @@ public: QColor getColor(); QColor color; QFxGradient *gradient; - QColor tintColor; QFxPen *getPen() { if (!pen) { Q_Q(QFxRect); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 070add7..b8e9d47 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -642,6 +642,8 @@ void QmlCompiler::compileTree(Object *tree) def.type = QmlInstruction::SetDefault; output->bytecode << def; + output->imports = unit->imports; + if (tree->metatype) static_cast<QMetaObject &>(output->root) = *tree->metaObject(); else @@ -781,6 +783,7 @@ void QmlCompiler::genObject(QmlParser::Object *obj) QmlInstruction create; create.type = QmlInstruction::CreateObject; create.line = obj->location.start.line; + create.create.column = obj->location.start.column; create.create.data = -1; if (!obj->custom.isEmpty()) create.create.data = output->indexForByteArray(obj->custom); @@ -937,6 +940,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj) QmlInstruction create; create.type = QmlInstruction::CreateComponent; create.line = root->location.start.line; + create.createComponent.column = root->location.start.column; create.createComponent.endLine = root->location.end.line; output->bytecode << create; int count = output->bytecode.count(); @@ -1452,10 +1456,13 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, if (!isValidId(val)) COMPILE_EXCEPTION(prop, val << "is not a valid object id"); - // We disallow id's that conflict with import prefixes + // We disallow id's that conflict with import prefixes and types QmlEnginePrivate::ImportedNamespace *ns = 0; + QmlType *type = 0; QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(), - 0, 0, 0, 0, &ns); + &type, 0, 0, 0, &ns); + if (type) + COMPILE_EXCEPTION(idValue, "id conflicts with type name"); if (ns) COMPILE_EXCEPTION(idValue, "id conflicts with namespace prefix"); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index c42c2d9..83c415c 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -76,6 +76,7 @@ public: QByteArray name; QUrl url; + QmlEnginePrivate::Imports imports; struct TypeReference { diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index c844a32..e897cce 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -488,6 +488,7 @@ QObject *QmlComponent::beginCreate(QmlContext *context) static_cast<QmlContextPrivate *>(QObjectPrivate::get(context)); QmlContext *ctxt = new QmlContext(context, 0, true); static_cast<QmlContextPrivate*>(ctxt->d_func())->url = d->cc->url; + static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = d->cc->imports; QmlVME vme; QObject *rv = vme.run(ctxt, d->cc, d->start, d->count); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 84d990c..b305408 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -60,6 +60,7 @@ #include <QtScript/qscriptvalue.h> #include <QtCore/qset.h> #include <private/qguard_p.h> +#include <private/qmlengine_p.h> QT_BEGIN_NAMESPACE @@ -91,6 +92,7 @@ public: QScriptValueList scopeChain; QUrl url; + QmlEnginePrivate::Imports imports; void init(); diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index 5a51eb7..a316c0c 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE class QmlCompiledData; class QmlAbstractBinding; +class QmlContext; class QmlDeclarativeData : public QDeclarativeData { public: @@ -69,6 +70,10 @@ public: QmlContext *context; QmlAbstractBinding *bindings; + QmlContext *outerContext; // Can't this be found from context? + ushort lineNumber; + ushort columnNumber; + QmlCompiledData *deferredComponent; // Can't this be found from the context? unsigned int deferredIdx; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 9a5efdb..3d8b2c4 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -80,6 +80,7 @@ #include <private/qmlbinding_p.h> #include <private/qmlvme_p.h> #include <private/qmlenginedebug_p.h> +#include <private/qmlstringconverters_p.h> #include <private/qmlxmlhttprequest_p.h> Q_DECLARE_METATYPE(QmlMetaProperty) @@ -121,12 +122,18 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) qt_add_qmlxmlhttprequest(&scriptEngine); + //types qtObject.setProperty(QLatin1String("rgba"), scriptEngine.newFunction(QmlEnginePrivate::rgba, 4)); qtObject.setProperty(QLatin1String("hsla"), scriptEngine.newFunction(QmlEnginePrivate::hsla, 4)); qtObject.setProperty(QLatin1String("rect"), scriptEngine.newFunction(QmlEnginePrivate::rect, 4)); qtObject.setProperty(QLatin1String("point"), scriptEngine.newFunction(QmlEnginePrivate::point, 2)); qtObject.setProperty(QLatin1String("size"), scriptEngine.newFunction(QmlEnginePrivate::size, 2)); qtObject.setProperty(QLatin1String("vector3d"), scriptEngine.newFunction(QmlEnginePrivate::vector, 3)); + + //color helpers + qtObject.setProperty(QLatin1String("lighter"), scriptEngine.newFunction(QmlEnginePrivate::lighter, 1)); + qtObject.setProperty(QLatin1String("darker"), scriptEngine.newFunction(QmlEnginePrivate::darker, 1)); + qtObject.setProperty(QLatin1String("tint"), scriptEngine.newFunction(QmlEnginePrivate::tint, 2)); } QmlEnginePrivate::~QmlEnginePrivate() @@ -174,6 +181,7 @@ void QmlEnginePrivate::init() contextClass = new QmlContextScriptClass(q); objectClass = new QmlObjectScriptClass(q); valueTypeClass = new QmlValueTypeScriptClass(q); + typeNameClass = new QmlTypeNameScriptClass(q); rootContext = new QmlContext(q,true); #ifdef QT_SCRIPTTOOLS_LIB if (qmlDebugger()){ @@ -204,40 +212,158 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p) { } +struct QmlTypeNameBridge +{ + QObject *object; + QmlType *type; + QmlEnginePrivate::ImportedNamespace *ns; +}; +Q_DECLARE_METATYPE(QmlTypeNameBridge); + +struct QmlValueTypeReference { + QmlValueType *type; + QGuard<QObject> object; + int property; +}; +Q_DECLARE_METATYPE(QmlValueTypeReference); + //////////////////////////////////////////////////////////////////// -typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache; -Q_GLOBAL_STATIC(FunctionCache, functionCache); +QScriptClass::QueryFlags +QmlEnginePrivate::queryContext(const QString &propName, uint *id, + QmlContext *bindContext) +{ + resolveData.safetyCheckId++; + *id = resolveData.safetyCheckId; + resolveData.clear(); + + QHash<QString, int>::Iterator contextProperty = + bindContext->d_func()->propertyNames.find(propName); + + if (contextProperty != bindContext->d_func()->propertyNames.end()) { + + resolveData.context = bindContext; + resolveData.contextIndex = *contextProperty; + + return QScriptClass::HandlesReadAccess; + } + + QmlType *type = 0; ImportedNamespace *ns = 0; + if (currentExpression && bindContext == currentExpression->context() && + propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) { + + if (type || ns) { + // Must be either an attached property, or an enum + resolveData.object = bindContext->d_func()->defaultObjects.first(); + resolveData.type = type; + resolveData.ns = ns; + return QScriptClass::HandlesReadAccess; + } + + } + + QScriptClass::QueryFlags rv = 0; + for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) { + rv = queryObject(propName, id, + bindContext->d_func()->defaultObjects.at(ii)); + } + + return rv; +} + +QScriptValue +QmlEnginePrivate::propertyContext(const QScriptString &name, + QmlContext *bindContext, + uint id) +{ + Q_ASSERT(id == resolveData.safetyCheckId); + + + if (resolveData.type || resolveData.ns) { + QmlTypeNameBridge tnb = { + resolveData.object, + resolveData.type, + resolveData.ns + }; + return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb))); + } else if (resolveData.context) { + QmlContext *bindContext = resolveData.context; + QmlContextPrivate *contextPrivate = bindContext->d_func(); + int index = resolveData.contextIndex; + + QScriptValue rv; + if (index < contextPrivate->idValueCount) { + rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data()))); + } else { + QVariant value = contextPrivate->propertyValues.at(index); + if (QmlMetaType::isObject(value.userType())) { + rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value)); + } else { + rv = scriptEngine.newVariant(value); + } + } + capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex); + return rv; + + } else { + + return propertyObject(name, resolveData.object, id); + + } + + return QScriptValue(); +} + +void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id) +{ + // As context properties cannot be written, we can assume that the + // write is a object property write + setPropertyObject(value, id); +} + +void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id) +{ + Q_ASSERT(id == resolveData.safetyCheckId); + Q_Q(QmlEngine); + + resolveData.property.write(QmlScriptClass::toVariant(q, value)); +} QScriptClass::QueryFlags QmlEnginePrivate::queryObject(const QString &propName, uint *id, QObject *obj) { + resolveData.safetyCheckId++; + *id = resolveData.safetyCheckId; + resolveData.clear(); + QScriptClass::QueryFlags rv = 0; QmlContext *ctxt = QmlEngine::contextForObject(obj); if (!ctxt) ctxt = rootContext; QmlMetaProperty prop(obj, propName, ctxt); + if (prop.type() == QmlMetaProperty::Invalid) { QPair<const QMetaObject *, QString> key = qMakePair(obj->metaObject(), propName); bool isFunction = false; - if (functionCache()->contains(key)) { - isFunction = functionCache()->value(key); + if (functionCache.contains(key)) { + isFunction = functionCache.value(key); } else { QScriptValue sobj = scriptEngine.newQObject(obj); QScriptValue func = sobj.property(propName); isFunction = func.isFunction(); - functionCache()->insert(key, isFunction); + functionCache.insert(key, isFunction); } if (isFunction) { - *id = QmlScriptClass::FunctionId; + resolveData.object = obj; + resolveData.isFunction = true; rv |= QScriptClass::HandlesReadAccess; - } + } } else { - *id = QmlScriptClass::PropertyId; - *id |= prop.save(); + resolveData.object = obj; + resolveData.property = prop; rv |= QScriptClass::HandlesReadAccess; if (prop.isWritable()) @@ -247,25 +373,19 @@ QmlEnginePrivate::queryObject(const QString &propName, return rv; } -struct QmlValueTypeReference { - QmlValueType *type; - QGuard<QObject> object; - int property; -}; -Q_DECLARE_METATYPE(QmlValueTypeReference); - QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, QObject *obj, uint id) { - if (id == QmlScriptClass::FunctionId) { + Q_ASSERT(id == resolveData.safetyCheckId); + Q_ASSERT(resolveData.object); + + if (resolveData.isFunction) { + // ### Optimize QScriptValue sobj = scriptEngine.newQObject(obj); QScriptValue func = sobj.property(propName); return func; } else { - QmlMetaProperty prop; - prop.restore(id, obj); - if (!prop.isValid()) - return QScriptValue(); + const QmlMetaProperty &prop = resolveData.property; if (prop.needsChangedNotifier()) capturedProperties << CapturedProperty(prop); @@ -802,6 +922,111 @@ QScriptValue QmlEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine) return qScriptValueFromValue(engine, qVariantFromValue(QSizeF(w, h))); } +QScriptValue QmlEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine) +{ + if(ctxt->argumentCount() < 1) + return engine->nullValue(); + QVariant v = ctxt->argument(0).toVariant(); + QColor color; + if (v.type() == QVariant::Color) + color = v.value<QColor>(); + else if (v.type() == QVariant::String) { + bool ok; + color = QmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) + return engine->nullValue(); + } else + return engine->nullValue(); + color = color.lighter(); + return qScriptValueFromValue(engine, qVariantFromValue(color)); +} + +QScriptValue QmlEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine) +{ + if(ctxt->argumentCount() < 1) + return engine->nullValue(); + QVariant v = ctxt->argument(0).toVariant(); + QColor color; + if (v.type() == QVariant::Color) + color = v.value<QColor>(); + else if (v.type() == QVariant::String) { + bool ok; + color = QmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) + return engine->nullValue(); + } else + return engine->nullValue(); + color = color.darker(); + return qScriptValueFromValue(engine, qVariantFromValue(color)); +} + +/*! + This function allows tinting one color with another. + + The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque. + + \qml + Rectangle { x: 0; width: 80; height: 80; color: "lightsteelblue" } + Rectangle { x: 100; width: 80; height: 80; color: Qt.tint("lightsteelblue", "#10FF0000") } + \endqml + \image declarative-rect_tint.png + + Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color. +*/ +QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) +{ + if(ctxt->argumentCount() < 2) + return engine->nullValue(); + //get color + QVariant v = ctxt->argument(0).toVariant(); + QColor color; + if (v.type() == QVariant::Color) + color = v.value<QColor>(); + else if (v.type() == QVariant::String) { + bool ok; + color = QmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) + return engine->nullValue(); + } else + return engine->nullValue(); + + //get tint color + v = ctxt->argument(1).toVariant(); + QColor tintColor; + if (v.type() == QVariant::Color) + tintColor = v.value<QColor>(); + else if (v.type() == QVariant::String) { + bool ok; + tintColor = QmlStringConverters::colorFromString(v.toString(), &ok); + if (!ok) + return engine->nullValue(); + } else + return engine->nullValue(); + + //tint + QColor finalColor; + int a = tintColor.alpha(); + if (a == 0xFF) + finalColor = tintColor; + else if (a == 0x00) + finalColor = color; + else { + uint src = tintColor.rgba(); + uint dest = color.rgba(); + + uint res = (((a * (src & 0xFF00FF)) + + ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF; + res |= (((a * ((src >> 8) & 0xFF00FF)) + + ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00; + if ((src & 0xFF000000) == 0xFF000000) + res |= 0xFF000000; + + finalColor = QColor::fromRgba(res); + } + + return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); +} + QmlScriptClass::QmlScriptClass(QmlEngine *bindengine) : QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)), engine(bindengine) @@ -856,23 +1081,11 @@ QmlContextScriptClass::queryProperty(const QScriptValue &object, Q_UNUSED(flags); QmlContext *bindContext = static_cast<QmlContext*>(object.data().toQObject()); - QueryFlags rv = 0; QString propName = name.toString(); - *id = InvalidId; - if (bindContext->d_func()->propertyNames.contains(propName)) { - rv |= HandlesReadAccess; - *id = VariantPropertyId; - } - - for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) { - rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, bindContext->d_func()->defaultObjects.at(ii)); - if (rv) - *id |= (ii << 24); - } - - return rv; + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + return ep->queryContext(propName, id, bindContext); } QScriptValue QmlContextScriptClass::property(const QScriptValue &object, @@ -882,46 +1095,8 @@ QScriptValue QmlContextScriptClass::property(const QScriptValue &object, QmlContext *bindContext = static_cast<QmlContext*>(object.data().toQObject()); - uint basicId = id & QmlScriptClass::ClassIdMask; - - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - - switch (basicId) { - case VariantPropertyId: - { - QmlContextPrivate *contextPrivate = bindContext->d_func(); - QString propName = name.toString(); - int index = contextPrivate->propertyNames.value(propName); - - QScriptValue rv; - if (index < contextPrivate->idValueCount) { - rv = scriptEngine->newObject(ep->objectClass, scriptEngine->newVariant(QVariant::fromValue(contextPrivate->idValues[index].data()))); - } else { - QVariant value = contextPrivate->propertyValues.at(index); - if (QmlMetaType::isObject(value.userType())) { - rv = scriptEngine->newObject(ep->objectClass, scriptEngine->newVariant(value)); - } else { - rv = scriptEngine->newVariant(value); - } - } - ep->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + bindContext->d_func()->notifyIndex); - return rv; - } - default: - { - int objId = (id & ClassIdSelectorMask) >> 24; - QObject *obj = bindContext->d_func()->defaultObjects.at(objId); - QScriptValue rv = ep->propertyObject(name, obj, - id & ~QmlScriptClass::ClassIdSelectorMask); - if (rv.isValid()) { - return rv; - } - break; - } - } - - return QScriptValue(); + return ep->propertyContext(name, bindContext, id); } void QmlContextScriptClass::setProperty(QScriptValue &object, @@ -931,17 +1106,82 @@ void QmlContextScriptClass::setProperty(QScriptValue &object, { Q_UNUSED(name); - QmlContext *bindContext = - static_cast<QmlContext*>(object.data().toQObject()); + QmlEnginePrivate::get(engine)->setPropertyContext(value, id); +} - int objIdx = (id & QmlScriptClass::ClassIdSelectorMask) >> 24; - QObject *obj = bindContext->d_func()->defaultObjects.at(objIdx); +///////////////////////////////////////////////////////////// +QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine) +: QmlScriptClass(engine), object(0), type(0) +{ +} - QmlMetaProperty prop; - prop.restore(id, obj); +QmlTypeNameScriptClass::~QmlTypeNameScriptClass() +{ +} - QVariant v = QmlScriptClass::toVariant(engine, value); - prop.write(v); +QmlTypeNameScriptClass::QueryFlags +QmlTypeNameScriptClass::queryProperty(const QScriptValue &scriptObject, + const QScriptString &name, + QueryFlags flags, uint *id) +{ + QmlTypeNameBridge bridge = + qvariant_cast<QmlTypeNameBridge>(scriptObject.data().toVariant()); + + object = 0; + type = 0; + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + if (bridge.ns) { + QmlType *type = 0; + ep->resolveTypeInNamespace(bridge.ns, name.toString().toUtf8(), + &type, 0, 0, 0); + if (type) { + object = bridge.object; + this->type = type; + return HandlesReadAccess; + } else { + return 0; + } + + } else { + Q_ASSERT(bridge.type); + QString strName = name.toString(); + if (strName.at(0).isUpper()) { + // Must be an enum + // ### Optimize + const char *enumName = strName.toUtf8().constData(); + const QMetaObject *metaObject = bridge.type->baseMetaObject(); + for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + int value = e.keyToValue(enumName); + if (value != -1) { + enumValue = value; + return HandlesReadAccess; + } + } + return 0; + } else { + // Must be an attached property + this->object = qmlAttachedPropertiesObjectById(bridge.type->index(), bridge.object); + Q_ASSERT(this->object); + return ep->queryObject(strName, id, this->object); + } + } +} + +QScriptValue QmlTypeNameScriptClass::property(const QScriptValue &, + const QScriptString &propName, + uint id) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + if (type) { + QmlTypeNameBridge tnb = { object, type, 0 }; + return ep->scriptEngine.newObject(ep->typeNameClass, ep->scriptEngine.newVariant(qVariantFromValue(tnb))); + } else if (object) { + return ep->propertyObject(propName, object, id); + } else { + return QScriptValue(enumValue); + } } ///////////////////////////////////////////////////////////// @@ -1119,14 +1359,8 @@ void QmlObjectScriptClass::setProperty(QScriptValue &object, const QScriptValue &value) { Q_UNUSED(name); - - QObject *obj = object.data().toQObject(); - - QmlMetaProperty prop; - prop.restore(id, obj); - - QVariant v = QmlScriptClass::toVariant(engine, value); - prop.write(v); + Q_UNUSED(object); + QmlEnginePrivate::get(engine)->setPropertyObject(value, id); } diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index b595e7c..f492ccb 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -82,6 +82,7 @@ class QmlExpression; class QmlBasicScriptNodeCache; class QmlContextScriptClass; class QmlObjectScriptClass; +class QmlTypeNameScriptClass; class QmlValueTypeScriptClass; class QScriptEngineDebugger; class QNetworkReply; @@ -97,10 +98,17 @@ public: void init(); + QScriptClass::QueryFlags queryContext(const QString &name, uint *id, + QmlContext *); + QScriptValue propertyContext(const QScriptString &propName, QmlContext *, + uint id); + void setPropertyContext(const QScriptValue &, uint id); QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *); QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0); + void setPropertyObject(const QScriptValue &, uint id); + struct CapturedProperty { CapturedProperty(QObject *o, int c, int n) @@ -120,9 +128,30 @@ public: QScriptEngineDebugger *debugger; #endif + struct ImportedNamespace; + struct ResolveData { + ResolveData() : safetyCheckId(0) {} + int safetyCheckId; + + void clear() { + object = 0; context = 0; + type = 0; ns = 0; + contextIndex = -1; isFunction = false; + } + QObject *object; + QmlContext *context; + + QmlType *type; + QmlEnginePrivate::ImportedNamespace *ns; + + int contextIndex; + bool isFunction; + QmlMetaProperty property; + } resolveData; QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; + QmlTypeNameScriptClass *typeNameClass; // Used by DOM Core 3 API QScriptClass *nodeListClass; QScriptClass *namedNodeMapClass; @@ -178,6 +207,9 @@ public: } QmlValueTypeFactory valueTypes; + // ### Fixme + typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache; + FunctionCache functionCache; QHash<const QMetaObject *, QmlMetaObjectCache> propertyCache; static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) { if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0; @@ -198,7 +230,6 @@ public: QmlImportsPrivate *d; }; - struct ImportedNamespace; bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const; bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, @@ -219,6 +250,10 @@ public: static QScriptValue size(QScriptContext*, QScriptEngine*); static QScriptValue rect(QScriptContext*, QScriptEngine*); + static QScriptValue lighter(QScriptContext*, QScriptEngine*); + static QScriptValue darker(QScriptContext*, QScriptEngine*); + static QScriptValue tint(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(); } @@ -288,6 +323,25 @@ public: const QScriptValue &value); }; +class QmlTypeNameScriptClass : public QmlScriptClass +{ +public: + QmlTypeNameScriptClass(QmlEngine *); + ~QmlTypeNameScriptClass(); + + virtual QueryFlags queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id); + virtual QScriptValue property(const QScriptValue &object, + const QScriptString &name, + uint id); + +private: + QObject *object; + QmlType *type; + quint32 enumValue; +}; + class QmlValueTypeScriptClass : public QmlScriptClass { public: diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 0e78cad..321fe74 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -181,9 +181,16 @@ void QmlEngineDebugServer::buildObjectList(QDataStream &message, QmlEngineDebugServer::QmlObjectData QmlEngineDebugServer::objectData(QObject *object) { + QmlDeclarativeData *ddata = QmlDeclarativeData::get(object); QmlObjectData rv; - rv.lineNumber = -1; - rv.columnNumber = -1; + if (ddata) { + rv.url = ddata->outerContext->baseUrl(); + rv.lineNumber = ddata->lineNumber; + rv.columnNumber = ddata->columnNumber; + } else { + rv.lineNumber = -1; + rv.columnNumber = -1; + } rv.objectName = object->objectName(); rv.objectType = object->metaObject()->className(); diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index 65a4298..e47b4ab 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "qmlinfo.h" +#include <private/qmldeclarativedata_p.h> +#include <QtDeclarative/qmlcontext.h> QT_BEGIN_NAMESPACE @@ -80,7 +82,19 @@ QmlInfo::QmlInfo(QObject *object) *this << "QML"; if (object) *this << object->metaObject()->className(); - *this << "(unknown location):"; + QmlDeclarativeData *ddata = QmlDeclarativeData::get(object); + if (ddata) { + QString location = QLatin1String("("); + location += ddata->outerContext->baseUrl().toString(); + location += QLatin1String(":"); + location += QString::number(ddata->lineNumber); + location += QLatin1String(":"); + location += QString::number(ddata->columnNumber); + location += QLatin1String(")"); + *this << location.toLatin1().constData(); + } else { + *this << "(unknown location):"; + } } /*! diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 8861609a..3c6af1b 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -170,6 +170,7 @@ public: struct { int type; int data; + ushort column; } create; struct { int data; @@ -283,6 +284,7 @@ public: } assignSignalObject; struct { int count; + ushort column; int endLine; int metaObject; } createComponent; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 930e6e4..4d133e3 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -174,6 +174,12 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData VME_EXCEPTION("Unable to create object of type" << types.at(instr.create.type).className); } + QmlDeclarativeData *ddata = QmlDeclarativeData::get(o); + Q_ASSERT(ddata); + ddata->outerContext = ctxt; + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.create.column; + if (instr.create.data != -1) { QmlCustomParser *customParser = types.at(instr.create.type).type->customParser(); @@ -216,6 +222,14 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::CreateComponent: { QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top()); + + QmlEngine::setContextForObject(qcomp, ctxt); + QmlDeclarativeData *ddata = QmlDeclarativeData::get(qcomp); + Q_ASSERT(ddata); + ddata->outerContext = ctxt; + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.create.column; + stack.push(qcomp); ii += instr.createComponent.count; } diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h index a898be8..7104f60 100644 --- a/src/declarative/util/qmlanimation.h +++ b/src/declarative/util/qmlanimation.h @@ -58,7 +58,7 @@ QT_MODULE(Declarative) class QmlAbstractAnimationPrivate; class QmlAnimationGroup; -class QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, public QmlParserStatus +class Q_AUTOTEST_EXPORT QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, public QmlParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QmlAbstractAnimation) @@ -68,8 +68,6 @@ class QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, publ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged()) Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged) - //Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) - //Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged) Q_CLASSINFO("DefaultMethod", "start()") Q_INTERFACES(QmlParserStatus) @@ -252,7 +250,7 @@ protected: }; class QmlPropertyAnimationPrivate; -class QmlPropertyAnimation : public QmlAbstractAnimation +class Q_AUTOTEST_EXPORT QmlPropertyAnimation : public QmlAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QmlPropertyAnimation) @@ -304,7 +302,7 @@ Q_SIGNALS: void propertiesChanged(const QString &); }; -class QmlColorAnimation : public QmlPropertyAnimation +class Q_AUTOTEST_EXPORT QmlColorAnimation : public QmlPropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QmlPropertyAnimation) @@ -322,7 +320,7 @@ public: void setTo(const QColor &); }; -class QmlNumberAnimation : public QmlPropertyAnimation +class Q_AUTOTEST_EXPORT QmlNumberAnimation : public QmlPropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QmlPropertyAnimation) |