diff --git a/Modules/QtWidgets/QmitkDataStorageTableModel.cpp b/Modules/QtWidgets/QmitkDataStorageTableModel.cpp index ad852bb6fb..dbedb4b827 100644 --- a/Modules/QtWidgets/QmitkDataStorageTableModel.cpp +++ b/Modules/QtWidgets/QmitkDataStorageTableModel.cpp @@ -1,524 +1,525 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkDataStorageTableModel.h" //# Own includes #include "mitkNodePredicateBase.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "QmitkEnums.h" #include "QmitkCustomVariants.h" #include //# Toolkit includes #include #include +#include //#CTORS/DTOR QmitkDataStorageTableModel::QmitkDataStorageTableModel(mitk::DataStorage::Pointer _DataStorage , mitk::NodePredicateBase* _Predicate , QObject* parent ) : QAbstractTableModel(parent) , m_DataStorage(0) , m_Predicate(0) , m_BlockEvents(false) , m_SortDescending(false) { this->SetPredicate(_Predicate); this->SetDataStorage(_DataStorage); } QmitkDataStorageTableModel::~QmitkDataStorageTableModel() { // set data storage 0 to remove event listeners this->SetDataStorage(0); } //# Public GETTER const mitk::DataStorage::Pointer QmitkDataStorageTableModel::GetDataStorage() const { return m_DataStorage.GetPointer(); } mitk::NodePredicateBase::Pointer QmitkDataStorageTableModel::GetPredicate() const { return m_Predicate; } mitk::DataNode::Pointer QmitkDataStorageTableModel::GetNode( const QModelIndex &index ) const { mitk::DataNode::Pointer node; if(index.isValid()) { node = m_NodeSet.at(index.row()); } return node; } QVariant QmitkDataStorageTableModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant headerData; // show only horizontal header if ( role == Qt::DisplayRole ) { if( orientation == Qt::Horizontal ) { // first column: "Name" if(section == 0) headerData = "Name"; else if(section == 1) headerData = "Data Type"; else if(section == 2) headerData = "Visibility"; } else if( orientation == Qt::Vertical ) { // show numbers for rows headerData = section+1; } } return headerData; } Qt::ItemFlags QmitkDataStorageTableModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); // name & visibility is editable if (index.column() == 0) { flags |= Qt::ItemIsEditable; } else if (index.column() == 2) { flags |= Qt::ItemIsUserCheckable; } return flags; } int QmitkDataStorageTableModel::rowCount(const QModelIndex &) const { return m_NodeSet.size(); } int QmitkDataStorageTableModel::columnCount(const QModelIndex &) const { // show name, type and visible columnn int columns = 3; return columns; } QVariant QmitkDataStorageTableModel::data(const QModelIndex &index, int role) const { QVariant data; if (index.isValid() && !m_NodeSet.empty()) { mitk::DataNode::Pointer node = m_NodeSet.at(index.row()); std::string nodeName = node->GetName(); if(nodeName.empty()) nodeName = "unnamed"; // get name if(index.column() == 0) { // get name of node (may also be edited) if (role == Qt::DisplayRole || role == Qt::EditRole) { - data = nodeName.c_str(); + data = QFile::encodeName(nodeName.c_str()); } else if (role == QmitkDataNodeRole) { data = QVariant::fromValue(node); } } else if (index.column() == 1) { QmitkNodeDescriptor* nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(node); // get type property of mitk::BaseData if (role == Qt::DisplayRole) { data = nodeDescriptor->GetClassName(); } // show some nice icons for datatype else if(role == Qt::DecorationRole) { data = nodeDescriptor->GetIcon(); } } else if (index.column() == 2) { // get visible property of mitk::BaseData bool visibility = false; if(node->GetVisibility(visibility, 0) && role == Qt::CheckStateRole) { data = (visibility ? Qt::Checked : Qt::Unchecked); } // node->GetVisibility(visibility, 0) && role == Qt::CheckStateRole } // index.column() == 2 } // index.isValid() && !m_NodeSet.empty() return data; } //# Public SETTERS void QmitkDataStorageTableModel::SetPredicate( mitk::NodePredicateBase* _Predicate ) { // ensure that a new predicate is set in order to avoid unnecessary changed events if(m_Predicate != _Predicate) { m_Predicate = _Predicate; this->Reset(); } } void QmitkDataStorageTableModel::SetDataStorage( mitk::DataStorage::Pointer _DataStorage ) { // only proceed if we have a new datastorage if(m_DataStorage.GetPointer() != _DataStorage.GetPointer()) { // if a data storage was set before remove old event listeners if(m_DataStorage.IsNotNull()) { this->m_DataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::AddNode ) ); this->m_DataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::RemoveNode ) ); } // set new data storage m_DataStorage = _DataStorage.GetPointer(); // if new storage is not 0 subscribe for events if(m_DataStorage.IsNotNull()) { // subscribe for node added/removed events this->m_DataStorage->AddNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::AddNode ) ); this->m_DataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::RemoveNode ) ); } // Reset model (even if datastorage is 0->will be checked in Reset()) this->Reset(); } } void QmitkDataStorageTableModel::AddNode( const mitk::DataNode* node ) { // garantuee no recursions when a new node event is thrown if(!m_BlockEvents) { // if we have a predicate, check node against predicate first if(m_Predicate.IsNotNull() && !m_Predicate->CheckNode(node)) return; // dont add nodes without data (formerly known as helper objects) if(node->GetData() == 0) return; // create listener commands to listen to changes in the name or the visibility of the node itk::MemberCommand::Pointer propertyModifiedCommand = itk::MemberCommand::New(); propertyModifiedCommand->SetCallbackFunction(this, &QmitkDataStorageTableModel::PropertyModified); mitk::BaseProperty* tempProperty = 0; // add listener for properties tempProperty = node->GetProperty("visible"); if(tempProperty) m_VisiblePropertyModifiedObserverTags[tempProperty] = tempProperty->AddObserver(itk::ModifiedEvent(), propertyModifiedCommand); tempProperty = node->GetProperty("name"); if(tempProperty) m_NamePropertyModifiedObserverTags[tempProperty] = tempProperty->AddObserver(itk::ModifiedEvent(), propertyModifiedCommand); // emit beginInsertRows event beginInsertRows(QModelIndex(), m_NodeSet.size(), m_NodeSet.size()); // add node m_NodeSet.push_back(const_cast(node)); // emit endInsertRows event endInsertRows(); } } void QmitkDataStorageTableModel::RemoveNode( const mitk::DataNode* node ) { // garantuee no recursions when a new node event is thrown if(!m_BlockEvents) { // find corresponding node std::vector::iterator nodeIt = std::find(m_NodeSet.begin(), m_NodeSet.end(), node); if(nodeIt != m_NodeSet.end()) { // now: remove listeners for name property ... mitk::BaseProperty* tempProperty = 0; tempProperty = (*nodeIt)->GetProperty("visible"); if(tempProperty) tempProperty->RemoveObserver(m_VisiblePropertyModifiedObserverTags[tempProperty]); m_VisiblePropertyModifiedObserverTags.erase(tempProperty); // ... and visibility property tempProperty = (*nodeIt)->GetProperty("name"); if(tempProperty) tempProperty->RemoveObserver(m_NamePropertyModifiedObserverTags[tempProperty]); m_NamePropertyModifiedObserverTags.erase(tempProperty); // get an index from iterator int row = std::distance(m_NodeSet.begin(), nodeIt); // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model) this->beginRemoveRows(QModelIndex(), row, row); // remove node m_NodeSet.erase(nodeIt); // emit endRemoveRows event endRemoveRows(); } } } void QmitkDataStorageTableModel::PropertyModified( const itk::Object *caller, const itk::EventObject & ) { if(!m_BlockEvents) { // get modified property const mitk::BaseProperty* modifiedProperty = dynamic_cast(caller); if(modifiedProperty) { // find node that holds the modified property int row = -1; int column = -1; std::vector::iterator it; mitk::BaseProperty* visibilityProperty = 0; mitk::BaseProperty* nameProperty = 0; // search for property that changed and emit datachanged on the corresponding ModelIndex for(it=m_NodeSet.begin(); it!=m_NodeSet.end(); it++) { // check for the visible property or the name property visibilityProperty = (*it)->GetProperty("visible"); if(modifiedProperty == visibilityProperty) { column = 2; break; } nameProperty = (*it)->GetProperty("name"); if(modifiedProperty == nameProperty) { column = 0; break; } } // if we have the property we have a valid iterator if( it != m_NodeSet.end() ) row = std::distance(m_NodeSet.begin(), it); // now emit the dataChanged signal QModelIndex indexOfChangedProperty = index(row, column); emit dataChanged(indexOfChangedProperty, indexOfChangedProperty); } } } bool QmitkDataStorageTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { bool noErr = false; if (index.isValid() && (role == Qt::EditRole || role == Qt::CheckStateRole)) { // any change events produced here should not be caught in this class // --> set m_BlockEvents to true m_BlockEvents = true; mitk::DataNode::Pointer node = m_NodeSet.at(index.row()); if(index.column() == 0) { node->SetStringProperty("name", value.toString().toStdString().c_str()); } else if(index.column() == 2) { node->SetBoolProperty("visible", (value.toInt() == Qt::Checked ? true : false)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } // inform listeners about changes emit dataChanged(index, index); m_BlockEvents = false; noErr = true; } return noErr; } //#Protected SETTER void QmitkDataStorageTableModel::Reset() { mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet; // remove all nodes now (dont use iterators because removing elements // would invalidate the iterator) // start at the last element: first in, last out unsigned int i = m_NodeSet.size(); while(!m_NodeSet.empty()) { --i; this->RemoveNode(m_NodeSet.at(i)); } // normally now everything should be empty->just to be sure // erase all arrays again m_NamePropertyModifiedObserverTags.clear(); m_VisiblePropertyModifiedObserverTags.clear(); m_NodeSet.clear(); // the whole reset depends on the fact if a data storage is set or not if(m_DataStorage.IsNotNull()) { if(m_Predicate.IsNotNull()) // get subset _NodeSet = m_DataStorage->GetSubset(m_Predicate); // if predicate is NULL, select all nodes else { _NodeSet = m_DataStorage->GetAll(); // remove ghost root node } // finally add all nodes to the model for(mitk::DataStorage::SetOfObjects::const_iterator it=_NodeSet->begin(); it!=_NodeSet->end() ; it++) { // save node this->AddNode(*it); } } } void QmitkDataStorageTableModel::sort( int column, Qt::SortOrder order /*= Qt::AscendingOrder */ ) { bool sortDescending = (order == Qt::DescendingOrder) ? true: false; // do not sort twice !!! (dont know why, but qt calls this func twice. STUPID!) /* if(sortDescending != m_SortDescending) {*/ //m_SortDescending = sortDescending; DataNodeCompareFunction::CompareCriteria _CompareCriteria = DataNodeCompareFunction::CompareByName; DataNodeCompareFunction::CompareOperator _CompareOperator = sortDescending ? DataNodeCompareFunction::Greater: DataNodeCompareFunction::Less; if(column == 1) _CompareCriteria = DataNodeCompareFunction::CompareByClassName; else if(column == 2) _CompareCriteria = DataNodeCompareFunction::CompareByVisibility; DataNodeCompareFunction compareFunc(_CompareCriteria, _CompareOperator); std::sort(m_NodeSet.begin(), m_NodeSet.end(), compareFunc); QAbstractTableModel::reset(); //} } std::vector QmitkDataStorageTableModel::GetNodeSet() const { return m_NodeSet; } QmitkDataStorageTableModel::DataNodeCompareFunction::DataNodeCompareFunction( CompareCriteria _CompareCriteria , CompareOperator _CompareOperator ) : m_CompareCriteria(_CompareCriteria) , m_CompareOperator(_CompareOperator) { } bool QmitkDataStorageTableModel::DataNodeCompareFunction::operator() ( const mitk::DataNode::Pointer& _Left , const mitk::DataNode::Pointer& _Right ) const { switch(m_CompareCriteria) { case CompareByClassName: if(m_CompareOperator == Less) return (_Left->GetData()->GetNameOfClass() < _Right->GetData()->GetNameOfClass() ); else return (_Left->GetData()->GetNameOfClass() > _Right->GetData()->GetNameOfClass() ); break; case CompareByVisibility: { bool _LeftVisibility = false; bool _RightVisibility = false; _Left->GetVisibility(_LeftVisibility, 0); _Right->GetVisibility(_RightVisibility, 0); if(m_CompareOperator == Less) return (_LeftVisibility < _RightVisibility); else return (_LeftVisibility > _RightVisibility); } break; // CompareByName: default: if(m_CompareOperator == Less) return (_Left->GetName() < _Right->GetName()); else return (_Left->GetName() > _Right->GetName()); break; } } diff --git a/Modules/QtWidgets/QmitkDataStorageTreeModel.cpp b/Modules/QtWidgets/QmitkDataStorageTreeModel.cpp index 3f129ce411..e5c540b57a 100644 --- a/Modules/QtWidgets/QmitkDataStorageTreeModel.cpp +++ b/Modules/QtWidgets/QmitkDataStorageTreeModel.cpp @@ -1,855 +1,858 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include "QmitkDataStorageTreeModel.h" #include "QmitkNodeDescriptorManager.h" #include #include #include #include #include #include +#include #include QmitkDataStorageTreeModel::QmitkDataStorageTreeModel( mitk::DataStorage* _DataStorage , bool _PlaceNewNodesOnTop , QObject* parent ) : QAbstractItemModel(parent) , m_DataStorage(0) , m_PlaceNewNodesOnTop(_PlaceNewNodesOnTop) , m_Root(0) { this->SetDataStorage(_DataStorage); } QmitkDataStorageTreeModel::~QmitkDataStorageTreeModel() { // set data storage to 0 = remove all listeners this->SetDataStorage(0); m_Root->Delete(); m_Root = 0; } mitk::DataNode::Pointer QmitkDataStorageTreeModel::GetNode( const QModelIndex &index ) const { return this->TreeItemFromIndex(index)->GetDataNode(); } const mitk::DataStorage::Pointer QmitkDataStorageTreeModel::GetDataStorage() const { return m_DataStorage.GetPointer(); } QModelIndex QmitkDataStorageTreeModel::index( int row, int column, const QModelIndex & parent ) const { TreeItem* parentItem; if (!parent.isValid()) parentItem = m_Root; else parentItem = static_cast(parent.internalPointer()); TreeItem *childItem = parentItem->GetChild(row); if (childItem) return createIndex(row, column, childItem); else return QModelIndex(); } int QmitkDataStorageTreeModel::rowCount(const QModelIndex &parent) const { TreeItem *parentTreeItem = this->TreeItemFromIndex(parent); return parentTreeItem->GetChildCount(); } Qt::ItemFlags QmitkDataStorageTreeModel::flags( const QModelIndex& index ) const { mitk::DataNode* dataNode = this->TreeItemFromIndex(index)->GetDataNode(); if (index.isValid()) { if(DicomPropertiesExists(*dataNode)) { return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; }else{ return Qt::ItemIsDropEnabled; } } int QmitkDataStorageTreeModel::columnCount( const QModelIndex& /* parent = QModelIndex() */ ) const { return 1; } QModelIndex QmitkDataStorageTreeModel::parent(const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); TreeItem *childItem = this->TreeItemFromIndex(index); TreeItem *parentItem = childItem->GetParent(); if (parentItem == m_Root) return QModelIndex(); return this->createIndex(parentItem->GetIndex(), 0, parentItem); } QmitkDataStorageTreeModel::TreeItem* QmitkDataStorageTreeModel::TreeItemFromIndex( const QModelIndex &index ) const { if (index.isValid()) return static_cast(index.internalPointer()); else return m_Root; } Qt::DropActions QmitkDataStorageTreeModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions QmitkDataStorageTreeModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } 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 listOfItemsToDrop = ToTreeItemPtrList(data); // 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::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; int numberOfNodesDropped = 0; QList dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data); mitk::DataNode* node = NULL; foreach(node, dataNodeList) { 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->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(); } } return returnValue; } QStringList QmitkDataStorageTreeModel::mimeTypes() const { QStringList types = QAbstractItemModel::mimeTypes(); types << "application/x-qabstractitemmodeldatalist"; types << "application/x-mitk-datanodes"; return types; } QMimeData * QmitkDataStorageTreeModel::mimeData(const QModelIndexList & indexes) const { return mimeDataFromModelIndexList(indexes); } QMimeData *QmitkDataStorageTreeModel::mimeDataFromModelIndexList(const QModelIndexList &indexes) { QMimeData * ret = new QMimeData; QString treeItemAddresses(""); QString dataNodeAddresses(""); QByteArray baTreeItemPtrs; QByteArray baDataNodePtrs; QDataStream dsTreeItemPtrs(&baTreeItemPtrs, QIODevice::WriteOnly); QDataStream dsDataNodePtrs(&baDataNodePtrs, QIODevice::WriteOnly); for (int i = 0; i < indexes.size(); i++) { TreeItem* treeItem = static_cast(indexes.at(i).internalPointer()); dsTreeItemPtrs << reinterpret_cast(treeItem); dsDataNodePtrs << reinterpret_cast(treeItem->GetDataNode().GetPointer()); // --------------- deprecated ----------------- unsigned long long treeItemAddress = reinterpret_cast(treeItem); unsigned long long dataNodeAddress = reinterpret_cast(treeItem->GetDataNode().GetPointer()); QTextStream(&treeItemAddresses) << treeItemAddress; QTextStream(&dataNodeAddresses) << dataNodeAddress; if (i != indexes.size() - 1) { QTextStream(&treeItemAddresses) << ","; QTextStream(&dataNodeAddresses) << ","; } // -------------- end deprecated ------------- } // ------------------ deprecated ----------------- ret->setData("application/x-qabstractitemmodeldatalist", QByteArray(treeItemAddresses.toAscii())); ret->setData("application/x-mitk-datanodes", QByteArray(dataNodeAddresses.toAscii())); // --------------- end deprecated ----------------- ret->setData(QmitkMimeTypes::DataStorageTreeItemPtrs, baTreeItemPtrs); ret->setData(QmitkMimeTypes::DataNodePtrs, baDataNodePtrs); return ret; } QVariant QmitkDataStorageTreeModel::data( const QModelIndex & index, int role ) const { mitk::DataNode* dataNode = this->TreeItemFromIndex(index)->GetDataNode(); // get name of treeItem (may also be edited) QString nodeName; if(DicomPropertiesExists(*dataNode)) { mitk::BaseProperty* seriesDescription = (dataNode->GetProperty("dicom.series.SeriesDescription")); mitk::BaseProperty* studyDescription = (dataNode->GetProperty("dicom.study.StudyDescription")); mitk::BaseProperty* patientsName = (dataNode->GetProperty("dicom.patient.PatientsName")); - nodeName.append(patientsName->GetValueAsString().c_str()).append("\n"); - nodeName.append(studyDescription->GetValueAsString().c_str()).append("\n"); - nodeName.append(seriesDescription->GetValueAsString().c_str()); - }else{ - nodeName = QString::fromStdString(dataNode->GetName()); + nodeName += QFile::encodeName(patientsName->GetValueAsString().c_str()) + "\n"; + nodeName += QFile::encodeName(studyDescription->GetValueAsString().c_str()) + "\n"; + nodeName += QFile::encodeName(seriesDescription->GetValueAsString().c_str()); + } + else + { + nodeName = QFile::encodeName(dataNode->GetName().c_str()); } if(nodeName.isEmpty()) { nodeName = "unnamed"; } if (role == Qt::DisplayRole) return nodeName; else if(role == Qt::ToolTipRole) return nodeName; else if(role == Qt::DecorationRole) { QmitkNodeDescriptor* nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(dataNode); return nodeDescriptor->GetIcon(); } else if(role == Qt::CheckStateRole) { return dataNode->IsVisible(0); } else if(role == QmitkDataNodeRole) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } else if(role == QmitkDataNodeRawPointerRole) { return QVariant::fromValue(dataNode); } return QVariant(); } bool QmitkDataStorageTreeModel::DicomPropertiesExists(const mitk::DataNode& node) const { bool propertiesExists = false; mitk::BaseProperty* seriesDescription = (node.GetProperty("dicom.series.SeriesDescription")); mitk::BaseProperty* studyDescription = (node.GetProperty("dicom.study.StudyDescription")); mitk::BaseProperty* patientsName = (node.GetProperty("dicom.patient.PatientsName")); if(patientsName!=NULL && studyDescription!=NULL && seriesDescription!=NULL) { if((!patientsName->GetValueAsString().empty())&& (!studyDescription->GetValueAsString().empty())&& (!seriesDescription->GetValueAsString().empty())) { propertiesExists = true; } } return propertiesExists; } QVariant QmitkDataStorageTreeModel::headerData(int /*section*/, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_Root) return QString::fromStdString(m_Root->GetDataNode()->GetName()); return QVariant(); } void QmitkDataStorageTreeModel::SetDataStorage( mitk::DataStorage* _DataStorage ) { if(m_DataStorage != _DataStorage) // dont take the same again { if(m_DataStorage.IsNotNull()) { // remove Listener for the data storage itself m_DataStorage.ObjectDelete.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetDataStorageDeleted ) ); // remove listeners for the nodes m_DataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::AddNode ) ); m_DataStorage->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetNodeModified ) ); m_DataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::RemoveNode ) ); } // take over the new data storage m_DataStorage = _DataStorage; // delete the old root (if necessary, create new) if(m_Root) m_Root->Delete(); mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Manager"); m_Root = new TreeItem(rootDataNode, 0); this->reset(); if(m_DataStorage.IsNotNull()) { // add Listener for the data storage itself m_DataStorage.ObjectDelete.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetDataStorageDeleted ) ); // add listeners for the nodes m_DataStorage->AddNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::AddNode ) ); m_DataStorage->ChangedNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetNodeModified ) ); m_DataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::RemoveNode ) ); mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = m_DataStorage->GetSubset(m_Predicate); // finally add all nodes to the model this->Update(); } } } void QmitkDataStorageTreeModel::SetDataStorageDeleted( const itk::Object* /*_DataStorage*/ ) { this->SetDataStorage(0); } void QmitkDataStorageTreeModel::AddNodeInternal(const mitk::DataNode *node) { if(node == 0 || m_DataStorage.IsNull() || !m_DataStorage->Exists(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(node)), 0); } else { beginInsertRows(index, parentTreeItem->GetChildCount() , parentTreeItem->GetChildCount()); new TreeItem(const_cast(node), parentTreeItem); } // emit endInsertRows event endInsertRows(); this->AdjustLayerProperty(); } void QmitkDataStorageTreeModel::AddNode( const mitk::DataNode* node ) { if(node == 0 || m_DataStorage.IsNull() || !m_DataStorage->Exists(node) || m_Root->Find(node) != 0) return; this->AddNodeInternal(node); } void QmitkDataStorageTreeModel::SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop) { m_PlaceNewNodesOnTop = _PlaceNewNodesOnTop; } 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 children = treeItem->GetChildren(); delete treeItem; // emit endRemoveRows event endRemoveRows(); // move all children of deleted node into its parent for ( std::vector::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(); } void QmitkDataStorageTreeModel::RemoveNode( const mitk::DataNode* node ) { if (node == 0) return; this->RemoveNodeInternal(node); } void QmitkDataStorageTreeModel::SetNodeModified( const mitk::DataNode* node ) { TreeItem* treeItem = m_Root->Find(node); if(treeItem) { TreeItem* parentTreeItem = treeItem->GetParent(); // as the root node should not be removed one should always have a parent item if(!parentTreeItem) return; QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem); // now emit the dataChanged signal emit dataChanged(index, index); } } mitk::DataNode* QmitkDataStorageTreeModel::GetParentNode( const mitk::DataNode* node ) const { mitk::DataNode* dataNode = 0; mitk::DataStorage::SetOfObjects::ConstPointer _Sources = m_DataStorage->GetSources(node); if(_Sources->Size() > 0) dataNode = _Sources->front(); return dataNode; } bool QmitkDataStorageTreeModel::setData( const QModelIndex &index, const QVariant &value, int role ) { mitk::DataNode* dataNode = this->TreeItemFromIndex(index)->GetDataNode(); if(!dataNode) return false; if(role == Qt::EditRole && !value.toString().isEmpty()) { dataNode->SetStringProperty("name", value.toString().toStdString().c_str()); mitk::PlanarFigure* planarFigure = dynamic_cast(dataNode->GetData()); if (planarFigure != NULL) mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if(role == Qt::CheckStateRole) { // Please note: value.toInt() returns 2, independentely from the actual checkstate of the index element. // Therefore the checkstate is being estimated again here. QVariant qcheckstate = index.data(Qt::CheckStateRole); int checkstate = qcheckstate.toInt(); bool isVisible = bool(checkstate); dataNode->SetVisibility(!isVisible); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } // inform listeners about changes emit dataChanged(index, index); return true; } bool QmitkDataStorageTreeModel::setHeaderData( int /*section*/, Qt::Orientation /*orientation*/, const QVariant& /* value */, int /*role = Qt::EditRole*/ ) { return false; } void QmitkDataStorageTreeModel::AdjustLayerProperty() { /// transform the tree into an array and set the layer property descending std::vector vec; this->TreeToVector(m_Root, vec); int i = vec.size()-1; for(std::vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { mitk::DataNode::Pointer dataNode = (*it)->GetDataNode(); bool fixedLayer = false; if (!(dataNode->GetBoolProperty("fixedLayer", fixedLayer) && fixedLayer)) dataNode->SetIntProperty("layer", i); --i; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataStorageTreeModel::TreeToVector(TreeItem* parent, std::vector& vec) const { TreeItem* current; for(int i = 0; iGetChildCount(); ++i) { current = parent->GetChild(i); this->TreeToVector(current, vec); vec.push_back(current); } } QModelIndex QmitkDataStorageTreeModel::IndexFromTreeItem( TreeItem* item ) const { if(item == m_Root) return QModelIndex(); else return this->createIndex(item->GetIndex(), 0, item); } QList QmitkDataStorageTreeModel::GetNodeSet() const { QList res; if(m_Root) this->TreeToNodeSet(m_Root, res); return res; } void QmitkDataStorageTreeModel::TreeToNodeSet( TreeItem* parent, QList& vec ) const { TreeItem* current; for(int i = 0; iGetChildCount(); ++i) { current = parent->GetChild(i); vec.push_back(current->GetDataNode()); this->TreeToNodeSet(current, vec); } } QModelIndex QmitkDataStorageTreeModel::GetIndex( const mitk::DataNode* node ) const { if(m_Root) { TreeItem* item = m_Root->Find(node); if(item) return this->IndexFromTreeItem(item); } return QModelIndex(); } QList QmitkDataStorageTreeModel::ToTreeItemPtrList(const QMimeData* mimeData) { if (mimeData == NULL || !mimeData->hasFormat(QmitkMimeTypes::DataStorageTreeItemPtrs)) { return QList(); } return ToTreeItemPtrList(mimeData->data(QmitkMimeTypes::DataStorageTreeItemPtrs)); } QList QmitkDataStorageTreeModel::ToTreeItemPtrList(const QByteArray& ba) { QList result; QDataStream ds(ba); while(!ds.atEnd()) { quintptr treeItemPtr; ds >> treeItemPtr; result.push_back(reinterpret_cast(treeItemPtr)); } return result; } QmitkDataStorageTreeModel::TreeItem::TreeItem( mitk::DataNode* _DataNode, TreeItem* _Parent ) : m_Parent(_Parent) , m_DataNode(_DataNode) { if(m_Parent) m_Parent->AddChild(this); } QmitkDataStorageTreeModel::TreeItem::~TreeItem() { if(m_Parent) m_Parent->RemoveChild(this); } void QmitkDataStorageTreeModel::TreeItem::Delete() { while(m_Children.size() > 0) delete m_Children.back(); delete this; } QmitkDataStorageTreeModel::TreeItem* QmitkDataStorageTreeModel::TreeItem::Find( const mitk::DataNode* _DataNode ) const { QmitkDataStorageTreeModel::TreeItem* item = 0; if(_DataNode) { if(m_DataNode == _DataNode) item = const_cast(this); else { for(std::vector::const_iterator it = m_Children.begin(); it != m_Children.end(); ++it) { if(item) break; item = (*it)->Find(_DataNode); } } } return item; } int QmitkDataStorageTreeModel::TreeItem::IndexOfChild( const TreeItem* item ) const { std::vector::const_iterator it = std::find(m_Children.begin(), m_Children.end(), item); return it != m_Children.end() ? std::distance(m_Children.begin(), it): -1; } QmitkDataStorageTreeModel::TreeItem* QmitkDataStorageTreeModel::TreeItem::GetChild( int index ) const { return (m_Children.size() > 0 && index >= 0 && index < (int)m_Children.size())? m_Children.at(index): 0; } void QmitkDataStorageTreeModel::TreeItem::AddChild( TreeItem* item ) { this->InsertChild(item); } void QmitkDataStorageTreeModel::TreeItem::RemoveChild( TreeItem* item ) { std::vector::iterator it = std::find(m_Children.begin(), m_Children.end(), item); if(it != m_Children.end()) { m_Children.erase(it); item->SetParent(0); } } int QmitkDataStorageTreeModel::TreeItem::GetChildCount() const { return m_Children.size(); } int QmitkDataStorageTreeModel::TreeItem::GetIndex() const { if (m_Parent) return m_Parent->IndexOfChild(this); return 0; } QmitkDataStorageTreeModel::TreeItem* QmitkDataStorageTreeModel::TreeItem::GetParent() const { return m_Parent; } mitk::DataNode::Pointer QmitkDataStorageTreeModel::TreeItem::GetDataNode() const { return m_DataNode; } void QmitkDataStorageTreeModel::TreeItem::InsertChild( TreeItem* item, int index ) { std::vector::iterator it = std::find(m_Children.begin(), m_Children.end(), item); if(it == m_Children.end()) { if(m_Children.size() > 0 && index >= 0 && index < (int)m_Children.size()) { it = m_Children.begin(); std::advance(it, index); m_Children.insert(it, item); } else m_Children.push_back(item); // add parent if necessary if(item->GetParent() != this) item->SetParent(this); } } std::vector QmitkDataStorageTreeModel::TreeItem::GetChildren() const { return m_Children; } void QmitkDataStorageTreeModel::TreeItem::SetParent( TreeItem* _Parent ) { m_Parent = _Parent; if(m_Parent) m_Parent->AddChild(this); } void QmitkDataStorageTreeModel::Update() { if (m_DataStorage.IsNotNull()) { this->reset(); mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = m_DataStorage->GetAll(); for (mitk::DataStorage::SetOfObjects::const_iterator it = _NodeSet->begin(); it != _NodeSet->end(); it++) { // save node this->AddNodeInternal(*it); } } }