diff --git a/CoreUI/Qmitk/QmitkDataStorageTreeModel.cpp b/CoreUI/Qmitk/QmitkDataStorageTreeModel.cpp index a26d1ef2d6..36b1ac5899 100644 --- a/CoreUI/Qmitk/QmitkDataStorageTreeModel.cpp +++ b/CoreUI/Qmitk/QmitkDataStorageTreeModel.cpp @@ -1,713 +1,746 @@ /*========================================================================= Program: MITK Language: C++ Date: $Date: 2008-08-13 16:56:36 +0200 (Mi, 13 Aug 2008) $ Version: $Revision: 14972 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include #include #include #include +#include #include #include #include #include "QmitkDataStorageTreeModel.h" #include "QmitkNodeDescriptorManager.h" #include #include #include #include #include QmitkDataStorageTreeModel::QmitkDataStorageTreeModel( mitk::DataStorage* _DataStorage , bool _PlaceNewNodesOnTop , bool _ShowHelperObjects + , bool _ShowNodesContainingNoData , QObject* parent ) : QAbstractItemModel(parent) , m_DataStorage(0) , m_PlaceNewNodesOnTop(_PlaceNewNodesOnTop) , m_Root(0) { this->SetShowHelperObjects( _ShowHelperObjects ); + this->SetShowNodesContainingNoData( _ShowNodesContainingNoData ); 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 { if (index.isValid()) 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) { if (action == Qt::IgnoreAction) return true; if(data->hasFormat("application/x-qabstractitemmodeldatalist")) { QString arg = QString(data->data("application/x-qabstractitemmodeldatalist").data()); long val = arg.toLong(); TreeItem* draggedItem = static_cast((void*)val); TreeItem* dropItem = this->TreeItemFromIndex(parent); TreeItem* parentItem = dropItem->GetParent(); if(dropItem == m_Root) // item was dropped onto empty space parentItem = m_Root; if(draggedItem != dropItem && draggedItem->GetParent() == parentItem) // dragging is only allowed within the same parent { QModelIndex parentModelIndex = this->IndexFromTreeItem(parentItem); // remove dragged item this->beginRemoveRows(parentModelIndex, draggedItem->GetIndex(), draggedItem->GetIndex()); parentItem->RemoveChild(draggedItem); endRemoveRows(); // now insert it again at the drop item position int index = parentItem->IndexOfChild(dropItem); if(dropItem == m_Root) index = parentItem->GetChildCount(); beginInsertRows(parentModelIndex, index, index); // add node parentItem->InsertChild( draggedItem, index ); // emit endInsertRows event endInsertRows(); this->AdjustLayerProperty(); } } else if(data->hasFormat("application/x-mitk-datanode")) { QString arg = QString(data->data("application/x-mitk-datanode").data()); long val = arg.toLong(); mitk::DataNode* node = static_cast((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 ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } return false; } QStringList QmitkDataStorageTreeModel::mimeTypes() const { QStringList types = QAbstractItemModel::mimeTypes(); types << "application/x-mitk-datanode"; return types; } QMimeData * QmitkDataStorageTreeModel::mimeData(const QModelIndexList & indexes) const{ QMimeData * ret = new QMimeData; TreeItem* treeItem = static_cast(indexes.at(0).internalPointer()); long a = reinterpret_cast(treeItem); long b = reinterpret_cast(treeItem->GetDataNode().GetPointer()); QString result; QString result2; QTextStream(&result) << a; QTextStream(&result2) << b; ret->setData("application/x-mitk-datanode", QByteArray(result2.toAscii())); ret->setData("application/x-qabstractitemmodeldatalist", QByteArray(result.toAscii())); 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 = QString::fromStdString(dataNode->GetName()); 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)); } return QVariant(); } 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::AddNode( 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(node)), 0); } else { beginInsertRows(index, parentTreeItem->GetChildCount() , parentTreeItem->GetChildCount()); new TreeItem(const_cast(node), parentTreeItem); } // emit endInsertRows event endInsertRows(); this->AdjustLayerProperty(); } void QmitkDataStorageTreeModel::SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop) { m_PlaceNewNodesOnTop = _PlaceNewNodesOnTop; } void QmitkDataStorageTreeModel::RemoveNode( 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::SetNodeModified( const mitk::DataNode* node ) { TreeItem* treeItem = m_Root->Find(node); if(!treeItem) return; 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()); } 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) { (*it)->GetDataNode()->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); } std::vector QmitkDataStorageTreeModel::GetNodeSet() const { std::vector vec; if(m_Root) this->TreeToNodeSet(m_Root, vec); return vec; } void QmitkDataStorageTreeModel::TreeToNodeSet( TreeItem* parent, std::vector& 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(); } 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::SetShowHelperObjects(bool _ShowHelperObjects) { m_ShowHelperObjects = _ShowHelperObjects; + this->UpdateNodeVisibility(); +} + +void QmitkDataStorageTreeModel::SetShowNodesContainingNoData(bool _ShowNodesContainingNoData) +{ + m_ShowNodesContainingNoData = _ShowNodesContainingNoData; + this->UpdateNodeVisibility(); +} +void QmitkDataStorageTreeModel::UpdateNodeVisibility() +{ mitk::NodePredicateData::Pointer dataIsNull = mitk::NodePredicateData::New(0); mitk::NodePredicateNot::Pointer dataIsNotNull = mitk::NodePredicateNot::New(dataIsNull);// Show only nodes that really contain dat mitk::NodePredicateProperty::Pointer isHelperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotHelperObject = mitk::NodePredicateNot::New(isHelperObject);// Show only nodes that really contain dat + mitk::NodePredicateAnd::Pointer isNotHelperObjectAndContainsData = mitk::NodePredicateAnd::New(isNotHelperObject,dataIsNotNull); + mitk::NodePredicateAnd::Pointer isNotHelperObjectAndContainsNoData = mitk::NodePredicateAnd::New(isNotHelperObject,dataIsNull); + mitk::NodePredicateAnd::Pointer isHelperObjectAndContainsNoData = mitk::NodePredicateAnd::New(isHelperObject,dataIsNull); + mitk::NodePredicateAnd::Pointer isHelperObjectAndContainsData = mitk::NodePredicateAnd::New(isHelperObject,dataIsNotNull); - if (! m_ShowHelperObjects) + if (m_ShowHelperObjects) { - //hide helper objects - m_Predicate = mitk::NodePredicateAnd::New(dataIsNotNull, isNotHelperObject); + if (m_ShowNodesContainingNoData) + { + // Show helper objects and nodes containing no data + mitk::NodePredicateOr::Pointer tempPredicate = mitk::NodePredicateOr::New(isNotHelperObjectAndContainsData,isHelperObjectAndContainsNoData); + m_Predicate = mitk::NodePredicateOr::New(tempPredicate,isHelperObjectAndContainsData); + } + else + { + // Show helper objects but not nodes containing no data + m_Predicate = mitk::NodePredicateOr::New(isNotHelperObjectAndContainsData,isHelperObjectAndContainsData); + } } else { - //show helper objects - m_Predicate = dataIsNotNull; + if (m_ShowNodesContainingNoData) + { + // Don't show helper objects but nodes containing no data + m_Predicate = mitk::NodePredicateOr::New(isNotHelperObjectAndContainsData,isNotHelperObjectAndContainsNoData); + } + else + { + // Don't show helper objects and nodes containing no data + m_Predicate = isNotHelperObjectAndContainsData; + } } - this->Update(); } void QmitkDataStorageTreeModel::Update() { if (m_DataStorage.IsNotNull()) { this->reset(); mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = m_DataStorage->GetSubset(m_Predicate); for(mitk::DataStorage::SetOfObjects::const_iterator it=_NodeSet->begin(); it!=_NodeSet->end(); it++) { // save node this->AddNode(*it); } mitk::DataStorage::SetOfObjects::ConstPointer _NotNodeSet = m_DataStorage->GetSubset(mitk::NodePredicateNot::New(m_Predicate)); for(mitk::DataStorage::SetOfObjects::const_iterator it=_NotNodeSet->begin(); it!=_NotNodeSet->end(); it++) { // remove node this->RemoveNode(*it); } } } diff --git a/CoreUI/Qmitk/QmitkDataStorageTreeModel.h b/CoreUI/Qmitk/QmitkDataStorageTreeModel.h index c486a043dc..dc5d6a32bd 100644 --- a/CoreUI/Qmitk/QmitkDataStorageTreeModel.h +++ b/CoreUI/Qmitk/QmitkDataStorageTreeModel.h @@ -1,259 +1,279 @@ /*========================================================================= Program: MITK Language: C++ Date: $Date: 2008-08-13 16:56:36 +0200 (Mi, 13 Aug 2008) $ Version: $Revision: 14972 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QMITKDATASTORAGETREEMODEL_H_ #define QMITKDATASTORAGETREEMODEL_H_ #include #include #include #include #include "QmitkEnums.h" #include "QmitkCustomVariants.h" #include #include #include class QMITK_EXPORT QmitkDataStorageTreeModel : public QAbstractItemModel { //# CONSTANTS,TYPEDEFS public: static const std::string COLUMN_NAME; static const std::string COLUMN_TYPE; static const std::string COLUMN_VISIBILITY; //# CTORS,DTOR public: QmitkDataStorageTreeModel(mitk::DataStorage* _DataStorage , bool _PlaceNewNodesOnTop=false , bool _ShowHelperObjects=false + , bool _ShowNodesContainingNoData=false , QObject* parent = 0); ~QmitkDataStorageTreeModel(); //# GETTER public: /// /// Get node at a specific model index. /// This function is used to get a node from a QModelIndex /// mitk::DataNode::Pointer GetNode(const QModelIndex &index) const; /// /// Returns a copy of the node-vector that is shown by this model /// virtual std::vector GetNodeSet() const; /// /// Get the DataStorage. /// const mitk::DataStorage::Pointer GetDataStorage() const; /// /// Get the top placement flag /// bool GetPlaceNewNodesOnTopFlag() { return m_PlaceNewNodesOnTop; } /// /// Get the helper object visibility flag /// bool GetShowHelperObjectsFlag() { return m_ShowHelperObjects; } + /// + /// Get the visibility flag for showing nodes that contain no data + /// + bool GetShowNodesContainingNoDataFlag() + { + return m_ShowNodesContainingNoData; + } + /// /// Set the top placement flag /// void SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop); //# (Re-)implemented from QAbstractItemModel //# Read model Qt::ItemFlags flags(const QModelIndex& index) const; QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; int rowCount ( const QModelIndex & parent = QModelIndex() ) const; int columnCount ( const QModelIndex & parent = QModelIndex() ) const; //# hierarchical model /// /// called whenever the model or the view needs to create a QModelIndex for a particular /// child item (or a top-level item if parent is an invalid QModelIndex) /// QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex parent ( const QModelIndex & index ) const; //# editable model bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); Qt::DropActions supportedDropActions() const; Qt::DropActions supportedDragActions() const; QStringList mimeTypes() const; QMimeData * mimeData(const QModelIndexList & indexes) const; //# End of QAbstractItemModel //# SETTER public: /// /// Sets the DataStorage. The whole model will be resetted. /// void SetDataStorage(mitk::DataStorage* _DataStorage); /// /// Notify that the DataStorage was deleted. The whole model will be resetted. /// void SetDataStorageDeleted(const itk::Object* _DataStorage); /// /// Adds a node to this model. /// If a predicate is set (not null) the node will be checked against it.The node has to have a data object (no one wants to see empty nodes). /// virtual void AddNode(const mitk::DataNode* node); /// /// Removes a node from this model. Also removes any event listener from the node. /// virtual void RemoveNode(const mitk::DataNode* node); /// /// Sets a node to modfified. Called by the DataStorage /// virtual void SetNodeModified(const mitk::DataNode* node); /// /// \return an index for the given datatreenode in the tree. If the node is not found /// QModelIndex GetIndex(const mitk::DataNode*) const; /// /// Show or hide helper objects /// void SetShowHelperObjects(bool _ShowHelperObjects); + /// + /// Show or hide objects that contain no data + /// + void SetShowNodesContainingNoData(bool _ShowNodesContainingNoData); + + /// + /// Update the visibility of data nodes according to the preference settings + /// + void UpdateNodeVisibility(); + //# MISC protected: /// /// Helper class to represent a tree structure of DataNodes /// class TreeItem { public: /// /// Constructs a new TreeItem with the given DataNode (must not be 0) /// TreeItem(mitk::DataNode* _DataNode, TreeItem* _Parent=0); /// /// Removes itself as child from its parent-> Does not delete its children /// \sa Delete() /// virtual ~TreeItem(); /// /// Find the index of an item /// int IndexOfChild(const TreeItem* item) const; /// /// \child The child at pos index or 0 if it not exists /// TreeItem* GetChild(int index) const; /// /// Find the TreeItem containing a special tree node (recursive tree function) /// TreeItem* Find( const mitk::DataNode* _DataNode) const; /// /// Get the amount of children /// int GetChildCount() const; /// /// \return the index of this node in its parent list /// int GetIndex() const; /// /// \return the parent of this tree item /// TreeItem* GetParent() const; /// /// Return the DataNode associated with this node /// mitk::DataNode::Pointer GetDataNode() const; /// /// Get all children as vector /// std::vector GetChildren() const; /// /// add another item as a child of this (only if not already in that list) /// void AddChild( TreeItem* item); /// /// remove another item as child from this /// void RemoveChild( TreeItem* item); /// /// inserts a child at the given position. if pos is not in range /// the element is added at the end /// void InsertChild( TreeItem* item, int index=-1 ); /// Sets the parent on the treeitem void SetParent(TreeItem* _Parent); /// /// Deletes the whole tree branch /// void Delete(); protected: TreeItem* m_Parent; std::vector m_Children; mitk::DataNode::Pointer m_DataNode; }; /// /// Adjusts the LayerProperty according to the nodes position /// void AdjustLayerProperty(); /// /// invoked after m_DataStorage or m_Predicate changed /// TreeItem* TreeItemFromIndex(const QModelIndex &index) const; /// /// Gives a ModelIndex for the Tree Item /// QModelIndex IndexFromTreeItem(TreeItem*) const; /// /// Returns the first element in the nodes sources list (if available) or 0 /// mitk::DataNode* GetParentNode(const mitk::DataNode* node) const; /// /// Adds all Childs in parent to vec. Before a child is added the function is called recursively /// void TreeToVector(TreeItem* parent, std::vector& vec) const; /// /// Adds all Childs in parent to vec. Before a child is added the function is called recursively /// void TreeToNodeSet(TreeItem* parent, std::vector& vec) const; /// /// Update Tree Model according to predicates /// void Update(); //# ATTRIBUTES protected: mitk::WeakPointer m_DataStorage; mitk::NodePredicateBase::Pointer m_Predicate; bool m_PlaceNewNodesOnTop; bool m_ShowHelperObjects; + bool m_ShowNodesContainingNoData; TreeItem* m_Root; }; #endif /* QMITKDATASTORAGETREEMODEL_H_ */ diff --git a/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp b/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp index f1a7e739b6..8921300d1b 100644 --- a/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp @@ -1,99 +1,104 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-07-07 16:57:15 +0200 (Di, 07 Jul 2009) $ Version: $Revision: 18019 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkDataManagerPreferencePage.h" #include "QmitkDataManagerView.h" #include #include #include #include #include #include QmitkDataManagerPreferencePage::QmitkDataManagerPreferencePage() : m_MainControl(0) { } QmitkDataManagerPreferencePage::QmitkDataManagerPreferencePage(const QmitkDataManagerPreferencePage& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } void QmitkDataManagerPreferencePage::Init(berry::IWorkbench::Pointer ) { } void QmitkDataManagerPreferencePage::CreateQtControl(QWidget* parent) { berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); m_DataManagerPreferencesNode = prefService->GetSystemPreferences()->Node(QmitkDataManagerView::VIEW_ID); m_MainControl = new QWidget(parent); m_EnableSingleEditing = new QCheckBox; m_PlaceNewNodesOnTop = new QCheckBox; m_ShowHelperObjects = new QCheckBox; + m_ShowNodesContainingNoData = new QCheckBox; m_UseSurfaceDecimation = new QCheckBox; QFormLayout *formLayout = new QFormLayout; formLayout->addRow("&Single click property editing:", m_EnableSingleEditing); formLayout->addRow("&Place new nodes on top:", m_PlaceNewNodesOnTop); formLayout->addRow("&Show helper objects:", m_ShowHelperObjects); + formLayout->addRow("&Show nodes containing no data", m_ShowNodesContainingNoData); formLayout->addRow("&Use surface decimation:", m_UseSurfaceDecimation); m_MainControl->setLayout(formLayout); this->Update(); } QWidget* QmitkDataManagerPreferencePage::GetQtControl() const { return m_MainControl; } bool QmitkDataManagerPreferencePage::PerformOk() { m_DataManagerPreferencesNode->PutBool("Single click property editing" , m_EnableSingleEditing->isChecked()); m_DataManagerPreferencesNode->PutBool("Place new nodes on top" , m_PlaceNewNodesOnTop->isChecked()); m_DataManagerPreferencesNode->PutBool("Show helper objects" , m_ShowHelperObjects->isChecked()); + m_DataManagerPreferencesNode->PutBool("Show nodes containing no data" + , m_ShowNodesContainingNoData->isChecked()); m_DataManagerPreferencesNode->PutBool("Use surface decimation" , m_UseSurfaceDecimation->isChecked()); return true; } void QmitkDataManagerPreferencePage::PerformCancel() { } void QmitkDataManagerPreferencePage::Update() { m_EnableSingleEditing->setChecked(m_DataManagerPreferencesNode->GetBool("Single click property editing", true)); m_PlaceNewNodesOnTop->setChecked(m_DataManagerPreferencesNode->GetBool("Place new nodes on top", true)); m_ShowHelperObjects->setChecked(m_DataManagerPreferencesNode->GetBool("Show helper objects", false)); + m_ShowNodesContainingNoData->setChecked(m_DataManagerPreferencesNode->GetBool("Show nodes containing no data", false)); m_UseSurfaceDecimation->setChecked(m_DataManagerPreferencesNode->GetBool("Use surface decimation", true)); } diff --git a/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h b/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h index 3f0e9781f7..e43bafa74d 100644 --- a/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h +++ b/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h @@ -1,68 +1,69 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-02-10 14:14:32 +0100 (Di, 10 Feb 2009) $ Version: $Revision: 16224 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QMITKDATAMANAGERPREFERENCEPAGE_H_ #define QMITKDATAMANAGERPREFERENCEPAGE_H_ #include "berryIQtPreferencePage.h" #include #include class QWidget; class QCheckBox; struct MITK_QT_DATAMANAGER QmitkDataManagerPreferencePage : public QObject, public berry::IQtPreferencePage { Q_OBJECT Q_INTERFACES(berry::IPreferencePage) public: QmitkDataManagerPreferencePage(); QmitkDataManagerPreferencePage(const QmitkDataManagerPreferencePage& other); void Init(berry::IWorkbench::Pointer workbench); void CreateQtControl(QWidget* widget); QWidget* GetQtControl() const; /// /// \see IPreferencePage::PerformOk() /// virtual bool PerformOk(); /// /// \see IPreferencePage::PerformCancel() /// virtual void PerformCancel(); /// /// \see IPreferencePage::Update() /// virtual void Update(); protected: QWidget* m_MainControl; QCheckBox* m_EnableSingleEditing; QCheckBox* m_PlaceNewNodesOnTop; QCheckBox* m_ShowHelperObjects; + QCheckBox* m_ShowNodesContainingNoData; QCheckBox* m_UseSurfaceDecimation; berry::IPreferences::Pointer m_DataManagerPreferencesNode; }; #endif /* QMITKDATAMANAGERPREFERENCEPAGE_H_ */ diff --git a/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp b/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp index 51234927ad..23b17fa058 100644 --- a/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp @@ -1,1014 +1,1019 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 18127 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkDataManagerView.h" #include //# Own Includes //## mitk #include "mitkDataStorageEditorInput.h" #include "mitkIDataStorageReference.h" #include "mitkNodePredicateDataType.h" #include "mitkCoreObjectFactory.h" #include "mitkPACSPlugin.h" #include "mitkDataNodeFactory.h" #include "mitkColorProperty.h" #include "mitkCommon.h" #include "mitkDelegateManager.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" #include "mitkEnumerationProperty.h" #include "mitkProperties.h" #include #include #include //## Qmitk #include #include #include #include #include #include #include #include #include "src/internal/QmitkNodeTableViewKeyFilter.h" #include "src/internal/QmitkInfoDialog.h" //## Berry #include #include #include #include //# Toolkit Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDataNodeObject.h" #include "mitkIContextMenuAction.h" #include "berryIExtensionPointService.h" const std::string QmitkDataManagerView::VIEW_ID = "org.mitk.views.datamanager"; QmitkDataManagerView::QmitkDataManagerView() { } QmitkDataManagerView::QmitkDataManagerView(const QmitkDataManagerView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkDataManagerView::~QmitkDataManagerView() { berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); if(s) s->RemoveSelectionListener(m_SelectionListener); berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(VIEW_ID)) .Cast(); prefs->OnChanged.RemoveListener( berry::MessageDelegate1( this , &QmitkDataManagerView::OnPreferencesChanged ) ); } void QmitkDataManagerView::CreateQtPartControl(QWidget* parent) { m_CurrentRowCount = 0; m_Parent = parent; //# Preferences berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(VIEW_ID)) .Cast(); assert( prefs ); prefs->OnChanged.AddListener( berry::MessageDelegate1( this , &QmitkDataManagerView::OnPreferencesChanged ) ); //# GUI m_NodeTreeModel = new QmitkDataStorageTreeModel(this->GetDataStorage()); m_NodeTreeModel->setParent( parent ); m_NodeTreeModel->SetPlaceNewNodesOnTop( prefs->GetBool("Place new nodes on top", true) ); m_NodeTreeModel->SetShowHelperObjects( - prefs->GetBool("Show helper objects", false) ); + prefs->GetBool("Show helper objects", false) ); + m_NodeTreeModel->SetShowNodesContainingNoData( + prefs->GetBool("Show nodes containing no data", false) ); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); //# Tree View (experimental) m_NodeTreeView = new QTreeView; m_NodeTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection ); m_NodeTreeView->setSelectionBehavior( QAbstractItemView::SelectRows ); m_NodeTreeView->setAlternatingRowColors(true); m_NodeTreeView->setDragEnabled(true); m_NodeTreeView->setDropIndicatorShown(true); m_NodeTreeView->setAcceptDrops(true); m_NodeTreeView->setContextMenuPolicy(Qt::CustomContextMenu); m_NodeTreeView->setModel(m_NodeTreeModel); m_NodeTreeView->installEventFilter(new QmitkNodeTableViewKeyFilter(this)); QObject::connect( m_NodeTreeView, SIGNAL(customContextMenuRequested(const QPoint&)) , this, SLOT(NodeTableViewContextMenuRequested(const QPoint&)) ); QObject::connect( m_NodeTreeModel, SIGNAL(rowsInserted (const QModelIndex&, int, int)) , this, SLOT(NodeTreeViewRowsInserted ( const QModelIndex&, int, int )) ); QObject::connect( m_NodeTreeModel, SIGNAL(rowsRemoved (const QModelIndex&, int, int)) , this, SLOT(NodeTreeViewRowsRemoved( const QModelIndex&, int, int )) ); QObject::connect( m_NodeTreeView->selectionModel() , SIGNAL( selectionChanged ( const QItemSelection &, const QItemSelection & ) ) , this , SLOT( NodeSelectionChanged ( const QItemSelection &, const QItemSelection & ) ) ); //# m_NodeMenu m_NodeMenu = new QMenu(m_NodeTreeView); //# m_SelectionProvider m_SelectionProvider = new QmitkDataNodeSelectionProvider(); m_SelectionProvider->SetItemSelectionModel(m_NodeTreeView->selectionModel()); this->GetSite()->SetSelectionProvider(m_SelectionProvider); // # Actions QmitkNodeDescriptor* unknownDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetUnknownDataNodeDescriptor(); QmitkNodeDescriptor* imageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Image"); QmitkNodeDescriptor* surfaceDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Surface"); m_GlobalReinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), "Global Reinit", this); QObject::connect( m_GlobalReinitAction, SIGNAL( triggered(bool) ) , this, SLOT( GlobalReinit(bool) ) ); unknownDataNodeDescriptor->AddAction(m_GlobalReinitAction); m_SaveAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Save_48.png"), "Save...", this); QObject::connect( m_SaveAction, SIGNAL( triggered(bool) ) , this, SLOT( SaveSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(m_SaveAction); m_RemoveAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Remove_48.png"), "Remove", this); QObject::connect( m_RemoveAction, SIGNAL( triggered(bool) ) , this, SLOT( RemoveSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(m_RemoveAction); m_ReinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), "Reinit", this); QObject::connect( m_ReinitAction, SIGNAL( triggered(bool) ) , this, SLOT( ReinitSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(m_ReinitAction); // find contextMenuAction extension points and add them to the node descriptor berry::IExtensionPointService::Pointer extensionPointService = berry::Platform::GetExtensionPointService(); berry::IConfigurationElement::vector cmActions( extensionPointService->GetConfigurationElementsFor("org.mitk.gui.qt.datamanager.contextMenuActions") ); berry::IConfigurationElement::vector::iterator cmActionsIt; std::string cmNodeDescriptorName; std::string cmLabel; std::string cmIcon; std::string cmClass; QmitkNodeDescriptor* tmpDescriptor; QAction* contextMenuAction; QVariant cmActionDataIt; m_ConfElements.clear(); int i=1; for (cmActionsIt = cmActions.begin() ; cmActionsIt != cmActions.end() ; ++cmActionsIt) { cmIcon.erase(); if((*cmActionsIt)->GetAttribute("nodeDescriptorName", cmNodeDescriptorName) && (*cmActionsIt)->GetAttribute("label", cmLabel) && (*cmActionsIt)->GetAttribute("class", cmClass)) { (*cmActionsIt)->GetAttribute("icon", cmIcon); // create context menu entry here tmpDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(QString::fromStdString(cmNodeDescriptorName)); if(!tmpDescriptor) { MITK_WARN << "cannot add action \"" << cmLabel << "\" because descriptor " << cmNodeDescriptorName << " does not exist"; continue; } contextMenuAction = new QAction( QString::fromStdString(cmLabel), parent); tmpDescriptor->AddAction(contextMenuAction); m_ConfElements[contextMenuAction] = *cmActionsIt; cmActionDataIt.setValue(i); contextMenuAction->setData( cmActionDataIt ); connect( contextMenuAction, SIGNAL( triggered(bool) ) , this, SLOT( ContextMenuActionTriggered(bool) ) ); ++i; } } m_OpacitySlider = new QSlider; m_OpacitySlider->setMinimum(0); m_OpacitySlider->setMaximum(100); m_OpacitySlider->setOrientation(Qt::Horizontal); QObject::connect( m_OpacitySlider, SIGNAL( valueChanged(int) ) , this, SLOT( OpacityChanged(int) ) ); QLabel* _OpacityLabel = new QLabel("Opacity: "); QHBoxLayout* _OpacityWidgetLayout = new QHBoxLayout; _OpacityWidgetLayout->setContentsMargins(4,4,4,4); _OpacityWidgetLayout->addWidget(_OpacityLabel); _OpacityWidgetLayout->addWidget(m_OpacitySlider); QWidget* _OpacityWidget = new QWidget; _OpacityWidget->setLayout(_OpacityWidgetLayout); m_OpacityAction = new QWidgetAction(this); m_OpacityAction->setDefaultWidget(_OpacityWidget); QObject::connect( m_OpacityAction, SIGNAL( changed() ) , this, SLOT( OpacityActionChanged() ) ); unknownDataNodeDescriptor->AddAction(m_OpacityAction, false); m_ColorButton = new QPushButton; m_ColorButton->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum); //m_ColorButton->setText("Change color"); QObject::connect( m_ColorButton, SIGNAL( clicked() ) , this, SLOT( ColorChanged() ) ); QLabel* _ColorLabel = new QLabel("Color: "); _ColorLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); QHBoxLayout* _ColorWidgetLayout = new QHBoxLayout; _ColorWidgetLayout->setContentsMargins(4,4,4,4); _ColorWidgetLayout->addWidget(_ColorLabel); _ColorWidgetLayout->addWidget(m_ColorButton); QWidget* _ColorWidget = new QWidget; _ColorWidget->setLayout(_ColorWidgetLayout); m_ColorAction = new QWidgetAction(this); m_ColorAction->setDefaultWidget(_ColorWidget); QObject::connect( m_ColorAction, SIGNAL( changed() ) , this, SLOT( ColorActionChanged() ) ); unknownDataNodeDescriptor->AddAction(m_ColorAction, false); m_TextureInterpolation = new QAction("Texture Interpolation", this); m_TextureInterpolation->setCheckable ( true ); QObject::connect( m_TextureInterpolation, SIGNAL( changed() ) , this, SLOT( TextureInterpolationChanged() ) ); QObject::connect( m_TextureInterpolation, SIGNAL( toggled(bool) ) , this, SLOT( TextureInterpolationToggled(bool) ) ); imageDataNodeDescriptor->AddAction(m_TextureInterpolation, false); m_SurfaceRepresentation = new QAction("Surface Representation", this); m_SurfaceRepresentation->setMenu(new QMenu); QObject::connect( m_SurfaceRepresentation->menu(), SIGNAL( aboutToShow() ) , this, SLOT( SurfaceRepresentationMenuAboutToShow() ) ); surfaceDataNodeDescriptor->AddAction(m_SurfaceRepresentation, false); m_ShowOnlySelectedNodes = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowSelectedNode_48.png") , "Show only selected nodes", this); QObject::connect( m_ShowOnlySelectedNodes, SIGNAL( triggered(bool) ) , this, SLOT( ShowOnlySelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(m_ShowOnlySelectedNodes); m_ToggleSelectedVisibility = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/InvertShowSelectedNode_48.png") , "Toggle visibility", this); QObject::connect( m_ToggleSelectedVisibility, SIGNAL( triggered(bool) ) , this, SLOT( ToggleVisibilityOfSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(m_ToggleSelectedVisibility); m_ActionShowInfoDialog = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowDataInfo_48.png") , "Details...", this); QObject::connect( m_ActionShowInfoDialog, SIGNAL( triggered(bool) ) , this, SLOT( ShowInfoDialogForSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(m_ActionShowInfoDialog); m_OtsuFilterAction = new QAction("Apply Otsu Filter", this); QObject::connect( m_OtsuFilterAction, SIGNAL( triggered(bool) ) , this, SLOT( OtsuFilter(bool) ) ); // Otsu filter does not work properly, remove it temporarily // imageDataNodeDescriptor->AddAction(m_OtsuFilterAction); QGridLayout* _DndFrameWidgetLayout = new QGridLayout; _DndFrameWidgetLayout->addWidget(m_NodeTreeView, 0, 0); _DndFrameWidgetLayout->setContentsMargins(0,0,0,0); m_DndFrameWidget = new QmitkDnDFrameWidget(m_Parent); m_DndFrameWidget->setLayout(_DndFrameWidgetLayout); QVBoxLayout* layout = new QVBoxLayout(parent); layout->addWidget(m_DndFrameWidget); layout->setContentsMargins(0,0,0,0); m_Parent->setLayout(layout); m_SelectionListener = new berry::SelectionChangedAdapter (this, &QmitkDataManagerView::SelectionChanged); berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); s->AddSelectionListener(m_SelectionListener); } void QmitkDataManagerView::SetFocus() { } void QmitkDataManagerView::ContextMenuActionTriggered( bool ) { QAction* action = qobject_cast ( sender() ); std::map::iterator it = m_ConfElements.find( action ); if( it == m_ConfElements.end() ) { MITK_WARN << "associated conf element for action " << action->text().toStdString() << " not found"; return; } berry::IConfigurationElement::Pointer confElem = it->second; mitk::IContextMenuAction* contextMenuAction = confElem->CreateExecutableExtension("class"); if (contextMenuAction == 0) { // support legacy BlueBerry extensions contextMenuAction = confElem->CreateExecutableExtension("class", mitk::IContextMenuAction::GetManifestName()); } std::string className; std::string smoothed; confElem->GetAttribute("class", className); confElem->GetAttribute("smoothed", smoothed); if(className == "QmitkThresholdAction") { contextMenuAction->SetDataStorage(this->GetDataStorage()); } if(className == "QmitkCreatePolygonModelAction") { contextMenuAction->SetDataStorage(this->GetDataStorage()); if(smoothed == "false") { contextMenuAction->SetSmoothed(false); } else { contextMenuAction->SetSmoothed(true); } contextMenuAction->SetDecimated(m_SurfaceDecimation); } if(className == "QmitkStatisticsAction") { contextMenuAction->SetFunctionality(this); } contextMenuAction->Run( this->GetSelectedNodes() ); // run the action } mitk::DataStorage::Pointer QmitkDataManagerView::GetDataStorage() const { mitk::IDataStorageService::Pointer service = berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); if (service.IsNotNull()) { return service->GetDefaultDataStorage()->GetDataStorage(); } return 0; } void QmitkDataManagerView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { if( m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() != prefs->GetBool("Place new nodes on top", true) ) m_NodeTreeModel->SetPlaceNewNodesOnTop( !m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() ); if( m_NodeTreeModel->GetShowHelperObjectsFlag()!= prefs->GetBool("Show helper objects", false) ) m_NodeTreeModel->SetShowHelperObjects( !m_NodeTreeModel->GetShowHelperObjectsFlag() ); - + + if( m_NodeTreeModel->GetShowNodesContainingNoDataFlag()!= prefs->GetBool("Show nodes containing no data", false) ) + m_NodeTreeModel->SetShowNodesContainingNoData( !m_NodeTreeModel->GetShowNodesContainingNoDataFlag() ); + m_NodeTreeView->expandAll(); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); this->GlobalReinit(); } void QmitkDataManagerView::NodeTableViewContextMenuRequested( const QPoint & pos ) { QModelIndex selected = m_NodeTreeView->indexAt ( pos ); mitk::DataNode::Pointer node = m_NodeTreeModel->GetNode(selected); std::vector selectedNodes = this->GetSelectedNodes(); if(!selectedNodes.empty()) { m_NodeMenu->clear(); QList actions; if(selectedNodes.size() == 1 ) { actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(node); for(QList::iterator it = actions.begin(); it != actions.end(); ++it) { (*it)->setData(QVariant::fromValue(node.GetPointer())); } } else actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(selectedNodes); m_NodeMenu->addActions(actions); m_NodeMenu->popup(QCursor::pos()); } } void QmitkDataManagerView::OpacityChanged(int value) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { float opacity = static_cast(value)/100.0f; node->SetFloatProperty("opacity", opacity); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } MITK_INFO << "slider changed"; } void QmitkDataManagerView::OpacityActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { float opacity = 0.0; if(node->GetFloatProperty("opacity", opacity)) { m_OpacitySlider->setValue(static_cast(opacity*100)); } } MITK_INFO << "changed"; } void QmitkDataManagerView::ColorChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { QColor color = QColorDialog::getColor(); m_ColorButton->setAutoFillBackground(true); node->SetProperty("color",mitk::ColorProperty::New(color.red()/255.0,color.green()/255.0,color.blue()/255.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } MITK_INFO << "slider changed"; } void QmitkDataManagerView::ColorActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { mitk::Color color; mitk::ColorProperty::Pointer colorProp; node->GetProperty(colorProp,"color"); if(colorProp.IsNull()) return; color = colorProp->GetValue(); QString styleSheet = "background-color:rgb("; styleSheet.append(QString::number(color[0]*255)); styleSheet.append(","); styleSheet.append(QString::number(color[1]*255)); styleSheet.append(","); styleSheet.append(QString::number(color[2]*255)); styleSheet.append(")"); m_ColorButton->setStyleSheet(styleSheet); } MITK_INFO << "changed"; } void QmitkDataManagerView::TextureInterpolationChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { bool textureInterpolation = false; node->GetBoolProperty("texture interpolation", textureInterpolation); m_TextureInterpolation->setChecked(textureInterpolation); } } void QmitkDataManagerView::TextureInterpolationToggled( bool checked ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { node->SetBoolProperty("texture interpolation", checked); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::SurfaceRepresentationMenuAboutToShow() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(!node) return; mitk::EnumerationProperty* representationProp = dynamic_cast (node->GetProperty("material.representation")); if(!representationProp) return; // clear menu m_SurfaceRepresentation->menu()->clear(); QAction* tmp; // create menu entries for(mitk::EnumerationProperty::EnumConstIterator it=representationProp->Begin(); it!=representationProp->End() ; it++) { tmp = m_SurfaceRepresentation->menu()->addAction(QString::fromStdString(it->second)); tmp->setCheckable(true); if(it->second == representationProp->GetValueAsString()) { tmp->setChecked(true); } QObject::connect( tmp, SIGNAL( triggered(bool) ) , this, SLOT( SurfaceRepresentationActionToggled(bool) ) ); } } void QmitkDataManagerView::SurfaceRepresentationActionToggled( bool /*checked*/ ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(!node) return; mitk::EnumerationProperty* representationProp = dynamic_cast (node->GetProperty("material.representation")); if(!representationProp) return; QAction* senderAction = qobject_cast ( QObject::sender() ); if(!senderAction) return; std::string activatedItem = senderAction->text().toStdString(); if ( activatedItem != representationProp->GetValueAsString() ) { if ( representationProp->IsValidEnumerationValue( activatedItem ) ) { representationProp->SetValue( activatedItem ); representationProp->InvokeEvent( itk::ModifiedEvent() ); representationProp->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkDataManagerView::SaveSelectedNodes( bool ) { QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows(); mitk::DataNode* node = 0; unsigned int indexesOfSelectedRowsSize = indexesOfSelectedRows.size(); for (unsigned int i = 0; iGetNode(indexesOfSelectedRows.at(i)); // if node is not defined or if the node contains geometry data do not remove it if ( node != 0 ) { mitk::BaseData::Pointer data = node->GetData(); if (data.IsNotNull()) { QString error; try { CommonFunctionality::SaveBaseData( data.GetPointer(), node->GetName().c_str() ); } catch(std::exception& e) { error = e.what(); } catch(...) { error = "Unknown error occured"; } if( !error.isEmpty() ) QMessageBox::critical( m_Parent, "Error saving...", error ); } } } } void QmitkDataManagerView::ReinitSelectedNodes( bool ) { this->ReinitMultiWidgetEditor(); std::vector selectedNodes = this->GetSelectedNodes(); mitk::DataNode* node = 0; for (std::vector::iterator it = selectedNodes.begin() ; it != selectedNodes.end(); it++) { node = *it; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkDataManagerView::RemoveSelectedNodes( bool ) { QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows(); if(indexesOfSelectedRows.size() < 1) { return; } std::vector selectedNodes; mitk::DataNode* node = 0; QString question = tr("Do you really want to remove "); for (QModelIndexList::iterator it = indexesOfSelectedRows.begin() ; it != indexesOfSelectedRows.end(); it++) { node = m_NodeTreeModel->GetNode(*it); // if node is not defined or if the node contains geometry data do not remove it if ( node != 0 /*& strcmp(node->GetData()->GetNameOfClass(), "Geometry2DData") != 0*/ ) { selectedNodes.push_back(node); question.append(QString::fromStdString(node->GetName())); question.append(", "); } } // remove the last two characters = ", " question = question.remove(question.size()-2, 2); question.append(" from data storage?"); QMessageBox::StandardButton answerButton = QMessageBox::question( m_Parent , tr("DataManager") , question , QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if(answerButton == QMessageBox::Yes) { for (std::vector::iterator it = selectedNodes.begin() ; it != selectedNodes.end(); it++) { node = *it; this->GetDataStorage()->Remove(node); this->GlobalReinit(false); } } } void QmitkDataManagerView::MakeAllNodesInvisible( bool ) { std::vector nodes = m_NodeTreeModel->GetNodeSet(); for (std::vector::iterator it = nodes.begin() ; it != nodes.end(); it++) { (*it)->SetVisibility(false); } //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowOnlySelectedNodes( bool ) { std::vector selectedNodes = this->GetSelectedNodes(); std::vector allNodes = m_NodeTreeModel->GetNodeSet(); mitk::DataNode* node = 0; for (std::vector::iterator it = allNodes.begin() ; it != allNodes.end(); it++) { node = *it; if(std::find(selectedNodes.begin(), selectedNodes.end(), node) == selectedNodes.end()) node->SetVisibility(false); else node->SetVisibility(true); } //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ToggleVisibilityOfSelectedNodes( bool ) { std::vector selectedNodes = this->GetSelectedNodes(); bool isVisible = false; mitk::DataNode* node = 0; for (std::vector::iterator it = selectedNodes.begin() ; it != selectedNodes.end(); it++) { isVisible = false; node = *it; node->GetBoolProperty("visible", isVisible); node->SetVisibility(!isVisible); } //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowInfoDialogForSelectedNodes( bool ) { std::vector selectedNodes = this->GetSelectedNodes(); QmitkInfoDialog _QmitkInfoDialog(selectedNodes, this->m_Parent); _QmitkInfoDialog.exec(); } void QmitkDataManagerView::Load( bool ) { QStringList fileNames = QFileDialog::getOpenFileNames(NULL, "Load data", "", mitk::CoreObjectFactory::GetInstance()->GetFileExtensions()); for ( QStringList::Iterator it = fileNames.begin(); it != fileNames.end(); ++it ) { FileOpen((*it).toAscii(), 0); } } void QmitkDataManagerView::FileOpen( const char * fileName, mitk::DataNode* parentNode ) { mitk::DataNodeFactory::Pointer factory = mitk::DataNodeFactory::New(); try { factory->SetFileName( fileName ); QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); factory->Update(); for ( unsigned int i = 0 ; i < factory->GetNumberOfOutputs( ); ++i ) { mitk::DataNode::Pointer node = factory->GetOutput( i ); if ( ( node.IsNotNull() ) && ( node->GetData() != NULL ) ) { this->GetDataStorage()->Add(node, parentNode); mitk::BaseData::Pointer basedata = node->GetData(); mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } catch ( itk::ExceptionObject & ex ) { itkGenericOutputMacro( << "Exception during file open: " << ex ); } QApplication::restoreOverrideCursor(); } void QmitkDataManagerView::GlobalReinit( bool ) { this->ReinitMultiWidgetEditor(); // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox" , mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } std::vector QmitkDataManagerView::GetSelectedNodes() const { QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows(); std::vector selectedNodes; mitk::DataNode* node = 0; for (QModelIndexList::iterator it = indexesOfSelectedRows.begin() ; it != indexesOfSelectedRows.end(); it++) { node = 0; node = m_NodeTreeModel->GetNode(*it); // if node is not defined or if the node contains geometry data do not remove it if ( node != 0 ) selectedNodes.push_back(node); } return selectedNodes; } void QmitkDataManagerView::SelectionChanged( berry::IWorkbenchPart::Pointer part , berry::ISelection::ConstPointer selection ) { if(part.GetPointer() == this) return; mitk::DataNodeSelection::ConstPointer _DataNodeSelection = selection.Cast(); if(_DataNodeSelection.IsNull()) return; std::vector selectedNodes; mitk::DataNodeObject* _DataNodeObject = 0; mitk::DataNode* _DataNode = 0; QItemSelection newSelection; m_NodeTreeView->selectionModel()->reset(); for(mitk::DataNodeSelection::iterator it = _DataNodeSelection->Begin(); it != _DataNodeSelection->End(); ++it) { _DataNodeObject = dynamic_cast((*it).GetPointer()); if(_DataNodeObject) _DataNode = _DataNodeObject->GetDataNode(); QModelIndex treeIndex = m_NodeTreeModel->GetIndex(_DataNode); if(treeIndex.isValid()) newSelection.select(treeIndex, treeIndex); } m_NodeTreeView->selectionModel()->select(newSelection, QItemSelectionModel::SelectCurrent); } void QmitkDataManagerView::OtsuFilter( bool ) { std::vector selectedNodes = this->GetSelectedNodes(); mitk::DataNode* _DataNode = 0; mitk::Image::Pointer mitkImage = 0; for (std::vector::iterator it = selectedNodes.begin() ; it != selectedNodes.end(); it++) { _DataNode = *it; mitkImage = dynamic_cast( _DataNode->GetData() ); if(mitkImage.IsNull()) continue; try { // get selected mitk image const unsigned short dim = 3; typedef short InputPixelType; typedef unsigned char OutputPixelType; typedef itk::Image< InputPixelType, dim > InputImageType; typedef itk::Image< OutputPixelType, dim > OutputImageType; typedef itk::OtsuThresholdImageFilter< InputImageType, OutputImageType > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetOutsideValue( 1 ); filter->SetInsideValue( 0 ); InputImageType::Pointer itkImage; mitk::CastToItkImage(mitkImage, itkImage); filter->SetInput( itkImage ); filter->Update(); mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); std::string nameOfResultImage = _DataNode->GetName(); nameOfResultImage.append("Otsu"); resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); resultNode->SetProperty("binary", mitk::BoolProperty::New(true) ); resultNode->SetData( mitk::ImportItkImage ( filter->GetOutput() ) ); this->GetDataStorage()->Add(resultNode, _DataNode); } catch( std::exception& err ) { MITK_ERROR(this->GetClassName()) << err.what(); } } } void QmitkDataManagerView::NodeTreeViewRowsRemoved ( const QModelIndex & parent, int start, int end ) { m_CurrentRowCount = m_NodeTreeModel->rowCount(); } void QmitkDataManagerView::NodeTreeViewRowsInserted( const QModelIndex & parent, int, int ) { m_NodeTreeView->setExpanded(parent, true); // a new row was inserted if( m_CurrentRowCount == 0 && m_NodeTreeModel->rowCount() == 1 ) { this->ReinitMultiWidgetEditor(); m_CurrentRowCount = m_NodeTreeModel->rowCount(); /* std::vector nodes = m_NodeTreeModel->GetNodeSet(); if(nodes.size() == 1) { QModelIndex treeIndex = m_NodeTreeModel->GetIndex(nodes.front()); m_NodeTreeView->selectionModel()->setCurrentIndex( treeIndex, QItemSelectionModel::ClearAndSelect ); } */ } } void QmitkDataManagerView::NodeSelectionChanged( const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/ ) { std::vector nodes = m_NodeTreeModel->GetNodeSet(); mitk::DataNode* node = 0; for (std::vector::iterator it = nodes.begin() ; it != nodes.end(); it++) { node = *it; if ( node ) node->SetBoolProperty("selected", false); } nodes.clear(); nodes = this->GetSelectedNodes(); for (std::vector::iterator it = nodes.begin() ; it != nodes.end(); it++) { node = *it; if ( node ) node->SetBoolProperty("selected", true); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ReinitMultiWidgetEditor() { berry::IEditorPart::Pointer editor; std::vector editors = this->GetSite()->GetPage()->GetEditors(); for (size_t i=0; i().IsNotNull() ) { editor = editors.at(i); break; } } if ( editor.IsNull() ) { mitk::IDataStorageService::Pointer service = berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); mitk::IDataStorageReference::Pointer DataStorageReference; if (service.IsNotNull()) { DataStorageReference = service->GetDefaultDataStorage(); } mitk::DataStorageEditorInput::Pointer editorInput; editorInput = new mitk::DataStorageEditorInput(DataStorageReference); // open a new multi-widget editor, but do not give it the focus berry::IEditorPart::Pointer editor = this->GetSite()->GetPage()->OpenEditor(editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID, false); } else this->GetSite()->GetPage()->OpenEditor(editor->GetEditorInput() , QmitkStdMultiWidgetEditor::EDITOR_ID, true); }