Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkOverlayController.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 "QmitkOverlayController.h"
14 
15 #include "QmitkOverlay.h"
17 #include "QmitkRenderWindow.h"
18 
19 #include <QHBoxLayout>
20 #include <QVBoxLayout>
21 
22 #include <algorithm>
23 
25  : QObject(), m_RenderWindow(rw), m_PropertyList(pl)
26 {
27  if (m_RenderWindow == nullptr)
28  {
29  MITK_ERROR << "invalid QmitkRenderWindow";
30  return;
31  }
32 
33  connect(rw, SIGNAL(moved()), this, SLOT(AdjustAllOverlayPosition()));
34 
37  this->SetOverlayVisibility(true);
38 
39  if (m_PropertyList.IsNull())
41 }
42 
44 {
45 }
46 
48 {
49  // setup widget for each position
58 }
59 
61 {
62  // create a new QWidget as Tool & FramelessWindowHint
63  m_PositionedOverlays[pos] = new QmitkOverlayContainerWidget(m_RenderWindow, Qt::Tool | Qt::FramelessWindowHint);
64 
65 // autoFillBackGround(false) and WA_TranslucentBackground = true are needed to have a translucent background
66 // transparency does NOT work under Win-XP 32-Bit --> paint black background
67 
68 #if !defined(_WIN32) || defined(_WIN64)
69  m_PositionedOverlays[pos]->setAttribute(Qt::WA_TranslucentBackground, true);
70 #else
71  m_PositionedOverlays[pos]->setStyleSheet("QWidget { background: black }");
72  m_PositionedOverlays[pos]->setAttribute(Qt::WA_TranslucentBackground, false);
73 #endif
74 
75  // X11 specific attributes
76  m_PositionedOverlays[pos]->setAttribute(Qt::WA_X11NetWmWindowTypeUtility, true);
77 
78  // mac-specific attributes:
79  // making sure overlays are even visible if RenderWindow does not have the focus (not default for Qt::Tool on mac)
80  m_PositionedOverlays[pos]->setAttribute(Qt::WA_MacAlwaysShowToolWindow, true);
81  // testing something
82  m_PositionedOverlays[pos]->setAttribute(Qt::WA_MacShowFocusRect, false);
83 
84  // overlays should not get the focus
85  m_PositionedOverlays[pos]->setFocusPolicy(Qt::NoFocus);
86 
87  // setting the color of the background to transparent - not sure it's needed after the attributes have been set above
88  QPalette p = QPalette();
89  p.setColor(QPalette::Window, Qt::transparent);
90  m_PositionedOverlays[pos]->setPalette(p);
91 
92  // setting position-specific properties
93  switch (pos)
94  {
96  {
97  // adding left-aligned top-to-bottom layout
98  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
99  layout->setDirection(QBoxLayout::TopToBottom);
100  layout->setAlignment(Qt::AlignLeft);
101  m_PositionedOverlays[pos]->layout()->setSpacing(0);
102  break;
103  }
105  {
106  // adding center-aligned top-to-bottom layout
107  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
108  layout->setDirection(QBoxLayout::TopToBottom);
109  layout->setAlignment(Qt::AlignCenter);
110  layout->setAlignment(Qt::AlignLeft);
111  m_PositionedOverlays[pos]->layout()->setSpacing(0);
112  break;
113  }
115  {
116  // adding right-aligned top-to-bottom layout
117  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
118  layout->setDirection(QBoxLayout::TopToBottom);
119  layout->setAlignment(Qt::AlignRight);
120  m_PositionedOverlays[pos]->layout()->setSpacing(0);
121  break;
122  }
124  {
125  // adding left-aligned left-to-right layout
126  QHBoxLayout *layout = new QHBoxLayout(m_PositionedOverlays[pos]);
127  layout->setDirection(QBoxLayout::LeftToRight);
128  layout->setAlignment(Qt::AlignLeft);
129  layout->setSpacing(3);
130  break;
131  }
133  {
134  // adding right-aligned right-to-left layout
135  QHBoxLayout *layout = new QHBoxLayout(m_PositionedOverlays[pos]);
136  layout->setDirection(QBoxLayout::RightToLeft);
137  layout->setAlignment(Qt::AlignRight);
138  layout->setSpacing(3);
139  break;
140  }
142  {
143  // adding left-aligned bottom-to-top layout
144  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
145  layout->setDirection(QBoxLayout::BottomToTop);
146  layout->setAlignment(Qt::AlignLeft);
147  m_PositionedOverlays[pos]->layout()->setSpacing(0);
148  break;
149  }
151  {
152  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
153  layout->setDirection(QBoxLayout::BottomToTop);
154  layout->setAlignment(Qt::AlignCenter);
155  m_PositionedOverlays[pos]->layout()->setSpacing(0);
156  break;
157  }
159  {
160  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
161  layout->setDirection(QBoxLayout::BottomToTop);
162  layout->setAlignment(Qt::AlignRight);
163  m_PositionedOverlays[pos]->layout()->setSpacing(0);
164  break;
165  }
166  }
167 }
168 
170 {
179 }
180 
182 {
183  QWidget *widget = m_PositionedOverlays[displayPosition];
184  QSize size = GetMinimumSizeForWidget(displayPosition);
185  QPoint pos;
186 
187  switch (displayPosition)
188  {
190  {
191  // setting position of top-left overlay-container
192  pos = m_RenderWindow->mapToGlobal(QPoint(0, 0));
193  m_PositionedOverlays[QmitkOverlay::top_Left]->move(pos.x(), pos.y());
194 
195  break;
196  }
197 
199  {
200  // setting position of top-center overlay-container
201  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
202 
203  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width() / 2, 0));
204  widget->move(pos.x() - widget->size().width() / 2, pos.y());
205 
206  break;
207  }
208 
210  {
211  // setting position of top-right overlay-container
212  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
213 
214  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width(), 0));
215  widget->move(pos.x() - widget->size().width(), pos.y());
216 
217  break;
218  }
219 
221  {
222  // setting position of middle-left overlay-container
223  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
224 
225  pos = m_RenderWindow->mapToGlobal(QPoint(0, m_RenderWindow->size().height() / 2));
226  widget->move(pos.x(), pos.y() - widget->size().height() / 2);
227 
228  break;
229  }
230 
232  {
233  // setting position of middle-right overlay-container
234  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
235 
236  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width(), m_RenderWindow->size().height() / 2));
237  widget->move(pos.x() - widget->size().width(), pos.y() - widget->size().height() / 2);
238 
239  break;
240  }
241 
243  {
244  // setting position of bottom-left overlay-container
245  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
246 
247  pos = m_RenderWindow->mapToGlobal(QPoint(0, m_RenderWindow->size().height()));
248  widget->move(pos.x(), pos.y() - widget->size().height());
249 
250  break;
251  }
252 
254  {
255  // setting position of bottom-center overlay-container
256  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
257 
258  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width() / 2, m_RenderWindow->size().height()));
259  widget->move(pos.x() - widget->size().width() / 2, pos.y() - widget->size().height());
260 
261  break;
262  }
263 
265  {
266  // setting position of bottom-right overlay-container
267  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
268 
269  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width(), m_RenderWindow->size().height()));
270  widget->move(pos.x() - widget->size().width(), pos.y() - widget->size().height());
271 
272  break;
273  }
274  }
275 }
276 
278 {
279  OverlayPositionMap::iterator overlayIter;
280  for (overlayIter = m_PositionedOverlays.begin(); overlayIter != m_PositionedOverlays.end(); overlayIter++)
281  {
282  if (visible)
283  {
284  (overlayIter->second)->show();
285  }
286  else
287  {
288  (overlayIter->second)->hide();
289  }
290  }
291 
292  OverlayVector::iterator allOverlaysIter;
293  for (allOverlaysIter = m_AllOverlays.begin(); allOverlaysIter != m_AllOverlays.end(); allOverlaysIter++)
294  {
295  if (visible)
296  {
297  (*allOverlaysIter)->GetWidget()->show();
298  }
299  else
300  {
301  (*allOverlaysIter)->GetWidget()->hide();
302  }
303  }
304 }
305 
307 {
308  // if no renderwindow has been set, it's not possible to add overlays...
309  if (m_RenderWindow == nullptr)
310  {
311  MITK_ERROR << "invalid QmitkRenderWindow";
312  return;
313  }
314 
315  if (overlay != nullptr)
316  {
317  // get desired position and layer of the overlay
319 
320  // concatenate local propertyList and propertyList of the RenderingManager
321  // local properties have priority as they are not overwritten if preset in both
323  false);
324 
325  // add the overlay to the OverlayContainer in the RenderWindow ...
326  overlay->GetWidget()->setParent(m_PositionedOverlays[pos]);
327 
328  // ... and set it up with the correct properties
329  this->UpdateOverlayData(overlay);
330 
331  // add overlay to list of all overlays and correctly put it into the layering
332  m_AllOverlays.push_back(overlay);
333  this->RestackOverlays(pos);
334 
335  // ... and reset the position of the widgets
336  this->AdjustOverlayPosition(pos);
337  }
338 }
339 
341 {
342  if (overlay != nullptr)
343  {
344  overlay->GenerateData(m_PropertyList);
346  }
347 }
348 
350 {
351  foreach (QmitkOverlay *overlay, m_AllOverlays)
352  {
353  overlay->GetWidget()->setParent(nullptr);
354  overlay->GetWidget()->hide();
355  overlay->deleteLater();
356  }
357 
358  m_AllOverlays.clear();
359 }
360 
362 {
363  if (overlay != nullptr)
364  {
365  // get desired position and layer of the overlay
367 
368  OverlayVector::iterator iter = std::find(m_AllOverlays.begin(), m_AllOverlays.end(), overlay);
369 
370  if (iter != m_AllOverlays.end())
371  {
372  m_AllOverlays.erase(iter);
373  overlay->GetWidget()->setParent(nullptr);
374  overlay->GetWidget()->hide();
375 
376  if (m_PositionedOverlays[pos]->layout()->isEmpty())
377  {
378  m_PositionedOverlays[pos]->hide();
379  }
380  else
381  {
382  this->RestackOverlays(pos);
383  // reset the position of the widgets
384  this->AdjustOverlayPosition(pos);
385  }
386  }
387 
388  overlay->deleteLater();
389  }
390 }
391 
393 {
394  // OverlayVector::iterator overlayIter;
395 
396  // for ( overlayIter=m_AllOverlays.begin(); overlayIter!=m_AllOverlays.end(); overlayIter++ )
397  //{
398  // int stackLayer = dynamic_cast<QBoxLayout*>( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout()
399  // )->isEmpty() ? 0 : layer;
400  // dynamic_cast<QBoxLayout*>( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout() )->addWidget(
401  // (*overlayIter)->GetWidget(), stackLayer, Qt::AlignLeft );
402  //}
403 }
404 
406 {
407  OverlayVector::iterator overlayIter;
408  QBoxLayout *layout = dynamic_cast<QBoxLayout *>(m_PositionedOverlays[pos]->layout());
409 
410  std::sort(m_AllOverlays.begin(), m_AllOverlays.end());
411 
412  for (overlayIter = m_AllOverlays.begin(); overlayIter != m_AllOverlays.end(); overlayIter++)
413  {
414  // do nothing if the overlay is not in the right position
415  if ((*overlayIter)->GetPosition() != pos)
416  {
417  continue;
418  }
419 
420  // determine the desired stacking layer
421  // if the overlay-container is empty, simply append the overlay to the list
422  // if it's not empty, use the layer of the overlay
423  unsigned int layer = (*overlayIter)->GetLayer();
424  int stackLayer = 0;
425  if (!layout->isEmpty())
426  {
427  stackLayer = layer;
428  }
429 
430  switch (pos)
431  {
432  // same alignment for all lefts, ...
434  {
435  }
437  {
438  }
440  {
441  layout->insertWidget(stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignLeft);
442  break;
443  }
444  // ... for all centers, ...
446  {
447  }
449  {
450  layout->insertWidget(stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignCenter);
451  break;
452  }
453  // ... and for all rights
455  {
456  }
458  {
459  }
461  {
462  layout->insertWidget(stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignRight);
463  break;
464  }
465  }
466  }
467 }
468 
470 {
471  foreach (QmitkOverlay *overlay, m_AllOverlays)
472  {
473  this->UpdateOverlayData(overlay);
474  }
475 }
476 
478 {
479  int width = 0;
480  int height = 0;
481 
482  foreach (QmitkOverlay *overlay, m_AllOverlays)
483  {
484  if (overlay->GetPosition() == displayPosition)
485  {
486  QSize overlaySize = overlay->GetNeededSize();
487  width = std::max(width, overlaySize.width());
488  height = std::max(height, overlaySize.height());
489  }
490  }
491 
492  QSize result(width, height);
493  return result;
494 }
void UpdateOverlayData(QmitkOverlay *overlay)
void InitializeOverlayLayout()
setting up the widgets that will hold all overlays
OverlayVector m_AllOverlays
all QmitkOverlays that are currently added
static Pointer New()
void RestackOverlays(QmitkOverlay::DisplayPosition pos)
Widget that overrides the paintEvent method to correctly display the Qt based overlays when using the...
void AdjustAllOverlayPosition()
adjusts the position of all overlays to the position of the RenderWindow
#define MITK_ERROR
Definition: mitkLogMacros.h:20
Abstract base class for all overlay-objects in MITK.
Definition: QmitkOverlay.h:49
virtual void AlignOverlays()
re-aligning the overlays - not implemented yet
void AdjustOverlayPosition(QmitkOverlay::DisplayPosition displayPosition)
virtual DisplayPosition GetPosition()
getter for the display-position
Key-value list holding instances of BaseProperty.
DisplayPosition
enumeration of all possible display positions
Definition: QmitkOverlay.h:55
QmitkOverlayController(QmitkRenderWindow *rw, mitk::PropertyList *pl=nullptr)
constructor with mandatory QmitkRenderWindow and optional mitk::PropertyList
virtual void GenerateData(mitk::PropertyList::Pointer)
abstract method to internally setup the overlay
Definition: QmitkOverlay.h:92
virtual QWidget * GetWidget()
returns the internally handled QWidget
mitk::PropertyList::Pointer m_PropertyList
PropertyList for RenderWindow-specific properties.
void AddOverlay(QmitkOverlay *)
adds an instance of QmitkOverlay to the RenderWindow
void InitializeWidget(QmitkOverlay::DisplayPosition pos)
initializes one QWidget - internally used by InitializeOverlayLayout()
static RenderingManager * GetInstance()
virtual QSize GetNeededSize()=0
MITK implementation of the QVTKWidget.
static T max(T x, T y)
Definition: svm.cpp:56
void SetOverlayVisibility(bool visible)
setting the visibility of all overlays
QSize GetMinimumSizeForWidget(QmitkOverlay::DisplayPosition displayPosition)
OverlayPositionMap m_PositionedOverlays
all possible positions and the QWidgets representing the corresponding QmitkOverlays ...
void RemoveOverlay(QmitkOverlay *)
mitk::PropertyList * GetPropertyList()
getter for the RenderWindow-specific PropertyList
QmitkRenderWindow * m_RenderWindow
RenderWindow that all Overlays will be added to.