aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2012-07-13 15:53:04 +1000
committerQt by Nokia <qt-info@nokia.com>2012-08-08 06:04:03 +0200
commit92562eacbc3c614a83a734f1108ed7df02415eae (patch)
tree05fc063849e032cb03e4f919811d8ea4da147773 /src/qml
parentb2120f68683b7948891d72fe077f44ab7e6baf18 (diff)
Allow signal parameters which are custom QML object-types
This commit allows lazy resolution of signal parameter types, which allows QML object types to be used as signal parameters. If a signal is emitted with an incorrect parameter type, it will be passed through as a null parameter. Task-number: QTBUG-14550 Change-Id: I7e899ad57452826cc405bed10c541f8d35789d04 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp9
-rw-r--r--src/qml/qml/qqmlcompiler.cpp30
-rw-r--r--src/qml/qml/qqmlscript.cpp37
-rw-r--r--src/qml/qml/qqmlscript_p.h1
4 files changed, 62 insertions, 15 deletions
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 6c4465eb96..5f5e7b09af 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -186,7 +186,7 @@ class QQmlBoundSignalParameters : public QObject
{
Q_OBJECT
public:
- QQmlBoundSignalParameters(const QMetaMethod &, QQmlAbstractBoundSignal*);
+ QQmlBoundSignalParameters(const QMetaMethod &, QQmlAbstractBoundSignal*, QQmlEngine*);
~QQmlBoundSignalParameters();
void setValues(void **);
@@ -344,7 +344,7 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
QList<QByteArray> names = QQmlPropertyCache::signalParameterNames(*s->m_scope, s->m_index);
if (!names.isEmpty()) {
QMetaMethod signal = QMetaObjectPrivate::signal(s->m_scope->metaObject(), s->m_index);
- s->m_params = new QQmlBoundSignalParameters(signal, s);
+ s->m_params = new QQmlBoundSignalParameters(signal, s, s->m_expression->engine());
}
s->setParamsValid(true);
@@ -364,7 +364,8 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
}
QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
- QQmlAbstractBoundSignal *owner)
+ QQmlAbstractBoundSignal *owner,
+ QQmlEngine *engine)
: types(0), values(0)
{
MetaObject *mo = new MetaObject(this);
@@ -389,7 +390,7 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
name = "__qt_anonymous_param_" + QByteArray::number(ii);
int t = QMetaType::type(type.constData());
- if (QQmlMetaType::isQObject(t)) {
+ if (QQmlEnginePrivate::get(engine)->isQObject(t)) {
types[ii] = QMetaType::QObjectStar;
QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
prop.setWritable(false);
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 453ee0841b..af8448001e 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -2978,9 +2978,33 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
paramTypes[0] = paramCount;
for (int i = 0; i < paramCount; ++i) {
- Q_ASSERT(s->parameterTypes.at(i) < builtinTypeCount);
- paramTypes[i + 1] = builtinTypes[s->parameterTypes.at(i)].metaType;
- names.append(s->parameterNames.at(i).toString().toUtf8());
+ if (s->parameterTypes.at(i) < builtinTypeCount) {
+ // built-in type
+ paramTypes[i + 1] = builtinTypes[s->parameterTypes.at(i)].metaType;
+ names.append(s->parameterNames.at(i).toString().toUtf8());
+ } else {
+ // lazily resolved type
+ Q_ASSERT(s->parameterTypes.at(i) == Object::DynamicProperty::Custom);
+ QQmlType *qmltype = 0;
+ QString url;
+ if (!unit->imports().resolveType(s->parameterTypeNames.at(i).toString(), &qmltype, &url, 0, 0, 0))
+ COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(s->parameterTypeNames.at(i).toString()));
+
+ if (!qmltype) {
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(QUrl(url));
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
+
+ QQmlCompiledData *data = tdata->compiledData();
+
+ paramTypes[i + 1] = data->metaTypeId;
+
+ tdata->release();
+ } else {
+ paramTypes[i + 1] = qmltype->typeId();
+ }
+ names.append(s->parameterNames.at(i).toString().toUtf8());
+ }
}
}
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index a237f9a2f8..985b6b6181 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -937,6 +937,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
if (paramLength) {
signal->parameterTypes = _parser->_pool.NewRawList<Object::DynamicProperty::Type>(paramLength);
+ signal->parameterTypeNames = _parser->_pool.NewRawList<QHashedStringRef>(paramLength);
signal->parameterNames = _parser->_pool.NewRawList<QHashedStringRef>(paramLength);
}
@@ -944,6 +945,15 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
while (p) {
const QStringRef &memberType = p->type;
+ if (memberType.isEmpty()) {
+ QQmlError error;
+ error.setDescription(QCoreApplication::translate("QQmlParser","Expected parameter type"));
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
const TypeNameToType *type = 0;
for(int typeIndex = 0; typeIndex < propTypeNameToTypesCount; ++typeIndex) {
const TypeNameToType *t = propTypeNameToTypes + typeIndex;
@@ -955,15 +965,26 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
}
if (!type) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Expected parameter type"));
- error.setLine(node->typeToken.startLine);
- error.setColumn(node->typeToken.startColumn);
- _parser->_errors << error;
- return false;
+ if (memberType.at(0).isUpper()) {
+ // Must be a QML object type.
+ // Lazily determine type during compilation.
+ signal->parameterTypes[index] = Object::DynamicProperty::Custom;
+ signal->parameterTypeNames[index] = QHashedStringRef(p->type);
+ } else {
+ QQmlError error;
+ QString errStr = QCoreApplication::translate("QQmlParser","Invalid signal parameter type: ");
+ errStr.append(memberType.toString());
+ error.setDescription(errStr);
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+ } else {
+ // the parameter is a known basic type
+ signal->parameterTypes[index] = type->type;
}
-
- 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 e08afa8ee3..60e667e4ea 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -409,6 +409,7 @@ public:
QHashedStringRef name;
QQmlPool::List<DynamicProperty::Type> parameterTypes;
+ QQmlPool::List<QHashedStringRef> parameterTypeNames;
QQmlPool::List<QHashedStringRef> parameterNames;
// Used by Object::DynamicSignalList