diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2010-02-22 11:26:08 (GMT) |
---|---|---|
committer | Roberto Raggi <roberto.raggi@nokia.com> | 2010-02-22 11:26:08 (GMT) |
commit | 97930918c8f5d20c6a27c22a1f0670ac7576c17a (patch) | |
tree | 688f93eacf376df07679f06203834e44143103fa /src/declarative/qml | |
parent | 80fc5bf17e5f049a395d6a5612843c69c5b0fde1 (diff) | |
parent | 66818ea9bc50af50bb26515cf667fe1c0c62a12d (diff) | |
download | Qt-97930918c8f5d20c6a27c22a1f0670ac7576c17a.zip Qt-97930918c8f5d20c6a27c22a1f0670ac7576c17a.tar.gz Qt-97930918c8f5d20c6a27c22a1f0670ac7576c17a.tar.bz2 |
Merge remote branch 'origin/master' into qtruntime
Conflicts:
src/declarative/qml/qml.pri
src/declarative/qml/qmlengine.cpp
src/declarative/util/qmlview.h
Diffstat (limited to 'src/declarative/qml')
32 files changed, 731 insertions, 747 deletions
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h index e5e7c59..7972305 100644 --- a/src/declarative/qml/qml.h +++ b/src/declarative/qml/qml.h @@ -59,12 +59,10 @@ QT_MODULE(Declarative) #define QML_DECLARE_TYPE(TYPE) \ Q_DECLARE_METATYPE(TYPE *) \ - Q_DECLARE_METATYPE(QList<TYPE *> *) \ - Q_DECLARE_METATYPE(QmlList<TYPE *> *) + Q_DECLARE_METATYPE(QmlListProperty<TYPE>) #define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \ - Q_DECLARE_METATYPE(QList<TYPE *> *) \ - Q_DECLARE_METATYPE(QmlList<TYPE *> *) + Q_DECLARE_METATYPE(QmlListProperty<TYPE>) #define QML_DECLARE_INTERFACE(INTERFACE) \ QML_DECLARE_TYPE(INTERFACE) diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 6c74863..daee431 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -53,7 +53,8 @@ SOURCES += \ $$PWD/qmlimageprovider.cpp \ $$PWD/qmlnetworkaccessmanagerfactory.cpp \ $$PWD/qmldirparser.cpp \ - $$PWD/qmlextensionplugin.cpp + $$PWD/qmlextensionplugin.cpp \ + $$PWD/qmllist.cpp HEADERS += \ $$PWD/qmlparser_p.h \ @@ -94,6 +95,7 @@ HEADERS += \ $$PWD/qmlcompositetypedata_p.h \ $$PWD/qmlcompositetypemanager_p.h \ $$PWD/qmllist.h \ + $$PWD/qmllist_p.h \ $$PWD/qmldeclarativedata_p.h \ $$PWD/qmlerror.h \ $$PWD/qmlscriptparser_p.h \ diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 0dbe63b..feadd0f 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -54,8 +54,6 @@ #include <QVariant> #include <QtCore/qdebug.h> -Q_DECLARE_METATYPE(QList<QObject *>); - QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 2b1081e..bbae201 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1495,8 +1495,7 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt)); - } else if (QmlEnginePrivate::get(engine)->isQmlList(prop->type) || - QmlMetaType::isList(prop->type)) { + } else if (QmlEnginePrivate::get(engine)->isList(prop->type)) { COMPILE_CHECK(buildListProperty(prop, obj, ctxt)); @@ -1552,8 +1551,7 @@ QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, void QmlCompiler::genValueProperty(QmlParser::Property *prop, QmlParser::Object *obj) { - if (QmlEnginePrivate::get(engine)->isQmlList(prop->type) || - QmlMetaType::isList(prop->type)) { + if (QmlEnginePrivate::get(engine)->isList(prop->type)) { genListProperty(prop, obj); } else { genPropertyAssignment(prop, obj); @@ -1563,22 +1561,10 @@ void QmlCompiler::genValueProperty(QmlParser::Property *prop, void QmlCompiler::genListProperty(QmlParser::Property *prop, QmlParser::Object *obj) { - QmlInstruction::Type fetchType; - QmlInstruction::Type storeType; - int listType; - - if (QmlEnginePrivate::get(engine)->isQmlList(prop->type)) { - fetchType = QmlInstruction::FetchQmlList; - storeType = QmlInstruction::StoreObjectQmlList; - listType = QmlEnginePrivate::get(engine)->qmlListType(prop->type); - } else { - fetchType = QmlInstruction::FetchQList; - storeType = QmlInstruction::StoreObjectQList; - listType = QmlMetaType::listType(prop->type); - } + int listType = QmlEnginePrivate::get(engine)->listType(prop->type); QmlInstruction fetch; - fetch.type = fetchType; + fetch.type = QmlInstruction::FetchQList; fetch.line = prop->location.start.line; fetch.fetchQmlList.property = prop->index; bool listTypeIsInterface = QmlMetaType::isInterface(listType); @@ -1598,7 +1584,7 @@ void QmlCompiler::genListProperty(QmlParser::Property *prop, output->bytecode << assign; } else { QmlInstruction store; - store.type = storeType; + store.type = QmlInstruction::StoreObjectQList; store.line = prop->location.start.line; output->bytecode << store; } @@ -1895,67 +1881,40 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &ctxt) { - Q_ASSERT(QmlMetaType::isList(prop->type) || - QmlEnginePrivate::get(engine)->isQmlList(prop->type)); + Q_ASSERT(QmlEnginePrivate::get(engine)->isList(prop->type)); int t = prop->type; obj->addValueProperty(prop); - if (QmlEnginePrivate::get(engine)->isQmlList(t)) { - int listType = QmlEnginePrivate::get(engine)->qmlListType(t); - bool listTypeIsInterface = QmlMetaType::isInterface(listType); - - for (int ii = 0; ii < prop->values.count(); ++ii) { - Value *v = prop->values.at(ii); - if (v->object) { - v->type = Value::CreatedObject; - COMPILE_CHECK(buildObject(v->object, ctxt)); - - // We check object coercian here. We check interface assignment - // at runtime. - if (!listTypeIsInterface) { - if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign object to list")); - } - } + int listType = QmlEnginePrivate::get(engine)->listType(t); + bool listTypeIsInterface = QmlMetaType::isInterface(listType); - } else { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign primitives to lists")); - } - } + bool assignedBinding = false; + for (int ii = 0; ii < prop->values.count(); ++ii) { + Value *v = prop->values.at(ii); + if (v->object) { + v->type = Value::CreatedObject; + COMPILE_CHECK(buildObject(v->object, ctxt)); - } else { - int listType = QmlMetaType::listType(t); - bool listTypeIsInterface = QmlMetaType::isInterface(listType); - - bool assignedBinding = false; - for (int ii = 0; ii < prop->values.count(); ++ii) { - Value *v = prop->values.at(ii); - if (v->object) { - v->type = Value::CreatedObject; - COMPILE_CHECK(buildObject(v->object, ctxt)); - - // We check object coercian here. We check interface assignment - // at runtime. - if (!listTypeIsInterface) { - if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign object to list")); - } + // We check object coercian here. We check interface assignment + // at runtime. + if (!listTypeIsInterface) { + if (!canCoerce(listType, v->object)) { + COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign object to list")); } + } - } else if (v->value.isScript()) { - if (assignedBinding) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Can only assign one binding to lists")); + } else if (v->value.isScript()) { + if (assignedBinding) + COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Can only assign one binding to lists")); - assignedBinding = true; - COMPILE_CHECK(buildBinding(v, prop, ctxt)); - v->type = Value::PropertyBinding; - } else { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign primitives to lists")); - } + assignedBinding = true; + COMPILE_CHECK(buildBinding(v, prop, ctxt)); + v->type = Value::PropertyBinding; + } else { + COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Cannot assign primitives to lists")); } - } return true; @@ -2335,10 +2294,10 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) propertyType = QMetaType::QObjectStar; } else { readonly = true; - type = "QmlList<"; + type = "QmlListProperty<"; type.append(customTypeName); - type.append("*>*"); - propertyType = qMetaTypeId<QmlList<QObject*>* >(); + type.append(">"); + propertyType = qMetaTypeId<QmlListProperty<QObject> >(); } } break; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 303af42..56038cf 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -544,5 +544,30 @@ QUrl QmlContext::baseUrl() const return QUrl(); } +int QmlContextPrivate::context_count(QmlListProperty<QObject> *prop) +{ + QmlContext *context = static_cast<QmlContext*>(prop->object); + QmlContextPrivate *d = QmlContextPrivate::get(context); + int contextProperty = (int)(intptr_t)prop->data; + + if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) { + return 0; + } else { + return ((const QList<QObject> *)d->propertyValues.at(contextProperty).constData())->count(); + } +} + +QObject *QmlContextPrivate::context_at(QmlListProperty<QObject> *prop, int index) +{ + QmlContext *context = static_cast<QmlContext*>(prop->object); + QmlContextPrivate *d = QmlContextPrivate::get(context); + int contextProperty = (int)(intptr_t)prop->data; + + if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) { + return 0; + } else { + return ((const QList<QObject*> *)d->propertyValues.at(contextProperty).constData())->at(index); + } +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index 21b1a1e..e96ed84 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -45,6 +45,7 @@ #include <QtCore/qurl.h> #include <QtCore/qobject.h> #include <QtScript/qscriptvalue.h> +#include <QtCore/qmetatype.h> QT_BEGIN_HEADER @@ -97,9 +98,10 @@ private: QmlContext(QmlContext *parent, QObject *objParent, bool); QmlContext(QmlEngine *, bool); }; - QT_END_NAMESPACE +Q_DECLARE_METATYPE(QList<QObject*>); + QT_END_HEADER #endif // QMLCONTEXT_H diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index bd4f5d5..965eeed 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -152,6 +152,9 @@ public: // Only used for debugging QList<QPointer<QObject> > instances; + + static int context_count(QmlListProperty<QObject> *); + static QObject *context_at(QmlListProperty<QObject> *, int); }; QmlContextPrivate::IdNotifier::IdNotifier() diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index be3bbc3..4c71903 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -44,6 +44,7 @@ #include "qmlengine_p.h" #include "qmlcontext_p.h" #include "qmltypenamescriptclass_p.h" +#include "qmllistscriptclass_p.h" #include "qmlguard_p.h" QT_BEGIN_NAMESPACE @@ -227,8 +228,12 @@ QmlContextScriptClass::property(Object *object, const Identifier &name) if (lastPropertyIndex < cp->idValueCount) { rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data()); } else { - QVariant value = cp->propertyValues.at(lastPropertyIndex); - rv = ep->scriptValueFromVariant(value); + const QVariant &value = cp->propertyValues.at(lastPropertyIndex); + if (value.userType() == qMetaTypeId<QList<QObject*> >()) { + rv = ep->listClass->newList(QmlListProperty<QObject>(bindContext, (void*)lastPropertyIndex, 0, QmlContextPrivate::context_count, QmlContextPrivate::context_at), qMetaTypeId<QmlListProperty<QObject> >()); + } else { + rv = ep->scriptValueFromVariant(value); + } } ep->capturedProperties << diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index 01061ee..c75a299 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -1346,7 +1346,6 @@ QmlDomValue::Type QmlDomValue::type() const { if (d->property) if (QmlMetaType::isList(d->property->type) || - QmlMetaType::isQmlList(d->property->type) || (d->property && d->property->values.count() > 1)) return List; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 1f5caa5..ce2a693 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -68,6 +68,8 @@ #include "qmlimageprovider.h" #include "qmldirparser_p.h" #include "qmlextensioninterface.h" +#include "qmllist_p.h" + #include <qfxperf_p_p.h> #include <QtCore/qmetaobject.h> @@ -109,7 +111,6 @@ #endif Q_DECLARE_METATYPE(QmlMetaProperty) -Q_DECLARE_METATYPE(QList<QObject *>); QT_BEGIN_NAMESPACE @@ -1172,6 +1173,15 @@ QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) QScriptValue QmlEnginePrivate::scriptValueFromVariant(const QVariant &val) { + if (val.userType() == qMetaTypeId<QmlListReference>()) { + QmlListReferencePrivate *p = QmlListReferencePrivate::get((QmlListReference*)val.constData()); + if (p->object) { + return listClass->newList(p->property, p->propertyType); + } else { + return scriptEngine.nullValue(); + } + } + bool objOk; QObject *obj = QmlMetaType::toQObject(val, &objOk); if (objOk) { @@ -1673,7 +1683,7 @@ void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data) QByteArray name = data->root->className(); QByteArray ptr = name + '*'; - QByteArray lst = "QmlList<" + ptr + ">*"; + QByteArray lst = "QmlListProperty<" + name + ">"; int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor, voidptr_constructor); @@ -1685,9 +1695,18 @@ void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data) data->addref(); } -bool QmlEnginePrivate::isQmlList(int t) const +bool QmlEnginePrivate::isList(int t) const { - return m_qmlLists.contains(t) || QmlMetaType::isQmlList(t); + return m_qmlLists.contains(t) || QmlMetaType::isList(t); +} + +int QmlEnginePrivate::listType(int t) const +{ + QHash<int, int>::ConstIterator iter = m_qmlLists.find(t); + if (iter != m_qmlLists.end()) + return *iter; + else + return QmlMetaType::listType(t); } bool QmlEnginePrivate::isQObject(int t) @@ -1706,21 +1725,12 @@ QObject *QmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const } } -int QmlEnginePrivate::qmlListType(int t) const -{ - QHash<int, int>::ConstIterator iter = m_qmlLists.find(t); - if (iter != m_qmlLists.end()) - return *iter; - else - return QmlMetaType::qmlListType(t); -} - QmlMetaType::TypeCategory QmlEnginePrivate::typeCategory(int t) const { if (m_compositeTypes.contains(t)) return QmlMetaType::Object; else if (m_qmlLists.contains(t)) - return QmlMetaType::QmlList; + return QmlMetaType::List; else return QmlMetaType::typeCategory(t); } diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 7ec6dd6..3fe7991 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -274,11 +274,12 @@ public: void registerCompositeType(QmlCompiledData *); - bool isQmlList(int) const; + bool isQObject(int); QObject *toQObject(const QVariant &, bool *ok = 0) const; - int qmlListType(int) const; QmlMetaType::TypeCategory typeCategory(int) const; + bool isList(int) const; + int listType(int) const; const QMetaObject *rawMetaObjectForType(int) const; const QMetaObject *metaObjectForType(int) const; QHash<int, int> m_qmlLists; @@ -322,7 +323,6 @@ public: QmlContext *getContext(QScriptContext *); }; - QT_END_NAMESPACE #endif // QMLENGINE_P_H diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index d3caa95..654157c 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -119,8 +119,7 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) rv.type = QmlObjectProperty::Basic; } else if (QmlMetaType::isQObject(prop.userType())) { rv.type = QmlObjectProperty::Object; - } else if (QmlMetaType::isList(prop.userType()) || - QmlMetaType::isQmlList(prop.userType())) { + } else if (QmlMetaType::isList(prop.userType())) { rv.type = QmlObjectProperty::List; } @@ -133,14 +132,15 @@ QVariant QmlEngineDebugServer::valueContents(const QVariant &value) const if (QVariant::Type(userType) < QVariant::UserType) return value; - - if (QmlMetaType::isList(userType) || QmlMetaType::isQmlList(userType)) { + /* + if (QmlMetaType::isList(userType)) { int count = QmlMetaType::listCount(value); QVariantList contents; for (int i=0; i<count; i++) contents << valueContents(QmlMetaType::listAt(value, i)); return contents; - } else if (QmlMetaType::isQObject(userType)) { + } else */ + if (QmlMetaType::isQObject(userType)) { QObject *o = QmlMetaType::toQObject(value); if (o) { QString name = o->objectName(); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index d428377..8f0c945 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -52,8 +52,6 @@ #include <private/qscriptdeclarativeclass_p.h> -Q_DECLARE_METATYPE(QList<QObject *>); - QT_BEGIN_NAMESPACE bool QmlDelayedError::addError(QmlEnginePrivate *e) diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index de01bfe..e37ade7 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -171,9 +171,6 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::BeginObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue; break; - case QmlInstruction::StoreObjectQmlList: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT_QMLLIST"; - break; case QmlInstruction::StoreObjectQList: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT_QLIST"; break; @@ -183,9 +180,6 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::FetchAttached: qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id; break; - case QmlInstruction::FetchQmlList: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type; - break; case QmlInstruction::FetchQList: qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property; break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 5613888..ea785b6 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -134,12 +134,10 @@ public: BeginObject, /* begin */ - StoreObjectQmlList, /* NA */ StoreObjectQList, /* NA */ AssignObjectList, /* NA */ FetchAttached, /* fetchAttached */ - FetchQmlList, /* fetchQmlList */ FetchQList, /* fetch */ FetchObject, /* fetch */ FetchValueType, /* fetchValue */ diff --git a/src/declarative/qml/qmllist.cpp b/src/declarative/qml/qmllist.cpp new file mode 100644 index 0000000..4cd2120 --- /dev/null +++ b/src/declarative/qml/qmllist.cpp @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmllist.h" +#include "qmllist_p.h" +#include "qmlengine_p.h" +#include "qmlmetaproperty_p.h" + +QT_BEGIN_NAMESPACE + +QmlListReferencePrivate::QmlListReferencePrivate() +: propertyType(-1), refCount(1) +{ +} + +QmlListReference QmlListReferencePrivate::init(const QmlListProperty<QObject> &prop, int propType, QmlEngine *engine) +{ + QmlListReference rv; + + if (!prop.object) return rv; + + QmlEnginePrivate *p = engine?QmlEnginePrivate::get(engine):0; + + int listType = p?p->listType(propType):QmlMetaType::listType(propType); + if (listType == -1) return rv; + + rv.d = new QmlListReferencePrivate; + rv.d->object = prop.object; + rv.d->elementType = p?p->rawMetaObjectForType(listType):QmlMetaType::qmlType(listType)->baseMetaObject(); + rv.d->property = prop; + rv.d->propertyType = propType; + + return rv; +} + +void QmlListReferencePrivate::addref() +{ + Q_ASSERT(refCount > 0); + ++refCount; +} + +void QmlListReferencePrivate::release() +{ + Q_ASSERT(refCount > 0); + --refCount; + if (!refCount) + delete this; +} + +QmlListReference::QmlListReference() +: d(0) +{ +} + +QmlListReference::QmlListReference(QObject *o, const char *property, QmlEngine *engine) +: d(0) +{ + if (!o || !property) return; + + QmlPropertyCache::Data local; + QmlPropertyCache::Data *data = QmlPropertyCache::property(engine, o, QLatin1String(property), local); + + if (!data || !(data->flags & QmlPropertyCache::Data::IsQList)) return; + + QmlEnginePrivate *p = engine?QmlEnginePrivate::get(engine):0; + + int listType = p?p->listType(data->propType):QmlMetaType::listType(data->propType); + if (listType == -1) return; + + d = new QmlListReferencePrivate; + d->object = o; + d->elementType = p?p->rawMetaObjectForType(listType):QmlMetaType::qmlType(listType)->baseMetaObject(); + d->propertyType = data->propType; + + void *args[] = { &d->property, 0 }; + QMetaObject::metacall(o, QMetaObject::ReadProperty, data->coreIndex, args); +} + +QmlListReference::QmlListReference(const QmlListReference &o) +: d(o.d) +{ + if (d) d->addref(); +} + +QmlListReference &QmlListReference::operator=(const QmlListReference &o) +{ + if (o.d) o.d->addref(); + if (d) d->release(); + d = o.d; + return *this; +} + +QmlListReference::~QmlListReference() +{ + if (d) d->release(); +} + +bool QmlListReference::isValid() const +{ + return d && d->object; +} + +QObject *QmlListReference::object() const +{ + if (isValid()) return d->object; + else return 0; +} + +const QMetaObject *QmlListReference::listElementType() const +{ + if (isValid()) return d->elementType; + else return 0; +} + +bool QmlListReference::canAppend() const +{ + return (isValid() && d->property.append); +} + +bool QmlListReference::canAt() const +{ + return (isValid() && d->property.at); +} + +bool QmlListReference::canClear() const +{ + return (isValid() && d->property.clear); +} + +bool QmlListReference::canCount() const +{ + return (isValid() && d->property.count); +} + +bool QmlListReference::append(QObject *o) const +{ + if (!canAppend()) return false; + + if (o && !QmlMetaPropertyPrivate::canConvert(o->metaObject(), d->elementType)) + return false; + + d->property.append(&d->property, o); + + return true; +} + +QObject *QmlListReference::at(int index) const +{ + if (!canAt()) return 0; + + return d->property.at(&d->property, index); +} + +bool QmlListReference::clear() const +{ + if (!canClear()) return false; + + d->property.clear(&d->property); + + return true; +} + +int QmlListReference::count() const +{ + if (!canCount()) return 0; + + return d->property.count(&d->property); +} + +/*! +\class QmlListProperty +\brief The QmlListProperty class allows applications to explose list-like +properties to QML. + +QML has many list properties, where more than one object value can be assigned. +The use of a list property from QML looks like this: + +\code +FruitBasket { + fruit: [ + Apple {}, + Orange{}, + Banana {} + ] +} +\endcode + +The QmlListProperty encapsulates a group of function pointers that represet the +set of actions QML can perform on the list - adding items, retrieving items and +clearing the list. In the future, additional operations may be supported. All +list properties must implement the append operation, but the rest are optional. + +To provide a list property, a C++ class must implement the operation callbacks, +and then return an appropriate QmlListProperty value from the property getter. +List properties should have no setter. In the example above, the Q_PROPERTY() +declarative will look like this: + +\code +Q_PROPERTY(QmlListProperty<Fruit> fruit READ fruit); +\endcode + +QML list properties are typesafe - in this case \c {Fruit} is a QObject type that +\c {Apple}, \c {Orange} and \c {Banana} all derive from. +*/ + +/*! +\fn QmlListProperty::QmlListProperty() +\internal +*/ + +/*! +\fn QmlListProperty::QmlListProperty(QObject *object, QList<T *> &list) + +Convenience constructor for making a QmlListProperty value from an existing +QList \a list. The \a list reference must remain valid for as long as \a object +exists. \a object must be provided. + +Generally this constructor should not be used in production code, as a +writable QList violates QML's memory management rules. However, this constructor +can very useful while prototyping. +*/ + +/*! +\fn QmlListProperty::QmlListProperty(QObject *object, void *data, AppendFunction append, + CountFunction count = 0, AtFunction at = 0, + ClearFunction clear = 0) + +Construct a QmlListProperty from a set of operation functions. An opaque \a data handle +may be passed which can be accessed from within the operation functions. The list property +remains valid while \a object exists. + +The \a append operation is compulsory and must be provided, while the \a count, \a at and +\a clear methods are optional. +*/ + +/*! +\typedef QmlListProperty::AppendFunction + +Synonym for \c {void (*)(QmlListProperty<T> *property, T *value)}. + +Append the \a value to the list \a property. +*/ + +/*! +\typedef QmlListProperty::CountFunction + +Synonym for \c {int (*)(QmlListProperty<T> *property)}. + +Return the number of elements in the list \a property. +*/ + +/*! +\fn bool QmlListProperty::operator==(const QmlListProperty &other) const + +Returns true if this QmlListProperty is equal to \a other, otherwise false. +*/ + +/*! +\typedef QmlListProperty::AtFunction + +Synonym for \c {T *(*)(QmlListProperty<T> *property, int index)}. + +Return the element at position \a index in the list \a property. +*/ + +/*! +\typedef QmlListProperty::ClearFunction + +Synonym for \c {void (*)(QmlListProperty<T> *property)}. + +Clear the list \a property. +*/ + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmllist.h b/src/declarative/qml/qmllist.h index 261145d..cedc35b 100644 --- a/src/declarative/qml/qmllist.h +++ b/src/declarative/qml/qmllist.h @@ -51,73 +51,89 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) template<typename T> -class QmlList : private QmlPrivate::ListInterface -{ -public: - virtual void append(T) = 0; - virtual void insert(int, T) = 0; - virtual void removeAt(int) = 0; - virtual T at(int) const = 0; - virtual int count() const = 0; - virtual void clear() = 0; - QmlList<T> &operator<<(T t) { append(t); return *this; } - -protected: - virtual int type() const { return qMetaTypeId<T>(); } - virtual void append(void *d) { const T &v = *(T *)d; append(v); } - virtual void insert(int i, void *d) { const T &v = *(T *)d; insert(i, v); } - virtual void at(int i, void *p) const { const T &v = at(i); *((T*)p) = v; } +struct QmlListProperty { + typedef void (*AppendFunction)(QmlListProperty<T> *, T*); + typedef int (*CountFunction)(QmlListProperty<T> *); + typedef T *(*AtFunction)(QmlListProperty<T> *, int); + typedef void (*ClearFunction)(QmlListProperty<T> *); + + QmlListProperty() + : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {} + QmlListProperty(QObject *o, QList<T *> &list) + : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), + clear(qlist_clear), dummy1(0), dummy2(0) {} + QmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0, + ClearFunction r = 0) + : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {} + + bool operator==(const QmlListProperty &o) const { + return object == o.object && + data == o.data && + append == o.append && + count == o.count && + at == o.at && + clear == o.clear; + } + + QObject *object; + void *data; + + AppendFunction append; + + CountFunction count; + AtFunction at; + + ClearFunction clear; + + void *dummy1; + void *dummy2; + +private: + static void qlist_append(QmlListProperty *p, T *v) { + ((QList<T *> *)p->data)->append(v); + } + static int qlist_count(QmlListProperty *p) { + return ((QList<T *> *)p->data)->count(); + } + static T *qlist_at(QmlListProperty *p, int idx) { + return ((QList<T *> *)p->data)->at(idx); + } + static void qlist_clear(QmlListProperty *p) { + return ((QList<T *> *)p->data)->clear(); + } }; -template<typename T> -class QmlConcreteList : public QList<T>, public QmlList<T> +class QmlEngine; +class QmlListReferencePrivate; +class Q_DECLARATIVE_EXPORT QmlListReference { public: - virtual void append(T v) { QList<T>::append(v); } - virtual void insert(int i, T v) { QList<T>::insert(i, v); } - virtual void clear() { QList<T>::clear(); } - virtual T at(int i) const { return QList<T>::at(i); } - virtual void removeAt(int i) { QList<T>::removeAt(i); } - virtual int count() const { return QList<T>::count(); } -}; + QmlListReference(); + QmlListReference(QObject *, const char *property, QmlEngine * = 0); + QmlListReference(const QmlListReference &); + QmlListReference &operator=(const QmlListReference &); + ~QmlListReference(); + + bool isValid() const; -#define QML_DECLARE_LIST_PROXY(ClassName, ListType, ListName) \ -class Qml_ProxyList_ ##ListName : public QmlList<ListType> \ -{ \ - public: \ - virtual void removeAt(int idx) \ - { \ - ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \ - p->ListName ## _removeAt(idx); \ - } \ - virtual int count() const \ - { \ - ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \ - return p->ListName ## _count(); \ - } \ - virtual void append(ListType v) \ - { \ - ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \ - p->ListName ## _append(v); \ - } \ - virtual void insert(int idx, ListType v) \ - { \ - ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \ - p->ListName ## _insert(idx, v); \ - } \ - virtual ListType at(int idx) const \ - { \ - ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \ - return p->ListName ## _at(idx); \ - } \ - virtual void clear() \ - { \ - ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \ - p->ListName ## _clear(); \ - } \ -}; \ -friend class Qml_ProxyList_ ##ListName ; \ -Qml_ProxyList_##ListName ListName; + QObject *object() const; + const QMetaObject *listElementType() const; + + bool canAppend() const; + bool canAt() const; + bool canClear() const; + bool canCount() const; + + bool append(QObject *) const; + QObject *at(int) const; + bool clear() const; + int count() const; + +private: + friend class QmlListReferencePrivate; + QmlListReferencePrivate* d; +}; +Q_DECLARE_METATYPE(QmlListReference); QT_END_NAMESPACE diff --git a/src/declarative/qml/qmllist_p.h b/src/declarative/qml/qmllist_p.h new file mode 100644 index 0000000..4660e47 --- /dev/null +++ b/src/declarative/qml/qmllist_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLLIST_P_H +#define QMLLIST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qmllist.h" +#include "qmlguard_p.h" + +QT_BEGIN_NAMESPACE + +class QmlListReferencePrivate +{ +public: + QmlListReferencePrivate(); + + static QmlListReference init(const QmlListProperty<QObject> &, int, QmlEngine *); + + QmlGuard<QObject> object; + const QMetaObject *elementType; + QmlListProperty<QObject> property; + int propertyType; + + void addref(); + void release(); + int refCount; + + static inline QmlListReferencePrivate *get(QmlListReference *ref) { + return ref->d; + } +}; + + +QT_END_NAMESPACE + +#endif // QMLLIST_P_H diff --git a/src/declarative/qml/qmllistscriptclass.cpp b/src/declarative/qml/qmllistscriptclass.cpp index d74a9b0..bb29763 100644 --- a/src/declarative/qml/qmllistscriptclass.cpp +++ b/src/declarative/qml/qmllistscriptclass.cpp @@ -43,13 +43,13 @@ #include "qmlengine_p.h" #include "qmlguard_p.h" +#include "qmllist_p.h" QT_BEGIN_NAMESPACE struct ListData : public QScriptDeclarativeClass::Object { QmlGuard<QObject> object; - int propertyIdx; - QmlListScriptClass::ListCategory type; + QmlListProperty<QObject> property; int propertyType; }; @@ -66,7 +66,7 @@ QmlListScriptClass::~QmlListScriptClass() { } -QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListCategory type, int propType) +QScriptValue QmlListScriptClass::newList(QObject *object, int propId, int propType) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); @@ -75,8 +75,20 @@ QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListCatego ListData *data = new ListData; data->object = object; - data->propertyIdx = propId; - data->type = type; + data->propertyType = propType; + void *args[] = { &data->property, 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args); + + return newObject(scriptEngine, this, data); +} + +QScriptValue QmlListScriptClass::newList(const QmlListProperty<QObject> &prop, int propType) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + ListData *data = new ListData; + data->object = prop.object; + data->property = prop; data->propertyType = propType; return newObject(scriptEngine, this, data); @@ -111,39 +123,14 @@ QmlListScriptClass::ScriptValue QmlListScriptClass::property(Object *obj, const if (!data->object) return Value(); - void *list = 0; - void *args[] = { &list, 0 }; - QMetaObject::metacall(data->object, QMetaObject::ReadProperty, - data->propertyIdx, args); + quint32 count = data->property.count?data->property.count(&data->property):0; - if (!list) + if (name == m_lengthId.identifier) + return Value(scriptEngine, count); + else if (lastIndex < count && data->property.at) + return Value(scriptEngine, enginePriv->objectClass->newQObject(data->property.at(&data->property, lastIndex))); + else return Value(); - - if (data->type == QListPtr) { - const QList<QObject *> &qlist = *((QList<QObject *>*)list); - - quint32 count = qlist.count(); - - if (name == m_lengthId.identifier) - return Value(scriptEngine, count); - else if (lastIndex < count) - return Value(scriptEngine, enginePriv->objectClass->newQObject(qlist.at(lastIndex))); - else - return Value(); - - } else { - Q_ASSERT(data->type == QmlListPtr); - const QmlList<QObject *> &qmllist = *((QmlList<QObject *>*)list); - - quint32 count = qmllist.count(); - - if (name == m_lengthId.identifier) - return Value(scriptEngine, count); - else if (lastIndex < count) - return Value(scriptEngine, enginePriv->objectClass->newQObject(qmllist.at(lastIndex))); - else - return Value(); - } } QVariant QmlListScriptClass::toVariant(Object *obj, bool *ok) @@ -155,18 +142,7 @@ QVariant QmlListScriptClass::toVariant(Object *obj, bool *ok) return QVariant(); } - void *list = 0; - void *args[] = { &list, 0 }; - QMetaObject::metacall(data->object, QMetaObject::ReadProperty, - data->propertyIdx, args); - - if (!list) { - if (ok) *ok = false; - return QVariant(); - } - - if (ok) *ok = true; - return QVariant(data->propertyType, &list); + return QVariant::fromValue(QmlListReferencePrivate::init(data->property, data->propertyType, engine)); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmllistscriptclass_p.h b/src/declarative/qml/qmllistscriptclass_p.h index 92cf17f..07b09c3 100644 --- a/src/declarative/qml/qmllistscriptclass_p.h +++ b/src/declarative/qml/qmllistscriptclass_p.h @@ -54,6 +54,7 @@ // #include <private/qmlscriptclass_p.h> +#include "qmllist.h" QT_BEGIN_NAMESPACE @@ -64,8 +65,8 @@ public: QmlListScriptClass(QmlEngine *); ~QmlListScriptClass(); - enum ListCategory { QListPtr, QmlListPtr }; - QScriptValue newList(QObject *, int, ListCategory, int); + QScriptValue newList(QObject *, int, int); + QScriptValue newList(const QmlListProperty<QObject> &, int); protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index d7d4a07..7c273dc 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -52,16 +52,13 @@ #include "qmlengine_p.h" #include "qmldeclarativedata_p.h" #include "qmlstringconverters_p.h" - -#include <qfxperf_p_p.h> +#include "qmllist_p.h" #include <QStringList> #include <QtCore/qdebug.h> #include <math.h> -Q_DECLARE_METATYPE(QList<QObject *>); - QT_BEGIN_NAMESPACE /*! @@ -213,7 +210,6 @@ QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other) \value InvalidProperty The property is invalid. \value Bindable The property is a QmlBinding. \value List The property is a QList pointer - \value QmlList The property is a QmlList pointer \value Object The property is a QObject derived type pointer \value Normal The property is none of the above. */ @@ -257,8 +253,6 @@ QmlMetaPropertyPrivate::propertyCategory() const return QmlMetaProperty::Bindable; else if (core.flags & QmlPropertyCache::Data::IsQObjectDerived) return QmlMetaProperty::Object; - else if (core.flags & QmlPropertyCache::Data::IsQmlList) - return QmlMetaProperty::QmlList; else if (core.flags & QmlPropertyCache::Data::IsQList) return QmlMetaProperty::List; else @@ -401,7 +395,7 @@ bool QmlMetaProperty::isWritable() const if (!d->object) return false; - if (category == List || category == QmlList) + if (category == List) return true; else if (type() & SignalProperty) return false; @@ -703,6 +697,13 @@ QVariant QmlMetaPropertyPrivate::readValueProperty() if (!ep) delete valueType; return rv; + } else if(core.flags & QmlPropertyCache::Data::IsQList) { + + QmlListProperty<QObject> prop; + void *args[] = { &prop, 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args); + return QVariant::fromValue(QmlListReferencePrivate::init(prop, core.propType, context?context->engine():0)); + } else { return object->metaObject()->property(core.coreIndex).read(object.data()); @@ -813,9 +814,7 @@ bool QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data int t = property.propType; int vt = value.userType(); - QmlEnginePrivate *enginePriv = 0; - if (context && context->engine()) - enginePriv = QmlEnginePrivate::get(context->engine()); + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(context); if (t == QVariant::Url) { @@ -880,55 +879,40 @@ bool QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data } else if (property.flags & QmlPropertyCache::Data::IsQList) { - int listType = QmlMetaType::listType(t); - QMetaProperty prop = object->metaObject()->property(property.coreIndex); - - if (value.userType() == qMetaTypeId<QList<QObject *> >()) { - const QList<QObject *> &list = - qvariant_cast<QList<QObject *> >(value); - QVariant listVar = prop.read(object); - QmlMetaType::clear(listVar); - for (int ii = 0; ii < list.count(); ++ii) { - QVariant v = QmlMetaType::qmlType(listType)->fromObject(list.at(ii)); - QmlMetaType::append(listVar, v); - } - - } else if (vt == listType || - value.userType() == listType) { - QVariant listVar = prop.read(object); - QmlMetaType::append(listVar, value); + const QMetaObject *listType = 0; + if (enginePriv) { + listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType)); + } else { + QmlType *type = QmlMetaType::qmlType(QmlMetaType::listType(property.propType)); + if (!type) return false; + listType = type->baseMetaObject(); } + if (!listType) return false; - } else if (property.flags & QmlPropertyCache::Data::IsQmlList) { + QmlListProperty<void> prop; + void *args[] = { &prop, 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, coreIdx, args); - // XXX - optimize! - QMetaProperty prop = object->metaObject()->property(property.coreIndex); - QVariant list = prop.read(object); - QmlPrivate::ListInterface *li = - *(QmlPrivate::ListInterface **)list.constData(); - - int type = li->type(); - - if (QObject *obj = QmlMetaType::toQObject(value)) { - const QMetaObject *mo = rawMetaObjectForType(enginePriv, type); - - const QMetaObject *objMo = obj->metaObject(); - bool found = false; - while(!found && objMo) { - if (equal(objMo, mo)) - found = true; - else - objMo = objMo->superClass(); - } + if (!prop.clear) return false; - if (!found) - return false; + prop.clear(&prop); + + if (value.userType() == qMetaTypeId<QList<QObject *> >()) { + const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value); - // NOTE: This assumes a cast to QObject does not alter - // the object pointer - void *d = (void *)&obj; - li->append(d); + for (int ii = 0; ii < list.count(); ++ii) { + QObject *o = list.at(ii); + if (!canConvert(o->metaObject(), listType)) + o = 0; + prop.append(&prop, (void *)o); + } + } else { + QObject *o = enginePriv?enginePriv->toQObject(value):QmlMetaType::toQObject(value); + if (!canConvert(o->metaObject(), listType)) + o = 0; + prop.append(&prop, (void *)o); } + } else { Q_ASSERT(vt != t); diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 723fc50..82266c8 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -68,7 +68,6 @@ public: InvalidProperty, Bindable, List, - QmlList, //XXX Object, Normal }; diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index b94a815..6db70d4 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -100,7 +100,6 @@ struct QmlMetaTypeData QBitArray objects; QBitArray interfaces; - QBitArray qmllists; QBitArray lists; }; Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData) @@ -124,8 +123,8 @@ public: QByteArray m_name; int m_version_maj; int m_version_min; - int m_typeId; int m_listId; int m_qmlListId; - QmlPrivate::Func m_opFunc; + int m_typeId; int m_listId; + QObject *(*m_newFunc)(); const QMetaObject *m_baseMetaObject; QmlAttachedPropertiesFunc m_attachedPropertiesFunc; const QMetaObject *m_attachedPropertiesType; @@ -141,32 +140,30 @@ public: }; QmlTypePrivate::QmlTypePrivate() -: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0), - m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), +: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), + m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) { } -QmlType::QmlType(int type, int listType, int qmlListType, - QmlPrivate::Func opFunc, const char *iid, int index) +QmlType::QmlType(int type, int listType, const char *iid, int index) : d(new QmlTypePrivate) { d->m_isInterface = true; d->m_iid = iid; d->m_typeId = type; d->m_listId = listType; - d->m_qmlListId = qmlListType; - d->m_opFunc = opFunc; + d->m_newFunc = 0; d->m_index = index; d->m_isSetup = true; d->m_version_maj = 0; d->m_version_min = 0; } -QmlType::QmlType(int type, int listType, int qmlListType, - QmlPrivate::Func opFunc, const char *qmlName, +QmlType::QmlType(int type, int listType, + QObject *(*newFunc)(), const char *qmlName, int version_maj, int version_min, const QMetaObject *metaObject, QmlAttachedPropertiesFunc attachedPropertiesFunc, @@ -182,8 +179,7 @@ QmlType::QmlType(int type, int listType, int qmlListType, d->m_version_min = version_min; d->m_typeId = type; d->m_listId = listType; - d->m_qmlListId = qmlListType; - d->m_opFunc = opFunc; + d->m_newFunc = newFunc; d->m_baseMetaObject = metaObject; d->m_attachedPropertiesFunc = attachedPropertiesFunc; d->m_attachedPropertiesType = attachedType; @@ -283,10 +279,7 @@ QObject *QmlType::create() const { d->init(); - QVariant v; - QObject *rv = 0; - d->m_opFunc(QmlPrivate::Create, 0, v, v, (void **)&rv); - + QObject *rv = d->m_newFunc(); if (rv && !d->m_metaObjects.isEmpty()) (void *)new QmlProxyMetaObject(rv, &d->m_metaObjects); @@ -313,39 +306,6 @@ int QmlType::qListTypeId() const return d->m_listId; } -int QmlType::qmlListTypeId() const -{ - return d->m_qmlListId; -} - -void QmlType::listClear(const QVariant &list) -{ - Q_ASSERT(list.userType() == qListTypeId()); - QVariant arg; - d->m_opFunc(QmlPrivate::Clear, 0, list, arg, 0); -} - -void QmlType::listAppend(const QVariant &list, const QVariant &item) -{ - Q_ASSERT(list.userType() == qListTypeId()); - d->m_opFunc(QmlPrivate::Append, 0, list, item, 0); -} - -QVariant QmlType::listAt(const QVariant &list, int idx) -{ - Q_ASSERT(list.userType() == qListTypeId()); - QVariant rv; - void *ptr = (void *)&rv; - d->m_opFunc(QmlPrivate::Value, idx, list, QVariant(), &ptr); - return rv; -} - -int QmlType::listCount(const QVariant &list) -{ - Q_ASSERT(list.userType() == qListTypeId()); - return d->m_opFunc(QmlPrivate::Length, 0, list, QVariant(), 0); -} - const QMetaObject *QmlType::metaObject() const { d->init(); @@ -387,15 +347,6 @@ int QmlType::propertyValueInterceptorCast() const return d->m_propertyValueInterceptorCast; } -QVariant QmlType::fromObject(QObject *obj) const -{ - QVariant rv; - QVariant *v_ptr = &rv; - QVariant vobj = QVariant::fromValue(obj); - d->m_opFunc(QmlPrivate::FromObject, 0, QVariant(), vobj, (void **)&v_ptr); - return rv; -} - const char *QmlType::interfaceIId() const { return d->m_iid; @@ -407,7 +358,6 @@ int QmlType::index() const } int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, - QmlPrivate::Func listFunction, const char *iid) { QWriteLocker lock(metaTypeDataLock()); @@ -415,31 +365,26 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, int index = data->types.count(); - QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, - listFunction, iid, index); + QmlType *type = new QmlType(id.typeId, id.listId, iid, index); data->types.append(type); data->idToType.insert(type->typeId(), type); data->idToType.insert(type->qListTypeId(), type); - data->idToType.insert(type->qmlListTypeId(), type); // XXX No insertMulti, so no multi-version interfaces? if (!type->qmlTypeName().isEmpty()) data->nameToType.insert(type->qmlTypeName(), type); - if (data->interfaces.size() < id.typeId) + if (data->interfaces.size() <= id.typeId) data->interfaces.resize(id.typeId + 16); - if (data->qmllists.size() < id.qmlListId) - data->qmllists.resize(id.qmlListId + 16); - if (data->lists.size() < id.listId) + if (data->lists.size() <= id.listId) data->lists.resize(id.listId + 16); data->interfaces.setBit(id.typeId, true); - data->qmllists.setBit(id.qmlListId, true); data->lists.setBit(id.listId, true); return index; } -int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, +int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QObject *(*func)(), const char *uri, int version_maj, int version_min, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) @@ -464,14 +409,13 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun name += '/'; name += cname; - QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, + QmlType *type = new QmlType(id.typeId, id.listId, func, name, version_maj, version_min, mo, attach, attachMo, pStatus, valueSource, valueInterceptor, extFunc, extmo, index, parser); data->types.append(type); data->idToType.insert(type->typeId(), type); data->idToType.insert(type->qListTypeId(), type); - data->idToType.insert(type->qmlListTypeId(), type); if (!type->qmlTypeName().isEmpty()) data->nameToType.insertMulti(type->qmlTypeName(), type); @@ -480,12 +424,9 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun if (data->objects.size() <= id.typeId) data->objects.resize(id.typeId + 16); - if (data->qmllists.size() <= id.qmlListId) - data->qmllists.resize(id.qmlListId + 16); if (data->lists.size() <= id.listId) data->lists.resize(id.listId + 16); data->objects.setBit(id.typeId, true); - data->qmllists.setBit(id.qmlListId, true); data->lists.setBit(id.listId, true); return index; @@ -527,51 +468,6 @@ int QmlMetaType::listType(int id) return 0; } -/* - Returns the item type for a qml list of type \a id. - */ -int QmlMetaType::qmlListType(int id) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->idToType.value(id); - if (type && type->qmlListTypeId() == id) - return type->typeId(); - else - return 0; -} - -bool QmlMetaType::clear(const QVariant &list) -{ - int userType = list.userType(); - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->idToType.value(userType); - lock.unlock(); - if (type && type->qListTypeId() == userType) { - type->listClear(list); - return true; - } else { - return false; - } -} - -bool QmlMetaType::append(const QVariant &list, const QVariant &item) -{ - int userType = list.userType(); - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->idToType.value(userType); - lock.unlock(); - if (type && type->qListTypeId() == userType && - item.userType() == type->typeId()) { - type->listAppend(list, item); - return true; - } else { - return false; - } -} - int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo) { QReadLocker lock(metaTypeDataLock()); @@ -656,8 +552,6 @@ QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType) QmlMetaTypeData *data = metaTypeData(); if (userType < data->objects.size() && data->objects.testBit(userType)) return Object; - else if (userType < data->qmllists.size() && data->qmllists.testBit(userType)) - return QmlList; else if (userType < data->lists.size() && data->lists.testBit(userType)) return List; else @@ -683,13 +577,6 @@ const char *QmlMetaType::interfaceIId(int userType) return 0; } -bool QmlMetaType::isQmlList(int userType) -{ - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - return userType >= 0 && userType < data->qmllists.size() && data->qmllists.testBit(userType); -} - bool QmlMetaType::isList(int userType) { QReadLocker lock(metaTypeDataLock()); @@ -697,44 +584,6 @@ bool QmlMetaType::isList(int userType) return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType); } -bool QmlMetaType::isList(const QVariant &v) -{ - return (v.type() == QVariant::UserType && isList(v.userType())); -} - -int QmlMetaType::listCount(const QVariant &v) -{ - int userType = v.userType(); - - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->idToType.value(userType); - lock.unlock(); - - if (type && type->qListTypeId() == userType) - return type->listCount(v); - else - return 0; -} - -QVariant QmlMetaType::listAt(const QVariant &v, int idx) -{ - if (idx < 0) - return QVariant(); - - int userType = v.userType(); - - QReadLocker lock(metaTypeDataLock()); - QmlMetaTypeData *data = metaTypeData(); - QmlType *type = data->idToType.value(userType); - lock.unlock(); - - if (type && type->qListTypeId() == userType) - return type->listAt(v, idx); - else - return QVariant(); -} - /*! A custom string convertor allows you to specify a function pointer that returns a variant of \a type. For example, if you have written your own icon diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 3d082f8..98d04c1 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -46,6 +46,7 @@ #include "qmlparserstatus.h" #include "qmlpropertyvaluesource.h" #include "qmlpropertyvalueinterceptor.h" +#include "qmllist.h" #include <QtCore/qglobal.h> #include <QtCore/qvariant.h> @@ -62,8 +63,8 @@ class QmlCustomParser; class Q_DECLARATIVE_EXPORT QmlMetaType { public: - static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); - static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *); + static int registerType(const QmlPrivate::MetaTypeIds &, QObject *(*)(), const char *, int vmaj, int vmin, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); + static int registerInterface(const QmlPrivate::MetaTypeIds &, const char *); static bool copy(int type, void *data, const void *copy = 0); @@ -83,22 +84,15 @@ public: static QObject *toQObject(const QVariant &, bool *ok = 0); static int listType(int); - static bool clear(const QVariant &); - static bool append(const QVariant &, const QVariant &); static int attachedPropertiesFuncId(const QMetaObject *); static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int); - enum TypeCategory { Unknown, Object, List, QmlList }; + enum TypeCategory { Unknown, Object, List }; static TypeCategory typeCategory(int); static bool isInterface(int); static const char *interfaceIId(int); static bool isList(int); - static bool isList(const QVariant &); - static bool isQmlList(int); - static int qmlListType(int); - static int listCount(const QVariant &); - static QVariant listAt(const QVariant &, int); typedef QVariant (*StringConverter)(const QString &); static void registerCustomStringConverter(int, StringConverter); @@ -123,12 +117,6 @@ public: bool isInterface() const; int typeId() const; int qListTypeId() const; - int qmlListTypeId() const; - - void listClear(const QVariant &); - void listAppend(const QVariant &, const QVariant &); - QVariant listAt(const QVariant &, int); - int listCount(const QVariant &); const QMetaObject *metaObject() const; const QMetaObject *baseMetaObject() const; @@ -147,8 +135,8 @@ private: friend class QmlMetaType; friend class QmlTypePrivate; friend struct QmlMetaTypeData; - QmlType(int, int, int, QmlPrivate::Func, const char *, int); - QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); + QmlType(int, int, const char *, int); + QmlType(int, int, QObject *(*)(), const char *, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); ~QmlType(); QmlTypePrivate *d; @@ -160,11 +148,10 @@ int qmlRegisterType(const char *typeName) QByteArray name(typeName); QmlPrivate::MetaTypeIds ids = { qRegisterMetaType<T *>(QByteArray(name + '*').constData()), - qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()), - qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData()) + qRegisterMetaType<QmlListProperty<T> >(QByteArray("QmlListProperty<" + name + ">").constData()), }; - return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0, 0, 0, 0, + return QmlMetaType::registerType(ids, 0, 0, 0, 0, 0, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc<T>(), QmlPrivate::attachedPropertiesMetaObject<T>(), @@ -181,11 +168,10 @@ int qmlRegisterType(const char *uri, int version_maj, int version_min, const cha QByteArray name(typeName); QmlPrivate::MetaTypeIds ids = { qRegisterMetaType<T *>(QByteArray(name + '*').constData()), - qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()), - qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData()) + qRegisterMetaType<QmlListProperty<T> >(QByteArray("QmlListProperty<" + name + ">").constData()), }; - return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, + return QmlMetaType::registerType(ids, QmlPrivate::create<T>, uri, version_maj, version_min, qmlName, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc<T>(), @@ -203,8 +189,7 @@ int qmlRegisterExtendedType(const char *typeName) QByteArray name(typeName); QmlPrivate::MetaTypeIds ids = { qRegisterMetaType<T *>(QByteArray(name + '*').constData()), - qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()), - qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData()) + qRegisterMetaType<QmlListProperty<T> >(QByteArray("QmlListProperty<" + name + ">").constData()), }; QmlAttachedPropertiesFunc attached = @@ -216,7 +201,7 @@ int qmlRegisterExtendedType(const char *typeName) attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>(); } - return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0, 0, 0, 0, + return QmlMetaType::registerType(ids, 0, 0, 0, 0, 0, &T::staticMetaObject, attached, attachedMo, QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), @@ -231,8 +216,7 @@ int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min, c QByteArray name(typeName); QmlPrivate::MetaTypeIds ids = { qRegisterMetaType<T *>(QByteArray(name + '*').constData()), - qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()), - qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData()) + qRegisterMetaType<QmlListProperty<T> >(QByteArray("QmlListProperty<" + name + ">").constData()), }; QmlAttachedPropertiesFunc attached = @@ -244,7 +228,7 @@ int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min, c attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>(); } - return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, + return QmlMetaType::registerType(ids, QmlPrivate::create<T>, uri, version_maj, version_min, qmlName, &T::staticMetaObject, attached, attachedMo, @@ -262,13 +246,10 @@ int qmlRegisterInterface(const char *typeName) QByteArray name(typeName); QmlPrivate::MetaTypeIds ids = { qRegisterMetaType<T *>(QByteArray(name + '*').constData()), - qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()), - qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData()) + qRegisterMetaType<QmlListProperty<T> >(QByteArray("QmlListProperty<" + name + ">").constData()), }; - return QmlMetaType::registerInterface(ids, - QmlPrivate::list_interface_op<T>, - qobject_interface_iid<T *>()); + return QmlMetaType::registerInterface(ids, qobject_interface_iid<T *>()); } template<typename T> @@ -277,11 +258,10 @@ int qmlRegisterCustomType(const char *uri, int version_maj, int version_min, con QByteArray name(typeName); QmlPrivate::MetaTypeIds ids = { qRegisterMetaType<T *>(QByteArray(name + '*').constData()), - qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()), - qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData()) + qRegisterMetaType<QmlListProperty<T> >(QByteArray("QmlListProperty<" + name + ">").constData()), }; - return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, + return QmlMetaType::registerType(ids, QmlPrivate::create<T>, uri, version_maj, version_min, qmlName, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc<T>(), diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 76d1837..15ece1d 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -239,9 +239,7 @@ QmlObjectScriptClass::property(QObject *obj, const Identifier &name) } if (lastData->flags & QmlPropertyCache::Data::IsQList) { - return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, QmlListScriptClass::QListPtr, lastData->propType)); - } else if (lastData->flags & QmlPropertyCache::Data::IsQmlList) { - return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, QmlListScriptClass::QmlListPtr, lastData->propType)); + return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, lastData->propType)); } else if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { QObject *rv = 0; void *args[] = { &rv, 0 }; diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h index e087788..e5ea07f 100644 --- a/src/declarative/qml/qmlprivate.h +++ b/src/declarative/qml/qmlprivate.h @@ -72,39 +72,8 @@ public: namespace QmlPrivate { - class ListInterface - { - public: - virtual ~ListInterface() {} - virtual int type() const = 0; - virtual void append(void *) = 0; - virtual void insert(int, void *) = 0; - virtual void removeAt(int) = 0; - virtual void at(int, void *) const = 0; - virtual int count() const = 0; - virtual void clear() = 0; - }; - - enum ListOp { Append, Set, Insert, Prepend, Length, FromObject, - Object, Create, Value, Clear }; - template<typename T> - int list_op(ListOp op, int val, - const QVariant &vlist, - const QVariant &value, - void **out); - - template<typename T> - int list_nocreate_op(ListOp op, int val, - const QVariant &vlist, - const QVariant &value, - void **out); - - template<typename T> - int list_interface_op(ListOp op, int val, - const QVariant &vlist, - const QVariant &value, - void **out); + QObject *create() { return new T; } template<class From, class To, int N> struct StaticCastSelectorClass @@ -201,9 +170,7 @@ namespace QmlPrivate struct MetaTypeIds { int typeId; int listId; - int qmlListId; }; - typedef int (*Func)(QmlPrivate::ListOp, int, const QVariant &, const QVariant &, void **); typedef QObject *(*CreateFunc)(QObject *); template<typename T> @@ -237,148 +204,6 @@ namespace QmlPrivate }; } -template<typename T> -int QmlPrivate::list_op(QmlPrivate::ListOp op, int val, - const QVariant &vlist, - const QVariant &value, - void **out) -{ - if (op == QmlPrivate::Create) { - QObject *obj = static_cast<QObject *>(new T); - *((QObject **)out) = obj; - return 0; - } - QList<T *> *list = vlist.value<QList<T *> *>(); - switch(op) { - case QmlPrivate::Append: - list->append(value.value<T *>()); - break; - case QmlPrivate::Set: - (*list)[val] = value.value<T *>(); - break; - case QmlPrivate::Insert: - list->insert(val, value.value<T *>()); - break; - case QmlPrivate::Prepend: - list->prepend(value.value<T *>()); - break; - case QmlPrivate::Length: - return list->count(); - break; - case QmlPrivate::Clear: - list->clear(); - return 0; - break; - case QmlPrivate::Create: - break; - case QmlPrivate::Object: - *out = static_cast<QObject *>(value.value<T *>()); - break; - case QmlPrivate::FromObject: - { - QObject *fromObj = value.value<QObject *>(); - T *me = qobject_cast<T *>(fromObj); - if (me) { - *((QVariant *)*out) = QVariant::fromValue(me); - } - } - break; - case QmlPrivate::Value: - if (list->count() <= val) *((QVariant *)*out) = QVariant(); - else *((QVariant *)*out) = QVariant::fromValue(list->at(val)); - break; - } - return 0; -} - -template<typename T> -int QmlPrivate::list_nocreate_op(QmlPrivate::ListOp op, int val, - const QVariant &vlist, - const QVariant &value, - void **out) -{ - QList<T *> *list = vlist.value<QList<T *> *>(); - switch(op) { - case QmlPrivate::Append: - list->append(value.value<T *>()); - break; - case QmlPrivate::Set: - (*list)[val] = value.value<T *>(); - break; - case QmlPrivate::Insert: - list->insert(val, value.value<T *>()); - break; - case QmlPrivate::Prepend: - list->prepend(value.value<T *>()); - break; - case QmlPrivate::Length: - return list->count(); - break; - case QmlPrivate::Clear: - list->clear(); - return 0; - break; - case QmlPrivate::Create: - break; - case QmlPrivate::Object: - *out = static_cast<QObject *>(value.value<T *>()); - break; - case QmlPrivate::FromObject: - { - QObject *fromObj = value.value<QObject *>(); - T *me = qobject_cast<T *>(fromObj); - if (me) { - *((QVariant *)*out) = QVariant::fromValue(me); - } - } - break; - case QmlPrivate::Value: - *((QVariant *)*out) = QVariant::fromValue(list->at(val)); - break; - } - return 0; -} - -template<typename T> -int QmlPrivate::list_interface_op(QmlPrivate::ListOp op, int val, - const QVariant &vlist, - const QVariant &value, - void **out) -{ - QList<T *> *list = vlist.value<QList<T *> *>(); - switch(op) { - case QmlPrivate::Append: - list->append(value.value<T *>()); - break; - case QmlPrivate::Set: - (*list)[val] = value.value<T *>(); - break; - case QmlPrivate::Insert: - list->insert(val, value.value<T *>()); - break; - case QmlPrivate::Prepend: - list->prepend(value.value<T *>()); - break; - case QmlPrivate::Length: - return list->count(); - break; - case QmlPrivate::Clear: - list->clear(); - return 0; - break; - case QmlPrivate::Create: - break; - case QmlPrivate::Object: - break; - case QmlPrivate::FromObject: - break; - case QmlPrivate::Value: - *((QVariant *)*out) = QVariant::fromValue(list->at(val)); - break; - } - return 0; -} - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index e567fd2..a3e655b 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -77,8 +77,6 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p, QmlEngine *engine) flags |= Data::IsQObjectDerived; else if (cat == QmlMetaType::List) flags |= Data::IsQList; - else if (cat == QmlMetaType::QmlList) - flags |= Data::IsQmlList; } } diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 34b648d..18eea80 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -86,7 +86,6 @@ public: IsFunction = 0x00000008, IsQObjectDerived = 0x00000010, IsEnumType = 0x00000020, - IsQmlList = 0x00000040, IsQList = 0x00000080, IsQmlBinding = 0x00000100, IsQScriptValue = 0x00000200, diff --git a/src/declarative/qml/qmlscript.cpp b/src/declarative/qml/qmlscript.cpp index c0320cd..ef142a5 100644 --- a/src/declarative/qml/qmlscript.cpp +++ b/src/declarative/qml/qmlscript.cpp @@ -58,7 +58,7 @@ console.log(otherinterestingitem.property); } } - MouseRegion { onClicked: debugMyComponent() } + MouseArea { onClicked: debugMyComponent() } \endqml \note While it is possible to use any JavaScript code within a Script element, diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 39de062..8655809 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -91,15 +91,13 @@ QmlVME::QmlVME() struct ListInstance { - ListInstance() {} - ListInstance(QList<void *> *q, int t) - : type(t), qListInterface(q), qmlListInterface(0) {} - ListInstance(QmlPrivate::ListInterface *q, int t) - : type(t), qListInterface(0), qmlListInterface(q) {} + ListInstance() + : type(0) {} + ListInstance(int t) + : type(t) {} int type; - QList<void *> *qListInterface; - QmlPrivate::ListInterface *qmlListInterface; + QmlListProperty<void> qListProperty; }; QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp, @@ -654,22 +652,12 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt, } break; - case QmlInstruction::StoreObjectQmlList: - { - QObject *assign = stack.pop(); - const ListInstance &list = qliststack.top(); - - void *d = (void *)&assign; - list.qmlListInterface->append(d); - } - break; - case QmlInstruction::StoreObjectQList: { QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); - list.qListInterface->append((void *)assign); + list.qListProperty.append((QmlListProperty<void>*)&list.qListProperty, assign); } break; @@ -690,12 +678,7 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt, VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign object to list")); - if (list.qmlListInterface) { - void *d = (void *)&ptr; - list.qmlListInterface->append(d); - } else { - list.qListInterface->append(ptr); - } + list.qListProperty.append((QmlListProperty<void>*)&list.qListProperty, ptr); } break; @@ -750,39 +733,16 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt, } break; - case QmlInstruction::FetchQmlList: - { - QObject *target = stack.top(); - - void *a[1]; - // We know that QmlList<*> can be converted to - // QmlPrivate::ListInterface - QmlPrivate::ListInterface *list = 0; - a[0] = &list; - QMetaObject::metacall(target, QMetaObject::ReadProperty, - instr.fetchQmlList.property, a); - if (!list) - VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign to null list")); - - qliststack.push(ListInstance(list, instr.fetchQmlList.type)); - } - break; - case QmlInstruction::FetchQList: { QObject *target = stack.top(); + qliststack.push(ListInstance(instr.fetchQmlList.type)); + void *a[1]; - // We know that QList<T *>* can be converted to - // QList<void *>* - QList<void *> *list = 0; - a[0] = &list; + a[0] = (void *)&(qliststack.top().qListProperty); QMetaObject::metacall(target, QMetaObject::ReadProperty, instr.fetchQmlList.property, a); - if (!list) - VME_EXCEPTION(QCoreApplication::translate("QmlVME","Cannot assign to null list")); - - qliststack.push(ListInstance(list, instr.fetchQmlList.type)); } break; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index 3858138..4886680 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -77,13 +77,14 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, data = new QVariant[metaData->propertyCount]; aConnected.resize(metaData->aliasCount); - int list_type = qMetaTypeId<QmlList<QObject*>* >(); + int list_type = qMetaTypeId<QmlListProperty<QObject> >(); // ### Optimize for (int ii = 0; ii < metaData->propertyCount; ++ii) { int t = (metaData->propertyData() + ii)->propertyType; if (t == list_type) { - listProperties.append(new List(this, ii)); - data[ii] = QVariant::fromValue((QmlList<QObject *>*)listProperties.last()); + listProperties.append(new List(methodOffset + ii)); + data[ii] = QVariant::fromValue(QmlListProperty<QObject>(obj, listProperties.last(), list_append, + list_count, list_at, list_clear)); } else if (t != -1) { data[ii] = QVariant((QVariant::Type)t); } @@ -182,8 +183,9 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) default: break; } - if (t == qMetaTypeId<QmlList<QObject*>* >()) { - *reinterpret_cast<QmlList<QObject *> **>(a[0]) = data[id].value<QmlList<QObject*>*>(); + if (t == qMetaTypeId<QmlListProperty<QObject> >()) { + *reinterpret_cast<QmlListProperty<QObject> *>(a[0]) = + data[id].value<QmlListProperty<QObject> >(); } } else if (c == QMetaObject::WriteProperty) { @@ -318,6 +320,30 @@ void QmlVMEMetaObject::listChanged(int id) activate(object, methodOffset + id, 0); } +void QmlVMEMetaObject::list_append(QmlListProperty<QObject> *prop, QObject *o) +{ + List *list = static_cast<List *>(prop->data); + list->append(o); + QMetaObject::activate(prop->object, list->notifyIndex, 0); +} + +int QmlVMEMetaObject::list_count(QmlListProperty<QObject> *prop) +{ + return static_cast<List *>(prop->data)->count(); +} + +QObject *QmlVMEMetaObject::list_at(QmlListProperty<QObject> *prop, int index) +{ + return static_cast<List *>(prop->data)->at(index); +} + +void QmlVMEMetaObject::list_clear(QmlListProperty<QObject> *prop) +{ + List *list = static_cast<List *>(prop->data); + list->clear(); + QMetaObject::activate(prop->object, list->notifyIndex, 0); +} + void QmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor) { if (aInterceptors.isEmpty()) diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 7fa46fd..3eb776e 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -138,33 +138,18 @@ private: QAbstractDynamicMetaObject *parent; void listChanged(int); - class List : public QmlConcreteList<QObject*> + class List : public QList<QObject*> { public: - List(QmlVMEMetaObject *p, int propIdx) - : parent(p), parentProperty(propIdx) { } - - virtual void append(QObject *v) { - QmlConcreteList<QObject*>::append(v); - parent->listChanged(parentProperty); - } - virtual void insert(int i, QObject *v) { - QmlConcreteList<QObject*>::insert(i, v); - parent->listChanged(parentProperty); - } - virtual void clear() { - QmlConcreteList<QObject*>::clear(); - parent->listChanged(parentProperty); - } - virtual void removeAt(int i) { - QmlConcreteList<QObject*>::removeAt(i); - parent->listChanged(parentProperty); - } - private: - QmlVMEMetaObject *parent; - int parentProperty; + List(int lpi) : notifyIndex(lpi) {} + int notifyIndex; }; QList<List *> listProperties; + + static void list_append(QmlListProperty<QObject> *, QObject *); + static int list_count(QmlListProperty<QObject> *); + static QObject *list_at(QmlListProperty<QObject> *, int); + static void list_clear(QmlListProperty<QObject> *); }; QT_END_NAMESPACE |