fda1df4de1ca8f924f116559c966291a789ca197
[quassel.git] / src / client / treemodel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-07 by the Quassel IRC Team                         *
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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include "treemodel.h"
22
23 /*****************************************
24  *  Buffer Items stored in the Tree Model
25  *****************************************/
26 TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
27   : QObject(parent),
28     itemData(data),
29     _parentItem(parent),
30     _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled)
31 {
32 }
33
34 TreeItem::TreeItem(TreeItem *parent)
35   : QObject(parent),
36     itemData(QList<QVariant>()),
37     _parentItem(parent),
38     _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled)
39 {
40 }
41
42 TreeItem::~TreeItem() {
43   qDeleteAll(_childItems);
44 }
45
46 uint TreeItem::id() const {
47   return (uint)this;
48 }
49
50 void TreeItem::appendChild(TreeItem *item) {
51   _childItems.append(item);
52   _childHash[item->id()] = item;
53   connect(item, SIGNAL(destroyed()),
54           this, SLOT(childDestroyed()));
55 }
56
57 void TreeItem::removeChild(int row) {
58   if(row >= _childItems.size())
59     return;
60   TreeItem *treeitem = _childItems.value(row);
61   _childItems.removeAt(row);
62   _childHash.remove(_childHash.key(treeitem));
63 }
64
65 TreeItem *TreeItem::child(int row) const {
66   if(row < _childItems.size())
67     return _childItems.value(row);
68   else
69     return 0;
70 }
71
72 TreeItem *TreeItem::childById(const uint &id) const {
73   if(_childHash.contains(id))
74     return _childHash.value(id);
75   else
76     return 0;
77 }
78
79 int TreeItem::childCount() const {
80   return _childItems.count();
81 }
82
83 int TreeItem::row() const {
84   if(_parentItem)
85     return _parentItem->_childItems.indexOf(const_cast<TreeItem*>(this));
86   else
87     return 0;
88 }
89
90 TreeItem *TreeItem::parent() {
91   return _parentItem;
92 }
93
94 int TreeItem::columnCount() const {
95   return itemData.count();
96 }
97
98 QVariant TreeItem::data(int column, int role) const {
99   if(role == Qt::DisplayRole && column < itemData.count())
100     return itemData[column];
101   else
102     return QVariant();
103 }
104
105 Qt::ItemFlags TreeItem::flags() const {
106   return _flags;
107 }
108
109 void TreeItem::setFlags(Qt::ItemFlags flags) {
110   _flags = flags;
111 }
112
113 void TreeItem::childDestroyed() {
114   TreeItem *item = static_cast<TreeItem*>(sender());
115   removeChild(item->row());
116 }
117   
118
119
120 /*****************************************
121  * TreeModel
122  *****************************************/
123 TreeModel::TreeModel(const QList<QVariant> &data, QObject *parent)
124   : QAbstractItemModel(parent)
125 {
126   rootItem = new TreeItem(data, 0);
127 }
128
129 TreeModel::~TreeModel() {
130   delete rootItem;
131 }
132
133 QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const {
134   if(!hasIndex(row, column, parent))
135     return QModelIndex();
136   
137   TreeItem *parentItem;
138   
139   if(!parent.isValid())
140     parentItem = rootItem;
141   else
142     parentItem = static_cast<TreeItem*>(parent.internalPointer());
143   
144   TreeItem *childItem = parentItem->child(row);
145   if(childItem)
146     return createIndex(row, column, childItem);
147   else
148     return QModelIndex();
149 }
150
151 QModelIndex TreeModel::indexById(uint id, const QModelIndex &parent) const {
152   TreeItem *parentItem; 
153   
154   if(!parent.isValid())
155     parentItem = rootItem;
156   else
157     parentItem = static_cast<TreeItem *>(parent.internalPointer());
158   
159   TreeItem *childItem = parentItem->childById(id);
160   if(childItem)
161     return createIndex(childItem->row(), 0, childItem);
162   else
163     return QModelIndex();
164 }
165
166 QModelIndex TreeModel::parent(const QModelIndex &index) const {
167   if(!index.isValid())
168     return QModelIndex();
169   
170   TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
171   TreeItem *parentItem = static_cast<TreeItem*>(childItem->parent());
172   
173   if(parentItem == rootItem)
174     return QModelIndex();
175   
176   return createIndex(parentItem->row(), 0, parentItem);
177 }
178
179 int TreeModel::rowCount(const QModelIndex &parent) const {
180   TreeItem *parentItem;
181   if(!parent.isValid())
182     parentItem = rootItem;
183   else
184     parentItem = static_cast<TreeItem*>(parent.internalPointer());
185   
186   return parentItem->childCount();
187 }
188
189 int TreeModel::columnCount(const QModelIndex &parent) const {
190   if(parent.isValid())
191     return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
192   else
193     return rootItem->columnCount();
194 }
195
196 QVariant TreeModel::data(const QModelIndex &index, int role) const {
197   if(!index.isValid())
198     return QVariant();
199
200   TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
201   return item->data(index.column(), role);
202 }
203
204 Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const {
205   TreeItem *item;
206   if(!index.isValid())
207     item = rootItem;
208   else
209     item = static_cast<TreeItem *>(index.internalPointer());
210   return item->flags();
211 }
212
213 QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
214   if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
215     return rootItem->data(section, role);
216   else
217     return QVariant();
218 }
219
220 bool TreeModel::removeRow(int row, const QModelIndex &parent) {
221   if(row > rowCount(parent))
222     return false;
223   
224   TreeItem *item;
225   if(!parent.isValid())
226     item = rootItem;
227   else
228     item = static_cast<TreeItem*>(parent.internalPointer());
229   
230   beginRemoveRows(parent, row, row);
231   item->removeChild(row);
232   endRemoveRows();
233   return true;
234 }
235
236 bool TreeModel::removeRows(int row, int count, const QModelIndex &parent) {
237   // check if there is work to be done
238   if(count == 0)
239     return true;
240
241   // out of range check
242   if(row + count - 1 > rowCount(parent) || row < 0 || count < 0) 
243     return false;
244   
245   TreeItem *item;
246   if(!parent.isValid())
247     item = rootItem;
248   else
249     item = static_cast<TreeItem*>(parent.internalPointer());
250   
251   
252   beginRemoveRows(parent, row, row + count - 1);
253
254   for(int i = row + count - 1; i >= 0; i--) {
255     item->removeChild(i);
256   }
257   endRemoveRows();
258   return true;
259 }
260
261 void TreeModel::clear() {
262   removeRows(0, rowCount());
263   reset();
264 }