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
45
46 #include "TreeModel.hh"
47
48
49 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
50
51
52 #include <QtWidgets>
53
54
55 //******************************************************************************
56
61 TreeModel::TreeModel( QObject *_parent) : QAbstractItemModel(_parent)
62 {
63 rootItem_ = new TreeItem( -1, "ROOT", DATA_UNKNOWN, 0);
64 }
65
66
67 //******************************************************************************
68
72 TreeModel::~TreeModel()
73 {
74
75 }
76
77
78 //******************************************************************************
79
80 int TreeModel::columnCount(const QModelIndex &/*_parent*/) const
81 {
82 // Id, Name -> 2
83 return (2);
84 }
85
86
87 //******************************************************************************
88
95 QVariant TreeModel::data(const QModelIndex &_index, int _role) const
96 {
97
98 // Skip invalid requests
99 if (!_index.isValid())
100 return QVariant();
101
102 // Get the corresponding tree item
103 TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
104
105 if ( item == rootItem_ ) {
106 std::cerr << "Root" << std::endl;
107 }
108
109 // Set the background color of the objects row
110 if ( _role == Qt::BackgroundRole ) {
111 if ( !item->visible() ) {
112 return QVariant (QBrush (QColor (192, 192, 192)));
113 }
114 }
115
116 if (_role == Qt::DisplayRole)
117 {
118 switch (_index.column ())
119 {
120 case 0:
121 return QVariant(item->id());
122 case 1:
123 return QVariant(item->name());
124 default:
125 return QVariant ();
126 }
127 }
128 else
129 return QVariant ();
130 }
131
132
133 //******************************************************************************
134
140 Qt::ItemFlags TreeModel::flags(const QModelIndex &_index) const
141 {
142 if (!_index.isValid())
143 return 0;
144
145 Qt::ItemFlags flags = 0;
146
147 // Show/Source/Target
148 if ( _index.column() == 0 || _index.column() == 1 )
149 flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
150 else
151 flags = Qt::ItemIsEnabled;
152
153 return flags;
154 }
155
156
157 //******************************************************************************
158
166 QVariant TreeModel::headerData(int _section, Qt::Orientation _orientation,
167 int _role) const
168 {
169 if (_orientation == Qt::Horizontal && _role == Qt::DisplayRole) {
170
171 if (_section == 0)
172 return QVariant("ID");
173 else if (_section == 1)
174 return QVariant("Name");
175 else
176 return QVariant();
177
178 }
179 return QVariant();
180 }
181
182
183 //******************************************************************************
184
192 QModelIndex TreeModel::index(int _row, int _column, const QModelIndex &_parent) const
193 {
194 TreeItem *parentItem;
195
196 if (!_parent.isValid())
197 parentItem = rootItem_;
198 else
199 parentItem = static_cast<TreeItem*>(_parent.internalPointer());
200
201 TreeItem *childItem = parentItem->child(_row);
202 if (childItem)
203 return createIndex(_row, _column, childItem);
204 else
205 return QModelIndex();
206 }
207
208
209 //******************************************************************************
210
216 QModelIndex TreeModel::parent(const QModelIndex &_index) const
217 {
218 if (!_index.isValid())
219 return QModelIndex();
220
221 TreeItem *childItem = static_cast<TreeItem*>(_index.internalPointer());
222 TreeItem *parentItem = childItem->parent();
223
224 if (parentItem == rootItem_)
225 return QModelIndex();
226
227 return createIndex(parentItem->row(), 0, parentItem);
228 }
229
230
231 //******************************************************************************
232
238 int TreeModel::rowCount(const QModelIndex &_parent) const
239 {
240 TreeItem *parentItem;
241 if (_parent.column() > 0)
242 return 0;
243
244 if (!_parent.isValid())
245 parentItem = rootItem_;
246 else
247 parentItem = static_cast<TreeItem*>(_parent.internalPointer());
248
249 return parentItem->childCount();
250 }
251
252
253 //******************************************************************************
254
259 void TreeModel::objectChanged(int _id) {
260
261 if ( _id != -1 ){
262
263 BaseObject* obj = 0;
264 PluginFunctions::getObject(_id, obj);
265
266 TreeItem* item = rootItem_->childExists(_id);
267
268 //if internal and external representation are both valid
269 if (obj != 0 && item != 0){
270 //update the name
271 if ( obj->name() != item->name() ){
272
273 item->name( obj->name() );
274
275 QModelIndex index = getModelIndex(item,0);
276 if ( index.isValid() )
277 emit dataChanged( index, index);
278 }
279
280 //update visibility
281 if ( obj->visible() != item->visible() || obj->isGroup() ){
282
283 item->visible( obj->visible() );
284
285 QModelIndex index0 = getModelIndex(item,0);
286 QModelIndex index1 = getModelIndex(item,3);
287
288 if ( index0.isValid() && index1.isValid() ){
289 //the whole row has to be updated because of the grey background-color
290 emit dataChanged( index0, index1);
291 propagateUpwards(item->parent(), 1, obj->visible() );
292 }
293
294 if ( obj->isGroup() )
295 propagateDownwards(item, 1 );
296 }
297
298 //update parent
299 if ( obj->parent() == PluginFunctions::objectRoot() && isRoot( item->parent() ) ){
300 return;
301 }else if ( obj->parent() == PluginFunctions::objectRoot() && !isRoot( item->parent() ) ){
302 moveItem(item, rootItem_ );
303 }else if ( obj->parent()->id() != item->parent()->id() ){
304 TreeItem* parent = rootItem_->childExists( obj->parent()->id() );
305
306 if (parent != 0)
307 moveItem(item, parent );
308 }
309 }
310 }
311 }
312
313
318 void TreeModel::objectAdded(BaseObject* _object){
319
320 objectAdded (_object, _object->parent());
321 }
322
328 void TreeModel::objectAdded(BaseObject* _object, BaseObject* _parent){
329
330 if (rootItem_->childExists(_object->id()))
331 return;
332
333 TreeItem* parent = 0;
334 //find the parent
335 if ( _parent == PluginFunctions::objectRoot() )
336 parent = rootItem_;
337 else
338 parent = rootItem_->childExists( _parent->id() );
339
340 if (!parent)
341 {
342 objectAdded(_parent);
343 parent = rootItem_->childExists( _parent->id() );
344 }
345
346 QModelIndex parentIndex = getModelIndex(parent, 0);
347
348 beginInsertRows(parentIndex, parent->childCount(), parent->childCount()); //insert at the bottom
349
350 TreeItem* item = new TreeItem( _object->id(), _object->name(), _object->dataType(), parent);
351
352 parent->appendChild( item );
353
354 endInsertRows();
355
356 objectChanged( _object->id() );
357 }
358
363 void TreeModel::objectDeleted(int _id){
364
365 TreeItem* item = rootItem_->childExists(_id);
366
367 if ( item != 0 && !isRoot(item) ){
368
369 QModelIndex itemIndex = getModelIndex(item, 0);
370 QModelIndex parentIndex = itemIndex.parent();
371
372 beginRemoveRows( parentIndex, itemIndex.row(), itemIndex.row() );
373
374 item->parent()->removeChild(item);
375 item->deleteSubtree();
376
377 delete item;
378
379 endRemoveRows();
380 }
381 }
382
383 //******************************************************************************
384
390 void TreeModel::moveItem(TreeItem* _item, TreeItem* _parent ){
391
392 QModelIndex itemIndex = getModelIndex(_item, 0);
393 QModelIndex oldParentIndex = itemIndex.parent();
394 QModelIndex newParentIndex = getModelIndex(_parent, 0);
395
396 //delete everything at the old location
397 beginRemoveRows( oldParentIndex, itemIndex.row(), itemIndex.row() );
398
399 _item->parent()->removeChild(_item);
400
401 endRemoveRows();
402
403 //insert it at the new location
404 beginInsertRows(newParentIndex, _parent->childCount(), _parent->childCount() ); //insert at the bottom
405 _item->setParent( _parent );
406 _parent->appendChild( _item );
407 endInsertRows();
408
409 emit layoutChanged();
410 }
411
412 //******************************************************************************
413
419 TreeItem* TreeModel::getItem(const QModelIndex &_index) const
420 {
421 if (_index.isValid()) {
422 TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
423 if (item) return item;
424 }
425 return rootItem_;
426 }
427
428
429 //******************************************************************************
430
436 QString TreeModel::itemName(const QModelIndex &_index) const
437 {
438 if (_index.isValid()) {
439 TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
440 if (item)
441 return item->name();
442 }
443 return "not found";
444 }
445
446 //******************************************************************************
447
453 int TreeModel::itemId(const QModelIndex &_index) const
454 {
455 if (_index.isValid()) {
456 TreeItem *item = static_cast<TreeItem*>(_index.internalPointer());
457 if (item)
458 return item->id();
459 }
460 return -1;
461 }
462
463 //******************************************************************************
464
473 QModelIndex TreeModel::getModelIndex(TreeItem* _object, int _column ){
474
475 // root item gets an invalid QModelIndex
476 if ( _object == rootItem_ )
477 return QModelIndex();
478
479 QModelIndex index = createIndex(_object->row(), _column, _object);
480
481 return index;
482 }
483
484 //******************************************************************************
485
494 QModelIndex TreeModel::getModelIndex(int _id, int _column ){
495
496 TreeItem *obj = rootItem_->childExists(_id);
497
498 if (obj)
499 return getModelIndex (obj, _column);
500
501 return QModelIndex();
502 }
503
504
505 //******************************************************************************
506
513 void TreeModel::propagateUpwards(TreeItem* _item, int _column, bool _value ){
514
515 if ( isRoot(_item) || (!_item->isGroup()) )
516 return;
517
518 if (_column == 1){ //visibility
519 _item->visible( _value );
520
521 //the whole row has to be updated because of the grey background-color
522 QModelIndex index0 = getModelIndex(_item,0);
523 QModelIndex index1 = getModelIndex(_item,3);
524
525 emit dataChanged( index0, index1);
526
527 } else {
528
529 QModelIndex index = getModelIndex(_item,_column);
530 emit dataChanged(index, index);
531 }
532
533 propagateUpwards( _item->parent(), _column, _value );
534 }
535
536 //******************************************************************************
537
543 void TreeModel::propagateDownwards(TreeItem* _item, int _column ){
544
545 for (int i=0; i < _item->childCount(); i++){
546
547 TreeItem* current = _item->child(i);
548
549 bool changed = false;
550
551 switch ( _column ){
552
553 case 1: //VISIBILTY
554
555 if ( current->visible() != _item->visible() ){
556
557 current->visible( _item->visible() );
558 changed = true;
559 }
560 break;
561
562 default:
563 break;
564 }
565
566 if (changed){
567 QModelIndex index = getModelIndex(current,_column);
568 emit dataChanged(index, index);
569 }
570
571 if ( current->isGroup() )
572 propagateDownwards(current, _column);
573 }
574 }
575
576 //******************************************************************************
577
578 bool TreeModel::setData(const QModelIndex &_index, const QVariant &_value, int /*role*/)
579 {
580
581 emit dataChangedInside( itemId(_index), _index.column(), _value );
582
583 return true;
584 }
585
586
587 //******************************************************************************
588
594 bool TreeModel::isRoot(TreeItem * _item) {
595 return ( _item == rootItem_ );
596 }
TreeItem::row
int row() const
get the row of this item from the parent
Definition: TreeItem.cc:228
BaseObject::isGroup
bool isGroup() const
Check if object is a group.
Definition: BaseObject.cc:619
TreeItem::removeChild
void removeChild(TreeItem *_item)
Remove a child from this object.
Definition: TreeItem.cc:308
BaseObject::id
int id() const
Definition: BaseObject.cc:190
TreeModel::objectDeleted
void objectDeleted(int _id)
The object with the given id has been deleted. delete it from the internal tree.
Definition: TreeModel.cc:461
PluginFunctions.hh
TreeModel::index
QModelIndex index(int _row, int _column, const QModelIndex &_parent=QModelIndex()) const
Get the ModelIndex at given row,column.
Definition: TreeModel.cc:285
TreeModel::itemName
QString itemName(const QModelIndex &_index) const
Get the name of a TreeItem corresponding to a given ModelIndex.
Definition: TreeModel.cc:525
TreeItem::appendChild
void appendChild(TreeItem *child)
add a child to this node
Definition: TreeItem.cc:248
TreeItem::name
QString name()
name
Definition: TreeItem.cc:163
TreeItem::setParent
void setParent(TreeItem *_parent)
Set the parent pointer.
Definition: TreeItem.cc:242
TreeModel::flags
Qt::ItemFlags flags(const QModelIndex &_index) const
return the types of the corresponding entry
Definition: TreeModel.cc:221
TreeModel::moveItem
void moveItem(TreeItem *_item, TreeItem *_parent)
move the item to a new parent
Definition: TreeModel.cc:488
TreeModel::getItem
TreeItem * getItem(const QModelIndex &_index) const
Get the TreeItem corresponding to a given ModelIndex.
Definition: TreeModel.cc:508
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
TreeItem::childCount
int childCount() const
get the number of children
Definition: TreeItem.cc:264
TreeModel::rootItem_
TreeItem * rootItem_
Root item of the tree.
Definition: TreeModel.hh:161
TreeModel::columnCount
int columnCount(const QModelIndex &_parent=QModelIndex()) const
Return the number of columns.
Definition: TreeModel.cc:80
TreeModel::itemId
int itemId(const QModelIndex &_index) const
Get the id of a TreeItem corresponding to a given ModelIndex.
Definition: TreeModel.cc:542
TreeModel::getModelIndex
QModelIndex getModelIndex(TreeItem *_object, int _column)
Return the ModelIndex corresponding to a given TreeItem and Column.
Definition: TreeModel.cc:562
TreeItem
Definition: TreeItem.hh:52
DATA_UNKNOWN
const DataType DATA_UNKNOWN(0)
None of the other Objects.
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:294
BaseObject::name
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:730
TreeModel::data
QVariant data(const QModelIndex &_index, int _role) const
Get the data of the corresponding entry.
Definition: TreeModel.cc:95
PluginFunctions::objectRoot
BaseObject *& objectRoot()
Get the root of the object structure.
Definition: PluginFunctions.cc:1099
BaseObject::visible
virtual bool visible()
return if object is visible
Definition: BaseObject.cc:339
TreeModel::parent
QModelIndex parent(const QModelIndex &_index) const
Get the parent ModelIndex.
Definition: TreeModel.cc:312
TreeModel::isRoot
bool isRoot(TreeItem *_item)
Check if the given item is the root item.
Definition: TreeModel.cc:592
TreeItem::id
int id()
id
Definition: TreeItem.cc:78
TreeModel::objectChanged
void objectChanged(int _id)
The object with the given id has been changed. Check if model also has to be changed.
Definition: TreeModel.cc:353
TreeItem::childExists
TreeItem * childExists(int _objectId)
Check if the element exists in the subtree of this element.
Definition: TreeItem.cc:271
TreeModel::propagateUpwards
void propagateUpwards(TreeItem *_obj, int _column, bool _value)
Recursively update a column up to the root of the tree.
Definition: TreeModel.cc:513
TreeItem::parent
TreeItem * parent()
Get the parent item ( 0 if root item )
Definition: TreeItem.cc:235
TreeModel::headerData
QVariant headerData(int _section, Qt::Orientation _orientation, int _role=Qt::DisplayRole) const
return the header data of the model
Definition: TreeModel.cc:258
TreeModel::propagateDownwards
void propagateDownwards(TreeItem *_obj, int _column)
Recursively update a column up to the root of the tree.
Definition: TreeModel.cc:543
TreeModel::rowCount
int rowCount(const QModelIndex &_parent=QModelIndex()) const
get the number of rows
Definition: TreeModel.cc:334
TreeModel::TreeModel
TreeModel(QObject *_parent=0)
Constructor.
Definition: TreeModel.cc:61
BaseObject
Definition: BaseObject.hh:82
TreeItem::child
TreeItem * child(int row)
return a child
Definition: TreeItem.cc:257
TreeModel::setData
bool setData(const QModelIndex &_index, const QVariant &_value, int _role)
Set Data at &#39;index&#39; to &#39;value&#39;.
Definition: TreeModel.cc:575
BaseObject::parent
BaseObject * parent()
Get the parent item ( 0 if rootitem )
Definition: BaseObject.cc:466
TreeItem::visible
bool visible()
visible
Definition: TreeItem.cc:151
TreeModel::~TreeModel
~TreeModel()
Destructor.
Definition: TreeModel.cc:72
TreeItem::deleteSubtree
void deleteSubtree()
delete the whole subtree below this item ( The item itself is not touched )
Definition: TreeItem.cc:343
TreeModel::objectAdded
void objectAdded(BaseObject *_object)
The object with the given id has been added. add it to the internal tree.
Definition: TreeModel.cc:426