aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/ftw/qfastmetabuilder.cpp149
-rw-r--r--src/qml/qml/ftw/qfastmetabuilder_p.h74
-rw-r--r--src/qml/qml/ftw/qqmlpool_p.h1
-rw-r--r--src/qml/qml/qml.pri2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp8
-rw-r--r--src/qml/qml/qqmlcompiler.cpp202
-rw-r--r--src/qml/qml/qqmlengine.cpp73
-rw-r--r--src/qml/qml/qqmlengine.h11
-rw-r--r--src/qml/qml/qqmlengine_p.h7
-rw-r--r--src/qml/qml/qqmlerror.h2
-rw-r--r--src/qml/qml/qqmlimageprovider.cpp351
-rw-r--r--src/qml/qml/qqmlimageprovider.h97
-rw-r--r--src/qml/qml/qqmlmetatype.cpp9
-rw-r--r--src/qml/qml/qqmlproperty.cpp31
-rw-r--r--src/qml/qml/qqmlproperty.h2
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp79
-rw-r--r--src/qml/qml/qqmlscript.cpp61
-rw-r--r--src/qml/qml/qqmlscript_p.h20
-rw-r--r--src/qml/qml/qqmlvme.cpp9
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp59
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h1
-rw-r--r--src/qml/qml/v8/qv8engine.cpp7
-rw-r--r--src/qml/qml/v8/qv8engine_p.h10
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp101
-rw-r--r--src/qml/qml/v8/qv8valuetypewrapper.cpp7
26 files changed, 516 insertions, 859 deletions
diff --git a/src/qml/qml/ftw/qfastmetabuilder.cpp b/src/qml/qml/ftw/qfastmetabuilder.cpp
index 08ea76b37e..9d956054d9 100644
--- a/src/qml/qml/ftw/qfastmetabuilder.cpp
+++ b/src/qml/qml/ftw/qfastmetabuilder.cpp
@@ -79,7 +79,8 @@ static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
{ return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
QFastMetaBuilder::QFastMetaBuilder()
-: m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
+ : m_stringData(0), m_stringCount(0), m_stringDataLength(0),
+ m_stringCountAllocated(0), m_stringCountLoaded(0)
{
}
@@ -89,7 +90,8 @@ QFastMetaBuilder::~QFastMetaBuilder()
QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
int propertyCount, int methodCount,
- int signalCount, int classInfoCount)
+ int signalCount, int classInfoCount,
+ int paramDataSize, int *paramIndex)
{
Q_ASSERT(m_data.isEmpty());
Q_ASSERT(classNameLength > 0);
@@ -97,20 +99,29 @@ QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
Q_ASSERT(methodCount >= 0);
Q_ASSERT(signalCount >= 0);
Q_ASSERT(classInfoCount >= 0);
+ Q_ASSERT(paramDataSize >= 0);
+ Q_ASSERT((paramIndex != 0) || (methodCount + signalCount == 0));
int fieldCount = FMBHEADER_FIELD_COUNT +
HEADER_FIELD_COUNT +
propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
methodCount * (METHOD_FIELD_COUNT) +
signalCount * (METHOD_FIELD_COUNT) +
+ paramDataSize +
classInfoCount * CLASSINFO_FIELD_COUNT;
+ // Ensure stringdata alignment (void*)
+ fieldCount += fieldCount % (sizeof(void*) / sizeof(uint));
- m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1);
- m_stringData = m_data.data() + m_data.size() - classNameLength - 1;
+ m_stringCount = 2; // class name and zero string
m_stringDataLength = classNameLength + 1;
- m_stringDataAllocated = classNameLength + 1;
- m_stringData[classNameLength] = 0;
- m_zeroPtr = classNameLength;
+ m_data.resize(fieldCount * sizeof(uint) + m_stringCount * sizeof(QByteArrayData) + m_stringDataLength);
+ m_stringCountAllocated = m_stringCount;
+ m_stringData = reinterpret_cast<QByteArrayData *>(m_data.data() + fieldCount * sizeof(uint));
+
+ m_zeroString._b = this;
+ m_zeroString._i = 1;
+ m_zeroString._o = classNameLength;
+ m_zeroString._l = 0;
header(m_data)->fieldCount = fieldCount;
@@ -118,7 +129,7 @@ QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
int dataIndex = HEADER_FIELD_COUNT;
- p->revision = 6;
+ p->revision = 7;
p->className = 0;
// Class infos
@@ -135,6 +146,8 @@ QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
if (p->methodCount) {
p->methodData = dataIndex;
dataIndex += p->methodCount * METHOD_FIELD_COUNT;
+ *paramIndex = dataIndex;
+ dataIndex += paramDataSize;
} else {
p->methodData = 0;
}
@@ -160,6 +173,7 @@ QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
StringRef className;
className._b = this;
+ className._i = 0;
className._o = 0;
className._l = classNameLength;
return className;
@@ -169,12 +183,16 @@ QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
{
Q_ASSERT(length > 0);
+ Q_ASSERT_X(m_stringCountLoaded == 0, Q_FUNC_INFO,
+ "All strings must be created before string loading begins");
StringRef sr;
sr._b = this;
+ sr._i = m_stringCount;
sr._o = m_stringDataLength;
sr._l = length;
+ ++m_stringCount;
m_stringDataLength += length + 1 /* for null terminator */;
return sr;
@@ -190,47 +208,24 @@ void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const Strin
uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
// classinfo: key, value
- ptr[0] = key.offset(); ptr[1] = value.offset();
+ ptr[0] = key.index(); ptr[1] = value.index();
}
-void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
- QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
+void QFastMetaBuilder::setProperty(int index, const StringRef &name, int type,
+ PropertyFlag flags, int notifySignal)
{
Q_ASSERT(!m_data.isEmpty());
Q_ASSERT(!name.isEmpty());
- Q_ASSERT(!type.isEmpty());
-
- QMetaObjectPrivate *p = priv(m_data);
- Q_ASSERT(index < p->propertyCount);
-
- uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
- // properties: name, type, flags
- ptr[0] = name.offset();
- ptr[1] = type.offset();
- if (notifySignal == -1) {
- ptr[2] = mtype << 24;
- ptr[2] |= flags | Scriptable | Readable;
- *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
- } else {
- ptr[2] = mtype << 24;
- ptr[2] |= flags | Scriptable | Readable | Notify;
- *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
- }
-}
-
-void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
- QFastMetaBuilder::PropertyFlag flags, int notifySignal)
-{
- Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!name.isEmpty() && !type.isEmpty());
+ Q_ASSERT(type != 0);
+ Q_ASSERT(QMetaType::isRegistered(type));
QMetaObjectPrivate *p = priv(m_data);
Q_ASSERT(index < p->propertyCount);
uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
// properties: name, type, flags
- ptr[0] = name.offset();
- ptr[1] = type.offset();
+ ptr[0] = name.index();
+ ptr[1] = type;
if (notifySignal == -1) {
ptr[2] = flags | Scriptable | Readable;
*(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
@@ -240,42 +235,72 @@ void QFastMetaBuilder::setProperty(int index, const StringRef &name, const Strin
}
}
-void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
- const StringRef &parameterNames,
- const StringRef &type)
+void QFastMetaBuilder::setSignal(int index, const StringRef &name,
+ int paramIndex, int argc, const int *types,
+ const StringRef *parameterNames,
+ QMetaType::Type type)
{
Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!signature.isEmpty());
+ Q_ASSERT(!name.isEmpty());
+ Q_ASSERT(QMetaType::isRegistered(type));
QMetaObjectPrivate *p = priv(m_data);
int mindex = metaObjectIndexForSignal(index);
uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
- // methods: signature, parameters, type, tag, flags
- ptr[0] = signature.offset();
- ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
- ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
- ptr[3] = m_zeroPtr;
+ // methods: name, arc, parameters, tag, flags
+ ptr[0] = name.index();
+ ptr[1] = argc;
+ ptr[2] = paramIndex;
+ ptr[3] = m_zeroString.index();
ptr[4] = AccessProtected | MethodSignal;
+
+ uint *paramPtr = fieldPointer(m_data) + paramIndex;
+ paramPtr[0] = type;
+ if (argc) {
+ Q_ASSERT(types != 0);
+ Q_ASSERT(parameterNames != 0);
+ for (int i = 0; i < argc; ++i) {
+ Q_ASSERT(types[i] != 0);
+ Q_ASSERT(QMetaType::isRegistered(types[i]));
+ paramPtr[1+i] = types[i];
+ paramPtr[1+argc+i] = parameterNames[i].index();
+ }
+ }
}
-void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
- const StringRef &parameterNames,
- const StringRef &type)
+void QFastMetaBuilder::setMethod(int index, const StringRef &name,
+ int paramIndex, int argc, const int *types,
+ const StringRef *parameterNames,
+ QMetaType::Type type)
{
Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!signature.isEmpty());
+ Q_ASSERT(!name.isEmpty());
+ Q_ASSERT(QMetaType::isRegistered(type));
QMetaObjectPrivate *p = priv(m_data);
int mindex = metaObjectIndexForMethod(index);
uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
- // methods: signature, parameters, type, tag, flags
- ptr[0] = signature.offset();
- ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
- ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
- ptr[3] = m_zeroPtr;
+ // methods: name, arc, parameters, tag, flags
+ ptr[0] = name.index();
+ ptr[1] = argc;
+ ptr[2] = paramIndex;
+ ptr[3] = m_zeroString.index();
ptr[4] = AccessProtected | MethodSlot;
+
+ uint *paramPtr = fieldPointer(m_data) + paramIndex;
+ paramPtr[0] = type;
+ if (argc) {
+ Q_ASSERT(types != 0);
+ Q_ASSERT(parameterNames != 0);
+ for (int i = 0; i < argc; ++i) {
+ Q_ASSERT(types[i] != 0);
+ Q_ASSERT(QMetaType::isRegistered(types[i]));
+ paramPtr[1+i] = types[i];
+ paramPtr[1+argc+i] = parameterNames[i].index();
+ }
+ }
}
int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
@@ -296,17 +321,19 @@ int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
void QFastMetaBuilder::allocateStringData()
{
- if (m_stringDataAllocated < m_stringDataLength) {
- m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated);
- m_stringDataAllocated = m_stringDataLength;
- m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
+ if (m_stringCountAllocated < m_stringCount) {
+ m_data.resize(header(m_data)->fieldCount * sizeof(uint)
+ + m_stringCount * sizeof(QByteArrayData) + m_stringDataLength);
+ m_stringCountAllocated = m_stringCount;
+ char *rawStringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
+ m_stringData = reinterpret_cast<QByteArrayData *>(rawStringData);
}
}
void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
{
output->d.superdata = parent;
- output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint);
+ output->d.stringdata = reinterpret_cast<const QByteArrayData *>(data.constData() + header(data)->fieldCount * sizeof(uint));
output->d.data = fieldPointer(data);
output->d.extradata = 0;
}
diff --git a/src/qml/qml/ftw/qfastmetabuilder_p.h b/src/qml/qml/ftw/qfastmetabuilder_p.h
index c1f6a3de5c..16f7b6e749 100644
--- a/src/qml/qml/ftw/qfastmetabuilder_p.h
+++ b/src/qml/qml/ftw/qfastmetabuilder_p.h
@@ -80,13 +80,15 @@ public:
inline bool isEmpty() const;
inline QFastMetaBuilder *builder() const;
- inline int offset() const;
+ inline int index() const;
inline char *data();
inline int length() const;
+ inline void loadByteArrayData();
private:
friend class QFastMetaBuilder;
QFastMetaBuilder *_b;
+ int _i;
int _o;
int _l;
};
@@ -95,7 +97,8 @@ public:
// Returns class name
StringRef init(int classNameLength,
int propertyCount, int methodCount,
- int signalCount, int classInfoCount);
+ int signalCount, int classInfoCount,
+ int paramDataSize, int *paramIndex);
void setClassInfo(int index, const StringRef &key, const StringRef &value);
@@ -106,48 +109,55 @@ public:
Constant = 0x00000400,
Final = 0x00000800
};
- // void setProperty(int index, const StringRef &name, QMetaType::Type type, int notifySignal = -1);
- void setProperty(int index, const StringRef &name, const StringRef &type,
- QMetaType::Type mtype, PropertyFlag flags, int notifySignal = -1);
- void setProperty(int index, const StringRef &name, const StringRef &type,
+ void setProperty(int index, const StringRef &name, int type,
PropertyFlag flags, int notifySignal = -1);
- void setMethod(int index, const StringRef &signature,
- const StringRef &parameterNames = StringRef(),
- const StringRef &type = StringRef());
- void setSignal(int index, const StringRef &signature,
- const StringRef &parameterNames = StringRef(),
- const StringRef &type = StringRef());
+ void setMethod(int index, const StringRef &name, int paramIndex, int argc = 0,
+ const int *types = 0, const StringRef *parameterNames = 0,
+ QMetaType::Type type = QMetaType::Void);
+ void setSignal(int index, const StringRef &name, int paramIndex, int argc = 0,
+ const int *types = 0, const StringRef *parameterNames = 0,
+ QMetaType::Type type = QMetaType::Void);
int metaObjectIndexForSignal(int) const;
int metaObjectIndexForMethod(int) const;
- QByteArray toData() const { return m_data; }
+ QByteArray toData() const {
+ if (m_stringCountLoaded == m_stringCount - 1) {
+ // zero-string is lazily loaded last
+ const_cast<StringRef &>(m_zeroString).loadByteArrayData();
+ }
+ Q_ASSERT(m_stringCountLoaded == m_stringCount);
+ return m_data;
+ }
static void fromData(QMetaObject *, const QMetaObject *parent, const QByteArray &);
private:
friend struct StringRef;
QByteArray m_data;
- int m_zeroPtr;
+ StringRef m_zeroString;
void allocateStringData();
- char *m_stringData;
+ QByteArrayData *m_stringData;
+ int m_stringCount;
int m_stringDataLength;
- int m_stringDataAllocated;
+ int m_stringCountAllocated;
+ int m_stringCountLoaded;
};
QFastMetaBuilder::StringRef::StringRef()
-: _b(0), _o(0), _l(0)
+: _b(0), _i(0), _o(0), _l(0)
{
}
QFastMetaBuilder::StringRef::StringRef(const StringRef &o)
-: _b(o._b), _o(o._o), _l(o._l)
+: _b(o._b), _i(o._i), _o(o._o), _l(o._l)
{
}
QFastMetaBuilder::StringRef &QFastMetaBuilder::StringRef::operator=(const StringRef &o)
{
_b = o._b;
+ _i = o._i;
_o = o._o;
_l = o._l;
return *this;
@@ -163,17 +173,17 @@ QFastMetaBuilder *QFastMetaBuilder::StringRef::builder() const
return _b;
}
-int QFastMetaBuilder::StringRef::offset() const
+int QFastMetaBuilder::StringRef::index() const
{
- return _o;
+ return _i;
}
char *QFastMetaBuilder::StringRef::data()
{
Q_ASSERT(_b);
- if (_b->m_stringDataLength != _b->m_stringDataAllocated)
- _b->allocateStringData();
- return _b->m_stringData + _o;
+ if (_b->m_stringCountAllocated < _b->m_stringCount)
+ _b->allocateStringData();
+ return reinterpret_cast<char *>(&_b->m_stringData[_b->m_stringCount]) + _o;
}
int QFastMetaBuilder::StringRef::length() const
@@ -186,18 +196,36 @@ void QFastMetaBuilder::StringRef::load(const QHashedStringRef &str)
Q_ASSERT(str.utf8length() == _l);
str.writeUtf8(data());
*(data() + _l) = 0;
+ loadByteArrayData();
}
void QFastMetaBuilder::StringRef::load(const QByteArray &str)
{
Q_ASSERT(str.length() == _l);
strcpy(data(), str.constData());
+ loadByteArrayData();
}
void QFastMetaBuilder::StringRef::load(const char *str)
{
Q_ASSERT(strlen(str) == (uint)_l);
strcpy(data(), str);
+ loadByteArrayData();
+}
+
+void QFastMetaBuilder::StringRef::loadByteArrayData()
+{
+ if (_b->m_stringCountAllocated < _b->m_stringCount)
+ _b->allocateStringData();
+ Q_ASSERT(_b->m_stringCountLoaded < _b->m_stringCount);
+
+ int offsetofCstrings = _b->m_stringCount * sizeof(QByteArrayData);
+ qptrdiff offset = offsetofCstrings + _o - _i * sizeof(QByteArrayData);
+
+ const QByteArrayData bad = { Q_REFCOUNT_INITIALIZE_STATIC, _l, 0, 0, offset };
+ memcpy(&_b->m_stringData[_i], &bad, sizeof(QByteArrayData));
+
+ ++_b->m_stringCountLoaded;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qqmlpool_p.h b/src/qml/qml/ftw/qqmlpool_p.h
index e4fa03ce34..8e8f367890 100644
--- a/src/qml/qml/ftw/qqmlpool_p.h
+++ b/src/qml/qml/ftw/qqmlpool_p.h
@@ -132,6 +132,7 @@ public:
Q_ASSERT(index < m_length);
return m_data[index];
};
+ const T *data() const { return m_data; }
private:
friend class QQmlPool;
List(T *d, int l) : m_length(l), m_data(d) {}
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index c75e4c9681..5d26197b1c 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -40,7 +40,6 @@ SOURCES += \
$$PWD/qqmltypenamecache.cpp \
$$PWD/qqmlscriptstring.cpp \
$$PWD/qquickworkerscript.cpp \
- $$PWD/qqmlimageprovider.cpp \
$$PWD/qqmlnetworkaccessmanagerfactory.cpp \
$$PWD/qqmldirparser.cpp \
$$PWD/qqmlextensionplugin.cpp \
@@ -109,7 +108,6 @@ HEADERS += \
$$PWD/qqmlscriptstring.h \
$$PWD/qquickworkerscript_p.h \
$$PWD/qqmlguard_p.h \
- $$PWD/qqmlimageprovider.h \
$$PWD/qqmlnetworkaccessmanagerfactory.h \
$$PWD/qqmldirparser_p.h \
$$PWD/qqmlextensioninterface.h \
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index ca6b13e7f8..aa130d9493 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -172,11 +172,11 @@ int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
return -1;
if (QQmlDebugService::isDebuggingEnabled())
- QV8DebugService::instance()->signalEmitted(QString::fromAscii(m_signal.signature()));
+ QV8DebugService::instance()->signalEmitted(QString::fromAscii(m_signal.methodSignature().constData()));
QQmlHandlingSignalProfiler prof;
if (prof.enabled) {
- prof.setSignalInfo(QString::fromLatin1(m_signal.signature()),
+ prof.setSignalInfo(QString::fromLatin1(m_signal.methodSignature().constData()),
m_expression->expression());
prof.setLocation(m_expression->sourceFile(), m_expression->lineNumber(),
m_expression->columnNumber());
@@ -226,14 +226,14 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
continue;
}
- QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
+ int t = QMetaType::type(type.constData());
if (QQmlMetaType::isQObject(t)) {
types[ii] = QMetaType::QObjectStar;
QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
prop.setWritable(false);
} else {
QByteArray propType = type;
- if (t >= QVariant::UserType || t == QVariant::Invalid) {
+ if (t >= int(QVariant::UserType) || t == QMetaType::UnknownType || t == QMetaType::Void) {
QByteArray scope;
QByteArray name;
int scopeIdx = propType.lastIndexOf("::");
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 9304a75fbf..51343b64d5 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -71,6 +71,7 @@
#include <QAtomicInt>
#include <QtCore/qdebug.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qvarlengtharray.h>
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<qreal>)
@@ -2830,32 +2831,37 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
}
}
+ // Size of the array that describes parameter types & names
+ int paramDataSize = (obj->aggregateDynamicSignalParameterCount() + obj->aggregateDynamicSlotParameterCount()) * 2
+ + obj->dynamicProperties.count() // for Changed() signals return types
+ // Return "parameters" don't have names
+ - (obj->dynamicSignals.count() + obj->dynamicSlots.count());
+
QFastMetaBuilder builder;
+ int paramIndex;
QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(),
obj->dynamicProperties.count() - (resolveAlias?0:aliasCount),
obj->dynamicSlots.count(),
obj->dynamicSignals.count() + obj->dynamicProperties.count(),
- defaultProperty?1:0);
+ defaultProperty?1:0, paramDataSize, &paramIndex);
struct TypeData {
Object::DynamicProperty::Type dtype;
int metaType;
- const char *cppType;
} builtinTypes[] = {
- { Object::DynamicProperty::Var, QMetaType::QVariant, "QVariant" },
- { Object::DynamicProperty::Variant, QMetaType::QVariant, "QVariant" },
- { Object::DynamicProperty::Int, QMetaType::Int, "int" },
- { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" },
- { Object::DynamicProperty::Real, QMetaType::Double, "double" },
- { Object::DynamicProperty::String, QMetaType::QString, "QString" },
- { Object::DynamicProperty::Url, QMetaType::QUrl, "QUrl" },
- { Object::DynamicProperty::Color, QMetaType::QColor, "QColor" },
- { Object::DynamicProperty::Time, QMetaType::QTime, "QTime" },
- { Object::DynamicProperty::Date, QMetaType::QDate, "QDate" },
- { Object::DynamicProperty::DateTime, QMetaType::QDateTime, "QDateTime" },
+ { Object::DynamicProperty::Var, QMetaType::QVariant },
+ { Object::DynamicProperty::Variant, QMetaType::QVariant },
+ { Object::DynamicProperty::Int, QMetaType::Int },
+ { Object::DynamicProperty::Bool, QMetaType::Bool },
+ { Object::DynamicProperty::Real, QMetaType::Double },
+ { Object::DynamicProperty::String, QMetaType::QString },
+ { Object::DynamicProperty::Url, QMetaType::QUrl },
+ { Object::DynamicProperty::Color, QMetaType::QColor },
+ { Object::DynamicProperty::Time, QMetaType::QTime },
+ { Object::DynamicProperty::Date, QMetaType::QDate },
+ { Object::DynamicProperty::DateTime, QMetaType::QDateTime },
};
static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
- QFastMetaBuilder::StringRef typeRefs[builtinTypeCount];
// Reserve dynamic properties
if (obj->dynamicProperties.count()) {
@@ -2868,18 +2874,16 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
if (p->type != Object::DynamicProperty::Alias || resolveAlias)
p->nameRef = builder.newString(p->name.utf8length());
- int propertyType = 0;
+ int metaType = 0;
+ int propertyType = 0; // for VMD
bool readonly = false;
- QFastMetaBuilder::StringRef typeRef;
if (p->type == Object::DynamicProperty::Alias) {
continue;
} else if (p->type < builtinTypeCount) {
Q_ASSERT(builtinTypes[p->type].dtype == p->type);
- propertyType = builtinTypes[p->type].metaType;
- if (typeRefs[p->type].isEmpty())
- typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType));
- typeRef = typeRefs[p->type];
+ metaType = builtinTypes[p->type].metaType;
+ propertyType = metaType;
} else {
Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
@@ -2915,9 +2919,9 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
propertyType = qMetaTypeId<QQmlListProperty<QObject> >();
}
- p->resolvedCustomTypeName = pool->NewByteArray(customTypeName);
- p->typeRef = builder.newString(customTypeName.length());
- typeRef = p->typeRef;
+ metaType = QMetaType::type(customTypeName);
+ Q_ASSERT(metaType != QMetaType::UnknownType);
+ Q_ASSERT(metaType != QMetaType::Void);
}
if (p->type == Object::DynamicProperty::Var)
@@ -2932,17 +2936,13 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
(vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType;
}
- if (p->type < builtinTypeCount)
- builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, (QMetaType::Type)propertyType,
- readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
- effectivePropertyIndex);
- else
- builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef,
- readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
- effectivePropertyIndex);
+ builder.setProperty(effectivePropertyIndex, p->nameRef, metaType,
+ readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
+ effectivePropertyIndex);
- p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
- builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
+ p->changedNameRef = builder.newString(p->name.utf8length() + strlen("Changed"));
+ builder.setSignal(effectivePropertyIndex, p->changedNameRef, paramIndex);
+ paramIndex++;
effectivePropertyIndex++;
}
@@ -2955,19 +2955,19 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
totalPropCount = varPropCount + effectivePropertyIndex;
for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
if (p->type == Object::DynamicProperty::Var) {
- QFastMetaBuilder::StringRef typeRef = typeRefs[p->type];
if (buildData) {
vmd->propertyCount++;
(vmd->propertyData() + effectivePropertyIndex)->propertyType = QMetaType::QVariant;
}
- builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef,
+ builder.setProperty(effectivePropertyIndex, p->nameRef,
QMetaType::QVariant,
p->isReadOnly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
effectivePropertyIndex);
- p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
- builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
+ p->changedNameRef = builder.newString(p->name.utf8length() + strlen("Changed"));
+ builder.setSignal(effectivePropertyIndex, p->changedNameRef, paramIndex);
+ paramIndex++;
effectivePropertyIndex++;
}
@@ -2986,8 +2986,9 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
}
// Even if we aren't resolving the alias, we need a fake signal so that the
// metaobject remains consistent across the resolve and non-resolve alias runs
- p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
- builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
+ p->changedNameRef = builder.newString(p->name.utf8length() + strlen("Changed"));
+ builder.setSignal(effectivePropertyIndex, p->changedNameRef, paramIndex);
+ paramIndex++;
effectivePropertyIndex++;
aliasIndex++;
}
@@ -3006,49 +3007,56 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
int signalIndex = 0;
for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
- int paramCount = s->parameterNames.count();
-
- int signatureSize = s->name.utf8length() + 2 /* paren */;
- int namesSize = 0;
- if (paramCount) signatureSize += s->parameterTypesLength() + (paramCount - 1) /* commas */;
- if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1) /* commas */;
+ s->nameRef = builder.newString(s->name.utf8length());
- s->signatureRef = builder.newString(signatureSize);
- if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
+ int paramCount = s->parameterNames.count();
+ QVarLengthArray<int, 10> paramTypes(paramCount);
+ if (paramCount) {
+ s->parameterNamesRef = pool->NewRawList<QFastMetaBuilder::StringRef>(paramCount);
+ for (int i = 0; i < paramCount; ++i) {
+ s->parameterNamesRef[i] = builder.newString(s->parameterNames.at(i).utf8length());
+ Q_ASSERT(s->parameterTypes.at(i) < builtinTypeCount);
+ paramTypes[i] = builtinTypes[s->parameterTypes.at(i)].metaType;
+ }
+ }
if (buildData)
((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
- builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->signatureRef, s->parameterNamesRef);
+ builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->nameRef,
+ paramIndex, paramCount, paramTypes.constData(), s->parameterNamesRef.data());
+ paramIndex += paramCount*2 + 1;
++signalIndex;
}
// Reserve dynamic slots
if (obj->dynamicSlots.count()) {
- // Allocate QVariant string
- if (typeRefs[0].isEmpty())
- typeRefs[0] = builder.newString(strlen(builtinTypes[0].cppType));
-
typedef QQmlVMEMetaData VMD;
int methodIndex = 0;
for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ s->nameRef = builder.newString(s->name.utf8length());
int paramCount = s->parameterNames.count();
- int signatureSize = s->name.utf8length() + 2 /* paren */;
- int namesSize = 0;
- if (paramCount) signatureSize += (paramCount * strlen("QVariant") + (paramCount - 1));
- if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
-
- s->signatureRef = builder.newString(signatureSize);
- if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
+ QVarLengthArray<int, 10> paramTypes(paramCount);
+ if (paramCount) {
+ s->parameterNamesRef = pool->NewRawList<QFastMetaBuilder::StringRef>(paramCount);
+ for (int i = 0; i < paramCount; ++i) {
+ s->parameterNamesRef[i] = builder.newString(s->parameterNames.at(i).size());
+ paramTypes[i] = QMetaType::QVariant;
+ }
+ }
- builder.setMethod(methodIndex, s->signatureRef, s->parameterNamesRef, typeRefs[0]);
+ builder.setMethod(methodIndex, s->nameRef, paramIndex, paramCount,
+ paramTypes.constData(), s->parameterNamesRef.data(), QMetaType::QVariant);
+ paramIndex += paramCount*2 + 1;
if (buildData) {
QString funcScript;
- funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ +
+ int namesSize = 0;
+ if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
+ funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ +
namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
for (int jj = 0; jj < paramCount; ++jj) {
@@ -3077,28 +3085,18 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
}
}
- // Now allocate used builtin types
- for (int ii = 0; ii < builtinTypeCount; ++ii) {
- if (!typeRefs[ii].isEmpty())
- typeRefs[ii].load(builtinTypes[ii].cppType);
- }
-
// Now allocate properties
for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
- char *d = p->changedSignatureRef.data();
+ char *d = p->changedNameRef.data();
p->name.writeUtf8(d);
- strcpy(d + p->name.utf8length(), "Changed()");
+ strcpy(d + p->name.utf8length(), "Changed");
+ p->changedNameRef.loadByteArrayData();
if (p->type == Object::DynamicProperty::Alias && !resolveAlias)
continue;
p->nameRef.load(p->name);
-
- if (p->type >= builtinTypeCount) {
- Q_ASSERT(p->resolvedCustomTypeName);
- p->typeRef.load(*p->resolvedCustomTypeName);
- }
}
// Allocate default property if necessary
@@ -3108,39 +3106,18 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
// Now allocate signals
for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
- char *d = s->signatureRef.data();
- char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
- s->name.writeUtf8(d); d += s->name.utf8length();
- *d++ = '(';
+ s->nameRef.load(s->name);
- for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
- if (jj != 0) { *d++ = ','; *d2++ = ','; }
- strcpy(d, s->parameterTypes.at(jj).constData());
- d += s->parameterTypes.at(jj).length();
- s->parameterNames.at(jj).writeUtf8(d2);
- d2 += s->parameterNames.at(jj).utf8length();
- }
- *d++ = ')';
- *d = 0;
- if (d2) *d2 = 0;
+ for (int jj = 0; jj < s->parameterNames.count(); ++jj)
+ s->parameterNamesRef[jj].load(s->parameterNames.at(jj));
}
// Now allocate methods
for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- char *d = s->signatureRef.data();
- char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
- s->name.writeUtf8(d); d += s->name.utf8length();
- *d++ = '(';
- for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
- if (jj != 0) { *d++ = ','; *d2++ = ','; }
- strcpy(d, "QVariant");
- d += strlen("QVariant");
- strcpy(d2, s->parameterNames.at(jj).constData());
- d2 += s->parameterNames.at(jj).length();
- }
- *d++ = ')';
- *d = 0;
- if (d2) *d2 = 0;
+ s->nameRef.load(s->name);
+
+ for (int jj = 0; jj < s->parameterNames.count(); ++jj)
+ s->parameterNamesRef[jj].load(s->parameterNames.at(jj).constData());
}
// Now allocate class name
@@ -3233,7 +3210,6 @@ bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
Object::DynamicProperty &prop)
{
Q_ASSERT(!prop.nameRef.isEmpty());
- Q_ASSERT(prop.typeRef.isEmpty());
if (!prop.defaultValue)
COMPILE_EXCEPTION(obj, tr("No property alias location"));
@@ -3278,9 +3254,7 @@ bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
writable = aliasProperty.isWritable() && !prop.isReadOnly;
resettable = aliasProperty.isResettable() && !prop.isReadOnly;
- if (aliasProperty.type() < QVariant::UserType
- || uint(aliasProperty.type()) == QMetaType::QVariant)
- type = aliasProperty.type();
+ type = aliasProperty.userType();
if (alias.count() == 3) {
QQmlValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()];
@@ -3298,9 +3272,7 @@ bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
propIdx |= (valueTypeIndex << 16);
// update the property type
- type = aliasProperty.type();
- if (type >= (int)QVariant::UserType)
- type = 0;
+ type = aliasProperty.userType();
}
if (aliasProperty.isEnumType())
@@ -3322,22 +3294,26 @@ bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
if (typeName.endsWith('*'))
flags |= QML_ALIAS_FLAG_PTR;
+ if (type == QMetaType::UnknownType) {
+ Q_ASSERT(!typeName.isEmpty());
+ type = QMetaType::type(typeName);
+ Q_ASSERT(type != QMetaType::UnknownType);
+ Q_ASSERT(type != QMetaType::Void);
+ }
+
QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags };
typedef QQmlVMEMetaData VMD;
VMD *vmd = (QQmlVMEMetaData *)data.data();
*(vmd->aliasData() + aliasIndex) = aliasData;
- prop.resolvedCustomTypeName = pool->NewByteArray(typeName);
- prop.typeRef = builder.newString(typeName.length());
-
int propertyFlags = 0;
if (writable)
propertyFlags |= QFastMetaBuilder::Writable;
if (resettable)
propertyFlags |= QFastMetaBuilder::Resettable;
- builder.setProperty(propIndex, prop.nameRef, prop.typeRef, (QMetaType::Type)type,
+ builder.setProperty(propIndex, prop.nameRef, type,
(QFastMetaBuilder::PropertyFlag)propertyFlags,
propIndex);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 489b4f895a..16cd1ecde6 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -59,7 +59,6 @@
#include "qquickworkerscript_p.h"
#include "qqmlcomponent_p.h"
#include "qqmlnetworkaccessmanagerfactory.h"
-#include "qqmlimageprovider.h"
#include "qqmldirparser_p.h"
#include "qqmlextensioninterface.h"
#include "qqmllist_p.h"
@@ -179,6 +178,12 @@ void QQmlEnginePrivate::defineModule()
qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
}
+
+QQmlImageProviderBase::~QQmlImageProviderBase()
+{
+}
+
+
/*!
\qmlclass Qt QQmlEnginePrivate
\ingroup qml-utility-elements
@@ -670,27 +675,29 @@ QNetworkAccessManager *QQmlEngine::networkAccessManager() const
takes ownership of \a provider.
Image providers enable support for pixmap and threaded image
- requests. See the QQmlImageProvider documentation for details on
+ requests. See the QQuickImageProvider documentation for details on
implementing and using image providers.
All required image providers should be added to the engine before any
QML sources files are loaded.
- \sa removeImageProvider()
+ \sa removeImageProvider(), QQuickImageProvider
*/
-void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
+void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
{
Q_D(QQmlEngine);
QMutexLocker locker(&d->mutex);
- d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
+ d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
}
/*!
- Returns the QQmlImageProvider set for \a providerId.
+ Returns the image provider set for \a providerId.
Returns the provider if it was found; otherwise returns 0.
+
+ \sa QQuickImageProvider
*/
-QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
+QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
{
Q_D(const QQmlEngine);
QMutexLocker locker(&d->mutex);
@@ -698,9 +705,9 @@ QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
}
/*!
- Removes the QQmlImageProvider for \a providerId.
+ Removes the image provider for \a providerId.
- \sa addImageProvider()
+ \sa addImageProvider(), QQuickImageProvider
*/
void QQmlEngine::removeImageProvider(const QString &providerId)
{
@@ -709,54 +716,6 @@ void QQmlEngine::removeImageProvider(const QString &providerId)
d->imageProviders.take(providerId);
}
-QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
-{
- QMutexLocker locker(&mutex);
- QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
- locker.unlock();
- if (provider)
- return provider->imageType();
- return QQmlImageProvider::Invalid;
-}
-
-QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
-{
- QMutexLocker locker(&mutex);
- QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
- locker.unlock();
- if (provider) {
- QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
- return provider->requestTexture(imageId, size, req_size);
- }
- return 0;
-}
-
-QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
-{
- QMutexLocker locker(&mutex);
- QImage image;
- QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
- locker.unlock();
- if (provider) {
- QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
- image = provider->requestImage(imageId, size, req_size);
- }
- return image;
-}
-
-QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
-{
- QMutexLocker locker(&mutex);
- QPixmap pixmap;
- QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
- locker.unlock();
- if (provider) {
- QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
- pixmap = provider->requestPixmap(imageId, size, req_size);
- }
- return pixmap;
-}
-
/*!
Return the base URL for this engine. The base URL is only used to
resolve components when a relative URL is passed to the
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 04ac61c05b..41696923c5 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -54,6 +54,12 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
+class Q_QML_EXPORT QQmlImageProviderBase
+{
+public:
+ virtual ~QQmlImageProviderBase();
+};
+
class QQmlComponent;
class QQmlEnginePrivate;
class QQmlImportsPrivate;
@@ -62,7 +68,6 @@ class QQmlContext;
class QQmlType;
class QUrl;
class QScriptContext;
-class QQmlImageProvider;
class QNetworkAccessManager;
class QQmlNetworkAccessManagerFactory;
class QQmlIncubationController;
@@ -94,8 +99,8 @@ public:
QNetworkAccessManager *networkAccessManager() const;
- void addImageProvider(const QString &id, QQmlImageProvider *);
- QQmlImageProvider *imageProvider(const QString &id) const;
+ void addImageProvider(const QString &id, QQmlImageProviderBase *);
+ QQmlImageProviderBase *imageProvider(const QString &id) const;
void removeImageProvider(const QString &id);
void setIncubationController(QQmlIncubationController *);
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index db834489ba..73a0b5a217 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -63,7 +63,6 @@
#include "qqmlcontext.h"
#include "qqmlcontext_p.h"
#include "qqmlexpression.h"
-#include "qqmlimageprovider.h"
#include "qqmlproperty_p.h"
#include "qqmlpropertycache_p.h"
#include "qqmlmetatype_p.h"
@@ -173,11 +172,7 @@ public:
mutable QNetworkAccessManager *networkAccessManager;
mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory;
- QHash<QString,QSharedPointer<QQmlImageProvider> > imageProviders;
- QQmlImageProvider::ImageType getImageProviderType(const QUrl &url);
- QQuickTextureFactory *getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
- QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
- QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
+ QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders;
// Scarce resources are "exceptionally high cost" QVariant types where allowing the
// normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
diff --git a/src/qml/qml/qqmlerror.h b/src/qml/qml/qqmlerror.h
index 3c148549d0..73581e29aa 100644
--- a/src/qml/qml/qqmlerror.h
+++ b/src/qml/qml/qqmlerror.h
@@ -80,6 +80,8 @@ private:
QDebug Q_QML_EXPORT operator<<(QDebug debug, const QQmlError &error);
+Q_DECLARE_TYPEINFO(QQmlError, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/qml/qml/qqmlimageprovider.cpp b/src/qml/qml/qqmlimageprovider.cpp
deleted file mode 100644
index d1afa54498..0000000000
--- a/src/qml/qml/qqmlimageprovider.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlimageprovider.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQmlImageProviderPrivate
-{
-public:
- QQmlImageProvider::ImageType type;
-};
-
-/*!
- \class QQuickTextureFactory
- \since 5.0
- \brief The QQuickTextureFactory class provides an interface for loading custom textures from QML.
-
- The purpose of the texture factory is to provide a placeholder for a image
- data that can be converted into an OpenGL texture.
-
- Creating a texture directly is not possible as there is rarely an OpenGL context
- available in the thread that is responsible for loading the image data.
- */
-
-QQuickTextureFactory::QQuickTextureFactory()
-{
-}
-
-QQuickTextureFactory::~QQuickTextureFactory()
-{
-}
-
-
-/*!
- \fn QImage QQuickTextureFactory::image() const
-
- Returns an image version of this texture.
-
- The lifespan of the returned image is unknown, so the implementation should
- return a self contained QImage, not make use of the QImage(uchar *, ...)
- constructor.
-
- This function is not commonly used and is expected to be slow.
- */
-
-QImage QQuickTextureFactory::image() const
-{
- return QImage();
-}
-
-
-/*!
- \fn QSGTexture *QQuickTextureFactory::createTexture() const
-
- This function is called on the scene graph rendering thread to create a QSGTexture
- instance from the factory.
-
- QML will internally cache the returned texture as needed. Each call to this
- function should return a unique instance.
-
- The OpenGL context used for rendering is bound when this function is called.
- */
-
-/*!
- \fn QSize QQuickTextureFactory::textureSize() const
-
- Returns the size of the texture. This function will be called from arbitrary threads
- and should not rely on an OpenGL context bound.
- */
-
-
-/*!
- \class QQmlImageProvider
- \since 4.7
- \brief The QQmlImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML.
-
- QQmlImageProvider is used to provide advanced image loading features
- in QML applications. It allows images in QML to be:
-
- \list
- \li Loaded using QPixmaps rather than actual image files
- \li Loaded asynchronously in a separate thread, if imageType() is \l{QQmlImageProvider::ImageType}{ImageType::Image}
- \endlist
-
- To specify that an image should be loaded by an image provider, use the
- \b {"image:"} scheme for the URL source of the image, followed by the
- identifiers of the image provider and the requested image. For example:
-
- \qml
- Image { source: "image://myimageprovider/image.png" }
- \endqml
-
- This specifies that the image should be loaded by the image provider named
- "myimageprovider", and the image to be loaded is named "image.png". The QML engine
- invokes the appropriate image provider according to the providers that have
- been registered through QQmlEngine::addImageProvider().
-
- Note that the identifiers are case-insensitive, but the rest of the URL will be passed on with
- preserved case. For example, the below snippet would still specify that the image is loaded by the
- image provider named "myimageprovider", but it would request a different image than the above snippet
- ("Image.png" instead of "image.png").
- \qml
- Image { source: "image://MyImageProvider/Image.png" }
- \endqml
-
- If you want the rest of the URL to be case insensitive, you will have to take care
- of that yourself inside your image provider.
-
- \section2 An example
-
- Here are two images. Their \c source values indicate they should be loaded by
- an image provider named "colors", and the images to be loaded are "yellow"
- and "red", respectively:
-
- \snippet examples/declarative/cppextensions/imageprovider/imageprovider-example.qml 0
-
- When these images are loaded by QML, it looks for a matching image provider
- and calls its requestImage() or requestPixmap() method (depending on its
- imageType()) to load the image. The method is called with the \c id
- parameter set to "yellow" for the first image, and "red" for the second.
-
- Here is an image provider implementation that can load the images
- requested by the above QML. This implementation dynamically
- generates QPixmap images that are filled with the requested color:
-
- \snippet examples/declarative/cppextensions/imageprovider/imageprovider.cpp 0
- \codeline
- \snippet examples/declarative/cppextensions/imageprovider/imageprovider.cpp 1
-
- To make this provider accessible to QML, it is registered with the QML engine
- with a "colors" identifier:
-
- \code
- int main(int argc, char *argv[])
- {
- ...
-
- QQmlEngine engine;
- engine->addImageProvider(QLatin1String("colors"), new ColorPixmapProvider);
-
- ...
- }
- \endcode
-
- Now the images can be successfully loaded in QML:
-
- \image imageprovider.png
-
- A complete example is available in Qt's
- \l {declarative/cppextensions/imageprovider}{examples/declarative/cppextensions/imageprovider}
- directory. Note the example registers the provider via a \l{QQmlExtensionPlugin}{plugin}
- instead of registering it in the application \c main() function as shown above.
-
-
- \section2 Asynchronous image loading
-
- Image providers that support QImage loading automatically include support
- for asychronous loading of images. To enable asynchronous loading for an
- image source, set the \c asynchronous property to \c true for the relevant
- \l Image, \l BorderImage or \l AnimatedImage object. When this is enabled,
- the image request to the provider is run in a low priority thread,
- allowing image loading to be executed in the background, and reducing the
- performance impact on the user interface.
-
- Asynchronous loading is not supported for image providers that provide
- QPixmap rather than QImage values, as pixmaps can only be created in the
- main thread. In this case, if \l {Image::}{asynchronous} is set to
- \c true, the value is ignored and the image is loaded
- synchronously.
-
-
- \section2 Image caching
-
- Images returned by a QQmlImageProvider are automatically cached,
- similar to any image loaded by the QML engine. When an image with a
- "image://" prefix is loaded from cache, requestImage() and requestPixmap()
- will not be called for the relevant image provider. If an image should always
- be fetched from the image provider, and should not be cached at all, set the
- \c cache property to \c false for the relevant \l Image, \l BorderImage or
- \l AnimatedImage object.
-
- \sa QQmlEngine::addImageProvider()
-*/
-
-/*!
- \enum QQmlImageProvider::ImageType
-
- Defines the type of image supported by this image provider.
-
- \value Image The Image Provider provides QImage images. The
- requestImage() method will be called for all image requests.
- \value Pixmap The Image Provider provides QPixmap images. The
- requestPixmap() method will be called for all image requests.
- \value Texture The Image Provider provides QSGTextureProvider based images.
- The requestTexture() method will be called for all image requests. \omitvalue
-*/
-
-/*!
- Creates an image provider that will provide images of the given \a type.
-*/
-QQmlImageProvider::QQmlImageProvider(ImageType type)
- : d(new QQmlImageProviderPrivate)
-{
- d->type = type;
-}
-
-/*!
- Destroys the QQmlImageProvider
-
- \note The destructor of your derived class need to be thread safe.
-*/
-QQmlImageProvider::~QQmlImageProvider()
-{
- delete d;
-}
-
-/*!
- Returns the image type supported by this provider.
-*/
-QQmlImageProvider::ImageType QQmlImageProvider::imageType() const
-{
- return d->type;
-}
-
-/*!
- Implement this method to return the image with \a id. The default
- implementation returns an empty image.
-
- The \a id is the requested image source, with the "image:" scheme and
- provider identifier removed. For example, if the image \l{Image::}{source}
- was "image://myprovider/icons/home", the given \a id would be "icons/home".
-
- The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
- an Image element. If \a requestedSize is a valid size, the image
- returned should be of that size.
-
- In all cases, \a size must be set to the original size of the image. This
- is used to set the \l {Item::}{width} and \l {Item::}{height} of the
- relevant \l Image if these values have not been set explicitly.
-
- \note this method may be called by multiple threads, so ensure the
- implementation of this method is reentrant.
-*/
-QImage QQmlImageProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize)
-{
- Q_UNUSED(id);
- Q_UNUSED(size);
- Q_UNUSED(requestedSize);
- if (d->type == Image)
- qWarning("ImageProvider supports Image type but has not implemented requestImage()");
- return QImage();
-}
-
-/*!
- Implement this method to return the pixmap with \a id. The default
- implementation returns an empty pixmap.
-
- The \a id is the requested image source, with the "image:" scheme and
- provider identifier removed. For example, if the image \l{Image::}{source}
- was "image://myprovider/icons/home", the given \a id would be "icons/home".
-
- The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
- an Image element. If \a requestedSize is a valid size, the image
- returned should be of that size.
-
- In all cases, \a size must be set to the original size of the image. This
- is used to set the \l {Item::}{width} and \l {Item::}{height} of the
- relevant \l Image if these values have not been set explicitly.
-*/
-QPixmap QQmlImageProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
-{
- Q_UNUSED(id);
- Q_UNUSED(size);
- Q_UNUSED(requestedSize);
- if (d->type == Pixmap)
- qWarning("ImageProvider supports Pixmap type but has not implemented requestPixmap()");
- return QPixmap();
-}
-
-
-/*!
- Implement this method to return the texture with \a id. The default
- implementation returns 0.
-
- The \a id is the requested image source, with the "image:" scheme and
- provider identifier removed. For example, if the image \l{Image::}{source}
- was "image://myprovider/icons/home", the given \a id would be "icons/home".
-
- The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
- an Image element. If \a requestedSize is a valid size, the image
- returned should be of that size.
-
- In all cases, \a size must be set to the original size of the image. This
- is used to set the \l {Item::}{width} and \l {Item::}{height} of the
- relevant \l Image if these values have not been set explicitly.
-
- \note this method may be called by multiple threads, so ensure the
- implementation of this method is reentrant.
-*/
-
-QQuickTextureFactory *QQmlImageProvider::requestTexture(const QString &id, QSize *size, const QSize &requestedSize)
-{
- Q_UNUSED(id);
- Q_UNUSED(size);
- Q_UNUSED(requestedSize);
- if (d->type == Texture)
- qWarning("ImageProvider supports Texture type but has not implemented requestTexture()");
- return 0;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/qml/qqmlimageprovider.h b/src/qml/qml/qqmlimageprovider.h
deleted file mode 100644
index da4d8c8248..0000000000
--- a/src/qml/qml/qqmlimageprovider.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLIMAGEPROVIDER_H
-#define QQMLIMAGEPROVIDER_H
-
-#include <QtQml/qtqmlglobal.h>
-#include <QtGui/qimage.h>
-#include <QtGui/qpixmap.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlImageProviderPrivate;
-class QSGTexture;
-class QQuickCanvas;
-
-class Q_QML_EXPORT QQuickTextureFactory : public QObject
-{
-public:
- QQuickTextureFactory();
- virtual ~QQuickTextureFactory();
-
- virtual QSGTexture *createTexture(QQuickCanvas *canvas) const = 0;
- virtual QSize textureSize() const = 0;
- virtual int textureByteCount() const = 0;
- virtual QImage image() const;
-};
-
-class Q_QML_EXPORT QQmlImageProvider
-{
-public:
- enum ImageType {
- Image,
- Pixmap,
- Texture,
- Invalid
- };
-
- QQmlImageProvider(ImageType type);
- virtual ~QQmlImageProvider();
-
- ImageType imageType() const;
-
- virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize);
- virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize);
- virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize);
-
-private:
- QQmlImageProviderPrivate *d;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQMLIMAGEPROVIDER
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 2061530dc5..5b80f57d01 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -340,9 +340,7 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
QMetaMethod method = mo->method(ii);
// More complex - need to search name
- QByteArray name = method.signature();
- int parenIdx = name.indexOf('(');
- if (parenIdx != -1) name = name.left(parenIdx);
+ QByteArray name = method.name();
bool found = false;
@@ -352,11 +350,8 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
++ii) {
QMetaMethod other = ignoreEnd->method(ii);
- QByteArray othername = other.signature();
- int parenIdx = othername.indexOf('(');
- if (parenIdx != -1) othername = othername.left(parenIdx);
- found = name == othername;
+ found = name == other.name();
}
QMetaMethodBuilder m = builder.addMethod(method);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 14778ce6c8..d3778fa5c5 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -334,7 +334,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
signalName[0] = signalName.at(0).toLower();
QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName.toLatin1().constData());
- if (method.signature()) {
+ if (method.isValid()) {
object = currentObject;
core.load(method);
return;
@@ -1148,7 +1148,7 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
return false;
} else if (v.userType() != QVariant::Int && v.userType() != QVariant::UInt) {
int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope() + QByteArray("::") + menum.name()));
- if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
return false;
v = QVariant(*reinterpret_cast<const int *>(v.constData()));
}
@@ -1487,6 +1487,17 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
if (expression->hasError()) {
return false;
+ } else if (isVmeProperty) {
+ typedef QQmlVMEMetaObject VMEMO;
+ if (!result.IsEmpty() && result->IsFunction()
+ && !result->ToObject()->GetHiddenValue(v8engine->bindingFlagKey()).IsEmpty()) {
+ // we explicitly disallow this case to avoid confusion. Users can still store one
+ // in an array in a var property if they need to, but the common case is user error.
+ expression->delayedError()->error.setDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ return false;
+ }
+ VMEMO *vmemo = static_cast<VMEMO *>(const_cast<QMetaObject *>(object->metaObject()));
+ vmemo->setVMEProperty(core.coreIndex, result);
} else if (isUndefined && core.isResettable()) {
void *args[] = { 0 };
QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args);
@@ -1496,12 +1507,11 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
expression->delayedError()->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(type)));
return false;
} else if (result->IsFunction()) {
- expression->delayedError()->error.setDescription(QLatin1String("Unable to assign a function to a property."));
+ if (!result->ToObject()->GetHiddenValue(v8engine->bindingFlagKey()).IsEmpty())
+ expression->delayedError()->error.setDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ else
+ expression->delayedError()->error.setDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
return false;
- } else if (isVmeProperty) {
- typedef QQmlVMEMetaObject VMEMO;
- VMEMO *vmemo = static_cast<VMEMO *>(const_cast<QMetaObject *>(object->metaObject()));
- vmemo->setVMEProperty(core.coreIndex, result);
} else if (!writeValueProperty(object, engine, core, value, context, flags)) {
if (watcher.wasDeleted())
@@ -1680,7 +1690,7 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
- QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
+ QByteArray signal(QByteArray("2") + prop.notifySignal().methodSignature());
return QObject::connect(d->object, signal.constData(), dest, slot);
} else {
return false;
@@ -1786,11 +1796,8 @@ QMetaMethod QQmlPropertyPrivate::findSignalByName(const QMetaObject *mo, const Q
int methods = mo->methodCount();
for (int ii = methods - 1; ii >= 2; --ii) { // >= 2 to block the destroyed signal
QMetaMethod method = mo->method(ii);
- QByteArray methodName = method.signature();
- int idx = methodName.indexOf('(');
- methodName = methodName.left(idx);
- if (methodName == name)
+ if (method.name() == name)
return method;
}
diff --git a/src/qml/qml/qqmlproperty.h b/src/qml/qml/qqmlproperty.h
index 2c4b2544c1..bd2b1d35ba 100644
--- a/src/qml/qml/qqmlproperty.h
+++ b/src/qml/qml/qqmlproperty.h
@@ -136,6 +136,8 @@ inline uint qHash (const QQmlProperty &key)
return qHash(key.object()) + qHash(key.name());
}
+Q_DECLARE_TYPEINFO(QQmlProperty, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 93c6aa1f00..af6cd9285b 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -176,19 +176,11 @@ void QQmlPropertyData::load(const QMetaMethod &m)
flags |= IsFunction;
if (m.methodType() == QMetaMethod::Signal)
flags |= IsSignal;
- propType = QVariant::Invalid;
-
- const char *returnType = m.typeName();
- if (returnType)
- propType = QMetaType::type(returnType);
+ propType = m.returnType();
- const char *signature = m.signature();
- while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; }
-
- ++signature;
- if (*signature != ')') {
+ if (m.parameterCount()) {
flags |= HasArguments;
- if (0 == ::strcmp(signature, "QQmlV8Function*)")) {
+ if ((m.parameterCount() == 1) && (m.parameterTypes().first() == "QQmlV8Function*")) {
flags |= IsV8Function;
}
}
@@ -212,13 +204,9 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
flags |= NotFullyResolved;
}
- const char *signature = m.signature();
- while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; }
-
- ++signature;
- if (*signature != ')') {
+ if (m.parameterCount()) {
flags |= HasArguments;
- if (0 == ::strcmp(signature, "QQmlV8Function*)")) {
+ if ((m.parameterCount() == 1) && (m.parameterTypes().first() == "QQmlV8Function*")) {
flags |= IsV8Function;
}
}
@@ -414,10 +402,17 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
continue;
// Extract method name
- const char *signature = m.signature();
+ const char *signature;
+ if (QMetaObjectPrivate::get(metaObject)->revision >= 7) {
+ // Safe to use the raw name pointer
+ signature = m.name().constData();
+ } else {
+ // Safe to use the raw signature pointer
+ signature = m.methodSignature().constData();
+ }
const char *cptr = signature;
char utf8 = 0;
- while (*cptr != '(') {
+ while (*cptr && *cptr != '(') {
Q_ASSERT(*cptr != 0);
utf8 |= *cptr & 0x80;
++cptr;
@@ -663,11 +658,7 @@ QString QQmlPropertyData::name(const QMetaObject *metaObject)
if (flags & IsFunction) {
QMetaMethod m = metaObject->method(coreIndex);
- QString name = QString::fromUtf8(m.signature());
- int parenIdx = name.indexOf(QLatin1Char('('));
- if (parenIdx != -1)
- name = name.left(parenIdx);
- return name;
+ return QString::fromUtf8(m.name().constData());
} else {
QMetaProperty p = metaObject->property(coreIndex);
return QString::fromUtf8(p.name());
@@ -727,15 +718,19 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
const QMetaObject *metaObject = object->metaObject();
QMetaMethod m = metaObject->method(index);
- QList<QByteArray> argTypeNames = m.parameterTypes();
- A *args = static_cast<A *>(malloc(sizeof(A) + (argTypeNames.count() + 1) * sizeof(int)));
- args->arguments[0] = argTypeNames.count();
+ int argc = m.parameterCount();
+ A *args = static_cast<A *>(malloc(sizeof(A) + (argc + 1) * sizeof(int)));
+ args->arguments[0] = argc;
+ QList<QByteArray> argTypeNames; // Only loaded if needed
- for (int ii = 0; ii < argTypeNames.count(); ++ii) {
- int type = QMetaType::type(argTypeNames.at(ii));
- if (type == QVariant::Invalid)
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+ if (type == QVariant::Invalid) {
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
type = EnumType(object->metaObject(), argTypeNames.at(ii));
+ }
if (type == QVariant::Invalid) {
if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
free(args);
@@ -751,14 +746,18 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
} else {
QMetaMethod m = object->metaObject()->method(index);
- QList<QByteArray> argTypeNames = m.parameterTypes();
- dummy.resize(argTypeNames.count() + 1);
- dummy[0] = argTypeNames.count();
+ int argc = m.parameterCount();
+ dummy.resize(argc + 1);
+ dummy[0] = argc;
+ QList<QByteArray> argTypeNames; // Only loaded if needed
- for (int ii = 0; ii < argTypeNames.count(); ++ii) {
- int type = QMetaType::type(argTypeNames.at(ii));
- if (type == QVariant::Invalid)
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+ if (type == QVariant::Invalid) {
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
type = EnumType(object->metaObject(), argTypeNames.at(ii));
+ }
if (type == QVariant::Invalid) {
if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
return 0;
@@ -804,13 +803,9 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject,
QMetaMethod m = metaObject->method(ii);
if (m.access() == QMetaMethod::Private)
continue;
- QString methodName = QString::fromUtf8(m.signature());
-
- int parenIdx = methodName.indexOf(QLatin1Char('('));
- Q_ASSERT(parenIdx != -1);
- QStringRef methodNameRef = methodName.leftRef(parenIdx);
+ QString methodName = QString::fromUtf8(m.name().constData());
- if (methodNameRef == property) {
+ if (methodName == property) {
rv.load(m);
return rv;
}
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index 8e22e488ed..e1925eb238 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -182,33 +182,30 @@ Property *QQmlScript::Object::getProperty(const QString &name, bool create)
}
}
-QQmlScript::Object::DynamicProperty::DynamicProperty()
-: isDefaultProperty(false), isReadOnly(false), type(Variant), defaultValue(0), nextProperty(0),
- resolvedCustomTypeName(0)
+int QQmlScript::Object::aggregateDynamicSignalParameterCount() const
{
+ int sum = 0;
+ for (DynamicSignal *s = dynamicSignals.first(); s; s = dynamicSignals.next(s))
+ sum += s->parameterTypes.count() + 1; // +1 for return type
+ return sum;
}
-QQmlScript::Object::DynamicSignal::DynamicSignal()
-: nextSignal(0)
+int QQmlScript::Object::aggregateDynamicSlotParameterCount() const
{
+ int sum = 0;
+ for (DynamicSlot *s = dynamicSlots.first(); s; s = dynamicSlots.next(s))
+ sum += s->parameterNames.count() + 1; // +1 for return type
+ return sum;
}
-// Returns length in utf8 bytes
-int QQmlScript::Object::DynamicSignal::parameterTypesLength() const
+QQmlScript::Object::DynamicProperty::DynamicProperty()
+: isDefaultProperty(false), isReadOnly(false), type(Variant), defaultValue(0), nextProperty(0)
{
- int rv = 0;
- for (int ii = 0; ii < parameterTypes.count(); ++ii)
- rv += parameterTypes.at(ii).length();
- return rv;
}
-// Returns length in utf8 bytes
-int QQmlScript::Object::DynamicSignal::parameterNamesLength() const
+QQmlScript::Object::DynamicSignal::DynamicSignal()
+: nextSignal(0)
{
- int rv = 0;
- for (int ii = 0; ii < parameterNames.count(); ++ii)
- rv += parameterNames.at(ii).utf8length();
- return rv;
}
QQmlScript::Object::DynamicSlot::DynamicSlot()
@@ -919,25 +916,23 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
const char *name;
int nameLength;
Object::DynamicProperty::Type type;
- const char *qtName;
- int qtNameLength;
} propTypeNameToTypes[] = {
- { "int", strlen("int"), Object::DynamicProperty::Int, "int", strlen("int") },
- { "bool", strlen("bool"), Object::DynamicProperty::Bool, "bool", strlen("bool") },
- { "double", strlen("double"), Object::DynamicProperty::Real, "double", strlen("double") },
- { "real", strlen("real"), Object::DynamicProperty::Real, "double", strlen("double") },
- { "string", strlen("string"), Object::DynamicProperty::String, "QString", strlen("QString") },
- { "url", strlen("url"), Object::DynamicProperty::Url, "QUrl", strlen("QUrl") },
- { "color", strlen("color"), Object::DynamicProperty::Color, "QColor", strlen("QColor") },
+ { "int", strlen("int"), Object::DynamicProperty::Int },
+ { "bool", strlen("bool"), Object::DynamicProperty::Bool },
+ { "double", strlen("double"), Object::DynamicProperty::Real },
+ { "real", strlen("real"), Object::DynamicProperty::Real },
+ { "string", strlen("string"), Object::DynamicProperty::String },
+ { "url", strlen("url"), Object::DynamicProperty::Url },
+ { "color", strlen("color"), Object::DynamicProperty::Color },
// Internally QTime, QDate and QDateTime are all supported.
// To be more consistent with JavaScript we expose only
// QDateTime as it matches closely with the Date JS type.
// We also call it "date" to match.
- // { "time", strlen("time"), Object::DynamicProperty::Time, "QTime", strlen("QTime") },
- // { "date", strlen("date"), Object::DynamicProperty::Date, "QDate", strlen("QDate") },
- { "date", strlen("date"), Object::DynamicProperty::DateTime, "QDateTime", strlen("QDateTime") },
- { "variant", strlen("variant"), Object::DynamicProperty::Variant, "QVariant", strlen("QVariant") },
- { "var", strlen("var"), Object::DynamicProperty::Var, "QVariant", strlen("QVariant") }
+ // { "time", strlen("time"), Object::DynamicProperty::Time },
+ // { "date", strlen("date"), Object::DynamicProperty::Date },
+ { "date", strlen("date"), Object::DynamicProperty::DateTime },
+ { "variant", strlen("variant"), Object::DynamicProperty::Variant },
+ { "var", strlen("var"), Object::DynamicProperty::Var }
};
static const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
sizeof(propTypeNameToTypes[0]);
@@ -952,7 +947,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
p = node->parameters;
if (paramLength) {
- signal->parameterTypes = _parser->_pool.NewRawList<QHashedCStringRef>(paramLength);
+ signal->parameterTypes = _parser->_pool.NewRawList<Object::DynamicProperty::Type>(paramLength);
signal->parameterNames = _parser->_pool.NewRawList<QHashedStringRef>(paramLength);
}
@@ -979,7 +974,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
return false;
}
- signal->parameterTypes[index] = QHashedCStringRef(type->qtName, type->qtNameLength);
+ signal->parameterTypes[index] = type->type;
signal->parameterNames[index] = QHashedStringRef(p->name);
p = p->next;
index++;
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index ddf4c9a392..8705f2aef9 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -406,10 +406,8 @@ public:
DynamicProperty *nextProperty;
// Used by the compiler
- QByteArray *resolvedCustomTypeName;
- QFastMetaBuilder::StringRef typeRef;
QFastMetaBuilder::StringRef nameRef;
- QFastMetaBuilder::StringRef changedSignatureRef;
+ QFastMetaBuilder::StringRef changedNameRef;
};
struct DynamicSignal : public QQmlPool::POD
@@ -417,18 +415,15 @@ public:
DynamicSignal();
QHashedStringRef name;
- QQmlPool::List<QHashedCStringRef> parameterTypes;
+ QQmlPool::List<DynamicProperty::Type> parameterTypes;
QQmlPool::List<QHashedStringRef> parameterNames;
- int parameterTypesLength() const;
- int parameterNamesLength() const;
-
// Used by Object::DynamicSignalList
DynamicSignal *nextSignal;
// Used by the compiler
- QFastMetaBuilder::StringRef signatureRef;
- QFastMetaBuilder::StringRef parameterNamesRef;
+ QFastMetaBuilder::StringRef nameRef;
+ QQmlPool::List<QFastMetaBuilder::StringRef> parameterNamesRef;
LocationSpan location;
};
@@ -447,8 +442,8 @@ public:
DynamicSlot *nextSlot;
// Used by the compiler
- QFastMetaBuilder::StringRef signatureRef;
- QFastMetaBuilder::StringRef parameterNamesRef;
+ QFastMetaBuilder::StringRef nameRef;
+ QQmlPool::List<QFastMetaBuilder::StringRef> parameterNamesRef;
};
// The list of dynamic properties
@@ -461,6 +456,9 @@ public:
typedef QFieldList<DynamicSlot, &DynamicSlot::nextSlot> DynamicSlotList;
DynamicSlotList dynamicSlots;
+ int aggregateDynamicSignalParameterCount() const;
+ int aggregateDynamicSlotParameterCount() const;
+
// Used by compiler
QQmlCompilerTypes::ComponentCompileState *componentCompileState;
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 2a7ea45053..86e9f0963a 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -690,11 +690,14 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
if (prop.type() & QQmlProperty::SignalProperty) {
QMetaMethod method = QQmlMetaType::defaultMethod(assign);
- if (method.signature() == 0)
+ if (!method.isValid())
VME_EXCEPTION(tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
- if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
- VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line);
+ if (!QMetaObject::checkConnectArgs(prop.method(), method)) {
+ VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2")
+ .arg(QString::fromLatin1(method.methodSignature().constData()))
+ .arg(QString::fromLatin1(prop.method().methodSignature().constData())), instr.line);
+ }
QQmlPropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index cc4ba091ce..c4e801f2db 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -760,7 +760,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
// performance reasons; see QTBUG-24064) and thus compilation will have failed.
QQmlError e;
e.setDescription(QString(QLatin1String("Exception occurred during compilation of function: %1")).
- arg(QLatin1String(QMetaObject::method(_id).signature())));
+ arg(QLatin1String(QMetaObject::method(_id).methodSignature().constData())));
ep->warning(e);
return -1; // The dynamic method with that id is not available.
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index b9f2b627da..68c62ef240 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1333,6 +1333,65 @@ v8::Handle<v8::Value> locale(const v8::Arguments &args)
return QQmlLocale::locale(v8engine, code);
}
+/*!
+ \qmlmethod Qt::binding(function)
+
+ Returns a JS object representing a binding expression which may be
+ assigned to any property in imperative code to cause a binding
+ assignment.
+
+ There are two main use-cases for the function: firstly, in imperative
+ JavaScript code to cause a binding assignment:
+
+ \snippet doc/src/snippets/declarative/qtBinding.1.qml 0
+
+ and secondly, when defining initial property values of dynamically
+ constructed objects (via Component.createObject() or
+ Loader.setSource()) as being bound to the result of an expression.
+
+ For example, assuming the existence of a DynamicText component:
+ \snippet doc/src/snippets/declarative/DynamicText.qml 0
+
+ the output from:
+ \snippet doc/src/snippets/declarative/qtBinding.2.qml 0
+
+ and from:
+ \snippet doc/src/snippets/declarative/qtBinding.3.qml 0
+
+ should both be:
+ \code
+ Root text extra text
+ Modified root text extra text
+ Dynamic text extra text
+ Modified dynamic text extra text
+ \endcode
+
+ This function cannot be used in property binding declarations
+ (see the documentation on \l{qml-javascript-assignment}{binding
+ declarations and binding assignments}) except when the result is
+ stored in an array bound to a var property.
+
+ \snippet doc/src/snippets/declarative/qtBinding.4.qml 0
+
+ Note: in QtQuick 1.x, all function assignment was treated as
+ binding assignment, so the Qt.binding() function is new in
+ QtQuick 2.0.
+
+ \since QtQuick 2.0
+*/
+v8::Handle<v8::Value> binding(const v8::Arguments &args)
+{
+ QString code;
+ if (args.Length() != 1)
+ V8THROW_ERROR("binding() requires 1 argument");
+ if (!args[0]->IsFunction())
+ V8THROW_TYPE("binding(): argument (binding expression) must be a function");
+
+ v8::Handle<v8::Object> rv = args[0]->ToObject()->Clone();
+ rv->SetHiddenValue(V8ENGINE()->bindingFlagKey(), v8::Boolean::New(true));
+ return rv;
+}
+
} // namespace QQmlBuiltinFunctions
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index ddb1c64243..bbfe88a292 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -103,6 +103,7 @@ v8::Handle<v8::Value> qsTrId(const v8::Arguments &args);
v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args);
v8::Handle<v8::Value> stringArg(const v8::Arguments &args);
v8::Handle<v8::Value> locale(const v8::Arguments &args);
+v8::Handle<v8::Value> binding(const v8::Arguments &args);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 8e8223fea1..ab3283f727 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -147,6 +147,8 @@ QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership)
QV8GCCallback::registerGcPrologueCallback();
m_strongReferencer = qPersistentNew(v8::Object::New());
+ m_bindingFlagKey = qPersistentNew(v8::String::New("qml::binding"));
+
m_stringWrapper.init();
m_contextWrapper.init(this);
m_qobjectWrapper.init(this);
@@ -191,6 +193,8 @@ QV8Engine::~QV8Engine()
m_contextWrapper.destroy();
m_stringWrapper.destroy();
+ qPersistentDispose(m_bindingFlagKey);
+
m_originalGlobalObject.destroy();
if (m_ownsV8Context)
@@ -314,6 +318,7 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
if (type < QMetaType::User) {
switch (QMetaType::Type(type)) {
+ case QMetaType::UnknownType:
case QMetaType::Void:
return v8::Undefined();
case QMetaType::Bool:
@@ -598,6 +603,7 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this));
qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this));
qt->Set(v8::String::New("locale"), V8FUNCTION(locale, this));
+ qt->Set(v8::String::New("binding"), V8FUNCTION(binding, this));
if (m_engine) {
qt->Set(v8::String::New("application"), newQObject(new QQuickApplication(m_engine)));
@@ -1112,6 +1118,7 @@ v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data)
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
+ case QMetaType::UnknownType:
case QMetaType::Void:
return v8::Undefined();
case QMetaType::Bool:
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index bc57b27085..825d7a3583 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -357,6 +357,9 @@ public:
// a QVariant wrapper
inline v8::Handle<v8::Value> newQVariant(const QVariant &);
+ // Return the JS string key for the "function is a binding" flag
+ inline v8::Handle<v8::String> bindingFlagKey() const;
+
// Return the network access manager for this engine. By default this returns the network
// access manager of the QQmlEngine. It is overridden in the case of a threaded v8
// instance (like in WorkerScript).
@@ -461,6 +464,8 @@ protected:
v8::Persistent<v8::Context> m_context;
QScriptOriginalGlobalObject m_originalGlobalObject;
+ v8::Persistent<v8::String> m_bindingFlagKey;
+
QV8StringWrapper m_stringWrapper;
QV8ContextWrapper m_contextWrapper;
QV8QObjectWrapper m_qobjectWrapper;
@@ -609,6 +614,11 @@ v8::Handle<v8::Value> QV8Engine::newSequence(int sequenceType, QObject *object,
return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded);
}
+v8::Handle<v8::String> QV8Engine::bindingFlagKey() const
+{
+ return m_bindingFlagKey;
+}
+
// XXX Can this be made more optimal? It is called prior to resolving each and every
// unqualified name in QV8ContextWrapper.
bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 3faea2c97b..2350b9dc2c 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -449,7 +449,7 @@ static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
return retn;
}
- if (property.propType == QVariant::Invalid) {
+ if (property.propType == QMetaType::UnknownType) {
QMetaProperty p = object->metaObject()->property(property.coreIndex);
qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property "
"'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
@@ -519,7 +519,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
return v8::Handle<v8::Value>();
}
- if (result->isFunction()) {
+ if (result->isFunction() && !result->isVMEProperty()) {
if (result->isVMEFunction()) {
return ((QQmlVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
} else if (result->isV8Function()) {
@@ -579,23 +579,53 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
v8::Handle<v8::Value> value)
{
QQmlBinding *newBinding = 0;
-
if (value->IsFunction()) {
- QQmlContextData *context = engine->callingContext();
- v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
-
- v8::Local<v8::StackTrace> trace =
- v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
- v8::StackTrace::kScriptName));
- v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
- int lineNumber = frame->GetLineNumber();
- int columnNumber = frame->GetColumn();
- QString url = engine->toString(frame->GetScriptName());
-
- newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber);
- newBinding->setTarget(object, *property, context);
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
- QQmlBinding::RequiresThisObject);
+ if (value->ToObject()->GetHiddenValue(engine->bindingFlagKey()).IsEmpty()) {
+ if (!property->isVMEProperty()) {
+ // XXX TODO: uncomment the following lines
+ // assigning a JS function to a non-var-property is not allowed.
+ //QString error = QLatin1String("Cannot assign JavaScript function to ") +
+ // QLatin1String(QMetaType::typeName(property->propType));
+ //v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ //return;
+ // XXX TODO: remove the following transition behaviour
+ // Temporarily allow assignment of functions to non-var properties
+ // to mean binding assignment (as per old behaviour).
+ QQmlContextData *context = engine->callingContext();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+ v8::Local<v8::StackTrace> trace =
+ v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+ v8::StackTrace::kScriptName));
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+ int lineNumber = frame->GetLineNumber();
+ int columnNumber = frame->GetColumn();
+ QString url = engine->toString(frame->GetScriptName());
+
+ newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber);
+ newBinding->setTarget(object, *property, context);
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+ QQmlBinding::RequiresThisObject);
+ qWarning("WARNING: function assignment is DEPRECATED and will be removed! Wrap RHS in Qt.binding(): %s:%d", qPrintable(engine->toString(frame->GetScriptName())), frame->GetLineNumber());
+ }
+ } else {
+ // binding assignment.
+ QQmlContextData *context = engine->callingContext();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+ v8::Local<v8::StackTrace> trace =
+ v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+ v8::StackTrace::kScriptName));
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+ int lineNumber = frame->GetLineNumber();
+ int columnNumber = frame->GetColumn();
+ QString url = engine->toString(frame->GetScriptName());
+
+ newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber);
+ newBinding->setTarget(object, *property, context);
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+ QQmlBinding::RequiresThisObject);
+ }
}
QQmlAbstractBinding *oldBinding =
@@ -603,6 +633,12 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
if (oldBinding)
oldBinding->destroy();
+ if (!newBinding && property->isVMEProperty()) {
+ // allow assignment of "special" values (null, undefined, function) to var properties
+ static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(object->metaObject()))->setVMEProperty(property->coreIndex, value);
+ return;
+ }
+
#define PROPERTY_STORE(cpptype, value) \
cpptype o = value; \
int status = -1; \
@@ -649,10 +685,14 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
if (v.userType() == QVariant::Invalid) valueType = "null";
else valueType = QMetaType::typeName(v.userType());
+ const char *targetTypeName = QMetaType::typeName(property->propType);
+ if (!targetTypeName)
+ targetTypeName = "an unregistered type";
+
QString error = QLatin1String("Cannot assign ") +
QLatin1String(valueType) +
QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(property->propType));
+ QLatin1String(targetTypeName);
v8::ThrowException(v8::Exception::Error(engine->toString(error)));
}
}
@@ -1640,16 +1680,6 @@ static inline int QMetaObject_methods(const QMetaObject *metaObject)
return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
}
-static QByteArray QMetaMethod_name(const QMetaMethod &m)
-{
- QByteArray sig = m.signature();
- int paren = sig.indexOf('(');
- if (paren == -1)
- return sig;
- else
- return sig.left(paren);
-}
-
/*!
Returns the next related method, if one, or 0.
*/
@@ -1678,9 +1708,9 @@ static const QQmlPropertyData * RelatedMethod(QObject *object,
dummy.load(method);
// Look for overloaded methods
- QByteArray methodName = QMetaMethod_name(method);
+ QByteArray methodName = method.name();
for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
- if (methodName == QMetaMethod_name(mo->method(ii))) {
+ if (methodName == mo->method(ii).name()) {
dummy.setFlags(dummy.getFlags() | QQmlPropertyData::IsOverload);
dummy.overrideIndexIsProperty = 0;
dummy.overrideIndex = ii;
@@ -1794,7 +1824,7 @@ static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QQmlPropertyD
const QQmlPropertyData *candidate = &data;
while (candidate) {
error += QLatin1String("\n ") +
- QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature());
+ QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).methodSignature().constData());
candidate = RelatedMethod(object, candidate, dummy);
}
@@ -1963,7 +1993,7 @@ void *CallArgument::dataPtr()
void CallArgument::initAsType(int callType)
{
if (type != 0) { cleanup(); type = 0; }
- if (callType == 0) return;
+ if (callType == QMetaType::UnknownType) return;
if (callType == qMetaTypeId<QJSValue>()) {
qjsValuePtr = new (&allocData) QJSValue();
@@ -1989,6 +2019,9 @@ void CallArgument::initAsType(int callType)
} else if (callType == qMetaTypeId<QQmlV8Handle>()) {
type = callType;
handlePtr = new (&allocData) QQmlV8Handle;
+ } else if (callType == QMetaType::Void) {
+ type = -1;
+ qvariantPtr = new (&allocData) QVariant();
} else {
type = -1;
qvariantPtr = new (&allocData) QVariant(callType, (void *)0);
@@ -2043,6 +2076,8 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Val
} else if (callType == qMetaTypeId<QQmlV8Handle>()) {
handlePtr = new (&allocData) QQmlV8Handle(QQmlV8Handle::fromHandle(value));
type = callType;
+ } else if (callType == QMetaType::Void) {
+ *qvariantPtr = QVariant();
} else {
qvariantPtr = new (&allocData) QVariant();
type = -1;
diff --git a/src/qml/qml/v8/qv8valuetypewrapper.cpp b/src/qml/qml/v8/qv8valuetypewrapper.cpp
index 7a3c675d49..cf2c13fce9 100644
--- a/src/qml/qml/v8/qv8valuetypewrapper.cpp
+++ b/src/qml/qml/v8/qv8valuetypewrapper.cpp
@@ -324,6 +324,13 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property
QQmlBinding *newBinding = 0;
if (value->IsFunction()) {
+ if (value->ToObject()->GetHiddenValue(r->engine->bindingFlagKey()).IsEmpty()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QLatin1String("Cannot assign JavaScript function to value-type property");
+ v8::ThrowException(v8::Exception::Error(r->engine->toString(error)));
+ return value;
+ }
+
QQmlContextData *context = r->engine->callingContext();
v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);