Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
QmitkAbstractView.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 #include "QmitkAbstractView.h"
15 #include "internal/QmitkCommonActivator.h"
16 #include "internal/QmitkDataNodeItemModel.h"
17 
18 // mitk Includes
19 #include <mitkLogMacros.h>
22 #include <mitkDataNodeObject.h>
23 #include <mitkIRenderingManager.h>
24 
25 // berry Includes
26 #include <berryIWorkbenchPage.h>
27 #include <berryIBerryPreferences.h>
28 #include <berryIEditorPart.h>
30 #include <berryUIException.h>
31 
32 // CTK Includes
33 #include <ctkServiceTracker.h>
34 
35 // Qt Includes
36 #include <QItemSelectionModel>
37 #include <QApplication>
38 #include <QMessageBox>
39 #include <QScrollArea>
40 #include <QVBoxLayout>
41 
42 class QmitkAbstractViewPrivate
43 {
44 public:
45 
46  QmitkAbstractViewPrivate(QmitkAbstractView* qq)
47  : q(qq)
48  , m_PrefServiceTracker(QmitkCommonActivator::GetContext())
49  , m_DataStorageServiceTracker(QmitkCommonActivator::GetContext())
50  , m_Parent(nullptr)
51  , m_DataNodeItemModel(new QmitkDataNodeItemModel)
52  , m_DataNodeSelectionModel(new QItemSelectionModel(m_DataNodeItemModel))
53  , m_InDataStorageChanged(false)
54  {
55  m_PrefServiceTracker.open();
56  m_DataStorageServiceTracker.open();
57  }
58 
59  ~QmitkAbstractViewPrivate()
60  {
61  delete m_DataNodeSelectionModel;
62  delete m_DataNodeItemModel;
63 
64  m_PrefServiceTracker.close();
65  m_DataStorageServiceTracker.close();
66  }
67 
73  void NodeAddedProxy(const mitk::DataNode* node)
74  {
75  // garantuee no recursions when a new node event is thrown in NodeAdded()
76  if(!m_InDataStorageChanged)
77  {
78  m_InDataStorageChanged = true;
79  q->NodeAdded(node);
80  q->DataStorageModified();
81  m_InDataStorageChanged = false;
82  }
83  }
84 
90  void NodeRemovedProxy(const mitk::DataNode* node)
91  {
92  // garantuee no recursions when a new node event is thrown in NodeAdded()
93  if(!m_InDataStorageChanged)
94  {
95  m_InDataStorageChanged = true;
96  q->NodeRemoved(node);
97  q->DataStorageModified();
98  m_InDataStorageChanged = false;
99  }
100  }
101 
107  void NodeChangedProxy(const mitk::DataNode* node)
108  {
109  // garantuee no recursions when a new node event is thrown in NodeAdded()
110  if(!m_InDataStorageChanged)
111  {
112  m_InDataStorageChanged = true;
113  q->NodeChanged(node);
114  q->DataStorageModified();
115  m_InDataStorageChanged = false;
116  }
117  }
118 
122  void BlueBerrySelectionChanged(const berry::IWorkbenchPart::Pointer& sourcepart,
123  const berry::ISelection::ConstPointer& selection)
124  {
125  if(sourcepart.IsNull() || sourcepart.GetPointer() == static_cast<berry::IWorkbenchPart*>(q))
126  return;
127 
128  if(selection.IsNull())
129  {
130  q->OnNullSelection(sourcepart);
131  return;
132  }
133 
134  mitk::DataNodeSelection::ConstPointer _DataNodeSelection
135  = selection.Cast<const mitk::DataNodeSelection>();
136  q->OnSelectionChanged(sourcepart, this->DataNodeSelectionToQList(_DataNodeSelection));
137  }
138 
142  QList<mitk::DataNode::Pointer> DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const;
143 
144  QmitkAbstractView* const q;
145 
146  ctkServiceTracker<berry::IPreferencesService*> m_PrefServiceTracker;
147 
148  ctkServiceTracker<mitk::IDataStorageService*> m_DataStorageServiceTracker;
149 
154  QWidget* m_Parent;
155 
159  QmitkDataNodeSelectionProvider::Pointer m_SelectionProvider;
160 
164  QmitkDataNodeItemModel* m_DataNodeItemModel;
165 
169  QItemSelectionModel* m_DataNodeSelectionModel;
170 
174  QScopedPointer<berry::ISelectionListener> m_BlueBerrySelectionListener;
175 
180  bool m_InDataStorageChanged;
181 
182 };
183 
185  : d(new QmitkAbstractViewPrivate(this))
186 {
187 }
188 
189 void QmitkAbstractView::CreatePartControl(QWidget* parent)
190 {
191 
192  // scrollArea
193  auto scrollArea = new QScrollArea;
194  //QVBoxLayout* scrollAreaLayout = new QVBoxLayout(scrollArea);
195  scrollArea->setFrameShadow(QFrame::Plain);
196  scrollArea->setFrameShape(QFrame::NoFrame);
197  scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
198  scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
199 
200  // m_Parent
201  d->m_Parent = new QWidget;
202  //m_Parent->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
203  this->CreateQtPartControl(d->m_Parent);
204 
205  //scrollAreaLayout->addWidget(m_Parent);
206  //scrollArea->setLayout(scrollAreaLayout);
207 
208  // set the widget now
209  scrollArea->setWidgetResizable(true);
210  scrollArea->setWidget(d->m_Parent);
211 
212  // add the scroll area to the real parent (the view tabbar)
213  QWidget* parentQWidget = static_cast<QWidget*>(parent);
214  auto parentLayout = new QVBoxLayout(parentQWidget);
215  parentLayout->setMargin(0);
216  parentLayout->setSpacing(0);
217  parentLayout->addWidget(scrollArea);
218 
219  // finally set the layout containing the scroll area to the parent widget (= show it)
220  parentQWidget->setLayout(parentLayout);
221 
222  this->AfterCreateQtPartControl();
223 }
224 
225 void QmitkAbstractView::AfterCreateQtPartControl()
226 {
227  this->SetSelectionProvider();
228 
229  // REGISTER DATASTORAGE LISTENER
231  ( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) );
233  ( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) );
235  ( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy ) );
236 
237  // REGISTER PREFERENCES LISTENER
239  if(prefs.IsNotNull())
240  prefs->OnChanged.AddListener(
242  &QmitkAbstractView::OnPreferencesChanged));
243 
244  // REGISTER FOR WORKBENCH SELECTION EVENTS
245  d->m_BlueBerrySelectionListener.reset(new berry::NullSelectionChangedAdapter<QmitkAbstractViewPrivate>(
246  d.data(), &QmitkAbstractViewPrivate::BlueBerrySelectionChanged));
247  this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(d->m_BlueBerrySelectionListener.data());
248 
249  // EMULATE INITIAL SELECTION EVENTS
250 
251  // send the current selection
252  berry::IWorkbenchPart::Pointer activePart = this->GetSite()->GetPage()->GetActivePart();
253  if (activePart.IsNotNull())
254  {
255  this->OnSelectionChanged(activePart, this->GetCurrentSelection());
256  }
257 
258  // send preferences changed event
259  this->OnPreferencesChanged(this->GetPreferences().Cast<berry::IBerryPreferences>().GetPointer());
260 }
261 
263 {
264  this->Register();
265 
267  ( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) );
269  ( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy) );
271  ( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) );
272 
274  if(prefs.IsNotNull())
275  {
276  prefs->OnChanged.RemoveListener(
278  &QmitkAbstractView::OnPreferencesChanged));
279  // flush the preferences here (disabled, everyone should flush them by themselves at the right moment)
280  // prefs->Flush();
281  }
282 
283  // REMOVE SELECTION PROVIDER
284  this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(nullptr));
285 
286  berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
287  if(s)
288  {
289  s->RemovePostSelectionListener(d->m_BlueBerrySelectionListener.data());
290  }
291 
292  this->UnRegister(false);
293 }
294 
295 void QmitkAbstractView::SetSelectionProvider()
296 {
297  // REGISTER A SELECTION PROVIDER
299  d->m_SelectionProvider->SetItemSelectionModel(GetDataNodeSelectionModel());
300  this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(d->m_SelectionProvider));
301 }
302 
303 QItemSelectionModel *QmitkAbstractView::GetDataNodeSelectionModel() const
304 {
305  return nullptr;
306 }
307 
308 void QmitkAbstractView::OnPreferencesChanged( const berry::IBerryPreferences* )
309 {
310 }
311 
312 void QmitkAbstractView::DataStorageModified()
313 {
314 }
315 
316 void QmitkAbstractView::DataStorageChanged(mitk::IDataStorageReference::Pointer /*dsRef*/)
317 {
318 }
319 
320 mitk::IRenderWindowPart* QmitkAbstractView::GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategies strategies) const
321 {
322  berry::IWorkbenchPage::Pointer page = GetSite()->GetPage();
323  return mitk::WorkbenchUtil::GetRenderWindowPart(page, strategies);
324 }
325 
327 {
328  mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart();
329  if (renderPart == nullptr) return;
330 
331  if (mitk::IRenderingManager* renderingManager = renderPart->GetRenderingManager())
332  {
333  renderingManager->RequestUpdateAll(requestType);
334  }
335  else
336  {
337  renderPart->RequestUpdate(requestType);
338  }
339 }
340 
341 void QmitkAbstractView::HandleException( const char* str, QWidget* parent, bool showDialog ) const
342 {
343  //itkGenericOutputMacro( << "Exception caught: " << str );
344  MITK_ERROR << str;
345  if ( showDialog )
346  {
347  QMessageBox::critical ( parent, "Exception caught!", str );
348  }
349 }
350 
351 void QmitkAbstractView::HandleException( std::exception& e, QWidget* parent, bool showDialog ) const
352 {
353  HandleException( e.what(), parent, showDialog );
354 }
355 
357 {
358  QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
359 }
360 
362 {
363  QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) );
364 }
365 
367 {
368  this->RestoreOverrideCursor();
369 }
370 
372 {
373  this->RestoreOverrideCursor();
374 }
375 
377 {
378  QApplication::restoreOverrideCursor();
379 }
380 
382 {
383  berry::IPreferencesService* prefService = d->m_PrefServiceTracker.getService();
384  // const_cast workaround for bad programming: const uncorrectness this->GetViewSite() should be const
385  QString id = "/" + (const_cast<QmitkAbstractView*>(this))->GetViewSite()->GetId();
386  return prefService ? prefService->GetSystemPreferences()->Node(id): berry::IPreferences::Pointer(nullptr);
387 }
388 
391 {
392  mitk::IDataStorageService* dsService = d->m_DataStorageServiceTracker.getService();
393 
394  if (dsService != nullptr)
395  {
396  return dsService->GetDataStorage()->GetDataStorage();
397  }
398 
399  return nullptr;
400 }
401 
403 {
404  mitk::IDataStorageService* dsService = d->m_DataStorageServiceTracker.getService();
405 
406  if (dsService != nullptr)
407  {
408  return dsService->GetDataStorage();
409  }
410 
411  return mitk::IDataStorageReference::Pointer(nullptr);
412 }
413 
414 QList<mitk::DataNode::Pointer> QmitkAbstractView::GetCurrentSelection() const
415 {
416  berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection());
417  mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast<const mitk::DataNodeSelection>();
418  return d->DataNodeSelectionToQList(currentSelection);
419 }
420 
422 {
423  return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection();
424 }
425 
426 QList<mitk::DataNode::Pointer> QmitkAbstractView::GetDataManagerSelection() const
427 {
428  berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
429  mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast<const mitk::DataNodeSelection>();
430  return d->DataNodeSelectionToQList(currentSelection);
431 }
432 
434 {
435  return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager");
436 }
437 
439  QItemSelectionModel::SelectionFlags flags) const
440 {
441  berry::IViewPart::Pointer datamanagerView = this->GetSite()->GetWorkbenchWindow()->GetActivePage()->FindView("org.mitk.views.datamanager");
442  if (datamanagerView.IsNull()) return;
443 
444  datamanagerView->GetSite()->GetSelectionProvider().Cast<berry::QtSelectionProvider>()->SetSelection(selection, flags);
445 }
446 
448 {
449  berry::ISelection::ConstPointer currentSelection = this->GetSite()->GetSelectionProvider()->GetSelection();
450  if (currentSelection.IsNull()) return;
451 
452  SetDataManagerSelection(currentSelection);
453 }
454 
455 void QmitkAbstractView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/,
456  const QList<mitk::DataNode::Pointer>& /*nodes*/)
457 {
458 }
459 
460 void QmitkAbstractView::OnNullSelection(berry::IWorkbenchPart::Pointer /*part*/)
461 {
462 }
463 
464 QList<mitk::DataNode::Pointer> QmitkAbstractViewPrivate::DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const
465 {
466  if (currentSelection.IsNull()) return QList<mitk::DataNode::Pointer>();
467  return QList<mitk::DataNode::Pointer>::fromStdList(currentSelection->GetSelectedDataNodes());
468 }
469 
470 void QmitkAbstractView::NodeAdded( const mitk::DataNode* /*node*/ )
471 {
472 }
473 
474 void QmitkAbstractView::NodeRemoved( const mitk::DataNode* /*node*/ )
475 {
476 }
477 
478 void QmitkAbstractView::NodeChanged( const mitk::DataNode* /*node*/ )
479 {
480 }
481 
483 {
484  QList<mitk::DataNode::Pointer> nodes;
485  nodes << node;
486  this->FireNodesSelected(nodes);
487 }
488 
489 void QmitkAbstractView::FireNodesSelected( const QList<mitk::DataNode::Pointer>& nodes )
490 {
491  // if this is the first call to FireNodesSelected and the selection provider has no QItemSelectiomMode
492  // yet, set our helper model
493  if (d->m_SelectionProvider->GetItemSelectionModel() == nullptr)
494  {
495  d->m_SelectionProvider->SetItemSelectionModel(d->m_DataNodeSelectionModel);
496  }
497  else if (d->m_SelectionProvider->GetItemSelectionModel() != d->m_DataNodeSelectionModel)
498  {
499  MITK_WARN << "A custom data node selection model has been set. Ignoring call to FireNodesSelected().";
500  return;
501  }
502 
503  if (nodes.empty())
504  {
505  d->m_DataNodeSelectionModel->clearSelection();
506  d->m_DataNodeItemModel->clear();
507  }
508  else
509  {
510 
511  // The helper data node model is just used for sending selection events.
512  // We add the to be selected nodes and set the selection range to everything.
513 
514  d->m_DataNodeItemModel->clear();
515  foreach(mitk::DataNode::Pointer node, nodes)
516  {
517  d->m_DataNodeItemModel->AddDataNode(node);
518  }
519  d->m_DataNodeSelectionModel->select(QItemSelection(d->m_DataNodeItemModel->index(0,0), d->m_DataNodeItemModel->index(nodes.size()-1, 0)),
520  QItemSelectionModel::ClearAndSelect);
521  }
522 }
A BlueBerry selection provider for mitk::DataNode selections.
virtual void RemovePostSelectionListener(ISelectionListener *listener)=0
virtual void RequestUpdate(mitk::RenderingManager::RequestType requestType=mitk::RenderingManager::REQUEST_UPDATE_ALL)=0
void FireNodeSelected(mitk::DataNode::Pointer node)
#define MITK_ERROR
Definition: mitkLogMacros.h:20
mitk::IDataStorageReference::Pointer GetDataStorageReference() const
virtual mitk::IRenderingManager * GetRenderingManager() const =0
SmartPointer< Other > Cast() const
void RequestRenderWindowUpdate(mitk::RenderingManager::RequestType requestType=mitk::RenderingManager::REQUEST_UPDATE_ALL)
virtual IDataStorageReference::Pointer GetDataStorage() const =0
mitk::IRenderWindowPart * GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategies strategies=mitk::WorkbenchUtil::NONE) const
Interface for a MITK Workbench Part providing a render window.
static IRenderWindowPart * GetRenderWindowPart(berry::IWorkbenchPage::Pointer page, IRenderWindowPartStrategies strategies)
Returns the currently active mitk::IRenderWindowPart.
virtual SmartPointer< IPreferences > GetSystemPreferences()=0
void Register() const
bool IsCurrentSelectionValid() const
QList< mitk::DataNode::Pointer > GetDataManagerSelection() const
void UnRegister(bool del=true) const
virtual void FireNodesSelected(const QList< mitk::DataNode::Pointer > &nodes)
berry::SmartPointer< Self > Pointer
Definition: berryObject.h:82
virtual void CreateQtPartControl(QWidget *parent)=0
void SynchronizeDataManagerSelection() const
#define MITK_WARN
Definition: mitkLogMacros.h:19
void HandleException(std::exception &e, QWidget *parent=nullptr, bool showDialog=true) const
A convenient base class for MITK related BlueBerry Views.
mitk::DataStorage::Pointer GetDataStorage() const
QList< mitk::DataNode::Pointer > GetCurrentSelection() const
berry::SmartPointer< Self > Pointer
void SetDataManagerSelection(const berry::ISelection::ConstPointer &selection, QItemSelectionModel::SelectionFlags flags=QItemSelectionModel::ClearAndSelect) const
An interface for accessing a mitk::RenderingManager instance.
bool IsDataManagerSelectionValid() const
berry::IPreferences::Pointer GetPreferences() const
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
IWorkbenchPartSite::Pointer GetSite() const override
ObjectType * GetPointer() const