Commit 232e681b authored by alexy's avatar alexy
Browse files

BUG 2639. Added logic to remove display and storage nodes when displayable node is removed.

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21528 3bd1e089-480b-0410-8dfb-8563597acbee
parent 0ad9d8b6
......@@ -3002,6 +3002,26 @@ vtkCollection* vtkMRMLScene::GetReferencedNodes(vtkMRMLNode *node)
return nodes;
}
//-----------------------------------------------------------------------------
void vtkMRMLScene::GetReferencingNodes(vtkMRMLNode* referencedNode, std::vector<vtkMRMLNode *> &referencingNodes)
{
referencingNodes.clear();
if (!referencedNode || referencedNode->GetID() == 0)
{
vtkErrorMacro("GetReferencingNodes: null node or referenced node");
return;
}
size_t nnodes = this->ReferencedIDs.size();
for(size_t n=0; n<nnodes; ++n)
{
if ( !strcmp(referencedNode->GetID(), this->ReferencedIDs[n].c_str()))
{
referencingNodes.push_back(this->ReferencingNodes[n]);
}
}
}
//------------------------------------------------------------------------------
void vtkMRMLScene::CopyNodeReferences(vtkMRMLScene *scene)
......
......@@ -328,6 +328,10 @@ public:
/// \sa GetReferencedSubScene()
vtkCollection* GetReferencedNodes(vtkMRMLNode *node);
/// Get vector of nodes containing references to an input node
void GetReferencingNodes(vtkMRMLNode* referencedNode, std::vector<vtkMRMLNode *> &referencingNodes);
/// Get a sub-scene containing all nodes directly or indirectly referenced by
/// the input node.
/// GetReferencedNodes() is internally called.
......
......@@ -24,6 +24,9 @@
// MRML includes
#include <vtkMRMLNode.h>
#include <vtkMRMLDisplayableNode.h>
#include <vtkMRMLDisplayNode.h>
#include <vtkMRMLStorageNode.h>
// VTK includes
#include <vtkNew.h>
......@@ -38,6 +41,8 @@ vtkStandardNewMacro(vtkSlicerDataModuleLogic);
vtkSlicerDataModuleLogic::vtkSlicerDataModuleLogic()
{
this->SceneChangedOff();
this->AutoRemoveDisplayAndStorageNodes = true;
}
//----------------------------------------------------------------------------
......@@ -49,7 +54,11 @@ vtkSlicerDataModuleLogic::~vtkSlicerDataModuleLogic()
void vtkSlicerDataModuleLogic::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
os << indent << "AutoRemoveDisplayAndStorageNode: " <<
(AutoRemoveDisplayAndStorageNodes ? "On" : "Off") << "\n";
}
//---------------------------------------------------------------------------
void vtkSlicerDataModuleLogic::SetMRMLSceneInternal(vtkMRMLScene * newScene)
......@@ -73,3 +82,47 @@ void vtkSlicerDataModuleLogic::UpdateFromMRMLScene()
{
this->SceneChangedOn();
}
//----------------------------------------------------------------------------
void vtkSlicerDataModuleLogic::OnMRMLSceneNodeRemoved(vtkMRMLNode* node)
{
vtkMRMLDisplayableNode* displayableNode = vtkMRMLDisplayableNode::SafeDownCast(node);
if (!displayableNode || this->GetMRMLScene()->IsClosing() || !this->AutoRemoveDisplayAndStorageNodes)
{
return;
}
/// we can't get the display node directly as it might be 0 because the
/// displayable node has no longer access to the scene
std::vector<vtkMRMLNode *> referencingNodes;
for (int i = 0; i < displayableNode->GetNumberOfDisplayNodes(); ++i)
{
vtkMRMLNode *dnode = this->GetMRMLScene()->GetNodeByID(
displayableNode->GetNthDisplayNodeID(i));
// make sure no other nodes reference this display node
this->GetMRMLScene()->GetReferencingNodes(dnode, referencingNodes);
if (referencingNodes.size() == 0 ||
(referencingNodes.size() == 1 && referencingNodes[0] == node) )
{
this->GetMRMLScene()->RemoveNode(dnode);
}
}
for (int i = 0; i < displayableNode->GetNumberOfStorageNodes(); ++i)
{
vtkMRMLNode *snode = this->GetMRMLScene()->GetNodeByID(
displayableNode->GetNthStorageNodeID(i));
// make sure no other nodes reference this storage node
this->GetMRMLScene()->GetReferencingNodes(snode, referencingNodes);
if (referencingNodes.size() == 0 ||
(referencingNodes.size() == 1 && referencingNodes[0] == node) )
{
this->GetMRMLScene()->RemoveNode(snode);
}
}
}
......@@ -56,6 +56,20 @@ protected:
virtual void SetMRMLSceneInternal(vtkMRMLScene* newScene);
virtual void UpdateFromMRMLScene();
/// Reimplemented to delete the storage/display nodes when a displayable
/// node is being removed.
virtual void OnMRMLSceneNodeRemoved(vtkMRMLNode* removedNode);
///
/// This property controls whether the removal from the scene of a model node
/// automatically removes its display and storage nodes or not.
/// This automatic behavior (true by default) is used to prevent the user
/// from seeing a model (display node) in a 3D view after a model node
/// has been deleted/removed (delete from a tree view qt widget).
/// If the nodes were not removed/deleted, the display and storage nodes
/// would be zombie nodes in the scene with no one pointing on them.
bool AutoRemoveDisplayAndStorageNodes;
private:
vtkSlicerDataModuleLogic(const vtkSlicerDataModuleLogic&); // Not implemented
void operator=(const vtkSlicerDataModuleLogic&); // Not implemented
......
......@@ -77,31 +77,6 @@ void vtkSlicerModelsLogic::SetMRMLSceneInternal(vtkMRMLScene* newScene)
}
}
//----------------------------------------------------------------------------
void vtkSlicerModelsLogic::OnMRMLSceneNodeRemoved(vtkMRMLNode* node)
{
vtkMRMLModelNode* modelNode = vtkMRMLModelNode::SafeDownCast(node);
if (!modelNode || this->GetMRMLScene()->IsClosing())
{
return;
}
if (this->AutoRemoveDisplayAndStorageNodes)
{
/// we can't get the display node directly as it might be 0 because the
/// model node has no longer access to the scene
for (int i = 0; i < modelNode->GetNumberOfDisplayNodes(); ++i)
{
this->GetMRMLScene()->RemoveNode(this->GetMRMLScene()->GetNodeByID(
modelNode->GetNthDisplayNodeID(i)));
}
for (int i = 0; i < modelNode->GetNumberOfStorageNodes(); ++i)
{
this->GetMRMLScene()->RemoveNode(this->GetMRMLScene()->GetNodeByID(
modelNode->GetNthStorageNodeID(i)));
}
}
}
//----------------------------------------------------------------------------
void vtkSlicerModelsLogic::SetActiveModelNode(vtkMRMLModelNode *activeNode)
{
......
......@@ -87,10 +87,6 @@ protected:
/// - observe the scene
virtual void SetMRMLSceneInternal(vtkMRMLScene* newScene);
/// Reimplemented to delete the storage/display nodes when a displayable
/// node is being removed.
virtual void OnMRMLSceneNodeRemoved(vtkMRMLNode* removedNode);
///
/// This property controls whether the removal from the scene of a model node
/// automatically removes its display and storage nodes or not.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment