File indexing completed on 2024-04-21 03:56:04
0001 /* 0002 SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef DYNAMICTREEMODEL_H 0008 #define DYNAMICTREEMODEL_H 0009 0010 #include <QAbstractItemModel> 0011 0012 #include <QHash> 0013 #include <QList> 0014 0015 #include "indexfinder.h" 0016 0017 #include "proxymodeltestsuite_export.h" 0018 0019 template<typename T> 0020 class QList; 0021 0022 class ModelMoveCommand; 0023 0024 class PROXYMODELTESTSUITE_EXPORT DynamicTreeModel : public QAbstractItemModel 0025 { 0026 Q_OBJECT 0027 public: 0028 enum Roles { 0029 DynamicTreeModelId = Qt::UserRole, 0030 0031 LastRole, 0032 }; 0033 0034 explicit DynamicTreeModel(QObject *parent = nullptr); 0035 0036 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 0037 QModelIndex parent(const QModelIndex &index) const override; 0038 int rowCount(const QModelIndex &index = QModelIndex()) const override; 0039 int columnCount(const QModelIndex &index = QModelIndex()) const override; 0040 0041 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 0042 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; 0043 0044 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; 0045 Qt::ItemFlags flags(const QModelIndex &index) const override; 0046 Qt::DropActions supportedDropActions() const override; 0047 QStringList mimeTypes() const override; 0048 QMimeData *mimeData(const QModelIndexList &indexes) const override; 0049 QModelIndexList match(const QModelIndex &start, 0050 int role, 0051 const QVariant &value, 0052 int hits = 1, 0053 Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const override; 0054 0055 void clear(); 0056 QList<int> indexToPath(const QModelIndex &idx) const; 0057 ModelMoveCommand *getMoveCommand(const QList<int> &srcPath, int startRow, int endRow); 0058 0059 protected Q_SLOTS: 0060 0061 /** 0062 Finds the parent id of the string with id @p searchId. 0063 0064 Returns -1 if not found. 0065 */ 0066 qint64 findParentId(qint64 searchId) const; 0067 0068 private: 0069 QHash<qint64, QString> m_items; 0070 QHash<qint64, QList<QList<qint64>>> m_childItems; 0071 qint64 nextId; 0072 qint64 newId() 0073 { 0074 return nextId++; 0075 } 0076 0077 QModelIndex m_nextParentIndex; 0078 int m_nextRow; 0079 0080 int m_depth; 0081 int maxDepth; 0082 0083 friend class ModelInsertCommand; 0084 friend class ModelInsertWithDescendantsCommand; 0085 friend class ModelRemoveCommand; 0086 friend class ModelDataChangeCommand; 0087 friend class ModelMoveCommand; 0088 friend class ModelMoveLayoutChangeCommand; 0089 friend class ModelResetCommand; 0090 friend class ModelLayoutChangeCommand; 0091 // friend class ModelSortIndexCommand; 0092 friend class ModelSortIndexLayoutChangeCommand; 0093 friend class ModelInsertAndRemoveQueuedCommand; 0094 }; 0095 0096 class PROXYMODELTESTSUITE_EXPORT ModelChangeCommand : public QObject 0097 { 0098 Q_OBJECT 0099 public: 0100 ModelChangeCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0101 0102 ~ModelChangeCommand() override 0103 { 0104 } 0105 0106 void setAncestorRowNumbers(const QList<int> &rowNumbers) 0107 { 0108 m_rowNumbers = rowNumbers; 0109 } 0110 QList<int> srcAncestors() const 0111 { 0112 return m_rowNumbers; 0113 } 0114 0115 QModelIndex findIndex(const QList<int> &rows) const; 0116 0117 void setStartRow(int row) 0118 { 0119 m_startRow = row; 0120 } 0121 0122 void setEndRow(int row) 0123 { 0124 m_endRow = row; 0125 } 0126 0127 void setNumCols(int cols) 0128 { 0129 m_numCols = cols; 0130 } 0131 0132 virtual void doCommand() = 0; 0133 0134 QModelIndex parentIndex() const 0135 { 0136 return findIndex(m_rowNumbers); 0137 } 0138 int startRow() const 0139 { 0140 return m_startRow; 0141 } 0142 int endRow() const 0143 { 0144 return m_endRow; 0145 } 0146 0147 protected: 0148 DynamicTreeModel *m_model; 0149 QList<int> m_rowNumbers; 0150 int m_startRow; 0151 int m_endRow; 0152 int m_numCols; 0153 }; 0154 0155 typedef QList<ModelChangeCommand *> ModelChangeCommandList; 0156 0157 /** 0158 @brief Inserts a sub tree into the dynamictreemodel. 0159 0160 As an alternative to setStartRow and setEndRow, the interpret command may be used. 0161 0162 The interpret command is used to set the structure of the subtree. 0163 0164 For example, 0165 @code 0166 cmd = new ModelInsertCommand(m_model, this); 0167 cmd->interpret( 0168 "- A" 0169 "- B" 0170 "- - C" 0171 "- D" 0172 ); 0173 @endcode 0174 0175 Will emit an insert for 3 rows, the second of which will have a child row. The interpretation 0176 string may be complex as long as it is valid. The text at the end of each row does not need to be consistent. 0177 There is a define DUMPTREE to make this command print the tree it inserts for better readability. 0178 0179 @code 0180 cmd->interpret( 0181 "- A" 0182 "- - B" 0183 "- - C" 0184 "- - - C" 0185 "- - C" 0186 "- - - C" 0187 "- - - C" 0188 "- - C" 0189 "- D" 0190 "- - E" 0191 "- - F" 0192 ); 0193 @endcode 0194 0195 The string is valid if (depth of row (N + 1)) <= ( (depth of row N) + 1). For example, the following is invalid 0196 because the depth of B is 2 and the depth of A is 0. 0197 0198 @code 0199 cmd->interpret( 0200 "- A" 0201 "- - - B" 0202 "- - C" 0203 @endcode 0204 */ 0205 class PROXYMODELTESTSUITE_EXPORT ModelInsertCommand : public ModelChangeCommand 0206 { 0207 Q_OBJECT 0208 0209 struct Token { 0210 enum Type { 0211 Branch, 0212 Leaf, 0213 }; 0214 Type type; 0215 QString content; 0216 }; 0217 0218 public: 0219 explicit ModelInsertCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0220 ~ModelInsertCommand() override 0221 { 0222 } 0223 0224 void interpret(const QString &treeString); 0225 0226 void doCommand() override; 0227 void doInsertTree(const QModelIndex &parent); 0228 0229 protected: 0230 QList<Token> tokenize(const QString &treeString) const; 0231 0232 QList<int> getDepths(const QString &treeString) const; 0233 0234 QString m_treeString; 0235 }; 0236 0237 class PROXYMODELTESTSUITE_EXPORT ModelInsertAndRemoveQueuedCommand : public ModelChangeCommand 0238 { 0239 Q_OBJECT 0240 0241 public: 0242 explicit ModelInsertAndRemoveQueuedCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0243 ~ModelInsertAndRemoveQueuedCommand() override 0244 { 0245 } 0246 0247 void doCommand() override; 0248 0249 Q_SIGNALS: 0250 void beginInsertRows(const QModelIndex &parent, int start, int end); 0251 void endInsertRows(); 0252 void beginRemoveRows(const QModelIndex &parent, int start, int end); 0253 void endRemoveRows(); 0254 0255 protected Q_SLOTS: 0256 void queuedBeginInsertRows(const QModelIndex &parent, int start, int end); 0257 void queuedEndInsertRows(); 0258 void queuedBeginRemoveRows(const QModelIndex &parent, int start, int end); 0259 void queuedEndRemoveRows(); 0260 0261 protected: 0262 void purgeItem(qint64 parent); 0263 }; 0264 0265 class PROXYMODELTESTSUITE_EXPORT ModelRemoveCommand : public ModelChangeCommand 0266 { 0267 Q_OBJECT 0268 public: 0269 explicit ModelRemoveCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0270 ~ModelRemoveCommand() override 0271 { 0272 } 0273 0274 void doCommand() override; 0275 0276 void purgeItem(qint64 parent); 0277 }; 0278 0279 class PROXYMODELTESTSUITE_EXPORT ModelDataChangeCommand : public ModelChangeCommand 0280 { 0281 Q_OBJECT 0282 public: 0283 explicit ModelDataChangeCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0284 0285 ~ModelDataChangeCommand() override 0286 { 0287 } 0288 0289 void doCommand() override; 0290 0291 void setStartColumn(int column) 0292 { 0293 m_startColumn = column; 0294 } 0295 0296 protected: 0297 int m_startColumn; 0298 }; 0299 0300 class PROXYMODELTESTSUITE_EXPORT ModelMoveCommand : public ModelChangeCommand 0301 { 0302 Q_OBJECT 0303 public: 0304 explicit ModelMoveCommand(DynamicTreeModel *model, QObject *parent); 0305 0306 ~ModelMoveCommand() override 0307 { 0308 } 0309 0310 virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); 0311 0312 void doCommand() override; 0313 0314 virtual void emitPostSignal(); 0315 0316 void setDestAncestors(const QList<int> &rows) 0317 { 0318 m_destRowNumbers = rows; 0319 } 0320 QList<int> destAncestors() const 0321 { 0322 return m_destRowNumbers; 0323 } 0324 0325 void setDestRow(int row) 0326 { 0327 m_destRow = row; 0328 } 0329 0330 protected: 0331 QList<int> m_destRowNumbers; 0332 int m_destRow; 0333 }; 0334 0335 class PROXYMODELTESTSUITE_EXPORT ModelMoveLayoutChangeCommand : public ModelMoveCommand 0336 { 0337 Q_OBJECT 0338 public: 0339 explicit ModelMoveLayoutChangeCommand(DynamicTreeModel *model, QObject *parent); 0340 ~ModelMoveLayoutChangeCommand() override; 0341 0342 bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) override; 0343 0344 void emitPostSignal() override; 0345 0346 void setEndOfMoveSourceAncestors(const QList<int> &rows) 0347 { 0348 m_endOfMoveSourceAncestors = rows; 0349 } 0350 void setEndOfMoveDestAncestors(const QList<int> &rows) 0351 { 0352 m_endOfMoveDestAncestors = rows; 0353 } 0354 0355 private: 0356 QModelIndexList m_beforeMoveList; 0357 QList<int> m_endOfMoveSourceAncestors; 0358 QList<int> m_endOfMoveDestAncestors; 0359 }; 0360 0361 class PROXYMODELTESTSUITE_EXPORT ModelResetCommand : public ModelChangeCommand 0362 { 0363 Q_OBJECT 0364 public: 0365 ModelResetCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0366 ~ModelResetCommand() override; 0367 0368 void setInitialTree(const QString &treeString); 0369 0370 void doCommand() override; 0371 0372 private: 0373 QString m_treeString; 0374 }; 0375 0376 class PROXYMODELTESTSUITE_EXPORT ModelLayoutChangeCommand : public ModelChangeCommand 0377 { 0378 Q_OBJECT 0379 public: 0380 ModelLayoutChangeCommand(DynamicTreeModel *model, QObject *parent = nullptr); 0381 ~ModelLayoutChangeCommand() override; 0382 0383 struct PersistentChange { 0384 QList<int> oldPath; 0385 QList<int> newPath; 0386 }; 0387 0388 void setPersistentChanges(const QList<PersistentChange> &changes); 0389 0390 void setInitialTree(const QString &treeString); 0391 0392 void doCommand() override; 0393 0394 private: 0395 QString m_treeString; 0396 QList<PersistentChange> m_changes; 0397 }; 0398 0399 #endif