From 347f84e5aca9423536cb0cd7a2eafaf836a72212 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 1 Dec 2011 14:01:13 +1000 Subject: Minimize the number of objects created per item in VisualDataModel. Derive from QDeclarativeContext and reference count the context object instead of parenting it to the context. Combined with a weak persistent v8 handle the allows the context object to be returned by javascript accessors instead of creating a new instance for every use. In addition to the efficiency advantages of creating fewer objects, routing all data access through a single object means that object can also persist data instead of just acting as a proxy. Change-Id: I107dc8c901f16f2a4b420ff1cbffa7a6be27de89 Reviewed-by: Martin Jones --- src/quick/items/qquickvisualdatamodel_p_p.h | 403 ++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 src/quick/items/qquickvisualdatamodel_p_p.h (limited to 'src/quick/items/qquickvisualdatamodel_p_p.h') diff --git a/src/quick/items/qquickvisualdatamodel_p_p.h b/src/quick/items/qquickvisualdatamodel_p_p.h new file mode 100644 index 0000000000..b843e6ac1a --- /dev/null +++ b/src/quick/items/qquickvisualdatamodel_p_p.h @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKVISUALDATAMODEL_P_P_H +#define QQUICKVISUALDATAMODEL_P_P_H + +#include "qquickvisualdatamodel_p.h" + +#include +#include + +#include + +// +// 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. +// + +QT_BEGIN_NAMESPACE + +class QQuickVisualDataModelItemMetaType : public QDeclarativeRefCount +{ +public: + QQuickVisualDataModelItemMetaType(QV8Engine *engine, QQuickVisualDataModel *model, const QStringList &groupNames); + ~QQuickVisualDataModelItemMetaType(); + + int parseGroups(const QStringList &groupNames) const; + int parseGroups(const v8::Local &groupNames) const; + + static void release_index(v8::Persistent object, void *parameter); + static void release_model(v8::Persistent object, void *parameter); + + static v8::Handle get_model(v8::Local, const v8::AccessorInfo &info); + static v8::Handle get_groups(v8::Local, const v8::AccessorInfo &info); + static void set_groups( + v8::Local, v8::Local value, const v8::AccessorInfo &info); + static v8::Handle get_member(v8::Local, const v8::AccessorInfo &info); + static void set_member( + v8::Local, v8::Local value, const v8::AccessorInfo &info); + static v8::Handle get_index(v8::Local, const v8::AccessorInfo &info); + + QDeclarativeGuard model; + const int groupCount; + const int memberPropertyOffset; + const int indexPropertyOffset; + QV8Engine * const v8Engine; + QMetaObject *metaObject; + const QStringList groupNames; + v8::Persistent constructor; +}; + +class QQuickVisualAdaptorModel; +class QVDMIncubationTask; + +class QQuickVisualDataModelItem : public QObject, public QV8ObjectResource +{ + Q_OBJECT + Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged) + V8_RESOURCE_TYPE(VisualDataItemType) +public: + QQuickVisualDataModelItem( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int modelIndex); + ~QQuickVisualDataModelItem(); + + void referenceObject() { ++objectRef; } + bool releaseObject() { return --objectRef == 0 && !(groups & QDeclarativeListCompositor::PersistedFlag); } + bool isObjectReferenced() const { return objectRef == 0 && !(groups & QDeclarativeListCompositor::PersistedFlag); } + + bool isReferenced() const { return scriptRef || incubationTask || (groups & QDeclarativeListCompositor::PersistedFlag); } + + void Dispose(); + + int modelIndex() const { return index[0]; } + void setModelIndex(int idx) { index[0] = idx; emit modelIndexChanged(); } + + virtual v8::Handle get() { return engine->newQObject(this); } + +Q_SIGNALS: + void modelIndexChanged(); + +public: + QQuickVisualDataModelItemMetaType * const metaType; + QDeclarativeGuard model; + QDeclarativeGuard object; + QQuickVisualDataModelAttached *attached; + v8::Persistent indexHandle; + v8::Persistent modelHandle; + QIntrusiveListNode cacheNode; + int objectRef; + int scriptRef; + int groups; + int index[QDeclarativeListCompositor::MaximumGroupCount]; + QVDMIncubationTask *incubationTask; +}; + +typedef QDeclarativeListCompositor Compositor; + +class QQuickVisualDataModelPrivate; +class QVDMIncubationTask : public QDeclarativeIncubator +{ +public: + QVDMIncubationTask(QQuickVisualDataModelPrivate *l, IncubationMode mode) + : QDeclarativeIncubator(mode) + , incubating(0) + , incubatingContext(0) + , vdm(l) {} + + virtual void statusChanged(Status); + virtual void setInitialState(QObject *); + + QQuickVisualDataModelItem *incubating; + QDeclarativeContext *incubatingContext; + +private: + QQuickVisualDataModelPrivate *vdm; +}; + + +class QQuickVisualDataGroupEmitter +{ +public: + virtual void emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset) = 0; + virtual void createdPackage(int, QDeclarativePackage *) {} + virtual void initPackage(int, QDeclarativePackage *) {} + virtual void destroyingPackage(QDeclarativePackage *) {} + + QIntrusiveListNode emitterNode; +}; + +typedef QIntrusiveList QQuickVisualDataGroupEmitterList; + +class QQuickVisualDataGroupPrivate : public QObjectPrivate +{ +public: + Q_DECLARE_PUBLIC(QQuickVisualDataGroup) + + QQuickVisualDataGroupPrivate() : group(Compositor::Cache), defaultInclude(false) {} + + static QQuickVisualDataGroupPrivate *get(QQuickVisualDataGroup *group) { + return static_cast(QObjectPrivate::get(group)); } + + void setModel(QQuickVisualDataModel *model, Compositor::Group group); + void emitChanges(QV8Engine *engine); + void emitModelUpdated(bool reset); + + void createdPackage(int index, QDeclarativePackage *package); + void initPackage(int index, QDeclarativePackage *package); + void destroyingPackage(QDeclarativePackage *package); + + bool parseIndex(const v8::Local &value, int *index, Compositor::Group *group) const; + bool parseGroupArgs( + QDeclarativeV8Function *args, Compositor::Group *group, int *index, int *count, int *groups) const; + + Compositor::Group group; + QDeclarativeGuard model; + QQuickVisualDataGroupEmitterList emitters; + QDeclarativeChangeSet changeSet; + QString name; + bool defaultInclude; +}; + +class QQuickVisualDataModelParts; + +class QQuickVisualDataModelPrivate : public QObjectPrivate, public QQuickVisualDataGroupEmitter +{ + Q_DECLARE_PUBLIC(QQuickVisualDataModel) +public: + QQuickVisualDataModelPrivate(QDeclarativeContext *); + ~QQuickVisualDataModelPrivate(); + + static QQuickVisualDataModelPrivate *get(QQuickVisualDataModel *m) { + return static_cast(QObjectPrivate::get(m)); + } + + void init(); + void connectModel(QQuickVisualAdaptorModel *model); + + QObject *object(Compositor::Group group, int index, bool asynchronous, bool reference); + void destroy(QObject *object); + QQuickVisualDataModel::ReleaseFlags release(QObject *object); + QString stringValue(Compositor::Group group, int index, const QString &name); + int cacheIndexOf(QObject *object) const; + void emitCreatedPackage(QQuickVisualDataModelItem *cacheItem, QDeclarativePackage *package); + void emitInitPackage(QQuickVisualDataModelItem *cacheItem, QDeclarativePackage *package); + void emitCreatedItem(QQuickVisualDataModelItem *cacheItem, QQuickItem *item) { + emit q_func()->createdItem(cacheItem->index[m_compositorGroup], item); } + void emitInitItem(QQuickVisualDataModelItem *cacheItem, QQuickItem *item) { + emit q_func()->initItem(cacheItem->index[m_compositorGroup], item); } + void emitDestroyingPackage(QDeclarativePackage *package); + void emitDestroyingItem(QQuickItem *item) { emit q_func()->destroyingItem(item); } + + void updateFilterGroup(); + + void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags); + void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags); + void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags); + + void itemsInserted( + const QVector &inserts, + QVarLengthArray, Compositor::MaximumGroupCount> *translatedInserts, + QHash > *movedItems = 0); + void itemsInserted(const QVector &inserts); + void itemsRemoved( + const QVector &removes, + QVarLengthArray, Compositor::MaximumGroupCount> *translatedRemoves, + QHash > *movedItems = 0); + void itemsRemoved(const QVector &removes); + void itemsMoved( + const QVector &removes, const QVector &inserts); + void itemsChanged(const QVector &changes); + template static v8::Local buildChangeList(const QVector &changes); + void emitChanges(); + void emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset); + + + static void group_append(QDeclarativeListProperty *property, QQuickVisualDataGroup *group); + static int group_count(QDeclarativeListProperty *property); + static QQuickVisualDataGroup *group_at(QDeclarativeListProperty *property, int index); + + void releaseIncubator(QVDMIncubationTask *incubationTask); + void incubatorStatusChanged(QVDMIncubationTask *incubationTask, QDeclarativeIncubator::Status status); + void setInitialState(QVDMIncubationTask *incubationTask, QObject *o); + + QQuickVisualAdaptorModel *m_adaptorModel; + QDeclarativeComponent *m_delegate; + QQuickVisualDataModelItemMetaType *m_cacheMetaType; + QDeclarativeGuard m_context; + + QList m_cache; + QQuickVisualDataModelParts *m_parts; + QQuickVisualDataGroupEmitterList m_pendingParts; + + QDeclarativeListCompositor m_compositor; + QDeclarativeListCompositor::Group m_compositorGroup; + bool m_complete : 1; + bool m_delegateValidated : 1; + bool m_reset : 1; + bool m_transaction : 1; + bool m_incubatorCleanupScheduled : 1; + + QString m_filterGroup; + QList watchedRoles; + + union { + struct { + QQuickVisualDataGroup *m_cacheItems; + QQuickVisualDataGroup *m_items; + QQuickVisualDataGroup *m_persistedItems; + }; + QQuickVisualDataGroup *m_groups[Compositor::MaximumGroupCount]; + }; + int m_groupCount; + + QList m_finishedIncubating; +}; + +class QQuickVisualPartsModel : public QQuickVisualModel, public QQuickVisualDataGroupEmitter +{ + Q_OBJECT + Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup) +public: + QQuickVisualPartsModel(QQuickVisualDataModel *model, const QString &part, QObject *parent = 0); + ~QQuickVisualPartsModel(); + + QString filterGroup() const; + void setFilterGroup(const QString &group); + void resetFilterGroup(); + void updateFilterGroup(); + void updateFilterGroup(Compositor::Group group, const QDeclarativeChangeSet &changeSet); + + int count() const; + bool isValid() const; + QQuickItem *item(int index, bool asynchronous=false); + ReleaseFlags release(QQuickItem *item); + QString stringValue(int index, const QString &role); + void setWatchedRoles(QList roles); + + int indexOf(QQuickItem *item, QObject *objectContext) const; + + void emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset); + + void createdPackage(int index, QDeclarativePackage *package); + void initPackage(int index, QDeclarativePackage *package); + void destroyingPackage(QDeclarativePackage *package); + +Q_SIGNALS: + void filterGroupChanged(); + +private: + QQuickVisualDataModel *m_model; + QHash m_packaged; + QString m_part; + QString m_filterGroup; + QList m_watchedRoles; + Compositor::Group m_compositorGroup; + bool m_inheritGroup; +}; + +class QMetaPropertyBuilder; + +class QQuickVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject +{ +public: + QQuickVisualDataModelPartsMetaObject(QObject *parent) + : QDeclarativeOpenMetaObject(parent) {} + + virtual void propertyCreated(int, QMetaPropertyBuilder &); + virtual QVariant initialValue(int); +}; + +class QQuickVisualDataModelParts : public QObject +{ +Q_OBJECT +public: + QQuickVisualDataModelParts(QQuickVisualDataModel *parent); + + QQuickVisualDataModel *model; + QList models; +}; + +class QQuickVisualDataModelAttachedMetaObject : public QAbstractDynamicMetaObject +{ +public: + QQuickVisualDataModelAttachedMetaObject( + QQuickVisualDataModelAttached *attached, QQuickVisualDataModelItemMetaType *metaType); + ~QQuickVisualDataModelAttachedMetaObject(); + + int metaCall(QMetaObject::Call, int _id, void **); + +private: + QQuickVisualDataModelAttached *attached; + QQuickVisualDataModelItemMetaType *metaType; +}; + +class QQuickVisualDataModelContext : public QDeclarativeContext +{ + Q_OBJECT +public: + QQuickVisualDataModelContext( + QQuickVisualDataModelItem *cacheItem, + QDeclarativeContext *parentContext, + QObject *parent = 0) + : QDeclarativeContext(parentContext, parent) + , cacheItem(cacheItem) + { + ++cacheItem->scriptRef; + } + + ~QQuickVisualDataModelContext() + { + cacheItem->Dispose(); + } + + QQuickVisualDataModelItem *cacheItem; +}; + +QT_END_NAMESPACE + +#endif -- cgit v1.2.3