From: Andrew den Exter Date: Wed, 4 Apr 2012 07:26:22 +0000 (+1000) Subject: Add an v8 object template for visual data model change sets. X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=6759ea52fa636505eda925907a15b3ef243c20c6;p=konrad%2Fqtdeclarative.git Add an v8 object template for visual data model change sets. This is more optimal than dynamically creating an object per change for each signal emission. Also create static string instances for property names common to all item objects. Change-Id: I8b0a6b683df4ee9c55c15cc928603e82f37045f7 Reviewed-by: Martin Jones Reviewed-by: Chris Adams --- diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 4e53964..85a2f1b 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -249,6 +249,7 @@ QVariant QV8Engine::toVariant(v8::Handle value, int typeHint) case QV8ObjectResource::Context2DType: case QV8ObjectResource::ParticleDataType: case QV8ObjectResource::LocaleDataType: + case QV8ObjectResource::ChangeSetArrayType: return QVariant(); case QV8ObjectResource::TypeType: return m_typeWrapper.toVariant(r); diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 0cd54ae..649edcd 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -126,7 +126,6 @@ QT_BEGIN_NAMESPACE return rv; \ } \ - template inline T *v8_resource_cast(v8::Handle object) { QV8ObjectResource *resource = static_cast(object->GetExternalResource()); diff --git a/src/qml/qml/v8/qv8objectresource_p.h b/src/qml/qml/v8/qv8objectresource_p.h index c37905a..919f2a9 100644 --- a/src/qml/qml/v8/qv8objectresource_p.h +++ b/src/qml/qml/v8/qv8objectresource_p.h @@ -73,7 +73,7 @@ public: ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType, ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType, ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType, - SequenceType, LocaleDataType }; + SequenceType, LocaleDataType, ChangeSetArrayType }; virtual ResourceType resourceType() const = 0; QV8Engine *engine; diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 0b0dbf0..a9b6e71 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -55,6 +55,48 @@ QT_BEGIN_NAMESPACE +class QQuickVisualDataModelEngineData : public QV8Engine::Deletable +{ +public: + enum + { + Model, + Groups, + IsUnresolved, + ItemsIndex, + PersistedItemsIndex, + InItems, + InPersistedItems, + StringCount + }; + + QQuickVisualDataModelEngineData(QV8Engine *engine); + ~QQuickVisualDataModelEngineData(); + + v8::Local array( + QV8Engine *engine, const QVector &changes); + v8::Local array( + QV8Engine *engine, const QVector &changes); + v8::Local array( + QV8Engine *engine, const QVector &changes); + + + inline v8::Local model() { return strings->Get(Model)->ToString(); } + inline v8::Local groups() { return strings->Get(Groups)->ToString(); } + inline v8::Local isUnresolved() { return strings->Get(IsUnresolved)->ToString(); } + inline v8::Local itemsIndex() { return strings->Get(ItemsIndex)->ToString(); } + inline v8::Local persistedItemsIndex() { return strings->Get(PersistedItemsIndex)->ToString(); } + inline v8::Local inItems() { return strings->Get(InItems)->ToString(); } + inline v8::Local inPersistedItems() { return strings->Get(InPersistedItems)->ToString(); } + + v8::Persistent strings; + v8::Persistent constructorChange; + v8::Persistent constructorChangeArray; +}; + +V8_DEFINE_EXTENSION(QQuickVisualDataModelEngineData, engineData) + + void QQuickVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop) { prop.setWritable(false); @@ -1453,21 +1495,26 @@ void QQuickVisualDataModelItemMetaType::initializeConstructor() v8::HandleScope handleScope; v8::Context::Scope contextScope(v8Engine->context()); + QQuickVisualDataModelEngineData *data = engineData(v8Engine); + constructor = qPersistentNew(v8::ObjectTemplate::New()); constructor->SetHasExternalResource(true); - constructor->SetAccessor(v8::String::New("model"), get_model); - constructor->SetAccessor(v8::String::New("groups"), get_groups, set_groups); - constructor->SetAccessor(v8::String::New("isUnresolved"), get_member, 0, v8::Int32::New(30)); - - int notifierId = 0; - for (int i = 0; i < groupNames.count(); ++i, ++notifierId) { + constructor->SetAccessor(data->model(), get_model); + constructor->SetAccessor(data->groups(), get_groups, set_groups); + constructor->SetAccessor(data->isUnresolved(), get_member, 0, v8::Int32::New(30)); + constructor->SetAccessor(data->inItems(), get_member, set_member, v8::Int32::New(1)); + constructor->SetAccessor(data->inPersistedItems(), get_member, set_member, v8::Int32::New(2)); + constructor->SetAccessor(data->itemsIndex(), get_index, 0, v8::Int32::New(1)); + constructor->SetAccessor(data->persistedItemsIndex(), get_index, 0, v8::Int32::New(2)); + + for (int i = 2; i < groupNames.count(); ++i) { QString propertyName = QStringLiteral("in") + groupNames.at(i); propertyName.replace(2, 1, propertyName.at(2).toUpper()); constructor->SetAccessor( v8Engine->toString(propertyName), get_member, set_member, v8::Int32::New(i + 1)); } - for (int i = 0; i < groupNames.count(); ++i, ++notifierId) { + for (int i = 2; i < groupNames.count(); ++i) { const QString propertyName = groupNames.at(i) + QStringLiteral("Index"); constructor->SetAccessor( v8Engine->toString(propertyName), get_index, 0, v8::Int32::New(i + 1)); @@ -1988,10 +2035,9 @@ void QQuickVisualDataGroupPrivate::emitChanges(QV8Engine *engine) if (isChangedConnected(q) && !changeSet.isEmpty()) { v8::HandleScope handleScope; v8::Context::Scope contextScope(engine->context()); - v8::Local removed = QQuickVisualDataModelPrivate::buildChangeList(changeSet.removes()); - v8::Local inserted = QQuickVisualDataModelPrivate::buildChangeList(changeSet.inserts()); - emit q->changed( - QQmlV8Handle::fromHandle(removed), QQmlV8Handle::fromHandle(inserted)); + v8::Local removed = engineData(engine)->array(engine, changeSet.removes()); + v8::Local inserted = engineData(engine)->array(engine, changeSet.inserts()); + emit q->changed(QQmlV8Handle::fromHandle(removed), QQmlV8Handle::fromHandle(inserted)); } if (changeSet.difference() != 0) emit q->countChanged(); @@ -2857,6 +2903,148 @@ void QQuickVisualPartsModel::emitModelUpdated(const QQuickChangeSet &changeSet, emit countChanged(); } +//============================================================================ + +v8::Handle get_change_index(v8::Local, const v8::AccessorInfo &info) +{ + return info.This()->GetInternalField(0); +} + +v8::Handle get_change_count(v8::Local, const v8::AccessorInfo &info) +{ + return info.This()->GetInternalField(1); +} + +v8::Handle get_change_moveId(v8::Local, const v8::AccessorInfo &info) +{ + return info.This()->GetInternalField(2); +} + +class QQuickVisualDataGroupChangeArray : public QV8ObjectResource +{ + V8_RESOURCE_TYPE(ChangeSetArrayType) +public: + QQuickVisualDataGroupChangeArray(QV8Engine *engine) + : QV8ObjectResource(engine) + { + } + + virtual quint32 count() const = 0; + virtual const QQuickChangeSet::Change &at(int index) const = 0; + + static v8::Handle get_change(quint32 index, const v8::AccessorInfo &info) + { + QQuickVisualDataGroupChangeArray *array = v8_resource_cast(info.This()); + if (!array) + V8THROW_ERROR("Not a valid change array"); + + if (index >= array->count()) + return v8::Undefined(); + + const QQuickChangeSet::Change &change = array->at(index); + + v8::Local object = engineData(array->engine)->constructorChange->NewInstance(); + object->SetInternalField(0, v8::Int32::New(change.index)); + object->SetInternalField(1, v8::Int32::New(change.count)); + if (change.isMove()) + object->SetInternalField(2, v8::Int32::New(change.moveId)); + + return object; + } + + static v8::Handle get_length(v8::Local, const v8::AccessorInfo &info) + { + QQuickVisualDataGroupChangeArray *array = v8_resource_cast(info.This()); + if (!array) + V8THROW_ERROR("Not a valid change array"); + + return v8::Integer::New(array->count()); + } + + static v8::Local constructor() + { + v8::Local changeArray = v8::FunctionTemplate::New(); + changeArray->InstanceTemplate()->SetHasExternalResource(true); + changeArray->InstanceTemplate()->SetIndexedPropertyHandler(get_change); + changeArray->InstanceTemplate()->SetAccessor(v8::String::New("length"), get_length); + return changeArray->GetFunction(); + } +}; + +class QQuickVisualDataGroupRemoveArray : public QQuickVisualDataGroupChangeArray +{ +public: + QQuickVisualDataGroupRemoveArray(QV8Engine *engine, const QVector &changes) + : QQuickVisualDataGroupChangeArray(engine) + , changes(changes) + { + } + + quint32 count() const { return changes.count(); } + const QQuickChangeSet::Change &at(int index) const { return changes.at(index); } + +private: + QVector changes; +}; + +class QQuickVisualDataGroupInsertArray : public QQuickVisualDataGroupChangeArray +{ +public: + QQuickVisualDataGroupInsertArray(QV8Engine *engine, const QVector &changes) + : QQuickVisualDataGroupChangeArray(engine) + , changes(changes) + { + } + + quint32 count() const { return changes.count(); } + const QQuickChangeSet::Change &at(int index) const { return changes.at(index); } + +private: + QVector changes; +}; + +QQuickVisualDataModelEngineData::QQuickVisualDataModelEngineData(QV8Engine *) +{ + strings = qPersistentNew(v8::Array::New(StringCount)); + strings->Set(Model, v8::String::New("model")); + strings->Set(Groups, v8::String::New("groups")); + strings->Set(IsUnresolved, v8::String::New("isUnresolved")); + strings->Set(ItemsIndex, v8::String::New("itemsIndex")); + strings->Set(PersistedItemsIndex, v8::String::New("persistedItemsIndex")); + strings->Set(InItems, v8::String::New("inItems")); + strings->Set(InPersistedItems, v8::String::New("inPersistedItems")); + + v8::Local change = v8::FunctionTemplate::New(); + change->InstanceTemplate()->SetAccessor(v8::String::New("index"), get_change_index); + change->InstanceTemplate()->SetAccessor(v8::String::New("count"), get_change_count); + change->InstanceTemplate()->SetAccessor(v8::String::New("moveId"), get_change_moveId); + change->InstanceTemplate()->SetInternalFieldCount(3); + constructorChange = qPersistentNew(change->GetFunction()); + constructorChangeArray = qPersistentNew(QQuickVisualDataGroupChangeArray::constructor()); +} + +QQuickVisualDataModelEngineData::~QQuickVisualDataModelEngineData() +{ + qPersistentDispose(strings); + qPersistentDispose(constructorChange); + qPersistentDispose(constructorChangeArray); +} + +v8::Local QQuickVisualDataModelEngineData::array( + QV8Engine *engine, const QVector &changes) +{ + v8::Local array = constructorChangeArray->NewInstance(); + array->SetExternalResource(new QQuickVisualDataGroupRemoveArray(engine, changes)); + return array; +} + +v8::Local QQuickVisualDataModelEngineData::array( + QV8Engine *engine, const QVector &changes) +{ + v8::Local array = constructorChangeArray->NewInstance(); + array->SetExternalResource(new QQuickVisualDataGroupInsertArray(engine, changes)); + return array; +} QT_END_NAMESPACE diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp index 9047dcc..02b1618 100644 --- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp +++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp @@ -290,7 +290,6 @@ void tst_qquickvisualdatamodel::initTestCase() void tst_qquickvisualdatamodel::cleanupTestCase() { - } tst_qquickvisualdatamodel::tst_qquickvisualdatamodel()