diff options
Diffstat (limited to 'src/declarative/qml')
54 files changed, 2139 insertions, 1751 deletions
diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 34163a4..6404be3 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -56,9 +56,11 @@ #include <stdio.h> #include <string.h> -QT_QML_BEGIN_NAMESPACE - +QT_BEGIN_NAMESPACE extern double qstrtod(const char *s00, char const **se, bool *ok); +QT_END_NAMESPACE + +QT_QML_BEGIN_NAMESPACE #define shiftWindowsLineBreak() \ do { \ diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 77b7484..dfdef11 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -99,7 +99,7 @@ int qmlRegisterType() qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), - 0, + 0, 0, 0, 0, 0, 0, &T::staticMetaObject, @@ -131,7 +131,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), - QDeclarativePrivate::create<T>, + sizeof(T), QDeclarativePrivate::createInto<T>, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -163,7 +163,7 @@ int qmlRegisterExtendedType() qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), - 0, + 0, 0, 0, 0, 0, 0, &T::staticMetaObject, @@ -203,7 +203,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), - QDeclarativePrivate::create<T>, + sizeof(T), QDeclarativePrivate::createInto<T>, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -256,7 +256,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), - QDeclarativePrivate::create<T>, + sizeof(T), QDeclarativePrivate::createInto<T>, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -275,18 +275,6 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, return QDeclarativePrivate::registerType(type); } -#define QML_REGISTER_INTERFACE(INTERFACE) \ - qmlRegisterInterface<INTERFACE>(#INTERFACE) - -#define QML_REGISTER_EXTENDED_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, CLASS, EXTENSION) \ - qmlRegisterExtendedType<CLASS,EXTENSION>(#URI, VERSION_MAJ, VERSION_MIN, #NAME) - -#define QML_REGISTER_TYPE(URI,VMAJ,VMIN,NAME,CLASS) \ - qmlRegisterType<CLASS>(#URI, VMAJ, VMIN, #NAME) - -#define QML_REGISTER_NOCREATE_TYPE(CLASS) \ - qmlRegisterType<CLASS>() - class QDeclarativeContext; class QDeclarativeEngine; Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *); diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 88ca5cd..090bd5b 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -79,14 +79,25 @@ QDeclarativeBindingPrivate::QDeclarativeBindingPrivate() { } -QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, QObject *obj, QDeclarativeContext *ctxt, const QString &url, int lineNumber, QObject *parent) +QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, QObject *obj, + QDeclarativeContextData *ctxt, const QString &url, int lineNumber, + QObject *parent) : QDeclarativeExpression(ctxt, data, rc, obj, url, lineNumber, *new QDeclarativeBindingPrivate) { setParent(parent); setNotifyOnValueChanged(true); } -QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContext *ctxt, QObject *parent) +QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContext *ctxt, + QObject *parent) +: QDeclarativeExpression(QDeclarativeContextData::get(ctxt), str, obj, *new QDeclarativeBindingPrivate) +{ + setParent(parent); + setNotifyOnValueChanged(true); +} + +QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContextData *ctxt, + QObject *parent) : QDeclarativeExpression(ctxt, str, obj, *new QDeclarativeBindingPrivate) { setParent(parent); @@ -181,8 +192,8 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } if (data->error.isValid()) { - QDeclarativeEnginePrivate *p = (data->context() && data->context()->engine())? - QDeclarativeEnginePrivate::get(data->context()->engine()):0; + QDeclarativeEnginePrivate *p = (data->context() && data->context()->engine)? + QDeclarativeEnginePrivate::get(data->context()->engine):0; if (!data->addError(p)) qWarning().nospace() << qPrintable(this->error().toString()); } else { @@ -223,7 +234,7 @@ void QDeclarativeBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteF int QDeclarativeBinding::propertyIndex() { Q_D(QDeclarativeBinding); - return d->bindingData()->property.index(); + return QDeclarativePropertyPrivate::bindingIndex(d->bindingData()->property); } bool QDeclarativeBinding::enabled() const @@ -259,23 +270,57 @@ void QDeclarativeAbstractBinding::addToObject(QObject *object) { Q_ASSERT(object); + if (m_object == object) + return; + + int index = propertyIndex(); + removeFromObject(); Q_ASSERT(!m_prevBinding); - QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(object, true); - m_nextBinding = data->bindings; - if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; - m_prevBinding = &data->bindings; - data->bindings = this; m_object = object; + QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(object, true); + + if (index & 0xFF000000) { + // Value type + + int coreIndex = index & 0xFFFFFF; + + // Find the value type proxy (if there is one) + QDeclarativeValueTypeProxyBinding *proxy = 0; + if (data->hasBindingBit(coreIndex)) { + QDeclarativeAbstractBinding *b = data->bindings; + while (b && b->propertyIndex() != coreIndex) + b = b->m_nextBinding; + Q_ASSERT(b && b->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy); + proxy = static_cast<QDeclarativeValueTypeProxyBinding *>(b); + } + + if (!proxy) + proxy = new QDeclarativeValueTypeProxyBinding(object, coreIndex); + proxy->addToObject(object); + + m_nextBinding = proxy->m_bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &proxy->m_bindings; + proxy->m_bindings = this; - data->setBindingBit(m_object, propertyIndex()); + } else { + m_nextBinding = data->bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &data->bindings; + data->bindings = this; + + data->setBindingBit(m_object, index); + } } void QDeclarativeAbstractBinding::removeFromObject() { if (m_prevBinding) { + int index = propertyIndex(); + Q_ASSERT(m_object); *m_prevBinding = m_nextBinding; @@ -283,8 +328,14 @@ void QDeclarativeAbstractBinding::removeFromObject() m_prevBinding = 0; m_nextBinding = 0; - QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(m_object, false); - if (data) data->clearBindingBit(propertyIndex()); + if (index & 0xFF000000) { + // Value type - we don't remove the proxy from the object. It will sit their happily + // doing nothing for ever more. + } else { + QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(m_object, false); + if (data) data->clearBindingBit(index); + } + m_object = 0; } } @@ -305,4 +356,88 @@ void QDeclarativeAbstractBinding::setEnabled(bool e, QDeclarativePropertyPrivate if (e) m_mePtr = 0; } +QDeclarativeValueTypeProxyBinding::QDeclarativeValueTypeProxyBinding(QObject *o, int index) +: m_object(o), m_index(index), m_bindings(0) +{ +} + +QDeclarativeValueTypeProxyBinding::~QDeclarativeValueTypeProxyBinding() +{ + while (m_bindings) { + QDeclarativeAbstractBinding *binding = m_bindings; + binding->setEnabled(false, 0); + binding->destroy(); + } +} + +void QDeclarativeValueTypeProxyBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags) +{ + if (e) { + addToObject(m_object); + + QDeclarativeAbstractBinding *bindings = m_bindings; + m_bindings = 0; + recursiveEnable(bindings, flags); + } else { + removeFromObject(); + + QDeclarativeAbstractBinding *bindings = m_bindings; + m_bindings = 0; + recursiveDisable(bindings); + } +} + +void QDeclarativeValueTypeProxyBinding::recursiveEnable(QDeclarativeAbstractBinding *b, QDeclarativePropertyPrivate::WriteFlags flags) +{ + if (!b) + return; + + QDeclarativeAbstractBinding *next = b->m_nextBinding; + b->m_prevBinding = 0; + b->m_nextBinding = 0; + Q_ASSERT(b->m_mePtr == 0); + b->m_mePtr = &b; + + recursiveEnable(next, flags); + + if (b) + b->setEnabled(true, flags); +} + +void QDeclarativeValueTypeProxyBinding::recursiveDisable(QDeclarativeAbstractBinding *b) +{ + if (!b) + return; + + recursiveDisable(b->m_nextBinding); + + b->setEnabled(false, 0); + + Q_ASSERT(b->m_prevBinding == 0); + Q_ASSERT(b->m_nextBinding == 0); + b->m_nextBinding = m_bindings; + if (b->m_nextBinding) b->m_nextBinding->m_prevBinding = &b->m_nextBinding; + b->m_prevBinding = &m_bindings; + m_bindings = b; +} + +int QDeclarativeValueTypeProxyBinding::propertyIndex() +{ + return m_index; +} + +void QDeclarativeValueTypeProxyBinding::update(QDeclarativePropertyPrivate::WriteFlags) +{ +} + +QDeclarativeAbstractBinding *QDeclarativeValueTypeProxyBinding::binding(int propertyIndex) +{ + QDeclarativeAbstractBinding *binding = m_bindings; + + while (binding && binding->propertyIndex() != propertyIndex) + binding = binding->m_nextBinding; + + return binding; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 1a714f0..56f1715 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -68,12 +68,14 @@ class Q_DECLARATIVE_EXPORT QDeclarativeAbstractBinding { public: QDeclarativeAbstractBinding(); - virtual ~QDeclarativeAbstractBinding(); virtual void destroy(); virtual QString expression() const; + enum Type { PropertyBinding, ValueTypeProxy }; + virtual Type bindingType() const { return PropertyBinding; } + void setEnabled(bool e) { setEnabled(e, QDeclarativePropertyPrivate::DontRemoveBinding); } virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags) = 0; virtual int propertyIndex() = 0; @@ -85,11 +87,13 @@ public: void removeFromObject(); protected: + virtual ~QDeclarativeAbstractBinding(); void clear(); private: + friend class QDeclarativeDeclarativeData; - friend class QDeclarativeProperty; + friend class QDeclarativeValueTypeProxyBinding; friend class QDeclarativePropertyPrivate; friend class QDeclarativeVME; @@ -99,6 +103,32 @@ private: QDeclarativeAbstractBinding *m_nextBinding; }; +class QDeclarativeValueTypeProxyBinding : public QDeclarativeAbstractBinding +{ +public: + QDeclarativeValueTypeProxyBinding(QObject *o, int coreIndex); + + virtual Type bindingType() const { return ValueTypeProxy; } + + virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags); + virtual int propertyIndex(); + virtual void update(QDeclarativePropertyPrivate::WriteFlags); + + QDeclarativeAbstractBinding *binding(int propertyIndex); + +protected: + ~QDeclarativeValueTypeProxyBinding(); + +private: + void recursiveEnable(QDeclarativeAbstractBinding *, QDeclarativePropertyPrivate::WriteFlags); + void recursiveDisable(QDeclarativeAbstractBinding *); + + friend class QDeclarativeAbstractBinding; + QObject *m_object; + int m_index; + QDeclarativeAbstractBinding *m_bindings; +}; + class QDeclarativeContext; class QDeclarativeBindingPrivate; class Q_DECLARATIVE_EXPORT QDeclarativeBinding : public QDeclarativeExpression, public QDeclarativeAbstractBinding @@ -106,9 +136,9 @@ class Q_DECLARATIVE_EXPORT QDeclarativeBinding : public QDeclarativeExpression, Q_OBJECT public: QDeclarativeBinding(const QString &, QObject *, QDeclarativeContext *, QObject *parent=0); - QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContext *, const QString &, int, - QObject *parent); - ~QDeclarativeBinding(); + QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0); + QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContextData *, + const QString &, int, QObject *parent); void setTarget(const QDeclarativeProperty &); QDeclarativeProperty property() const; @@ -125,6 +155,7 @@ public Q_SLOTS: void update() { update(QDeclarativePropertyPrivate::DontRemoveBinding); } protected: + ~QDeclarativeBinding(); void emitValueChanged(); private: diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 17937fd..1acca2f 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -48,12 +48,17 @@ #include <private/qdeclarativejsast_p.h> #include <private/qdeclarativejsengine_p.h> #include <private/qdeclarativeexpression_p.h> +#include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> #include <QtCore/qnumeric.h> #include <private/qdeclarativeanchors_p_p.h> +#include <private/qdeclarativeglobal_p.h> QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL); +DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER); + using namespace QDeclarativeJS; namespace { @@ -124,24 +129,7 @@ public: QDeclarativeCompiledBindingsPrivate *parent; }; - struct Subscription { - struct Signal { - QDeclarativeGuard<QObject> source; - int notifyIndex; - }; - - enum { InvalidType, SignalType, IdType } type; - inline Subscription(); - inline ~Subscription(); - bool isSignal() const { return type == SignalType; } - bool isId() const { return type == IdType; } - inline Signal *signal(); - inline QDeclarativeContextPrivate::IdNotifier *id(); - union { - char signalData[sizeof(Signal)]; - char idData[sizeof(QDeclarativeContextPrivate::IdNotifier)]; - }; - }; + typedef QDeclarativeNotifierEndpoint Subscription; Subscription *subscriptions; QScriptDeclarativeClass::PersistentIdentifier *identifiers; @@ -154,18 +142,18 @@ public: static int methodCount; void init(); - void run(int instr, QDeclarativeContextPrivate *context, + void run(int instr, QDeclarativeContextData *context, QDeclarativeDelayedError *error, QObject *scope, QObject *output); inline void unsubscribe(int subIndex); - inline void subscribeId(QDeclarativeContextPrivate *p, int idIndex, int subIndex); + inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex); inline void subscribe(QObject *o, int notifyIndex, int subIndex); QDeclarativePropertyCache::Data *findproperty(QObject *obj, - const QScriptDeclarativeClass::Identifier &name, - QDeclarativeEnginePrivate *enginePriv, - QDeclarativePropertyCache::Data &local); + const QScriptDeclarativeClass::Identifier &name, + QDeclarativeEnginePrivate *enginePriv, + QDeclarativePropertyCache::Data &local); bool findproperty(QObject *obj, Register *output, QDeclarativeEnginePrivate *enginePriv, @@ -174,7 +162,7 @@ public: bool isTerminal); void findgeneric(Register *output, // value output int subIdx, // Subscription index in config - QDeclarativeContextPrivate *context, // Context to search in + QDeclarativeContextData *context, // Context to search in const QScriptDeclarativeClass::Identifier &name, bool isTerminal); }; @@ -190,21 +178,9 @@ QDeclarativeCompiledBindingsPrivate::~QDeclarativeCompiledBindingsPrivate() delete [] identifiers; identifiers = 0; } -QDeclarativeCompiledBindingsPrivate::Subscription::Subscription() -: type(InvalidType) -{ -} - -QDeclarativeCompiledBindingsPrivate::Subscription::~Subscription() -{ - if (type == SignalType) ((Signal *)signalData)->~Signal(); - else if (type == IdType) ((QDeclarativeContextPrivate::IdNotifier *)idData)->~IdNotifier(); -} - - int QDeclarativeCompiledBindingsPrivate::methodCount = -1; -QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContext *context) +QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context) : QObject(*(new QDeclarativeCompiledBindingsPrivate)) { Q_D(QDeclarativeCompiledBindings); @@ -248,7 +224,6 @@ void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarati { if (e) { addToObject(target); - update(flags); } else { removeFromObject(); } @@ -276,8 +251,8 @@ void QDeclarativeCompiledBindingsPrivate::Binding::destroy() { enabled = false; removeFromObject(); - parent->q_func()->release(); clear(); + parent->q_func()->release(); } int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **) @@ -303,47 +278,51 @@ void QDeclarativeCompiledBindingsPrivate::run(Binding *binding) if (!binding->enabled) return; - if (binding->updating) - qWarning("ERROR: Circular binding"); - QDeclarativeContext *context = q->QDeclarativeAbstractExpression::context(); + QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context(); if (!context) { qWarning("QDeclarativeCompiledBindings: Attempted to evaluate an expression in an invalid context"); return; } - QDeclarativeContextPrivate *cp = QDeclarativeContextPrivate::get(context); + if (!context->engine) + return; + + if (binding->updating) { + QString name; + if (binding->property & 0xFFFF0000) { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); + + QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + + name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name()); + name.append(QLatin1String(".")); + name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name())); + } else { + name = QLatin1String(binding->target->metaObject()->property(binding->property).name()); + } + qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeCompiledBindings", "Binding loop detected for property \"%1\"").arg(name); + return; + } + + binding->updating = true; if (binding->property & 0xFFFF0000) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(cp->engine); + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; Q_ASSERT(vt); vt->read(binding->target, binding->property & 0xFFFF); QObject *target = vt; - run(binding->index, cp, binding, binding->scope, target); + run(binding->index, context, binding, binding->scope, target); vt->write(binding->target, binding->property & 0xFFFF, QDeclarativePropertyPrivate::DontRemoveBinding); } else { - run(binding->index, cp, binding, binding->scope, binding->target); + run(binding->index, context, binding, binding->scope, binding->target); } -} - -QDeclarativeCompiledBindingsPrivate::Subscription::Signal *QDeclarativeCompiledBindingsPrivate::Subscription::signal() -{ - if (type == IdType) ((QDeclarativeContextPrivate::IdNotifier *)idData)->~IdNotifier(); - if (type != SignalType) new (signalData) Signal; - type = SignalType; - return (Signal *)signalData; -} - -QDeclarativeContextPrivate::IdNotifier *QDeclarativeCompiledBindingsPrivate::Subscription::id() -{ - if (type == SignalType) ((Signal *)signalData)->~Signal(); - if (type != IdType) new (idData) QDeclarativeContextPrivate::IdNotifier; - type = IdType; - return (QDeclarativeContextPrivate::IdNotifier *)idData; + binding->updating = false; } namespace { @@ -653,26 +632,11 @@ struct QDeclarativeBindingCompilerPrivate void QDeclarativeCompiledBindingsPrivate::unsubscribe(int subIndex) { - Q_Q(QDeclarativeCompiledBindings); - QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - if (sub->isSignal()) { - QDeclarativeCompiledBindingsPrivate::Subscription::Signal *s = sub->signal(); - if (s->source) -#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) - QMetaObject::disconnectOne(s->source, s->notifyIndex, - q, methodCount + subIndex); -#else - // QTBUG-6781 - QMetaObject::disconnect(s->source, s->notifyIndex, - q, methodCount + subIndex); -#endif - } else if (sub->isId()) { - sub->id()->clear(); - } + sub->disconnect(); } -void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextPrivate *p, int idIndex, int subIndex) +void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex) { Q_Q(QDeclarativeCompiledBindings); @@ -680,15 +644,9 @@ void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextPrivate if (p->idValues[idIndex]) { QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - QDeclarativeContextPrivate::IdNotifier *i = sub->id(); - - i->next = p->idValues[idIndex].bindings; - i->prev = &p->idValues[idIndex].bindings; - p->idValues[idIndex].bindings = i; - if (i->next) i->next->prev = &i->next; - - i->target = q; - i->methodIndex = methodCount + subIndex; + sub->target = q; + sub->targetMethod = methodCount + subIndex; + sub->connect(&p->idValues[idIndex].bindings); } } @@ -697,27 +655,12 @@ void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, Q_Q(QDeclarativeCompiledBindings); QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - - if (sub->isId()) - unsubscribe(subIndex); - - QDeclarativeCompiledBindingsPrivate::Subscription::Signal *s = sub->signal(); - if (o != s->source || notifyIndex != s->notifyIndex) { - if (s->source) -#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) - QMetaObject::disconnectOne(s->source, s->notifyIndex, - q, methodCount + subIndex); -#else - // QTBUG-6781 - QMetaObject::disconnect(s->source, s->notifyIndex, - q, methodCount + subIndex); -#endif - s->source = o; - s->notifyIndex = notifyIndex; - if (s->source && s->notifyIndex != -1) - QMetaObject::connect(s->source, s->notifyIndex, q, - methodCount + subIndex, Qt::DirectConnection); - } + sub->target = q; + sub->targetMethod = methodCount + subIndex; + if (o) + sub->connect(o, notifyIndex); + else + sub->disconnect(); } // Conversion functions - these MUST match the QtScript expression path @@ -767,7 +710,7 @@ inline static bool toBool(Register *reg, int type, bool *ok = 0) } } -inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextPrivate *context, bool *ok = 0) +inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0) { if (ok) *ok = true; @@ -811,9 +754,9 @@ static QObject *variantToQObject(const QVariant &value, bool *ok) } bool QDeclarativeCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, - QDeclarativeEnginePrivate *enginePriv, - int subIdx, const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) + QDeclarativeEnginePrivate *enginePriv, + int subIdx, const QScriptDeclarativeClass::Identifier &name, + bool isTerminal) { if (!obj) { output->setUndefined(); @@ -884,10 +827,10 @@ bool QDeclarativeCompiledBindingsPrivate::findproperty(QObject *obj, Register *o } void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output, - int subIdx, - QDeclarativeContextPrivate *context, - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) + int subIdx, + QDeclarativeContextData *context, + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal) { QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context->engine); @@ -898,14 +841,17 @@ void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output, if (contextPropertyIndex != -1) { - if (subIdx != -1) - subscribe(QDeclarativeContextPrivate::get(context), contextPropertyIndex + context->notifyIndex, subIdx); - if (contextPropertyIndex < context->idValueCount) { output->setQObject(context->idValues[contextPropertyIndex]); output->settype(QMetaType::QObjectStar); + + if (subIdx != -1) + subscribeId(context, contextPropertyIndex, subIdx); + } else { - const QVariant &value = context->propertyValues.at(contextPropertyIndex); + QDeclarativeContextPrivate *cp = context->asQDeclarativeContextPrivate(); + const QVariant &value = cp->propertyValues.at(contextPropertyIndex); + if (isTerminal) { new (output->typeDataPtr()) QVariant(value); output->settype(qMetaTypeId<QVariant>()); @@ -916,6 +862,11 @@ void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output, else { output->settype(QMetaType::QObjectStar); } return; } + + if (subIdx != -1) + subscribe(context->asQDeclarativeContext(), contextPropertyIndex + cp->notifyIndex, subIdx); + + } return; @@ -928,18 +879,14 @@ void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output, } } - if (QObject *root = context->defaultObjects.isEmpty()?0:context->defaultObjects.first()) { + if (QObject *root = context->contextObject) { if (findproperty(root, output, enginePriv, subIdx, name, isTerminal)) return; } - if (context->parent) { - context = QDeclarativeContextPrivate::get(context->parent); - } else { - context = 0; - } + context = context->parent; } output->setUndefined(); @@ -958,7 +905,7 @@ void QDeclarativeCompiledBindingsPrivate::init() } static void throwException(int id, QDeclarativeDelayedError *error, - Program *program, QDeclarativeContextPrivate *context, + Program *program, QDeclarativeContextData *context, const QString &description = QString()) { error->error.setUrl(context->url); @@ -1120,8 +1067,8 @@ static void dumpInstruction(const Instr *instr) } void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, - QDeclarativeContextPrivate *context, QDeclarativeDelayedError *error, - QObject *scope, QObject *output) + QDeclarativeContextData *context, QDeclarativeDelayedError *error, + QObject *scope, QObject *output) { error->removeError(); @@ -1169,7 +1116,7 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, break; case Instr::LoadRoot: - registers[instr->load.reg].setQObject(context->defaultObjects.at(0)); + registers[instr->load.reg].setQObject(context->contextObject); break; case Instr::LoadAttached: @@ -1455,7 +1402,7 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, // name is not present in the current context or it would have been // found during the static compile findgeneric(registers + instr->find.reg, instr->find.subscribeIndex, - QDeclarativeContextPrivate::get(context->parent), + context->parent, identifiers[instr->find.name].identifier, instr->common.type == Instr::FindGenericTerminal); break; @@ -1612,6 +1559,9 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node return false; if (type.unknownType) { + if (!qmlExperimental()) + return false; + if (destination->type != QMetaType::QReal && destination->type != QVariant::String && destination->type != QMetaType::Bool && @@ -1895,7 +1845,7 @@ bool QDeclarativeBindingCompilerPrivate::parseName(AST::Node *node, Result &type if (!fetch(type, component->metaObject(), reg, d1Idx, subscribeName, nameNodes.at(ii))) return false; - } else { + } else if (qmlExperimental()) { Instr find; if (nameParts.count() == 1) find.common.type = Instr::FindGenericTerminal; @@ -2051,7 +2001,11 @@ bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result int lhsTmp = -1; int rhsTmp = -1; + if (lhs.unknownType) { + if (!qmlExperimental()) + return false; + lhsTmp = acquireReg(); Instr conv; @@ -2062,6 +2016,9 @@ bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result } if (rhs.unknownType) { + if (!qmlExperimental()) + return false; + rhsTmp = acquireReg(); Instr conv; @@ -2107,6 +2064,9 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result int rhsTmp = -1; if (lhs.unknownType) { + if (!qmlExperimental()) + return false; + lhsTmp = acquireReg(Instr::CleanupString); Instr convert; @@ -2117,6 +2077,9 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result } if (rhs.unknownType) { + if (!qmlExperimental()) + return false; + rhsTmp = acquireReg(Instr::CleanupString); Instr convert; @@ -2637,6 +2600,12 @@ int QDeclarativeBindingCompiler::compile(const Expression &expression, QDeclarat { if (!expression.expression.asAST()) return false; + if (!qmlExperimental() && expression.property->isValueTypeSubProperty) + return -1; + + if (qmlDisableOptimizer()) + return -1; + d->context = expression.context; d->component = expression.component; d->destination = expression.property; diff --git a/src/declarative/qml/qdeclarativecompiledbindings_p.h b/src/declarative/qml/qdeclarativecompiledbindings_p.h index 2e24371..84a5df9 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings_p.h +++ b/src/declarative/qml/qdeclarativecompiledbindings_p.h @@ -95,7 +95,7 @@ class QDeclarativeCompiledBindingsPrivate; class QDeclarativeCompiledBindings : public QObject, public QDeclarativeAbstractExpression, public QDeclarativeRefCount { public: - QDeclarativeCompiledBindings(const char *program, QDeclarativeContext *context); + QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context); virtual ~QDeclarativeCompiledBindings(); QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property); diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index bdf16a3..dfbf453 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -199,20 +199,6 @@ void QDeclarativeCompiledData::clear() cachedPrograms[ii] = 0; } - -QObject *QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContext *ctxt, const QBitField &bindings) const -{ - if (type) { - QObject *rv = type->create(); - if (rv) - QDeclarativeEngine::setContextForObject(rv, ctxt); - return rv; - } else { - Q_ASSERT(component); - return QDeclarativeComponentPrivate::get(component)->create(ctxt, bindings); - } -} - const QMetaObject *QDeclarativeCompiledData::TypeReference::metaObject() const { if (type) { diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index ef1032b..42d2950 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -82,7 +82,7 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP); DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATISTICS_DUMP); -DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL); +DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP); using namespace QDeclarativeParser; @@ -825,7 +825,9 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) if (isCustomParser && !customProps.isEmpty()) { QDeclarativeCustomParser *cp = output->types.at(obj->type).type->customParser(); cp->clearErrors(); + cp->compiler = this; obj->custom = cp->compile(customProps); + cp->compiler = 0; foreach (QDeclarativeError err, cp->errors()) { err.setUrl(output->url); exceptions << err; @@ -1711,16 +1713,6 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop, COMPILE_CHECK(checkValidId(idValue, val)); - // We disallow id's that conflict with import prefixes and types - QDeclarativeEnginePrivate::ImportedNamespace *ns = 0; - QDeclarativeType *type = 0; - QDeclarativeEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(), - &type, 0, 0, 0, &ns); - if (type) - COMPILE_EXCEPTION(idValue, QCoreApplication::translate("QDeclarativeCompiler","id conflicts with type name")); - if (ns) - COMPILE_EXCEPTION(idValue, QCoreApplication::translate("QDeclarativeCompiler","id conflicts with namespace prefix")); - if (compileState.ids.contains(val)) COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","id is not unique")); @@ -1850,6 +1842,7 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, QMetaProperty p = type->metaObject()->property(idx); prop->index = idx; prop->type = p.userType(); + prop->isValueTypeSubProperty = true; if (prop->value) COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Property assignment expected")); @@ -2183,6 +2176,27 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop return true; } +// Similar logic to above, but not knowing target property. +int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const +{ + int dot = script.indexOf('.'); + if (dot > 0) { + QDeclarativeType *type = 0; + QDeclarativeEnginePrivate::get(engine)->resolveType(unit->imports, script.left(dot), &type, 0, 0, 0, 0); + if (!type) + return -1; + const QMetaObject *mo = type->metaObject(); + const char *key = script.constData() + dot+1; + int i = mo->enumeratorCount(); + while (i--) { + int v = mo->enumerator(i).keyToValue(key); + if (v >= 0) + return v; + } + } + return -1; +} + // Ensures that the dynamic meta specification on obj is valid bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) { @@ -2712,7 +2726,9 @@ bool QDeclarativeCompiler::completeComponentBuild() QDeclarativeBindingCompiler bindingCompiler; - for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) { + for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); + iter != compileState.bindings.end(); ++iter) { + BindingReference &binding = *iter; expr.context = binding.bindingContext.object; @@ -2720,18 +2736,13 @@ bool QDeclarativeCompiler::completeComponentBuild() expr.expression = binding.expression; expr.imports = unit->imports; - if (qmlExperimental()) { - int index = bindingCompiler.compile(expr, QDeclarativeEnginePrivate::get(engine)); - if (index != -1) { - qWarning() << "Accepted for optimization:" << qPrintable(expr.expression.asScript()); - binding.dataType = BindingReference::Experimental; - binding.compiledIndex = index; - componentStat.optimizedBindings++; - continue; - } else { - qWarning() << "Rejected for optimization:" << qPrintable(expr.expression.asScript()); - } - } + int index = bindingCompiler.compile(expr, QDeclarativeEnginePrivate::get(engine)); + if (index != -1) { + binding.dataType = BindingReference::Experimental; + binding.compiledIndex = index; + componentStat.optimizedBindings++; + continue; + } binding.dataType = BindingReference::QtScript; @@ -2768,7 +2779,8 @@ bool QDeclarativeCompiler::completeComponentBuild() if (bindingCompiler.isValid()) { compileState.compiledBindingData = bindingCompiler.program(); - QDeclarativeBindingCompiler::dump(compileState.compiledBindingData); + if (bindingsDump()) + QDeclarativeBindingCompiler::dump(compileState.compiledBindingData); } saveComponentState(); diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index cca42e2..a81259b 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -72,6 +72,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QDeclarativeComponent; class QDeclarativeContext; +class QDeclarativeContextData; class QScriptProgram; class Q_AUTOTEST_EXPORT QDeclarativeCompiledData : public QDeclarativeRefCount, public QDeclarativeCleanup @@ -95,7 +96,7 @@ public: QDeclarativeComponent *component; QDeclarativeRefCount *ref; - QObject *createInstance(QDeclarativeContext *, const QBitField &) const; + QObject *createInstance(QDeclarativeContextData *, const QBitField &) const; const QMetaObject *metaObject() const; }; QList<TypeReference> types; @@ -160,6 +161,8 @@ public: static QMetaMethod findSignalByName(const QMetaObject *, const QByteArray &name); + int evaluateEnum(const QByteArray& script) const; // for QDeclarativeCustomParser::evaluateEnum + private: static void reset(QDeclarativeCompiledData *); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index d6bb216..a280d7e 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -404,23 +404,9 @@ QDeclarativeContext *QDeclarativeComponent::creationContext() const { Q_D(const QDeclarativeComponent); if(d->creationContext) - return d->creationContext; - QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(this); - if (ddata) - return ddata->context; - else - return 0; -} + return d->creationContext->asQDeclarativeContext(); -/*! - \internal - Sets the QDeclarativeContext the component was created in. This is only - desirable for components created in QML script. -*/ -void QDeclarativeComponent::setCreationContext(QDeclarativeContext* c) -{ - Q_D(QDeclarativeComponent); - d->creationContext = c; + return qmlContext(this); } /*! @@ -512,7 +498,6 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q { } - /*! \internal A version of create which returns a scriptObject, for use in script @@ -526,7 +511,9 @@ QScriptValue QDeclarativeComponent::createObject() return QScriptValue(); } QObject* ret = create(ctxt); - return QDeclarativeEnginePrivate::qmlScriptObject(ret, d->engine); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine); + QDeclarativeDeclarativeData::get(ret, true)->setImplicitDestructible(); + return priv->objectClass->newQObject(ret, QMetaType::QObjectStar); } /*! @@ -541,19 +528,19 @@ QObject *QDeclarativeComponent::create(QDeclarativeContext *context) { Q_D(QDeclarativeComponent); - return d->create(context, QBitField()); + if (!context) + context = d->engine->rootContext(); + + QObject *rv = beginCreate(context); + completeCreate(); + return rv; } -QObject *QDeclarativeComponentPrivate::create(QDeclarativeContext *context, - const QBitField &bindings) +QObject *QDeclarativeComponentPrivate::create(QDeclarativeContextData *context, + const QBitField &bindings) { if (!context) - context = engine->rootContext(); - - if (context->engine() != engine) { - qWarning("QDeclarativeComponent::create(): Must create component in context from the same QDeclarativeEngine"); - return 0; - } + context = QDeclarativeContextData::get(engine->rootContext()); QObject *rv = beginCreate(context, bindings); completeCreate(); @@ -586,11 +573,17 @@ QObject *QDeclarativeComponentPrivate::create(QDeclarativeContext *context, QObject *QDeclarativeComponent::beginCreate(QDeclarativeContext *context) { Q_D(QDeclarativeComponent); - return d->beginCreate(context, QBitField()); + QObject *rv = d->beginCreate(context?QDeclarativeContextData::get(context):0, QBitField()); + if (rv) { + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(rv); + Q_ASSERT(ddata); + ddata->indestructible = true; + } + return rv; } QObject * -QDeclarativeComponentPrivate::beginCreate(QDeclarativeContext *context, const QBitField &bindings) +QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, const QBitField &bindings) { Q_Q(QDeclarativeComponent); if (!context) { @@ -598,7 +591,7 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContext *context, const QB return 0; } - if (context->engine() != engine) { + if (context->engine != engine) { qWarning("QDeclarativeComponent::beginCreate(): Must create component in context from the same QDeclarativeEngine"); return 0; } @@ -615,29 +608,24 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContext *context, const QB QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeContextPrivate *contextPriv = - static_cast<QDeclarativeContextPrivate *>(QObjectPrivate::get(context)); - QDeclarativeContext *ctxt = new QDeclarativeContext(context, 0, true); - static_cast<QDeclarativeContextPrivate*>(ctxt->d_func())->url = cc->url; - static_cast<QDeclarativeContextPrivate*>(ctxt->d_func())->imports = cc->importCache; + QDeclarativeContextData *ctxt = new QDeclarativeContextData; + ctxt->isInternal = true; + ctxt->url = cc->url; + ctxt->imports = cc->importCache; cc->importCache->addref(); + ctxt->setParent(context); QObject *rv = begin(ctxt, ep, cc, start, count, &state, bindings); - if (rv) { - QDeclarative_setParent_noEvent(ctxt, rv); - } else { - delete ctxt; - } + if (rv && !context->isInternal && ep->isDebugging) + context->asQDeclarativeContextPrivate()->instances.append(rv); - if (rv && !contextPriv->isInternal && ep->isDebugging) - contextPriv->instances.append(rv); return rv; } -QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContext *ctxt, QDeclarativeEnginePrivate *enginePriv, - QDeclarativeCompiledData *component, int start, int count, - ConstructionState *state, const QBitField &bindings) +QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv, + QDeclarativeCompiledData *component, int start, int count, + ConstructionState *state, const QBitField &bindings) { bool isRoot = !enginePriv->inBeginCreate; enginePriv->inBeginCreate = true; @@ -667,8 +655,8 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContext *ctxt, QDeclar return rv; } -void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeContext *, QDeclarativeEnginePrivate *enginePriv, - QObject *object, ConstructionState *state) +void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeContextData *, QDeclarativeEnginePrivate *enginePriv, + QObject *object, ConstructionState *state) { bool isRoot = !enginePriv->inBeginCreate; enginePriv->inBeginCreate = true; diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index aec0480..13a243e 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -104,7 +104,6 @@ public: void loadUrl(const QUrl &url); void setData(const QByteArray &, const QUrl &baseUrl); - void setCreationContext(QDeclarativeContext*); QDeclarativeContext *creationContext() const; static QDeclarativeComponentAttached *qmlAttachedProperties(QObject *); diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 3155813..649fce5 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -81,8 +81,8 @@ class QDeclarativeComponentPrivate : public QObjectPrivate public: QDeclarativeComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), engine(0), creationContext(0) {} - QObject *create(QDeclarativeContext *context, const QBitField &); - QObject *beginCreate(QDeclarativeContext *, const QBitField &); + QObject *create(QDeclarativeContextData *, const QBitField &); + QObject *beginCreate(QDeclarativeContextData *, const QBitField &); void completeCreate(); QDeclarativeCompositeTypeData *typeData; @@ -108,15 +108,15 @@ public: }; ConstructionState state; - static QObject *begin(QDeclarativeContext *ctxt, QDeclarativeEnginePrivate *enginePriv, + static QObject *begin(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv, QDeclarativeCompiledData *component, int start, int count, ConstructionState *state, const QBitField &bindings = QBitField()); - static void beginDeferred(QDeclarativeContext *ctxt, QDeclarativeEnginePrivate *enginePriv, + static void beginDeferred(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv, QObject *object, ConstructionState *state); static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state); QDeclarativeEngine *engine; - QDeclarativeContext *creationContext; + QDeclarativeContextData *creationContext; void clear(); diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp index b90a598..5014323 100644 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ b/src/declarative/qml/qdeclarativecompositetypemanager.cpp @@ -154,7 +154,7 @@ QDeclarativeCompositeTypeData::TypeReference::TypeReference() } QDeclarativeCompositeTypeManager::QDeclarativeCompositeTypeManager(QDeclarativeEngine *e) -: engine(e) +: engine(e), redirectCount(0) { } @@ -172,6 +172,10 @@ QDeclarativeCompositeTypeManager::~QDeclarativeCompositeTypeManager() QDeclarativeCompositeTypeData *QDeclarativeCompositeTypeManager::get(const QUrl &url) { + Redirects::Iterator redir = redirects.find(url); + if (redir != redirects.end()) + return get(*redir); + QDeclarativeCompositeTypeData *unit = components.value(url); if (!unit) { @@ -219,6 +223,8 @@ void QDeclarativeCompositeTypeManager::clearCache() } } +#define TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION 16 + void QDeclarativeCompositeTypeManager::replyFinished() { QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); @@ -226,6 +232,26 @@ void QDeclarativeCompositeTypeManager::replyFinished() QDeclarativeCompositeTypeData *unit = components.value(reply->url()); Q_ASSERT(unit); + redirectCount++; + if (redirectCount < TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + redirects.insert(reply->url(),url); + unit->imports.setBaseUrl(url); + components.remove(reply->url()); + components.insert(url, unit); + reply->deleteLater(); + reply = engine->networkAccessManager()->get(QNetworkRequest(url)); + QObject::connect(reply, SIGNAL(finished()), + this, SLOT(replyFinished())); + QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + return; + } + } + redirectCount = 0; + if (reply->error() != QNetworkReply::NoError) { QString errorDescription; // ### - Fill in error @@ -256,6 +282,24 @@ void QDeclarativeCompositeTypeManager::resourceReplyFinished() QDeclarativeCompositeTypeResource *resource = resources.value(reply->url()); Q_ASSERT(resource); + redirectCount++; + if (redirectCount < TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + redirects.insert(reply->url(),url); + resource->url = url.toString(); + resources.remove(reply->url()); + resources.insert(url, resource); + reply->deleteLater(); + reply = engine->networkAccessManager()->get(QNetworkRequest(url)); + QObject::connect(reply, SIGNAL(finished()), + this, SLOT(resourceReplyFinished())); + return; + } + } + redirectCount = 0; + if (reply->error() != QNetworkReply::NoError) { resource->status = QDeclarativeCompositeTypeResource::Error; @@ -271,12 +315,17 @@ void QDeclarativeCompositeTypeManager::resourceReplyFinished() reply->deleteLater(); } +// XXX this beyonds in QUrl::toLocalFile() +// WARNING, there is a copy of this function in qdeclarativeengine.cpp static QString toLocalFileOrQrc(const QUrl& url) { - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; + if (url.scheme() == QLatin1String("qrc")) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); + qWarning() << "Invalid url:" << url.toString() << "authority" << url.authority() << "not known."; + return QString(); + } + return url.toLocalFile(); } void QDeclarativeCompositeTypeManager::loadResource(QDeclarativeCompositeTypeResource *resource) @@ -461,18 +510,21 @@ int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData int waiting = 0; + + foreach (QDeclarativeScriptParser::Import imp, unit->data.imports()) { - QString qmldir; + QString qmldircontentnetwork; if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) { QString importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))).toString(); for (int ii = 0; ii < unit->resources.count(); ++ii) { if (unit->resources.at(ii)->url == importUrl) { - qmldir = QString::fromUtf8(unit->resources.at(ii)->data); + qmldircontentnetwork = QString::fromUtf8(unit->resources.at(ii)->data); break; } } } + int vmaj = -1; int vmin = -1; if (!imp.version.isEmpty()) { @@ -487,7 +539,7 @@ int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData } if (!QDeclarativeEnginePrivate::get(engine)-> - addToImport(&unit->imports, qmldir, imp.uri, imp.qualifier, vmaj, vmin, imp.type)) + addToImport(&unit->imports, qmldircontentnetwork, imp.uri, imp.qualifier, vmaj, vmin, imp.type)) { QDeclarativeError error; error.setUrl(unit->imports.baseUrl()); @@ -500,6 +552,27 @@ int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData } } + /* + For local urls, add an implicit import "." as first lookup. This will also trigger + the loading of the qmldir and the import of any native types from available plugins. + */ + { + + QString qmldircontentnetwork; + if (QDeclarativeCompositeTypeResource *resource + = resources.value(unit->imports.baseUrl().resolved(QUrl(QLatin1String("./qmldir"))))) + qmldircontentnetwork = QString::fromUtf8(resource->data); + + QDeclarativeEnginePrivate::get(engine)-> + addToImport(&unit->imports, + qmldircontentnetwork, + QLatin1String("."), + QString(), + -1, -1, + QDeclarativeScriptParser::Import::File); + } + + QList<QDeclarativeScriptParser::TypeReference*> types = unit->data.referencedTypes(); for (int ii = 0; ii < types.count(); ++ii) { @@ -546,6 +619,10 @@ int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData continue; } + Redirects::Iterator redir = redirects.find(url); + if (redir != redirects.end()) + url = *redir; + QDeclarativeCompositeTypeData *urlUnit = components.value(url); if (!urlUnit) { diff --git a/src/declarative/qml/qdeclarativecompositetypemanager_p.h b/src/declarative/qml/qdeclarativecompositetypemanager_p.h index 03d16b8..a572e0c 100644 --- a/src/declarative/qml/qdeclarativecompositetypemanager_p.h +++ b/src/declarative/qml/qdeclarativecompositetypemanager_p.h @@ -109,6 +109,9 @@ private: Components components; typedef QHash<QUrl, QDeclarativeCompositeTypeResource *> Resources; Resources resources; + typedef QHash<QUrl, QUrl> Redirects; + Redirects redirects; + int redirectCount; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index f70e143..782c0d7 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -58,83 +58,13 @@ QT_BEGIN_NAMESPACE QDeclarativeContextPrivate::QDeclarativeContextPrivate() -: parent(0), engine(0), isInternal(false), propertyNames(0), - notifyIndex(-1), highPriorityCount(0), imports(0), expressions(0), contextObjects(0), - idValues(0), idValueCount(0), optimizedBindings(0) +: data(0), notifyIndex(-1) { } -void QDeclarativeContextPrivate::addScript(const QDeclarativeParser::Object::ScriptBlock &script, QObject *scopeObject) -{ - Q_Q(QDeclarativeContext); - - if (!engine) - return; - - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); - - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - - scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject)); - scriptContext->pushScope(enginePriv->globalClass->globalObject()); - - QScriptValue scope = scriptEngine->newObject(); - scriptContext->setActivationObject(scope); - scriptContext->pushScope(scope); - - for (int ii = 0; ii < script.codes.count(); ++ii) { - scriptEngine->evaluate(script.codes.at(ii), script.files.at(ii), script.lineNumbers.at(ii)); - - if (scriptEngine->hasUncaughtException()) { - QDeclarativeError error; - QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); - qWarning().nospace() << qPrintable(error.toString()); - } - } - - scriptEngine->popContext(); - - scripts.append(scope); -} - -void QDeclarativeContextPrivate::destroyed(ContextGuard *guard) -{ - Q_Q(QDeclarativeContext); - - // process of being deleted (which is *probably* why obj has been destroyed - // anyway), as we're about to get deleted which will invalidate all the - // expressions that could depend on us - QObject *parent = q->parent(); - if (parent && QObjectPrivate::get(parent)->wasDeleted) - return; - - while(guard->bindings) { - QObject *o = guard->bindings->target; - int mi = guard->bindings->methodIndex; - guard->bindings->clear(); - if (o) o->qt_metacall(QMetaObject::InvokeMetaMethod, mi, 0); - } - - for (int ii = 0; ii < idValueCount; ++ii) { - if (&idValues[ii] == guard) { - QMetaObject::activate(q, ii + notifyIndex, 0); - return; - } - } -} - -void QDeclarativeContextPrivate::init() -{ - Q_Q(QDeclarativeContext); - - if (parent) - parent->d_func()->childContexts.insert(q); -} - /*! \class QDeclarativeContext - \since 4.7 + \since 4.7 \brief The QDeclarativeContext class defines a context within a QML engine. \mainclass @@ -177,7 +107,7 @@ void QDeclarativeContextPrivate::init() MyDataSet myDataSet; QDeclarativeEngine engine; QDeclarativeContext context(engine.rootContext()); - context.addDefaultObject(&myDataSet); + context.setContextObject(&myDataSet); QDeclarativeComponent component(&engine, "ListView { model=myModel }"); component.create(&context); @@ -221,8 +151,9 @@ QDeclarativeContext::QDeclarativeContext(QDeclarativeEngine *e, bool) : QObject(*(new QDeclarativeContextPrivate)) { Q_D(QDeclarativeContext); - d->engine = e; - d->init(); + d->data = new QDeclarativeContextData(this); + + d->data->engine = e; } /*! @@ -233,10 +164,9 @@ QDeclarativeContext::QDeclarativeContext(QDeclarativeEngine *engine, QObject *pa : QObject(*(new QDeclarativeContextPrivate), parent) { Q_D(QDeclarativeContext); - QDeclarativeContext *parentContext = engine?engine->rootContext():0; - d->parent = parentContext; - d->engine = parentContext->engine(); - d->init(); + d->data = new QDeclarativeContextData(this); + + d->data->setParent(engine?QDeclarativeContextData::get(engine->rootContext()):0); } /*! @@ -247,22 +177,19 @@ QDeclarativeContext::QDeclarativeContext(QDeclarativeContext *parentContext, QOb : QObject(*(new QDeclarativeContextPrivate), parent) { Q_D(QDeclarativeContext); - d->parent = parentContext; - d->engine = parentContext->engine(); - d->init(); + d->data = new QDeclarativeContextData(this); + + d->data->setParent(parentContext?QDeclarativeContextData::get(parentContext):0); } /*! \internal */ -QDeclarativeContext::QDeclarativeContext(QDeclarativeContext *parentContext, QObject *parent, bool) -: QObject(*(new QDeclarativeContextPrivate), parent) +QDeclarativeContext::QDeclarativeContext(QDeclarativeContextData *data) +: QObject(*(new QDeclarativeContextPrivate), 0) { Q_D(QDeclarativeContext); - d->parent = parentContext; - d->engine = parentContext->engine(); - d->isInternal = true; - d->init(); + d->data = data; } /*! @@ -275,78 +202,9 @@ QDeclarativeContext::QDeclarativeContext(QDeclarativeContext *parentContext, QOb QDeclarativeContext::~QDeclarativeContext() { Q_D(QDeclarativeContext); - if (d->parent) - d->parent->d_func()->childContexts.remove(this); - - for (QSet<QDeclarativeContext *>::ConstIterator iter = d->childContexts.begin(); - iter != d->childContexts.end(); - ++iter) { - (*iter)->d_func()->invalidateEngines(); - (*iter)->d_func()->parent = 0; - } - - QDeclarativeAbstractExpression *expression = d->expressions; - while (expression) { - QDeclarativeAbstractExpression *nextExpression = expression->m_nextExpression; - - expression->m_context = 0; - expression->m_prevExpression = 0; - expression->m_nextExpression = 0; - - expression = nextExpression; - } - - while (d->contextObjects) { - QDeclarativeDeclarativeData *co = d->contextObjects; - d->contextObjects = d->contextObjects->nextContextObject; - - co->context = 0; - co->nextContextObject = 0; - co->prevContextObject = 0; - } - - if (d->propertyNames) - d->propertyNames->release(); - - if (d->imports) - d->imports->release(); - - if (d->optimizedBindings) - d->optimizedBindings->release(); - - delete [] d->idValues; -} - -void QDeclarativeContextPrivate::invalidateEngines() -{ - if (!engine) - return; - engine = 0; - for (QSet<QDeclarativeContext *>::ConstIterator iter = childContexts.begin(); - iter != childContexts.end(); - ++iter) { - (*iter)->d_func()->invalidateEngines(); - } -} - -/* -Refreshes all expressions that could possibly depend on this context. -Refreshing flushes all context-tree dependent caches in the expressions, and should occur every -time the context tree *structure* (not values) changes. -*/ -void QDeclarativeContextPrivate::refreshExpressions() -{ - for (QSet<QDeclarativeContext *>::ConstIterator iter = childContexts.begin(); - iter != childContexts.end(); - ++iter) { - (*iter)->d_func()->refreshExpressions(); - } - QDeclarativeAbstractExpression *expression = expressions; - while (expression) { - expression->refresh(); - expression = expression->m_nextExpression; - } + if (!d->data->isInternal) + d->data->destroy(); } /*! @@ -356,7 +214,7 @@ void QDeclarativeContextPrivate::refreshExpressions() QDeclarativeEngine *QDeclarativeContext::engine() const { Q_D(const QDeclarativeContext); - return d->engine; + return d->data->engine; } /*! @@ -366,17 +224,33 @@ QDeclarativeEngine *QDeclarativeContext::engine() const QDeclarativeContext *QDeclarativeContext::parentContext() const { Q_D(const QDeclarativeContext); - return d->parent; + return d->data->parent?d->data->parent->asQDeclarativeContext():0; +} + +/*! + Return the context object, or 0 if there is no context object. +*/ +QObject *QDeclarativeContext::contextObject() const +{ + Q_D(const QDeclarativeContext); + return d->data->contextObject; } /*! - Add \a defaultObject to this context. The object will be added after - any existing default objects. + Set the context \a object. */ -void QDeclarativeContext::addDefaultObject(QObject *defaultObject) +void QDeclarativeContext::setContextObject(QObject *object) { Q_D(QDeclarativeContext); - d->defaultObjects.prepend(defaultObject); + + QDeclarativeContextData *data = d->data; + + if (data->isInternal) { + qWarning("QDeclarativeContext: Cannot set context object for internal context."); + return; + } + + data->contextObject = object; } /*! @@ -388,50 +262,36 @@ void QDeclarativeContext::setContextProperty(const QString &name, const QVariant if (d->notifyIndex == -1) d->notifyIndex = this->metaObject()->methodCount(); - if (d->engine) { + QDeclarativeContextData *data = d->data; + + if (data->isInternal) { + qWarning("QDeclarativeContext: Cannot set property on internal context."); + return; + } + + if (data->engine) { bool ok; - QObject *o = QDeclarativeEnginePrivate::get(d->engine)->toQObject(value, &ok); + QObject *o = QDeclarativeEnginePrivate::get(data->engine)->toQObject(value, &ok); if (ok) { setContextProperty(name, o); return; } } - if (!d->propertyNames) d->propertyNames = new QDeclarativeIntegerCache(d->engine); + if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine); - int idx = d->propertyNames->value(name); + int idx = data->propertyNames->value(name); if (idx == -1) { - d->propertyNames->add(name, d->idValueCount + d->propertyValues.count()); + data->propertyNames->add(name, data->idValueCount + d->propertyValues.count()); d->propertyValues.append(value); - d->refreshExpressions(); + data->refreshExpressions(); } else { d->propertyValues[idx] = value; QMetaObject::activate(this, idx + d->notifyIndex, 0); } } -void QDeclarativeContextPrivate::setIdProperty(int idx, QObject *obj) -{ - if (notifyIndex == -1) { - Q_Q(QDeclarativeContext); - notifyIndex = q->metaObject()->methodCount(); - } - - idValues[idx].priv = this; - idValues[idx] = obj; -} - -void QDeclarativeContextPrivate::setIdPropertyData(QDeclarativeIntegerCache *data) -{ - Q_ASSERT(!propertyNames); - propertyNames = data; - propertyNames->addref(); - - idValueCount = data->count(); - idValues = new ContextGuard[idValueCount]; -} - /*! Set the \a value of the \a name property on this context. @@ -443,14 +303,21 @@ void QDeclarativeContext::setContextProperty(const QString &name, QObject *value if (d->notifyIndex == -1) d->notifyIndex = this->metaObject()->methodCount(); - if (!d->propertyNames) d->propertyNames = new QDeclarativeIntegerCache(d->engine); - int idx = d->propertyNames->value(name); + QDeclarativeContextData *data = d->data; + + if (data->isInternal) { + qWarning("QDeclarativeContext: Cannot set property on internal context."); + return; + } + + if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine); + int idx = data->propertyNames->value(name); if (idx == -1) { - d->propertyNames->add(name, d->idValueCount + d->propertyValues.count()); + data->propertyNames->add(name, data->idValueCount + d->propertyValues.count()); d->propertyValues.append(QVariant::fromValue(value)); - d->refreshExpressions(); + data->refreshExpressions(); } else { d->propertyValues[idx] = QVariant::fromValue(value); QMetaObject::activate(this, idx + d->notifyIndex, 0); @@ -466,26 +333,27 @@ QVariant QDeclarativeContext::contextProperty(const QString &name) const Q_D(const QDeclarativeContext); QVariant value; int idx = -1; - if (d->propertyNames) - idx = d->propertyNames->value(name); + + QDeclarativeContextData *data = d->data; + + if (data->propertyNames) + idx = data->propertyNames->value(name); if (idx == -1) { QByteArray utf8Name = name.toUtf8(); - for (int ii = d->defaultObjects.count() - 1; ii >= 0; --ii) { - QObject *obj = d->defaultObjects.at(ii); + if (data->contextObject) { + QObject *obj = data->contextObject; QDeclarativePropertyCache::Data local; - QDeclarativePropertyCache::Data *property = QDeclarativePropertyCache::property(d->engine, obj, name, local); + QDeclarativePropertyCache::Data *property = + QDeclarativePropertyCache::property(data->engine, obj, name, local); - if (property) { - value = obj->metaObject()->property(property->coreIndex).read(obj); - break; - } + if (property) value = obj->metaObject()->property(property->coreIndex).read(obj); } if (!value.isValid() && parentContext()) value = parentContext()->contextProperty(name); } else { if (idx >= d->propertyValues.count()) - value = QVariant::fromValue(d->idValues[idx - d->propertyValues.count()].data()); + value = QVariant::fromValue(data->idValues[idx - d->propertyValues.count()].data()); else value = d->propertyValues[idx]; } @@ -502,20 +370,26 @@ QVariant QDeclarativeContext::contextProperty(const QString &name) const QUrl QDeclarativeContext::resolvedUrl(const QUrl &src) { Q_D(QDeclarativeContext); - QDeclarativeContext *ctxt = this; + return d->data->resolvedUrl(src); +} + +QUrl QDeclarativeContextData::resolvedUrl(const QUrl &src) +{ + QDeclarativeContextData *ctxt = this; + if (src.isRelative() && !src.isEmpty()) { if (ctxt) { while(ctxt) { - if(ctxt->d_func()->url.isValid()) + if(ctxt->url.isValid()) break; else - ctxt = ctxt->parentContext(); + ctxt = ctxt->parent; } if (ctxt) - return ctxt->d_func()->url.resolved(src); - else if (d->engine) - return d->engine->baseUrl().resolved(src); + return ctxt->url.resolved(src); + else if (engine) + return engine->baseUrl().resolved(src); } return QUrl(); } else { @@ -523,6 +397,7 @@ QUrl QDeclarativeContext::resolvedUrl(const QUrl &src) } } + /*! Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl. @@ -533,7 +408,9 @@ QUrl QDeclarativeContext::resolvedUrl(const QUrl &src) */ void QDeclarativeContext::setBaseUrl(const QUrl &baseUrl) { - d_func()->url = baseUrl; + Q_D(QDeclarativeContext); + + d->data->url = baseUrl; } /*! @@ -542,12 +419,13 @@ void QDeclarativeContext::setBaseUrl(const QUrl &baseUrl) */ QUrl QDeclarativeContext::baseUrl() const { - const QDeclarativeContext* p = this; - while (p && p->d_func()->url.isEmpty()) { - p = p->parentContext(); - } - if (p) - return p->d_func()->url; + Q_D(const QDeclarativeContext); + const QDeclarativeContextData* data = d->data; + while (data && data->url.isEmpty()) + data = data->parent; + + if (data) + return data->url; else return QUrl(); } @@ -578,4 +456,215 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject } } + +QDeclarativeContextData::QDeclarativeContextData() +: parent(0), engine(0), isInternal(false), publicContext(0), propertyNames(0), contextObject(0), + imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0), + contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0) +{ +} + +QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt) +: parent(0), engine(0), isInternal(false), publicContext(ctxt), propertyNames(0), contextObject(0), + imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0), + contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0) +{ +} + +void QDeclarativeContextData::destroy() +{ + if (linkedContext) + linkedContext->destroy(); + + if (prevChild) { + *prevChild = nextChild; + if (nextChild) nextChild->prevChild = prevChild; + nextChild = 0; + prevChild = 0; + } + + QDeclarativeContextData *child = childContexts; + while (child) { + QDeclarativeContextData *next = child->nextChild; + + child->invalidateEngines(); + child->parent = 0; + child->nextChild = 0; + child->prevChild = 0; + + child = next; + } + childContexts = 0; + + QDeclarativeAbstractExpression *expression = expressions; + while (expression) { + QDeclarativeAbstractExpression *nextExpression = expression->m_nextExpression; + + expression->m_context = 0; + expression->m_prevExpression = 0; + expression->m_nextExpression = 0; + + expression = nextExpression; + } + expressions = 0; + + while (contextObjects) { + QDeclarativeDeclarativeData *co = contextObjects; + contextObjects = contextObjects->nextContextObject; + + co->context = 0; + co->outerContext = 0; + co->nextContextObject = 0; + co->prevContextObject = 0; + } + + QDeclarativeGuardedContextData *contextGuard = contextGuards; + while (contextGuard) { + QDeclarativeGuardedContextData *next = contextGuard->m_next; + contextGuard->m_next = 0; + contextGuard->m_prev = 0; + contextGuard->m_contextData = 0; + contextGuard = next; + } + contextGuards = 0; + + if (propertyNames) + propertyNames->release(); + + if (imports) + imports->release(); + + if (optimizedBindings) + optimizedBindings->release(); + + delete [] idValues; + + if (isInternal) + delete publicContext; + + delete this; +} + +void QDeclarativeContextData::setParent(QDeclarativeContextData *p) +{ + if (p) { + parent = p; + engine = p->engine; + nextChild = p->childContexts; + if (nextChild) nextChild->prevChild = &nextChild; + prevChild = &p->childContexts; + p->childContexts = this; + } +} + +void QDeclarativeContextData::invalidateEngines() +{ + if (!engine) + return; + engine = 0; + + QDeclarativeContextData *child = childContexts; + while (child) { + child->invalidateEngines(); + child = child->nextChild; + } +} + +/* +Refreshes all expressions that could possibly depend on this context. Refreshing flushes all +context-tree dependent caches in the expressions, and should occur every time the context tree + *structure* (not values) changes. +*/ +void QDeclarativeContextData::refreshExpressions() +{ + QDeclarativeContextData *child = childContexts; + while (child) { + child->refreshExpressions(); + child = child->nextChild; + } + + QDeclarativeAbstractExpression *expression = expressions; + while (expression) { + expression->refresh(); + expression = expression->m_nextExpression; + } +} + +void QDeclarativeContextData::addObject(QObject *o) +{ + QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(o, true); + + Q_ASSERT(data->context == 0); + + data->context = this; + data->outerContext = this; + + data->nextContextObject = contextObjects; + if (data->nextContextObject) + data->nextContextObject->prevContextObject = &data->nextContextObject; + data->prevContextObject = &contextObjects; + contextObjects = data; +} + +void QDeclarativeContextData::addScript(const QDeclarativeParser::Object::ScriptBlock &script, + QObject *scopeObject) +{ + if (!engine) + return; + + QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); + + scriptContext->pushScope(enginePriv->contextClass->newContext(this, scopeObject)); + scriptContext->pushScope(enginePriv->globalClass->globalObject()); + + QScriptValue scope = scriptEngine->newObject(); + scriptContext->setActivationObject(scope); + scriptContext->pushScope(scope); + + for (int ii = 0; ii < script.codes.count(); ++ii) { + scriptEngine->evaluate(script.codes.at(ii), script.files.at(ii), script.lineNumbers.at(ii)); + + if (scriptEngine->hasUncaughtException()) { + QDeclarativeError error; + QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); + qWarning().nospace() << qPrintable(error.toString()); + } + } + + scriptEngine->popContext(); + + scripts.append(scope); +} + +void QDeclarativeContextData::setIdProperty(int idx, QObject *obj) +{ + idValues[idx] = obj; + idValues[idx].context = this; +} + +void QDeclarativeContextData::setIdPropertyData(QDeclarativeIntegerCache *data) +{ + Q_ASSERT(!propertyNames); + propertyNames = data; + propertyNames->addref(); + + idValueCount = data->count(); + idValues = new ContextGuard[idValueCount]; +} + +QDeclarativeContext *QDeclarativeContextData::asQDeclarativeContext() +{ + if (!publicContext) + publicContext = new QDeclarativeContext(this); + return publicContext; +} + +QDeclarativeContextPrivate *QDeclarativeContextData::asQDeclarativeContextPrivate() +{ + return QDeclarativeContextPrivate::get(asQDeclarativeContext()); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h index 0fb9bee..a349628 100644 --- a/src/declarative/qml/qdeclarativecontext.h +++ b/src/declarative/qml/qdeclarativecontext.h @@ -58,6 +58,7 @@ class QDeclarativeEngine; class QDeclarativeRefCount; class QDeclarativeContextPrivate; class QDeclarativeCompositeTypeData; +class QDeclarativeContextData; class Q_DECLARATIVE_EXPORT QDeclarativeContext : public QObject { @@ -72,11 +73,12 @@ public: QDeclarativeEngine *engine() const; QDeclarativeContext *parentContext() const; - void addDefaultObject(QObject *); - void setContextProperty(const QString &, QObject *); - void setContextProperty(const QString &, const QVariant &); + QObject *contextObject() const; + void setContextObject(QObject *); QVariant contextProperty(const QString &) const; + void setContextProperty(const QString &, QObject *); + void setContextProperty(const QString &, const QVariant &); QUrl resolvedUrl(const QUrl &); @@ -95,7 +97,8 @@ private: friend class QDeclarativeComponentPrivate; friend class QDeclarativeScriptPrivate; friend class QDeclarativeBoundSignalProxy; - QDeclarativeContext(QDeclarativeContext *parent, QObject *objParent, bool); + friend class QDeclarativeContextData; + QDeclarativeContext(QDeclarativeContextData *); QDeclarativeContext(QDeclarativeEngine *, bool); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 8297280..d74aa33 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -56,9 +56,11 @@ #include "qdeclarativecontext.h" #include "qdeclarativedeclarativedata_p.h" -#include "qdeclarativeengine_p.h" #include "qdeclarativeintegercache_p.h" #include "qdeclarativetypenamecache_p.h" +#include "qdeclarativenotifier_p.h" +#include "qdeclarativelist.h" +#include "qdeclarativeparser_p.h" #include <QtCore/qhash.h> #include <QtScript/qscriptvalue.h> @@ -77,6 +79,7 @@ class QDeclarativeExpressionPrivate; class QDeclarativeAbstractExpression; class QDeclarativeBinding_Id; class QDeclarativeCompiledBindings; +class QDeclarativeContextData; class Q_DECLARATIVE_EXPORT QDeclarativeContextPrivate : public QObjectPrivate { @@ -84,110 +87,182 @@ class Q_DECLARATIVE_EXPORT QDeclarativeContextPrivate : public QObjectPrivate public: QDeclarativeContextPrivate(); - QDeclarativeContext *parent; + QDeclarativeContextData *data; + + QList<QVariant> propertyValues; + int notifyIndex; + + static QDeclarativeContextPrivate *get(QDeclarativeContext *context) { + return static_cast<QDeclarativeContextPrivate *>(QObjectPrivate::get(context)); + } + static QDeclarativeContext *get(QDeclarativeContextPrivate *context) { + return static_cast<QDeclarativeContext *>(context->q_func()); + } + + // Only used for debugging + QList<QPointer<QObject> > instances; + + static int context_count(QDeclarativeListProperty<QObject> *); + static QObject *context_at(QDeclarativeListProperty<QObject> *, int); +}; + +class QDeclarativeGuardedContextData; +class QDeclarativeContextData +{ +public: + QDeclarativeContextData(); + QDeclarativeContextData(QDeclarativeContext *); + void destroy(); + + // My parent context and engine + QDeclarativeContextData *parent; QDeclarativeEngine *engine; + void setParent(QDeclarativeContextData *); + void invalidateEngines(); + void refreshExpressions(); + + void addObject(QObject *); + + QUrl resolvedUrl(const QUrl &); + + // My containing QDeclarativeContext. If isInternal is true this owns publicContext. + // If internal is false publicContext owns this. + QDeclarativeContext *asQDeclarativeContext(); + QDeclarativeContextPrivate *asQDeclarativeContextPrivate(); bool isInternal; + QDeclarativeContext *publicContext; + // Property name cache QDeclarativeIntegerCache *propertyNames; - QList<QVariant> propertyValues; - int notifyIndex; - QObjectList defaultObjects; - int highPriorityCount; + // Context object + QObject *contextObject; + // Any script blocks that exist on this context QList<QScriptValue> scripts; - void addScript(const QDeclarativeParser::Object::ScriptBlock &, QObject *); + void addScript(const QDeclarativeParser::Object::ScriptBlock &script, QObject *scopeObject); + // Context base url QUrl url; + // List of imports that apply to this context QDeclarativeTypeNameCache *imports; - void init(); + // My children + QDeclarativeContextData *childContexts; - void invalidateEngines(); - void refreshExpressions(); - QSet<QDeclarativeContext *> childContexts; + // My peers in parent's childContexts list + QDeclarativeContextData *nextChild; + QDeclarativeContextData **prevChild; + // Expressions that use this context QDeclarativeAbstractExpression *expressions; + // Doubly-linked list of objects that are owned by this context QDeclarativeDeclarativeData *contextObjects; - struct IdNotifier - { - inline IdNotifier(); - inline ~IdNotifier(); - - inline void clear(); - - IdNotifier *next; - IdNotifier**prev; - QObject *target; - int methodIndex; - }; + // Doubly-linked list of context guards (XXX merge with contextObjects) + QDeclarativeGuardedContextData *contextGuards; + // id guards struct ContextGuard : public QDeclarativeGuard<QObject> { - inline ContextGuard(); - inline ContextGuard &operator=(QObject *obj); - inline virtual void objectDestroyed(QObject *); - - QDeclarativeContextPrivate *priv; - IdNotifier *bindings; + ContextGuard() : context(0) {} + inline ContextGuard &operator=(QObject *obj) + { QDeclarativeGuard<QObject>::operator=(obj); return *this; } + virtual void objectDestroyed(QObject *) { + if (!QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify(); + } + QDeclarativeContextData *context; + QDeclarativeNotifier bindings; }; ContextGuard *idValues; int idValueCount; void setIdProperty(int, QObject *); void setIdPropertyData(QDeclarativeIntegerCache *); - void destroyed(ContextGuard *); - static QDeclarativeContextPrivate *get(QDeclarativeContext *context) { - return static_cast<QDeclarativeContextPrivate *>(QObjectPrivate::get(context)); - } - static QDeclarativeContext *get(QDeclarativeContextPrivate *context) { - return static_cast<QDeclarativeContext *>(context->q_func()); + // Optimized binding pointer + QDeclarativeCompiledBindings *optimizedBindings; + + // Linked contexts. this owns linkedContext. + QDeclarativeContextData *linkedContext; + + static QDeclarativeContextData *get(QDeclarativeContext *context) { + return QDeclarativeContextPrivate::get(context)->data; } - QDeclarativeCompiledBindings *optimizedBindings; +private: + ~QDeclarativeContextData() {} +}; - // Only used for debugging - QList<QPointer<QObject> > instances; +class QDeclarativeGuardedContextData +{ +public: + inline QDeclarativeGuardedContextData(); + inline QDeclarativeGuardedContextData(QDeclarativeContextData *); + inline ~QDeclarativeGuardedContextData(); - static int context_count(QDeclarativeListProperty<QObject> *); - static QObject *context_at(QDeclarativeListProperty<QObject> *, int); + inline void setContextData(QDeclarativeContextData *); + + inline QDeclarativeContextData *contextData(); + + inline operator QDeclarativeContextData*() const { return m_contextData; } + inline QDeclarativeContextData* operator->() const { return m_contextData; } + +private: + friend class QDeclarativeContextData; + + inline void clear(); + + QDeclarativeContextData *m_contextData; + QDeclarativeGuardedContextData *m_next; + QDeclarativeGuardedContextData **m_prev; }; -QDeclarativeContextPrivate::IdNotifier::IdNotifier() -: next(0), prev(0), target(0), methodIndex(-1) +QDeclarativeGuardedContextData::QDeclarativeGuardedContextData() +: m_contextData(0), m_next(0), m_prev(0) { } -QDeclarativeContextPrivate::IdNotifier::~IdNotifier() +QDeclarativeGuardedContextData::QDeclarativeGuardedContextData(QDeclarativeContextData *data) +: m_contextData(0), m_next(0), m_prev(0) { - clear(); + setContextData(data); } -void QDeclarativeContextPrivate::IdNotifier::clear() +QDeclarativeGuardedContextData::~QDeclarativeGuardedContextData() { - if (next) next->prev = prev; - if (prev) *prev = next; - next = 0; prev = 0; target = 0; - methodIndex = -1; + clear(); } -QDeclarativeContextPrivate::ContextGuard::ContextGuard() -: priv(0), bindings(0) +void QDeclarativeGuardedContextData::setContextData(QDeclarativeContextData *contextData) { + clear(); + + if (contextData) { + m_contextData = contextData; + m_next = contextData->contextGuards; + if (m_next) m_next->m_prev = &m_next; + m_prev = &contextData->contextGuards; + contextData->contextGuards = this; + } } -QDeclarativeContextPrivate::ContextGuard &QDeclarativeContextPrivate::ContextGuard::operator=(QObject *obj) +QDeclarativeContextData *QDeclarativeGuardedContextData::contextData() { - (QDeclarativeGuard<QObject>&)*this = obj; return *this; + return m_contextData; } -void QDeclarativeContextPrivate::ContextGuard::objectDestroyed(QObject *) -{ - priv->destroyed(this); +void QDeclarativeGuardedContextData::clear() +{ + if (m_prev) { + *m_prev = m_next; + if (m_next) m_next->m_prev = m_prev; + m_contextData = 0; + m_next = 0; + m_prev = 0; + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp index 5fcf4e2..847d632 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp +++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp @@ -51,17 +51,17 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { ContextData() : overrideObject(0), isSharedContext(true) {} - ContextData(QDeclarativeContext *c, QObject *o) : context(c), scopeObject(o), overrideObject(0), isSharedContext(false) {} - QDeclarativeGuard<QDeclarativeContext> context; + ContextData(QDeclarativeContextData *c, QObject *o) : context(c), scopeObject(o), overrideObject(0), isSharedContext(false) {} + QDeclarativeGuardedContextData context; QDeclarativeGuard<QObject> scopeObject; QObject *overrideObject; bool isSharedContext; - QDeclarativeContext *getContext(QDeclarativeEngine *engine) { + QDeclarativeContextData *getContext(QDeclarativeEngine *engine) { if (isSharedContext) { return QDeclarativeEnginePrivate::get(engine)->sharedContext; } else { - return context.data(); + return context.contextData(); } } @@ -80,7 +80,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { */ QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine) : QDeclarativeScriptClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) + lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1) { } @@ -88,7 +88,7 @@ QDeclarativeContextScriptClass::~QDeclarativeContextScriptClass() { } -QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContext *context, QObject *scopeObject) +QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContextData *context, QObject *scopeObject) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -102,7 +102,7 @@ QScriptValue QDeclarativeContextScriptClass::newSharedContext() return newObject(scriptEngine, this, new ContextData()); } -QDeclarativeContext *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v) +QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v) { if (scriptClass(v) != this) return 0; @@ -132,9 +132,8 @@ QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier & lastContext = 0; lastData = 0; lastPropertyIndex = -1; - lastDefaultObject = -1; - QDeclarativeContext *bindContext = ((ContextData *)object)->getContext(engine); + QDeclarativeContextData *bindContext = ((ContextData *)object)->getContext(engine); QObject *scopeObject = ((ContextData *)object)->getScope(engine); if (!bindContext) return 0; @@ -160,29 +159,28 @@ QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier & scopeObject = 0; // Only applies to the first context includeTypes = false; // Only applies to the first context if (rv) return rv; - bindContext = bindContext->parentContext(); + bindContext = bindContext->parent; } return 0; } QScriptClass::QueryFlags -QDeclarativeContextScriptClass::queryProperty(QDeclarativeContext *bindContext, QObject *scopeObject, - const Identifier &name, - QScriptClass::QueryFlags flags, - bool includeTypes) +QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindContext, QObject *scopeObject, + const Identifier &name, + QScriptClass::QueryFlags flags, + bool includeTypes) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeContextPrivate *cp = QDeclarativeContextPrivate::get(bindContext); - lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1; + lastPropertyIndex = bindContext->propertyNames?bindContext->propertyNames->value(name):-1; if (lastPropertyIndex != -1) { lastContext = bindContext; return QScriptClass::HandlesReadAccess; } - if (includeTypes && cp->imports) { - QDeclarativeTypeNameCache::Data *data = cp->imports->data(name); + if (includeTypes && bindContext->imports) { + QDeclarativeTypeNameCache::Data *data = bindContext->imports->data(name); if (data) { lastData = data; @@ -191,8 +189,8 @@ QDeclarativeContextScriptClass::queryProperty(QDeclarativeContext *bindContext, } } - for (int ii = 0; ii < cp->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + for (int ii = 0; ii < bindContext->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(bindContext->scripts.at(ii), name); if (lastFunction.isValid()) { lastContext = bindContext; return QScriptClass::HandlesReadAccess; @@ -210,13 +208,13 @@ QDeclarativeContextScriptClass::queryProperty(QDeclarativeContext *bindContext, } } - for (int ii = cp->defaultObjects.count() - 1; ii >= 0; --ii) { + if (bindContext->contextObject) { QScriptClass::QueryFlags rv = - ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, bindContext, + ep->objectClass->queryProperty(bindContext->contextObject, name, flags, bindContext, QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties); if (rv) { - lastDefaultObject = ii; + lastScopeObject = bindContext->contextObject; lastContext = bindContext; return rv; } @@ -230,11 +228,10 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); - QDeclarativeContext *bindContext = lastContext; + QDeclarativeContextData *bindContext = lastContext; Q_ASSERT(bindContext); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeContextPrivate *cp = QDeclarativeContextPrivate::get(bindContext); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); if (lastScopeObject) { @@ -244,33 +241,33 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name) } else if (lastData) { if (lastData->type) - return Value(scriptEngine, ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type)); + return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->type)); else - return Value(scriptEngine, ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace)); + return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->typeNamespace)); } else if (lastPropertyIndex != -1) { QScriptValue rv; - if (lastPropertyIndex < cp->idValueCount) { - rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data()); + if (lastPropertyIndex < bindContext->idValueCount) { + rv = ep->objectClass->newQObject(bindContext->idValues[lastPropertyIndex].data()); + + if (ep->captureProperties) + ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(&bindContext->idValues[lastPropertyIndex].bindings); } else { + QDeclarativeContextPrivate *cp = bindContext->asQDeclarativeContextPrivate(); const QVariant &value = cp->propertyValues.at(lastPropertyIndex); if (value.userType() == qMetaTypeId<QList<QObject*> >()) { - rv = ep->listClass->newList(QDeclarativeListProperty<QObject>(bindContext, (void*)lastPropertyIndex, 0, QDeclarativeContextPrivate::context_count, QDeclarativeContextPrivate::context_at), qMetaTypeId<QDeclarativeListProperty<QObject> >()); + rv = ep->listClass->newList(QDeclarativeListProperty<QObject>(bindContext->asQDeclarativeContext(), (void*)lastPropertyIndex, 0, QDeclarativeContextPrivate::context_count, QDeclarativeContextPrivate::context_at), qMetaTypeId<QDeclarativeListProperty<QObject> >()); } else { rv = ep->scriptValueFromVariant(value); } - } - if (ep->captureProperties) - ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex); + if (ep->captureProperties) + ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext->asQDeclarativeContext(), -1, lastPropertyIndex + cp->notifyIndex); + } return Value(scriptEngine, rv); - } else if(lastDefaultObject != -1) { - - // Default object property - return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name); } else { @@ -283,20 +280,14 @@ void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifie const QScriptValue &value) { Q_UNUSED(object); - Q_ASSERT(lastScopeObject || lastDefaultObject != -1); + Q_ASSERT(lastScopeObject); - QDeclarativeContext *bindContext = lastContext; + QDeclarativeContextData *bindContext = lastContext; Q_ASSERT(bindContext); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeContextPrivate *cp = QDeclarativeContextPrivate::get(bindContext); - if (lastScopeObject) { - ep->objectClass->setProperty(lastScopeObject, name, value, bindContext); - } else { - ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value, - bindContext); - } + ep->objectClass->setProperty(lastScopeObject, name, value, bindContext); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontextscriptclass_p.h b/src/declarative/qml/qdeclarativecontextscriptclass_p.h index 4b0dca0..93e4b20 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass_p.h +++ b/src/declarative/qml/qdeclarativecontextscriptclass_p.h @@ -60,16 +60,17 @@ QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QDeclarativeContext; +class QDeclarativeContextData; class QDeclarativeContextScriptClass : public QDeclarativeScriptClass { public: QDeclarativeContextScriptClass(QDeclarativeEngine *); ~QDeclarativeContextScriptClass(); - QScriptValue newContext(QDeclarativeContext *, QObject * = 0); + QScriptValue newContext(QDeclarativeContextData *, QObject * = 0); QScriptValue newSharedContext(); - QDeclarativeContext *contextFromValue(const QScriptValue &); + QDeclarativeContextData *contextFromValue(const QScriptValue &); QObject *setOverrideObject(QScriptValue &, QObject *); protected: @@ -79,7 +80,7 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: - QScriptClass::QueryFlags queryProperty(QDeclarativeContext *, QObject *scopeObject, + QScriptClass::QueryFlags queryProperty(QDeclarativeContextData *, QObject *scopeObject, const Identifier &, QScriptClass::QueryFlags flags, bool includeTypes); @@ -87,10 +88,9 @@ private: QDeclarativeEngine *engine; QObject *lastScopeObject; - QDeclarativeContext *lastContext; + QDeclarativeContextData *lastContext; QDeclarativeTypeNameCache::Data *lastData; int lastPropertyIndex; - int lastDefaultObject; QScriptValue lastFunction; uint m_id; diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp index 67f0963..a3a511c 100644 --- a/src/declarative/qml/qdeclarativecustomparser.cpp +++ b/src/declarative/qml/qdeclarativecustomparser.cpp @@ -43,6 +43,7 @@ #include "qdeclarativecustomparser_p_p.h" #include "qdeclarativeparser_p.h" +#include "qdeclarativecompiler_p.h" #include <QtCore/qdebug.h> @@ -260,4 +261,15 @@ void QDeclarativeCustomParser::error(const QDeclarativeCustomParserNode& node, c exceptions << error; } +/*! + If \a script is a simply enum expression (eg. Text.AlignLeft), + returns the integer equivalent (eg. 1). + + Otherwise, returns -1. +*/ +int QDeclarativeCustomParser::evaluateEnum(const QByteArray& script) const +{ + return compiler->evaluateEnum(script); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h index 99587a8..f9bf513 100644 --- a/src/declarative/qml/qdeclarativecustomparser_p.h +++ b/src/declarative/qml/qdeclarativecustomparser_p.h @@ -66,6 +66,8 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QDeclarativeCompiler; + class QDeclarativeCustomParserPropertyPrivate; class Q_DECLARATIVE_EXPORT QDeclarativeCustomParserProperty { @@ -111,6 +113,7 @@ private: class Q_DECLARATIVE_EXPORT QDeclarativeCustomParser { public: + QDeclarativeCustomParser() : compiler(0) {} virtual ~QDeclarativeCustomParser() {} void clearErrors(); @@ -124,13 +127,18 @@ protected: void error(const QDeclarativeCustomParserProperty&, const QString& description); void error(const QDeclarativeCustomParserNode&, const QString& description); + int evaluateEnum(const QByteArray&) const; + private: QList<QDeclarativeError> exceptions; + QDeclarativeCompiler *compiler; + friend class QDeclarativeCompiler; }; +#if 0 #define QML_REGISTER_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE, CUSTOMTYPE) \ qmlRegisterCustomType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE, new CUSTOMTYPE) - +#endif QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativedeclarativedata_p.h b/src/declarative/qml/qdeclarativedeclarativedata_p.h index ae40130..d1d063a 100644 --- a/src/declarative/qml/qdeclarativedeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedeclarativedata_p.h @@ -63,18 +63,32 @@ class QDeclarativeCompiledData; class QDeclarativeAbstractBinding; class QDeclarativeContext; class QDeclarativePropertyCache; +class QDeclarativeContextData; class Q_AUTOTEST_EXPORT QDeclarativeDeclarativeData : public QDeclarativeData { public: - QDeclarativeDeclarativeData(QDeclarativeContext *ctxt = 0) - : context(ctxt), bindings(0), nextContextObject(0), prevContextObject(0), - bindingBitsSize(0), bindingBits(0), outerContext(0), lineNumber(0), - columnNumber(0), deferredComponent(0), deferredIdx(0), attachedProperties(0), - propertyCache(0), guards(0) {} + QDeclarativeDeclarativeData() + : 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), propertyCache(0), guards(0) {} virtual void destroyed(QObject *); + virtual void parentChanged(QObject *, QObject *); + + void setImplicitDestructible() { + if (!explicitIndestructibleSet) indestructible = false; + } + + quint32 ownMemory:1; + quint32 ownContext:1; + quint32 indestructible:1; + quint32 explicitIndestructibleSet:1; + quint32 dummy:28; + + QDeclarativeContextData *context; + QDeclarativeContextData *outerContext; - QDeclarativeContext *context; QDeclarativeAbstractBinding *bindings; // Linked list for QDeclarativeContext::contextObjects @@ -87,7 +101,6 @@ public: void clearBindingBit(int); void setBindingBit(QObject *obj, int); - QDeclarativeContext *outerContext; // Can't this be found from context? ushort lineNumber; ushort columnNumber; diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index e730b92..b6d2115 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -151,13 +151,16 @@ bool QDeclarativeDirParser::parse() _plugins.append(entry); + } else if (sectionCount == 2) { + // No version specified (should only be used for relative qmldir files) + const Component entry(sections[0], sections[1], -1, -1); + _components.append(entry); } else if (sectionCount == 3) { const QString &version = sections[1]; const int dotIndex = version.indexOf(QLatin1Char('.')); if (dotIndex == -1) { qWarning() << "expected '.'"; // ### use reportError - } else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) { qWarning() << "unexpected '.'"; // ### use reportError diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index c23b17c..800434a 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -146,12 +146,11 @@ static bool qt_QmlQtModule_registered = false; void QDeclarativeEnginePrivate::defineModule() { - QML_REGISTER_TYPE(Qt,4,6,Component,QDeclarativeComponent); - QML_REGISTER_TYPE(Qt,4,6,QtObject,QObject); - QML_REGISTER_TYPE(Qt,4,6,WorkerScript,QDeclarativeWorkerScript); - QML_REGISTER_TYPE(Qt,4,6,WorkerListModel,QDeclarativeWorkerListModel); + qmlRegisterType<QDeclarativeComponent>("Qt",4,6,"Component"); + qmlRegisterType<QObject>("Qt",4,6,"QtObject"); + qmlRegisterType<QDeclarativeWorkerScript>("Qt",4,6,"WorkerScript"); - QML_REGISTER_NOCREATE_TYPE(QDeclarativeBinding); + qmlRegisterType<QDeclarativeBinding>(); } QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) @@ -190,7 +189,7 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url) { if (p) { - QDeclarativeContext *ctxt = QDeclarativeEnginePrivate::get(this)->getContext(context); + QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(this)->getContext(context); Q_ASSERT(ctxt); return ctxt->resolvedUrl(url); } @@ -243,7 +242,6 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr qtObject.setProperty(QLatin1String("formatDateTime"),newFunction(QDeclarativeEnginePrivate::formatDateTime, 2)); //misc methods - qtObject.setProperty(QLatin1String("closestAngle"), newFunction(QDeclarativeEnginePrivate::closestAngle, 2)); qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QDeclarativeEnginePrivate::desktopOpenUrl, 1)); qtObject.setProperty(QLatin1String("md5"),newFunction(QDeclarativeEnginePrivate::md5, 1)); qtObject.setProperty(QLatin1String("btoa"),newFunction(QDeclarativeEnginePrivate::btoa, 1)); @@ -637,9 +635,9 @@ QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object) if (!data) return 0; else if (data->outerContext) - return data->outerContext; + return data->outerContext->asQDeclarativeContext(); else - return data->context; + return 0; } /*! @@ -660,12 +658,63 @@ void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContex return; } - data->context = context; - data->nextContextObject = context->d_func()->contextObjects; - if (data->nextContextObject) - data->nextContextObject->prevContextObject = &data->nextContextObject; - data->prevContextObject = &context->d_func()->contextObjects; - context->d_func()->contextObjects = data; + QDeclarativeContextData *contextData = QDeclarativeContextData::get(context); + contextData->addObject(object); +} + +/*! +\enum QDeclarativeEngine::ObjectOwnership + +Ownership controls whether or not QML automatically destroys the QObject when the object +is garbage collected by the JavaScript engine. The two ownership options are: + +\list +\o CppOwnership - The object is owned by C++ code, and will never be deleted by QML. The +JavaScript destroy() method cannot be used on objects with CppOwnership. This option +is similar to QScriptEngine::QtOwnership. + +\o JavaScriptOwnership - The object is owned by JavaScript. When the object is returned to QML +as the return value of a method call or property access, QML will delete the object if there +are no remaining JavaScript references to it and it has no QObject::parent(). This option +is similar to QScriptEngine::ScriptOwnership. +\endlist + +Generally an application doesn't need to set an object's ownership explicitly. QML uses +a heuristic to set the default object ownership. By default, an object that is created by +QML has JavaScriptOwnership. The exception to this are the root objects created by calling +QDeclarativeCompnent::create() or QDeclarativeComponent::beginCreate() which have +CppOwnership by default. The ownership of these root-level objects is considered to have +been transfered to the C++ caller. + +Objects not-created by QML have CppOwnership by default. The exception to this is objects +returned from a C++ method call. The ownership of these objects is passed to JavaScript. + +Calling setObjectOwnership() overrides the default ownership heuristic used by QML. +*/ + +/*! +Sets the \a ownership of \a object. +*/ +void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership) +{ + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, true); + if (!ddata) + return; + + ddata->indestructible = (ownership == CppOwnership)?true:false; + ddata->explicitIndestructibleSet = true; +} + +/*! +Returns the ownership of \a object. +*/ +QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object) +{ + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, false); + if (!ddata) + return CppOwnership; + else + return ddata->indestructible?CppOwnership:JavaScriptOwnership; } void qmlExecuteDeferred(QObject *object) @@ -674,7 +723,7 @@ void qmlExecuteDeferred(QObject *object) if (data && data->deferredComponent) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine()); + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine); QDeclarativeComponentPrivate::ConstructionState state; QDeclarativeComponentPrivate::beginDeferred(data->context, ep, object, &state); @@ -775,7 +824,18 @@ void QDeclarativeDeclarativeData::destroyed(QObject *object) g->objectDestroyed(object); } - delete this; + if (ownContext) + context->destroy(); + + if (ownMemory) + delete this; + else + this->~QDeclarativeDeclarativeData(); +} + +void QDeclarativeDeclarativeData::parentChanged(QObject *, QObject *parent) +{ + if (!parent && scriptValue.isValid()) scriptValue = QScriptValue(); } bool QDeclarativeDeclarativeData::hasBindingBit(int bit) const @@ -832,7 +892,7 @@ QScriptValue QDeclarativeEnginePrivate::qmlScriptObject(QObject* object, /*! Returns the QDeclarativeContext for the executing QScript \a ctxt. */ -QDeclarativeContext *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt) +QDeclarativeContextData *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt) { QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3); Q_ASSERT(scopeNode.isValid()); @@ -840,15 +900,15 @@ QDeclarativeContext *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt) return contextClass->contextFromValue(scopeNode); } -QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, - QScriptEngine *engine) +QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine) { QDeclarativeEnginePrivate *activeEnginePriv = static_cast<QDeclarativeScriptEngine*>(engine)->p; QDeclarativeEngine* activeEngine = activeEnginePriv->q_func(); - QDeclarativeContext* context = activeEnginePriv->getContext(ctxt); + QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt); Q_ASSERT(context); + if(ctxt->argumentCount() != 1) { return engine->nullValue(); }else{ @@ -857,7 +917,8 @@ QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, return engine->nullValue(); QUrl url = QUrl(context->resolvedUrl(QUrl(arg))); QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine); - c->setCreationContext(context); + QDeclarativeComponentPrivate::get(c)->creationContext = context; + QDeclarativeDeclarativeData::get(c, true)->setImplicitDestructible(); return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QDeclarativeComponent*>()); } } @@ -871,7 +932,7 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3) return engine->nullValue(); - QDeclarativeContext* context = activeEnginePriv->getContext(ctxt); + QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt); Q_ASSERT(context); QString qml = ctxt->argument(0).toString(); @@ -909,7 +970,7 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS return engine->nullValue(); } - QObject *obj = component.create(context); + QObject *obj = component.create(context->asQDeclarativeContext()); if(component.isError()) { QList<QDeclarativeError> errors = component.errors(); @@ -928,7 +989,8 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS if(gobj && gparent) gobj->setParentItem(gparent); - return qmlScriptObject(obj, activeEngine); + QDeclarativeDeclarativeData::get(obj, true)->setImplicitDestructible(); + return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar); } QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine) @@ -1177,25 +1239,6 @@ QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptE return QScriptValue(); } -QScriptValue QDeclarativeEnginePrivate::closestAngle(QScriptContext *ctxt, QScriptEngine *e) -{ - if(ctxt->argumentCount() < 2) - return e->newVariant(QVariant(0.0)); - qreal a = ctxt->argument(0).toNumber(); - qreal b = ctxt->argument(1).toNumber(); - qreal ret = b; - qreal diff = b-a; - while(diff > 180.0){ - ret -= 360.0; - diff -= 360.0; - } - while(diff < -180.0){ - ret += 360.0; - diff += 360.0; - } - return e->newVariant(QVariant(ret)); -} - QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) @@ -1299,12 +1342,16 @@ QVariant QDeclarativeScriptClass::toVariant(QDeclarativeEngine *engine, const QS } // XXX this beyonds in QUrl::toLocalFile() +// WARNING, there is a copy of this function in qdeclarativecompositetypemanager.cpp static QString toLocalFileOrQrc(const QUrl& url) { - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; + if (url.scheme() == QLatin1String("qrc")) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); + qWarning() << "Invalid url:" << url.toString() << "authority" << url.authority() << "not known."; + return QString(); + } + return url.toLocalFile(); } ///////////////////////////////////////////////////////////// @@ -1316,7 +1363,7 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { QList<bool> isLibrary; QList<QString> qmlDirContent; - bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return) const + bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return) { for (int i=0; i<urls.count(); ++i) { int vmaj = majversions.at(i); @@ -1326,14 +1373,10 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { qt += '/'; qt += type; - if (qmlImportTrace()) - qDebug() << "Look in" << qt; QDeclarativeType *t = QDeclarativeMetaType::qmlType(qt,vmaj,vmin); if (t) { if (vmajor) *vmajor = vmaj; if (vminor) *vminor = vmin; - if (qmlImportTrace()) - qDebug() << "Found" << qt; if (type_return) *type_return = t; return true; @@ -1341,15 +1384,9 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml")); QString qmldircontent = qmlDirContent.at(i); - if (vmaj>=0 || !qmldircontent.isEmpty()) { - // Check version file - XXX cache these in QDeclarativeEngine! - if (qmldircontent.isEmpty()) { - QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir")))); - if (qmldir.open(QIODevice::ReadOnly)) { - qmldircontent = QString::fromUtf8(qmldir.readAll()); - } - } + bool typeWasDeclaredInQmldir = false; + if (!qmldircontent.isEmpty()) { const QString typeName = QString::fromUtf8(type); QDeclarativeDirParser qmldirParser; @@ -1358,17 +1395,18 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { qmldirParser.parse(); foreach (const QDeclarativeDirParser::Component &c, qmldirParser.components()) { // ### TODO: cache the components - if (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion)) { - if (c.typeName == typeName) { + if (c.typeName == typeName) { + typeWasDeclaredInQmldir = true; + if (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion)) { if (url_return) *url_return = url.resolved(QUrl(c.fileName)); - return true; } } } + } - } else { + if (!typeWasDeclaredInQmldir && !isLibrary.at(i)) { // XXX search non-files too! (eg. zip files, see QT-524) QFileInfo f(toLocalFileOrQrc(url)); if (f.exists()) { @@ -1396,8 +1434,88 @@ public: QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded; - bool add(const QUrl& base, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, const QStringList& importPath, QDeclarativeEngine *engine) + QString importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine) { + QFile file(absoluteFilePath); + QString dir = QFileInfo(file).path(); + QString qmldircontent; + if (file.open(QFile::ReadOnly)) { + qmldircontent = QString::fromUtf8(file.readAll()); + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::add: loaded" << absoluteFilePath; + } + + if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { + qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); + + QDeclarativeDirParser qmldirParser; + qmldirParser.setSource(qmldircontent); + qmldirParser.parse(); + + foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { + QDir pluginDir(dir + QDir::separator() + plugin.path); + if (dir.startsWith(QLatin1Char(':'))) + pluginDir = QDir(QCoreApplication::applicationDirPath()); + QString resolvedFilePath = + QDeclarativeEnginePrivate::get(engine) + ->resolvePlugin(pluginDir, + plugin.name); + + if (!resolvedFilePath.isEmpty()) { + engine->importExtension(resolvedFilePath, uri); + } + } + } + return qmldircontent; + } + + QString resolvedUri(const QString &dir_arg, QDeclarativeEngine *engine) { + QString dir = dir_arg; + if (dir.endsWith(QLatin1Char('/')) || dir.endsWith(QLatin1Char('\\'))) + dir.chop(1); + + QStringList paths; + + if (!base.isEmpty()) { + QString baseDir = QFileInfo(toLocalFileOrQrc(base)).path(); + paths += baseDir; + } + + QString applicationDirPath = QCoreApplication::applicationDirPath(); + if (!applicationDirPath.isEmpty()) + paths += applicationDirPath; + + paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath; +#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) + QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); +#else + QString builtinPath; +#endif + if (!builtinPath.isEmpty()) + paths += builtinPath; + + // add fileImportPath last, this is *not* search order. + paths += QDeclarativeEnginePrivate::get(engine)->fileImportPath; + + QString stableRelativePath = dir; + foreach( QString path, paths) { + if (dir.startsWith(path)) { + stableRelativePath = dir.mid(path.length()+1); + break; + } + } + stableRelativePath.replace(QLatin1Char('/'), QLatin1Char('.')); + stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('.')); + return stableRelativePath; + } + + + + + bool add(const QUrl& base, const QString &qmldircontentnetwork, const QString& uri_arg, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, QDeclarativeEngine *engine) + { + QString qmldircontent = qmldircontentnetwork; + QString uri = uri_arg; QDeclarativeEnginePrivate::ImportedNamespace *s; if (prefix.isEmpty()) { s = &unqualifiedset; @@ -1406,30 +1524,40 @@ public: if (!s) set.insert(prefix,(s=new QDeclarativeEnginePrivate::ImportedNamespace)); } + + + QString url = uri; if (importType == QDeclarativeScriptParser::Import::Library) { url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; - QString content; QString dir; + // user import paths QStringList paths; - // base.. - paths += QFileInfo(base.toLocalFile()).path(); - paths += importPath; + QString localFileOrQrc = toLocalFileOrQrc(base); + QString localFileOrQrcPath = QFileInfo(localFileOrQrc).path(); + paths += localFileOrQrcPath; + paths += QDeclarativeEnginePrivate::get(engine)->fileImportPath; + + QString applicationDirPath = QCoreApplication::applicationDirPath(); + if (!applicationDirPath.isEmpty()) + paths += applicationDirPath; + paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath; -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) + #if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); -#else + #else QString builtinPath; -#endif + #endif if (!builtinPath.isEmpty()) paths += builtinPath; foreach (const QString &p, paths) { dir = p+QLatin1Char('/')+url; + QFileInfo fi(dir+QLatin1String("/qmldir")); const QString absoluteFilePath = fi.absoluteFilePath(); @@ -1437,33 +1565,31 @@ public: found = true; url = QUrl::fromLocalFile(fi.absolutePath()).toString(); - - QFile file(absoluteFilePath); - if (file.open(QFile::ReadOnly)) - content = QString::fromUtf8(file.readAll()); - - if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { - qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); - - QDeclarativeDirParser qmldirParser; - qmldirParser.setSource(content); - qmldirParser.parse(); - - foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { - QString resolvedFilePath = QDeclarativeEnginePrivate::get(engine)->resolvePlugin(QDir(dir + QDir::separator() + plugin.path), - plugin.name); - - if (!resolvedFilePath.isEmpty()) - engine->importExtension(resolvedFilePath, uri); - } - } - + uri = resolvedUri(dir, engine); + qmldircontent = importExtension(absoluteFilePath, uri, engine); break; } } } else { + + if (importType == QDeclarativeScriptParser::Import::File && qmldircontent.isEmpty()) { + QUrl importUrl = base.resolved(QUrl(uri + QLatin1String("/qmldir"))); + QString localFileOrQrc = toLocalFileOrQrc(importUrl); + if (!localFileOrQrc.isEmpty()) { + uri = resolvedUri(toLocalFileOrQrc(base.resolved(QUrl(uri))), engine); + qmldircontent = importExtension(localFileOrQrc, + uri, + engine); + + if (uri.endsWith(QLatin1Char('/'))) + uri.chop(1); + } + } + url = base.resolved(QUrl(url)).toString(); + if (url.endsWith(QLatin1Char('/'))) + url.chop(1); } s->uris.prepend(uri); @@ -1493,12 +1619,18 @@ public: if (s) { if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return)) return true; - if (s->urls.count() == 1 && !s->isLibrary[0] && url_return) { + if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) { + // qualified, and only 1 url *url_return = QUrl(s->urls[0]+QLatin1Char('/')).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml"))); return true; } } + + + /* now comes really nasty code. It makes "private" types load in the remote case, but + it does this by breaking the import order. This must go. Instead private types must + be marked private in the qmldir. */ if (url_return) { *url_return = base.resolved(QUrl(QString::fromUtf8(type + ".qml"))); return true; @@ -1642,9 +1774,10 @@ QUrl QDeclarativeEnginePrivate::Imports::baseUrl() const type version mapping and possibly declarative extensions plugins. The engine searches in the base directory of the qml file, then - the paths added via addImportPath(), then the paths specified in the - \c QML_IMPORT_PATH environment variable, then the builtin \c ImportsPath from - QLibraryInfo. + the paths added via addImportPath(), then in the directory containing the + application executable (QCoreApplication::applicationDirPath()), + then the paths specified in the \c QML_IMPORT_PATH environment variable, then the + builtin \c ImportsPath from QLibraryInfo. */ void QDeclarativeEngine::addImportPath(const QString& path) @@ -1661,6 +1794,8 @@ void QDeclarativeEngine::addImportPath(const QString& path) */ bool QDeclarativeEngine::importExtension(const QString &fileName, const QString &uri) { + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::importExtension" << uri << "from" << fileName; QFileInfo fileInfo(fileName); const QString absoluteFilePath = fileInfo.absoluteFilePath(); QPluginLoader loader(absoluteFilePath); @@ -1744,6 +1879,8 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString return fileInfo.absoluteFilePath(); } + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << dir.absolutePath(); return QString(); } @@ -1784,6 +1921,9 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString return resolvePlugin(dir, baseName, QStringList() +# ifdef QT_DEBUG + << QLatin1String("_debug.dylib") // try a qmake-style debug build first +# endif << QLatin1String(".dylib") << QLatin1String(".so") << QLatin1String(".bundle"), @@ -1830,12 +1970,12 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString The base URL must already have been set with Import::setBaseUrl(). */ -bool QDeclarativeEnginePrivate::addToImport(Imports* imports, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const +bool QDeclarativeEnginePrivate::addToImport(Imports* imports, const QString &qmldircontentnetwork, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const { QDeclarativeEngine *engine = QDeclarativeEnginePrivate::get(const_cast<QDeclarativeEnginePrivate *>(this)); - bool ok = imports->d->add(imports->d->base,qmldircontent,uri,prefix,vmaj,vmin,importType,fileImportPath, engine); if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::addToImport(" << imports << uri << prefix << vmaj << '.' << vmin << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") << ": " << ok; + qDebug().nospace() << "QDeclarativeEngine::addToImport " << imports << " " << uri << " " << vmaj << '.' << vmin << " " << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") << " as " << prefix; + bool ok = imports->d->add(imports->d->base,qmldircontentnetwork, uri,prefix,vmaj,vmin,importType, engine); return ok; } @@ -1855,8 +1995,6 @@ bool QDeclarativeEnginePrivate::resolveType(const Imports& imports, const QByteA { ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type)); if (ns) { - if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::resolveType" << type << "is namespace for" << ns->urls; if (ns_return) *ns_return = ns; return true; @@ -1864,15 +2002,15 @@ bool QDeclarativeEnginePrivate::resolveType(const Imports& imports, const QByteA if (type_return || url_return) { if (imports.d->find(type,vmaj,vmin,type_return,url_return)) { if (qmlImportTrace()) { + if (type_return && *type_return && url_return && !url_return->isEmpty()) + qDebug() << "QDeclarativeEngine::resolveType" << type << '=' << (*type_return)->typeName() << *url_return; if (type_return && *type_return) qDebug() << "QDeclarativeEngine::resolveType" << type << '=' << (*type_return)->typeName(); - if (url_return) + if (url_return && !url_return->isEmpty()) qDebug() << "QDeclarativeEngine::resolveType" << type << '=' << *url_return; } return true; } - if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::resolveType" << type << "not found"; } return false; } diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h index fd66358..19e81b6 100644 --- a/src/declarative/qml/qdeclarativeengine.h +++ b/src/declarative/qml/qdeclarativeengine.h @@ -98,6 +98,10 @@ public: static QDeclarativeContext *contextForObject(const QObject *); static void setContextForObject(QObject *, QDeclarativeContext *); + enum ObjectOwnership { CppOwnership, JavaScriptOwnership }; + static void setObjectOwnership(QObject *, ObjectOwnership); + static ObjectOwnership objectOwnership(QObject *); + Q_SIGNALS: void quit (); diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 459a325..f1b7b0e 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -61,6 +61,7 @@ #include "qdeclarative.h" #include "qdeclarativevaluetype_p.h" #include "qdeclarativecontext.h" +#include "qdeclarativecontext_p.h" #include "qdeclarativeexpression.h" #include "qdeclarativeproperty_p.h" #include "qdeclarativepropertycache_p.h" @@ -144,10 +145,13 @@ public: struct CapturedProperty { CapturedProperty(QObject *o, int c, int n) - : object(o), coreIndex(c), notifyIndex(n) {} + : object(o), coreIndex(c), notifier(0), notifyIndex(n) {} + CapturedProperty(QDeclarativeNotifier *n) + : object(0), coreIndex(-1), notifier(n), notifyIndex(-1) {} QObject *object; int coreIndex; + QDeclarativeNotifier *notifier; int notifyIndex; }; bool captureProperties; @@ -159,7 +163,7 @@ public: struct ImportedNamespace; QDeclarativeContextScriptClass *contextClass; - QDeclarativeContext *sharedContext; + QDeclarativeContextData *sharedContext; QObject *sharedScope; QDeclarativeObjectScriptClass *objectClass; QDeclarativeValueTypeScriptClass *valueTypeClass; @@ -276,7 +280,7 @@ public: QString resolvePlugin(const QDir &dir, const QString &baseName); - bool addToImport(Imports*, const QString& qmlDirContent,const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const; + bool addToImport(Imports*, const QString& uri, const QString &qmldircontentnetwork, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const; bool resolveType(const Imports&, const QByteArray& type, QDeclarativeType** type_return, QUrl* url_return, int *version_major, int *version_minor, @@ -318,7 +322,6 @@ public: static QScriptValue darker(QScriptContext*, QScriptEngine*); static QScriptValue tint(QScriptContext*, QScriptEngine*); - static QScriptValue closestAngle(QScriptContext*, QScriptEngine*); static QScriptValue desktopOpenUrl(QScriptContext*, QScriptEngine*); static QScriptValue md5(QScriptContext*, QScriptEngine*); static QScriptValue btoa(QScriptContext*, QScriptEngine*); @@ -334,9 +337,10 @@ public: static QDeclarativeEngine *getEngine(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p->q_func(); } static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e) { return e->d_func(); } static QDeclarativeEnginePrivate *get(QDeclarativeContext *c) { return (c && c->engine()) ? QDeclarativeEnginePrivate::get(c->engine()) : 0; } + static QDeclarativeEnginePrivate *get(QDeclarativeContextData *c) { return (c && c->engine) ? QDeclarativeEnginePrivate::get(c->engine) : 0; } static QDeclarativeEnginePrivate *get(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p; } static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p) { return p->q_func(); } - QDeclarativeContext *getContext(QScriptContext *); + QDeclarativeContextData *getContext(QScriptContext *); static void defineModule(); }; diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 3e4acbe..a377b35 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -49,6 +49,7 @@ #include "qdeclarativebinding_p.h" #include "qdeclarativecontext_p.h" #include "qdeclarativewatcher_p.h" +#include "qdeclarativevaluetype_p.h" #include <QtCore/qdebug.h> #include <QtCore/qmetaobject.h> @@ -218,10 +219,9 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message, message << fakeProperties[ii]; } -void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, - QDeclarativeContext *ctxt) +void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt) { - QDeclarativeContextPrivate *p = (QDeclarativeContextPrivate *)QObjectPrivate::get(ctxt); + QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt); QString ctxtName = ctxt->objectName(); int ctxtId = QDeclarativeDebugService::idForObject(ctxt); @@ -230,35 +230,34 @@ void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, int count = 0; - for (QSet<QDeclarativeContext *>::ConstIterator iter = p->childContexts.begin(); - iter != p->childContexts.end(); ++iter) { - QDeclarativeContextPrivate *p = (QDeclarativeContextPrivate *)QObjectPrivate::get(*iter); - if (p->isInternal) - continue; - ++count; + QDeclarativeContextData *child = p->childContexts; + while (child) { + if (!child->isInternal) + ++count; + child = child->nextChild; } message << count; - for (QSet<QDeclarativeContext *>::ConstIterator iter = p->childContexts.begin(); - iter != p->childContexts.end(); ++iter) { - QDeclarativeContextPrivate *p = (QDeclarativeContextPrivate *)QObjectPrivate::get(*iter); - if (p->isInternal) - continue; - buildObjectList(message, *iter); + child = p->childContexts; + while (child) { + if (!child->isInternal) + buildObjectList(message, child->asQDeclarativeContext()); + child = child->nextChild; } // Clean deleted objects - for (int ii = 0; ii < p->instances.count(); ++ii) { - if (!p->instances.at(ii)) { - p->instances.removeAt(ii); + QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt); + for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { + if (!ctxtPriv->instances.at(ii)) { + ctxtPriv->instances.removeAt(ii); --ii; } } - message << p->instances.count(); - for (int ii = 0; ii < p->instances.count(); ++ii) { - message << objectData(p->instances.at(ii)); + message << ctxtPriv->instances.count(); + for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { + message << objectData(ctxtPriv->instances.at(ii)); } } @@ -267,8 +266,8 @@ QDeclarativeEngineDebugServer::objectData(QObject *object) { QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object); QDeclarativeObjectData rv; - if (ddata) { - rv.url = ddata->outerContext->baseUrl(); + if (ddata && ddata->outerContext) { + rv.url = ddata->outerContext->url; rv.lineNumber = ddata->lineNumber; rv.columnNumber = ddata->columnNumber; } else { diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 899f402..9eed345 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -95,11 +95,18 @@ QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate(QDeclarativeExpress QDeclarativeExpressionPrivate::~QDeclarativeExpressionPrivate() { - if (data) { data->q = 0; data->release(); data = 0; } + if (data) { + delete [] data->guardList; + data->guardList = 0; + data->guardListLength = 0; + data->q = 0; + data->release(); + data = 0; + } } -void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, const QString &expr, - QObject *me) +void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr, + QObject *me) { data->expression = expr; @@ -107,8 +114,8 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, const QStrin data->me = me; } -void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, void *expr, QDeclarativeRefCount *rc, - QObject *me, const QString &url, int lineNumber) +void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr, QDeclarativeRefCount *rc, + QObject *me, const QString &url, int lineNumber) { data->url = url; data->line = lineNumber; @@ -127,7 +134,7 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, void *expr, bool isShared = progIdx & 0x80000000; progIdx &= 0x7FFFFFFF; - QDeclarativeEngine *engine = ctxt->engine(); + QDeclarativeEngine *engine = ctxt->engine; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -167,10 +174,10 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, void *expr, data->me = me; } -QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContext *context, QObject *object, +QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object, const QString &program, QScriptValue *contextObject) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine()); + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); if (contextObject) { *contextObject = ep->contextClass->newContext(context, object); @@ -184,10 +191,11 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex return rv; } -QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContext *context, QObject *object, - const QScriptProgram &program, QScriptValue *contextObject) +QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object, + const QScriptProgram &program, + QScriptValue *contextObject) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine()); + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); if (contextObject) { *contextObject = ep->contextClass->newContext(context, object); @@ -219,10 +227,10 @@ QDeclarativeExpression::QDeclarativeExpression() } /*! \internal */ -QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt, void *expr, - QDeclarativeRefCount *rc, QObject *me, - const QString &url, int lineNumber, - QDeclarativeExpressionPrivate &dd) +QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, void *expr, + QDeclarativeRefCount *rc, QObject *me, + const QString &url, int lineNumber, + QDeclarativeExpressionPrivate &dd) : QObject(dd, 0) { Q_D(QDeclarativeExpression); @@ -237,7 +245,18 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt, void * the expression's execution. */ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt, const QString &expression, - QObject *scope) + QObject *scope) +: QObject(*new QDeclarativeExpressionPrivate, 0) +{ + Q_D(QDeclarativeExpression); + d->init(QDeclarativeContextData::get(ctxt), expression, scope); +} + +/*! + \internal +*/ +QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, const QString &expression, + QObject *scope) : QObject(*new QDeclarativeExpressionPrivate, 0) { Q_D(QDeclarativeExpression); @@ -245,8 +264,8 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt, const } /*! \internal */ -QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt, const QString &expression, - QObject *scope, QDeclarativeExpressionPrivate &dd) +QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, const QString &expression, + QObject *scope, QDeclarativeExpressionPrivate &dd) : QObject(dd, 0) { Q_D(QDeclarativeExpression); @@ -267,7 +286,7 @@ QDeclarativeExpression::~QDeclarativeExpression() QDeclarativeEngine *QDeclarativeExpression::engine() const { Q_D(const QDeclarativeExpression); - return d->data->context()?d->data->context()->engine():0; + return d->data->context()?d->data->context()->engine:0; } /*! @@ -277,7 +296,8 @@ QDeclarativeEngine *QDeclarativeExpression::engine() const QDeclarativeContext *QDeclarativeExpression::context() const { Q_D(const QDeclarativeExpression); - return d->data->context(); + QDeclarativeContextData *data = d->data->context(); + return data?data->asQDeclarativeContext():0; } /*! @@ -338,8 +358,7 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo #endif QDeclarativeExpressionData *data = this->data; - QDeclarativeContextPrivate *ctxtPriv = data->context()->d_func(); - QDeclarativeEngine *engine = data->context()->engine(); + QDeclarativeEngine *engine = data->context()->engine; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -370,7 +389,7 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo data->expressionFunctionValid = true; } - QDeclarativeContext *oldSharedContext = 0; + QDeclarativeContextData *oldSharedContext = 0; QObject *oldSharedScope = 0; QObject *oldOverride = 0; if (data->isShared) { @@ -622,137 +641,96 @@ void QDeclarativeExpression::__q_notify() void QDeclarativeExpressionPrivate::clearGuards() { - Q_Q(QDeclarativeExpression); - - static int notifyIdx = -1; - if (notifyIdx == -1) - notifyIdx = - QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()"); - - for (int ii = 0; ii < data->guardListLength; ++ii) { - if (data->guardList[ii].data()) { -#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) - QMetaObject::disconnectOne(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); -#else - // QTBUG-6781 - QMetaObject::disconnect(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); -#endif - } - } - - delete [] data->guardList; data->guardList = 0; + delete [] data->guardList; + data->guardList = 0; data->guardListLength = 0; } void QDeclarativeExpressionPrivate::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties) { - //clearGuards(); Q_Q(QDeclarativeExpression); static int notifyIdx = -1; if (notifyIdx == -1) - notifyIdx = - QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()"); + notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()"); - QDeclarativeExpressionData::SignalGuard *newGuardList = 0; - - if (properties.count() != data->guardListLength) - newGuardList = new QDeclarativeExpressionData::SignalGuard[properties.count()]; + if (properties.count() != data->guardListLength) { + QDeclarativeNotifierEndpoint *newGuardList = + new QDeclarativeNotifierEndpoint[properties.count()]; + + for (int ii = 0; ii < qMin(data->guardListLength, properties.count()); ++ii) + data->guardList[ii].copyAndClear(newGuardList[ii]); + + delete [] data->guardList; + data->guardList = newGuardList; + data->guardListLength = properties.count(); + } bool outputWarningHeader = false; - int hit = 0; + bool noChanges = true; for (int ii = 0; ii < properties.count(); ++ii) { + QDeclarativeNotifierEndpoint &guard = data->guardList[ii]; const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii); - bool needGuard = true; - if (ii >= data->guardListLength) { - // New guard - } else if(data->guardList[ii].data() == property.object && - data->guardList[ii].notifyIndex == property.notifyIndex) { - // Cache hit - if (!data->guardList[ii].isDuplicate || - (data->guardList[ii].isDuplicate && hit == ii)) { - needGuard = false; - ++hit; - } - } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { - // Cache miss -#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) - QMetaObject::disconnectOne(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); -#else - // QTBUG-6781 - QMetaObject::disconnect(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); -#endif - } - /* else { - // Cache miss, but nothing to do - } */ - - if (needGuard) { - if (!newGuardList) { - newGuardList = new QDeclarativeExpressionData::SignalGuard[properties.count()]; - for (int jj = 0; jj < ii; ++jj) - newGuardList[jj] = data->guardList[jj]; - } + guard.target = q; + guard.targetMethod = notifyIdx; + + if (property.notifier != 0) { + + if (!noChanges && guard.isConnected(property.notifier)) { + // Nothing to do + + } else { + noChanges = false; - if (property.notifyIndex != -1) { bool existing = false; for (int jj = 0; !existing && jj < ii; ++jj) - existing = newGuardList[jj].data() == property.object && - newGuardList[jj].notifyIndex == property.notifyIndex; - - newGuardList[ii] = property.object; - newGuardList[ii].notifyIndex = property.notifyIndex; - if (existing) - newGuardList[ii].isDuplicate = true; - else - QMetaObject::connect(property.object, property.notifyIndex, - q, notifyIdx); - } else { - if (!outputWarningHeader) { - outputWarningHeader = true; - qWarning() << "QDeclarativeExpression: Expression" << q->expression() - << "depends on non-NOTIFYable properties:"; + if (data->guardList[jj].isConnected(property.notifier)) + existing = true; + + if (existing) { + // duplicate + guard.disconnect(); + } else { + guard.connect(property.notifier); } + } - const QMetaObject *metaObj = property.object->metaObject(); - QMetaProperty metaProp = metaObj->property(property.coreIndex); - qWarning().nospace() << " " << metaObj->className() - << "::" << metaProp.name(); + } else if (property.notifyIndex != -1) { + + if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) { + // Nothing to do + + } else { + noChanges = false; + + bool existing = false; + for (int jj = 0; !existing && jj < ii; ++jj) + if (data->guardList[jj].isConnected(property.object, property.notifyIndex)) + existing = true; + + if (existing) { + // duplicate + guard.disconnect(); + } else { + guard.connect(property.object, property.notifyIndex); + } + } + + } else { + if (!outputWarningHeader) { + outputWarningHeader = true; + qWarning() << "QDeclarativeExpression: Expression" << q->expression() + << "depends on non-NOTIFYable properties:"; } - } else if (newGuardList) { - newGuardList[ii] = data->guardList[ii]; - } - } - for (int ii = properties.count(); ii < data->guardListLength; ++ii) { - if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { -#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) - QMetaObject::disconnectOne(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); -#else - // QTBUG-6781 - QMetaObject::disconnect(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); -#endif - } - } + const QMetaObject *metaObj = property.object->metaObject(); + QMetaProperty metaProp = metaObj->property(property.coreIndex); - if (newGuardList) { - if (data->guardList) delete [] data->guardList; - data->guardList = newGuardList; - data->guardListLength = properties.count(); + qWarning().nospace() << " " << metaObj->className() + << "::" << metaProp.name(); + } } } @@ -784,12 +762,12 @@ QDeclarativeAbstractExpression::~QDeclarativeAbstractExpression() } } -QDeclarativeContext *QDeclarativeAbstractExpression::context() const +QDeclarativeContextData *QDeclarativeAbstractExpression::context() const { return m_context; } -void QDeclarativeAbstractExpression::setContext(QDeclarativeContext *context) +void QDeclarativeAbstractExpression::setContext(QDeclarativeContextData *context) { if (m_prevExpression) { *m_prevExpression = m_nextExpression; @@ -802,13 +780,11 @@ void QDeclarativeAbstractExpression::setContext(QDeclarativeContext *context) m_context = context; if (m_context) { - QDeclarativeContextPrivate *cp = - static_cast<QDeclarativeContextPrivate *>(QObjectPrivate::get(m_context)); - m_nextExpression = cp->expressions; + m_nextExpression = m_context->expressions; if (m_nextExpression) m_nextExpression->m_prevExpression = &m_nextExpression; - m_prevExpression = &cp->expressions; - cp->expressions = this; + m_prevExpression = &context->expressions; + m_context->expressions = this; } } diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h index 911d328..73a5793 100644 --- a/src/declarative/qml/qdeclarativeexpression.h +++ b/src/declarative/qml/qdeclarativeexpression.h @@ -58,6 +58,7 @@ class QDeclarativeRefCount; class QDeclarativeEngine; class QDeclarativeContext; class QDeclarativeExpressionPrivate; +class QDeclarativeContextData; class Q_DECLARATIVE_EXPORT QDeclarativeExpression : public QObject { Q_OBJECT @@ -91,18 +92,21 @@ Q_SIGNALS: void valueChanged(); protected: - QDeclarativeExpression(QDeclarativeContext *, const QString &, QObject *, - QDeclarativeExpressionPrivate &dd); - QDeclarativeExpression(QDeclarativeContext *, void *, QDeclarativeRefCount *rc, QObject *me, const QString &, - int, QDeclarativeExpressionPrivate &dd); + QDeclarativeExpression(QDeclarativeContextData *, const QString &, QObject *, + QDeclarativeExpressionPrivate &dd); + QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc, + QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd); private Q_SLOTS: void __q_notify(); private: + QDeclarativeExpression(QDeclarativeContextData *, const QString &, QObject *); + Q_DECLARE_PRIVATE(QDeclarativeExpression) friend class QDeclarativeDebugger; friend class QDeclarativeContext; + friend class QDeclarativeVME; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h index cd1729d..5adaa89 100644 --- a/src/declarative/qml/qdeclarativeexpression_p.h +++ b/src/declarative/qml/qdeclarativeexpression_p.h @@ -70,15 +70,16 @@ public: bool isValid() const; - QDeclarativeContext *context() const; - void setContext(QDeclarativeContext *); + QDeclarativeContextData *context() const; + void setContext(QDeclarativeContextData *); virtual void refresh(); private: friend class QDeclarativeContext; + friend class QDeclarativeContextData; friend class QDeclarativeContextPrivate; - QDeclarativeContext *m_context; + QDeclarativeContextData *m_context; QDeclarativeAbstractExpression **m_prevExpression; QDeclarativeAbstractExpression *m_nextExpression; }; @@ -129,24 +130,7 @@ public: QString url; // This is a QString for a reason. QUrls are slooooooow... int line; - struct SignalGuard : public QDeclarativeGuard<QObject> { - SignalGuard() : isDuplicate(false), notifyIndex(-1) {} - - SignalGuard &operator=(QObject *obj) { - QDeclarativeGuard<QObject>::operator=(obj); - return *this; - } - SignalGuard &operator=(const SignalGuard &o) { - QDeclarativeGuard<QObject>::operator=(o); - isDuplicate = o.isDuplicate; - notifyIndex = o.notifyIndex; - return *this; - } - - bool isDuplicate:1; - int notifyIndex:31; - }; - SignalGuard *guardList; + QDeclarativeNotifierEndpoint *guardList; int guardListLength; }; @@ -160,8 +144,8 @@ public: QDeclarativeExpressionPrivate(QDeclarativeExpressionData *); ~QDeclarativeExpressionPrivate(); - void init(QDeclarativeContext *, const QString &, QObject *); - void init(QDeclarativeContext *, void *, QDeclarativeRefCount *, QObject *, const QString &, int); + void init(QDeclarativeContextData *, const QString &, QObject *); + void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int); QDeclarativeExpressionData *data; @@ -181,8 +165,8 @@ public: virtual void emitValueChanged(); static void exceptionToError(QScriptEngine *, QDeclarativeError &); - static QScriptValue evalInObjectScope(QDeclarativeContext *, QObject *, const QString &, QScriptValue * = 0); - static QScriptValue evalInObjectScope(QDeclarativeContext *, QObject *, const QScriptProgram &, QScriptValue * = 0); + static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, QScriptValue * = 0); + static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &, QScriptValue * = 0); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinfo.cpp b/src/declarative/qml/qdeclarativeinfo.cpp index 7dc61fd..5146bb6 100644 --- a/src/declarative/qml/qdeclarativeinfo.cpp +++ b/src/declarative/qml/qdeclarativeinfo.cpp @@ -43,6 +43,7 @@ #include "qdeclarativedeclarativedata_p.h" #include "qdeclarativecontext.h" +#include "qdeclarativecontext_p.h" #include "qdeclarativemetatype_p.h" #include <QCoreApplication> @@ -102,8 +103,8 @@ QDeclarativeInfo::QDeclarativeInfo(const QObject *object) QDeclarativeDeclarativeData *ddata = object?QDeclarativeDeclarativeData::get(object):0; pos += QLatin1String(" ("); if (ddata) { - if (ddata->outerContext) { - pos += ddata->outerContext->baseUrl().toString(); + if (ddata->outerContext && !ddata->outerContext->url.isEmpty()) { + pos += ddata->outerContext->url.toString(); pos += QLatin1Char(':'); pos += QString::number(ddata->lineNumber); pos += QLatin1Char(':'); diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index cf485fe..a23ff75 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -90,7 +90,7 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); break; case QDeclarativeInstruction::StoreUrl: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << primitives.at(instr->storeUrl.value); + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value); break; case QDeclarativeInstruction::StoreColor: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16); diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 50ab56b..b32e575 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -124,7 +124,10 @@ public: int m_version_maj; int m_version_min; int m_typeId; int m_listId; - QObject *(*m_newFunc)(); + + int m_allocationSize; + void (*m_newFunc)(void *); + const QMetaObject *m_baseMetaObject; QDeclarativeAttachedPropertiesFunc m_attachedPropertiesFunc; const QMetaObject *m_attachedPropertiesType; @@ -141,7 +144,7 @@ public: QDeclarativeTypePrivate::QDeclarativeTypePrivate() : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), - m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), + m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) { @@ -174,6 +177,7 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe d->m_version_min = type.versionMinor; d->m_typeId = type.typeId; d->m_listId = type.listId; + d->m_allocationSize = type.objectSize; d->m_newFunc = type.create; d->m_baseMetaObject = type.metaObject; d->m_attachedPropertiesFunc = type.attachedPropertiesFunction; @@ -274,13 +278,29 @@ QObject *QDeclarativeType::create() const { d->init(); - QObject *rv = d->m_newFunc(); + QObject *rv = (QObject *)operator new(d->m_allocationSize); + d->m_newFunc(rv); + if (rv && !d->m_metaObjects.isEmpty()) (void *)new QDeclarativeProxyMetaObject(rv, &d->m_metaObjects); return rv; } +void QDeclarativeType::create(QObject **out, void **memory, size_t additionalMemory) const +{ + d->init(); + + QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory); + d->m_newFunc(rv); + + if (rv && !d->m_metaObjects.isEmpty()) + (void *)new QDeclarativeProxyMetaObject(rv, &d->m_metaObjects); + + *out = rv; + *memory = ((char *)rv) + d->m_allocationSize; +} + QDeclarativeCustomParser *QDeclarativeType::customParser() const { return d->m_customParser; diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index cf8946d..1a36f10 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -111,6 +111,7 @@ public: bool availableInVersion(int vmajor, int vminor) const; QObject *create() const; + void create(QObject **, void **, size_t) const; QDeclarativeCustomParser *customParser() const; diff --git a/src/declarative/qml/qdeclarativenotifier.cpp b/src/declarative/qml/qdeclarativenotifier.cpp new file mode 100644 index 0000000..b12bf77 --- /dev/null +++ b/src/declarative/qml/qdeclarativenotifier.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** 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 "qdeclarativenotifier_p.h" + +QT_BEGIN_NAMESPACE + +void QDeclarativeNotifier::emitNotify(QDeclarativeNotifierEndpoint *endpoint) +{ + QDeclarativeNotifierEndpoint::Notifier *n = endpoint->asNotifier(); + + QDeclarativeNotifierEndpoint **oldDisconnected = n->disconnected; + n->disconnected = &endpoint; + + if (n->next) + emitNotify(n->next); + + if (endpoint) { + void *args[] = { 0 }; + + QMetaObject::metacall(endpoint->target, QMetaObject::InvokeMetaMethod, + endpoint->targetMethod, args); + + if (endpoint) + endpoint->asNotifier()->disconnected = oldDisconnected; + } + + if (oldDisconnected) *oldDisconnected = endpoint; +} + +void QDeclarativeNotifierEndpoint::copyAndClear(QDeclarativeNotifierEndpoint &other) +{ + other.disconnect(); + + other.target = target; + other.targetMethod = targetMethod; + + if (!isConnected()) + return; + + if (SignalType == type) { + Signal *other_s = other.toSignal(); + Signal *s = asSignal(); + + other_s->source = s->source; + other_s->sourceSignal = s->sourceSignal; + s->source = 0; + } else if(NotifierType == type) { + Notifier *other_n = other.toNotifier(); + Notifier *n = asNotifier(); + + other_n->notifier = n->notifier; + other_n->disconnected = n->disconnected; + if (other_n->disconnected) *other_n->disconnected = &other; + + if (n->next) { + other_n->next = n->next; + n->next->asNotifier()->prev = &other_n->next; + } + other_n->prev = n->prev; + *other_n->prev = &other; + + n->prev = 0; + n->next = 0; + n->disconnected = 0; + n->notifier = 0; + } +} + + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qdeclarativenotifier_p.h b/src/declarative/qml/qdeclarativenotifier_p.h new file mode 100644 index 0000000..2a9660d --- /dev/null +++ b/src/declarative/qml/qdeclarativenotifier_p.h @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** 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 QDECLARATIVENOTIFIER_P_H +#define QDECLARATIVENOTIFIER_P_H + +#include "qdeclarativeguard_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeNotifierEndpoint; +class QDeclarativeNotifier +{ +public: + inline QDeclarativeNotifier(); + inline ~QDeclarativeNotifier(); + inline void notify(); + +private: + friend class QDeclarativeNotifierEndpoint; + + static void emitNotify(QDeclarativeNotifierEndpoint *); + QDeclarativeNotifierEndpoint *endpoints; +}; + +class QDeclarativeNotifierEndpoint +{ +public: + inline QDeclarativeNotifierEndpoint(); + inline QDeclarativeNotifierEndpoint(QObject *t, int m); + inline ~QDeclarativeNotifierEndpoint(); + + QObject *target; + int targetMethod; + + inline bool isConnected(); + inline bool isConnected(QObject *source, int sourceSignal); + inline bool isConnected(QDeclarativeNotifier *); + + inline void connect(QObject *source, int sourceSignal); + inline void connect(QDeclarativeNotifier *); + inline void disconnect(); + + void copyAndClear(QDeclarativeNotifierEndpoint &other); + +private: + friend class QDeclarativeNotifier; + + struct Signal { + QDeclarativeGuard<QObject> source; + int sourceSignal; + }; + + struct Notifier { + QDeclarativeNotifier *notifier; + QDeclarativeNotifierEndpoint **disconnected; + + QDeclarativeNotifierEndpoint *next; + QDeclarativeNotifierEndpoint **prev; + }; + + enum { InvalidType, SignalType, NotifierType } type; + union { + char signalData[sizeof(Signal)]; + char notifierData[sizeof(Notifier)]; + }; + + inline Notifier *toNotifier(); + inline Notifier *asNotifier(); + inline Signal *toSignal(); + inline Signal *asSignal(); +}; + +QDeclarativeNotifier::QDeclarativeNotifier() +: endpoints(0) +{ +} + +QDeclarativeNotifier::~QDeclarativeNotifier() +{ + QDeclarativeNotifierEndpoint *endpoint = endpoints; + while (endpoint) { + QDeclarativeNotifierEndpoint::Notifier *n = endpoint->asNotifier(); + endpoint = n->next; + + n->next = 0; + n->prev = 0; + n->notifier = 0; + if (n->disconnected) *n->disconnected = 0; + n->disconnected = 0; + } + endpoints = 0; +} + +void QDeclarativeNotifier::notify() +{ + if (endpoints) emitNotify(endpoints); +} + +QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint() +: target(0), targetMethod(0), type(InvalidType) +{ +} + +QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint(QObject *t, int m) +: target(t), targetMethod(m), type(InvalidType) +{ +} + +QDeclarativeNotifierEndpoint::~QDeclarativeNotifierEndpoint() +{ + disconnect(); + if (SignalType == type) { + Signal *s = asSignal(); + s->~Signal(); + } +} + +bool QDeclarativeNotifierEndpoint::isConnected() +{ + if (SignalType == type) { + return asSignal()->source; + } else if (NotifierType == type) { + return asNotifier()->notifier; + } else { + return false; + } +} + +bool QDeclarativeNotifierEndpoint::isConnected(QObject *source, int sourceSignal) +{ + return SignalType == type && asSignal()->source == source && asSignal()->sourceSignal == sourceSignal; +} + +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(); + + if (n->notifier == notifier) + return; + + disconnect(); + + n->next = notifier->endpoints; + if (n->next) { n->next->asNotifier()->prev = &n->next; } + notifier->endpoints = this; + n->prev = ¬ifier->endpoints; + n->notifier = notifier; +} + +void QDeclarativeNotifierEndpoint::disconnect() +{ + if (type == SignalType) { + Signal *s = (Signal *)&signalData; + if (s->source) { + QMetaObject::disconnectOne(s->source, s->sourceSignal, target, targetMethod); + s->source = 0; + } + } else if (type == NotifierType) { + Notifier *n = asNotifier(); + + if (n->next) n->next->asNotifier()->prev = n->prev; + if (n->prev) *n->prev = n->next; + if (n->disconnected) *n->disconnected = 0; + n->next = 0; + n->prev = 0; + n->disconnected = 0; + n->notifier = 0; + } +} + +QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::toNotifier() +{ + if (NotifierType == type) + return asNotifier(); + + if (SignalType == type) { + disconnect(); + Signal *s = asSignal(); + s->~Signal(); + } + + Notifier *n = asNotifier(); + n->next = 0; + n->prev = 0; + n->disconnected = 0; + n->notifier = 0; + type = NotifierType; + return n; +} + +QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::asNotifier() +{ + return (Notifier *)(¬ifierData); +} + +QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::toSignal() +{ + if (SignalType == type) + return asSignal(); + + disconnect(); + Signal *s = asSignal(); + new (s) Signal; + type = SignalType; + + return s; +} + +QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::asSignal() +{ + return (Signal *)(&signalData); +} + +QT_END_NAMESPACE + +#endif // QDECLARATIVENOTIFIER_P_H + diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index e6f6e5f..027166a 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -59,6 +59,15 @@ QT_BEGIN_NAMESPACE struct ObjectData : public QScriptDeclarativeClass::Object { ObjectData(QObject *o, int t) : object(o), type(t) {} + + virtual ~ObjectData() { + if (object && !object->parent()) { + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, false); + if (ddata && !ddata->indestructible) + object->deleteLater(); + } + } + QDeclarativeGuard<QObject> object; int type; }; @@ -87,7 +96,7 @@ QDeclarativeObjectScriptClass::~QDeclarativeObjectScriptClass() { } -QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type) +QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -96,7 +105,11 @@ QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, true); - if (!ddata->scriptValue.isValid()) { + if (!ddata) { + return scriptEngine->undefinedValue(); + } else if (!ddata->indestructible && !object->parent()) { + return newObject(scriptEngine, this, new ObjectData(object, type)); + } else if (!ddata->scriptValue.isValid()) { ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object, type)); return ddata->scriptValue; } else if (ddata->scriptValue.engine() == QDeclarativeEnginePrivate::getScriptEngine(engine)) { @@ -129,7 +142,7 @@ QDeclarativeObjectScriptClass::queryProperty(Object *object, const Identifier &n QScriptClass::QueryFlags QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, - QScriptClass::QueryFlags flags, QDeclarativeContext *evalContext, + QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext, QueryHints hints) { Q_UNUSED(flags); @@ -160,15 +173,11 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam } } - if (evalContext) { - QDeclarativeContextPrivate *cp = QDeclarativeContextPrivate::get(evalContext); - - if (cp->imports) { - QDeclarativeTypeNameCache::Data *data = cp->imports->data(name); - if (data) { - lastTNData = data; - return QScriptClass::HandlesReadAccess; - } + if (evalContext && evalContext->imports) { + QDeclarativeTypeNameCache::Data *data = evalContext->imports->data(name); + if (data) { + lastTNData = data; + return QScriptClass::HandlesReadAccess; } } } @@ -303,7 +312,7 @@ void QDeclarativeObjectScriptClass::setProperty(Object *object, void QDeclarativeObjectScriptClass::setProperty(QObject *obj, const Identifier &name, const QScriptValue &value, - QDeclarativeContext *evalContext) + QDeclarativeContextData *evalContext) { Q_UNUSED(name); @@ -338,7 +347,8 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, } } - QDeclarativeAbstractBinding *delBinding = QDeclarativePropertyPrivate::setBinding(obj, *lastData, 0); + QDeclarativeAbstractBinding *delBinding = + QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, 0); if (delBinding) delBinding->destroy(); @@ -392,17 +402,30 @@ QScriptValue QDeclarativeObjectScriptClass::tostring(QScriptContext *context, QS QScriptValue QDeclarativeObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine) { - QObject* obj = context->thisObject().toQObject(); - if(obj){ - int delay = 0; - if(context->argumentCount() > 0) - delay = context->argument(0).toInt32(); - if (delay > 0) - QTimer::singleShot(delay, obj, SLOT(deleteLater())); - else - obj->deleteLater(); - } - return engine->nullValue(); + QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); + QScriptValue that = context->thisObject(); + + if (scriptClass(that) != p->objectClass) + return engine->undefinedValue(); + + ObjectData *data = (ObjectData *)p->objectClass->object(that); + if (!data->object) + return engine->undefinedValue(); + + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(data->object, false); + if (!ddata || ddata->indestructible) + return engine->currentContext()->throwError(QLatin1String("Invalid attempt to destroy() an indestructible object")); + + QObject *obj = data->object; + int delay = 0; + if (context->argumentCount() > 0) + delay = context->argument(0).toInt32(); + if (delay > 0) + QTimer::singleShot(delay, obj, SLOT(deleteLater())); + else + obj->deleteLater(); + + return engine->undefinedValue(); } QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object) @@ -428,6 +451,14 @@ QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object) return cache->propertyNames(); } +bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2) +{ + ObjectData *d1 = (ObjectData *)o1; + ObjectData *d2 = (ObjectData *)o2; + + return d1 == d2 || d1->object == d2->object; +} + #if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) struct MethodData : public QScriptDeclarativeClass::Object { @@ -441,6 +472,8 @@ QDeclarativeObjectMethodScriptClass::QDeclarativeObjectMethodScriptClass(QDeclar : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) { + qRegisterMetaType<QList<QObject *> >("QList<QObject *>"); + setSupportsCall(true); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -551,7 +584,7 @@ private: inline void cleanup(); - char *data[16]; + void *data[4]; int type; }; } @@ -569,11 +602,13 @@ MetaCallArgument::~MetaCallArgument() void MetaCallArgument::cleanup() { if (type == QMetaType::QString) { - ((QString *)data)->~QString(); + ((QString *)&data)->~QString(); } else if (type == -1 || type == qMetaTypeId<QVariant>()) { - ((QVariant *)data)->~QVariant(); + ((QVariant *)&data)->~QVariant(); } else if (type == qMetaTypeId<QScriptValue>()) { - ((QScriptValue *)data)->~QScriptValue(); + ((QScriptValue *)&data)->~QScriptValue(); + } else if (type == qMetaTypeId<QList<QObject *> >()) { + ((QList<QObject *> *)&data)->~QList<QObject *>(); } } @@ -582,7 +617,7 @@ void *MetaCallArgument::dataPtr() if (type == -1) return ((QVariant *)data)->data(); else - return (void *)data; + return (void *)&data; } void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e) @@ -593,7 +628,7 @@ void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e) QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e); if (callType == qMetaTypeId<QScriptValue>()) { - new (data) QScriptValue(engine->undefinedValue()); + new (&data) QScriptValue(engine->undefinedValue()); type = callType; } else if (callType == QMetaType::Int || callType == QMetaType::UInt || @@ -602,17 +637,20 @@ void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e) callType == QMetaType::Float) { type = callType; } else if (callType == QMetaType::QObjectStar) { - *((QObject **)data) = 0; + *((QObject **)&data) = 0; type = callType; } else if (callType == QMetaType::QString) { - new (data) QString(); + new (&data) QString(); type = callType; } else if (callType == qMetaTypeId<QVariant>()) { - type = qMetaTypeId<QVariant>(); - new (data) QVariant(); + type = callType; + new (&data) QVariant(); + } else if (callType == qMetaTypeId<QList<QObject *> >()) { + type = callType; + new (&data) QList<QObject *>(); } else { type = -1; - new (data) QVariant(callType, (void *)0); + new (&data) QVariant(callType, (void *)0); } } @@ -621,47 +659,50 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, if (type != 0) { cleanup(); type = 0; } if (callType == qMetaTypeId<QScriptValue>()) { - new (data) QScriptValue(value); + new (&data) QScriptValue(value); type = qMetaTypeId<QScriptValue>(); } else if (callType == QMetaType::Int) { - *((int *)data) = int(value.toInt32()); + *((int *)&data) = int(value.toInt32()); type = callType; } else if (callType == QMetaType::UInt) { - *((uint *)data) = uint(value.toUInt32()); + *((uint *)&data) = uint(value.toUInt32()); type = callType; } else if (callType == QMetaType::Bool) { - *((bool *)data) = value.toBool(); + *((bool *)&data) = value.toBool(); type = callType; } else if (callType == QMetaType::Double) { - *((double *)data) = double(value.toNumber()); + *((double *)&data) = double(value.toNumber()); type = callType; } else if (callType == QMetaType::Float) { - *((float *)data) = float(value.toNumber()); + *((float *)&data) = float(value.toNumber()); type = callType; } else if (callType == QMetaType::QString) { if (value.isNull() || value.isUndefined()) - new (data) QString(); + new (&data) QString(); else - new (data) QString(value.toString()); + new (&data) QString(value.toString()); type = callType; } else if (callType == QMetaType::QObjectStar) { - *((QObject **)data) = value.toQObject(); + *((QObject **)&data) = value.toQObject(); type = callType; } else if (callType == qMetaTypeId<QVariant>()) { - new (data) QVariant(QDeclarativeScriptClass::toVariant(engine, value)); + new (&data) QVariant(QDeclarativeScriptClass::toVariant(engine, value)); + type = callType; + } else if (callType == qMetaTypeId<QList<QObject*> >()) { + new (&data) QList<QObject *>(); // We don't support passing in QList<QObject*> type = callType; } else { - new (data) QVariant(); + new (&data) QVariant(); type = -1; QVariant v = QDeclarativeScriptClass::toVariant(engine, value); if (v.userType() == callType) { - *((QVariant *)data) = v; + *((QVariant *)&data) = v; } else if (v.canConvert((QVariant::Type)callType)) { - *((QVariant *)data) = v; - ((QVariant *)data)->convert((QVariant::Type)callType); + *((QVariant *)&data) = v; + ((QVariant *)&data)->convert((QVariant::Type)callType); } else { - *((QVariant *)data) = QVariant(callType, (void *)0); + *((QVariant *)&data) = QVariant(callType, (void *)0); } } } @@ -671,23 +712,36 @@ QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e) QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e); if (type == qMetaTypeId<QScriptValue>()) { - return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)data)); + return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)&data)); } else if (type == QMetaType::Int) { - return QScriptDeclarativeClass::Value(engine, *((int *)data)); + return QScriptDeclarativeClass::Value(engine, *((int *)&data)); } else if (type == QMetaType::UInt) { - return QScriptDeclarativeClass::Value(engine, *((uint *)data)); + return QScriptDeclarativeClass::Value(engine, *((uint *)&data)); } else if (type == QMetaType::Bool) { - return QScriptDeclarativeClass::Value(engine, *((bool *)data)); + return QScriptDeclarativeClass::Value(engine, *((bool *)&data)); } else if (type == QMetaType::Double) { - return QScriptDeclarativeClass::Value(engine, *((double *)data)); + return QScriptDeclarativeClass::Value(engine, *((double *)&data)); } else if (type == QMetaType::Float) { - return QScriptDeclarativeClass::Value(engine, *((float *)data)); + return QScriptDeclarativeClass::Value(engine, *((float *)&data)); } else if (type == QMetaType::QString) { - return QScriptDeclarativeClass::Value(engine, *((QString *)data)); + return QScriptDeclarativeClass::Value(engine, *((QString *)&data)); } else if (type == QMetaType::QObjectStar) { - return QScriptDeclarativeClass::Value(engine, QDeclarativeEnginePrivate::get(e)->objectClass->newQObject(*((QObject **)data))); + QObject *object = *((QObject **)&data); + QDeclarativeDeclarativeData::get(object, true)->setImplicitDestructible(); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e); + return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(object)); + } else if (type == qMetaTypeId<QList<QObject *> >()) { + QList<QObject *> &list = *(QList<QObject *>*)&data; + QScriptValue rv = engine->newArray(list.count()); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e); + for (int ii = 0; ii < list.count(); ++ii) { + QObject *object = list.at(ii); + QDeclarativeDeclarativeData::get(object, true)->setImplicitDestructible(); + rv.setProperty(ii, priv->objectClass->newQObject(object)); + } + return QScriptDeclarativeClass::Value(engine, rv); } else if (type == -1 || type == qMetaTypeId<QVariant>()) { - return QScriptDeclarativeClass::Value(engine, QDeclarativeEnginePrivate::get(e)->scriptValueFromVariant(*((QVariant *)data))); + return QScriptDeclarativeClass::Value(engine, QDeclarativeEnginePrivate::get(e)->scriptValueFromVariant(*((QVariant *)&data))); } else { return QScriptDeclarativeClass::Value(); } diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h index 04e760f..396b782 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h @@ -57,13 +57,14 @@ #include "qdeclarativetypenamecache_p.h" #include <private/qdeclarativescriptclass_p.h> +#include <QtScript/qscriptengine.h> QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QScriptContext; class QScriptEngine; -class QDeclarativeContext; +class QDeclarativeContextData; #if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) class Q_AUTOTEST_EXPORT QDeclarativeObjectMethodScriptClass : public QScriptDeclarativeClass @@ -99,6 +100,7 @@ public: ~QDeclarativeObjectScriptClass(); QScriptValue newQObject(QObject *, int type = QMetaType::QObjectStar); + QObject *toQObject(const QScriptValue &) const; int objectType(const QScriptValue &) const; @@ -110,14 +112,15 @@ public: QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &, QScriptClass::QueryFlags flags, - QDeclarativeContext *evalContext, + QDeclarativeContextData *evalContext, QueryHints hints = 0); ScriptValue property(QObject *, const Identifier &); void setProperty(QObject *, const Identifier &name, const QScriptValue &, - QDeclarativeContext *evalContext = 0); + QDeclarativeContextData *evalContext = 0); virtual QStringList propertyNames(Object *); + virtual bool compare(Object *, Object *); protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index b0599ad..51f1660 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -207,13 +207,14 @@ QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) } QDeclarativeParser::Property::Property() -: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false) +: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false), + isValueTypeSubProperty(false) { } QDeclarativeParser::Property::Property(const QByteArray &n) : parent(0), type(0), index(-1), value(0), name(n), isDefault(false), - isDeferred(false) + isDeferred(false), isValueTypeSubProperty(false) { } diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 5bf4b68..9dfb86b 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -351,6 +351,8 @@ namespace QDeclarativeParser // True if the setting of this property will be deferred. Set by the // QDeclarativeCompiler bool isDeferred; + // True if this property is a value-type psuedo-property + bool isValueTypeSubProperty; LocationSpan location; LocationRange listValueRange; diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h index 01369d4..bebe82c 100644 --- a/src/declarative/qml/qdeclarativeprivate.h +++ b/src/declarative/qml/qdeclarativeprivate.h @@ -73,6 +73,9 @@ namespace QDeclarativePrivate QObject *create() { return new T; } template<typename T> + void createInto(void *memory) { new (memory) T; } + + template<typename T> QObject *createParent(QObject *p) { return new T(p); } template<class From, class To, int N> @@ -172,7 +175,8 @@ namespace QDeclarativePrivate int typeId; int listId; - QObject *(*create)(); + int objectSize; + void (*create)(void *); const char *uri; int versionMajor; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 945d098..caa1acf 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -124,7 +124,7 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeContext *ct : d(new QDeclarativePropertyPrivate) { d->q = this; - d->context = ctxt; + d->context = ctxt?QDeclarativeContextData::get(ctxt):0; d->engine = ctxt?ctxt->engine():0; d->initDefault(obj); } @@ -177,7 +177,7 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QD : d(new QDeclarativePropertyPrivate) { d->q = this; - d->context = ctxt; + d->context = ctxt?QDeclarativeContextData::get(ctxt):0; d->engine = ctxt?ctxt->engine():0; d->initProperty(obj, name); if (!isValid()) { d->object = 0; d->context = 0; d->engine = 0; } @@ -204,7 +204,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name { if (!obj) return; - QDeclarativeTypeNameCache *typeNameCache = context?QDeclarativeContextPrivate::get(context)->imports:0; + QDeclarativeTypeNameCache *typeNameCache = context?context->imports:0; QStringList path = name.split(QLatin1Char('.')); if (path.isEmpty()) return; @@ -494,15 +494,13 @@ QDeclarativeProperty &QDeclarativeProperty::operator=(const QDeclarativeProperty */ bool QDeclarativeProperty::isWritable() const { - QDeclarativeProperty::PropertyTypeCategory category = propertyTypeCategory(); - if (!d->object) return false; - if (category == List) + if (d->core.flags & QDeclarativePropertyCache::Data::IsQList) //list return true; - else if (type() & SignalProperty) + else if (d->core.flags & QDeclarativePropertyCache::Data::IsFunction) //signal handler return false; - else if (d->core.isValid() && d->object) + else if (d->core.isValid()) //normal property return d->core.flags & QDeclarativePropertyCache::Data::IsWritable; else return false; @@ -598,7 +596,6 @@ QMetaMethod QDeclarativeProperty::method() const return QMetaMethod(); } - /*! Returns the binding associated with this property, or 0 if no binding exists. @@ -617,13 +614,18 @@ QDeclarativePropertyPrivate::binding(const QDeclarativeProperty &that) return 0; QDeclarativeAbstractBinding *binding = data->bindings; - while (binding) { - // ### This wont work for value types - if (binding->propertyIndex() == that.d->core.coreIndex) - return binding; + while (binding && binding->propertyIndex() != that.d->core.coreIndex) binding = binding->m_nextBinding; + + if (binding && that.d->valueType.valueTypeCoreIdx != -1) { + if (binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) { + QDeclarativeValueTypeProxyBinding *proxy = static_cast<QDeclarativeValueTypeProxyBinding *>(binding); + + binding = proxy->binding(bindingIndex(that)); + } } - return 0; + + return binding; } /*! @@ -650,36 +652,36 @@ QDeclarativePropertyPrivate::setBinding(const QDeclarativeProperty &that, return 0; } - return that.d->setBinding(that.d->object, that.d->core, newBinding, flags); + return that.d->setBinding(that.d->object, that.d->core.coreIndex, + that.d->valueType.valueTypeCoreIdx, newBinding, flags); } QDeclarativeAbstractBinding * -QDeclarativePropertyPrivate::setBinding(QObject *object, const QDeclarativePropertyCache::Data &core, - QDeclarativeAbstractBinding *newBinding, WriteFlags flags) +QDeclarativePropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex, + QDeclarativeAbstractBinding *newBinding, WriteFlags flags) { QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(object, 0 != newBinding); + QDeclarativeAbstractBinding *binding = 0; - if (data && data->hasBindingBit(core.coreIndex)) { - QDeclarativeAbstractBinding *binding = data->bindings; - while (binding) { - // ### This wont work for value types - if (binding->propertyIndex() == core.coreIndex) { - binding->setEnabled(false); + if (data && data->hasBindingBit(coreIndex)) { + binding = data->bindings; - if (newBinding) - newBinding->setEnabled(true, flags); + while (binding && binding->propertyIndex() != coreIndex) + binding = binding->m_nextBinding; + } - return binding; // ### QDeclarativeAbstractBinding; - } + if (binding && valueTypeIndex != -1 && binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) { + int index = coreIndex | (valueTypeIndex << 24); + binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); + } - binding = binding->m_nextBinding; - } - } + if (binding) + binding->setEnabled(false); - if (newBinding) + if (newBinding) newBinding->setEnabled(true, flags); - return 0; + return binding; } /*! @@ -922,7 +924,7 @@ bool QDeclarativePropertyPrivate::writeValueProperty(const QVariant &value, Writ } bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePropertyCache::Data &property, - const QVariant &value, QDeclarativeContext *context, + const QVariant &value, QDeclarativeContextData *context, WriteFlags flags) { int coreIdx = property.coreIndex; @@ -1253,6 +1255,18 @@ int QDeclarativePropertyPrivate::valueTypeCoreIndex(const QDeclarativeProperty & return that.d->valueType.valueTypeCoreIdx; } +/*! + Returns the "property index" for use in bindings. The top 8 bits are the value type + offset, and 0 otherwise. The bottom 24-bits are the regular property index. +*/ +int QDeclarativePropertyPrivate::bindingIndex(const QDeclarativeProperty &that) +{ + int rv = that.d->core.coreIndex; + if (rv != -1 && that.d->valueType.valueTypeCoreIdx != -1) + rv = rv | (that.d->valueType.valueTypeCoreIdx << 24); + return rv; +} + struct SerializedData { bool isValueType; QDeclarativePropertyCache::Data core; @@ -1291,7 +1305,7 @@ QByteArray QDeclarativePropertyPrivate::saveProperty(const QMetaObject *metaObje } QDeclarativeProperty -QDeclarativePropertyPrivate::restore(const QByteArray &data, QObject *object, QDeclarativeContext *ctxt) +QDeclarativePropertyPrivate::restore(const QByteArray &data, QObject *object, QDeclarativeContextData *ctxt) { QDeclarativeProperty prop; @@ -1300,7 +1314,7 @@ QDeclarativePropertyPrivate::restore(const QByteArray &data, QObject *object, QD prop.d->object = object; prop.d->context = ctxt; - prop.d->engine = ctxt?ctxt->engine():0; + prop.d->engine = ctxt->engine; const SerializedData *sd = (const SerializedData *)data.constData(); if (sd->isValueType) { diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index c31e2d3..1bbee64 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -82,7 +82,7 @@ public: valueType(other.valueType) {} QDeclarativeProperty *q; - QDeclarativeContext *context; + QDeclarativeContextData *context; QDeclarativeEngine *engine; QDeclarativeGuard<QObject> object; @@ -109,15 +109,15 @@ public: static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags); static bool write(QObject *, const QDeclarativePropertyCache::Data &, const QVariant &, - QDeclarativeContext *, WriteFlags flags = 0); - static QDeclarativeAbstractBinding *setBinding(QObject *, const QDeclarativePropertyCache::Data &, + QDeclarativeContextData *, WriteFlags flags = 0); + static QDeclarativeAbstractBinding *setBinding(QObject *, int coreIndex, int valueTypeIndex /* -1 */, QDeclarativeAbstractBinding *, WriteFlags flags = DontRemoveBinding); static QByteArray saveValueType(const QMetaObject *, int, const QMetaObject *, int); static QByteArray saveProperty(const QMetaObject *, int); - static QDeclarativeProperty restore(const QByteArray &, QObject *, QDeclarativeContext *); + static QDeclarativeProperty restore(const QByteArray &, QObject *, QDeclarativeContextData *); static bool equal(const QMetaObject *, const QMetaObject *); static bool canConvert(const QMetaObject *from, const QMetaObject *to); @@ -133,6 +133,7 @@ public: QDeclarativeExpression *) ; static bool write(const QDeclarativeProperty &that, const QVariant &, WriteFlags); static int valueTypeCoreIndex(const QDeclarativeProperty &that); + static int bindingIndex(const QDeclarativeProperty &that); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyPrivate::WriteFlags) diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 68e6e6b..bfbeff4 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -55,15 +55,16 @@ #include "qdeclarativerefcount_p.h" #include "qdeclarativecleanup_p.h" +#include "qdeclarativenotifier_p.h" #include <QtCore/qvector.h> #include <QtScript/private/qscriptdeclarativeclass_p.h> - QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QMetaProperty; + class QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup { public: @@ -83,9 +84,9 @@ public: IsResettable = 0x00000004, // These are mutualy exclusive - IsFunction = 0x00000008, - IsQObjectDerived = 0x00000010, - IsEnumType = 0x00000020, + IsFunction = 0x00000010, + IsQObjectDerived = 0x00000020, + IsEnumType = 0x00000040, IsQList = 0x00000080, IsQmlBinding = 0x00000100, IsQScriptValue = 0x00000200, @@ -96,7 +97,7 @@ public: }; Q_DECLARE_FLAGS(Flags, Flag) - + bool isValid() const { return coreIndex != -1; } Flags flags; @@ -114,9 +115,9 @@ public: struct ValueTypeData { inline ValueTypeData(); inline bool operator==(const ValueTypeData &); - Data::Flags flags; // flags on the value type wrapper - int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper - int valueTypePropType; // The QVariant::Type of access property on the value type wrapper + Data::Flags flags; // flags of the access property on the value type proxy object + int valueTypeCoreIdx; // The prop index of the access property on the value type proxy object + int valueTypePropType; // The QVariant::Type of access property on the value type proxy object }; void update(QDeclarativeEngine *, const QMetaObject *); diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index c070123..00e6704 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -61,7 +61,7 @@ int qmlRegisterValueTypeEnums(const char *qmlName) QDeclarativePrivate::RegisterType type = { 0, - qRegisterMetaType<T *>(pointerName.constData()), 0, 0, + qRegisterMetaType<T *>(pointerName.constData()), 0, 0, 0, "Qt", 4, 6, qmlName, &T::staticMetaObject, diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index 9cb65f8..a567c38 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -41,6 +41,8 @@ #include "qdeclarativevaluetypescriptclass_p.h" +#include "qdeclarativebinding_p.h" +#include "qdeclarativeproperty_p.h" #include "qdeclarativeengine_p.h" #include "qdeclarativeguard_p.h" @@ -115,6 +117,11 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier { QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj); + QDeclarativeAbstractBinding *delBinding = + QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, 0); + if (delBinding) + delBinding->destroy(); + QVariant v = QDeclarativeScriptClass::toVariant(engine, value); ref->type->read(ref->object, ref->property); diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 6a08674..4457404 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -100,9 +100,8 @@ struct ListInstance QDeclarativeListProperty<void> qListProperty; }; -QObject *QDeclarativeVME::run(QDeclarativeContext *ctxt, QDeclarativeCompiledData *comp, - int start, int count, - const QBitField &bindingSkipList) +QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, + int start, int count, const QBitField &bindingSkipList) { QDeclarativeVMEStack<QObject *> stack; @@ -119,7 +118,7 @@ void QDeclarativeVME::runDeferred(QObject *object) if (!data || !data->context || !data->deferredComponent) return; - QDeclarativeContext *ctxt = data->context; + QDeclarativeContextData *ctxt = data->context; QDeclarativeCompiledData *comp = data->deferredComponent; int start = data->deferredIdx + 1; int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount; @@ -129,10 +128,11 @@ void QDeclarativeVME::runDeferred(QObject *object) run(stack, ctxt, comp, start, count, QBitField()); } -QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarativeContext *ctxt, - QDeclarativeCompiledData *comp, - int start, int count, - const QBitField &bindingSkipList) +QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, + QDeclarativeContextData *ctxt, + QDeclarativeCompiledData *comp, + int start, int count, + const QBitField &bindingSkipList) { Q_ASSERT(comp); Q_ASSERT(ctxt); @@ -152,8 +152,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati QDeclarativeVMEStack<ListInstance> qliststack; vmeErrors.clear(); - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine()); - QDeclarativeContextPrivate *cp = (QDeclarativeContextPrivate *)QObjectPrivate::get(ctxt); + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); int status = -1; //for dbus QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor; @@ -169,9 +168,9 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati if (instr.init.parserStatusSize) parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize); if (instr.init.contextCache != -1) - cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); + ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); if (instr.init.compiledBinding != -1) - cp->optimizedBindings = new QDeclarativeCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); + ctxt->optimizedBindings = new QDeclarativeCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); } break; @@ -188,6 +187,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati QObject *o = types.at(instr.create.type).createInstance(ctxt, bindings); + if (!o) { if(types.at(instr.create.type).component) vmeErrors << types.at(instr.create.type).component->errors(); @@ -197,6 +197,25 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(o); Q_ASSERT(ddata); + + if (stack.isEmpty()) { + if (ddata->context) { + Q_ASSERT(ddata->context != ctxt); + Q_ASSERT(ddata->outerContext); + Q_ASSERT(ddata->outerContext != ctxt); + QDeclarativeContextData *c = ddata->context; + while (c->linkedContext) c = c->linkedContext; + c->linkedContext = ctxt; + } else { + ctxt->addObject(o); + } + + ddata->ownContext = true; + } else if (!ddata->context) { + ctxt->addObject(o); + } + + ddata->setImplicitDestructible(); ddata->outerContext = ctxt; ddata->lineNumber = instr.line; ddata->columnNumber = instr.create.column; @@ -228,25 +247,31 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati case QDeclarativeInstruction::SetId: { QObject *target = stack.top(); - cp->setIdProperty(instr.setId.index, target); + ctxt->setIdProperty(instr.setId.index, target); } break; case QDeclarativeInstruction::SetDefault: { - QObject *target = stack.top(); - ctxt->addDefaultObject(target); + ctxt->contextObject = stack.top(); } break; case QDeclarativeInstruction::CreateComponent: { - QObject *qcomp = new QDeclarativeComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top()); + QObject *qcomp = new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count, + stack.isEmpty() ? 0 : stack.top()); - QDeclarativeEngine::setContextForObject(qcomp, ctxt); - QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(qcomp); + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(qcomp, true); Q_ASSERT(ddata); + + ctxt->addObject(qcomp); + + if (stack.isEmpty()) + ddata->ownContext = true; + + ddata->setImplicitDestructible(); ddata->outerContext = ctxt; ddata->lineNumber = instr.line; ddata->columnNumber = instr.create.column; @@ -553,7 +578,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati case QDeclarativeInstruction::StoreScript: { QObject *target = stack.top(); - cp->addScript(scripts.at(instr.storeScript.value), target); + ctxt->addScript(scripts.at(instr.storeScript.value), target); } break; @@ -562,7 +587,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati QObject *target = stack.top(); QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope); QDeclarativeScriptString ss; - ss.setContext(ctxt); + ss.setContext(ctxt->asQDeclarativeContext()); ss.setScopeObject(scope); ss.setScript(primitives.at(instr.storeScriptString.value)); @@ -618,7 +643,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati break; QDeclarativeAbstractBinding *binding = - cp->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property); + ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property); bindValues.append(binding); binding->m_mePtr = &bindValues.values[bindValues.count - 1]; binding->addToObject(target); @@ -819,7 +844,9 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati if (isError()) { if (!stack.isEmpty()) { - delete stack.at(0); + delete stack.at(0); // ### What about failures in deferred creation? + } else { + ctxt->destroy(); } QDeclarativeEnginePrivate::clear(bindValues); @@ -832,11 +859,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati if (parserStatus.count) ep->parserStatus << parserStatus; - if (stack.isEmpty()) - return 0; - else - return stack.top(); - return 0; + Q_ASSERT(stack.count() == 1); + return stack.top(); } bool QDeclarativeVME::isError() const @@ -849,4 +873,25 @@ QList<QDeclarativeError> QDeclarativeVME::errors() const return vmeErrors; } +QObject * +QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt, + const QBitField &bindings) const +{ + if (type) { + QObject *rv = 0; + void *memory = 0; + + type->create(&rv, &memory, sizeof(QDeclarativeDeclarativeData)); + QDeclarativeDeclarativeData *ddata = new (memory) QDeclarativeDeclarativeData; + ddata->ownMemory = false; + QObjectPrivate::get(rv)->declarativeData = ddata; + + return rv; + } else { + Q_ASSERT(component); + return QDeclarativeComponentPrivate::get(component)->create(ctxt, bindings); + } +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h index 951f6a7..1c6fd3c 100644 --- a/src/declarative/qml/qdeclarativevme_p.h +++ b/src/declarative/qml/qdeclarativevme_p.h @@ -65,13 +65,13 @@ class QObject; class QDeclarativeInstruction; class QDeclarativeCompiledData; class QDeclarativeCompiledData; -class QDeclarativeContext; +class QDeclarativeContextData; template<typename T, int N = 128> class QDeclarativeVMEStack { public: - QDeclarativeVMEStack() : index(-1), maxSize(N), data(fixedData) {} - ~QDeclarativeVMEStack() { if (data != fixedData) qFree(fixedData); } + QDeclarativeVMEStack() : index(-1), maxSize(N), data((T *)fixedData) {} + ~QDeclarativeVMEStack() { if (data != (T *)fixedData) qFree(data); } bool isEmpty() const { return index == -1; } const T &top() const { return data[index]; } @@ -83,7 +83,7 @@ public: private: void realloc() { maxSize += N; - if (data != fixedData) { + if (data != (T *)fixedData) { data = (T*)qRealloc(data, maxSize * sizeof(T)); } else { data = (T*)qMalloc(maxSize * sizeof(T)); @@ -92,7 +92,7 @@ private: int index; int maxSize; T *data; - T fixedData[N]; + char fixedData[N * sizeof(T)]; }; class QDeclarativeVME @@ -100,7 +100,7 @@ class QDeclarativeVME public: QDeclarativeVME(); - QObject *run(QDeclarativeContext *, QDeclarativeCompiledData *, + QObject *run(QDeclarativeContextData *, QDeclarativeCompiledData *, int start = -1, int count = -1, const QBitField & = QBitField()); void runDeferred(QObject *); @@ -109,8 +109,10 @@ public: QList<QDeclarativeError> errors() const; private: - QObject *run(QDeclarativeVMEStack<QObject *> &, QDeclarativeContext *, QDeclarativeCompiledData *, - int start, int count, const QBitField &); + QObject *run(QDeclarativeVMEStack<QObject *> &, + QDeclarativeContextData *, QDeclarativeCompiledData *, + int start, int count, + const QBitField &); QList<QDeclarativeError> vmeErrors; }; diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index d67c834..f9c99ee 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -55,11 +55,11 @@ QT_BEGIN_NAMESPACE QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj, - const QMetaObject *other, - const QDeclarativeVMEMetaData *meta, - QDeclarativeCompiledData *cdata) -: object(obj), compiledData(cdata), ctxt(qmlContext(obj)), metaData(meta), methods(0), - parent(0) + const QMetaObject *other, + const QDeclarativeVMEMetaData *meta, + QDeclarativeCompiledData *cdata) +: object(obj), compiledData(cdata), ctxt(QDeclarativeDeclarativeData::get(obj)->outerContext), + metaData(meta), methods(0), parent(0) { compiledData->addref(); @@ -115,7 +115,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) if (type != QVariant::Invalid) { if (valueIndex != -1) { - QDeclarativeEnginePrivate *ep = ctxt?QDeclarativeEnginePrivate::get(ctxt->engine()):0; + QDeclarativeEnginePrivate *ep = ctxt?QDeclarativeEnginePrivate::get(ctxt->engine):0; QDeclarativeValueType *valueType = 0; if (ep) valueType = ep->valueTypes[type]; else valueType = QDeclarativeValueTypeFactory::valueType(type); @@ -214,16 +214,17 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) *reinterpret_cast<void **>(a[0]) = 0; if (!ctxt) return -1; - QDeclarativeContextPrivate *ctxtPriv = - (QDeclarativeContextPrivate *)QObjectPrivate::get(ctxt); - QObject *target = ctxtPriv->idValues[d->contextIdx].data(); + QDeclarativeContext *context = ctxt->asQDeclarativeContext(); + QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context); + + QObject *target = ctxtPriv->data->idValues[d->contextIdx].data(); if (!target) return -1; if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { int sigIdx = methodOffset + id + metaData->propertyCount; - QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); + QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); if (d->propertyIdx != -1) { QMetaProperty prop = @@ -262,10 +263,10 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) id -= plainSignals; if (id < metaData->methodCount) { - if (!ctxt->engine()) + if (!ctxt->engine) return -1; // We can't run the method - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine()); + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); QScriptValue function = method(id); diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index 37c0b7a..e11f6fa 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -63,6 +63,7 @@ #include "qdeclarativeguard_p.h" #include "qdeclarativecompiler_p.h" +#include "qdeclarativecontext_p.h" QT_BEGIN_NAMESPACE @@ -121,7 +122,7 @@ protected: private: QObject *object; QDeclarativeCompiledData *compiledData; - QDeclarativeGuard<QDeclarativeContext> ctxt; + QDeclarativeGuardedContextData ctxt; const QDeclarativeVMEMetaData *metaData; int propOffset; diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index 784353a..10c0b54 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -40,7 +40,8 @@ ****************************************************************************/ #include "qdeclarativeworkerscript_p.h" - +#include "qdeclarativelistmodel_p.h" +#include "qdeclarativelistmodelworkeragent_p.h" #include "qdeclarativeengine_p.h" #include <QtCore/qcoreevent.h> @@ -104,6 +105,7 @@ private: class QDeclarativeWorkerScriptEnginePrivate : public QObject { + Q_OBJECT public: QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *eng); @@ -165,87 +167,6 @@ private: void processLoad(int, const QUrl &); }; -// Currently this will leak as no-one releases it in the worker thread -class QDeclarativeWorkerListModelAgent : public QObject -{ - Q_OBJECT - Q_PROPERTY(int count READ count) - -public: - QDeclarativeWorkerListModelAgent(QDeclarativeWorkerListModel *); - ~QDeclarativeWorkerListModelAgent(); - - void addref(); - void release(); - - int count() const; - - Q_INVOKABLE void clear(); - Q_INVOKABLE void remove(int index); - Q_INVOKABLE void append(const QScriptValue &); - Q_INVOKABLE void insert(int index, const QScriptValue&); - Q_INVOKABLE QScriptValue get(int index) const; - Q_INVOKABLE void set(int index, const QScriptValue &); - Q_INVOKABLE void sync(); - - struct VariantRef - { - VariantRef() : a(0) {} - VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); } - VariantRef(QDeclarativeWorkerListModelAgent *_a) : a(_a) { if (a) a->addref(); } - ~VariantRef() { if (a) a->release(); } - - VariantRef &operator=(const VariantRef &o) { - if (o.a) o.a->addref(); - if (a) a->release(); a = o.a; - return *this; - } - - QDeclarativeWorkerListModelAgent *a; - }; -protected: - virtual bool event(QEvent *); - -private: - friend class QDeclarativeWorkerScriptEnginePrivate; - friend class QDeclarativeWorkerListModel; - QScriptEngine *m_engine; - - struct Change { - enum { Inserted, Removed, Moved, Changed } type; - int index; // Inserted/Removed/Moved/Changed - int count; // Inserted/Removed/Moved/Changed - int to; // Moved - }; - - struct Data { - QHash<int, QString> roles; - QHash<QString, int> strings; - QList<QHash<int, QVariant> > values; - QList<Change> changes; - - void clearChange(); - void insertChange(int index, int count); - void removeChange(int index, int count); - void changedChange(int index, int count); - }; - Data data; - - struct Sync : public QEvent { - Sync() : QEvent(QEvent::User) {} - Data data; - }; - - QAtomicInt m_ref; - QDeclarativeWorkerListModel *m_model; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QDeclarativeWorkerListModelAgent::VariantRef); - -QT_BEGIN_NAMESPACE - QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine) : workerEngine(0), qmlengine(engine), m_nextId(0) { @@ -390,10 +311,15 @@ QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScri return QVariant(list); } else if (value.isQObject()) { - QDeclarativeWorkerListModel *lm = qobject_cast<QDeclarativeWorkerListModel *>(value.toQObject()); + QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(value.toQObject()); if (lm) { - QDeclarativeWorkerListModelAgent::VariantRef v(lm->agent()); - return qVariantFromValue(v); + QDeclarativeListModelWorkerAgent *agent = lm->agent(); + if (agent) { + QDeclarativeListModelWorkerAgent::VariantRef v(agent); + return qVariantFromValue(v); + } else { + return QVariant(); + } } else { // No other QObject's are allowed to be sent return QVariant(); @@ -423,11 +349,11 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(const Q return QScriptValue(value.toString()); } else if (value.userType() == QMetaType::QReal) { return QScriptValue(value.toReal()); - } else if (value.userType() == qMetaTypeId<QDeclarativeWorkerListModelAgent::VariantRef>()) { - QDeclarativeWorkerListModelAgent::VariantRef vr = qvariant_cast<QDeclarativeWorkerListModelAgent::VariantRef>(value); - if (vr.a->m_engine == 0) - vr.a->m_engine = engine; - else if (vr.a->m_engine != engine) + } else if (value.userType() == qMetaTypeId<QDeclarativeListModelWorkerAgent::VariantRef>()) { + QDeclarativeListModelWorkerAgent::VariantRef vr = qvariant_cast<QDeclarativeListModelWorkerAgent::VariantRef>(value); + if (vr.a->scriptEngine() == 0) + vr.a->setScriptEngine(engine); + else if (vr.a->scriptEngine() != engine) return engine->nullValue(); QScriptValue o = engine->newQObject(vr.a); o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc @@ -619,8 +545,6 @@ void QDeclarativeWorkerScriptEngine::run() called, triggering the \tt WorkerScript.onMessage() handler in \tt source.js. This in turn sends a reply message that is then received by the \tt onMessage() handler of \tt myWorker. - - \sa WorkerListModel */ QDeclarativeWorkerScript::QDeclarativeWorkerScript(QObject *parent) : QObject(parent), m_engine(0), m_scriptId(-1) @@ -714,544 +638,7 @@ bool QDeclarativeWorkerScript::event(QEvent *event) } } -void QDeclarativeWorkerListModelAgent::Data::clearChange() -{ - changes.clear(); -} - -void QDeclarativeWorkerListModelAgent::Data::insertChange(int index, int count) -{ - Change c = { Change::Inserted, index, count, 0 }; - changes << c; -} - -void QDeclarativeWorkerListModelAgent::Data::removeChange(int index, int count) -{ - Change c = { Change::Removed, index, count, 0 }; - changes << c; -} - -void QDeclarativeWorkerListModelAgent::Data::changedChange(int index, int count) -{ - Change c = { Change::Changed, index, count, 0 }; - changes << c; -} - -QDeclarativeWorkerListModelAgent::QDeclarativeWorkerListModelAgent(QDeclarativeWorkerListModel *m) -: m_engine(0), m_ref(1), m_model(m) -{ - data.roles = m_model->m_roles; - data.strings = m_model->m_strings; - data.values = m_model->m_values; -} - -QDeclarativeWorkerListModelAgent::~QDeclarativeWorkerListModelAgent() -{ -} - -void QDeclarativeWorkerListModelAgent::addref() -{ - m_ref.ref(); -} - -void QDeclarativeWorkerListModelAgent::release() -{ - bool del = !m_ref.deref(); - - if (del) - delete this; -} - -int QDeclarativeWorkerListModelAgent::count() const -{ - return data.values.count(); -} - -void QDeclarativeWorkerListModelAgent::clear() -{ - data.clearChange(); - data.removeChange(0, data.values.count()); - data.values.clear(); -} - -void QDeclarativeWorkerListModelAgent::remove(int index) -{ - if (data.values.count() <= index) - return; - - data.values.removeAt(index); - data.removeChange(index, 1); -} - -void QDeclarativeWorkerListModelAgent::append(const QScriptValue &value) -{ - QHash<int, QVariant> row; - - QScriptValueIterator it(value); - while (it.hasNext()) { - it.next(); - QString name = it.name(); - QVariant v = it.value().toVariant(); - - QHash<QString, int>::Iterator iter = data.strings.find(name); - if (iter == data.strings.end()) { - int role = data.roles.count(); - data.roles.insert(role, name); - iter = data.strings.insert(name, role); - } - row.insert(*iter, v); - } - - data.values.append(row); - data.insertChange(data.values.count() - 1, 1); -} - -void QDeclarativeWorkerListModelAgent::insert(int index, const QScriptValue &value) -{ - if (index > data.values.count()) - return; - - QHash<int, QVariant> row; - - QScriptValueIterator it(value); - while (it.hasNext()) { - it.next(); - QString name = it.name(); - QVariant v = it.value().toVariant(); - - QHash<QString, int>::Iterator iter = data.strings.find(name); - if (iter == data.strings.end()) { - int role = data.roles.count(); - data.roles.insert(role, name); - iter = data.strings.insert(name, role); - } - row.insert(*iter, v); - } - - data.values.insert(index, row); - data.insertChange(index, 1); -} - -void QDeclarativeWorkerListModelAgent::set(int index, const QScriptValue &value) -{ - if (data.values.count() <= index) - return; - - QHash<int, QVariant> row; - - QScriptValueIterator it(value); - while (it.hasNext()) { - it.next(); - QString name = it.name(); - QVariant v = it.value().toVariant(); - - QHash<QString, int>::Iterator iter = data.strings.find(name); - if (iter == data.strings.end()) { - int role = data.roles.count(); - data.roles.insert(role, name); - iter = data.strings.insert(name, role); - } - row.insert(*iter, v); - } - - if (data.values.at(index) != row) { - data.values[index] = row; - data.changedChange(index, 1); - } -} - -QScriptValue QDeclarativeWorkerListModelAgent::get(int index) const -{ - if (data.values.count() <= index) - return m_engine->undefinedValue(); - - QScriptValue rv = m_engine->newObject(); - - QHash<int, QVariant> row = data.values.at(index); - for (QHash<int, QVariant>::ConstIterator iter = row.begin(); iter != row.end(); ++iter) - rv.setProperty(data.roles.value(iter.key()), qScriptValueFromValue(m_engine, iter.value())); - - return rv; -} - -void QDeclarativeWorkerListModelAgent::sync() -{ - Sync *s = new Sync; - s->data = data; - data.changes.clear(); - QCoreApplication::postEvent(this, s); -} - -bool QDeclarativeWorkerListModelAgent::event(QEvent *e) -{ - if (e->type() == QEvent::User) { - Sync *s = static_cast<Sync *>(e); - - const QList<Change> &changes = s->data.changes; - - if (m_model) { - bool cc = m_model->m_values.count() != s->data.values.count(); - - m_model->m_roles = s->data.roles; - m_model->m_strings = s->data.strings; - m_model->m_values = s->data.values; - - for (int ii = 0; ii < changes.count(); ++ii) { - const Change &change = changes.at(ii); - switch (change.type) { - case Change::Inserted: - emit m_model->itemsInserted(change.index, change.count); - break; - case Change::Removed: - emit m_model->itemsRemoved(change.index, change.count); - break; - case Change::Moved: - emit m_model->itemsMoved(change.index, change.to, change.count); - break; - case Change::Changed: - emit m_model->itemsMoved(change.index, change.to, change.count); - break; - } - } - - if (cc) - emit m_model->countChanged(); - } - } - - return QObject::event(e); -} - -/*! - \qmlclass WorkerListModel QDeclarativeWorkerListModel - \brief The WorkerListModel element provides a threaded list model. - - Use WorkerListModel together with WorkerScript to define a list model - that is controlled by a separate thread. This is useful if list modification - operations are synchronous and take some time: using WorkerListModel - moves these operations to a different thread and avoids blocking of the - main GUI thread. - - The thread that creates the WorkerListModel can modify the model for any - initial set-up requirements. However, once the model has been modified by - the associated WorkerScript, the model can only be modified by that worker - script and becomes read-only to all other threads. - - Here is an example application that uses WorkerScript to append the - current time to a WorkerListModel: - - \snippet examples/declarative/workerlistmodel/timedisplay.qml 0 - - The included file, \tt dataloader.js, looks like this: - - \snippet examples/declarative/workerlistmodel/dataloader.js 0 - - The application's \tt Timer object periodically sends a message to the - worker script by calling \tt WorkerScript::sendMessage(). When this message - is received, \tt WorkerScript.onMessage() is invoked in - \tt dataloader.js, which appends the current time to the worker list - model. - - Note that unlike ListModel, WorkerListModel does not have \tt move() and - \tt setProperty() methods. - - \sa WorkerScript, ListModel -*/ -QDeclarativeWorkerListModel::QDeclarativeWorkerListModel(QObject *parent) -: QListModelInterface(parent), m_agent(0) -{ -} - -QDeclarativeWorkerListModel::~QDeclarativeWorkerListModel() -{ - if (m_agent) { - m_agent->m_model = 0; - m_agent->release(); - } -} - -/*! - \qmlmethod WorkerListModel::clear() - - Deletes all content from the model. The properties are cleared such that - different properties may be set on subsequent additions. - - \sa append() remove() -*/ -void QDeclarativeWorkerListModel::clear() -{ - if (m_agent) { - qmlInfo(this) << "List can only be modified from a WorkerScript"; - return; - } - - int count = m_values.count(); - m_values.clear(); - if (count) { - emit itemsRemoved(0, count); - emit countChanged(); - } -} - -/*! - \qmlmethod WorkerListModel::remove(int index) - - Deletes the content at \a index from the model. - - \sa clear() -*/ -void QDeclarativeWorkerListModel::remove(int index) -{ - if (m_agent) { - qmlInfo(this) << "List can only be modified from a WorkerScript"; - return; - } - - if (m_values.count() <= index) - return; - - m_values.removeAt(index); - emit itemsRemoved(index, 1); - emit countChanged(); -} - -/*! - \qmlmethod WorkerListModel::append(jsobject dict) - - Adds a new item to the end of the list model, with the - values in \a dict. - - \code - FruitModel.append({"cost": 5.95, "name":"Pizza"}) - \endcode - - \sa set() remove() -*/ -void QDeclarativeWorkerListModel::append(const QScriptValue &value) -{ - if (m_agent) { - qmlInfo(this) << "List can only be modified from a WorkerScript"; - return; - } - - QHash<int, QVariant> data; - - QScriptValueIterator it(value); - while (it.hasNext()) { - it.next(); - QString name = it.name(); - QVariant v = it.value().toVariant(); - - QHash<QString, int>::Iterator iter = m_strings.find(name); - if (iter == m_strings.end()) { - int role = m_roles.count(); - m_roles.insert(role, name); - iter = m_strings.insert(name, role); - } - data.insert(*iter, v); - } - - m_values.append(data); - - emit itemsInserted(m_values.count() - 1, 1); - emit countChanged(); -} - -/*! - \qmlmethod WorkerListModel::insert(int index, jsobject dict) - - Adds a new item to the list model at position \a index, with the - values in \a dict. - - \code - FruitModel.insert(2, {"cost": 5.95, "name":"Pizza"}) - \endcode - - The \a index must be to an existing item in the list, or one past - the end of the list (equivalent to append). - - \sa set() append() -*/ -void QDeclarativeWorkerListModel::insert(int index, const QScriptValue &value) -{ - if (m_agent) { - qmlInfo(this) << "List can only be modified from a WorkerScript"; - return; - } - - if (index > m_values.count()) - return; - - QHash<int, QVariant> data; - - QScriptValueIterator it(value); - while (it.hasNext()) { - it.next(); - QString name = it.name(); - QVariant v = it.value().toVariant(); - - QHash<QString, int>::Iterator iter = m_strings.find(name); - if (iter == m_strings.end()) { - int role = m_roles.count(); - m_roles.insert(role, name); - iter = m_strings.insert(name, role); - } - data.insert(*iter, v); - } - - m_values.insert(index, data); - emit itemsInserted(index, 1); - emit countChanged(); -} - -/*! - \qmlmethod object ListModel::get(int index) - - Returns the item at \a index in the list model. - - \code - FruitModel.append({"cost": 5.95, "name":"Jackfruit"}) - FruitModel.get(0).cost - \endcode - - The \a index must be an element in the list. - - Note that properties of the returned object that are themselves objects - will also be models, and this get() method is used to access elements: - - \code - FruitModel.append(..., "attributes": - [{"name":"spikes","value":"7mm"}, - {"name":"color","value":"green"}]); - FruitModel.get(0).attributes.get(1).value; // == "green" - \endcode - - \sa append() -*/ -QScriptValue QDeclarativeWorkerListModel::get(int index) const -{ - QDeclarativeEngine *engine = qmlEngine(this); - if (!engine || m_values.count() <= index) - return QScriptValue(); - - QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); - QScriptValue rv = scriptEngine->newObject(); - - QHash<int, QVariant> data = m_values.at(index); - for (QHash<int, QVariant>::ConstIterator iter = data.begin(); iter != data.end(); ++iter) - rv.setProperty(m_roles.value(iter.key()), qScriptValueFromValue(scriptEngine, iter.value())); - - return rv; -} - -/*! - \qmlmethod WorkerListModel::set(int index, jsobject dict) - - Changes the item at \a index in the list model with the - values in \a dict. Properties not appearing in \a valuemap - are left unchanged. - - \code - FruitModel.set(3, {"cost": 5.95, "name":"Pizza"}) - \endcode - - The \a index must be an element in the list. - - \sa append() -*/ -void QDeclarativeWorkerListModel::set(int index, const QScriptValue &value) -{ - if (m_agent) { - qmlInfo(this) << "List can only be modified from a WorkerScript"; - return; - } - - if (m_values.count() <= index) - return; - - QHash<int, QVariant> data; - - QScriptValueIterator it(value); - while (it.hasNext()) { - it.next(); - QString name = it.name(); - QVariant v = it.value().toVariant(); - - QHash<QString, int>::Iterator iter = m_strings.find(name); - if (iter == m_strings.end()) { - int role = m_roles.count(); - m_roles.insert(role, name); - iter = m_strings.insert(name, role); - } - data.insert(*iter, v); - } - - if (m_values.at(index) != data) { - m_values[index] = data; - emit itemsChanged(index, 1, m_roles.keys()); - } -} - -/*! - \qmlmethod WorkerListModel::sync() - - Writes any unsaved changes to the list model. This must be called after - changes have been made to the list model in the worker script. - - Note that this method can only be called from the associated worker script. -*/ -void QDeclarativeWorkerListModel::sync() -{ - // This is really a dummy method to make it look like sync() exists in - // WorkerListModel (and not QDeclarativeWorkerListModelAgent) and to let - // us document sync(). - qmlInfo(this) << "sync() can only be called from a WorkerScript"; -} - -QDeclarativeWorkerListModelAgent *QDeclarativeWorkerListModel::agent() -{ - if (!m_agent) - m_agent = new QDeclarativeWorkerListModelAgent(this); - - return m_agent; -} - -QList<int> QDeclarativeWorkerListModel::roles() const -{ - return m_roles.keys(); -} - -QString QDeclarativeWorkerListModel::toString(int role) const -{ - return m_roles.value(role); -} - -/*! - \qmlproperty int ListModel::count - The number of data entries in the model. -*/ -int QDeclarativeWorkerListModel::count() const -{ - return m_values.count(); -} - -QHash<int,QVariant> QDeclarativeWorkerListModel::data(int index, const QList<int> &) const -{ - if (m_values.count() <= index) - return QHash<int, QVariant>(); - else - return m_values.at(index); -} - -QVariant QDeclarativeWorkerListModel::data(int index, int role) const -{ - if (m_values.count() <= index) - return QVariant(); - else - return m_values.at(index).value(role); -} - QT_END_NAMESPACE -#include "qdeclarativeworkerscript.moc" +#include <qdeclarativeworkerscript.moc> diff --git a/src/declarative/qml/qdeclarativeworkerscript_p.h b/src/declarative/qml/qdeclarativeworkerscript_p.h index 912eac9..6cce799 100644 --- a/src/declarative/qml/qdeclarativeworkerscript_p.h +++ b/src/declarative/qml/qdeclarativeworkerscript_p.h @@ -55,7 +55,6 @@ #include "qdeclarative.h" #include "qdeclarativeparserstatus.h" -#include <private/qlistmodelinterface_p.h> #include <QtCore/qthread.h> #include <QtScript/qscriptvalue.h> @@ -118,49 +117,9 @@ private: QUrl m_source; }; -class QDeclarativeWorkerListModelAgent; -class Q_DECLARATIVE_EXPORT QDeclarativeWorkerListModel : public QListModelInterface -{ - Q_OBJECT - Q_PROPERTY(int count READ count NOTIFY countChanged) - -public: - QDeclarativeWorkerListModel(QObject * = 0); - virtual ~QDeclarativeWorkerListModel(); - - Q_INVOKABLE void clear(); - Q_INVOKABLE void remove(int index); - Q_INVOKABLE void append(const QScriptValue &); - Q_INVOKABLE void insert(int index, const QScriptValue&); - Q_INVOKABLE QScriptValue get(int index) const; - Q_INVOKABLE void set(int index, const QScriptValue &); - Q_INVOKABLE void sync(); - - QDeclarativeWorkerListModelAgent *agent(); - - virtual QList<int> roles() const; - virtual QString toString(int role) const; - virtual int count() const; - virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const; - virtual QVariant data(int index, int role) const; - -Q_SIGNALS: - void countChanged(); - -private: - friend class QDeclarativeWorkerListModelAgent; - - QHash<int, QString> m_roles; - QHash<QString, int> m_strings; - QList<QHash<int, QVariant> > m_values; - - QDeclarativeWorkerListModelAgent *m_agent; -}; - QT_END_NAMESPACE QML_DECLARE_TYPE(QDeclarativeWorkerScript); -QML_DECLARE_TYPE(QDeclarativeWorkerListModel); QT_END_HEADER diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index 87cab85..58e67fa 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -1245,7 +1245,7 @@ void QDeclarativeXMLHttpRequest::finished() if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) { QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute); if (redirect.isValid()) { - QUrl url = redirect.toUrl(); + QUrl url = m_network->url().resolved(redirect.toUrl()); destroyNetwork(); requestFromUrl(url); return; diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index aa1a34b..49888c3 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -38,6 +38,7 @@ SOURCES += \ $$PWD/qdeclarativescript.cpp \ $$PWD/qdeclarativecleanup.cpp \ $$PWD/qdeclarativepropertycache.cpp \ + $$PWD/qdeclarativenotifier.cpp \ $$PWD/qdeclarativeintegercache.cpp \ $$PWD/qdeclarativetypenamecache.cpp \ $$PWD/qdeclarativescriptstring.cpp \ @@ -108,6 +109,7 @@ HEADERS += \ $$PWD/qdeclarativewatcher_p.h \ $$PWD/qdeclarativecleanup_p.h \ $$PWD/qdeclarativepropertycache_p.h \ + $$PWD/qdeclarativenotifier_p.h \ $$PWD/qdeclarativeintegercache_p.h \ $$PWD/qdeclarativetypenamecache_p.h \ $$PWD/qdeclarativescriptstring.h \ |