TreeModel.cc 23.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*===========================================================================*\
 *                                                                           *
 *                              OpenFlipper                                  *
 *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openflipper.org                             *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenFlipper.                                        *
 *                                                                           *
 *  OpenFlipper is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenFlipper is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenFlipper. If not,                                  *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
37
 *   $Revision$                                                       *
38 39 40 41
 *   $Author$                                                      *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
42 43 44 45 46 47 48 49 50 51

#include <QtGui>
#include <QBrush>

#include "TreeModel.hh"

#include <iostream>


#include <OpenFlipper/common/Types.hh>
52
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
Jan Möbius's avatar
 
Jan Möbius committed
53

Dirk Wilden's avatar
Dirk Wilden committed
54 55 56 57

//******************************************************************************

/** \brief Constructor
58
 *
Dirk Wilden's avatar
Dirk Wilden committed
59 60
 * @param _parent parent Object
 */
Jan Möbius's avatar
 
Jan Möbius committed
61 62
TreeModel::TreeModel( QObject *_parent) : QAbstractItemModel(_parent)
{
63
  rootItem_ = new TreeItem( -1, "ROOT", DATA_UNKNOWN, 0);
Jan Möbius's avatar
 
Jan Möbius committed
64 65
}

Dirk Wilden's avatar
Dirk Wilden committed
66 67 68 69

//******************************************************************************

/** \brief Destructor
70
 *
Dirk Wilden's avatar
Dirk Wilden committed
71
 */
Jan Möbius's avatar
 
Jan Möbius committed
72 73
TreeModel::~TreeModel()
{
Dirk Wilden's avatar
Dirk Wilden committed
74

Jan Möbius's avatar
 
Jan Möbius committed
75 76
}

Dirk Wilden's avatar
Dirk Wilden committed
77 78 79 80

//******************************************************************************

/** \brief Return the number of columns
81
 *
Dirk Wilden's avatar
Dirk Wilden committed
82 83 84
 * @param unused
 * @return return always 4
 */
Dirk Wilden's avatar
Dirk Wilden committed
85
int TreeModel::columnCount(const QModelIndex &/*_parent*/) const
Jan Möbius's avatar
 
Jan Möbius committed
86 87 88 89 90
{
  // Name,Visible,Source,Target -> 4
  return (4);
}

Dirk Wilden's avatar
Dirk Wilden committed
91 92 93 94

//******************************************************************************

/** \brief Returns the data stored under the given role for the item referred to by the index
95
 *
Dirk Wilden's avatar
Dirk Wilden committed
96 97 98 99
 * @param index a ModelIndex that defines the item in the tree
 * @param role defines the kind of data requested
 * @return requested data
 */
Jan Möbius's avatar
 
Jan Möbius committed
100 101 102 103 104 105
QVariant TreeModel::data(const QModelIndex &index, int role) const
{

  // Skip invalid requests
  if (!index.isValid())
      return QVariant();
106

Jan Möbius's avatar
 
Jan Möbius committed
107
  // Get the corresponding tree item
Dirk Wilden's avatar
Dirk Wilden committed
108
  TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
109

Jan Möbius's avatar
 
Jan Möbius committed
110
  if ( item == rootItem_ ) {
111
    std::cerr << "Root" << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
112
  }
113

Jan Möbius's avatar
 
Jan Möbius committed
114 115 116
  // Set the background color of the objects row
  if ( role == Qt::BackgroundRole ) {
    if ( !item->visible() ) {
117
      return QVariant( QBrush(QColor(100,100,100) ) );
Jan Möbius's avatar
 
Jan Möbius committed
118 119
    }
  }
120 121
  

Dirk Wilden's avatar
Dirk Wilden committed
122

Jan Möbius's avatar
 
Jan Möbius committed
123 124 125
  switch (index.column() ) {
    // Name
    case 0 :
126 127 128 129 130

      // If we are setting the name, also add the icon
      if ( role == Qt::DecorationRole ) {
        return QVariant( typeIcon(item->dataType()) );
      }
131

Dirk Wilden's avatar
Dirk Wilden committed
132
      if (role != Qt::DisplayRole && role != Qt::EditRole )
Jan Möbius's avatar
 
Jan Möbius committed
133
        return QVariant();
134

Jan Möbius's avatar
 
Jan Möbius committed
135
      return QVariant(item->name());
136

Jan Möbius's avatar
 
Jan Möbius committed
137 138 139 140 141 142 143
      break;
    // Visible
    case 1 :
      if (role == Qt::CheckStateRole ) {
        bool visibility = false;
        // visiblity group
        if (item->isGroup()){
Dirk Wilden's avatar
Dirk Wilden committed
144
          QList< TreeItem* > children = item->getLeafs();
Jan Möbius's avatar
 
Jan Möbius committed
145 146 147 148 149 150 151 152 153 154 155
          bool initRound = true;
          for (int i=0; i < children.size(); i++){
            if (initRound){
              visibility = children[i]->visible();
              initRound = false;
            }else if (visibility != children[i]->visible())
              return QVariant(Qt::PartiallyChecked);
          }
        }else
          //visibility item
          visibility = item->visible();
156
        if (visibility)
Jan Möbius's avatar
 
Jan Möbius committed
157 158 159 160 161
          return QVariant(Qt::Checked);
        else
          return QVariant(Qt::Unchecked);
      }
      return QVariant();
162

Jan Möbius's avatar
 
Jan Möbius committed
163 164 165 166 167 168 169
      break;
    // Source
    case 2 :
      if (role == Qt::CheckStateRole ) {
        bool source = false;
        // source group
        if (item->isGroup()){
Dirk Wilden's avatar
Dirk Wilden committed
170
          QList< TreeItem* > children = item->getLeafs();
171

Jan Möbius's avatar
 
Jan Möbius committed
172 173 174 175 176 177 178 179 180 181 182
          bool initRound = true;
          for (int i=0; i < children.size(); i++){
            if (initRound){
              source = children[i]->source();
              initRound = false;
            }else if (source != children[i]->source())
              return QVariant(Qt::PartiallyChecked);
          }
        }else
          //source item
          source = item->source();
183
        if (source)
Jan Möbius's avatar
 
Jan Möbius committed
184 185 186 187 188 189
          return QVariant(Qt::Checked);
        else
          return QVariant(Qt::Unchecked);
      }
      return QVariant();

190
    // Target
Jan Möbius's avatar
 
Jan Möbius committed
191 192 193 194 195
    case 3 :
      if (role == Qt::CheckStateRole ) {
        bool target = false;
        // target group
        if (item->isGroup()){
Dirk Wilden's avatar
Dirk Wilden committed
196
          QList< TreeItem* > children = item->getLeafs();
197

Jan Möbius's avatar
 
Jan Möbius committed
198 199 200 201 202 203 204 205 206 207 208
          bool initRound = true;
          for (int i=0; i < children.size(); i++){
            if (initRound){
              target = children[i]->target();
              initRound = false;
            }else if (target != children[i]->target())
              return QVariant(Qt::PartiallyChecked);
          }
        }else
          //target item
          target = item->target();
209
        if (target)
Jan Möbius's avatar
 
Jan Möbius committed
210 211 212 213 214 215 216
          return QVariant(Qt::Checked);
        else
          return QVariant(Qt::Unchecked);
      }
      return QVariant();

      break;
217

Jan Möbius's avatar
 
Jan Möbius committed
218 219 220 221 222 223
    default:
      return QVariant();
  }

}

Dirk Wilden's avatar
Dirk Wilden committed
224 225 226 227

//******************************************************************************

/** \brief Returns the item flags for the given index
228
 *
Dirk Wilden's avatar
Dirk Wilden committed
229 230 231
 * @param index ModelIndex that defines an item in the tree
 * @return flags for the given ModelIndex
 */
Jan Möbius's avatar
 
Jan Möbius committed
232 233 234 235
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;
236 237 238

    Qt::ItemFlags flags = 0;

Jan Möbius's avatar
 
Jan Möbius committed
239
    // Show/Source/Target
240
    if ( ( index.column() == 1 ) ||
Jan Möbius's avatar
 
Jan Möbius committed
241 242
         ( index.column() == 2 ) ||
         ( index.column() == 3 ) )
243 244
      flags = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
Jan Möbius's avatar
 
Jan Möbius committed
245
    if ( index.column() == 0 )
246 247 248 249 250
      flags = Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
      flags = Qt::ItemIsEnabled;

  // Get the corresponding tree item
Dirk Wilden's avatar
Dirk Wilden committed
251
  TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
252 253 254 255 256

  if ( item->isGroup() )
    return flags | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
  else
    return flags | Qt::ItemIsDragEnabled;
Jan Möbius's avatar
 
Jan Möbius committed
257 258
}

Dirk Wilden's avatar
Dirk Wilden committed
259 260 261 262

//******************************************************************************

/** \brief Returns the data in the header
263
 *
Dirk Wilden's avatar
Dirk Wilden committed
264 265 266 267 268
 * @param section the column in the header
 * @param orientation header orientation (only horizontal handled)
 * @param role the role that defines the type of data
 * @return the requested data
 */
Jan Möbius's avatar
 
Jan Möbius committed
269 270 271 272
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
                                int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
273

Jan Möbius's avatar
 
Jan Möbius committed
274 275 276 277 278 279 280 281 282 283 284 285
      switch (section) {
        case 0 : return QVariant("Name");
        case 1 : return QVariant("Show");
        case 2 : return QVariant("Source");
        case 3 : return QVariant("Target");
        default :
          return QVariant();
      }
    }
    return QVariant();
}

Dirk Wilden's avatar
Dirk Wilden committed
286 287 288 289

//******************************************************************************

/** \brief Returns the index of the item in the model specified by the given row, column and parent index.
290 291
 *
 * @param row the row
Dirk Wilden's avatar
Dirk Wilden committed
292 293 294 295
 * @param column the column
 * @param _parent parent item
 * @return corresponding ModelIndex
 */
Jan Möbius's avatar
 
Jan Möbius committed
296 297
QModelIndex TreeModel::index(int row, int column, const QModelIndex &_parent) const
{
Dirk Wilden's avatar
Dirk Wilden committed
298 299
//     if (!hasIndex(row, column, _parent))
//         return QModelIndex();
Jan Möbius's avatar
 
Jan Möbius committed
300

Dirk Wilden's avatar
Dirk Wilden committed
301
    TreeItem *parentItem;
Jan Möbius's avatar
 
Jan Möbius committed
302 303 304 305

    if (!_parent.isValid())
        parentItem = rootItem_;
    else
Dirk Wilden's avatar
Dirk Wilden committed
306
        parentItem = static_cast<TreeItem*>(_parent.internalPointer());
Jan Möbius's avatar
 
Jan Möbius committed
307

Dirk Wilden's avatar
Dirk Wilden committed
308
    TreeItem *childItem = parentItem->child(row);
Jan Möbius's avatar
 
Jan Möbius committed
309 310 311 312 313 314
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

Dirk Wilden's avatar
Dirk Wilden committed
315 316 317 318

//******************************************************************************

/** \brief Return index of parent item
319
 *
Dirk Wilden's avatar
Dirk Wilden committed
320 321 322
 * @param index a ModelIndex
 * @return parent of the given ModelIndex
 */
Jan Möbius's avatar
 
Jan Möbius committed
323 324 325 326 327
QModelIndex TreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

Dirk Wilden's avatar
Dirk Wilden committed
328 329
    TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
    TreeItem *parentItem = childItem->parent();
Jan Möbius's avatar
 
Jan Möbius committed
330 331 332 333 334 335 336

    if (parentItem == rootItem_)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

Dirk Wilden's avatar
Dirk Wilden committed
337 338 339 340

//******************************************************************************

/** \brief Returns the number of rows under given parent
341
 *
Dirk Wilden's avatar
Dirk Wilden committed
342 343 344
 * @param _parent parent Item
 * @return number of rows that are children of given parent
 */
Jan Möbius's avatar
 
Jan Möbius committed
345 346
int TreeModel::rowCount(const QModelIndex &_parent) const
{
Dirk Wilden's avatar
Dirk Wilden committed
347
    TreeItem *parentItem;
Jan Möbius's avatar
 
Jan Möbius committed
348 349 350 351 352 353
    if (_parent.column() > 0)
        return 0;

    if (!_parent.isValid())
        parentItem = rootItem_;
    else
Dirk Wilden's avatar
Dirk Wilden committed
354
        parentItem = static_cast<TreeItem*>(_parent.internalPointer());
Jan Möbius's avatar
 
Jan Möbius committed
355 356 357 358 359

    return parentItem->childCount();
}


Dirk Wilden's avatar
Dirk Wilden committed
360 361
//******************************************************************************

Dirk Wilden's avatar
Dirk Wilden committed
362
/** \brief The object with the given id has been changed. Update the model.
363
 *
Dirk Wilden's avatar
Dirk Wilden committed
364 365
 * @param _id  id of an object
 */
Dirk Wilden's avatar
Dirk Wilden committed
366
void TreeModel::objectChanged(int _id) {
Jan Möbius's avatar
 
Jan Möbius committed
367

Dirk Wilden's avatar
Dirk Wilden committed
368
  if ( _id != -1 ){
Jan Möbius's avatar
 
Jan Möbius committed
369

Dirk Wilden's avatar
Dirk Wilden committed
370 371
    BaseObject* obj = 0;
    PluginFunctions::getObject(_id, obj);
Jan Möbius's avatar
 
Jan Möbius committed
372

Dirk Wilden's avatar
Dirk Wilden committed
373 374 375 376 377 378 379 380 381
    TreeItem* item = rootItem_->childExists(_id);

    //if internal and external representation are both valid
    if (obj != 0 && item != 0){
      //update the name
      if ( obj->name() != item->name() ){

        item->name( obj->name() );

382 383 384 385 386 387
        //TODO actually we do not need to update the whole row but single column somehow doesn't work
        QModelIndex index0 = getModelIndex(item,0);
        QModelIndex index1 = getModelIndex(item,3);

        if ( index0.isValid() && index1.isValid() )
          emit dataChanged( index0, index1);
Dirk Wilden's avatar
Dirk Wilden committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
      }

      //update visibility
      if ( obj->visible() != item->visible() || obj->isGroup() ){

        item->visible( obj->visible() );

        QModelIndex index0 = getModelIndex(item,0);
        QModelIndex index1 = getModelIndex(item,3);

        if ( index0.isValid() && index1.isValid() ){
          //the whole row has to be updated because of the grey background-color
          emit dataChanged( index0, index1);
          propagateUpwards(item->parent(), 1, obj->visible() );
        }

        if ( obj->isGroup() )
          propagateDownwards(item, 1 );
      }

      //update source flag
      if ( obj->source() != item->source() || obj->isGroup() ){

        item->source( obj->source() );

413 414 415 416 417 418 419
        //TODO actually we do not need to update the whole row but single column somehow doesn't work
        QModelIndex index0 = getModelIndex(item,0);
        QModelIndex index1 = getModelIndex(item,3);

        if ( index0.isValid() && index1.isValid() ){
          //the whole row has to be updated because of the grey background-color
          emit dataChanged( index0, index1);
Dirk Wilden's avatar
Dirk Wilden committed
420 421 422 423 424 425 426 427 428 429 430 431
          propagateUpwards(item->parent(), 2, false );
        }

        if ( obj->isGroup() )
          propagateDownwards(item, 2 );
      }

      //update target flag
      if ( obj->target() != item->target() || obj->isGroup() ){

        item->target( obj->target() );

432 433 434 435 436 437 438
        //TODO actually we do not need to update the whole row but single column somehow doesn't work
        QModelIndex index0 = getModelIndex(item,0);
        QModelIndex index1 = getModelIndex(item,3);

        if ( index0.isValid() && index1.isValid() ){
          //the whole row has to be updated because of the grey background-color
          emit dataChanged( index0, index1);
Dirk Wilden's avatar
Dirk Wilden committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
          propagateUpwards(item->parent(), 3, false );
        }

        if ( obj->isGroup() )
          propagateDownwards(item, 3 );
      }

      //update parent
      if ( obj->parent() == PluginFunctions::objectRoot() && isRoot( item->parent() ) ){
        return;
      }else if ( obj->parent() == PluginFunctions::objectRoot() && !isRoot( item->parent() ) ){
        moveItem(item, rootItem_ );
      }else if ( obj->parent()->id() != item->parent()->id() ){
        TreeItem* parent = rootItem_->childExists( obj->parent()->id() );

        if (parent != 0)
          moveItem(item, parent );
      }
Dirk Wilden's avatar
Dirk Wilden committed
457
    }
Dirk Wilden's avatar
Dirk Wilden committed
458 459
  }
}
Dirk Wilden's avatar
Dirk Wilden committed
460

Dirk Wilden's avatar
Dirk Wilden committed
461 462

/** \brief The object with the given id has been added. add it to the internal tree
463
 *
Dirk Wilden's avatar
Dirk Wilden committed
464 465 466 467
 * @param id_ id of the object
 */
void TreeModel::objectAdded(BaseObject* _object){

468 469 470 471 472 473 474
  // check if item already in model tree
  // this function can be called by addEmpty and fileOpened
  // both will be called by fileOpened such that the item
  // already exists
  if( rootItem_->childExists( _object->id() )) 
    return;

Dirk Wilden's avatar
Dirk Wilden committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
  TreeItem* parent = 0;
  //find the parent
  if ( _object->parent() == PluginFunctions::objectRoot() )
    parent = rootItem_;
  else
    parent = rootItem_->childExists( _object->parent()->id() );

  if (parent != 0){
    QModelIndex parentIndex = getModelIndex(parent, 0);

    beginInsertRows(parentIndex, parent->childCount(), parent->childCount()); //insert at the bottom

      TreeItem* item = new TreeItem( _object->id(), _object->name(), _object->dataType(), parent);

      parent->appendChild( item );

    endInsertRows();
Jan Möbius's avatar
 
Jan Möbius committed
492
  }
Dirk Wilden's avatar
Dirk Wilden committed
493

Dirk Wilden's avatar
Dirk Wilden committed
494
  objectChanged( _object->id() );
Jan Möbius's avatar
 
Jan Möbius committed
495 496
}

Dirk Wilden's avatar
Dirk Wilden committed
497
/** \brief The object with the given id has been deleted. delete it from the internal tree
498
 *
Dirk Wilden's avatar
Dirk Wilden committed
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
 * @param id_ id of the object
 */
void TreeModel::objectDeleted(int _id){

  TreeItem* item = rootItem_->childExists(_id);

  if ( item != 0 && !isRoot(item) ){

    QModelIndex itemIndex   = getModelIndex(item, 0);
    QModelIndex parentIndex = itemIndex.parent();

    beginRemoveRows( parentIndex, itemIndex.row(), itemIndex.row() );

    item->parent()->removeChild(item);
    item->deleteSubtree();

    delete item;

    endRemoveRows();
  }
}

//******************************************************************************

/** \brief move the item to a new parent
524
 *
Dirk Wilden's avatar
Dirk Wilden committed
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
 * @param _item the item
 * @param _parent new parent
 */
void TreeModel::moveItem(TreeItem* _item, TreeItem* _parent ){

  QModelIndex itemIndex   = getModelIndex(_item, 0);
  QModelIndex oldParentIndex = itemIndex.parent();
  QModelIndex newParentIndex = getModelIndex(_parent, 0);

  //delete everything at the old location
  beginRemoveRows( oldParentIndex, itemIndex.row(), itemIndex.row() );

    _item->parent()->removeChild(_item);

  endRemoveRows();

  //insert it at the new location
542
  beginInsertRows(newParentIndex, _parent->childCount(), _parent->childCount() ); //insert at the bottom
Dirk Wilden's avatar
Dirk Wilden committed
543 544 545 546
    _item->setParent( _parent );
    _parent->appendChild( _item );
  endInsertRows();

547
  emit layoutChanged();
Dirk Wilden's avatar
Dirk Wilden committed
548
}
Dirk Wilden's avatar
Dirk Wilden committed
549 550 551 552

//******************************************************************************

/** \brief Return item at given index
553
 *
Dirk Wilden's avatar
Dirk Wilden committed
554 555 556
 * @param index a ModelIndex
 * @return item at given index
 */
Dirk Wilden's avatar
Dirk Wilden committed
557
TreeItem* TreeModel::getItem(const QModelIndex &index) const
Jan Möbius's avatar
 
Jan Möbius committed
558 559
{
    if (index.isValid()) {
Dirk Wilden's avatar
Dirk Wilden committed
560
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
Jan Möbius's avatar
 
Jan Möbius committed
561 562 563 564 565
        if (item) return item;
    }
    return rootItem_;
}

Dirk Wilden's avatar
Dirk Wilden committed
566

Dirk Wilden's avatar
Dirk Wilden committed
567 568 569
//******************************************************************************

/** \brief Return item-name at given index
570
 *
Dirk Wilden's avatar
Dirk Wilden committed
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
 * @param index a ModelIndex
 * @return name of the item at given index
 */
QString TreeModel::itemName(const QModelIndex &index) const
{
    if (index.isValid()) {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item)
          return item->name();
    }
    return "not found";
}

//******************************************************************************

/** \brief Return item-id at given index
587
 *
Dirk Wilden's avatar
Dirk Wilden committed
588 589 590 591 592 593 594 595 596 597 598 599 600
 * @param index a ModelIndex
 * @return item-id at given index
 */
int TreeModel::itemId(const QModelIndex &index) const
{
    if (index.isValid()) {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item)
          return item->id();
    }
    return -1;
}

Dirk Wilden's avatar
Dirk Wilden committed
601 602 603
//******************************************************************************

/** \brief Return index of given item
Dirk Wilden's avatar
Dirk Wilden committed
604 605 606
 *
 * Warning: Only use this function if you know that all ModelIndices are created
 *
Dirk Wilden's avatar
Dirk Wilden committed
607 608 609 610
 * @param _object an object
 * @param _column a column
 * @return index of object and column
 */
Dirk Wilden's avatar
Dirk Wilden committed
611
QModelIndex TreeModel::getModelIndex(TreeItem* _object, int _column ){
612

Dirk Wilden's avatar
Dirk Wilden committed
613 614 615 616 617
  // root item gets an invalid QModelIndex
  if ( _object == rootItem_ )
    return QModelIndex();

  QModelIndex index = createIndex(_object->row(), _column, _object);
618

Dirk Wilden's avatar
Dirk Wilden committed
619
  return index;
620 621 622
}


Dirk Wilden's avatar
Dirk Wilden committed
623 624
//******************************************************************************

Dirk Wilden's avatar
Dirk Wilden committed
625
/** \brief Recursively update a column up to the root of the tree
Dirk Wilden's avatar
Dirk Wilden committed
626 627
 *
 * @param _item item to start with
Dirk Wilden's avatar
Dirk Wilden committed
628
 */
Dirk Wilden's avatar
Dirk Wilden committed
629
void TreeModel::propagateUpwards(TreeItem* _item, int _column, bool _value ){
630

Dirk Wilden's avatar
Dirk Wilden committed
631
  if ( isRoot(_item) || (!_item->isGroup()) )
632 633
    return;

Dirk Wilden's avatar
Dirk Wilden committed
634 635
  if (_column == 1){ //visibility
    _item->visible( _value );
Dirk Wilden's avatar
Dirk Wilden committed
636

Dirk Wilden's avatar
Dirk Wilden committed
637 638 639
    //the whole row has to be updated because of the grey background-color
    QModelIndex index0 = getModelIndex(_item,0);
    QModelIndex index1 = getModelIndex(_item,3);
Dirk Wilden's avatar
Dirk Wilden committed
640

Dirk Wilden's avatar
Dirk Wilden committed
641
    emit dataChanged( index0, index1);
642

Dirk Wilden's avatar
Dirk Wilden committed
643
  } else {
Dirk Wilden's avatar
Dirk Wilden committed
644

Dirk Wilden's avatar
Dirk Wilden committed
645 646
    QModelIndex index = getModelIndex(_item,_column);
    emit dataChanged(index, index);
Dirk Wilden's avatar
Dirk Wilden committed
647 648
  }

Dirk Wilden's avatar
Dirk Wilden committed
649
  propagateUpwards( _item->parent(), _column, _value );
Dirk Wilden's avatar
Dirk Wilden committed
650
}
Dirk Wilden's avatar
Dirk Wilden committed
651 652 653

//******************************************************************************

Dirk Wilden's avatar
Dirk Wilden committed
654
/** \brief Recursively update a column up to the root of the tree
Dirk Wilden's avatar
Dirk Wilden committed
655 656
 *
 * @param _item item to start with
Dirk Wilden's avatar
Dirk Wilden committed
657
 */
Dirk Wilden's avatar
Dirk Wilden committed
658
void TreeModel::propagateDownwards(TreeItem* _item, int _column ){
659

Dirk Wilden's avatar
Dirk Wilden committed
660
  for (int i=0; i < _item->childCount(); i++){
661

Dirk Wilden's avatar
Dirk Wilden committed
662
    TreeItem* current = _item->child(i);
663

Dirk Wilden's avatar
Dirk Wilden committed
664
    bool changed = false;
665

Dirk Wilden's avatar
Dirk Wilden committed
666
    switch ( _column ){
667

Dirk Wilden's avatar
Dirk Wilden committed
668 669
      case 1: //VISIBILTY

Dirk Wilden's avatar
Dirk Wilden committed
670
        if ( current->visible() != _item->visible() ){
Dirk Wilden's avatar
Dirk Wilden committed
671

Dirk Wilden's avatar
Dirk Wilden committed
672
          current->visible( _item->visible() );
Dirk Wilden's avatar
Dirk Wilden committed
673 674 675 676 677
          changed = true;
        }
        break;

      case 2: //SOURCE
678

Dirk Wilden's avatar
Dirk Wilden committed
679
        if ( current->source() != _item->source() ){
Dirk Wilden's avatar
Dirk Wilden committed
680

Dirk Wilden's avatar
Dirk Wilden committed
681
          current->source( _item->source() );
Dirk Wilden's avatar
Dirk Wilden committed
682 683 684 685 686 687
          changed = true;
        }
        break;

      case 3: //TARGET

Dirk Wilden's avatar
Dirk Wilden committed
688
        if ( current->target() != _item->target() ){
Dirk Wilden's avatar
Dirk Wilden committed
689

Dirk Wilden's avatar
Dirk Wilden committed
690
          current->target( _item->target() );
Dirk Wilden's avatar
Dirk Wilden committed
691 692 693 694 695 696 697 698
          changed = true;
        }
        break;

      default:
        break;
    }

Dirk Wilden's avatar
Dirk Wilden committed
699 700 701 702
    if (changed){
      QModelIndex index = getModelIndex(current,_column);
      emit dataChanged(index, index);
    }
Dirk Wilden's avatar
Dirk Wilden committed
703

Dirk Wilden's avatar
Dirk Wilden committed
704 705
    if ( current->isGroup() )
      propagateDownwards(current, _column);
Dirk Wilden's avatar
Dirk Wilden committed
706 707
  }
}
Dirk Wilden's avatar
Dirk Wilden committed
708 709 710 711

//******************************************************************************

/** \brief Set Data at 'index' to 'value'
712
 *
Dirk Wilden's avatar
Dirk Wilden committed
713 714 715 716 717
 * @param index a ModelIndex defining the positin in the model
 * @param value the new value
 * @param  unused
 * @return return if the data was set successfully
 */
Dirk Wilden's avatar
Dirk Wilden committed
718
bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int /*role*/)
Jan Möbius's avatar
 
Jan Möbius committed
719
{
720

Dirk Wilden's avatar
Dirk Wilden committed
721
  emit dataChangedInside( itemId(index), index.column(), value );
Dirk Wilden's avatar
Dirk Wilden committed
722

723
  
Jan Möbius's avatar
 
Jan Möbius committed
724 725 726
  return true;
}

Dirk Wilden's avatar
Dirk Wilden committed
727 728 729 730

//******************************************************************************

/** \brief return if an object is equal to the root object
731
 *
Dirk Wilden's avatar
Dirk Wilden committed
732 733 734
 * @param _item the item to be checked
 * @return is it the root object?
 */
Dirk Wilden's avatar
Dirk Wilden committed
735
bool TreeModel::isRoot(TreeItem * _item) {
736
  return ( _item == rootItem_ );
Jan Möbius's avatar
 
Jan Möbius committed
737 738
}

Dirk Wilden's avatar
Dirk Wilden committed
739 740 741
/*******************************************************************************
        drag & drop stuff
 *******************************************************************************/
742

Dirk Wilden's avatar
Dirk Wilden committed
743
/** \brief return the supported drop actions
744
 *
Dirk Wilden's avatar
Dirk Wilden committed
745 746
 * @return drop actions
 */
747 748 749 750 751
Qt::DropActions TreeModel::supportedDropActions() const
{
    return /*Qt::CopyAction |*/ Qt::MoveAction;
}

Dirk Wilden's avatar
Dirk Wilden committed
752 753 754 755

//******************************************************************************

/** \brief return the mimeType for drag & drop
756
 *
Dirk Wilden's avatar
Dirk Wilden committed
757 758
 * @return the mimeType
 */
759 760 761 762 763 764 765
QStringList TreeModel::mimeTypes() const
{
    QStringList types;
    types << "DataControl/dragDrop";
    return types;
}

Dirk Wilden's avatar
Dirk Wilden committed
766 767 768 769

//******************************************************************************

/** \brief generate mimeData for given ModelIndexes
770
 *
Dirk Wilden's avatar
Dirk Wilden committed
771 772 773
 * @param indexes list of ModelIndexes
 * @return the mimeData
 */
774 775 776 777 778 779 780 781 782 783 784 785 786
QMimeData* TreeModel::mimeData(const QModelIndexList& indexes) const
{
    QMimeData *mimeData = new QMimeData();
    QByteArray encodedData;

    QDataStream stream(&encodedData, QIODevice::WriteOnly);

    QVector< int > rows;

    foreach (QModelIndex index, indexes) {
        if (index.isValid()) {

          if (!rows.contains( index.row() ) ){
Dirk Wilden's avatar
Dirk Wilden committed
787
            TreeItem *item = getItem(index);
788 789 790 791 792 793 794 795 796 797 798
            stream << item->id();

            rows.push_back( index.row() );
          }
        }
    }

    mimeData->setData("DataControl/dragDrop", encodedData);
    return mimeData;
}

Dirk Wilden's avatar
Dirk Wilden committed
799 800 801 802

//******************************************************************************

/** \brief this is called when mimeData is dropped
803
 *
Dirk Wilden's avatar
Dirk Wilden committed
804 805 806
 * @param data the dropped data
 * @param action the definition of the dropAction which occured
 * @param unused
807 808
 * @param unused
 * @param parent parent under which the drop occurred
Dirk Wilden's avatar
Dirk Wilden committed
809 810
 * @return returns if the drop was sucessful
 */
811 812
bool TreeModel::dropMimeData(const QMimeData *data,
     Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex &parent)
Dirk Wilden's avatar
Dirk Wilden committed
813 814 815
{
  if (action == Qt::IgnoreAction)
      return true;
816

Dirk Wilden's avatar
Dirk Wilden committed
817 818
  if (!data->hasFormat("DataControl/dragDrop"))
      return false;
819

Dirk Wilden's avatar
Dirk Wilden committed
820 821
  QByteArray encodedData = data->data("DataControl/dragDrop");
  QDataStream stream(&encodedData, QIODevice::ReadOnly);
822

Dirk Wilden's avatar
Dirk Wilden committed
823
  QVector< int > ids;
824

Dirk Wilden's avatar
Dirk Wilden committed
825 826 827
  while (!stream.atEnd()) {
    int id;
    stream >> id;
828

Dirk Wilden's avatar
Dirk Wilden committed
829 830
    ids.push_back( id );
  }
831

Dirk Wilden's avatar
Dirk Wilden committed
832 833
  if (ids.count() == 0)
    return false;
834

Dirk Wilden's avatar
Dirk Wilden committed
835 836
  //get new parent
  TreeItem *newParent = getItem(parent);
837

Dirk Wilden's avatar
Dirk Wilden committed
838 839 840 841 842 843 844 845
  if ( newParent == 0 || !newParent->isGroup() )
    return false;

  //and move all objects
  for (int i = 0; i < ids.count(); i++){
    //tell the DataControlPlugin to move the corresponding BaseObject
    emit moveBaseObject( ids[i], newParent->id()  );
  }
846

Dirk Wilden's avatar
Dirk Wilden committed
847
  return true;
Dirk Wilden's avatar
Dirk Wilden committed
848

849
 }