Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkAbstractNodeSelectionWidget.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 
16 
17 QmitkAbstractNodeSelectionWidget::QmitkAbstractNodeSelectionWidget(QWidget* parent) : QWidget(parent), m_InvalidInfo("Error. Select data."),
18 m_EmptyInfo("Empty. Make a selection."), m_PopUpTitel("Select a data node"), m_PopUpHint(""),
19 m_IsOptional(false), m_SelectOnlyVisibleNodes(true), m_DataStorageDeletedTag(0), m_LastEmissionAllowance(true), m_RecursionGuard(false)
20 {
21 }
22 
24 {
25  auto dataStorage = m_DataStorage.Lock();
26  if (dataStorage.IsNotNull())
27  {
28  // remove Listener for the data storage itself
29  dataStorage->RemoveObserver(m_DataStorageDeletedTag);
30 
31  // remove "add node listener" from data storage
32  dataStorage->AddNodeEvent.RemoveListener(
33  mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));
34 
35  // remove "remove node listener" from data storage
36  dataStorage->RemoveNodeEvent.RemoveListener(
37  mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
38  }
39 
40  for (auto& node : m_CurrentInternalSelection)
41  {
42  this->RemoveNodeObserver(node);
43  }
44 }
45 
47 {
48  return this->CompileEmitSelection();
49 }
50 
52 {
53  if (m_DataStorage == dataStorage)
54  {
55  return;
56  }
57 
58  auto oldStorage = m_DataStorage.Lock();
59  if (oldStorage.IsNotNull())
60  {
61  // remove Listener for the data storage itself
62  oldStorage->RemoveObserver(m_DataStorageDeletedTag);
63 
64  // remove "add node listener" from old data storage
65  oldStorage->AddNodeEvent.RemoveListener(
66  mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));
67 
68  // remove "remove node listener" from old data storage
69  oldStorage->RemoveNodeEvent.RemoveListener(
70  mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
71  }
72 
73  m_DataStorage = dataStorage;
74 
75  auto newStorage = m_DataStorage.Lock();
76 
77  if (newStorage.IsNotNull())
78  {
79  // add Listener for the data storage itself
80  auto command = itk::SimpleMemberCommand<QmitkAbstractNodeSelectionWidget>::New();
81  command->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted);
82  m_DataStorageDeletedTag = newStorage->AddObserver(itk::DeleteEvent(), command);
83 
84  // add "add node listener" for new data storage
85  newStorage->AddNodeEvent.AddListener(
86  mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage));
87 
88  // add remove node listener for new data storage
89  newStorage->RemoveNodeEvent.AddListener(
90  mitk::MessageDelegate1<QmitkAbstractNodeSelectionWidget, const mitk::DataNode*>(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage));
91  }
92 
93  this->OnDataStorageChanged();
94 
96 }
97 
99 {
100  if (m_NodePredicate != nodePredicate)
101  {
102  m_NodePredicate = nodePredicate;
103 
104  this->OnNodePredicateChanged();
105 
106  NodeList newInternalNodes;
107 
108  for (auto& node : m_CurrentInternalSelection)
109  {
110  if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node))
111  {
112  newInternalNodes.append(node);
113  }
114  }
115 
117  {
118  for (auto& node : m_CurrentExternalSelection)
119  {
120  if (!newInternalNodes.contains(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)))
121  {
122  newInternalNodes.append(node);
123  }
124  }
125  }
126 
127  this->HandleChangeOfInternalSelection(newInternalNodes);
128  }
129 }
130 
132 {
133  this->ReviseSelectionChanged(m_CurrentInternalSelection, newInternalSelection);
134 
135  this->SetCurrentInternalSelection(newInternalSelection);
136 
138 
139  auto newEmission = this->CompileEmitSelection();
140 
141  this->EmitSelection(newEmission);
142 
143  this->UpdateInfo();
144 }
145 
147 {
148  if (!m_RecursionGuard)
149  {
150  m_CurrentExternalSelection = selectedNodes;
151 
152  auto dataStorage = m_DataStorage.Lock();
153  NodeList newInternalSelection;
154  for (auto node : selectedNodes)
155  {
156  if (dataStorage.IsNotNull() && dataStorage->Exists(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)))
157  {
158  newInternalSelection.append(node);
159  }
160  }
161 
162  this->HandleChangeOfInternalSelection(newInternalSelection);
163  }
164 }
165 
167 {
168  return m_NodePredicate;
169 }
170 
172 {
173  return m_InvalidInfo;
174 }
175 
177 {
178  return m_EmptyInfo;
179 }
180 
182 {
183  return m_PopUpTitel;
184 }
185 
187 {
188  return m_PopUpHint;
189 }
190 
192 {
193  return m_IsOptional;
194 }
195 
197 {
199 }
200 
202 {
203  if (m_SelectOnlyVisibleNodes != selectOnlyVisibleNodes)
204  {
205  m_SelectOnlyVisibleNodes = selectOnlyVisibleNodes;
206 
207  auto newEmission = this->CompileEmitSelection();
208 
209  this->EmitSelection(newEmission);
210  }
211 }
212 
214 {
216  this->UpdateInfo();
217 }
218 
220 {
221  m_EmptyInfo = info;
222  this->UpdateInfo();
223 }
224 
226 {
227  m_PopUpTitel = info;
228 }
229 
231 {
232  m_PopUpHint = info;
233 }
234 
236 {
237  m_IsOptional = isOptional;
238  this->UpdateInfo();
239 }
240 
241 void QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted()
242 {
243  this->OnDataStorageChanged();
245 }
246 
247 void QmitkAbstractNodeSelectionWidget::ReviseSelectionChanged(const NodeList& /*oldInternalSelection*/, NodeList& /*newInternalSelection*/)
248 {
249 }
250 
252 {
253  return true;
254 }
255 
257 {
258  m_LastEmissionAllowance = this->AllowEmissionOfSelection(emissionCandidates);
259  if (m_LastEmissionAllowance && !EqualNodeSelections(m_LastEmission, emissionCandidates))
260  {
261  m_RecursionGuard = true;
262  emit CurrentSelectionChanged(emissionCandidates);
263  m_RecursionGuard = false;
264  m_LastEmission = emissionCandidates;
265  }
266 }
267 
269 {
270  for (auto& node : m_CurrentInternalSelection)
271  {
272  this->RemoveNodeObserver(node);
273  }
274 
275  m_CurrentInternalSelection = selectedNodes;
276 
277  for (auto& node : m_CurrentInternalSelection)
278  {
279  this->AddNodeObserver(node);
280  }
281 }
282 
284 {
285  return m_CurrentInternalSelection;
286 }
287 
289 {
290  return m_CurrentExternalSelection;
291 }
292 
294 {
295 }
296 
298 {
299 }
300 
302 {
303 }
304 
305 void QmitkAbstractNodeSelectionWidget::NodeAddedToStorage(const mitk::DataNode* node)
306 {
307  this->OnNodeAddedToStorage(node);
308 }
309 
311 {
312 }
313 
314 void QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage(const mitk::DataNode* node)
315 {
316  this->OnNodeRemovedFromStorage(node);
317  this->RemoveNodeFromSelection(node);
318 }
319 
321 {
322 }
323 
325 {
326  NodeList result = m_CurrentInternalSelection;
327 
329  {
330  for (auto node : m_CurrentExternalSelection)
331  {
332  if (!result.contains(node) && m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node))
333  {
334  result.append(node);
335  }
336  }
337  }
338 
339  return result;
340 }
341 
343 {
344  auto newSelection = m_CurrentInternalSelection;
345 
346  auto finding = std::find(std::begin(newSelection), std::end(newSelection), node);
347 
348  if (finding != std::end(newSelection))
349  {
350  newSelection.erase(finding);
351  this->HandleChangeOfInternalSelection(newSelection);
352  }
353 }
354 
355 void QmitkAbstractNodeSelectionWidget::OnNodeModified(const itk::Object * caller, const itk::EventObject & event)
356 {
357  if (itk::ModifiedEvent().CheckEvent(&event))
358  {
359  auto node = dynamic_cast<const mitk::DataNode*>(caller);
360 
361  if (node)
362  {
363  if (m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node))
364  {
365  this->RemoveNodeFromSelection(node);
366  }
367  else
368  {
369  auto oldAllowance = m_LastEmissionAllowance;
370  auto newEmission = this->CompileEmitSelection();
371  auto nonConstNode = const_cast<mitk::DataNode*>(node);
372  if (newEmission.contains(nonConstNode) && (oldAllowance != this->AllowEmissionOfSelection(newEmission)))
373  {
374  this->EmitSelection(newEmission);
375  this->UpdateInfo();
376  }
377  }
378  }
379  }
380 }
381 
382 void QmitkAbstractNodeSelectionWidget::AddNodeObserver(mitk::DataNode* node)
383 {
384  if (node)
385  {
386  auto modifiedCommand = itk::MemberCommand<QmitkAbstractNodeSelectionWidget>::New();
387  modifiedCommand->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::OnNodeModified);
388 
389  auto nodeModifiedObserverTag = node->AddObserver(itk::ModifiedEvent(), modifiedCommand);
390 
391  m_NodeObserverTags.insert(std::make_pair(node, nodeModifiedObserverTag));
392  }
393 }
394 
395 void QmitkAbstractNodeSelectionWidget::RemoveNodeObserver(mitk::DataNode* node)
396 {
397  if (node)
398  {
399  auto finding = m_NodeObserverTags.find(node);
400  if (finding != std::end(m_NodeObserverTags))
401  {
402  node->RemoveObserver(finding->second);
403  }
404  else
405  {
406  MITK_ERROR << "Selection widget is in a wrong state. A node should be removed from the internal selection but seems to have no observer. Node:" << node;
407  }
408  m_NodeObserverTags.erase(node);
409  }
410 }
virtual void OnNodeRemovedFromStorage(const mitk::DataNode *node)
void SetDataStorage(mitk::DataStorage *dataStorage)
Sets the data storage that will be used /monitored by widget.
Data management class that handles &#39;was created by&#39; relations.
itk::SmartPointer< T > Lock() const
const mitk::NodePredicateBase * GetNodePredicate() const
void RemoveNodeFromSelection(const mitk::DataNode *node)
#define MITK_ERROR
Definition: mitkLogMacros.h:20
void SetCurrentInternalSelection(NodeList selectedNodes)
QList< mitk::DataNode::Pointer > NodeList
virtual void ReviseSelectionChanged(const NodeList &oldInternalSelection, NodeList &newInternalSelection)
void CurrentSelectionChanged(NodeList nodes)
static void info(const char *fmt,...)
Definition: svm.cpp:86
void SetNodePredicate(const mitk::NodePredicateBase *nodePredicate)
mitk::WeakPointer< mitk::DataStorage > m_DataStorage
virtual void OnNodeAddedToStorage(const mitk::DataNode *node)
bool MITKQTWIDGETS_EXPORT EqualNodeSelections(const QList< mitk::DataNode::Pointer > &selection1, const QList< mitk::DataNode::Pointer > &selection2)
void SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes)
mitk::NodePredicateBase::ConstPointer m_NodePredicate
Interface for evaluation conditions used in the DataStorage class GetSubset() method.
void EmitSelection(const NodeList &emissionCandidates)
virtual bool AllowEmissionOfSelection(const NodeList &emissionCandidates) const
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
void HandleChangeOfInternalSelection(NodeList newInternalSelection)