CustusX  2023.01.05-dev+develop.0da12
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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxViewContainer.h"
13 
14 #include <QResizeEvent>
15 #include "vtkRenderWindow.h"
16 #include "vtkRenderer.h"
17 #include <QGridLayout>
18 #include "cxViewUtilities.h"
19 #include "cxViewContainerItem.h"
20 #include "cxTypeConversions.h"
21 #include "cxGLHelpers.h"
22 #include "cxOSXHelper.h"
23 #include "cxViewCache.h"
24 #include "cxLogger.h"
25 
26 namespace cx
27 {
28 
29 ViewContainer::ViewContainer(RenderWindowFactoryPtr factory, QWidget *parent, Qt::WindowFlags f) :
30  mRenderWindowFactory(factory),
31  QVTKWidget(parent, f),
32  mMouseEventTarget(NULL),
33  mRenderWindow(NULL)
34 {
35  mOffScreenRendering = false;
36  this->setContextMenuPolicy(Qt::CustomContextMenu);
37  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequestedSlot(const QPoint &)));
38  mMTimeHash = 0;
39  mMouseEventTarget = NULL;
40  this->setLayout(new QGridLayout);
41  disableGLHiDPI(this->winId());
42 }
43 
45 {
46 }
47 
52 {
53  QLayoutItem *item;
54  while ((item = getGridLayout()->takeAt(0)) != 0)
55  {
56  ViewItem* viewItem = dynamic_cast<ViewItem*>(item);
57  delete viewItem;
58  }
60  this->setModified();
61  mMouseEventTarget = NULL;
62 }
63 
68 {
69  return dynamic_cast<QGridLayout*>(layout());
70 }
71 
72 void ViewContainer::paintEvent(QPaintEvent* event)
73 {
74  inherited_widget::paintEvent(event);
75  this->setModified();
76 }
77 
79 {
80  if (this->getGridLayout())
81  {
82  for (int i = 0; i < this->getGridLayout()->count(); ++i)
83  {
84  this->getViewItem(i)->getView()->setModified();
85  }
86  }
87  mMTimeHash = 0;
88 }
89 
91 {
92  return dynamic_cast<ViewItem*>(this->getGridLayout()->itemAt(index));
93 }
94 
99 ViewItem *ViewContainer::addView(QString uid, LayoutRegion region, QString name)
100 {
101  this->initializeRenderWindow();
102 
103  // Create a viewItem for this view
104  ViewItem *item = new ViewItem(uid, name, this, mRenderWindow, QRect());
105  if (getGridLayout())
106  getGridLayout()->addItem(item,
107  region.pos.row, region.pos.col,
108  region.span.row, region.span.col);
109  view_utils::setStretchFactors(this->getGridLayout(), region, 1);
110 
111  return item;
112 }
113 
115 {
116  this->clear();
117  mOffScreenRendering = on;
118 }
119 
121 {
122  return mOffScreenRendering;
123 }
124 
125 void ViewContainer::initializeRenderWindow()
126 {
127  if (mRenderWindow)
128  return;
129 
130  QString uid = QString("rw_oscr=%1").arg(mOffScreenRendering);
131 
132  bool renderWindowExists = mRenderWindowFactory->renderWindowExists(uid);
133 
134  mRenderWindow = mRenderWindowFactory->getRenderWindow(uid, mOffScreenRendering);
135  if(!renderWindowExists)
136  this->addBackgroundRenderer(mRenderWindow);
137  this->SetRenderWindow(mRenderWindow);
138  mRenderWindow->GetInteractor()->EnableRenderOff();
139 
140 
141 
142 // if (!mCachedRenderWindows.count(uid))
143 // {
145 // vtkRenderWindowPtr rw = mRenderWindowFactory->getRenderWindow(uid, mOffScreenRendering);
146 // this->addBackgroundRenderer(rw);
147 // mCachedRenderWindows[uid] = rw;
148 // }
149 
150 // // replace the previous renderwindow with one from the cache.
151 // // the old renderwindow is not hidden explicitly: is this a problem??
154 // mRenderWindow = mCachedRenderWindows[uid];
155 // this->SetRenderWindow(mRenderWindow);
156 // mRenderWindow->GetInteractor()->EnableRenderOff();
158 }
159 
160 void ViewContainer::addBackgroundRenderer(vtkRenderWindowPtr rw)
161 {
162  vtkRendererPtr renderer = vtkRendererPtr::New();
163  rw->AddRenderer(renderer);
164  renderer->SetViewport(0,0,1,1);
165  QColor background = palette().color(QPalette::Background);
166  renderer->SetBackground(background.redF(), background.greenF(), background.blueF());
167 }
168 
169 void ViewContainer::customContextMenuRequestedSlot(const QPoint& point)
170 {
171  ViewItem* item = this->findViewItem(point);
172  if (!item)
173  return;
174 
175  QWidget* sender = dynamic_cast<QWidget*>(this->sender());
176  QPoint pointGlobal = sender->mapToGlobal(point);
177 
178  item->customContextMenuRequestedGlobalSlot(pointGlobal);
179 }
180 
181 void ViewContainer::mouseMoveEvent(QMouseEvent* event)
182 {
183  inherited_widget::mouseMoveEvent(event);
184 
185  if (mMouseEventTarget)
186  {
187  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
188  mMouseEventTarget->mouseMoveSlot(p.x(), p.y(), event->buttons());
189  }
190 }
191 
192 void ViewContainer::mousePressEvent(QMouseEvent* event)
193 {
194  // special case for CustusX: when context menu is opened, mousereleaseevent is never called.
195  // this sets the render interactor in a zoom state after each menu call. This hack prevents
196  // the mouse press event in this case.
197  // NOTE: this doesnt seem to be the case in this class - investigate
198  if ((this->contextMenuPolicy() == Qt::CustomContextMenu) && event->buttons().testFlag(Qt::RightButton))
199  return;
200 
201  inherited_widget::mousePressEvent(event);
202 
203  mMouseEventTarget = this->findViewItem(event->pos());
204  if (mMouseEventTarget)
205  {
206  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
207  mMouseEventTarget->mousePressSlot(p.x(), p.y(), event->buttons());
208  }
209 }
210 
211 QPoint ViewContainer::convertToItemSpace(const QPoint &pos, ViewItem* item) const
212 {
213  QRect r = item->geometry();
214  QPoint retval(pos.x() - r.left(), pos.y() - r.top());
215  return retval;
216 }
217 
218 ViewItem* ViewContainer::findViewItem(const QPoint &pos)
219 {
220  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
221  {
222  ViewItem *item = this->getViewItem(i);
223  QRect r = item->geometry();
224  if (r.contains(pos))
225  return item;
226  }
227  return NULL;
228 }
229 
230 void ViewContainer::mouseReleaseEvent(QMouseEvent* event)
231 {
232  inherited_widget::mouseReleaseEvent(event);
233 
234  if (mMouseEventTarget)
235  {
236  QPoint p = this->convertToItemSpace(event->pos(), mMouseEventTarget);
237  mMouseEventTarget->mouseReleaseSlot(p.x(), p.y(), event->buttons());
238  mMouseEventTarget = NULL;
239  }
240 }
241 
242 void ViewContainer::focusInEvent(QFocusEvent* event)
243 {
244  inherited_widget::focusInEvent(event);
245 }
246 
247 void ViewContainer::wheelEvent(QWheelEvent* event)
248 {
249  inherited_widget::wheelEvent(event);
250 
251  ViewItem *item = this->findViewItem(event->pos());
252  if (item)
253  {
254  QPoint p = this->convertToItemSpace(event->pos(), item);
255  item->mouseWheelSlot(p.x(), p.y(),
256  event->delta(), event->orientation(), event->buttons());
257  }
258 }
259 
260 void ViewContainer::showEvent(QShowEvent* event)
261 {
262  inherited_widget::showEvent(event);
263 }
264 
266 {
267  // First, calculate if anything has changed
268  long hash = 0;
269  for (int i = 0; getGridLayout() && i < getGridLayout()->count(); ++i)
270  {
271  ViewItem *item = this->getViewItem(i);
272  hash += item->getView()->computeTotalMTime();
273  }
274  // Then, if anything has changed, render everything anew
275  if (hash != mMTimeHash)
276  {
277  this->doRender();
278  mMTimeHash = hash;
279 
280  QString msg("During rendering of ViewContainer");
282  }
283 }
284 
286 {
287  if (!mRenderWindow)
288  return;
289  this->getRenderWindow()->Render();
290 }
291 
292 void ViewContainer::resizeEvent( QResizeEvent *event)
293 {
294  inherited_widget::resizeEvent(event);
295  this->setModified();
296  this->getGridLayout()->update();
297 }
298 
299 
300 } /* 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:46
void mouseReleaseSlot(int x, int y, Qt::MouseButtons buttons)
#define report_gl_error_text(text)
Definition: cxGLHelpers.h:29
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:82
LayoutPosition pos
start position of region
Definition: cxLayoutData.h:45
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