diff options
author | Paul Olav Tvete <paul.tvete@nokia.com> | 2010-10-22 09:05:17 (GMT) |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@nokia.com> | 2010-10-22 09:05:17 (GMT) |
commit | 26139fcacc05b4a74fce1ef4e0db819118765310 (patch) | |
tree | 75ce453868e95faa72b8f3b871c58969bbeb2a7e /src/declarative/qml | |
parent | 9a216c3f7abeacae8b9e9f78e50ddfcfbb5e2fa3 (diff) | |
parent | b8238ec7e41d483a9166eb7aebbf911f36976cdc (diff) | |
download | Qt-26139fcacc05b4a74fce1ef4e0db819118765310.zip Qt-26139fcacc05b4a74fce1ef4e0db819118765310.tar.gz Qt-26139fcacc05b4a74fce1ef4e0db819118765310.tar.bz2 |
Merge remote branch 'qt/master' into lighthouse-master
Conflicts:
src/gui/kernel/qapplication_win.cpp
src/gui/kernel/qwidget.cpp
src/gui/text/qfontengine_ft.cpp
Diffstat (limited to 'src/declarative/qml')
24 files changed, 360 insertions, 334 deletions
diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 8769122..6af3e05 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -103,7 +103,7 @@ QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMeth if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); QDeclarative_setParent_noEvent(this, parent); - QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); } QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val, @@ -117,7 +117,7 @@ QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, cons if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); QDeclarative_setParent_noEvent(this, parent); - QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); m_expression = new QDeclarativeExpression(ctxt, scope, val); } diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 90d38b3..74bc5bd 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -945,7 +945,8 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) propertyCache = enginePrivate->cache(obj->metaObject()->superClass())->copy(); propertyCache->append(engine, obj->metaObject(), QDeclarativePropertyCache::Data::NoFlags, - QDeclarativePropertyCache::Data::IsVMEFunction); + QDeclarativePropertyCache::Data::IsVMEFunction, + QDeclarativePropertyCache::Data::IsVMESignal); if (obj == unitRoot) { propertyCache->addref(); @@ -1098,7 +1099,8 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativePropertyCache *propertyCache = enginePrivate->cache(prop->value->metaObject()->superClass())->copy(); propertyCache->append(engine, prop->value->metaObject(), QDeclarativePropertyCache::Data::NoFlags, - QDeclarativePropertyCache::Data::IsVMEFunction); + QDeclarativePropertyCache::Data::IsVMEFunction, + QDeclarativePropertyCache::Data::IsVMESignal); output->propertyCaches << propertyCache; output->bytecode << meta; @@ -1930,6 +1932,9 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property { obj->addValueProperty(prop); + if (prop->values.count() > 1) + COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign multiple values to a singular property") ); + for (int ii = 0; ii < prop->values.count(); ++ii) { Value *v = prop->values.at(ii); if (v->object) { @@ -2560,8 +2565,8 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, QStringList alias = astNodeToStringList(node); - if (alias.count() != 1 && alias.count() != 2) - COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id> or <id>.<property>")); + if (alias.count() < 1 || alias.count() > 3) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>")); if (!compileState.ids.contains(alias.at(0))) COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0))); @@ -2573,11 +2578,14 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, int propIdx = -1; int flags = 0; bool writable = false; - if (alias.count() == 2) { + if (alias.count() == 2 || alias.count() == 3) { propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); - if (-1 == propIdx) + if (-1 == propIdx) { COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + } else if (propIdx > 0xFFFF) { + COMPILE_EXCEPTION(prop.defaultValue, tr("Alias property exceeds alias bounds")); + } QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); if (!aliasProperty.isScriptable()) @@ -2585,6 +2593,22 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, writable = aliasProperty.isWritable(); + if (alias.count() == 3) { + QDeclarativeValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()]; + if (!valueType) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + + propIdx |= ((unsigned int)aliasProperty.type()) << 24; + + int valueTypeIndex = valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData()); + if (valueTypeIndex == -1) + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + Q_ASSERT(valueTypeIndex <= 0xFF); + + aliasProperty = valueType->metaObject()->property(valueTypeIndex); + propIdx |= (valueTypeIndex << 16); + } + if (aliasProperty.isEnumType()) typeName = "int"; // Avoid introducing a dependency on the aliased metaobject else diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index b532b0c..cfef9cf 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -57,7 +57,6 @@ #include <QStack> #include <QStringList> -#include <QFileInfo> #include <QtCore/qdebug.h> #include <QApplication> diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index e916273..def4188 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -64,6 +64,7 @@ class QDeclarativeAbstractBinding; class QDeclarativeContext; class QDeclarativePropertyCache; class QDeclarativeContextData; +class QDeclarativeNotifier; // This class is structured in such a way, that simply zero'ing it is the // default state for elemental object allocations. This is crucial in the // workings of the QDeclarativeInstruction::CreateSimpleObject instruction. @@ -75,20 +76,23 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - attachedProperties(0), scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0) { + scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), extendedData(0) { init(); } static inline void init() { QAbstractDeclarativeData::destroyed = destroyed; QAbstractDeclarativeData::parentChanged = parentChanged; + QAbstractDeclarativeData::objectNameChanged = objectNameChanged; } static void destroyed(QAbstractDeclarativeData *, QObject *); static void parentChanged(QAbstractDeclarativeData *, QObject *, QObject *); + static void objectNameChanged(QAbstractDeclarativeData *, QObject *); void destroyed(QObject *); void parentChanged(QObject *, QObject *); + void objectNameChanged(QObject *); void setImplicitDestructible() { if (!explicitIndestructibleSet) indestructible = false; @@ -123,8 +127,6 @@ public: QDeclarativeCompiledData *deferredComponent; // Can't this be found from the context? unsigned int deferredIdx; - QHash<int, QObject *> *attachedProperties; - // ### Can we make this QScriptValuePrivate so we incur no additional allocation // cost? QScriptValue *scriptValue; @@ -147,6 +149,18 @@ public: return 0; } } + + QDeclarativeNotifier *objectNameNotifier() const; + QHash<int, QObject *> *attachedProperties() const; + + struct ExtendedData { + ExtendedData(); + ~ExtendedData(); + + QHash<int, QObject *> attachedProperties; + void *objectNameNotifier; + }; + mutable ExtendedData *extendedData; }; template<class T> diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index cffded3..c391568 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -68,6 +68,7 @@ #include "private/qdeclarativelist_p.h" #include "private/qdeclarativetypenamecache_p.h" #include "private/qdeclarativeinclude_p.h" +#include "private/qdeclarativenotifier_p.h" #include <QtCore/qmetaobject.h> #include <QScriptClass> @@ -104,6 +105,7 @@ #ifdef Q_OS_WIN // for %APPDATA% #include <qt_windows.h> #include <qlibrary.h> +#include <windows.h> #define CSIDL_APPDATA 0x001a // <username>\Application Data #endif @@ -207,7 +209,7 @@ For example: import QtQuick 1.0 Text { - color: Qt.rgba(255, 0, 0, 1) + color: Qt.rgba(1, 0, 0, 1) text: Qt.md5("hello, world") } \endqml @@ -284,9 +286,11 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url) { if (p) { - QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(this)->getContext(context); - Q_ASSERT(ctxt); - return ctxt->resolvedUrl(url); + QDeclarativeContextData *ctxt = p->getContext(context); + if (ctxt) + return ctxt->resolvedUrl(url); + else + return p->getUrl(context).resolved(url); } return baseUrl.resolved(url); } @@ -466,6 +470,11 @@ void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QO static_cast<QDeclarativeData *>(d)->parentChanged(o, p); } +void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o) +{ + static_cast<QDeclarativeData *>(d)->objectNameChanged(o); +} + void QDeclarativeEnginePrivate::init() { Q_Q(QDeclarativeEngine); @@ -947,7 +956,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre if (!data) return 0; // Attached properties are only on objects created by QML - QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0; + QObject *rv = data->extendedData?data->attachedProperties()->value(id):0; if (rv || !create) return rv; @@ -957,11 +966,8 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre rv = pf(const_cast<QObject *>(object)); - if (rv) { - if (!data->attachedProperties) - data->attachedProperties = new QHash<int, QObject *>(); - data->attachedProperties->insert(id, rv); - } + if (rv) + data->attachedProperties()->insert(id, rv); return rv; } @@ -982,8 +988,6 @@ void QDeclarativeData::destroyed(QObject *object) { if (deferredComponent) deferredComponent->release(); - if (attachedProperties) - delete attachedProperties; if (nextContextObject) nextContextObject->prevContextObject = prevContextObject; @@ -1017,6 +1021,9 @@ void QDeclarativeData::destroyed(QObject *object) if (scriptValue) delete scriptValue; + if (extendedData) + delete extendedData; + if (ownMemory) delete this; } @@ -1026,6 +1033,11 @@ void QDeclarativeData::parentChanged(QObject *, QObject *parent) if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; } } +void QDeclarativeData::objectNameChanged(QObject *) +{ + if (extendedData) objectNameNotifier()->notify(); +} + bool QDeclarativeData::hasBindingBit(int bit) const { if (bindingBitsSize > bit) @@ -1062,6 +1074,28 @@ void QDeclarativeData::setBindingBit(QObject *obj, int bit) bindingBits[bit / 32] |= (1 << (bit % 32)); } +QDeclarativeData::ExtendedData::ExtendedData() +: objectNameNotifier(0) +{ +} + +QDeclarativeData::ExtendedData::~ExtendedData() +{ + ((QDeclarativeNotifier *)&objectNameNotifier)->~QDeclarativeNotifier(); +} + +QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const +{ + if (!extendedData) extendedData = new ExtendedData; + return (QDeclarativeNotifier *)&extendedData->objectNameNotifier; +} + +QHash<int, QObject *> *QDeclarativeData::attachedProperties() const +{ + if (!extendedData) extendedData = new ExtendedData; + return &extendedData->attachedProperties; +} + /*! Creates a QScriptValue allowing you to use \a object in QML script. \a engine is the QDeclarativeEngine it is to be created in. @@ -1146,12 +1180,8 @@ QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QS QString arg = ctxt->argument(0).toString(); if (arg.isEmpty()) return engine->nullValue(); - QUrl url; + QUrl url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt, QUrl(arg)); QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt); - if (context) - url = QUrl(context->resolvedUrl(QUrl(arg))); - else - url = activeEnginePriv->getUrl(ctxt).resolved(QUrl(arg)); QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine); QDeclarativeComponentPrivate::get(c)->creationContext = context; QDeclarativeData::get(c, true)->setImplicitDestructible(); @@ -1635,7 +1665,7 @@ QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QSc return QScriptValue(e, false); bool ret = false; #ifndef QT_NO_DESKTOPSERVICES - ret = QDesktopServices::openUrl(QUrl(ctxt->argument(0).toString())); + ret = QDesktopServices::openUrl(QDeclarativeScriptEngine::get(e)->resolvedUrl(ctxt, QUrl(ctxt->argument(0).toString()))); #endif return QScriptValue(e, ret); } @@ -2161,4 +2191,42 @@ const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const } } +bool QDeclarative_isFileCaseCorrect(const QString &fileName) +{ +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) + QFileInfo info(fileName); + + QString absolute = info.absoluteFilePath(); + +#if defined(Q_OS_MAC) + QString canonical = info.canonicalFilePath(); +#elif defined(Q_OS_WIN32) + wchar_t buffer[1024]; + + DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024); + if (rv == 0 || rv >= 1024) return true; + rv = ::GetLongPathName(buffer, buffer, 1024); + if (rv == 0 || rv >= 1024) return true; + + QString canonical((QChar *)buffer); +#endif + + int absoluteLength = absolute.length(); + int canonicalLength = canonical.length(); + + int length = qMin(absoluteLength, canonicalLength); + for (int ii = 0; ii < length; ++ii) { + const QChar &a = absolute.at(absoluteLength - 1 - ii); + const QChar &c = canonical.at(canonicalLength - 1 - ii); + + if (a.toLower() != c.toLower()) + return true; + if (a != c) + return false; + } +#endif + + return true; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativefastproperties.cpp b/src/declarative/qml/qdeclarativefastproperties.cpp index eb69b6a..78e3afd 100644 --- a/src/declarative/qml/qdeclarativefastproperties.cpp +++ b/src/declarative/qml/qdeclarativefastproperties.cpp @@ -51,10 +51,19 @@ QT_BEGIN_NAMESPACE // primarily read from bindings is a candidate for inclusion as a fast // property. +static void QObject_objectName(QObject *object, void *output, QDeclarativeNotifierEndpoint *endpoint) +{ + if (endpoint) + endpoint->connect(QDeclarativeData::get(object, true)->objectNameNotifier()); + *((QString *)output) = object->objectName(); +} + QDeclarativeFastProperties::QDeclarativeFastProperties() { add(&QDeclarativeItem::staticMetaObject, QDeclarativeItem::staticMetaObject.indexOfProperty("parent"), QDeclarativeItemPrivate::parentProperty); + add(&QObject::staticMetaObject, QObject::staticMetaObject.indexOfProperty("objectName"), + QObject_objectName); } int QDeclarativeFastProperties::accessorIndexForProperty(const QMetaObject *metaObject, int propertyIndex) diff --git a/src/declarative/qml/qdeclarativeglobal_p.h b/src/declarative/qml/qdeclarativeglobal_p.h index 1041992..65d9b24 100644 --- a/src/declarative/qml/qdeclarativeglobal_p.h +++ b/src/declarative/qml/qdeclarativeglobal_p.h @@ -75,6 +75,19 @@ struct QDeclarativeGraphics_DerivedObject : public QObject }; /*! + Returns true if the case of \a fileName is equivalent to the file case of + \a fileName on disk, and false otherwise. + + This is used to ensure that the behavior of QML on a case-insensitive file + system is the same as on a case-sensitive file system. This function + performs a "best effort" attempt to determine the real case of the file. + It may have false positives (say the case is correct when it isn't), but it + should never have a false negative (say the case is incorrect when it is + correct). +*/ +bool QDeclarative_isFileCaseCorrect(const QString &fileName); + +/*! Makes the \a object a child of \a parent. Note that when using this method, neither \a parent nor the object's previous parent (if it had one) will receive ChildRemoved or ChildAdded events. diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index fe4ed48..6f5216a 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -351,7 +351,11 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath { QFile file(absoluteFilePath); QString filecontent; - if (file.open(QFile::ReadOnly)) { + if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { + if (errorString) + *errorString = QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath); + return false; + } else if (file.open(QFile::ReadOnly)) { filecontent = QString::fromUtf8(file.readAll()); if (qmlImportTrace()) qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: " @@ -913,6 +917,11 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt } if (!engineInitialized || !typesRegistered) { + if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { + if (errorString) + *errorString = tr("File name case mismatch for \"%2\"").arg(absoluteFilePath); + return false; + } QPluginLoader loader(absoluteFilePath); if (!loader.load()) { diff --git a/src/declarative/qml/qdeclarativenotifier.cpp b/src/declarative/qml/qdeclarativenotifier.cpp index 8c946f8..2e3f756 100644 --- a/src/declarative/qml/qdeclarativenotifier.cpp +++ b/src/declarative/qml/qdeclarativenotifier.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "private/qdeclarativenotifier_p.h" +#include "private/qdeclarativeproperty_p.h" QT_BEGIN_NAMESPACE @@ -66,6 +67,21 @@ void QDeclarativeNotifier::emitNotify(QDeclarativeNotifierEndpoint *endpoint) if (oldDisconnected) *oldDisconnected = endpoint; } +void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal) +{ + Signal *s = toSignal(); + + if (s->source == source && s->sourceSignal == sourceSignal) + return; + + disconnect(); + + QDeclarativePropertyPrivate::connect(source, sourceSignal, target, targetMethod); + + s->source = source; + s->sourceSignal = sourceSignal; +} + void QDeclarativeNotifierEndpoint::copyAndClear(QDeclarativeNotifierEndpoint &other) { other.disconnect(); diff --git a/src/declarative/qml/qdeclarativenotifier_p.h b/src/declarative/qml/qdeclarativenotifier_p.h index 0781caf..ad04ba8 100644 --- a/src/declarative/qml/qdeclarativenotifier_p.h +++ b/src/declarative/qml/qdeclarativenotifier_p.h @@ -75,7 +75,7 @@ public: inline bool isConnected(QObject *source, int sourceSignal); inline bool isConnected(QDeclarativeNotifier *); - inline void connect(QObject *source, int sourceSignal); + void connect(QObject *source, int sourceSignal); inline void connect(QDeclarativeNotifier *); inline void disconnect(); @@ -175,21 +175,6 @@ bool QDeclarativeNotifierEndpoint::isConnected(QDeclarativeNotifier *notifier) return NotifierType == type && asNotifier()->notifier == notifier; } -void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal) -{ - Signal *s = toSignal(); - - if (s->source == source && s->sourceSignal == sourceSignal) - return; - - disconnect(); - - QMetaObject::connect(source, sourceSignal, target, targetMethod); - - s->source = source; - s->sourceSignal = sourceSignal; -} - void QDeclarativeNotifierEndpoint::connect(QDeclarativeNotifier *notifier) { Notifier *n = toNotifier(); diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index ab6ff74..61a1f55 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -239,8 +239,13 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) } } else { if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) { - enginePriv->capturedProperties << - QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + if (lastData->coreIndex == 0) { + enginePriv->capturedProperties << + QDeclarativeEnginePrivate::CapturedProperty(QDeclarativeData::get(obj, true)->objectNameNotifier()); + } else { + enginePriv->capturedProperties << + QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + } } if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) { diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index bc20bff..b5fb619 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -53,6 +53,7 @@ #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativelist_p.h" #include "private/qdeclarativecompiler_p.h" +#include "private/qdeclarativevmemetaobject_p.h" #include <QStringList> #include <QtCore/qdebug.h> @@ -1212,7 +1213,7 @@ bool QDeclarativeProperty::connectNotifySignal(QObject *dest, int method) const QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex); if (prop.hasNotifySignal()) { - return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection); + return QDeclarativePropertyPrivate::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection); } else { return false; } @@ -1383,4 +1384,57 @@ QMetaMethod QDeclarativePropertyPrivate::findSignalByName(const QMetaObject *mo, return QMetaMethod(); } +static inline int QMetaObject_methods(const QMetaObject *metaObject) +{ + struct Private + { + int revision; + int className; + int classInfoCount, classInfoData; + int methodCount, methodData; + }; + + return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount; +} + +static inline void flush_vme_signal(const QObject *object, int index) +{ + QDeclarativeData *data = static_cast<QDeclarativeData *>(QObjectPrivate::get(const_cast<QObject *>(object))->declarativeData); + if (data && data->propertyCache) { + QDeclarativePropertyCache::Data *property = data->propertyCache->method(index); + + if (property && property->flags & QDeclarativePropertyCache::Data::IsVMESignal) { + const QMetaObject *metaObject = object->metaObject(); + int methodOffset = metaObject->methodOffset(); + + while (methodOffset > index) { + methodOffset -= QMetaObject_methods(metaObject); + metaObject = metaObject->d.superdata; + } + + QDeclarativeVMEMetaObject *vme = + static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(metaObject)); + + vme->connectAliasSignal(index); + } + } +} + +/*! +Connect \a sender \a signal_index to \a receiver \a method_index with the specified +\a type and \a types. This behaves identically to QMetaObject::connect() except that +it connects any lazy "proxy" signal connections set up by QML. + +It is possible that this logic should be moved to QMetaObject::connect(). +*/ +bool QDeclarativePropertyPrivate::connect(const QObject *sender, int signal_index, + const QObject *receiver, int method_index, + int type, int *types) +{ + flush_vme_signal(sender, signal_index); + flush_vme_signal(receiver, method_index); + + return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index 8522561..a8438c8 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -133,6 +133,9 @@ public: static int valueTypeCoreIndex(const QDeclarativeProperty &that); static int bindingIndex(const QDeclarativeProperty &that); static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &); + static bool connect(const QObject *sender, int signal_index, + const QObject *receiver, int method_index, + int type = 0, int *types = 0); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyPrivate::WriteFlags) diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 08503c2..9e1ceb8 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -94,6 +94,8 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) { coreIndex = m.methodIndex(); flags |= Data::IsFunction; + if (m.methodType() == QMetaMethod::Signal) + flags |= Data::IsSignal; propType = QVariant::Invalid; const char *returnType = m.typeName(); @@ -215,7 +217,7 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const } void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, - Data::Flag propertyFlags, Data::Flag methodFlags) + Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); @@ -251,6 +253,8 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb int methodCount = metaObject->methodCount(); int methodOffset = qMax(2, metaObject->methodOffset()); // 2 to block the destroyed signal + + methodIndexCache.resize(methodCount); for (int ii = methodOffset; ii < methodCount; ++ii) { QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) @@ -272,6 +276,10 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb data->load(m); if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method) data->flags |= methodFlags; + else if (m.methodType() == QMetaMethod::Signal) + data->flags |= signalFlags; + + methodIndexCache[ii] = data; stringCache.insert(methodName, data); identifierCache.insert(data->identifier.identifier, data); @@ -350,6 +358,15 @@ QDeclarativePropertyCache::property(int index) const } QDeclarativePropertyCache::Data * +QDeclarativePropertyCache::method(int index) const +{ + if (index < 0 || index >= methodIndexCache.count()) + return 0; + + return methodIndexCache.at(index); +} + +QDeclarativePropertyCache::Data * QDeclarativePropertyCache::property(const QString &str) const { return stringCache.value(str); diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 72cfeba..79b126d 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -94,8 +94,9 @@ public: // Apply only to IsFunctions IsVMEFunction = 0x00000400, - HasArguments = 0x00000800 - + HasArguments = 0x00000800, + IsSignal = 0x00001000, + IsVMESignal = 0x00002000, }; Q_DECLARE_FLAGS(Flags, Flag) @@ -125,7 +126,7 @@ public: QDeclarativePropertyCache *copy() const; void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags, - Data::Flag methodFlags = Data::NoFlags); + Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags); static QDeclarativePropertyCache *create(QDeclarativeEngine *, const QMetaObject *); static Data create(const QMetaObject *, const QString &); @@ -133,6 +134,7 @@ public: inline Data *property(const QScriptDeclarativeClass::Identifier &id) const; Data *property(const QString &) const; Data *property(int) const; + Data *method(int) const; QStringList propertyNames() const; inline QDeclarativeEngine *qmlEngine() const; @@ -152,6 +154,7 @@ private: QDeclarativeEngine *engine; IndexCache indexCache; + IndexCache methodIndexCache; StringCache stringCache; IdentifierCache identifierCache; }; diff --git a/src/declarative/qml/qdeclarativeproxymetaobject.cpp b/src/declarative/qml/qdeclarativeproxymetaobject.cpp index c2dce0a..ceb6977 100644 --- a/src/declarative/qml/qdeclarativeproxymetaobject.cpp +++ b/src/declarative/qml/qdeclarativeproxymetaobject.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "private/qdeclarativeproxymetaobject_p.h" +#include "private/qdeclarativeproperty_p.h" QT_BEGIN_NAMESPACE @@ -95,8 +96,7 @@ int QDeclarativeProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a) QMetaMethod method = metaObject->method(jj + methodOffset); if (method.methodType() == QMetaMethod::Signal) - QMetaObject::connect(proxy, methodOffset + jj, - object, localOffset + jj); + QDeclarativePropertyPrivate::connect(proxy, methodOffset + jj, object, localOffset + jj); } } diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 061f309..c8e1a07 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -44,6 +44,7 @@ #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativecompiler_p.h> #include <private/qdeclarativecomponent_p.h> +#include <private/qdeclarativeglobal_p.h> #include <QtDeclarative/qdeclarativecomponent.h> #include <QtCore/qdebug.h> @@ -493,6 +494,13 @@ void QDeclarativeDataLoader::load(QDeclarativeDataBlob *blob) QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(blob->m_url); if (!lf.isEmpty()) { + if (!QDeclarative_isFileCaseCorrect(lf)) { + QDeclarativeError error; + error.setUrl(blob->m_url); + error.setDescription(QLatin1String("File name case mismatch")); + blob->setError(error); + return; + } QFile file(lf); if (file.open(QFile::ReadOnly)) { QByteArray data = file.readAll(); diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 4e41c22..360186c 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -608,7 +608,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature()))); - QMetaObject::connect(target, prop.index(), assign, method.methodIndex()); + QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex()); } else { VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr))); diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 3e32006..e28062b 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -459,7 +459,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) id -= propOffset; if (id < metaData->propertyCount) { - int t = (metaData->propertyData() + id)->propertyType; + int t = (metaData->propertyData() + id)->propertyType; bool needActivate = false; if (t == -1) { @@ -584,25 +584,28 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) if (!target) return -1; - if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { - int sigIdx = methodOffset + id + metaData->propertyCount; - QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); + connectAlias(id); - if (d->propertyIdx != -1) { - QMetaProperty prop = - target->metaObject()->property(d->propertyIdx); - if (prop.hasNotifySignal()) - QMetaObject::connect(target, prop.notifySignalIndex(), - object, sigIdx); - } - aConnected.setBit(id); - } - - if (d->propertyIdx == -1) { + if (d->isObjectAlias()) { *reinterpret_cast<QObject **>(a[0]) = target; return -1; + } else if (d->isValueTypeAlias()) { + // Value type property + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); + + QDeclarativeValueType *valueType = ep->valueTypes[d->valueType()]; + Q_ASSERT(valueType); + + valueType->read(target, d->propertyIndex()); + int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a); + + if (c == QMetaObject::WriteProperty) + valueType->write(target, d->propertyIndex(), 0x00); + + return rv; + } else { - return QMetaObject::metacall(target, c, d->propertyIdx, a); + return QMetaObject::metacall(target, c, d->propertyIndex(), a); } } @@ -818,4 +821,38 @@ void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v) return writeVarProperty(index - propOffset, v); } +void QDeclarativeVMEMetaObject::connectAlias(int aliasId) +{ + if (!aConnected.testBit(aliasId)) { + aConnected.setBit(aliasId); + + QDeclarativeContext *context = ctxt->asQDeclarativeContext(); + QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context); + + QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + aliasId; + + QObject *target = ctxtPriv->data->idValues[d->contextIdx].data(); + if (!target) + return; + + int sigIdx = methodOffset + aliasId + metaData->propertyCount; + QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); + + if (!d->isObjectAlias()) { + QMetaProperty prop = target->metaObject()->property(d->propertyIndex()); + if (prop.hasNotifySignal()) + QDeclarativePropertyPrivate::connect(target, prop.notifySignalIndex(), object, sigIdx); + } + } +} + +void QDeclarativeVMEMetaObject::connectAliasSignal(int index) +{ + int aliasId = (index - methodOffset) - metaData->propertyCount; + if (aliasId < 0 || aliasId >= metaData->aliasCount) + return; + + connectAlias(aliasId); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index 20ca80b..5134763 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -84,6 +84,25 @@ struct QDeclarativeVMEMetaData int contextIdx; int propertyIdx; int flags; + + bool isObjectAlias() const { + return propertyIdx == -1; + } + bool isPropertyAlias() const { + return !isObjectAlias() && !(propertyIdx & 0xFF000000); + } + bool isValueTypeAlias() const { + return !isObjectAlias() && (propertyIdx & 0xFF000000); + } + int propertyIndex() const { + return propertyIdx & 0x0000FFFF; + } + int valueTypeIndex() const { + return (propertyIdx & 0x00FF0000) >> 16; + } + int valueType() const { + return ((unsigned int)propertyIdx) >> 24; + } }; struct PropertyData { @@ -126,6 +145,7 @@ public: QScriptValue vmeProperty(int index); void setVMEProperty(int index, const QScriptValue &); + void connectAliasSignal(int index); protected: virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); @@ -140,6 +160,7 @@ private: QDeclarativeVMEVariant *data; + void connectAlias(int aliasId); QBitArray aConnected; QBitArray aInterceptors; QHash<int, QPair<int, QDeclarativePropertyValueInterceptor*> > interceptors; diff --git a/src/declarative/qml/qdeclarativewatcher.cpp b/src/declarative/qml/qdeclarativewatcher.cpp index da1419f..b9d5ec8 100644 --- a/src/declarative/qml/qdeclarativewatcher.cpp +++ b/src/declarative/qml/qdeclarativewatcher.cpp @@ -46,6 +46,7 @@ #include "qdeclarative.h" #include <qdeclarativedebugservice_p.h> +#include "private/qdeclarativeproperty_p.h" #include <QtCore/qmetaobject.h> #include <QtCore/qdebug.h> @@ -103,7 +104,7 @@ QDeclarativeWatchProxy::QDeclarativeWatchProxy(int id, refreshIdx = QDeclarativeWatchProxy::staticMetaObject.indexOfMethod("notifyValueChanged()"); if (prop.hasNotifySignal()) - QMetaObject::connect(m_object, prop.notifySignalIndex(), this, refreshIdx); + QDeclarativePropertyPrivate::connect(m_object, prop.notifySignalIndex(), this, refreshIdx); } void QDeclarativeWatchProxy::notifyValueChanged() diff --git a/src/declarative/qml/rewriter/rewriter.cpp b/src/declarative/qml/rewriter/rewriter.cpp deleted file mode 100644 index 6d2ccfb..0000000 --- a/src/declarative/qml/rewriter/rewriter.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/rewriter_p.h" - -#include <qdeclarativejsast_p.h> - -QT_QML_BEGIN_NAMESPACE - -using namespace QDeclarativeJS; - -void Rewriter::replace(const AST::SourceLocation &loc, const QString &text) -{ replace(loc.offset, loc.length, text); } - -void Rewriter::remove(const AST::SourceLocation &loc) -{ return replace(loc.offset, loc.length, QString()); } - -void Rewriter::remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc) -{ return replace(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, QString()); } - -void Rewriter::insertTextBefore(const AST::SourceLocation &loc, const QString &text) -{ replace(loc.offset, 0, text); } - -void Rewriter::insertTextAfter(const AST::SourceLocation &loc, const QString &text) -{ replace(loc.offset + loc.length, 0, text); } - -void Rewriter::replace(int offset, int length, const QString &text) -{ textWriter.replace(offset, length, text); } - -void Rewriter::insertText(int offset, const QString &text) -{ replace(offset, 0, text); } - -void Rewriter::removeText(int offset, int length) -{ replace(offset, length, QString()); } - -QString Rewriter::textAt(const AST::SourceLocation &loc) const -{ return _code.mid(loc.offset, loc.length); } - -QString Rewriter::textAt(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc) const -{ return _code.mid(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset); } - -void Rewriter::accept(QDeclarativeJS::AST::Node *node) -{ QDeclarativeJS::AST::Node::acceptChild(node, this); } - -void Rewriter::moveTextBefore(const AST::SourceLocation &firstLoc, - const AST::SourceLocation &lastLoc, - const AST::SourceLocation &loc) -{ - move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset); -} - -void Rewriter::moveTextAfter(const AST::SourceLocation &firstLoc, - const AST::SourceLocation &lastLoc, - const AST::SourceLocation &loc) -{ - move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset + loc.length); -} - -void Rewriter::move(int pos, int length, int to) -{ - textWriter.move(pos, length, to); -} - -QT_QML_END_NAMESPACE diff --git a/src/declarative/qml/rewriter/rewriter.pri b/src/declarative/qml/rewriter/rewriter.pri index 2c29061..a9fa1b5 100644 --- a/src/declarative/qml/rewriter/rewriter.pri +++ b/src/declarative/qml/rewriter/rewriter.pri @@ -2,8 +2,3 @@ INCLUDEPATH += $$PWD HEADERS += $$PWD/textwriter_p.h SOURCES += $$PWD/textwriter.cpp - -!no_ast_rewriter { - HEADERS += $$PWD/rewriter_p.h - SOURCES += $$PWD/rewriter.cpp -} diff --git a/src/declarative/qml/rewriter/rewriter_p.h b/src/declarative/qml/rewriter/rewriter_p.h deleted file mode 100644 index 4799469..0000000 --- a/src/declarative/qml/rewriter/rewriter_p.h +++ /dev/null @@ -1,153 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef REWRITER_H -#define REWRITER_H - -#include "private/textwriter_p.h" - -#include <qdeclarativejsastvisitor_p.h> - -#include <QtCore/QList> -#include <QtCore/QString> - -QT_BEGIN_HEADER -QT_QML_BEGIN_NAMESPACE - -namespace QDeclarativeJS { - -//////////////////////////////////////////////////////////////////////////////// -// Replacement -//////////////////////////////////////////////////////////////////////////////// -class Replacement -{ - int _offset; - int _length; - QString _text; - -public: - Replacement(int offset = 0, int length = 0, const QString &text = QString()) - : _offset(offset), _length(length), _text(text) - { } - - bool isNull() const { return _offset == _length; } - operator bool() const { return ! isNull(); } - - int offset() const { return _offset; } - int length() const { return _length; } - QString text() const { return _text; } -}; - - - -//////////////////////////////////////////////////////////////////////////////// -// Rewriter -//////////////////////////////////////////////////////////////////////////////// -class Rewriter: public AST::Visitor -{ -protected: - TextWriter textWriter; -public: - // - // Token based API - // - - /// Returns the text of the token at the given \a location. - QString textAt(const AST::SourceLocation &location) const; - - QString textAt(const AST::SourceLocation &firstLoc, - const AST::SourceLocation &lastLoc) const; - - /// Replace the token at \a loc with the given \a text. - void replace(const AST::SourceLocation &loc, const QString &text); - - /// Remove the token at the given \a location. - void remove(const AST::SourceLocation &location); - - /// Remove all tokens in the range [\a firstLoc, \a lastLoc]. - void remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc); - - /// Insert \a text before the token at the given \a location. - void insertTextBefore(const AST::SourceLocation &location, const QString &text); - - /// Insert \a text after the token at the given \a location. - void insertTextAfter(const AST::SourceLocation &loc, const QString &text); - - void moveTextBefore(const AST::SourceLocation &firstLoc, - const AST::SourceLocation &lastLoc, - const AST::SourceLocation &loc); - - void moveTextAfter(const AST::SourceLocation &firstLoc, - const AST::SourceLocation &lastLoc, - const AST::SourceLocation &loc); - - // - // low-level offset based API - // - virtual void replace(int offset, int length, const QString &text); - virtual void move(int pos, int length, int to); - void insertText(int offset, const QString &text); - void removeText(int offset, int length); - - /// Visit the given \a node. - void accept(AST::Node *node); - - /// Returns the original unchanged source code. - QString code() const { return _code; } - - /// Returns the list of replacements. - QList<Replacement> replacementList() const { return _replacementList; } - -protected: - /// \internal - void setCode(const QString &code) { _code = code; } - -private: - QString _code; - QList<Replacement> _replacementList; -}; - -} // end of namespace QDeclarativeJS - -QT_QML_END_NAMESPACE -QT_END_HEADER - -#endif // REWRITER_H |