Medical Imaging Interaction Toolkit  2016.11.0
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "QmitkOverlayController.h"
18 
19 #include "QmitkOverlay.h"
21 #include "QmitkRenderWindow.h"
22 
23 #include <QHBoxLayout>
24 #include <QVBoxLayout>
25 
26 #include <algorithm>
27 
29  : QObject(), m_RenderWindow(rw), m_PropertyList(pl)
30 {
31  if (m_RenderWindow == NULL)
32  {
33  MITK_ERROR << "invalid QmitkRenderWindow";
34  return;
35  }
36 
37  connect(rw, SIGNAL(moved()), this, SLOT(AdjustAllOverlayPosition()));
38 
41  this->SetOverlayVisibility(true);
42 
43  if (m_PropertyList.IsNull())
45 }
46 
48 {
49 }
50 
52 {
53  // setup widget for each position
62 }
63 
65 {
66  // create a new QWidget as Tool & FramelessWindowHint
67  m_PositionedOverlays[pos] = new QmitkOverlayContainerWidget(m_RenderWindow, Qt::Tool | Qt::FramelessWindowHint);
68 
69 // autoFillBackGround(false) and WA_TranslucentBackground = true are needed to have a translucent background
70 // transparency does NOT work under Win-XP 32-Bit --> paint black background
71 
72 #if !defined(_WIN32) || defined(_WIN64)
73  m_PositionedOverlays[pos]->setAttribute(Qt::WA_TranslucentBackground, true);
74 #else
75  m_PositionedOverlays[pos]->setStyleSheet("QWidget { background: black }");
76  m_PositionedOverlays[pos]->setAttribute(Qt::WA_TranslucentBackground, false);
77 #endif
78 
79  // X11 specific attributes
80  m_PositionedOverlays[pos]->setAttribute(Qt::WA_X11NetWmWindowTypeUtility, true);
81 
82  // mac-specific attributes:
83  // making sure overlays are even visible if RenderWindow does not have the focus (not default for Qt::Tool on mac)
84  m_PositionedOverlays[pos]->setAttribute(Qt::WA_MacAlwaysShowToolWindow, true);
85  // testing something
86  m_PositionedOverlays[pos]->setAttribute(Qt::WA_MacShowFocusRect, false);
87 
88  // overlays should not get the focus
89  m_PositionedOverlays[pos]->setFocusPolicy(Qt::NoFocus);
90 
91  // setting the color of the background to transparent - not sure it's needed after the attributes have been set above
92  QPalette p = QPalette();
93  p.setColor(QPalette::Window, Qt::transparent);
94  m_PositionedOverlays[pos]->setPalette(p);
95 
96  // setting position-specific properties
97  switch (pos)
98  {
100  {
101  // adding left-aligned top-to-bottom layout
102  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
103  layout->setDirection(QBoxLayout::TopToBottom);
104  layout->setAlignment(Qt::AlignLeft);
105  m_PositionedOverlays[pos]->layout()->setSpacing(0);
106  break;
107  }
109  {
110  // adding center-aligned top-to-bottom layout
111  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
112  layout->setDirection(QBoxLayout::TopToBottom);
113  layout->setAlignment(Qt::AlignCenter);
114  layout->setAlignment(Qt::AlignLeft);
115  m_PositionedOverlays[pos]->layout()->setSpacing(0);
116  break;
117  }
119  {
120  // adding right-aligned top-to-bottom layout
121  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
122  layout->setDirection(QBoxLayout::TopToBottom);
123  layout->setAlignment(Qt::AlignRight);
124  m_PositionedOverlays[pos]->layout()->setSpacing(0);
125  break;
126  }
128  {
129  // adding left-aligned left-to-right layout
130  QHBoxLayout *layout = new QHBoxLayout(m_PositionedOverlays[pos]);
131  layout->setDirection(QBoxLayout::LeftToRight);
132  layout->setAlignment(Qt::AlignLeft);
133  layout->setSpacing(3);
134  break;
135  }
137  {
138  // adding right-aligned right-to-left layout
139  QHBoxLayout *layout = new QHBoxLayout(m_PositionedOverlays[pos]);
140  layout->setDirection(QBoxLayout::RightToLeft);
141  layout->setAlignment(Qt::AlignRight);
142  layout->setSpacing(3);
143  break;
144  }
146  {
147  // adding left-aligned bottom-to-top layout
148  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
149  layout->setDirection(QBoxLayout::BottomToTop);
150  layout->setAlignment(Qt::AlignLeft);
151  m_PositionedOverlays[pos]->layout()->setSpacing(0);
152  break;
153  }
155  {
156  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
157  layout->setDirection(QBoxLayout::BottomToTop);
158  layout->setAlignment(Qt::AlignCenter);
159  m_PositionedOverlays[pos]->layout()->setSpacing(0);
160  break;
161  }
163  {
164  QVBoxLayout *layout = new QVBoxLayout(m_PositionedOverlays[pos]);
165  layout->setDirection(QBoxLayout::BottomToTop);
166  layout->setAlignment(Qt::AlignRight);
167  m_PositionedOverlays[pos]->layout()->setSpacing(0);
168  break;
169  }
170  }
171 }
172 
174 {
183 }
184 
186 {
187  QWidget *widget = m_PositionedOverlays[displayPosition];
188  QSize size = GetMinimumSizeForWidget(displayPosition);
189  QPoint pos;
190 
191  switch (displayPosition)
192  {
194  {
195  // setting position of top-left overlay-container
196  pos = m_RenderWindow->mapToGlobal(QPoint(0, 0));
197  m_PositionedOverlays[QmitkOverlay::top_Left]->move(pos.x(), pos.y());
198 
199  break;
200  }
201 
203  {
204  // setting position of top-center overlay-container
205  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
206 
207  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width() / 2, 0));
208  widget->move(pos.x() - widget->size().width() / 2, pos.y());
209 
210  break;
211  }
212 
214  {
215  // setting position of top-right overlay-container
216  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
217 
218  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width(), 0));
219  widget->move(pos.x() - widget->size().width(), pos.y());
220 
221  break;
222  }
223 
225  {
226  // setting position of middle-left overlay-container
227  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
228 
229  pos = m_RenderWindow->mapToGlobal(QPoint(0, m_RenderWindow->size().height() / 2));
230  widget->move(pos.x(), pos.y() - widget->size().height() / 2);
231 
232  break;
233  }
234 
236  {
237  // setting position of middle-right overlay-container
238  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
239 
240  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width(), m_RenderWindow->size().height() / 2));
241  widget->move(pos.x() - widget->size().width(), pos.y() - widget->size().height() / 2);
242 
243  break;
244  }
245 
247  {
248  // setting position of bottom-left overlay-container
249  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
250 
251  pos = m_RenderWindow->mapToGlobal(QPoint(0, m_RenderWindow->size().height()));
252  widget->move(pos.x(), pos.y() - widget->size().height());
253 
254  break;
255  }
256 
258  {
259  // setting position of bottom-center overlay-container
260  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
261 
262  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width() / 2, m_RenderWindow->size().height()));
263  widget->move(pos.x() - widget->size().width() / 2, pos.y() - widget->size().height());
264 
265  break;
266  }
267 
269  {
270  // setting position of bottom-right overlay-container
271  widget->setFixedWidth(std::max(widget->width(), size.width() * 2));
272 
273  pos = m_RenderWindow->mapToGlobal(QPoint(m_RenderWindow->size().width(), m_RenderWindow->size().height()));
274  widget->move(pos.x() - widget->size().width(), pos.y() - widget->size().height());
275 
276  break;
277  }
278  }
279 }
280 
282 {
283  OverlayPositionMap::iterator overlayIter;
284  for (overlayIter = m_PositionedOverlays.begin(); overlayIter != m_PositionedOverlays.end(); overlayIter++)
285  {
286  if (visible)
287  {
288  (overlayIter->second)->show();
289  }
290  else
291  {
292  (overlayIter->second)->hide();
293  }
294  }
295 
296  OverlayVector::iterator allOverlaysIter;
297  for (allOverlaysIter = m_AllOverlays.begin(); allOverlaysIter != m_AllOverlays.end(); allOverlaysIter++)
298  {
299  if (visible)
300  {
301  (*allOverlaysIter)->GetWidget()->show();
302  }
303  else
304  {
305  (*allOverlaysIter)->GetWidget()->hide();
306  }
307  }
308 }
309 
311 {
312  // if no renderwindow has been set, it's not possible to add overlays...
313  if (m_RenderWindow == NULL)
314  {
315  MITK_ERROR << "invalid QmitkRenderWindow";
316  return;
317  }
318 
319  if (overlay != NULL)
320  {
321  // get desired position and layer of the overlay
323 
324  // concatenate local propertyList and propertyList of the RenderingManager
325  // local properties have priority as they are not overwritten if preset in both
327  false);
328 
329  // add the overlay to the OverlayContainer in the RenderWindow ...
330  overlay->GetWidget()->setParent(m_PositionedOverlays[pos]);
331 
332  // ... and set it up with the correct properties
333  this->UpdateOverlayData(overlay);
334 
335  // add overlay to list of all overlays and correctly put it into the layering
336  m_AllOverlays.push_back(overlay);
337  this->RestackOverlays(pos);
338 
339  // ... and reset the position of the widgets
340  this->AdjustOverlayPosition(pos);
341  }
342 }
343 
345 {
346  if (overlay != NULL)
347  {
348  overlay->GenerateData(m_PropertyList);
350  }
351 }
352 
354 {
355  foreach (QmitkOverlay *overlay, m_AllOverlays)
356  {
357  overlay->GetWidget()->setParent(NULL);
358  overlay->GetWidget()->hide();
359  overlay->deleteLater();
360  }
361 
362  m_AllOverlays.clear();
363 }
364 
366 {
367  if (overlay != NULL)
368  {
369  // get desired position and layer of the overlay
371 
372  OverlayVector::iterator iter = std::find(m_AllOverlays.begin(), m_AllOverlays.end(), overlay);
373 
374  if (iter != m_AllOverlays.end())
375  {
376  m_AllOverlays.erase(iter);
377  overlay->GetWidget()->setParent(NULL);
378  overlay->GetWidget()->hide();
379 
380  if (m_PositionedOverlays[pos]->layout()->isEmpty())
381  {
382  m_PositionedOverlays[pos]->hide();
383  }
384  else
385  {
386  this->RestackOverlays(pos);
387  // reset the position of the widgets
388  this->AdjustOverlayPosition(pos);
389  }
390  }
391 
392  overlay->deleteLater();
393  }
394 }
395 
397 {
398  // OverlayVector::iterator overlayIter;
399 
400  // for ( overlayIter=m_AllOverlays.begin(); overlayIter!=m_AllOverlays.end(); overlayIter++ )
401  //{
402  // int stackLayer = dynamic_cast<QBoxLayout*>( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout()
403  // )->isEmpty() ? 0 : layer;
404  // dynamic_cast<QBoxLayout*>( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout() )->addWidget(
405  // (*overlayIter)->GetWidget(), stackLayer, Qt::AlignLeft );
406  //}
407 }
408 
410 {
411  OverlayVector::iterator overlayIter;
412  QBoxLayout *layout = dynamic_cast<QBoxLayout *>(m_PositionedOverlays[pos]->layout());
413 
414  std::sort(m_AllOverlays.begin(), m_AllOverlays.end());
415 
416  for (overlayIter = m_AllOverlays.begin(); overlayIter != m_AllOverlays.end(); overlayIter++)
417  {
418  // do nothing if the overlay is not in the right position
419  if ((*overlayIter)->GetPosition() != pos)
420  {
421  continue;
422  }
423 
424  // determine the desired stacking layer
425  // if the overlay-container is empty, simply append the overlay to the list
426  // if it's not empty, use the layer of the overlay
427  unsigned int layer = (*overlayIter)->GetLayer();
428  int stackLayer = 0;
429  if (!layout->isEmpty())
430  {
431  stackLayer = layer;
432  }
433 
434  switch (pos)
435  {
436  // same alignment for all lefts, ...
438  {
439  }
441  {
442  }
444  {
445  layout->insertWidget(stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignLeft);
446  break;
447  }
448  // ... for all centers, ...
450  {
451  }
453  {
454  layout->insertWidget(stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignCenter);
455  break;
456  }
457  // ... and for all rights
459  {
460  }
462  {
463  }
465  {
466  layout->insertWidget(stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignRight);
467  break;
468  }
469  }
470  }
471 }
472 
474 {
475  foreach (QmitkOverlay *overlay, m_AllOverlays)
476  {
477  this->UpdateOverlayData(overlay);
478  }
479 }
480 
482 {
483  int width = 0;
484  int height = 0;
485 
486  foreach (QmitkOverlay *overlay, m_AllOverlays)
487  {
488  if (overlay->GetPosition() == displayPosition)
489  {
490  QSize overlaySize = overlay->GetNeededSize();
491  width = std::max(width, overlaySize.width());
492  height = std::max(height, overlaySize.height());
493  }
494  }
495 
496  QSize result(width, height);
497  return result;
498 }
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)
PropertyList::Pointer GetPropertyList() const
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:24
Abstract base class for all overlay-objects in MITK.
Definition: QmitkOverlay.h:53
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:59
virtual void GenerateData(mitk::PropertyList::Pointer)
abstract method to internally setup the overlay
Definition: QmitkOverlay.h:96
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
virtual mitk::RenderingManager * GetRenderingManager() const
Setter for the RenderingManager that handles this instance of BaseRenderer.
void InitializeWidget(QmitkOverlay::DisplayPosition pos)
initializes one QWidget - internally used by InitializeOverlayLayout()
QmitkOverlayController(QmitkRenderWindow *rw, mitk::PropertyList *pl=NULL)
constructor with mandatory QmitkRenderWindow and optional mitk::PropertyList
virtual QSize GetNeededSize()=0
MITK implementation of the QVTKWidget.
virtual mitk::VtkPropRenderer * GetRenderer()
static T max(T x, T y)
Definition: svm.cpp:70
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 *)
QmitkRenderWindow * m_RenderWindow
RenderWindow that all Overlays will be added to.