File indexing completed on 2023-09-24 08:11:57
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"