CustusX  16.12
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxViewContainer.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxViewContainer.h"
34 
35 #include <QResizeEvent>
36 #include "vtkRenderWindow.h"
37 #include "vtkRenderer.h"
38 #include <QGridLayout>
39 #include "cxViewUtilities.h"
40 #include "cxViewContainerItem.h"
41 #include "cxTypeConversions.h"
42 #include "cxGLHelpers.h"
43 #include "cxOSXHelper.h"
44 #include "cxViewCache.h"
45 #include "cxLogger.h"
46 
47 namespace cx
48 {
49 
50 ViewContainer::ViewContainer(QWidget *parent, Qt::WindowFlags f) :
51  QVTKWidget(parent, f),
52  mMouseEventTarget(NULL),
53  mRenderWindow(NULL)
54 {
55  mOffScreenRendering = false;
56  this->setContextMenuPolicy(Qt::CustomContextMenu);
57  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequestedSlot(const QPoint &)));
58  mMTimeHash = 0;
59  mMouseEventTarget = NULL;
60  this->setLayout(new QGridLayout);
61  disableGLHiDPI(this->winId());
62 }
63 
65 {
66 }
67 
72 {
73  QLayoutItem *item;
74  while ((item = getGridLayout()->takeAt(0)) != 0)
75  {
76  ViewItem* viewItem = dynamic_cast<ViewItem*>(item);
77  delete viewItem;
78  }
80  this->setModified();
81  mMouseEventTarget = NULL;
82 }
83 
88 {
89  return dynamic_cast<QGridLayout*>(layout());
90 }
91 
92 void ViewContainer::paintEvent(QPaintEvent* event)
93 {
94  inherited_widget::paintEvent(event);
95  this->setModified();
96 }
97 
99 {
100  if (this->getGridLayout())
101  {
102  for (int i = 0; i < this->getGridLayout()->count(); ++i)
103  {
104  this->getViewItem(i)->getView()->setModified();
105  }
106  }
107  mMTimeHash = 0;
108 }
109 
111 {
112  return dynamic_cast<ViewItem*>(this->getGridLayout()->itemAt(index));
113 }
114 
119 ViewItem *ViewContainer::addView(QString uid, LayoutRegion region, QString name)
120 {
121  this->initializeRenderWindow();
122 
123  // Create a viewItem for this view
124  ViewItem *item = new ViewItem(uid, name, this, mRenderWindow, QRect());
125  if (getGridLayout())
126  getGridLayout()->addItem(item,
127  region.pos.row, region.pos.col,
128  region.span.row, region.span.col);
129  view_utils::setStretchFactors(this->getGridLayout(), region, 1);
130 
131  return item;
132 }
133 
135 {
136  this->clear();
137  mOffScreenRendering = on;
138 }
139 
141 {
142  return mOffScreenRendering;
143 }
144 
145 void ViewContainer::initializeRenderWindow()
146 {
147  if (mRenderWindow)
148  return;
149 
150  QString uid = QString("rw_oscr=%1").arg(mOffScreenRendering);
151 
152  if (!mCachedRenderWindows.count(uid))
153  {
154  vtkRenderWindowPtr rw = vtkRenderWindowPtr::New();
155  this->addBackgroundRenderer(rw);
156  rw->SetOffScreenRendering(mOffScreenRendering);
157  mCachedRenderWindows[uid] = rw;
158  }
159 
160  // replace the previous renderwindow with one from the cache.
161  // the old renderwindow is not hidden explicitly: is this a problem??
162  if (mRenderWindow != mCachedRenderWindows[uid])
163  {
164  mRenderWindow = mCachedRenderWindows[uid];
165  this->SetRenderWindow(mRenderWindow);
166  mRenderWindow->GetInteractor()->EnableRenderOff();
167  }
168 }
169 
170 void ViewContainer::addBackgroundRenderer(vtkRenderWindowPtr rw)
171 {
172  vtkRendererPtr renderer = vtkRendererPtr::New();
173  rw->AddRenderer(renderer);
174  renderer->SetViewport(0,0,1,1);
175  QColor background = palette().color(QPalette::Background);
176  renderer->SetBackground(background.redF(), background.greenF(), background.blueF());
177 }
178 
179 void ViewContainer::customContextMenuRequestedSlot(const QPoint& point)
180 {
181  ViewItem* item = this->findViewItem(point);
182  if (!item)
183  return;
184 
185  QWidget* sender = dynamic_cast<QWidget*>(this->sender());
186  QPoint pointGlobal = sender->mapToGlobal(point);
187 
188  item->customContextMenuRequestedGlobalSlot(pointGlobal);
189 }
190 
191 void ViewContainer::mouseMoveEvent(QMouseEvent* event)
192 {
193  inherited_widget::mouseMoveEvent(event);
194 
195  if (mMouseEventTarget)
196  {
197  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
198  mMouseEventTarget->mouseMoveSlot(p.x(), p.y(), event->buttons());
199  }
200 }
201 
202 void ViewContainer::mousePressEvent(QMouseEvent* event)
203 {
204  // special case for CustusX: when context menu is opened, mousereleaseevent is never called.
205  // this sets the render interactor in a zoom state after each menu call. This hack prevents
206  // the mouse press event in this case.
207  // NOTE: this doesnt seem to be the case in this class - investigate
208  if ((this->contextMenuPolicy() == Qt::CustomContextMenu) && event->buttons().testFlag(Qt::RightButton))
209  return;
210 
211  inherited_widget::mousePressEvent(event);
212 
213  mMouseEventTarget = this->findViewItem(event->pos());
214  if (mMouseEventTarget)
215  {
216  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
217  mMouseEventTarget->mousePressSlot(p.x(), p.y(), event->buttons());
218  }
219 }
220 
221 QPoint ViewContainer::convertToItemSpace(const QPoint &pos, ViewItem* item) const
222 {
223  QRect r = item->geometry();
224  QPoint retval(pos.x() - r.left(), pos.y() - r.top());
225  return retval;
226 }
227 
228 ViewItem* ViewContainer::findViewItem(const QPoint &pos)
229 {
230  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
231  {
232  ViewItem *item = this->getViewItem(i);
233  QRect r = item->geometry();
234  if (r.contains(pos))
235  return item;
236  }
237  return NULL;
238 }
239 
240 void ViewContainer::mouseReleaseEvent(QMouseEvent* event)
241 {
242  inherited_widget::mouseReleaseEvent(event);
243 
244  if (mMouseEventTarget)
245  {
246  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
247  mMouseEventTarget->mouseReleaseSlot(p.x(), p.y(), event->buttons());
248  mMouseEventTarget = NULL;
249  }
250 }
251 
252 void ViewContainer::focusInEvent(QFocusEvent* event)
253 {
254  inherited_widget::focusInEvent(event);
255 }
256 
257 void ViewContainer::wheelEvent(QWheelEvent* event)
258 {
259  inherited_widget::wheelEvent(event);
260 
261  ViewItem *item = this->findViewItem(event->pos());
262  if (item)
263  {
264  QPoint p = this->convertToItemSpace(event->pos(), item);
265  item->mouseWheelSlot(p.x(), p.y(),
266  event->delta(), event->orientation(), event->buttons());
267  }
268 }
269 
270 void ViewContainer::showEvent(QShowEvent* event)
271 {
272  inherited_widget::showEvent(event);
273 }
274 
276 {
277  // First, calculate if anything has changed
278  long hash = 0;
279  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
280  {
281  ViewItem *item = this->getViewItem(i);
282  hash += item->getView()->computeTotalMTime();
283  }
284  // Then, if anything has changed, render everything anew
285  if (hash != mMTimeHash)
286  {
287  this->doRender();
288  mMTimeHash = hash;
289 
290  QString msg("During rendering of ViewContainer");
292  }
293 }
294 
296 {
297  this->getRenderWindow()->Render();
298 }
299 
300 void ViewContainer::resizeEvent( QResizeEvent *event)
301 {
302  inherited_widget::resizeEvent(event);
303  this->setModified();
304  this->getGridLayout()->update();
305 }
306 
307 
308 } /* namespace cx */
virtual void doRender()
vtkSmartPointer< class vtkRenderWindow > vtkRenderWindowPtr
cstring_cast_Placeholder cstring_cast(const T &val)
LayoutPosition span
size of region
Definition: cxLayoutData.h:67
void mouseReleaseSlot(int x, int y, Qt::MouseButtons buttons)
#define report_gl_error_text(text)
Definition: cxGLHelpers.h:51
ViewContainer(QWidget *parent=NULL, Qt::WindowFlags f=0)
ViewItem * addView(QString uid, LayoutRegion region, QString name="")
void mousePressSlot(int x, int y, Qt::MouseButtons buttons)
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
ViewItem * getViewItem(int index)
vtkRenderWindowPtr getRenderWindow()
unsigned long mMTimeHash
sum of all MTimes in objects rendered
void mouseMoveSlot(int x, int y, Qt::MouseButtons buttons)
void setStretchFactors(QGridLayout *layout, LayoutRegion region, int stretchFactor)
virtual void setModified()
void renderAll()
Use this function to render all views at once. Do not call render on each view.
virtual void clear()
static const int MaxGridSize
Definition: cxLayoutData.h:103
LayoutPosition pos
start position of region
Definition: cxLayoutData.h:66
virtual void setOffScreenRenderingAndClear(bool on)
virtual QGridLayout * getGridLayout()
ViewRepCollectionPtr getView()
virtual bool getOffScreenRendering() const
vtkRenderWindowPtr mRenderWindow
ViewItem * mMouseEventTarget