src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    76 public:
    76 public:
    77     QDeclarativeVisualItemModelPrivate() : QObjectPrivate() {}
    77     QDeclarativeVisualItemModelPrivate() : QObjectPrivate() {}
    78 
    78 
    79     static void children_append(QDeclarativeListProperty<QDeclarativeItem> *prop, QDeclarativeItem *item) {
    79     static void children_append(QDeclarativeListProperty<QDeclarativeItem> *prop, QDeclarativeItem *item) {
    80         QDeclarative_setParent_noEvent(item, prop->object);
    80         QDeclarative_setParent_noEvent(item, prop->object);
    81         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.append(item);
    81         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.append(Item(item));
    82         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->itemAppended();
    82         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->itemAppended();
    83         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
    83         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
    84     }
    84     }
    85 
    85 
    86     static int children_count(QDeclarativeListProperty<QDeclarativeItem> *prop) {
    86     static int children_count(QDeclarativeListProperty<QDeclarativeItem> *prop) {
    87         return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.count();
    87         return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.count();
    88     }
    88     }
    89 
    89 
    90     static QDeclarativeItem *children_at(QDeclarativeListProperty<QDeclarativeItem> *prop, int index) {
    90     static QDeclarativeItem *children_at(QDeclarativeListProperty<QDeclarativeItem> *prop, int index) {
    91         return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.at(index);
    91         return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.at(index).item;
    92     }
    92     }
    93 
    93 
    94     void itemAppended() {
    94     void itemAppended() {
    95         Q_Q(QDeclarativeVisualItemModel);
    95         Q_Q(QDeclarativeVisualItemModel);
    96         QDeclarativeVisualItemModelAttached *attached = QDeclarativeVisualItemModelAttached::properties(children.last());
    96         QDeclarativeVisualItemModelAttached *attached = QDeclarativeVisualItemModelAttached::properties(children.last().item);
    97         attached->setIndex(children.count()-1);
    97         attached->setIndex(children.count()-1);
    98         emit q->itemsInserted(children.count()-1, 1);
    98         emit q->itemsInserted(children.count()-1, 1);
    99         emit q->countChanged();
    99         emit q->countChanged();
   100     }
   100     }
   101 
   101 
   102     void emitChildrenChanged() {
   102     void emitChildrenChanged() {
   103         Q_Q(QDeclarativeVisualItemModel);
   103         Q_Q(QDeclarativeVisualItemModel);
   104         emit q->childrenChanged();
   104         emit q->childrenChanged();
   105     }
   105     }
   106 
   106 
   107     QList<QDeclarativeItem *> children;
   107     int indexOf(QDeclarativeItem *item) const {
       
   108         for (int i = 0; i < children.count(); ++i)
       
   109             if (children.at(i).item == item)
       
   110                 return i;
       
   111         return -1;
       
   112     }
       
   113 
       
   114     class Item {
       
   115     public:
       
   116         Item(QDeclarativeItem *i) : item(i), ref(0) {}
       
   117 
       
   118         void addRef() { ++ref; }
       
   119         bool deref() { return --ref == 0; }
       
   120 
       
   121         QDeclarativeItem *item;
       
   122         int ref;
       
   123     };
       
   124 
       
   125     QList<Item> children;
   108 };
   126 };
   109 
   127 
   110 
   128 
   111 /*!
   129 /*!
   112     \qmlclass VisualItemModel QDeclarativeVisualItemModel
   130     \qmlclass VisualItemModel QDeclarativeVisualItemModel
       
   131     \ingroup qml-working-with-data
   113   \since 4.7
   132   \since 4.7
   114     \brief The VisualItemModel allows items to be provided to a view.
   133     \brief The VisualItemModel allows items to be provided to a view.
   115 
   134 
   116     A VisualItemModel contains the visual items to be used in a view.
   135     A VisualItemModel contains the visual items to be used in a view.
   117     When a VisualItemModel is used in a view, the view does not require
   136     When a VisualItemModel is used in a view, the view does not require
   180 }
   199 }
   181 
   200 
   182 QDeclarativeItem *QDeclarativeVisualItemModel::item(int index, bool)
   201 QDeclarativeItem *QDeclarativeVisualItemModel::item(int index, bool)
   183 {
   202 {
   184     Q_D(QDeclarativeVisualItemModel);
   203     Q_D(QDeclarativeVisualItemModel);
   185     return d->children.at(index);
   204     QDeclarativeVisualItemModelPrivate::Item &item = d->children[index];
       
   205     item.addRef();
       
   206     return item.item;
   186 }
   207 }
   187 
   208 
   188 QDeclarativeVisualModel::ReleaseFlags QDeclarativeVisualItemModel::release(QDeclarativeItem *item)
   209 QDeclarativeVisualModel::ReleaseFlags QDeclarativeVisualItemModel::release(QDeclarativeItem *item)
   189 {
   210 {
   190     if (item->scene())
   211     Q_D(QDeclarativeVisualItemModel);
   191         item->scene()->removeItem(item);
   212     int idx = d->indexOf(item);
   192     QDeclarative_setParent_noEvent(item, this);
   213     if (idx >= 0) {
       
   214         if (d->children[idx].deref()) {
       
   215             if (item->scene())
       
   216                 item->scene()->removeItem(item);
       
   217             QDeclarative_setParent_noEvent(item, this);
       
   218         }
       
   219     }
   193     return 0;
   220     return 0;
   194 }
   221 }
   195 
   222 
   196 bool QDeclarativeVisualItemModel::completePending() const
   223 bool QDeclarativeVisualItemModel::completePending() const
   197 {
   224 {
   206 QString QDeclarativeVisualItemModel::stringValue(int index, const QString &name)
   233 QString QDeclarativeVisualItemModel::stringValue(int index, const QString &name)
   207 {
   234 {
   208     Q_D(QDeclarativeVisualItemModel);
   235     Q_D(QDeclarativeVisualItemModel);
   209     if (index < 0 || index >= d->children.count())
   236     if (index < 0 || index >= d->children.count())
   210         return QString();
   237         return QString();
   211     return QDeclarativeEngine::contextForObject(d->children.at(index))->contextProperty(name).toString();
   238     return QDeclarativeEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
   212 }
       
   213 
       
   214 QVariant QDeclarativeVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
       
   215 {
       
   216     Q_D(QDeclarativeVisualItemModel);
       
   217     if (index < 0 || index >= d->children.count())
       
   218         return QVariant();
       
   219     QDeclarativeContext *ccontext = qmlContext(this);
       
   220     QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
       
   221     ctxt->setContextObject(d->children.at(index));
       
   222     QDeclarativeExpression e(ctxt, objectContext, expression);
       
   223     QVariant value = e.evaluate();
       
   224     delete ctxt;
       
   225     return value;
       
   226 }
   239 }
   227 
   240 
   228 int QDeclarativeVisualItemModel::indexOf(QDeclarativeItem *item, QObject *) const
   241 int QDeclarativeVisualItemModel::indexOf(QDeclarativeItem *item, QObject *) const
   229 {
   242 {
   230     Q_D(const QDeclarativeVisualItemModel);
   243     Q_D(const QDeclarativeVisualItemModel);
   231     return d->children.indexOf(item);
   244     return d->indexOf(item);
   232 }
   245 }
   233 
   246 
   234 QDeclarativeVisualItemModelAttached *QDeclarativeVisualItemModel::qmlAttachedProperties(QObject *obj)
   247 QDeclarativeVisualItemModelAttached *QDeclarativeVisualItemModel::qmlAttachedProperties(QObject *obj)
   235 {
   248 {
   236     return QDeclarativeVisualItemModelAttached::properties(obj);
   249     return QDeclarativeVisualItemModelAttached::properties(obj);
   416     int index() const;
   429     int index() const;
   417     void setIndex(int index);
   430     void setIndex(int index);
   418 
   431 
   419     int propForRole(int) const;
   432     int propForRole(int) const;
   420     void setValue(int, const QVariant &);
   433     void setValue(int, const QVariant &);
       
   434     bool hasValue(int id) const {
       
   435         return m_meta->hasValue(id);
       
   436     }
   421 
   437 
   422     void ensureProperties();
   438     void ensureProperties();
   423 
   439 
   424 Q_SIGNALS:
   440 Q_SIGNALS:
   425     void indexChanged();
   441     void indexChanged();
   494         QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
   510         QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
   495         if (it != model->m_roleNames.end()) {
   511         if (it != model->m_roleNames.end()) {
   496             QVariant value = model->m_listModelInterface->data(data->m_index, *it);
   512             QVariant value = model->m_listModelInterface->data(data->m_index, *it);
   497             return value;
   513             return value;
   498         } else if (model->m_roles.count() == 1 && propName == "modelData") {
   514         } else if (model->m_roles.count() == 1 && propName == "modelData") {
   499             //for compatability with other lists, assign modelData if there is only a single role
   515             //for compatibility with other lists, assign modelData if there is only a single role
   500             QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
   516             QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
   501             return value;
   517             return value;
   502         }
   518         }
   503     } else if (model->m_abstractItemModel) {
   519     } else if (model->m_abstractItemModel) {
   504         model->ensureRoles();
   520         model->ensureRoles();
   613 
   629 
   614 //---------------------------------------------------------------------------
   630 //---------------------------------------------------------------------------
   615 
   631 
   616 /*!
   632 /*!
   617     \qmlclass VisualDataModel QDeclarativeVisualDataModel
   633     \qmlclass VisualDataModel QDeclarativeVisualDataModel
       
   634     \ingroup qml-working-with-data
   618     \brief The VisualDataModel encapsulates a model and delegate
   635     \brief The VisualDataModel encapsulates a model and delegate
   619 
   636 
   620     A VisualDataModel encapsulates a model and the delegate that will
   637     A VisualDataModel encapsulates a model and the delegate that will
   621     be instantiated for items in the model.
   638     be instantiated for items in the model.
   622 
   639 
   695         QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
   712         QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
   696                             this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
   713                             this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
   697         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
   714         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
   698                             this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
   715                             this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
   699         QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
   716         QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
       
   717         QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
       
   718         d->m_abstractItemModel = 0;
   700     } else if (d->m_visualItemModel) {
   719     } else if (d->m_visualItemModel) {
   701         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
   720         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
   702                          this, SIGNAL(itemsInserted(int,int)));
   721                          this, SIGNAL(itemsInserted(int,int)));
   703         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
   722         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
   704                          this, SIGNAL(itemsRemoved(int,int)));
   723                          this, SIGNAL(itemsRemoved(int,int)));
   741         QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
   760         QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
   742                             this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
   761                             this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
   743         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
   762         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
   744                             this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
   763                             this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
   745         QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
   764         QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
       
   765         QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
   746         d->m_metaDataCacheable = true;
   766         d->m_metaDataCacheable = true;
   747         return;
   767         return;
   748     }
   768     }
   749     if ((d->m_visualItemModel = qvariant_cast<QDeclarativeVisualDataModel *>(model))) {
   769     if ((d->m_visualItemModel = qvariant_cast<QDeclarativeVisualDataModel *>(model))) {
   750         QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
   770         QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
   946         // Remove any bindings to avoid warnings due to parent change.
   966         // Remove any bindings to avoid warnings due to parent change.
   947         QObjectPrivate *p = QObjectPrivate::get(obj);
   967         QObjectPrivate *p = QObjectPrivate::get(obj);
   948         Q_ASSERT(p->declarativeData);
   968         Q_ASSERT(p->declarativeData);
   949         QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
   969         QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
   950         if (d->ownContext && d->context)
   970         if (d->ownContext && d->context)
   951             d->context->clearExpressions();
   971             d->context->clearContext();
   952 
   972 
   953         if (inPackage) {
   973         if (inPackage) {
   954             emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
   974             emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
   955         } else {
   975         } else {
   956             if (item->scene())
   976             if (item->scene())
  1134         delete data;
  1154         delete data;
  1135 
  1155 
  1136     return val;
  1156     return val;
  1137 }
  1157 }
  1138 
  1158 
  1139 QVariant QDeclarativeVisualDataModel::evaluate(int index, const QString &expression, QObject *objectContext)
       
  1140 {
       
  1141     Q_D(QDeclarativeVisualDataModel);
       
  1142     if (d->m_visualItemModel)
       
  1143         return d->m_visualItemModel->evaluate(index, expression, objectContext);
       
  1144 
       
  1145     if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
       
  1146         return QVariant();
       
  1147 
       
  1148     QVariant value;
       
  1149     QObject *nobj = d->m_cache.item(index);
       
  1150     if (nobj) {
       
  1151         QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj);
       
  1152         if (item) {
       
  1153             QDeclarativeExpression e(qmlContext(item), objectContext, expression);
       
  1154             value = e.evaluate();
       
  1155         }
       
  1156     } else {
       
  1157         QDeclarativeContext *ccontext = d->m_context;
       
  1158         if (!ccontext) ccontext = qmlContext(this);
       
  1159         QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
       
  1160         QDeclarativeVisualDataModelData *data = new QDeclarativeVisualDataModelData(index, this);
       
  1161         ctxt->setContextObject(data);
       
  1162         QDeclarativeExpression e(ctxt, objectContext, expression);
       
  1163         value = e.evaluate();
       
  1164         delete data;
       
  1165         delete ctxt;
       
  1166     }
       
  1167 
       
  1168     return value;
       
  1169 }
       
  1170 
       
  1171 int QDeclarativeVisualDataModel::indexOf(QDeclarativeItem *item, QObject *) const
  1159 int QDeclarativeVisualDataModel::indexOf(QDeclarativeItem *item, QObject *) const
  1172 {
  1160 {
  1173     QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
  1161     QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
  1174         return val.toInt();
  1162         return val.toInt();
  1175     return -1;
  1163     return -1;
  1188             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
  1176             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
  1189             for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
  1177             for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
  1190                 int role = roles.at(roleIdx);
  1178                 int role = roles.at(roleIdx);
  1191                 int propId = data->propForRole(role);
  1179                 int propId = data->propForRole(role);
  1192                 if (propId != -1) {
  1180                 if (propId != -1) {
  1193                     if (d->m_listModelInterface) {
  1181                     if (data->hasValue(propId)) {
  1194                         data->setValue(propId, d->m_listModelInterface->data(idx, QList<int>() << role).value(role));
  1182                         if (d->m_listModelInterface) {
  1195                     } else if (d->m_abstractItemModel) {
  1183                             data->setValue(propId, d->m_listModelInterface->data(idx, QList<int>() << role).value(role));
  1196                         QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
  1184                         } else if (d->m_abstractItemModel) {
  1197                         data->setValue(propId, d->m_abstractItemModel->data(index, role));
  1185                             QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
       
  1186                             data->setValue(propId, d->m_abstractItemModel->data(index, role));
       
  1187                         }
  1198                     }
  1188                     }
  1199                 } else {
  1189                 } else {
  1200                     QString roleName;
  1190                     QString roleName;
  1201                     if (d->m_listModelInterface)
  1191                     if (d->m_listModelInterface)
  1202                         roleName = d->m_listModelInterface->toString(role);
  1192                         roleName = d->m_listModelInterface->toString(role);
  1313     emit itemsMoved(from, to, count);
  1303     emit itemsMoved(from, to, count);
  1314 }
  1304 }
  1315 
  1305 
  1316 void QDeclarativeVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
  1306 void QDeclarativeVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
  1317 {
  1307 {
  1318     if (!parent.isValid())
  1308     Q_D(QDeclarativeVisualDataModel);
       
  1309     if (parent == d->m_root)
  1319         _q_itemsInserted(begin, end - begin + 1);
  1310         _q_itemsInserted(begin, end - begin + 1);
  1320 }
  1311 }
  1321 
  1312 
  1322 void QDeclarativeVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
  1313 void QDeclarativeVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
  1323 {
  1314 {
  1324     if (!parent.isValid())
  1315     Q_D(QDeclarativeVisualDataModel);
       
  1316     if (parent == d->m_root)
  1325         _q_itemsRemoved(begin, end - begin + 1);
  1317         _q_itemsRemoved(begin, end - begin + 1);
  1326 }
  1318 }
  1327 
  1319 
  1328 void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
  1320 void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
  1329 {
  1321 {
       
  1322     Q_D(QDeclarativeVisualDataModel);
  1330     const int count = sourceEnd - sourceStart + 1;
  1323     const int count = sourceEnd - sourceStart + 1;
  1331     if (!destinationParent.isValid() && !sourceParent.isValid()) {
  1324     if (destinationParent == d->m_root && sourceParent == d->m_root) {
  1332         _q_itemsMoved(sourceStart, destinationRow, count);
  1325         _q_itemsMoved(sourceStart, destinationRow, count);
  1333     } else if (!sourceParent.isValid()) {
  1326     } else if (sourceParent == d->m_root) {
  1334         _q_itemsRemoved(sourceStart, count);
  1327         _q_itemsRemoved(sourceStart, count);
  1335     } else if (!destinationParent.isValid()) {
  1328     } else if (destinationParent == d->m_root) {
  1336         _q_itemsInserted(destinationRow, count);
  1329         _q_itemsInserted(destinationRow, count);
  1337     }
  1330     }
  1338 }
  1331 }
  1339 
  1332 
  1340 void QDeclarativeVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
  1333 void QDeclarativeVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
  1341 {
  1334 {
  1342     Q_D(QDeclarativeVisualDataModel);
  1335     Q_D(QDeclarativeVisualDataModel);
  1343     if (!begin.parent().isValid())
  1336     if (begin.parent() == d->m_root)
  1344         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
  1337         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
  1345 }
  1338 }
  1346 
  1339 
       
  1340 void QDeclarativeVisualDataModel::_q_layoutChanged()
       
  1341 {
       
  1342     Q_D(QDeclarativeVisualDataModel);
       
  1343     _q_itemsChanged(0, count(), d->m_roles);
       
  1344 }
       
  1345 
  1347 void QDeclarativeVisualDataModel::_q_modelReset()
  1346 void QDeclarativeVisualDataModel::_q_modelReset()
  1348 {
  1347 {
  1349     emit modelReset();
  1348     emit modelReset();
  1350 }
  1349 }
  1351 
  1350