void QmitkDataStorageTreeModel::AddNodeInternal(const mitk::DataNode *node)
{
    if(node == 0
      || m_DataStorage.IsNull()
      || !m_DataStorage->Exists(node)
      || !m_Predicate->CheckNode(node)
      || m_Root->Find(node) != 0)
      return;

    // find out if we have a root node
    TreeItem* parentTreeItem = m_Root;
    QModelIndex index;
    mitk::DataNode* parentDataNode = this->GetParentNode(node);

    if(parentDataNode) // no top level data node
    {
      parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item
      if(!parentTreeItem)
      {
        this->AddNode(parentDataNode);
        parentTreeItem = m_Root->Find(parentDataNode);
        if(!parentTreeItem)
          return;
      }

      // get the index of this parent with the help of the grand parent
      index = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem);
    }

    // add node
    if(m_PlaceNewNodesOnTop)
    {
      // emit beginInsertRows event
      beginInsertRows(index, 0, 0);
      parentTreeItem->InsertChild(new TreeItem(
          const_cast<mitk::DataNode*>(node)), 0);
    }
    else
    {
      beginInsertRows(index, parentTreeItem->GetChildCount()
                      , parentTreeItem->GetChildCount());
      new TreeItem(const_cast<mitk::DataNode*>(node), parentTreeItem);
    }

    // emit endInsertRows event
    endInsertRows();

    this->AdjustLayerProperty();
}
void QmitkDataStorageTreeModel::RemoveNodeInternal( const mitk::DataNode* node )
{
    if(!m_Root) return;

    TreeItem* treeItem = m_Root->Find(node);
    if(!treeItem)
      return; // return because there is no treeitem containing this node

    TreeItem* parentTreeItem = treeItem->GetParent();
    QModelIndex parentIndex = this->IndexFromTreeItem(parentTreeItem);

    // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model)
    this->beginRemoveRows(parentIndex, treeItem->GetIndex(), treeItem->GetIndex());

    // remove node
    std::vector<TreeItem*> children = treeItem->GetChildren();
    delete treeItem;

    // emit endRemoveRows event
    endRemoveRows();

    // move all children of deleted node into its parent
    for ( std::vector<TreeItem*>::iterator it = children.begin()
      ; it != children.end(); it++)
    {
      // emit beginInsertRows event
      beginInsertRows(parentIndex, parentTreeItem->GetChildCount(), parentTreeItem->GetChildCount());

      // add nodes again
      parentTreeItem->AddChild(*it);

      // emit endInsertRows event
      endInsertRows();
    }

    this->AdjustLayerProperty();
}
int QmitkDataStorageTreeModel::rowCount(const QModelIndex &parent) const
{
  TreeItem *parentTreeItem = this->TreeItemFromIndex(parent);
  return parentTreeItem->GetChildCount();
}
bool QmitkDataStorageTreeModel::dropMimeData(const QMimeData *data,
                                     Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex &parent)
{
  // Early exit, returning true, but not actually doing anything (ignoring data).
  if (action == Qt::IgnoreAction)
  {
    return true;
  }

  // Note, we are returning true if we handled it, and false otherwise
  bool returnValue = false;

  if(data->hasFormat("application/x-qabstractitemmodeldatalist"))
  {
    returnValue = true;

    // First we extract a Qlist of TreeItem* pointers.
    QString arg = QString(data->data("application/x-qabstractitemmodeldatalist").data());
    QStringList listOfTreeItemAddressPointers = arg.split(",");

    QStringList::iterator slIter;
    QList<TreeItem*> listOfItemsToDrop;

    for(slIter  = listOfTreeItemAddressPointers.begin();
        slIter != listOfTreeItemAddressPointers.end();
        slIter++)
    {
      long val = (*slIter).toLong();
      listOfItemsToDrop << static_cast<TreeItem *>((void*)val);
    }

    // Retrieve the TreeItem* where we are dropping stuff, and its parent.
    TreeItem* dropItem = this->TreeItemFromIndex(parent);
    TreeItem* parentItem = dropItem->GetParent();

    // If item was dropped onto empty space, we select the root node
    if(dropItem == m_Root)
    {
      parentItem = m_Root;
    }

    // Dragging and Dropping is only allowed within the same parent, so use the first item in list to validate.
    // (otherwise, you could have a derived image such as a segmentation, and assign it to another image).
    // NOTE: We are assuming the input list is valid... i.e. when it was dragged, all the items had the same parent.

    if(listOfItemsToDrop[0] != dropItem && listOfItemsToDrop[0]->GetParent() == parentItem)
    {
      // Retrieve the index of where we are dropping stuff.
      QModelIndex dropItemModelIndex = this->IndexFromTreeItem(dropItem);
      QModelIndex parentModelIndex = this->IndexFromTreeItem(parentItem);

      // Iterate through the list of TreeItem (which may be at non-consecutive indexes).
      QList<TreeItem*>::iterator diIter;
      for (diIter  = listOfItemsToDrop.begin();
           diIter != listOfItemsToDrop.end();
           diIter++)
      {
        // Here we assume that as you remove items, one at a time, that GetIndex() will be valid.
        this->beginRemoveRows(parentModelIndex, (*diIter)->GetIndex(), (*diIter)->GetIndex());
        parentItem->RemoveChild(*diIter);
        this->endRemoveRows();
      }

      // Select the target index position, or put it at the end of the list.
      int dropIndex = dropItemModelIndex.row();
      if (dropIndex == -1)
      {
        dropIndex = parentItem->GetChildCount();
      }

      // Now insert items again at the drop item position
      this->beginInsertRows(parentModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1);

      for (diIter  = listOfItemsToDrop.begin();
           diIter != listOfItemsToDrop.end();
           diIter++)
      {
        parentItem->InsertChild( (*diIter), dropIndex );
        dropIndex++;
      }
      this->endInsertRows();

      // Change Layers to match.
      this->AdjustLayerProperty();
    }
  }
  else if(data->hasFormat("application/x-mitk-datanodes"))
  {
    returnValue = true;

    QString arg = QString(data->data("application/x-mitk-datanodes").data());
    QStringList listOfDataNodeAddressPointers = arg.split(",");
    int numberOfNodesDropped = 0;

    QStringList::iterator slIter;
    for (slIter = listOfDataNodeAddressPointers.begin();
         slIter != listOfDataNodeAddressPointers.end();
         slIter++)
    {
      long val = (*slIter).toLong();
      mitk::DataNode* node = static_cast<mitk::DataNode *>((void*)val);

      if(node && m_DataStorage.IsNotNull() && !m_DataStorage->Exists(node))
      {
          m_DataStorage->Add( node );
          mitk::BaseData::Pointer basedata = node->GetData();

          if (basedata.IsNotNull())
          {
            mitk::RenderingManager::GetInstance()->InitializeViews(
              basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );

            numberOfNodesDropped++;
          }
      }
    }
    // Only do a rendering update, if we actually dropped anything.
    if (numberOfNodesDropped > 0)
    {
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    }
  }

  return returnValue;
}
bool QmitkDataStorageTreeModel::dropMimeData(
  const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent)
{
  // Early exit, returning true, but not actually doing anything (ignoring data).
  if (action == Qt::IgnoreAction)
  {
    return true;
  }

  // Note, we are returning true if we handled it, and false otherwise
  bool returnValue = false;

  if (data->hasFormat("application/x-qabstractitemmodeldatalist"))
  {
    returnValue = true;

    // First we extract a Qlist of TreeItem* pointers.
    QList<TreeItem *> listOfItemsToDrop = ToTreeItemPtrList(data);
    if (listOfItemsToDrop.empty())
    {
      return false;
    }

    // Retrieve the TreeItem* where we are dropping stuff, and its parent.
    TreeItem *dropItem = this->TreeItemFromIndex(parent);
    TreeItem *parentItem = dropItem->GetParent();

    // If item was dropped onto empty space, we select the root node
    if (dropItem == m_Root)
    {
      parentItem = m_Root;
    }

    // Dragging and Dropping is only allowed within the same parent, so use the first item in list to validate.
    // (otherwise, you could have a derived image such as a segmentation, and assign it to another image).
    // NOTE: We are assuming the input list is valid... i.e. when it was dragged, all the items had the same parent.

    // Determine whether or not the drag and drop operation is a valid one.
    // Examples of invalid operations include:
    //  - dragging nodes with different parents
    //  - dragging nodes from one parent to another parent, if m_AllowHierarchyChange is false
    //  - dragging a node on one of its child nodes (only relevant if m_AllowHierarchyChange is true)

    bool isValidDragAndDropOperation(true);

    // different parents
    {
      TreeItem *firstParent = listOfItemsToDrop[0]->GetParent();
      QList<TreeItem *>::iterator diIter;
      for (diIter = listOfItemsToDrop.begin() + 1; diIter != listOfItemsToDrop.end(); diIter++)
      {
        if (firstParent != (*diIter)->GetParent())
        {
          isValidDragAndDropOperation = false;
          break;
        }
      }
    }

    // dragging from one parent to another
    if ((!m_AllowHierarchyChange) && isValidDragAndDropOperation)
    {
      if (row == -1) // drag onto a node
      {
        isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == parentItem;
      }
      else // drag between nodes
      {
        isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == dropItem;
      }
    }

    // dragging on a child node of one the dragged nodes
    {
      QList<TreeItem *>::iterator diIter;
      for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++)
      {
        TreeItem *tempItem = dropItem;

        while (tempItem != m_Root)
        {
          tempItem = tempItem->GetParent();
          if (tempItem == *diIter)
          {
            isValidDragAndDropOperation = false;
          }
        }
      }
    }

    if (!isValidDragAndDropOperation)
      return isValidDragAndDropOperation;

    if (listOfItemsToDrop[0] != dropItem && isValidDragAndDropOperation)
    {
      // Retrieve the index of where we are dropping stuff.
      QModelIndex parentModelIndex = this->IndexFromTreeItem(parentItem);

      int dragIndex = 0;

      // Iterate through the list of TreeItem (which may be at non-consecutive indexes).
      QList<TreeItem *>::iterator diIter;
      for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++)
      {
        TreeItem *itemToDrop = *diIter;

        // if the item is dragged down we have to compensate its final position for the
        // fact it is deleted lateron, this only applies if it is dragged within the same level
        if ((itemToDrop->GetIndex() < row) && (itemToDrop->GetParent() == dropItem))
        {
          dragIndex = 1;
        }

        // Here we assume that as you remove items, one at a time, that GetIndex() will be valid.
        this->beginRemoveRows(
          this->IndexFromTreeItem(itemToDrop->GetParent()), itemToDrop->GetIndex(), itemToDrop->GetIndex());
        itemToDrop->GetParent()->RemoveChild(itemToDrop);
        this->endRemoveRows();
      }

      // row = -1 dropped on an item, row != -1 dropped  in between two items
      // Select the target index position, or put it at the end of the list.
      int dropIndex = 0;
      if (row != -1)
      {
        if (dragIndex == 0)
          dropIndex = std::min(row, parentItem->GetChildCount() - 1);
        else
          dropIndex = std::min(row - 1, parentItem->GetChildCount() - 1);
      }
      else
      {
        dropIndex = dropItem->GetIndex();
      }

      QModelIndex dropItemModelIndex = this->IndexFromTreeItem(dropItem);
      if ((row == -1 && dropItemModelIndex.row() == -1) || dropItemModelIndex.row() > parentItem->GetChildCount())
        dropIndex = parentItem->GetChildCount() - 1;

      // Now insert items again at the drop item position

      if (m_AllowHierarchyChange)
      {
        this->beginInsertRows(dropItemModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1);
      }
      else
      {
        this->beginInsertRows(parentModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1);
      }

      for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++)
      {
        // dropped on node, behaviour depends on preference setting
        if (m_AllowHierarchyChange)
        {
          auto dataStorage = m_DataStorage.Lock();

          m_BlockDataStorageEvents = true;
          mitk::DataNode *droppedNode = (*diIter)->GetDataNode();
          mitk::DataNode *dropOntoNode = dropItem->GetDataNode();
          dataStorage->Remove(droppedNode);
          dataStorage->Add(droppedNode, dropOntoNode);
          m_BlockDataStorageEvents = false;

          dropItem->InsertChild((*diIter), dropIndex);
        }
        else
        {
          if (row == -1) // drag onto a node
          {
            parentItem->InsertChild((*diIter), dropIndex);
          }
          else // drag between nodes
          {
            dropItem->InsertChild((*diIter), dropIndex);
          }
        }

        dropIndex++;
      }
      this->endInsertRows();

      // Change Layers to match.
      this->AdjustLayerProperty();
    }
  }
  else if (data->hasFormat("application/x-mitk-datanodes"))
  {
    returnValue = true;

    int numberOfNodesDropped = 0;

    QList<mitk::DataNode *> dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data);
    mitk::DataNode *node = nullptr;
    foreach (node, dataNodeList)
    {
      if (node && !m_DataStorage.IsExpired() && !m_DataStorage.Lock()->Exists(node))
      {
        m_DataStorage.Lock()->Add(node);
        mitk::BaseData::Pointer basedata = node->GetData();

        if (basedata.IsNotNull())
        {
          mitk::RenderingManager::GetInstance()->InitializeViews(
            basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true);

          numberOfNodesDropped++;
        }
      }
    }
    // Only do a rendering update, if we actually dropped anything.
    if (numberOfNodesDropped > 0)
    {
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    }
  }