File indexing completed on 2024-05-19 05:34:38

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
0003     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies) <qt-info@nokia.com>
0004 
0005     This file is part of the test suite of the Qt Toolkit.
0006 
0007     SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1
0008 */
0009 
0010 #include "dynamictreemodel.h"
0011 
0012 #include <QTimer>
0013 
0014 DynamicTreeModel::DynamicTreeModel(QObject *parent)
0015     : QAbstractItemModel(parent)
0016     , nextId(1)
0017 {
0018 }
0019 
0020 QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const
0021 {
0022     //   if (column != 0)
0023     //     return QModelIndex();
0024 
0025     if (column < 0 || row < 0) {
0026         return QModelIndex();
0027     }
0028 
0029     QList<QList<qint64>> childIdColumns = m_childItems.value(parent.internalId());
0030 
0031     const qint64 grandParent = findParentId(parent.internalId());
0032     if (grandParent >= 0) {
0033         QList<QList<qint64>> parentTable = m_childItems.value(grandParent);
0034         Q_ASSERT(parent.column() < parentTable.size());
0035         QList<qint64> parentSiblings = parentTable.at(parent.column());
0036         Q_ASSERT(parent.row() < parentSiblings.size());
0037     }
0038 
0039     if (childIdColumns.size() == 0) {
0040         return QModelIndex();
0041     }
0042 
0043     if (column >= childIdColumns.size()) {
0044         return QModelIndex();
0045     }
0046 
0047     QList<qint64> rowIds = childIdColumns.at(column);
0048 
0049     if (row >= rowIds.size()) {
0050         return QModelIndex();
0051     }
0052 
0053     qint64 id = rowIds.at(row);
0054 
0055     return createIndex(row, column, reinterpret_cast<void *>(id));
0056 }
0057 
0058 qint64 DynamicTreeModel::findParentId(qint64 searchId) const
0059 {
0060     if (searchId <= 0) {
0061         return -1;
0062     }
0063 
0064     QHashIterator<qint64, QList<QList<qint64>>> i(m_childItems);
0065     while (i.hasNext()) {
0066         i.next();
0067         QListIterator<QList<qint64>> j(i.value());
0068         while (j.hasNext()) {
0069             QList<qint64> l = j.next();
0070             if (l.contains(searchId)) {
0071                 return i.key();
0072             }
0073         }
0074     }
0075     return -1;
0076 }
0077 
0078 QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const
0079 {
0080     if (!index.isValid()) {
0081         return QModelIndex();
0082     }
0083 
0084     qint64 searchId = index.internalId();
0085     qint64 parentId = findParentId(searchId);
0086     // Will never happen for valid index, but what the hey...
0087     if (parentId <= 0) {
0088         return QModelIndex();
0089     }
0090 
0091     qint64 grandParentId = findParentId(parentId);
0092     if (grandParentId < 0) {
0093         grandParentId = 0;
0094     }
0095 
0096     int column = 0;
0097     QList<qint64> childList = m_childItems.value(grandParentId).at(column);
0098 
0099     int row = childList.indexOf(parentId);
0100 
0101     return createIndex(row, column, reinterpret_cast<void *>(parentId));
0102 }
0103 
0104 int DynamicTreeModel::rowCount(const QModelIndex &index) const
0105 {
0106     QList<QList<qint64>> cols = m_childItems.value(index.internalId());
0107 
0108     if (cols.size() == 0) {
0109         return 0;
0110     }
0111 
0112     if (index.column() > 0) {
0113         return 0;
0114     }
0115 
0116     return cols.at(0).size();
0117 }
0118 
0119 int DynamicTreeModel::columnCount(const QModelIndex &index) const
0120 {
0121     //   Q_UNUSED(index);
0122     return m_childItems.value(index.internalId()).size();
0123 }
0124 
0125 QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const
0126 {
0127     if (!index.isValid()) {
0128         return QVariant();
0129     }
0130 
0131     if (Qt::DisplayRole == role) {
0132         return m_items.value(index.internalId());
0133     }
0134     return QVariant();
0135 }
0136 
0137 void DynamicTreeModel::clear()
0138 {
0139     beginResetModel();
0140     m_items.clear();
0141     m_childItems.clear();
0142     nextId = 1;
0143     endResetModel();
0144 }
0145 
0146 ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent)
0147     : QObject(parent)
0148     , m_model(model)
0149     , m_numCols(1)
0150     , m_startRow(-1)
0151     , m_endRow(-1)
0152 {
0153 }
0154 
0155 QModelIndex ModelChangeCommand::findIndex(QList<int> rows)
0156 {
0157     const int col = 0;
0158     QModelIndex parent = QModelIndex();
0159     QListIterator<int> i(rows);
0160     while (i.hasNext()) {
0161         parent = m_model->index(i.next(), col, parent);
0162         Q_ASSERT(parent.isValid());
0163     }
0164     return parent;
0165 }
0166 
0167 ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent)
0168     : ModelChangeCommand(model, parent)
0169 {
0170 }
0171 
0172 void ModelInsertCommand::doCommand()
0173 {
0174     QModelIndex parent = findIndex(m_rowNumbers);
0175     m_model->beginInsertRows(parent, m_startRow, m_endRow);
0176     qint64 parentId = parent.internalId();
0177     for (int row = m_startRow; row <= m_endRow; row++) {
0178         for (int col = 0; col < m_numCols; col++) {
0179             if (m_model->m_childItems[parentId].size() <= col) {
0180                 m_model->m_childItems[parentId].append(QList<qint64>());
0181             }
0182             //       QString name = QUuid::createUuid().toString();
0183             qint64 id = m_model->newId();
0184             QString name = QString::number(id);
0185 
0186             m_model->m_items.insert(id, name);
0187             m_model->m_childItems[parentId][col].insert(row, id);
0188         }
0189     }
0190     m_model->endInsertRows();
0191 }
0192 
0193 ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent)
0194     : ModelChangeCommand(model, parent)
0195 {
0196 }
0197 bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
0198 {
0199     return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow);
0200 }
0201 
0202 void ModelMoveCommand::doCommand()
0203 {
0204     QModelIndex srcParent = findIndex(m_rowNumbers);
0205     QModelIndex destParent = findIndex(m_destRowNumbers);
0206 
0207     if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow)) {
0208         return;
0209     }
0210 
0211     for (int column = 0; column < m_numCols; ++column) {
0212         const QList<qint64> lst = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1);
0213 
0214         for (int i = m_startRow; i <= m_endRow; i++) {
0215             m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow);
0216         }
0217         int d;
0218         if (m_destRow < m_startRow) {
0219             d = m_destRow;
0220         } else {
0221             if (srcParent == destParent) {
0222                 d = m_destRow - (m_endRow - m_startRow + 1);
0223             } else {
0224                 d = m_destRow - (m_endRow - m_startRow) + 1;
0225             }
0226         }
0227 
0228         for (const qint64 id : lst) {
0229             m_model->m_childItems[destParent.internalId()][column].insert(d++, id);
0230         }
0231     }
0232 
0233     emitPostSignal();
0234 }
0235 
0236 void ModelMoveCommand::emitPostSignal()
0237 {
0238     m_model->endMoveRows();
0239 }
0240 
0241 ModelResetCommand::ModelResetCommand(DynamicTreeModel *model, QObject *parent)
0242     : ModelMoveCommand(model, parent)
0243 {
0244 }
0245 
0246 ModelResetCommand::~ModelResetCommand()
0247 {
0248 }
0249 
0250 bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
0251 {
0252     Q_UNUSED(srcParent);
0253     Q_UNUSED(srcStart);
0254     Q_UNUSED(srcEnd);
0255     Q_UNUSED(destParent);
0256     Q_UNUSED(destRow);
0257 
0258     return true;
0259 }
0260 
0261 void ModelResetCommand::emitPostSignal()
0262 {
0263     m_model->reset();
0264 }
0265 
0266 ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent)
0267     : ModelMoveCommand(model, parent)
0268 {
0269 }
0270 
0271 ModelResetCommandFixed::~ModelResetCommandFixed()
0272 {
0273 }
0274 
0275 bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
0276 {
0277     Q_UNUSED(srcParent);
0278     Q_UNUSED(srcStart);
0279     Q_UNUSED(srcEnd);
0280     Q_UNUSED(destParent);
0281     Q_UNUSED(destRow);
0282 
0283     m_model->beginResetModel();
0284     return true;
0285 }
0286 
0287 void ModelResetCommandFixed::emitPostSignal()
0288 {
0289     m_model->endResetModel();
0290 }
0291 
0292 #include "moc_dynamictreemodel.cpp"