/* SPDX-FileCopyrightText: 2009 Stephen Kelly SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies) This file is part of the test suite of the Qt Toolkit. SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1 */ #include "dynamictreemodel.h" #include DynamicTreeModel::DynamicTreeModel(QObject *parent) : QAbstractItemModel(parent) , nextId(1) { } QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const { // if (column != 0) // return QModelIndex(); if (column < 0 || row < 0) { return QModelIndex(); } QList> childIdColumns = m_childItems.value(parent.internalId()); const qint64 grandParent = findParentId(parent.internalId()); if (grandParent >= 0) { QList> parentTable = m_childItems.value(grandParent); Q_ASSERT(parent.column() < parentTable.size()); QList parentSiblings = parentTable.at(parent.column()); Q_ASSERT(parent.row() < parentSiblings.size()); } if (childIdColumns.size() == 0) { return QModelIndex(); } if (column >= childIdColumns.size()) { return QModelIndex(); } QList rowIds = childIdColumns.at(column); if (row >= rowIds.size()) { return QModelIndex(); } qint64 id = rowIds.at(row); return createIndex(row, column, reinterpret_cast(id)); } qint64 DynamicTreeModel::findParentId(qint64 searchId) const { if (searchId <= 0) { return -1; } QHashIterator>> i(m_childItems); while (i.hasNext()) { i.next(); QListIterator> j(i.value()); while (j.hasNext()) { QList l = j.next(); if (l.contains(searchId)) { return i.key(); } } } return -1; } QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const { if (!index.isValid()) { return QModelIndex(); } qint64 searchId = index.internalId(); qint64 parentId = findParentId(searchId); // Will never happen for valid index, but what the hey... if (parentId <= 0) { return QModelIndex(); } qint64 grandParentId = findParentId(parentId); if (grandParentId < 0) { grandParentId = 0; } int column = 0; QList childList = m_childItems.value(grandParentId).at(column); int row = childList.indexOf(parentId); return createIndex(row, column, reinterpret_cast(parentId)); } int DynamicTreeModel::rowCount(const QModelIndex &index) const { QList> cols = m_childItems.value(index.internalId()); if (cols.size() == 0) { return 0; } if (index.column() > 0) { return 0; } return cols.at(0).size(); } int DynamicTreeModel::columnCount(const QModelIndex &index) const { // Q_UNUSED(index); return m_childItems.value(index.internalId()).size(); } QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (Qt::DisplayRole == role) { return m_items.value(index.internalId()); } return QVariant(); } void DynamicTreeModel::clear() { beginResetModel(); m_items.clear(); m_childItems.clear(); nextId = 1; endResetModel(); } ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent) : QObject(parent) , m_model(model) , m_numCols(1) , m_startRow(-1) , m_endRow(-1) { } QModelIndex ModelChangeCommand::findIndex(QList rows) { const int col = 0; QModelIndex parent = QModelIndex(); QListIterator i(rows); while (i.hasNext()) { parent = m_model->index(i.next(), col, parent); Q_ASSERT(parent.isValid()); } return parent; } ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent) : ModelChangeCommand(model, parent) { } void ModelInsertCommand::doCommand() { QModelIndex parent = findIndex(m_rowNumbers); m_model->beginInsertRows(parent, m_startRow, m_endRow); qint64 parentId = parent.internalId(); for (int row = m_startRow; row <= m_endRow; row++) { for (int col = 0; col < m_numCols; col++) { if (m_model->m_childItems[parentId].size() <= col) { m_model->m_childItems[parentId].append(QList()); } // QString name = QUuid::createUuid().toString(); qint64 id = m_model->newId(); QString name = QString::number(id); m_model->m_items.insert(id, name); m_model->m_childItems[parentId][col].insert(row, id); } } m_model->endInsertRows(); } ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) : ModelChangeCommand(model, parent) { } bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) { return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow); } void ModelMoveCommand::doCommand() { QModelIndex srcParent = findIndex(m_rowNumbers); QModelIndex destParent = findIndex(m_destRowNumbers); if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow)) { return; } for (int column = 0; column < m_numCols; ++column) { const QList lst = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1); for (int i = m_startRow; i <= m_endRow; i++) { m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow); } int d; if (m_destRow < m_startRow) { d = m_destRow; } else { if (srcParent == destParent) { d = m_destRow - (m_endRow - m_startRow + 1); } else { d = m_destRow - (m_endRow - m_startRow) + 1; } } for (const qint64 id : lst) { m_model->m_childItems[destParent.internalId()][column].insert(d++, id); } } emitPostSignal(); } void ModelMoveCommand::emitPostSignal() { m_model->endMoveRows(); } ModelResetCommand::ModelResetCommand(DynamicTreeModel *model, QObject *parent) : ModelMoveCommand(model, parent) { } ModelResetCommand::~ModelResetCommand() { } bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) { Q_UNUSED(srcParent); Q_UNUSED(srcStart); Q_UNUSED(srcEnd); Q_UNUSED(destParent); Q_UNUSED(destRow); return true; } void ModelResetCommand::emitPostSignal() { m_model->reset(); } ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent) : ModelMoveCommand(model, parent) { } ModelResetCommandFixed::~ModelResetCommandFixed() { } bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) { Q_UNUSED(srcParent); Q_UNUSED(srcStart); Q_UNUSED(srcEnd); Q_UNUSED(destParent); Q_UNUSED(destRow); m_model->beginResetModel(); return true; } void ModelResetCommandFixed::emitPostSignal() { m_model->endResetModel(); } #include "moc_dynamictreemodel.cpp"