test: Add build system support and a main function for unit tests
[quassel.git] / src / client / treemodel.h
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 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 <QList>
26 #include <QStringList>
27 #include <QVariant>
28 #include <QAbstractItemModel>
29
30 #include <QLinkedList> // needed for debug
31
32 /*****************************************
33  *  general item used in the Tree Model
34  *****************************************/
35 class CLIENT_EXPORT AbstractTreeItem : public QObject
36 {
37     Q_OBJECT
38
39 public:
40     enum TreeItemFlag {
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);
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
66     virtual inline Qt::ItemFlags flags() const { return _flags; }
67     virtual inline void setFlags(Qt::ItemFlags flags) { _flags = flags; }
68
69     inline AbstractTreeItem::TreeItemFlags treeItemFlags() const { return _treeItemFlags; }
70     inline void setTreeItemFlags(AbstractTreeItem::TreeItemFlags flags) { _treeItemFlags = flags; }
71     int row() const;
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);
94     inline void checkForDeletion()
95     {
96         if (treeItemFlags() & DeleteOnLastChildRemoved && childCount() == 0) parent()->removeChildLater(this);
97     }
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 /*****************************************
122  * PropertyMapItem
123  *****************************************/
124 class CLIENT_EXPORT PropertyMapItem : public AbstractTreeItem
125 {
126     Q_OBJECT
127
128 public:
129     PropertyMapItem(AbstractTreeItem *parent = nullptr);
130
131     virtual QStringList propertyOrder() const = 0;
132
133     QVariant data(int column, int role) const override;
134     bool setData(int column, const QVariant &value, int role) override;
135
136     virtual QString toolTip(int column) const { Q_UNUSED(column) return QString(); }
137     int columnCount() const override;
138 };
139
140
141 /*****************************************
142  * TreeModel
143  *****************************************/
144 class CLIENT_EXPORT TreeModel : public QAbstractItemModel
145 {
146     Q_OBJECT
147
148 public:
149     enum myRoles {
150         SortRole = Qt::UserRole,
151         UserRole
152     };
153
154     TreeModel(const QList<QVariant> &, QObject *parent = nullptr);
155     ~TreeModel() override;
156
157     AbstractTreeItem *root() const;
158
159     QVariant data(const QModelIndex &index, int role) const override;
160     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
161
162     Qt::ItemFlags flags(const QModelIndex &index) const override;
163     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
164
165     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
166     QModelIndex indexByItem(AbstractTreeItem *item) const;
167
168     QModelIndex parent(const QModelIndex &index) const override;
169
170     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
171     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
172
173     virtual void clear();
174
175 private slots:
176     void itemDataChanged(int column = -1);
177
178     void beginAppendChilds(int firstRow, int lastRow);
179     void endAppendChilds();
180
181     void beginRemoveChilds(int firstRow, int lastRow);
182     void endRemoveChilds();
183
184 protected:
185     AbstractTreeItem *rootItem;
186
187 private:
188     void connectItem(AbstractTreeItem *item);
189
190     struct ChildStatus {
191         QModelIndex parent;
192         int childCount;
193         int start;
194         int end;
195         inline ChildStatus(QModelIndex parent_, int cc_, int s_, int e_) : parent(parent_), childCount(cc_), start(s_), end(e_) {};
196     };
197     ChildStatus _childStatus;
198     int _aboutToRemoveOrInsert;
199
200 private slots:
201     void debug_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
202     void debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
203     void debug_rowsInserted(const QModelIndex &parent, int start, int end);
204     void debug_rowsRemoved(const QModelIndex &parent, int start, int end);
205     void debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
206 };