Fraxinus  17.12
An IGT application
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(RenderWindowFactoryPtr factory, QWidget *parent, Qt::WindowFlags f) :
51  mRenderWindowFactory(factory),
52  QVTKWidget(parent, f),
53  mMouseEventTarget(NULL),
54  mRenderWindow(NULL)
55 {
56  mOffScreenRendering = false;
57  this->setContextMenuPolicy(Qt::CustomContextMenu);
58  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequestedSlot(const QPoint &)));
59  mMTimeHash = 0;
60  mMouseEventTarget = NULL;
61  this->setLayout(new QGridLayout);
62  disableGLHiDPI(this->winId());
63 }
64 
66 {
67 }
68 
73 {
74  QLayoutItem *item;
75  while ((item = getGridLayout()->takeAt(0)) != 0)
76  {
77  ViewItem* viewItem = dynamic_cast<ViewItem*>(item);
78  delete viewItem;
79  }
81  this->setModified();
82  mMouseEventTarget = NULL;
83 }
84 
89 {
90  return dynamic_cast<QGridLayout*>(layout());
91 }
92 
93 void ViewContainer::paintEvent(QPaintEvent* event)
94 {
95  inherited_widget::paintEvent(event);
96  this->setModified();
97 }
98 
100 {
101  if (this->getGridLayout())
102  {
103  for (int i = 0; i < this->getGridLayout()->count(); ++i)
104  {
105  this->getViewItem(i)->getView()->setModified();
106  }
107  }
108  mMTimeHash = 0;
109 }
110 
112 {
113  return dynamic_cast<ViewItem*>(this->getGridLayout()->itemAt(index));
114 }
115 
120 ViewItem *ViewContainer::addView(QString uid, LayoutRegion region, QString name)
121 {
122  this->initializeRenderWindow();
123 
124  // Create a viewItem for this view
125  ViewItem *item = new ViewItem(uid, name, this, mRenderWindow, QRect());
126  if (getGridLayout())
127  getGridLayout()->addItem(item,
128  region.pos.row, region.pos.col,
129  region.span.row, region.span.col);
130  view_utils::setStretchFactors(this->getGridLayout(), region, 1);
131 
132  return item;
133 }
134 
136 {
137  this->clear();
138  mOffScreenRendering = on;
139 }
140 
142 {
143  return mOffScreenRendering;
144 }
145 
146 void ViewContainer::initializeRenderWindow()
147 {
148  if (mRenderWindow)
149  return;
150 
151  QString uid = QString("rw_oscr=%1").arg(mOffScreenRendering);
152 
153  bool renderWindowExists = mRenderWindowFactory->renderWindowExists(uid);
154 
155  mRenderWindow = mRenderWindowFactory->getRenderWindow(uid, mOffScreenRendering);
156  if(!renderWindowExists)
157  this->addBackgroundRenderer(mRenderWindow);
158  this->SetRenderWindow(mRenderWindow);
159  mRenderWindow->GetInteractor()->EnableRenderOff();
160 
161 
162 
163 // if (!mCachedRenderWindows.count(uid))
164 // {
166 // vtkRenderWindowPtr rw = mRenderWindowFactory->getRenderWindow(uid, mOffScreenRendering);
167 // this->addBackgroundRenderer(rw);
168 // mCachedRenderWindows[uid] = rw;
169 // }
170 
171 // // replace the previous renderwindow with one from the cache.
172 // // the old renderwindow is not hidden explicitly: is this a problem??
175 // mRenderWindow = mCachedRenderWindows[uid];
176 // this->SetRenderWindow(mRenderWindow);
177 // mRenderWindow->GetInteractor()->EnableRenderOff();
179 }
180 
181 void ViewContainer::addBackgroundRenderer(vtkRenderWindowPtr rw)
182 {
183  vtkRendererPtr renderer = vtkRendererPtr::New();
184  rw->AddRenderer(renderer);
185  renderer->SetViewport(0,0,1,1);
186  QColor background = palette().color(QPalette::Background);
187  renderer->SetBackground(background.redF(), background.greenF(), background.blueF());
188 }
189 
190 void ViewContainer::customContextMenuRequestedSlot(const QPoint& point)
191 {
192  ViewItem* item = this->findViewItem(point);
193  if (!item)
194  return;
195 
196  QWidget* sender = dynamic_cast<QWidget*>(this->sender());
197  QPoint pointGlobal = sender->mapToGlobal(point);
198 
199  item->customContextMenuRequestedGlobalSlot(pointGlobal);
200 }
201 
202 void ViewContainer::mouseMoveEvent(QMouseEvent* event)
203 {
204  inherited_widget::mouseMoveEvent(event);
205 
206  if (mMouseEventTarget)
207  {
208  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
209  mMouseEventTarget->mouseMoveSlot(p.x(), p.y(), event->buttons());
210  }
211 }
212 
213 void ViewContainer::mousePressEvent(QMouseEvent* event)
214 {
215  // special case for CustusX: when context menu is opened, mousereleaseevent is never called.
216  // this sets the render interactor in a zoom state after each menu call. This hack prevents
217  // the mouse press event in this case.
218  // NOTE: this doesnt seem to be the case in this class - investigate
219  if ((this->contextMenuPolicy() == Qt::CustomContextMenu) && event->buttons().testFlag(Qt::RightButton))
220  return;
221 
222  inherited_widget::mousePressEvent(event);
223 
224  mMouseEventTarget = this->findViewItem(event->pos());
225  if (mMouseEventTarget)
226  {
227  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
228  mMouseEventTarget->mousePressSlot(p.x(), p.y(), event->buttons());
229  }
230 }
231 
232 QPoint ViewContainer::convertToItemSpace(const QPoint &pos, ViewItem* item) const
233 {
234  QRect r = item->geometry();
235  QPoint retval(pos.x() - r.left(), pos.y() - r.top());
236  return retval;
237 }
238 
239 ViewItem* ViewContainer::findViewItem(const QPoint &pos)
240 {
241  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
242  {
243  ViewItem *item = this->getViewItem(i);
244  QRect r = item->geometry();
245  if (r.contains(pos))
246  return item;
247  }
248  return NULL;
249 }
250 
251 void ViewContainer::mouseReleaseEvent(QMouseEvent* event)
252 {
253  inherited_widget::mouseReleaseEvent(event);
254 
255  if (mMouseEventTarget)
256  {
257  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
258  mMouseEventTarget->mouseReleaseSlot(p.x(), p.y(), event->buttons());
259  mMouseEventTarget = NULL;
260  }
261 }
262 
263 void ViewContainer::focusInEvent(QFocusEvent* event)
264 {
265  inherited_widget::focusInEvent(event);
266 }
267 
268 void ViewContainer::wheelEvent(QWheelEvent* event)
269 {
270  inherited_widget::wheelEvent(event);
271 
272  ViewItem *item = this->findViewItem(event->pos());
273  if (item)
274  {
275  QPoint p = this->convertToItemSpace(event->pos(), item);
276  item->mouseWheelSlot(p.x(), p.y(),
277  event->delta(), event->orientation(), event->buttons());
278  }
279 }
280 
281 void ViewContainer::showEvent(QShowEvent* event)
282 {
283  inherited_widget::showEvent(event);
284 }
285 
287 {
288  // First, calculate if anything has changed
289  long hash = 0;
290  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
291  {
292  ViewItem *item = this->getViewItem(i);
293  hash += item->getView()->computeTotalMTime();
294  }
295  // Then, if anything has changed, render everything anew
296  if (hash != mMTimeHash)
297  {
298  this->doRender();
299  mMTimeHash = hash;
300 
301  QString msg("During rendering of ViewContainer");
303  }
304 }
305 
307 {
308  if (!mRenderWindow)
309  return;
310  this->getRenderWindow()->Render();
311 }
312 
313 void ViewContainer::resizeEvent( QResizeEvent *event)
314 {
315  inherited_widget::resizeEvent(event);
316  this->setModified();
317  this->getGridLayout()->update();
318 }
319 
320 
321 } /* namespace cx */
void mouseWheelSlot(int x, int y, int delta, int orientation, Qt::MouseButtons buttons)
virtual void doRender()
vtkSmartPointer< class vtkRenderWindow > vtkRenderWindowPtr
cstring_cast_Placeholder cstring_cast(const T &val)
ViewContainer(RenderWindowFactoryPtr factory, QWidget *parent=NULL, Qt::WindowFlags f=0)
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:50
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)
boost::shared_ptr< class RenderWindowFactory > RenderWindowFactoryPtr
virtual QGridLayout * getGridLayout()
void customContextMenuRequestedGlobalSlot(const QPoint &point)
ViewRepCollectionPtr getView()
virtual QRect geometry() const
virtual bool getOffScreenRendering() const
vtkRenderWindowPtr mRenderWindow
Namespace for all CustusX production code.
ViewItem * mMouseEventTarget