1 /* 2 * SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 5 */ 6 7 #pragma once 8 9 #include <QAbstractProxyModel> 10 #include <QSharedPointer> 11 #include <QVector> 12 13 /** 14 * A model that can hold an extra set of nodes which can "adopt" (reparent), 15 * source nodes. 16 */ 17 class ReparentingModel : public QAbstractProxyModel 18 { 19 Q_OBJECT 20 public: 21 struct Node { 22 using Ptr = QSharedPointer<Node>; 23 virtual ~Node(); 24 virtual bool operator==(const Node &) const; 25 26 protected: 27 Node(ReparentingModel &personModel); 28 29 private: 30 friend class ReparentingModel; 31 Node(ReparentingModel &personModel, Node *parent, const QModelIndex &sourceIndex); 32 virtual QVariant data(int role) const; 33 virtual bool setData(const QVariant &variant, int role); 34 virtual bool adopts(const QModelIndex &sourceIndex); 35 virtual bool isDuplicateOf(const QModelIndex &sourceIndex); 36 virtual void update(const Node::Ptr &node); 37 38 bool isSourceNode() const; 39 Node::Ptr searchNode(Node *node); 40 void reparent(Node *node); 41 void addChild(const Node::Ptr &node); 42 int row() const; 43 void clearHierarchy(); 44 45 QPersistentModelIndex sourceIndex; 46 QVector<Ptr> children; 47 Node *parent = nullptr; 48 ReparentingModel &personModel; 49 const bool mIsSourceNode = false; 50 }; 51 52 struct NodeManager { 53 using Ptr = QSharedPointer<NodeManager>; 54 NodeManagerNodeManager55 NodeManager(ReparentingModel &m) 56 : model(m) 57 { 58 } 59 ~NodeManagerNodeManager60 virtual ~NodeManager() 61 { 62 } 63 64 protected: 65 ReparentingModel &model; 66 67 private: 68 friend class ReparentingModel; 69 70 // Allows the implementation to create proxy nodes as necessary checkSourceIndexNodeManager71 virtual void checkSourceIndex(const QModelIndex & /* sourceIndex */) 72 { 73 } 74 checkSourceIndexRemovalNodeManager75 virtual void checkSourceIndexRemoval(const QModelIndex & /* sourceIndex */) 76 { 77 } 78 updateSourceIndexNodeManager79 virtual void updateSourceIndex(const QModelIndex &sourceIndex) 80 { 81 checkSourceIndex(sourceIndex); 82 } 83 }; 84 85 public: 86 explicit ReparentingModel(QObject *parent = nullptr); 87 ~ReparentingModel() override; 88 89 void setNodeManager(const NodeManager::Ptr &nodeManager); 90 void addNode(const Node::Ptr &node); 91 void updateNode(const Node::Ptr &node); 92 void removeNode(const Node &node); 93 void setNodes(const QList<Node::Ptr> &nodes); 94 void clear(); 95 96 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 97 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 98 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 99 QModelIndex parent(const QModelIndex &child) const override; 100 QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const override; 101 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; 102 Qt::ItemFlags flags(const QModelIndex &index) const override; 103 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; 104 QModelIndex buddy(const QModelIndex &index) const override; 105 106 void setSourceModel(QAbstractItemModel *sourceModel) override; 107 QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; 108 QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; 109 110 private Q_SLOTS: 111 void onSourceRowsAboutToBeInserted(const QModelIndex &, int, int); 112 void onSourceRowsInserted(const QModelIndex &, int, int); 113 void onSourceRowsAboutToBeRemoved(const QModelIndex &, int, int); 114 void onSourceRowsRemoved(const QModelIndex &, int, int); 115 void onSourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int); 116 void onSourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); 117 void onSourceDataChanged(const QModelIndex &, const QModelIndex &); 118 void onSourceLayoutAboutToBeChanged(); 119 void onSourceLayoutChanged(); 120 void onSourceModelAboutToBeReset(); 121 void onSourceModelReset(); 122 void doAddNode(const Node::Ptr &node); 123 124 private: 125 void rebuildFromSource(Node *parentNode, const QModelIndex &idx, const QModelIndexList &skip = QModelIndexList()); 126 bool isDuplicate(const Node::Ptr &proxyNode) const; 127 void insertProxyNode(const Node::Ptr &proxyNode); 128 void reparentSourceNodes(const Node::Ptr &proxyNode); 129 void rebuildAll(); 130 QModelIndex index(Node *node) const; 131 int row(Node *node) const; 132 Node *getReparentNode(const QModelIndex &sourceIndex); 133 Node *getParentNode(const QModelIndex &sourceIndex); 134 bool validateNode(const Node *node) const; 135 Node *extractNode(const QModelIndex &index) const; 136 void appendSourceNode(Node *parentNode, const QModelIndex &sourceIndex, const QModelIndexList &skip = QModelIndexList()); 137 QModelIndexList descendants(const QModelIndex &sourceIndex); 138 void removeDuplicates(const QModelIndex &sourceIndex); 139 Node *getSourceNode(const QModelIndex &sourceIndex) const; 140 141 Node mRootNode; 142 QList<Node *> mSourceNodes; 143 QVector<Node::Ptr> mProxyNodes; 144 QVector<Node::Ptr> mNodesToAdd; 145 NodeManager::Ptr mNodeManager; 146 }; 147 148