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); |
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(); |
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 |