summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/parser/qdeclarativejslexer.cpp6
-rw-r--r--src/declarative/qml/qdeclarative.h22
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp161
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h41
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings.cpp235
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings_p.h2
-rw-r--r--src/declarative/qml/qdeclarativecompileddata.cpp14
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp62
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h5
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp82
-rw-r--r--src/declarative/qml/qdeclarativecomponent.h1
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h10
-rw-r--r--src/declarative/qml/qdeclarativecompositetypemanager.cpp93
-rw-r--r--src/declarative/qml/qdeclarativecompositetypemanager_p.h3
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp527
-rw-r--r--src/declarative/qml/qdeclarativecontext.h11
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h187
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp83
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass_p.h10
-rw-r--r--src/declarative/qml/qdeclarativecustomparser.cpp12
-rw-r--r--src/declarative/qml/qdeclarativecustomparser_p.h10
-rw-r--r--src/declarative/qml/qdeclarativedeclarativedata_p.h27
-rw-r--r--src/declarative/qml/qdeclarativedirparser.cpp5
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp350
-rw-r--r--src/declarative/qml/qdeclarativeengine.h4
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h14
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp45
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp250
-rw-r--r--src/declarative/qml/qdeclarativeexpression.h12
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h34
-rw-r--r--src/declarative/qml/qdeclarativeinfo.cpp5
-rw-r--r--src/declarative/qml/qdeclarativeinstruction.cpp2
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp26
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h1
-rw-r--r--src/declarative/qml/qdeclarativenotifier.cpp110
-rw-r--r--src/declarative/qml/qdeclarativenotifier_p.h276
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp174
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass_p.h9
-rw-r--r--src/declarative/qml/qdeclarativeparser.cpp5
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeprivate.h6
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp84
-rw-r--r--src/declarative/qml/qdeclarativeproperty_p.h9
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h17
-rw-r--r--src/declarative/qml/qdeclarativevaluetype.cpp2
-rw-r--r--src/declarative/qml/qdeclarativevaluetypescriptclass.cpp7
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp99
-rw-r--r--src/declarative/qml/qdeclarativevme_p.h18
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp25
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject_p.h3
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp647
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript_p.h41
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp2
-rw-r--r--src/declarative/qml/qml.pri2
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 = &notifier->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 *)(&notifierData);
+}
+
+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 \