CustusX  15.8
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 
44 namespace cx
45 {
46 
47 ViewContainer::ViewContainer(QWidget *parent, Qt::WindowFlags f) :
48  QVTKWidget(parent, f),
49  mMouseEventTarget(NULL)
50 {
51  this->setContextMenuPolicy(Qt::CustomContextMenu);
52  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequestedSlot(const QPoint &)));
53  mMTimeHash = 0;
54  mMouseEventTarget = NULL;
55  this->setLayout(new QGridLayout);
56 }
57 
59 {
60 }
61 
66 {
67  QLayoutItem *item;
68  while ((item = getGridLayout()->takeAt(0)) != 0)
69  {
70  ViewItem* viewItem = dynamic_cast<ViewItem*>(item);
71  delete viewItem;
72  }
73  view_utils::setStretchFactors(this->getGridLayout(), LayoutRegion(0, 0, 10, 10), 0);
74  this->setModified();
75  mMouseEventTarget = NULL;
76 }
77 
82 {
83  return (QGridLayout*) layout();
84 }
85 
86 void ViewContainer::paintEvent(QPaintEvent* event)
87 {
88  inherited_widget::paintEvent(event);
89  this->setModified();
90 }
91 
93 {
94  if (this->getGridLayout())
95  {
96  for (int i = 0; i < this->getGridLayout()->count(); ++i)
97  {
98  this->getViewItem(i)->getView()->setModified();
99  }
100  }
101  mMTimeHash = 0;
102 }
103 
105 {
106  return dynamic_cast<ViewItem*>(this->getGridLayout()->itemAt(index));
107 }
108 
113 ViewItem *ViewContainer::addView(QString uid, LayoutRegion region, QString name)
114 {
115  this->initializeRenderWindow();
116 
117  // Create a viewItem for this view
118  ViewItem *item = new ViewItem(uid, name, this, mRenderWindow, QRect());
119  if (getGridLayout())
120  getGridLayout()->addItem(item,
121  region.pos.row, region.pos.col,
122  region.span.row, region.span.col);
123  view_utils::setStretchFactors(this->getGridLayout(), region, 1);
124 
125  return item;
126 }
127 
128 void ViewContainer::initializeRenderWindow()
129 {
130  if (mRenderWindow)
131  return;
132 
133  mRenderWindow = vtkRenderWindowPtr::New();
134  this->SetRenderWindow(mRenderWindow);
135  mRenderWindow->GetInteractor()->EnableRenderOff();
136 
137  this->addBackgroundRenderer();
138 }
139 
140 void ViewContainer::addBackgroundRenderer()
141 {
142  vtkRendererPtr renderer = vtkRendererPtr::New();
143  mRenderWindow->AddRenderer(renderer);
144  renderer->SetViewport(0,0,1,1);
145  QColor background = palette().color(QPalette::Background);
146  renderer->SetBackground(background.redF(), background.greenF(), background.blueF());
147 }
148 
149 void ViewContainer::customContextMenuRequestedSlot(const QPoint& point)
150 {
151  ViewItem* item = this->findViewItem(point);
152  if (!item)
153  return;
154 
155  QWidget* sender = dynamic_cast<QWidget*>(this->sender());
156  QPoint pointGlobal = sender->mapToGlobal(point);
157 
158  item->customContextMenuRequestedGlobalSlot(pointGlobal);
159 }
160 
161 void ViewContainer::mouseMoveEvent(QMouseEvent* event)
162 {
163  inherited_widget::mouseMoveEvent(event);
164 
165  if (mMouseEventTarget)
166  {
167  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
168  mMouseEventTarget->mouseMoveSlot(p.x(), p.y(), event->buttons());
169  }
170 }
171 
172 void ViewContainer::mousePressEvent(QMouseEvent* event)
173 {
174  // special case for CustusX: when context menu is opened, mousereleaseevent is never called.
175  // this sets the render interactor in a zoom state after each menu call. This hack prevents
176  // the mouse press event in this case.
177  // NOTE: this doesnt seem to be the case in this class - investigate
178  if ((this->contextMenuPolicy() == Qt::CustomContextMenu) && event->buttons().testFlag(Qt::RightButton))
179  return;
180 
181  inherited_widget::mousePressEvent(event);
182 
183  mMouseEventTarget = this->findViewItem(event->pos());
184  if (mMouseEventTarget)
185  {
186  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
187  mMouseEventTarget->mousePressSlot(p.x(), p.y(), event->buttons());
188  }
189 }
190 
191 QPoint ViewContainer::convertToItemSpace(const QPoint &pos, ViewItem* item) const
192 {
193  QRect r = item->geometry();
194  QPoint retval(pos.x() - r.left(), pos.y() - r.top());
195  return retval;
196 }
197 
198 ViewItem* ViewContainer::findViewItem(const QPoint &pos)
199 {
200  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
201  {
202  ViewItem *item = this->getViewItem(i);
203  QRect r = item->geometry();
204  if (r.contains(pos))
205  return item;
206  }
207  return NULL;
208 }
209 
210 void ViewContainer::mouseReleaseEvent(QMouseEvent* event)
211 {
212  inherited_widget::mouseReleaseEvent(event);
213 
214  if (mMouseEventTarget)
215  {
216  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
217  mMouseEventTarget->mouseReleaseSlot(p.x(), p.y(), event->buttons());
218  mMouseEventTarget = NULL;
219  }
220 }
221 
222 void ViewContainer::focusInEvent(QFocusEvent* event)
223 {
224  inherited_widget::focusInEvent(event);
225 }
226 
227 void ViewContainer::wheelEvent(QWheelEvent* event)
228 {
229  inherited_widget::wheelEvent(event);
230 
231  ViewItem *item = this->findViewItem(event->pos());
232  if (item)
233  {
234  QPoint p = this->convertToItemSpace(event->pos(), item);
235  item->mouseWheelSlot(p.x(), p.y(),
236  event->delta(), event->orientation(), event->buttons());
237  }
238 }
239 
240 void ViewContainer::showEvent(QShowEvent* event)
241 {
242  inherited_widget::showEvent(event);
243 }
244 
246 {
247  // First, calculate if anything has changed
248  long hash = 0;
249  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
250  {
251  ViewItem *item = this->getViewItem(i);
252  hash += item->getView()->computeTotalMTime();
253  }
254  // Then, if anything has changed, render everything anew
255  if (hash != mMTimeHash)
256  {
257  this->doRender();
258  mMTimeHash = hash;
259 
260  QString msg("During rendering of ViewContainer");
262  }
263 }
264 
266 {
267  this->getRenderWindow()->Render();
268 }
269 
270 void ViewContainer::resizeEvent( QResizeEvent *event)
271 {
272  inherited_widget::resizeEvent(event);
273  this->setModified();
274  this->getGridLayout()->update();
275 }
276 
277 
278 } /* namespace cx */
virtual void doRender()
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()
LayoutPosition pos
start position of region
Definition: cxLayoutData.h:66
virtual QGridLayout * getGridLayout()
ViewRepCollectionPtr getView()
vtkRenderWindowPtr mRenderWindow
ViewItem * mMouseEventTarget