1 /*************************************************************************** 2 * Copyright (C) 2005-2020 by the Quassel Project * 3 * devel@quassel-irc.org * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) version 3. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 19 ***************************************************************************/ 20 21 #pragma once 22 23 #include "client-export.h" 24 25 #include <QAbstractItemModel> 26 #include <QLinkedList> // needed for debug 27 #include <QList> 28 #include <QStringList> 29 #include <QVariant> 30 31 /***************************************** 32 * general item used in the Tree Model 33 *****************************************/ 34 class CLIENT_EXPORT AbstractTreeItem : public QObject 35 { 36 Q_OBJECT 37 38 public: 39 enum TreeItemFlag 40 { 41 NoTreeItemFlag = 0x00, 42 DeleteOnLastChildRemoved = 0x01 43 }; 44 Q_DECLARE_FLAGS(TreeItemFlags, TreeItemFlag) 45 46 AbstractTreeItem(AbstractTreeItem* parent = nullptr); 47 48 bool newChild(AbstractTreeItem* child); 49 bool newChilds(const QList<AbstractTreeItem*>& items); 50 51 bool removeChild(int row); removeChild(AbstractTreeItem * child)52 inline bool removeChild(AbstractTreeItem* child) { return removeChild(child->row()); } 53 void removeAllChilds(); 54 55 bool reParent(AbstractTreeItem* newParent); 56 57 AbstractTreeItem* child(int row) const; 58 59 int childCount(int column = 0) const; 60 61 virtual int columnCount() const = 0; 62 63 virtual QVariant data(int column, int role) const = 0; 64 virtual bool setData(int column, const QVariant& value, int role) = 0; 65 flags()66 virtual inline Qt::ItemFlags flags() const { return _flags; } setFlags(Qt::ItemFlags flags)67 virtual inline void setFlags(Qt::ItemFlags flags) { _flags = flags; } 68 treeItemFlags()69 inline AbstractTreeItem::TreeItemFlags treeItemFlags() const { return _treeItemFlags; } setTreeItemFlags(AbstractTreeItem::TreeItemFlags flags)70 inline void setTreeItemFlags(AbstractTreeItem::TreeItemFlags flags) { _treeItemFlags = flags; } 71 int row() const; parent()72 inline AbstractTreeItem* parent() const { return qobject_cast<AbstractTreeItem*>(QObject::parent()); } 73 74 void dumpChildList(); 75 76 signals: 77 void dataChanged(int column = -1); 78 79 void beginAppendChilds(int firstRow, int lastRow); 80 void endAppendChilds(); 81 82 void beginRemoveChilds(int firstRow, int lastRow); 83 void endRemoveChilds(); 84 85 protected: 86 void customEvent(QEvent* event) override; 87 88 private: 89 QList<AbstractTreeItem*> _childItems; 90 Qt::ItemFlags _flags{}; 91 TreeItemFlags _treeItemFlags{}; 92 93 void removeChildLater(AbstractTreeItem* child); checkForDeletion()94 inline void checkForDeletion() 95 { 96 if (treeItemFlags() & DeleteOnLastChildRemoved && childCount() == 0) 97 parent()->removeChildLater(this); 98 } 99 }; 100 101 /***************************************** 102 * SimpleTreeItem 103 *****************************************/ 104 class CLIENT_EXPORT SimpleTreeItem : public AbstractTreeItem 105 { 106 Q_OBJECT 107 108 public: 109 SimpleTreeItem(QList<QVariant> data, AbstractTreeItem* parent = nullptr); 110 111 QVariant data(int column, int role) const override; 112 bool setData(int column, const QVariant& value, int role) override; 113 114 int columnCount() const override; 115 116 private: 117 QList<QVariant> _itemData; 118 }; 119 120 /***************************************** 121 * PropertyMapItem 122 *****************************************/ 123 class CLIENT_EXPORT PropertyMapItem : public AbstractTreeItem 124 { 125 Q_OBJECT 126 127 public: 128 PropertyMapItem(AbstractTreeItem* parent = nullptr); 129 130 virtual QStringList propertyOrder() const = 0; 131 132 QVariant data(int column, int role) const override; 133 bool setData(int column, const QVariant& value, int role) override; 134 toolTip(int column)135 virtual QString toolTip(int column) const { Q_UNUSED(column) return QString(); } 136 int columnCount() const override; 137 }; 138 139 /***************************************** 140 * TreeModel 141 *****************************************/ 142 class CLIENT_EXPORT TreeModel : public QAbstractItemModel 143 { 144 Q_OBJECT 145 146 public: 147 enum myRoles 148 { 149 SortRole = Qt::UserRole, 150 UserRole 151 }; 152 153 TreeModel(const QList<QVariant>&, QObject* parent = nullptr); 154 ~TreeModel() override; 155 156 AbstractTreeItem* root() const; 157 158 QVariant data(const QModelIndex& index, int role) const override; 159 bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; 160 161 Qt::ItemFlags flags(const QModelIndex& index) const override; 162 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 163 164 QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; 165 QModelIndex indexByItem(AbstractTreeItem* item) const; 166 167 QModelIndex parent(const QModelIndex& index) const override; 168 169 int rowCount(const QModelIndex& parent = QModelIndex()) const override; 170 int columnCount(const QModelIndex& parent = QModelIndex()) const override; 171 172 virtual void clear(); 173 174 private slots: 175 void itemDataChanged(int column = -1); 176 177 void beginAppendChilds(int firstRow, int lastRow); 178 void endAppendChilds(); 179 180 void beginRemoveChilds(int firstRow, int lastRow); 181 void endRemoveChilds(); 182 183 protected: 184 AbstractTreeItem* rootItem; 185 186 private: 187 void connectItem(AbstractTreeItem* item); 188 189 struct ChildStatus 190 { 191 QModelIndex parent; 192 int childCount; 193 int start; 194 int end; ChildStatusChildStatus195 inline ChildStatus(QModelIndex parent_, int cc_, int s_, int e_) 196 : parent(parent_) 197 , childCount(cc_) 198 , start(s_) 199 , end(e_){}; 200 }; 201 ChildStatus _childStatus; 202 int _aboutToRemoveOrInsert; 203 204 private slots: 205 void debug_rowsAboutToBeInserted(const QModelIndex& parent, int start, int end); 206 void debug_rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); 207 void debug_rowsInserted(const QModelIndex& parent, int start, int end); 208 void debug_rowsRemoved(const QModelIndex& parent, int start, int end); 209 void debug_dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); 210 }; 211