#include "QmlObjectVectorModel.h" #include #include const int QmlObjectVectorModel::ObjectRole = Qt::UserRole; const int QmlObjectVectorModel::TextRole = Qt::UserRole + 1; QmlObjectVectorModel::QmlObjectVectorModel(QObject* parent) : QAbstractListModel(parent) , _dirty(false) , _skipDirtyFirstItem(false) { } int QmlObjectVectorModel::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent); return _objectList.count(); } QVariant QmlObjectVectorModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() < 0 || index.row() >= _objectList.count()) { return QVariant(); } if (role == ObjectRole) { return QVariant::fromValue(_objectList[index.row()]); } else if (role == TextRole) { return QVariant::fromValue(_objectList[index.row()]->objectName()); } else { return QVariant(); } } QHash QmlObjectVectorModel::roleNames(void) const { QHash hash; hash[ObjectRole] = "object"; hash[TextRole] = "text"; return hash; } bool QmlObjectVectorModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (index.isValid() && role == ObjectRole) { _objectList.replace(index.row(), value.value()); emit dataChanged(index, index); return true; } return false; } bool QmlObjectVectorModel::insertRows(int position, int rows, const QModelIndex& parent) { Q_UNUSED(parent); if (position < 0 || position > _objectList.count() + 1) { qWarning() << "Invalid position position:count" << position << _objectList.count(); } beginInsertRows(QModelIndex(), position, position + rows - 1); endInsertRows(); emit countChanged(count()); return true; } bool QmlObjectVectorModel::removeRows(int position, int rows, const QModelIndex& parent) { Q_UNUSED(parent); if (position < 0 || position >= _objectList.count()) { qWarning() << "Invalid position position:count" << position << _objectList.count(); } else if (position + rows > _objectList.count()) { qWarning() << "Invalid rows position:rows:count" << position << rows << _objectList.count(); } beginRemoveRows(QModelIndex(), position, position + rows - 1); for (int row=0; row= _objectList.count()) { return NULL; } return _objectList[index]; } const QObject* QmlObjectVectorModel::operator[](int index) const { if (index < 0 || index >= _objectList.count()) { return NULL; } return _objectList[index]; } void QmlObjectVectorModel::clear() { while (rowCount()) { removeAt(0); } } QObject* QmlObjectVectorModel::removeAt(int i) { QObject* removedObject = _objectList[i]; if(removedObject) { // Look for a dirtyChanged signal on the object if (_objectList[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) { if (!_skipDirtyFirstItem || i != 0) { QObject::disconnect(_objectList[i], SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool))); } } } removeRows(i, 1); setDirty(true); return removedObject; } void QmlObjectVectorModel::insert(int i, QObject* object) { if (i < 0 || i > _objectList.count()) { qWarning() << "Invalid index index:count" << i << _objectList.count(); } QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); // Look for a dirtyChanged signal on the object if (object->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) { if (!_skipDirtyFirstItem || i != 0) { QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool))); } } _objectList.insert(i, object); insertRows(i, 1); setDirty(true); } void QmlObjectVectorModel::insert(int i, QVector objects) { if (i < 0 || i > _objectList.count()) { qWarning() << "Invalid index index:count" << i << _objectList.count(); } int j = i; for (QObject* object: objects) { QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); // Look for a dirtyChanged signal on the object if (object->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) { if (!_skipDirtyFirstItem || j != 0) { QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool))); } } j++; _objectList.insert(j, object); } insertRows(i, objects.count()); setDirty(true); } void QmlObjectVectorModel::append(QObject* object) { insert(_objectList.count(), object); } void QmlObjectVectorModel::append(QVector objects) { insert(_objectList.count(), objects); } QVector QmlObjectVectorModel::swapObjectList(const QVector& newlist) { QVector oldlist(_objectList); beginResetModel(); _objectList = newlist; endResetModel(); emit countChanged(count()); return oldlist; } int QmlObjectVectorModel::count() const { return rowCount(); } void QmlObjectVectorModel::setDirty(bool dirty) { if (_dirty != dirty) { _dirty = dirty; if (!dirty) { // Need to clear dirty from all children for(QObject* object: _objectList) { if (object->property("dirty").isValid()) { object->setProperty("dirty", false); } } } emit dirtyChanged(_dirty); } } void QmlObjectVectorModel::_childDirtyChanged(bool dirty) { _dirty |= dirty; // We want to emit dirtyChanged even if the actual value of _dirty didn't change. It can be a useful // signal to know when a child has changed dirty state emit dirtyChanged(_dirty); } void QmlObjectVectorModel::deleteListAndContents() { for (int i=0; i<_objectList.count(); i++) { _objectList[i]->deleteLater(); } deleteLater(); } void QmlObjectVectorModel::clearAndDeleteContents() { beginResetModel(); for (int i=0; i<_objectList.count(); i++) { _objectList[i]->deleteLater(); } clear(); endResetModel(); } void swap(QmlObjectVectorModel &list1, QmlObjectVectorModel &list2) { using std::swap; swap(list1._objectList, list2._objectList); swap(list1._dirty, list2._dirty); swap(list1._skipDirtyFirstItem, list2._skipDirtyFirstItem); }