Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/gui.git] / src / TreeData / TreeItem.cxx
1 // Copyright (C) 2007-2012  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.
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 <QStringList>
24 #include "TreeItem.hxx"
25
26 TreeItem::TreeItem(const QString &nameId,
27                    const QVector<QVariant> &columnValues,
28                    TreeItem *parent)
29 {
30   this->initialize(nameId, columnValues, parent);
31 }
32
33 /*!
34  * This initializes the tree item. Called by the constructors.
35  */
36 void TreeItem::initialize(const QString &nameId,
37                           const QVector<QVariant> &columnValues,
38                           TreeItem *parent) {
39   _itemNameId = nameId;
40   _itemData   = columnValues;
41   _parentItem = parent;
42
43   // An item is associated to the model of its parent. It can't be
44   //done automatically in the case where the item has no parent. Then
45   //the function associatedToModel has to be called explicitely from
46   //within the user code (for exemple at construction of the model,
47   //when creating the root item).
48   if ( parent != NULL ) {
49     this->associateToModel(parent->associatedModel());
50   }  
51 }
52
53 TreeItem::~TreeItem()
54 {
55   qDeleteAll(_childItems);
56   qDeleteAll(_childItemsMapById);
57   qDeleteAll(_childItemsMapByLabel);
58 }
59
60 /*!
61  * This must be used to specified which model this item belongs to. It
62  * is required because the item sometimes requests its model for
63  * global informations about the data tree. In standard usage, this
64  * function is automatically set when the item is instantiated by
65  * requested the parent item. Then only the root item needs a manual
66  * setting.
67  */
68 void TreeItem::associateToModel(TreeModel * model) {
69   _associatedModel = model;
70 }
71
72 TreeModel * TreeItem::associatedModel() {
73   return _associatedModel;
74 }
75
76 /*!
77  * This provide an identifier for this item
78  */
79 QString TreeItem::nameId() {
80   return _itemNameId;
81 }
82
83 /*!
84  * This creates an item from the specified dataObject and put it in
85  * the decendency of this item at the specified relativePath. The
86  * created item could not be a direct child of this item in the case
87  * where the relative path is not null. Note that no reference on the
88  * dataObject is kept in this instance. Only the identifier is used to
89  * set the item identifier, and the properties may be used to set the
90  * values of the item (stored in columns).
91  */
92 void TreeItem::appendChild(DataObject * dataObject,
93                            const QStringList &relativePath) {
94   // Definition of the nameId
95   QString nameId = QString(dataObject->getNameId().c_str());
96
97   // Definition of columns data values
98   QVector<QVariant> columnValues;
99   columnValues << QString(dataObject->getLabel().c_str());
100   columnValues << "No value"; // We could use the dataObject properties
101
102   // Append the item at the specified location with the specified values:
103   this->appendChild(nameId, columnValues, relativePath);
104 }
105
106 void TreeItem::appendChild(const QString &nameId,
107                            const QVector<QVariant> &columnValues,
108                            const QStringList &relativePath) {
109
110   if ( relativePath.isEmpty() ) {
111     // It is a direct child => just create and append to this.
112     TreeItem * child = new TreeItem(nameId, columnValues, this);
113     this->appendChild(child);
114     return;
115   }
116
117   // The child is embedded in a sub-folder (to be created if doesn't
118   // exist).
119   // We first check if the sub-folder already exist:
120   TreeItem * folder = this->childByLabel(relativePath[0]);
121   if ( folder == NULL ) {
122     // The folder does not exist. It must be created before going any
123     // further. By convention we choose the folder name as
124     // identifier.
125     QString folderNameId = relativePath[0];
126     QVector<QVariant> folderColumnValues;
127     folderColumnValues << relativePath[0] << "No value";
128     folder = new TreeItem(folderNameId, folderColumnValues, this);
129     this->appendChild(folder);
130   }
131     
132   // We create the relative path of the next iteration (delete the
133   // first folder path).
134   QStringList nextRelativePath;
135   for (int i = 1; i < relativePath.size(); ++i)
136     nextRelativePath << relativePath[i];
137     
138   folder->appendChild(nameId, columnValues, nextRelativePath);
139 }
140
141 /*!
142  * This appends the specified child to this item. This item is the
143  * direct parent of the specified child.
144  */
145 void TreeItem::appendChild(TreeItem *item)
146 {
147   TreeModel * model = this->associatedModel();
148
149   int position = this->childCount();
150   model->beginInsertRows(this->modelIndex(), position, position);
151   _childItems.append(item);
152   _childItemsMapById[item->nameId()] = item;
153   _childItemsMapByLabel[item->data(0).toString()] = item;
154   model->endInsertRows();
155 }
156
157 /*!
158  * The child() function returns the child that corresponds to the
159  * specified row number in the item's list of child items.
160  */
161 TreeItem *TreeItem::child(int row)
162 {
163   return _childItems.value(row);
164 }
165
166 TreeItem *TreeItem::childById(const QString &nameId)
167 {
168   QMap <QString, TreeItem*>::iterator it;
169   it = _childItemsMapById.find ( nameId );
170
171   if ( it != _childItemsMapById.end() ) {
172     return it.value();
173   }
174   return NULL;
175 }
176
177 TreeItem *TreeItem::childByLabel(const QString &label)
178 {
179   QMap <QString, TreeItem*>::iterator it;
180   it = _childItemsMapByLabel.find ( label );
181
182   if ( it != _childItemsMapByLabel.end() ) {
183     return it.value();
184   }
185   return NULL;
186 }
187
188
189
190 int TreeItem::childCount() const
191 {
192   return _childItems.count();
193 }
194
195 /*!
196  * The rowIndex() function reports the item's location within its
197  * parent's list of items.
198  */
199 int TreeItem::rowIndex() const
200 {
201   if (_parentItem)
202     return _parentItem->_childItems.indexOf(const_cast<TreeItem*>(this));
203
204   return 0;
205 }
206
207 int TreeItem::columnCount() const
208 {
209   return _itemData.count();
210 }
211
212 QVariant TreeItem::data(int column) const
213 {
214   return _itemData.value(column);
215 }
216
217 TreeItem *TreeItem::parent()
218 {
219   return _parentItem;
220 }
221
222 bool TreeItem::setData(int column, const QVariant &value)
223 {
224   if (column < 0 || column >= _itemData.size())
225     return false;
226
227   _itemData[column] = value;
228   return true;
229 }
230
231 QModelIndex TreeItem::modelIndex(int column)
232 {
233   TreeModel * model = this->associatedModel();
234   if (_parentItem && (_parentItem != model->getRootItem()))
235     return model->index(rowIndex(),
236                         column,
237                         _parentItem->modelIndex());
238   else
239     return model->index(rowIndex(),
240                         column,
241                         QModelIndex());
242 }