Fraxinus  2023.01.05-dev+develop.0da12
An IGT application
cxQVTKWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: CXQVTKWidget.cxx
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /*
16  * Copyright 2004 Sandia Corporation.
17  * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
18  * license for use of this work by or on behalf of the
19  * U.S. Government. Redistribution and use in source and binary forms, with
20  * or without modification, are permitted provided that this Notice and any
21  * statement of authorship are reproduced on all copies.
22  */
23 
24 /*========================================================================
25  For general information about using VTK and Qt, see:
26  http://www.trolltech.com/products/3rdparty/vtksupport.html
27 =========================================================================*/
28 
29 #ifdef _MSC_VER
30 // Disable warnings that Qt headers give.
31 #pragma warning(disable:4127)
32 #pragma warning(disable:4512)
33 #endif
34 
35 #include "cxQVTKWidget.h"
36 
37 //#include "QVTKPaintEngine.h"
38 #include "QVTKInteractorAdapter.h"
39 #include "QVTKInteractor.h"
40 
41 #include "qevent.h"
42 #include "qapplication.h"
43 #include "qpainter.h"
44 #include "qsignalmapper.h"
45 #include "qtimer.h"
46 #include "vtkRenderingOpenGLModule.h"
47 #if defined(Q_WS_X11)
48 #include "qx11info_x11.h"
49 #endif
50 
51 #if defined(Q_WS_WIN)
52 # include <windows.h>
53 # include <QSysInfo>
54 #endif
55 
56 #include "vtkInteractorStyleTrackballCamera.h"
57 #include "vtkRenderWindow.h"
58 #include "vtkCommand.h"
59 #include "vtkOStrStreamWrapper.h"
60 #include "vtkObjectFactory.h"
61 #include "vtkCallbackCommand.h"
62 #include "vtkConfigure.h"
63 #include "vtkUnsignedCharArray.h"
64 #include "vtkImageData.h"
65 #include "vtkPointData.h"
66 #include "vtkRenderer.h"
67 #include "vtkRendererCollection.h"
68 
69 #if defined(VTK_USE_TDX) && defined(Q_WS_X11)
70 # include "vtkTDxUnixDevice.h"
71 #endif
72 
74 CXQVTKWidget::CXQVTKWidget(QWidget* p, Qt::WindowFlags f)
75  : QWidget(p, f | Qt::MSWindowsOwnDC), mRenWin(NULL)
76 {
77  this->UseTDx=false;
78  // no background
79 // this->setAttribute(Qt::WA_NoBackground);
80 // // no double buffering
81 // this->setAttribute(Qt::WA_PaintOnScreen);
82 
83  // default to strong focus
84  this->setFocusPolicy(Qt::StrongFocus);
85 
86  // default to enable mouse events when a mouse button isn't down
87  // so we can send enter/leave events to VTK
88  this->setMouseTracking(true);
89 
90  // set expanding to take up space for better default layouts
91  this->setSizePolicy(
92  QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding )
93  );
94 
95  mIrenAdapter = new QVTKInteractorAdapter(this);
96 
97 }
98 
102 {
103  // get rid of the VTK window
104  this->SetRenderWindow(NULL);
105 }
106 
107 // ----------------------------------------------------------------------------
108 void CXQVTKWidget::SetUseTDx(bool useTDx)
109 {
110  if(useTDx!=this->UseTDx)
111  {
112  this->UseTDx=useTDx;
113  if(this->UseTDx)
114  {
115 #if defined(VTK_USE_TDX) && defined(Q_WS_X11)
116  QByteArray theSignal=
117  QMetaObject::normalizedSignature("CreateDevice(vtkTDxDevice *)");
118  if(QApplication::instance()->metaObject()->indexOfSignal(theSignal)!=-1)
119  {
120  QObject::connect(QApplication::instance(),
121  SIGNAL(CreateDevice(vtkTDxDevice *)),
122  this,
123  SLOT(setDevice(vtkTDxDevice *)));
124  }
125  else
126  {
127  vtkGenericWarningMacro("Missing signal CreateDevice on QApplication. 3DConnexion device will not work. Define it or derive your QApplication from QVTKApplication.");
128  }
129 #endif
130  }
131  }
132 }
133 
134 // ----------------------------------------------------------------------------
136 {
137  return this->UseTDx;
138 }
139 
143 {
144  if (!this->mRenWin)
145  {
146  // create a default vtk window
147  vtkRenderWindow* win = vtkRenderWindow::New();
148  this->SetRenderWindow(win);
149  win->Delete();
150  }
151 
152  return this->mRenWin;
153 }
154 
159 void CXQVTKWidget::SetRenderWindow(vtkRenderWindow* w)
160 {
161  // do nothing if we don't have to
162  if(w == this->mRenWin)
163  {
164  return;
165  }
166 
167  // unregister previous window
168  if(this->mRenWin)
169  {
170  //clean up window as one could remap it
171  if(this->mRenWin->GetMapped())
172  {
173  this->mRenWin->Finalize();
174  }
175 #ifdef Q_WS_X11
176  this->mRenWin->SetDisplayId(NULL);
177 #endif
178  this->mRenWin->SetWindowId(NULL);
179  this->mRenWin->UnRegister(NULL);
180  }
181 
182  // now set the window
183  this->mRenWin = w;
184 
185  if(this->mRenWin)
186  {
187  // register new window
188  this->mRenWin->Register(NULL);
189 
190  // if it is mapped somewhere else, unmap it
191  if(this->mRenWin->GetMapped())
192  {
193  this->mRenWin->Finalize();
194  }
195 
196 #ifdef Q_WS_X11
197  // give the qt display id to the vtk window
198  this->mRenWin->SetDisplayId(QX11Info::display());
199 #endif
200 
201  // special x11 setup
203 
204  // give the qt window id to the vtk window
205  this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
206 
207  // tell the vtk window what the size of this window is
208  this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height());
209  this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y());
210 
211  // have VTK start this window and create the necessary graphics resources
212  if(isVisible())
213  {
214  this->mRenWin->Start();
215  }
216 
217  // if an interactor wasn't provided, we'll make one by default
218  if(!this->mRenWin->GetInteractor())
219  {
220  // create a default interactor
221  QVTKInteractor* iren = QVTKInteractor::New();
222  iren->SetUseTDx(this->UseTDx);
223  this->mRenWin->SetInteractor(iren);
224  iren->Initialize();
225 
226  // now set the default style
227  vtkInteractorStyle* s = vtkInteractorStyleTrackballCamera::New();
228  iren->SetInteractorStyle(s);
229 
230  iren->Delete();
231  s->Delete();
232  }
233  // tell the interactor the size of this window
234  this->mRenWin->GetInteractor()->SetSize(this->width(), this->height());
235  }
236 }
237 
238 
239 
243 {
244  return QVTKInteractor
245  ::SafeDownCast(this->GetRenderWindow()->GetInteractor());
246 }
247 
248 
252 bool CXQVTKWidget::event(QEvent* e)
253 {
254  if(e->type() == QEvent::ParentAboutToChange)
255  {
256  if (this->mRenWin)
257  {
258  // Finalize the window to remove graphics resources associated with
259  // this window
260  if(this->mRenWin->GetMapped())
261  {
262  this->mRenWin->Finalize();
263  }
264  }
265  }
266  else if(e->type() == QEvent::ParentChange)
267  {
268  if(this->mRenWin)
269  {
271  // connect to new window
272  this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
273 
274  // start up the window to create graphics resources for this window
275  if(isVisible())
276  {
277  this->mRenWin->Start();
278  }
279  }
280  }
281 
282  if(QObject::event(e))
283  {
284  return true;
285  }
286 
287  if(e->type() == QEvent::KeyPress)
288  {
289  QKeyEvent* ke = static_cast<QKeyEvent*>(e);
290  this->keyPressEvent(ke);
291  return ke->isAccepted();
292  }
293 
294  return QWidget::event(e);
295 }
296 
297 
300 void CXQVTKWidget::resizeEvent(QResizeEvent* e)
301 {
302  return;
303  QWidget::resizeEvent(e);
304 
305  if(!this->mRenWin)
306  {
307  return;
308  }
309 
310  // Don't set size on subclass of vtkRenderWindow or it triggers recursion.
311  // Getting this event in the first place means the window was already
312  // resized and we're updating the sizes in VTK.
313  this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height());
314 
315  // and update the interactor
316  if(this->mRenWin->GetInteractor())
317  {
318  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
319  }
320 
321 }
322 
323 void CXQVTKWidget::moveEvent(QMoveEvent* e)
324 {
325  QWidget::moveEvent(e);
326 
327  if(!this->mRenWin)
328  {
329  return;
330  }
331 
332  // Don't set size on subclass of vtkRenderWindow or it triggers recursion.
333  // Getting this event in the first place means the window was already
334  // resized and we're updating the sizes in VTK.
335  this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y());
336 }
337 
339 // */
340 void CXQVTKWidget::paintEvent(QPaintEvent* )
341 {
342  std::cout << "******************** paintEvent " << this << std::endl;
343  std::cout << " xy= " << this->x() << ", " << this->y() << " \t wh= " << this->width() << ", " << this->height() << std::endl;
344 // vtkRenderWindowInteractor* iren = NULL;
345 // if(this->mRenWin)
346 // {
347 // iren = this->mRenWin->GetInteractor();
348 // }
349 
350 // if(!iren || !iren->GetEnabled())
351 // {
352 // return;
353 // }
354 
355 // std::cout << "******************** paintEvent into" << std::endl;
356 
357 // iren->Render();
358 
359 // // In Qt 4.1+ let's support redirected painting
360 // // if redirected, let's grab the image from VTK, and paint it to the device
361 // QPaintDevice* device = QPainter::redirected(this);
362 // if(device != NULL && device != this)
363 // {
364 // int w = this->width();
365 // int h = this->height();
366 // QImage img(w, h, QImage::Format_RGB32);
367 // vtkUnsignedCharArray* pixels = vtkUnsignedCharArray::New();
368 // pixels->SetArray(img.bits(), w*h*4, 1);
369 // this->mRenWin->GetRGBACharPixelData(0, 0, w-1, h-1, 1, pixels);
370 // pixels->Delete();
371 // img = img.rgbSwapped();
372 // img = img.mirrored();
373 
374 // QPainter painter(this);
375 // painter.drawImage(QPointF(0.0,0.0), img);
376 // return;
377 // }
378 }
379 
382 void CXQVTKWidget::mousePressEvent(QMouseEvent* e)
383 {
384 
385  // Emit a mouse press event for anyone who might be interested
386  emit mouseEvent(e);
387 
388  if(this->mRenWin)
389  {
390  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
391  }
392 
393 }
394 
397 void CXQVTKWidget::mouseMoveEvent(QMouseEvent* e)
398 {
399  if(this->mRenWin)
400  {
401  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
402 
403  // Emit a mouse press event for anyone who might be interested
404  emit mouseEvent(e);
405  }
406 }
407 
408 
412 {
413  if(this->mRenWin)
414  {
415  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
416  }
417 }
418 
422 {
423  if(this->mRenWin)
424  {
425  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
426  }
427 }
428 
432 {
433  if(this->mRenWin)
434  {
435  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
436 
437  // Emit a mouse press event for anyone who might be interested
438  emit mouseEvent(e);
439  }
440 }
441 
444 void CXQVTKWidget::keyPressEvent(QKeyEvent* e)
445 {
446  if(this->mRenWin)
447  {
448  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
449  }
450 }
451 
455 {
456  if(this->mRenWin)
457  {
458  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
459  }
460 }
461 
462 void CXQVTKWidget::wheelEvent(QWheelEvent* e)
463 {
464  if(this->mRenWin)
465  {
466  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
467  }
468 }
469 
470 void CXQVTKWidget::focusInEvent(QFocusEvent* e)
471 {
472  // These prevent updates when the window
473  // gains or loses focus. By default, Qt
474  // does an update because the color group's
475  // active status changes. We don't even use
476  // color groups so we do nothing here.
477 
478  // also pass to interactor
479  mIrenAdapter->ProcessEvent(e, this->GetInteractor());
480 }
481 
482 void CXQVTKWidget::focusOutEvent(QFocusEvent* e)
483 {
484  // These prevent updates when the window
485  // gains or loses focus. By default, Qt
486  // does an update because the color group's
487  // active status changes. We don't even use
488  // color groups so we do nothing here.
489 
490  // also pass to interactor
491  mIrenAdapter->ProcessEvent(e, this->GetInteractor());
492 }
493 
494 
495 void CXQVTKWidget::contextMenuEvent(QContextMenuEvent* e)
496 {
497  if(this->mRenWin)
498  {
499  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
500  }
501 }
502 
503 void CXQVTKWidget::dragEnterEvent(QDragEnterEvent* e)
504 {
505  if(this->mRenWin)
506  {
507  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
508  }
509 }
510 
511 void CXQVTKWidget::dragMoveEvent(QDragMoveEvent* e)
512 {
513  if(this->mRenWin)
514  {
515  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
516  }
517 }
518 
519 void CXQVTKWidget::dragLeaveEvent(QDragLeaveEvent* e)
520 {
521  if(this->mRenWin)
522  {
523  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
524  }
525 }
526 
527 void CXQVTKWidget::dropEvent(QDropEvent* e)
528 {
529  if(this->mRenWin)
530  {
531  mIrenAdapter->ProcessEvent(e, this->mRenWin->GetInteractor());
532  }
533 }
534 
535 void CXQVTKWidget::showEvent(QShowEvent* e)
536 {
537  QWidget::showEvent(e);
538 }
539 
540 
541 // X11 stuff near the bottom of the file
542 // to prevent namespace collisions with Qt headers
543 
544 #if defined Q_WS_X11
545 #if defined(VTK_USE_OPENGL_LIBRARY)
546 #include "vtkXOpenGLRenderWindow.h"
547 #endif
548 #endif
549 
550 #ifdef VTK_USE_TDX
551 // Description:
552 // Receive notification of the creation of the TDxDevice
553 void CXQVTKWidget::setDevice(vtkTDxDevice *device)
554 {
555 #ifdef Q_WS_X11
556  if(this->GetInteractor()->GetDevice()!=device)
557  {
558  this->GetInteractor()->SetDevice(device);
559  }
560 #else
561  (void)device; // to avoid warnings.
562 #endif
563 }
564 #endif
565 
567 {
568 #if defined Q_WS_X11
569 
570  // this whole function is to allow this window to have a
571  // different colormap and visual than the rest of the Qt application
572  // this is very important if Qt's default visual and colormap is
573  // not enough to get a decent graphics window
574 
575 
576  // save widget states
577  bool tracking = this->hasMouseTracking();
578  Qt::FocusPolicy focus_policy = focusPolicy();
579  bool visible = isVisible();
580  if(visible)
581  {
582  hide();
583  }
584 
585 
586  // get visual and colormap from VTK
587  XVisualInfo* vi = 0;
588  Colormap cmap = 0;
589  Display* display = reinterpret_cast<Display*>(mRenWin->GetGenericDisplayId());
590 
591  // check ogl and mesa and get information we need to create a decent window
592 #if defined(VTK_USE_OPENGL_LIBRARY)
593  vtkXOpenGLRenderWindow* ogl_win = vtkXOpenGLRenderWindow::SafeDownCast(mRenWin);
594  if(ogl_win)
595  {
596  vi = ogl_win->GetDesiredVisualInfo();
597  cmap = ogl_win->GetDesiredColormap();
598  }
599 #endif
600 
601  // can't get visual, oh well.
602  // continue with Qt's default visual as it usually works
603  if(!vi)
604  {
605  if(visible)
606  {
607  show();
608  }
609  return;
610  }
611 
612  // create the X window based on information VTK gave us
613  XSetWindowAttributes attrib;
614  attrib.colormap = cmap;
615  attrib.border_pixel = 0;
616  attrib.background_pixel = 0;
617 
618  Window p = RootWindow(display, DefaultScreen(display));
619  if(parentWidget())
620  {
621  p = parentWidget()->winId();
622  }
623 
624  XWindowAttributes a;
625  XGetWindowAttributes(display, this->winId(), &a);
626 
627  Window win = XCreateWindow(display, p, a.x, a.y, a.width, a.height,
628  0, vi->depth, InputOutput, vi->visual,
629  CWBackPixel|CWBorderPixel|CWColormap, &attrib);
630 
631  // backup colormap stuff
632  Window *cmw;
633  Window *cmwret;
634  int count;
635  if ( XGetWMColormapWindows(display, topLevelWidget()->winId(), &cmwret, &count) )
636  {
637  cmw = new Window[count+1];
638  memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count );
639  XFree( (char *)cmwret );
640  int i;
641  for ( i=0; i<count; i++ )
642  {
643  if ( cmw[i] == winId() )
644  {
645  cmw[i] = win;
646  break;
647  }
648  }
649  if ( i >= count )
650  {
651  cmw[count++] = win;
652  }
653  }
654  else
655  {
656  count = 1;
657  cmw = new Window[count];
658  cmw[0] = win;
659  }
660 
661 
662  // tell Qt to initialize anything it needs to for this window
663  create(win);
664 
665  // restore colormaps
666  XSetWMColormapWindows( display, topLevelWidget()->winId(), cmw, count );
667 
668  delete [] cmw;
669  XFree(vi);
670 
671  XFlush(display);
672 
673  // restore widget states
674  this->setMouseTracking(tracking);
675  this->setAttribute(Qt::WA_NoBackground);
676  this->setAttribute(Qt::WA_PaintOnScreen);
677  this->setFocusPolicy(focus_policy);
678  if(visible)
679  {
680  show();
681  }
682 
683 #endif
684 }
685 
686 #if defined(Q_WS_WIN)
687 bool CXQVTKWidget::winEvent(MSG* msg, long*)
688 {
689  // Starting with Windows Vista, Microsoft introduced WDDM.
690  // We need to call InvalidateRect() to work with WDDM correctly,
691  // especially when AERO is off.
692  if(msg->message == WM_PAINT &&
693  QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
694  {
695  InvalidateRect(this->winId(), NULL, FALSE);
696  }
697  return false;
698 }
699 #endif
700 
bool GetUseTDx() const
virtual void paintEvent(QPaintEvent *event)
virtual void dropEvent(QDropEvent *)
virtual QVTKInteractor * GetInteractor()
void mouseEvent(QMouseEvent *event)
virtual void showEvent(QShowEvent *)
virtual void mouseReleaseEvent(QMouseEvent *event)
virtual void dragMoveEvent(QDragMoveEvent *)
virtual ~CXQVTKWidget()
destructor
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void SetRenderWindow(vtkRenderWindow *)
void SetUseTDx(bool useTDx)
virtual void keyPressEvent(QKeyEvent *event)
virtual void wheelEvent(QWheelEvent *)
virtual void focusInEvent(QFocusEvent *)
virtual vtkRenderWindow * GetRenderWindow()
virtual void contextMenuEvent(QContextMenuEvent *)
virtual void keyReleaseEvent(QKeyEvent *event)
virtual void focusOutEvent(QFocusEvent *)
virtual void dragEnterEvent(QDragEnterEvent *)
virtual void dragLeaveEvent(QDragLeaveEvent *)
virtual void mousePressEvent(QMouseEvent *event)
virtual void moveEvent(QMoveEvent *event)
virtual void leaveEvent(QEvent *)
virtual void resizeEvent(QResizeEvent *event)
QVTKInteractorAdapter * mIrenAdapter
Definition: cxQVTKWidget.h:182
CXQVTKWidget(QWidget *parent=NULL, Qt::WindowFlags f=0)
constructor
virtual void enterEvent(QEvent *)
vtkRenderWindow * mRenWin
Definition: cxQVTKWidget.h:169
void x11_setup_window()
bool event(QEvent *e)