Salome HOME
Update copyrights 2014.
[modules/gui.git] / src / TreeData / TreeModel.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // Author: Guillaume Boulant (EDF/R&D)
21
22
23 #include <QtGui>
24
25 #include "TreeItem.hxx"
26 #include "TreeModel.hxx"
27
28 TreeModel::TreeModel(const QStringList &headers, QObject *parent)
29   : QAbstractItemModel(parent)
30 {
31   QVector<QVariant> rootData;
32   foreach (QString header, headers)
33     rootData << header;
34
35   // _MEM_ We have to specify a string identifier for each item so
36   // that it could be easily retrieved by its parent. In the case of
37   // the root item, the value of the identifier doesn't matter => we
38   // choose an arbitrary value
39   //QString rootNameId = "rootItem";
40   _rootItem = new TreeItem("rootItem", rootData);
41   _rootItem->associateToModel(this);
42 }
43
44 TreeModel::~TreeModel()
45 {
46   delete _rootItem;
47 }
48
49 TreeItem * TreeModel::getRootItem() {
50   return _rootItem;
51 }
52
53 //
54 // =================================================================
55 // This part of the implementation is the standard interface required
56 // for providing an operational TreeModel. These methods are used by
57 // the TreeView for display purpose. We just have to implement how we
58 // want the items to be displayed in the view.
59 // =================================================================
60 //
61 int TreeModel::columnCount(const QModelIndex & /* parent */) const
62 {
63   return _rootItem->columnCount();
64 }
65
66 /*!
67  * This function is used by the tree model to inform the tree view of
68  * what data used for rendering of the item in the different possible
69  * role (edition, ...).
70  */
71 QVariant TreeModel::data(const QModelIndex &index, int role) const
72 {
73   if (!index.isValid())
74     return QVariant();
75
76   if (role != Qt::DisplayRole && role != Qt::EditRole)
77     return QVariant();
78
79   TreeItem *item = getItem(index);
80
81   return item->data(index.column());
82 }
83
84 Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
85 {
86   if (!index.isValid())
87     return 0;
88
89   return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
90 }
91
92 /*!
93  * This retrieves the item asociated to the specified index.
94  */
95 TreeItem *TreeModel::getItem(const QModelIndex &index) const
96 {
97   // The item associated to an index can be retrieved using the
98   // internalPointer() function on the index object.
99   if (index.isValid()) {
100     TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
101     if (item) return item;
102   }
103   return _rootItem;
104 }
105
106 QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
107                                int role) const
108 {
109   if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
110     return _rootItem->data(section);
111
112   return QVariant();
113 }
114
115 /*!
116  * This retrieves the index of the item located at (row,column) place
117  * relative to the parent specified by its index.
118  */
119 QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
120 {
121   if (parent.isValid() && parent.column() != 0)
122     return QModelIndex();
123
124   TreeItem *parentItem = getItem(parent);
125
126   TreeItem *childItem = parentItem->child(row);
127   if (childItem)
128     return createIndex(row, column, childItem);
129   else
130     return QModelIndex();
131 }
132
133 QModelIndex TreeModel::parent(const QModelIndex &index) const
134 {
135   if (!index.isValid())
136     return QModelIndex();
137
138   TreeItem *childItem = getItem(index);
139   TreeItem *parentItem = childItem->parent();
140
141   if (parentItem == _rootItem)
142     return QModelIndex();
143
144   return createIndex(parentItem->rowIndex(), 0, parentItem);
145 }
146
147 int TreeModel::rowCount(const QModelIndex &parent) const
148 {
149   TreeItem *parentItem = getItem(parent);
150
151   return parentItem->childCount();
152 }
153
154 bool TreeModel::setData(const QModelIndex &index, const QVariant &value,
155                         int role)
156 {
157   if (role != Qt::EditRole)
158     return false;
159
160   TreeItem *item = getItem(index);
161   bool result = item->setData(index.column(), value);
162
163   if (result)
164     emit dataChanged(index, index);
165
166   return result;
167 }
168
169 bool TreeModel::setHeaderData(int section, Qt::Orientation orientation,
170                               const QVariant &value, int role)
171 {
172   if (role != Qt::EditRole || orientation != Qt::Horizontal)
173     return false;
174
175   bool result = _rootItem->setData(section, value);
176
177   if (result)
178     emit headerDataChanged(orientation, section, section);
179
180   return result;
181 }
182
183
184 //
185 // =================================================================
186 // This part is a specific behavior to get a TreeModel that can
187 // organize itself the tree hierarchy using data provided in a
188 // filesystem-like format:
189 // 
190 // data="a/b/c" ==> creation/filling of the hierarchy a->b->c
191 // The "folder" categories are unique whereas the leaves may exists
192 // in multiple instances.
193 // =================================================================
194 //
195
196 /*
197  * The addData functions run a recurcive filling of the tree model, starting
198  * form the rootItem and descending in the tree using the recurcive
199  * function TreeItem::addData.
200  */
201
202 bool TreeModel::addData(DataObject * dataObject) {
203   QStringList path = QString(dataObject->getPath().c_str()).split(DataObject::pathsep.c_str());
204   return addData(dataObject, path);
205 }
206 bool TreeModel::addData(DataObject * dataObject, const QStringList &path) {
207   TreeItem * rootItem = this->getItem();
208   rootItem->appendChild(dataObject, path);
209   return true;
210 }