Hello Alex,
maybe what you are looking for is currently done in
"QmitkSegmentationView" or "mitkLevelWindowManager".
Check the cpp-files and you'll find code like
"itk::SimpleMemberCommand<QmitkSegmentationView>::Pointer command =
itk::SimpleMemberCommand<QmitkSegmentationView>::New();" or
"itk::ReceptorMemberCommand<LevelWindowManager>::Pointer command =
itk::ReceptorMemberCommand<LevelWindowManager>::New();"
What is done here and in the lines following that is this:
An itk-command is created and a callback function is connected to that command.
The callback function is a local function that you implement so that it reacts
the way you want to react on the property changed (e.g. name changed)
("command->SetCallbackFunction(...)").
After that you'll retrieve the property you want to look at from every node and
add the command as observer
("node->GetProperty("name")->AddObserver(itk::ModifiedEvent(), command))").
"Every node" means, you have to make sure that you connect this command each
time a node has been added to the data storage and make sure you disconnect
this command each time a node has been removed from the data storage.
For this you can check the "NodeAdded" and "NodeRemoved" functions from the
"QmitkAbstractView.cpp", which can be overridden in a subclass (typically a
plugin view). Again, an example for this can be seen inside
"QmitkSegmentationView.cpp"
Another simple solution would be to check out the "NodeChanged" event /
function (also "QmitkAbstractView.cpp"): You could override this and each time
your node is changed (regardless of which property has changed) you'll check
inside this function, if the name you retrieve from the node is still the name
that you stored previously as a local member variable. The problem with that
approach is, unfortunately, "NodeChanged" event is send very often and you will
get a lot of noise.
Best,
Amir
________________________________
Von: Alex Melville <[email protected]>
Gesendet: Montag, 31. August 2020 17:06
An: [email protected]
Betreff: Re: [mitk-users] Event to handle Data Manager node renames
Hello, I still haven't been able to find a solution for this. I figured I'd try
again since there weren't any replies, I'll post my progress on investigating
this in case this helps somebody.
It looks like if there is a way to do this, it would involve hooking into
something on the ITK side.
A possible workaround for this would be to have some kind of periodic checker
function that goes through everything in the treeview and looks for node names
that changed and roll back invalid / duplicate names, but I would rather not do
that.
MITK\Modules\Core\src\DataManagement\mitkDataStorage.cpp
void mitk::DataStorage::OnNodeModifiedOrDeleted(const itk::Object *caller,
const itk::EventObject &event)
{
if (m_BlockNodeModifiedEvents)
return;
const mitk::DataNode *_Node = dynamic_cast<const mitk::DataNode *>(caller);
if (_Node)
{
const itk::ModifiedEvent *modEvent = dynamic_cast<const itk::ModifiedEvent
*>(&event);
if (modEvent)
ChangedNodeEvent.Send(_Node);
else
DeleteNodeEvent.Send(_Node);
}
in MITK\Modules\Core\src\DataManagement\mitkDataStorage.cpp
void mitk::DataStorage::AddListeners(const mitk::DataNode *_Node)
{
itk::MutexLockHolder<itk::SimpleFastMutexLock> locked(m_MutexOne);
// node must not be 0 and must not be yet registered
mitk::DataNode *NonConstNode = const_cast<mitk::DataNode *>(_Node);
if (_Node && m_NodeModifiedObserverTags.find(NonConstNode) ==
m_NodeModifiedObserverTags.end())
{
itk::MemberCommand<mitk::DataStorage>::Pointer nodeModifiedCommand =
itk::MemberCommand<mitk::DataStorage>::New();
nodeModifiedCommand->SetCallbackFunction(this,
&mitk::DataStorage::OnNodeModifiedOrDeleted);
m_NodeModifiedObserverTags[NonConstNode] =
NonConstNode->AddObserver(itk::ModifiedEvent(), nodeModifiedCommand);
itk::MemberCommand<mitk::DataStorage>::Pointer interactorChangedCommand =
itk::MemberCommand<mitk::DataStorage>::New();
interactorChangedCommand->SetCallbackFunction(this,
&mitk::DataStorage::OnNodeInteractorChanged);
m_NodeInteractorChangedObserverTags[NonConstNode] =
NonConstNode->AddObserver(mitk::DataNode::InteractorChangedEvent(),
interactorChangedCommand);
// add itk delete listener on datastorage
itk::MemberCommand<mitk::DataStorage>::Pointer deleteCommand =
itk::MemberCommand<mitk::DataStorage>::New();
deleteCommand->SetCallbackFunction(this,
&mitk::DataStorage::OnNodeModifiedOrDeleted);
// add observer
m_NodeDeleteObserverTags[NonConstNode] =
NonConstNode->AddObserver(itk::DeleteEvent(), deleteCommand);
}
}
Now we're getting into ITK.
Looks like maybe I should look at itk::ModifiedEvent()
Seems like
Modules/Core/Common/src/itkEventObject.cxx:70:itkEventMacroDefinition(ModifiedEvent,
AnyEvent)
#define itkEventMacroDeclaration(classname, super) \
/** \class classname */ \
class ITKEvent_EXPORT classname:public super \
{ \
public: \
typedef classname Self; \
typedef super Superclass; \
classname(); \
classname(const Self &s); \
virtual ~classname(); \
virtual const char *GetEventName() const; \
virtual bool CheckEvent(const::itk::EventObject * e) const; \
virtual ::itk::EventObject *MakeObject() const; \
private: \
void operator=(const Self &); \
};
#define itkEventMacroDefinition(classname, super) \
classname::classname() {} \
classname::classname(const classname &s):super(s){}; \
classname::~classname() {} \
const char * classname::GetEventName() const { return #classname; } \
bool classname::CheckEvent(const::itk::EventObject * e) const \
{ return ( dynamic_cast< const classname * >( e ) != ITK_NULLPTR ); } \
::itk::EventObject *classname::MakeObject() const { return new classname; } \
I guess most of the interesting stuff is in the EventObject class, but it seems
like this just serves as an intermediary for some other code
ITK_4.9.0>grep ModifiedEvent * -RinF
Modules/Core/Common/include/itkEventObject.h:179:itkEventMacroDeclaration(ModifiedEvent,
AnyEvent)
Modules/Core/Common/include/itkTreeChangeEvent.h:33:class
TreeChangeEvent:public ModifiedEvent
Modules/Core/Common/include/itkTreeChangeEvent.h:39: typedef ModifiedEvent
Superclass;
Modules/Core/Common/include/itkTreeChangeEvent.h:65: TreeChangeEvent(const
Self & s):itk::ModifiedEvent(s) {}
Modules/Core/Common/src/itkEventObject.cxx:70:itkEventMacroDefinition(ModifiedEvent,
AnyEvent)
Modules/Core/Common/src/itkObject.cxx:390: InvokeEvent( ModifiedEvent() );
Modules/Core/Common/wrapping/ITKCommonBase.wrap:13:itk_wrap_simple_class("itk::ModifiedEvent")
Modules/Filtering/LabelMap/include/itkLabelMap.h:472: bool
iEmitModifiedEvent );
Modules/Filtering/LabelMap/include/itkLabelMap.hxx:256: bool
emitModifiedEvent = ( iLabel == m_BackgroundValue );
Modules/Filtering/LabelMap/include/itkLabelMap.hxx:257:
this->RemovePixel( tempIt, idx, emitModifiedEvent );
Modules/Filtering/LabelMap/include/itkLabelMap.hxx:326: bool
iEmitModifiedEvent )
Modules/Filtering/LabelMap/include/itkLabelMap.hxx:337: if(
iEmitModifiedEvent )
Modules/Filtering/LabelMap/include/itkLabelMap.hxx:359: bool emitModifiedEvent
= true;
Modules/Filtering/LabelMap/include/itkLabelMap.hxx:360: RemovePixel( it, idx,
emitModifiedEvent );
Modules/ThirdParty/GDCM/src/gdcm/Source/Common/gdcmEvent.h:91:gdcmEventMacro(
ModifiedEvent , AnyEvent );
Doesn't seem like this is used anywhere. Maybe that's just something that's
treated as a ModifiedEvent, need to figure out where the event is created.
Let me know if you have any suggestions, thanks,
- Alex
On Wed, Aug 26, 2020 at 11:26 AM Alex Melville
<[email protected]<mailto:[email protected]>> wrote:
Hello,
Using the MITK sample project as an example, I would like to add an event
handler for when a node in the Data Manager is renamed by double clicking on it.
I would like to be able to:
- Have our program do something in response to the node being renamed
- Show a message and cancel the renaming operation if it can't be used (e.g.,
if the name is already in use, or invalid)
I would also like this same behavior to happen when the "name" property of a
node is edited in the "Properties" window, I notice that they seem to be tied
together, so this might be the same event.
If this isn't possible, I would also be OK with disabling this double click
rename functionality completely, and the property tree rename too, and using my
own custom UI instead for renaming nodes.
I've been looking through the source, and I've seen some things like
ModifiedEvent in itk that sound promising, but I am having trouble locating
exactly which object / event to hook into.
Thanks,
- Alex
_______________________________________________
mitk-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mitk-users