Developer Documentation
TreeModel.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 
52 #include "TreeModel.hh"
53 
54 
56 
57 #if QT_VERSION >= 0x050000
58 #include <QtWidgets>
59 #else
60 #include <QtGui>
61 #endif
62 
63 
64 //******************************************************************************
65 
70 TreeModel::TreeModel( QObject *_parent) : QAbstractItemModel(_parent)
71 {
72  rootItem_ = new TreeItem( -1, "ROOT", DATA_UNKNOWN, 0);
73 }
74 
75 
76 //******************************************************************************
77 
82 {
83 
84 }
85 
86 
87 //******************************************************************************
88 
89 int TreeModel::columnCount(const QModelIndex &/*_parent*/) const
90 {
91  // Id, Name -> 2
92  return (2);
93 }
94 
95 
96 //******************************************************************************
97 
104 QVariant TreeModel::data(const QModelIndex &_index, int _role) const
105 {
106 
107  // Skip invalid requests
108  if (!_index.isValid())
109  return QVariant();
110 
111  // Get the corresponding tree item
112  TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
113 
114  if ( item == rootItem_ ) {
115  std::cerr << "Root" << std::endl;
116  }
117 
118  // Set the background color of the objects row
119  if ( _role == Qt::BackgroundRole ) {
120  if ( !item->visible() ) {
121  return QVariant (QBrush (QColor (192, 192, 192)));
122  }
123  }
124 
125  if (_role == Qt::DisplayRole)
126  {
127  switch (_index.column ())
128  {
129  case 0:
130  return QVariant(item->id());
131  case 1:
132  return QVariant(item->name());
133  default:
134  return QVariant ();
135  }
136  }
137  else
138  return QVariant ();
139 }
140 
141 
142 //******************************************************************************
143 
149 Qt::ItemFlags TreeModel::flags(const QModelIndex &_index) const
150 {
151  if (!_index.isValid())
152  return 0;
153 
154  Qt::ItemFlags flags = 0;
155 
156  // Show/Source/Target
157  if ( _index.column() == 0 || _index.column() == 1 )
158  flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
159  else
160  flags = Qt::ItemIsEnabled;
161 
162  return flags;
163 }
164 
165 
166 //******************************************************************************
167 
175 QVariant TreeModel::headerData(int _section, Qt::Orientation _orientation,
176  int _role) const
177 {
178  if (_orientation == Qt::Horizontal && _role == Qt::DisplayRole) {
179 
180  if (_section == 0)
181  return QVariant("ID");
182  else if (_section == 1)
183  return QVariant("Name");
184  else
185  return QVariant();
186 
187  }
188  return QVariant();
189 }
190 
191 
192 //******************************************************************************
193 
201 QModelIndex TreeModel::index(int _row, int _column, const QModelIndex &_parent) const
202 {
203  TreeItem *parentItem;
204 
205  if (!_parent.isValid())
206  parentItem = rootItem_;
207  else
208  parentItem = static_cast<TreeItem*>(_parent.internalPointer());
209 
210  TreeItem *childItem = parentItem->child(_row);
211  if (childItem)
212  return createIndex(_row, _column, childItem);
213  else
214  return QModelIndex();
215 }
216 
217 
218 //******************************************************************************
219 
225 QModelIndex TreeModel::parent(const QModelIndex &_index) const
226 {
227  if (!_index.isValid())
228  return QModelIndex();
229 
230  TreeItem *childItem = static_cast<TreeItem*>(_index.internalPointer());
231  TreeItem *parentItem = childItem->parent();
232 
233  if (parentItem == rootItem_)
234  return QModelIndex();
235 
236  return createIndex(parentItem->row(), 0, parentItem);
237 }
238 
239 
240 //******************************************************************************
241 
247 int TreeModel::rowCount(const QModelIndex &_parent) const
248 {
249  TreeItem *parentItem;
250  if (_parent.column() > 0)
251  return 0;
252 
253  if (!_parent.isValid())
254  parentItem = rootItem_;
255  else
256  parentItem = static_cast<TreeItem*>(_parent.internalPointer());
257 
258  return parentItem->childCount();
259 }
260 
261 
262 //******************************************************************************
263 
268 void TreeModel::objectChanged(int _id) {
269 
270  if ( _id != -1 ){
271 
272  BaseObject* obj = 0;
273  PluginFunctions::getObject(_id, obj);
274 
275  TreeItem* item = rootItem_->childExists(_id);
276 
277  //if internal and external representation are both valid
278  if (obj != 0 && item != 0){
279  //update the name
280  if ( obj->name() != item->name() ){
281 
282  item->name( obj->name() );
283 
284  QModelIndex index = getModelIndex(item,0);
285  if ( index.isValid() )
286  emit dataChanged( index, index);
287  }
288 
289  //update visibility
290  if ( obj->visible() != item->visible() || obj->isGroup() ){
291 
292  item->visible( obj->visible() );
293 
294  QModelIndex index0 = getModelIndex(item,0);
295  QModelIndex index1 = getModelIndex(item,3);
296 
297  if ( index0.isValid() && index1.isValid() ){
298  //the whole row has to be updated because of the grey background-color
299  emit dataChanged( index0, index1);
300  propagateUpwards(item->parent(), 1, obj->visible() );
301  }
302 
303  if ( obj->isGroup() )
304  propagateDownwards(item, 1 );
305  }
306 
307  //update parent
308  if ( obj->parent() == PluginFunctions::objectRoot() && isRoot( item->parent() ) ){
309  return;
310  }else if ( obj->parent() == PluginFunctions::objectRoot() && !isRoot( item->parent() ) ){
311  moveItem(item, rootItem_ );
312  }else if ( obj->parent()->id() != item->parent()->id() ){
313  TreeItem* parent = rootItem_->childExists( obj->parent()->id() );
314 
315  if (parent != 0)
316  moveItem(item, parent );
317  }
318  }
319  }
320 }
321 
322 
327 void TreeModel::objectAdded(BaseObject* _object){
328 
329  objectAdded (_object, _object->parent());
330 }
331 
338 
339  if (rootItem_->childExists(_object->id()))
340  return;
341 
342  TreeItem* parent = 0;
343  //find the parent
344  if ( _parent == PluginFunctions::objectRoot() )
345  parent = rootItem_;
346  else
347  parent = rootItem_->childExists( _parent->id() );
348 
349  if (!parent)
350  {
351  objectAdded(_parent);
352  parent = rootItem_->childExists( _parent->id() );
353  }
354 
355  QModelIndex parentIndex = getModelIndex(parent, 0);
356 
357  beginInsertRows(parentIndex, parent->childCount(), parent->childCount()); //insert at the bottom
358 
359  TreeItem* item = new TreeItem( _object->id(), _object->name(), _object->dataType(), parent);
360 
361  parent->appendChild( item );
362 
363  endInsertRows();
364 
365  objectChanged( _object->id() );
366 }
367 
372 void TreeModel::objectDeleted(int _id){
373 
374  TreeItem* item = rootItem_->childExists(_id);
375 
376  if ( item != 0 && !isRoot(item) ){
377 
378  QModelIndex itemIndex = getModelIndex(item, 0);
379  QModelIndex parentIndex = itemIndex.parent();
380 
381  beginRemoveRows( parentIndex, itemIndex.row(), itemIndex.row() );
382 
383  item->parent()->removeChild(item);
384  item->deleteSubtree();
385 
386  delete item;
387 
388  endRemoveRows();
389  }
390 }
391 
392 //******************************************************************************
393 
399 void TreeModel::moveItem(TreeItem* _item, TreeItem* _parent ){
400 
401  QModelIndex itemIndex = getModelIndex(_item, 0);
402  QModelIndex oldParentIndex = itemIndex.parent();
403  QModelIndex newParentIndex = getModelIndex(_parent, 0);
404 
405  //delete everything at the old location
406  beginRemoveRows( oldParentIndex, itemIndex.row(), itemIndex.row() );
407 
408  _item->parent()->removeChild(_item);
409 
410  endRemoveRows();
411 
412  //insert it at the new location
413  beginInsertRows(newParentIndex, _parent->childCount(), _parent->childCount() ); //insert at the bottom
414  _item->setParent( _parent );
415  _parent->appendChild( _item );
416  endInsertRows();
417 
418  emit layoutChanged();
419 }
420 
421 //******************************************************************************
422 
428 TreeItem* TreeModel::getItem(const QModelIndex &_index) const
429 {
430  if (_index.isValid()) {
431  TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
432  if (item) return item;
433  }
434  return rootItem_;
435 }
436 
437 
438 //******************************************************************************
439 
445 QString TreeModel::itemName(const QModelIndex &_index) const
446 {
447  if (_index.isValid()) {
448  TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
449  if (item)
450  return item->name();
451  }
452  return "not found";
453 }
454 
455 //******************************************************************************
456 
462 int TreeModel::itemId(const QModelIndex &_index) const
463 {
464  if (_index.isValid()) {
465  TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
466  if (item)
467  return item->id();
468  }
469  return -1;
470 }
471 
472 //******************************************************************************
473 
482 QModelIndex TreeModel::getModelIndex(TreeItem* _object, int _column ){
483 
484  // root item gets an invalid QModelIndex
485  if ( _object == rootItem_ )
486  return QModelIndex();
487 
488  QModelIndex index = createIndex(_object->row(), _column, _object);
489 
490  return index;
491 }
492 
493 //******************************************************************************
494 
503 QModelIndex TreeModel::getModelIndex(int _id, int _column ){
504 
505  TreeItem *obj = rootItem_->childExists(_id);
506 
507  if (obj)
508  return getModelIndex (obj, _column);
509 
510  return QModelIndex();
511 }
512 
513 
514 //******************************************************************************
515 
522 void TreeModel::propagateUpwards(TreeItem* _item, int _column, bool _value ){
523 
524  if ( isRoot(_item) || (!_item->isGroup()) )
525  return;
526 
527  if (_column == 1){ //visibility
528  _item->visible( _value );
529 
530  //the whole row has to be updated because of the grey background-color
531  QModelIndex index0 = getModelIndex(_item,0);
532  QModelIndex index1 = getModelIndex(_item,3);
533 
534  emit dataChanged( index0, index1);
535 
536  } else {
537 
538  QModelIndex index = getModelIndex(_item,_column);
539  emit dataChanged(index, index);
540  }
541 
542  propagateUpwards( _item->parent(), _column, _value );
543 }
544 
545 //******************************************************************************
546 
552 void TreeModel::propagateDownwards(TreeItem* _item, int _column ){
553 
554  for (int i=0; i < _item->childCount(); i++){
555 
556  TreeItem* current = _item->child(i);
557 
558  bool changed = false;
559 
560  switch ( _column ){
561 
562  case 1: //VISIBILTY
563 
564  if ( current->visible() != _item->visible() ){
565 
566  current->visible( _item->visible() );
567  changed = true;
568  }
569  break;
570 
571  default:
572  break;
573  }
574 
575  if (changed){
576  QModelIndex index = getModelIndex(current,_column);
577  emit dataChanged(index, index);
578  }
579 
580  if ( current->isGroup() )
581  propagateDownwards(current, _column);
582  }
583 }
584 
585 //******************************************************************************
586 
587 bool TreeModel::setData(const QModelIndex &_index, const QVariant &_value, int /*role*/)
588 {
589 
590  emit dataChangedInside( itemId(_index), _index.column(), _value );
591 
592  return true;
593 }
594 
595 
596 //******************************************************************************
597 
603 bool TreeModel::isRoot(TreeItem * _item) {
604  return ( _item == rootItem_ );
605 }
BaseObject *& objectRoot()
Get the root of the object structure.
int itemId(const QModelIndex &_index) const
Get the id of a TreeItem corresponding to a given ModelIndex.
Definition: TreeModel.cc:552
int columnCount(const QModelIndex &_parent=QModelIndex()) const
Return the number of columns.
Definition: TreeModel.cc:90
int rowCount(const QModelIndex &_parent=QModelIndex()) const
get the number of rows
Definition: TreeModel.cc:344
void deleteSubtree()
delete the whole subtree below this item ( The item itself is not touched )
Definition: TreeItem.cc:351
bool visible()
visible
Definition: TreeItem.cc:159
QModelIndex getModelIndex(TreeItem *_object, int _column)
Return the ModelIndex corresponding to a given TreeItem and Column.
Definition: TreeModel.cc:572
void objectChanged(int _id)
The object with the given id has been changed. Check if model also has to be changed.
Definition: TreeModel.cc:363
void propagateDownwards(TreeItem *_obj, int _column)
Recursively update a column up to the root of the tree.
Definition: TreeModel.cc:552
virtual bool visible()
return if object is visible
Definition: BaseObject.cc:350
QString itemName(const QModelIndex &_index) const
Get the name of a TreeItem corresponding to a given ModelIndex.
Definition: TreeModel.cc:535
TreeModel(QObject *_parent=0)
Constructor.
Definition: TreeModel.cc:71
TreeItem * parent()
Get the parent item ( 0 if root item )
Definition: TreeItem.cc:243
bool getObject(int _identifier, BSplineCurveObject *&_object)
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
const DataType DATA_UNKNOWN(0)
None of the other Objects.
TreeItem * childExists(int _objectId)
Check if the element exists in the subtree of this element.
Definition: TreeItem.cc:279
QString name()
name
Definition: TreeItem.cc:171
~TreeModel()
Destructor.
Definition: TreeModel.cc:82
int id() const
Definition: BaseObject.cc:201
BaseObject * parent()
Get the parent item ( 0 if rootitem )
Definition: BaseObject.cc:477
Qt::ItemFlags flags(const QModelIndex &_index) const
return the types of the corresponding entry
Definition: TreeModel.cc:231
void setParent(TreeItem *_parent)
Set the parent pointer.
Definition: TreeItem.cc:250
int id()
id
Definition: TreeItem.cc:86
void appendChild(TreeItem *child)
add a child to this node
Definition: TreeItem.cc:256
TreeItem * rootItem_
Root item of the tree.
Definition: TreeModel.hh:167
int row() const
get the row of this item from the parent
Definition: TreeItem.cc:236
TreeItem * child(int row)
return a child
Definition: TreeItem.cc:265
void removeChild(TreeItem *_item)
Remove a child from this object.
Definition: TreeItem.cc:316
void propagateUpwards(TreeItem *_obj, int _column, bool _value)
Recursively update a column up to the root of the tree.
Definition: TreeModel.cc:522
int childCount() const
get the number of children
Definition: TreeItem.cc:272
QVariant data(const QModelIndex &_index, int _role) const
Get the data of the corresponding entry.
Definition: TreeModel.cc:105
void objectAdded(BaseObject *_object)
The object with the given id has been added. add it to the internal tree.
Definition: TreeModel.cc:436
bool isGroup() const
Check if object is a group.
Definition: BaseObject.cc:630
QModelIndex parent(const QModelIndex &_index) const
Get the parent ModelIndex.
Definition: TreeModel.cc:322
void moveItem(TreeItem *_item, TreeItem *_parent)
move the item to a new parent
Definition: TreeModel.cc:498
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
bool isRoot(TreeItem *_item)
Check if the given item is the root item.
Definition: TreeModel.cc:602
TreeItem * getItem(const QModelIndex &_index) const
Get the TreeItem corresponding to a given ModelIndex.
Definition: TreeModel.cc:518
QModelIndex index(int _row, int _column, const QModelIndex &_parent=QModelIndex()) const
Get the ModelIndex at given row,column.
Definition: TreeModel.cc:295
void objectDeleted(int _id)
The object with the given id has been deleted. delete it from the internal tree.
Definition: TreeModel.cc:471
QVariant headerData(int _section, Qt::Orientation _orientation, int _role=Qt::DisplayRole) const
return the header data of the model
Definition: TreeModel.cc:268
bool setData(const QModelIndex &_index, const QVariant &_value, int _role)
Set Data at &#39;index&#39; to &#39;value&#39;.
Definition: TreeModel.cc:585