1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // Author: Guillaume Boulant (EDF/R&D)
23 #include <QStringList>
24 #include "TreeItem.hxx"
26 TreeItem::TreeItem(const QString &nameId,
27 const QVector<QVariant> &columnValues,
30 this->initialize(nameId, columnValues, parent);
34 * This initializes the tree item. Called by the constructors.
36 void TreeItem::initialize(const QString &nameId,
37 const QVector<QVariant> &columnValues,
40 _itemData = columnValues;
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());
55 qDeleteAll(_childItems);
56 qDeleteAll(_childItemsMapById);
57 qDeleteAll(_childItemsMapByLabel);
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
68 void TreeItem::associateToModel(TreeModel * model) {
69 _associatedModel = model;
72 TreeModel * TreeItem::associatedModel() {
73 return _associatedModel;
77 * This provide an identifier for this item
79 QString TreeItem::nameId() {
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).
92 void TreeItem::appendChild(DataObject * dataObject,
93 const QStringList &relativePath) {
94 // Definition of the nameId
95 QString nameId = QString(dataObject->getNameId().c_str());
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
102 // Append the item at the specified location with the specified values:
103 this->appendChild(nameId, columnValues, relativePath);
106 void TreeItem::appendChild(const QString &nameId,
107 const QVector<QVariant> &columnValues,
108 const QStringList &relativePath) {
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);
117 // The child is embedded in a sub-folder (to be created if doesn't
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
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);
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];
138 folder->appendChild(nameId, columnValues, nextRelativePath);
142 * This appends the specified child to this item. This item is the
143 * direct parent of the specified child.
145 void TreeItem::appendChild(TreeItem *item)
147 TreeModel * model = this->associatedModel();
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();
158 * This removes the specified child to this item. This item is the
159 * direct parent of the specified child.
161 void TreeItem::removeChild(TreeItem *item)
163 TreeModel * model = this->associatedModel();
165 int position = this->childCount();
166 model->beginRemoveRows(this->modelIndex(), position, position);
167 _childItems.removeOne(item);
168 _childItemsMapById.remove(item->nameId());
169 _childItemsMapByLabel.remove(item->data(0).toString());
170 model->endRemoveRows();
173 void TreeItem::removeChild(DataObject * dataObject, const QStringList &relativePath) {
174 if ( relativePath.isEmpty() ) {
175 // It is a direct child => just remove it.
176 QString nameId = QString(dataObject->getNameId().c_str());
177 TreeItem * child = this->childById(nameId);
179 this->removeChild(child);
183 // The child is embedded in a sub-folder.
184 // We first check if the sub-folder already exist:
185 TreeItem * folder = this->childByLabel(relativePath[0]);
186 if ( folder == NULL )
189 // Go down into subfolder, if any.
190 QStringList nextRelativePath;
191 for (int i = 1; i < relativePath.size(); ++i)
192 nextRelativePath << relativePath[i];
194 folder->removeChild(dataObject, nextRelativePath);
196 if (folder->childCount() == 0)
197 this->removeChild(folder);
201 * The child() function returns the child that corresponds to the
202 * specified row number in the item's list of child items.
204 TreeItem *TreeItem::child(int row)
206 return _childItems.value(row);
209 TreeItem *TreeItem::childById(const QString &nameId)
211 QMap <QString, TreeItem*>::iterator it;
212 it = _childItemsMapById.find ( nameId );
214 if ( it != _childItemsMapById.end() ) {
220 TreeItem *TreeItem::childByLabel(const QString &label)
222 QMap <QString, TreeItem*>::iterator it;
223 it = _childItemsMapByLabel.find ( label );
225 if ( it != _childItemsMapByLabel.end() ) {
233 int TreeItem::childCount() const
235 return _childItems.count();
239 * The rowIndex() function reports the item's location within its
240 * parent's list of items.
242 int TreeItem::rowIndex() const
245 return _parentItem->_childItems.indexOf(const_cast<TreeItem*>(this));
250 int TreeItem::columnCount() const
252 return _itemData.count();
255 QVariant TreeItem::data(int column) const
257 return _itemData.value(column);
260 TreeItem *TreeItem::parent()
265 bool TreeItem::setData(int column, const QVariant &value)
267 if (column < 0 || column >= _itemData.size())
270 _itemData[column] = value;
274 QModelIndex TreeItem::modelIndex(int column)
276 TreeModel * model = this->associatedModel();
277 if (_parentItem && (_parentItem != model->getRootItem()))
278 return model->index(rowIndex(),
280 _parentItem->modelIndex());
282 return model->index(rowIndex(),