You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1376 lines
36 KiB
1376 lines
36 KiB
2 years ago
|
/*
|
||
|
* Copyright 2004 Sandia Corporation.
|
||
|
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
|
||
|
* license for use of this work by or on behalf of the
|
||
|
* U.S. Government. Redistribution and use in source and binary forms, with
|
||
|
* or without modification, are permitted provided that this Notice and any
|
||
|
* statement of authorship are reproduced on all copies.
|
||
|
*/
|
||
|
|
||
|
/*========================================================================
|
||
|
For general information about using VTK and Qt, see:
|
||
|
http://www.trolltech.com/products/3rdparty/vtksupport.html
|
||
|
=========================================================================*/
|
||
|
|
||
|
/*========================================================================
|
||
|
!!! WARNING for those who want to contribute code to this file.
|
||
|
!!! If you use a commercial edition of Qt, you can modify this code.
|
||
|
!!! If you use an open source version of Qt, you are free to modify
|
||
|
!!! and use this code within the guidelines of the GPL license.
|
||
|
!!! Unfortunately, you cannot contribute the changes back into this
|
||
|
!!! file. Doing so creates a conflict between the GPL and BSD-like VTK
|
||
|
!!! license.
|
||
|
=========================================================================*/
|
||
|
|
||
|
#include "QVTKWidget.h"
|
||
|
|
||
|
#include "qevent.h"
|
||
|
#include "qapplication.h"
|
||
|
#include "qpainter.h"
|
||
|
#if QT_VERSION >= 0x040000 && defined(Q_WS_X11)
|
||
|
#include "qx11info_x11.h"
|
||
|
#endif
|
||
|
|
||
|
#include "vtkInteractorStyleTrackballCamera.h"
|
||
|
#include "vtkRenderWindow.h"
|
||
|
#if defined(Q_WS_MAC)
|
||
|
# include "vtkCarbonRenderWindow.h"
|
||
|
#endif
|
||
|
#include "vtkCommand.h"
|
||
|
#include "vtkOStrStreamWrapper.h"
|
||
|
#include "vtkObjectFactory.h"
|
||
|
#include "vtkCallbackCommand.h"
|
||
|
#include "vtkConfigure.h"
|
||
|
#include "vtkToolkits.h"
|
||
|
#include "vtkUnsignedCharArray.h"
|
||
|
|
||
|
|
||
|
// VTK 4.5 added some major functionality, so we'll make a short define to use
|
||
|
#if (VTK_MAJOR_VERSION > 4) || (VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION >=5)
|
||
|
#define QVTK_HAVE_VTK_4_5
|
||
|
#endif
|
||
|
|
||
|
#if QT_VERSION >= 0x040000 && !defined(QVTK_HAVE_VTK_4_5)
|
||
|
#error "Qt4 and VTK < 4.5 is not supported"
|
||
|
#endif
|
||
|
|
||
|
// function to get VTK keysyms from ascii characters
|
||
|
static const char* ascii_to_key_sym(int);
|
||
|
// function to get VTK keysyms from Qt keys
|
||
|
static const char* qt_key_to_key_sym(Qt::Key);
|
||
|
|
||
|
// function to dirty cache when a render occurs.
|
||
|
static void dirty_cache(vtkObject *, unsigned long, void *, void *);
|
||
|
|
||
|
|
||
|
|
||
|
#if QT_VERSION < 0x040000
|
||
|
/*! constructor */
|
||
|
QVTKWidget::QVTKWidget(QWidget* parent, const char* name, Qt::WFlags f)
|
||
|
#if QT_VERSION < 0x030000
|
||
|
: QWidget(parent, name, f | 0x10000000) // WWinOwnDC
|
||
|
#else
|
||
|
: QWidget(parent, name, f | Qt::WWinOwnDC )
|
||
|
#endif
|
||
|
, mRenWin(NULL),
|
||
|
cachedImageCleanFlag(false),
|
||
|
automaticImageCache(false), maxImageCacheRenderRate(1.0)
|
||
|
{
|
||
|
// no background
|
||
|
setBackgroundMode( Qt::NoBackground );
|
||
|
|
||
|
// default to strong focus
|
||
|
this->setFocusPolicy(QWidget::StrongFocus);
|
||
|
|
||
|
// default to enable mouse events when a mouse button isn't down
|
||
|
// so we can send enter/leave events to VTK
|
||
|
this->setMouseTracking(true);
|
||
|
|
||
|
// set expanding to take up space for better default layouts
|
||
|
this->setSizePolicy(
|
||
|
QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding )
|
||
|
);
|
||
|
|
||
|
this->mCachedImage = vtkUnsignedCharArray::New();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if QT_VERSION >= 0x040000
|
||
|
/*! constructor */
|
||
|
QVTKWidget::QVTKWidget(QWidget* parent, Qt::WFlags f)
|
||
|
: QWidget(parent, f | Qt::MSWindowsOwnDC), mRenWin(NULL),
|
||
|
cachedImageCleanFlag(false),
|
||
|
automaticImageCache(false), maxImageCacheRenderRate(1.0)
|
||
|
|
||
|
{
|
||
|
// no background
|
||
|
this->setAttribute(Qt::WA_NoBackground);
|
||
|
// no double buffering
|
||
|
this->setAttribute(Qt::WA_PaintOnScreen);
|
||
|
|
||
|
// default to strong focus
|
||
|
this->setFocusPolicy(Qt::StrongFocus);
|
||
|
|
||
|
// default to enable mouse events when a mouse button isn't down
|
||
|
// so we can send enter/leave events to VTK
|
||
|
this->setMouseTracking(true);
|
||
|
|
||
|
// set expanding to take up space for better default layouts
|
||
|
this->setSizePolicy(
|
||
|
QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding )
|
||
|
);
|
||
|
|
||
|
this->mCachedImage = vtkUnsignedCharArray::New();
|
||
|
|
||
|
#if defined(Q_WS_MAC)
|
||
|
this->DirtyRegionHandler = 0;
|
||
|
this->DirtyRegionHandlerUPP = 0;
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*! destructor */
|
||
|
|
||
|
QVTKWidget::~QVTKWidget()
|
||
|
{
|
||
|
// get rid of the VTK window
|
||
|
this->SetRenderWindow(NULL);
|
||
|
|
||
|
this->mCachedImage->Delete();
|
||
|
}
|
||
|
|
||
|
/*! get the render window
|
||
|
*/
|
||
|
vtkRenderWindow* QVTKWidget::GetRenderWindow()
|
||
|
{
|
||
|
if (!this->mRenWin)
|
||
|
{
|
||
|
// create a default vtk window
|
||
|
vtkRenderWindow* win = vtkRenderWindow::New();
|
||
|
this->SetRenderWindow(win);
|
||
|
win->Delete();
|
||
|
}
|
||
|
|
||
|
return this->mRenWin;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*! set the render window
|
||
|
this will bind a VTK window with the Qt window
|
||
|
it'll also replace an existing VTK window
|
||
|
*/
|
||
|
void QVTKWidget::SetRenderWindow(vtkRenderWindow* window)
|
||
|
{
|
||
|
// do nothing if we don't have to
|
||
|
if(window == this->mRenWin)
|
||
|
return;
|
||
|
|
||
|
// unregister previous window
|
||
|
if(this->mRenWin)
|
||
|
{
|
||
|
#if defined(QVTK_HAVE_VTK_4_5)
|
||
|
//clean up window as one could remap it
|
||
|
if(this->mRenWin->GetMapped())
|
||
|
this->mRenWin->Finalize();
|
||
|
#endif
|
||
|
this->mRenWin->SetDisplayId(NULL);
|
||
|
this->mRenWin->SetParentId(NULL);
|
||
|
this->mRenWin->SetWindowId(NULL);
|
||
|
this->mRenWin->UnRegister(NULL);
|
||
|
}
|
||
|
|
||
|
// now set the window
|
||
|
this->mRenWin = window;
|
||
|
|
||
|
if(this->mRenWin)
|
||
|
{
|
||
|
// register new window
|
||
|
this->mRenWin->Register(NULL);
|
||
|
|
||
|
#if defined(QVTK_HAVE_VTK_4_5)
|
||
|
// if it is mapped somewhere else, unmap it
|
||
|
if(this->mRenWin->GetMapped())
|
||
|
this->mRenWin->Finalize();
|
||
|
#endif
|
||
|
|
||
|
#ifdef Q_WS_X11
|
||
|
// give the qt display id to the vtk window
|
||
|
#if QT_VERSION < 0x040000
|
||
|
this->mRenWin->SetDisplayId( this->x11Display() );
|
||
|
#else
|
||
|
this->mRenWin->SetDisplayId(QX11Info::display());
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
// special x11 setup
|
||
|
x11_setup_window();
|
||
|
|
||
|
// give the qt window id to the vtk window
|
||
|
this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
|
||
|
|
||
|
// mac compatibility issues
|
||
|
#ifdef Q_WS_MAC
|
||
|
# ifdef QVTK_HAVE_VTK_4_5
|
||
|
# if QT_VERSION < 0x040000
|
||
|
this->mRenWin->SetWindowId( NULL );
|
||
|
static_cast<vtkCarbonRenderWindow*>(this->mRenWin)->SetRootWindow(
|
||
|
reinterpret_cast<WindowPtr>(this->handle()));
|
||
|
# endif
|
||
|
# else
|
||
|
// give the Qt/Mac window handle to VTK and flag whether we have a parent
|
||
|
this->mRenWin->SetWindowId(reinterpret_cast<void*>(this->handle()));
|
||
|
this->mRenWin->SetParentId(reinterpret_cast<void*>(0x1));
|
||
|
# endif
|
||
|
# endif
|
||
|
|
||
|
|
||
|
// tell the vtk window what the size of this window is
|
||
|
this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height());
|
||
|
this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y());
|
||
|
|
||
|
// have VTK start this window and create the necessary graphics resources
|
||
|
if(isVisible())
|
||
|
{
|
||
|
this->mRenWin->Start();
|
||
|
#if defined (Q_WS_MAC) && (QT_VERSION < 0x040000)
|
||
|
macFixRect();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// if an interactor wasn't provided, we'll make one by default
|
||
|
if(!this->mRenWin->GetInteractor())
|
||
|
{
|
||
|
// create a default interactor
|
||
|
QVTKInteractor* iren = QVTKInteractor::New();
|
||
|
this->mRenWin->SetInteractor(iren);
|
||
|
iren->Initialize();
|
||
|
|
||
|
// now set the default style
|
||
|
vtkInteractorStyle* style = vtkInteractorStyleTrackballCamera::New();
|
||
|
iren->SetInteractorStyle(style);
|
||
|
|
||
|
iren->Delete();
|
||
|
style->Delete();
|
||
|
}
|
||
|
|
||
|
// tell the interactor the size of this window
|
||
|
this->mRenWin->GetInteractor()->SetSize(this->width(), this->height());
|
||
|
|
||
|
// Add an observer to monitor when the image changes. Should work most
|
||
|
// of the time. The application will have to call
|
||
|
// markCachedImageAsDirty for any other case.
|
||
|
vtkCallbackCommand *cbc = vtkCallbackCommand::New();
|
||
|
cbc->SetClientData(this);
|
||
|
cbc->SetCallback(dirty_cache);
|
||
|
this->mRenWin->AddObserver(vtkCommand::EndEvent, cbc);
|
||
|
cbc->Delete();
|
||
|
}
|
||
|
|
||
|
#if defined(Q_WS_MAC) && QT_VERSION >= 0x040000
|
||
|
if(mRenWin && !this->DirtyRegionHandlerUPP)
|
||
|
{
|
||
|
this->DirtyRegionHandlerUPP = NewEventHandlerUPP(QVTKWidget::DirtyRegionProcessor);
|
||
|
static EventTypeSpec events[] = { {'cute', 20} };
|
||
|
// kEventClassQt, kEventQtRequestWindowChange from qt_mac_p.h
|
||
|
// Suggested by Sam Magnuson at Trolltech as best portabile hack
|
||
|
// around Apple's missing functionality in HI Toolbox.
|
||
|
InstallEventHandler(GetApplicationEventTarget(), this->DirtyRegionHandlerUPP,
|
||
|
GetEventTypeCount(events), events,
|
||
|
reinterpret_cast<void*>(this), &this->DirtyRegionHandler);
|
||
|
}
|
||
|
else if(!mRenWin && this->DirtyRegionHandlerUPP)
|
||
|
{
|
||
|
RemoveEventHandler(this->DirtyRegionHandler);
|
||
|
DisposeEventHandlerUPP(this->DirtyRegionHandlerUPP);
|
||
|
this->DirtyRegionHandler = 0;
|
||
|
this->DirtyRegionHandlerUPP = 0;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*! get the Qt/VTK interactor
|
||
|
*/
|
||
|
QVTKInteractor* QVTKWidget::GetInteractor()
|
||
|
{
|
||
|
return QVTKInteractor
|
||
|
::SafeDownCast(this->GetRenderWindow()->GetInteractor());
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::markCachedImageAsDirty()
|
||
|
{
|
||
|
if (this->cachedImageCleanFlag)
|
||
|
{
|
||
|
this->cachedImageCleanFlag = false;
|
||
|
emit cachedImageDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::saveImageToCache()
|
||
|
{
|
||
|
if (this->cachedImageCleanFlag) return;
|
||
|
|
||
|
this->mRenWin->GetPixelData(0, 0, this->width()-1, this->height()-1, 1,
|
||
|
this->mCachedImage);
|
||
|
this->cachedImageCleanFlag = true;
|
||
|
emit cachedImageClean();
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::setAutomaticImageCacheEnabled(bool flag)
|
||
|
{
|
||
|
this->automaticImageCache = flag;
|
||
|
if (!flag)
|
||
|
{
|
||
|
this->mCachedImage->Initialize();
|
||
|
}
|
||
|
}
|
||
|
bool QVTKWidget::isAutomaticImageCacheEnabled() const
|
||
|
{
|
||
|
return this->automaticImageCache;
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::setMaxRenderRateForImageCache(double rate)
|
||
|
{
|
||
|
this->maxImageCacheRenderRate = rate;
|
||
|
}
|
||
|
double QVTKWidget::maxRenderRateForImageCache() const
|
||
|
{
|
||
|
return this->maxImageCacheRenderRate;
|
||
|
}
|
||
|
|
||
|
vtkUnsignedCharArray* QVTKWidget::cachedImage()
|
||
|
{
|
||
|
// Make sure image is up to date.
|
||
|
this->paintEvent(NULL);
|
||
|
this->saveImageToCache();
|
||
|
|
||
|
return this->mCachedImage;
|
||
|
}
|
||
|
|
||
|
/*! overloaded Qt's event handler to capture additional keys that Qt has
|
||
|
default behavior for (for example the Tab and Shift-Tab key)
|
||
|
*/
|
||
|
bool QVTKWidget::event(QEvent* e)
|
||
|
{
|
||
|
#if QT_VERSION >= 0x040000 && defined(QVTK_HAVE_VTK_4_5)
|
||
|
if(e->type() == QEvent::ParentAboutToChange)
|
||
|
{
|
||
|
this->markCachedImageAsDirty();
|
||
|
if (this->mRenWin)
|
||
|
{
|
||
|
// Finalize the window to remove graphics resources associated with
|
||
|
// this window
|
||
|
if(this->mRenWin->GetMapped())
|
||
|
this->mRenWin->Finalize();
|
||
|
}
|
||
|
}
|
||
|
else if(e->type() == QEvent::ParentChange)
|
||
|
{
|
||
|
if(this->mRenWin)
|
||
|
{
|
||
|
x11_setup_window();
|
||
|
// connect to new window
|
||
|
this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
|
||
|
|
||
|
// start up the window to create graphics resources for this window
|
||
|
if(isVisible())
|
||
|
this->mRenWin->Start();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if(QObject::event(e))
|
||
|
return TRUE;
|
||
|
|
||
|
if(e->type() == QEvent::KeyPress)
|
||
|
{
|
||
|
QKeyEvent* ke = static_cast<QKeyEvent*>(e);
|
||
|
keyPressEvent(ke);
|
||
|
return ke->isAccepted();
|
||
|
}
|
||
|
|
||
|
return QWidget::event(e);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*! handle resize event
|
||
|
*/
|
||
|
void QVTKWidget::resizeEvent(QResizeEvent* event)
|
||
|
{
|
||
|
QWidget::resizeEvent(event);
|
||
|
|
||
|
if(!this->mRenWin)
|
||
|
return;
|
||
|
|
||
|
// give the size to the interactor and vtk window
|
||
|
this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height());
|
||
|
if(this->mRenWin->GetInteractor())
|
||
|
this->mRenWin->GetInteractor()->SetSize(this->width(), this->height());
|
||
|
this->markCachedImageAsDirty();
|
||
|
|
||
|
#if defined (Q_WS_MAC) && (QT_VERSION < 0x040000)
|
||
|
macFixRect();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::moveEvent(QMoveEvent* event)
|
||
|
{
|
||
|
QWidget::moveEvent(event);
|
||
|
|
||
|
if(!this->mRenWin)
|
||
|
return;
|
||
|
|
||
|
// give the size to the interactor and vtk window
|
||
|
this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y());
|
||
|
|
||
|
#if defined (Q_WS_MAC) && (QT_VERSION < 0x040000)
|
||
|
macFixRect();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*! handle paint event
|
||
|
*/
|
||
|
void QVTKWidget::paintEvent(QPaintEvent* )
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
|
||
|
// if we have a saved image, use it
|
||
|
if (this->cachedImageCleanFlag)
|
||
|
{
|
||
|
// put cached image into back buffer if we can
|
||
|
this->mRenWin->SetPixelData(0, 0, this->width()-1, this->height()-1,
|
||
|
this->mCachedImage,
|
||
|
!this->mRenWin->GetDoubleBuffer());
|
||
|
// swap buffers, if double buffering
|
||
|
this->mRenWin->Frame();
|
||
|
// or should we just put it on the front buffer?
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
iren->Render();
|
||
|
}
|
||
|
|
||
|
/*! handle mouse press event
|
||
|
*/
|
||
|
void QVTKWidget::mousePressEvent(QMouseEvent* event)
|
||
|
{
|
||
|
|
||
|
// Emit a mouse press event for anyone who might be interested
|
||
|
emit mouseEvent(event);
|
||
|
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// give interactor the event information
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton ),
|
||
|
0,
|
||
|
event->type() == QEvent::MouseButtonDblClick ? 1 : 0);
|
||
|
#else
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier ),
|
||
|
0,
|
||
|
event->type() == QEvent::MouseButtonDblClick ? 1 : 0);
|
||
|
#endif
|
||
|
|
||
|
// invoke appropriate vtk event
|
||
|
switch(event->button())
|
||
|
{
|
||
|
case Qt::LeftButton:
|
||
|
iren->InvokeEvent(vtkCommand::LeftButtonPressEvent, event);
|
||
|
break;
|
||
|
|
||
|
case Qt::MidButton:
|
||
|
iren->InvokeEvent(vtkCommand::MiddleButtonPressEvent, event);
|
||
|
break;
|
||
|
|
||
|
case Qt::RightButton:
|
||
|
iren->InvokeEvent(vtkCommand::RightButtonPressEvent, event);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*! handle mouse move event
|
||
|
*/
|
||
|
void QVTKWidget::mouseMoveEvent(QMouseEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// give interactor the event information
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton ));
|
||
|
#else
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier ));
|
||
|
#endif
|
||
|
|
||
|
// invoke vtk event
|
||
|
iren->InvokeEvent(vtkCommand::MouseMoveEvent, event);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*! handle enter event
|
||
|
*/
|
||
|
void QVTKWidget::enterEvent(QEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
iren->InvokeEvent(vtkCommand::EnterEvent, event);
|
||
|
}
|
||
|
|
||
|
/*! handle leave event
|
||
|
*/
|
||
|
void QVTKWidget::leaveEvent(QEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
iren->InvokeEvent(vtkCommand::LeaveEvent, event);
|
||
|
}
|
||
|
|
||
|
/*! handle mouse release event
|
||
|
*/
|
||
|
void QVTKWidget::mouseReleaseEvent(QMouseEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// give vtk event information
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton ));
|
||
|
#else
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier ));
|
||
|
#endif
|
||
|
|
||
|
// invoke appropriate vtk event
|
||
|
switch(event->button())
|
||
|
{
|
||
|
case Qt::LeftButton:
|
||
|
iren->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, event);
|
||
|
break;
|
||
|
|
||
|
case Qt::MidButton:
|
||
|
iren->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, event);
|
||
|
break;
|
||
|
|
||
|
case Qt::RightButton:
|
||
|
iren->InvokeEvent(vtkCommand::RightButtonReleaseEvent, event);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*! handle key press event
|
||
|
*/
|
||
|
void QVTKWidget::keyPressEvent(QKeyEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// get key and keysym information
|
||
|
#if QT_VERSION < 0x040000
|
||
|
int ascii_key = event->text().length() ? event->text().unicode()->latin1() : 0;
|
||
|
#else
|
||
|
int ascii_key = event->text().length() ? event->text().unicode()->toLatin1() : 0;
|
||
|
#endif
|
||
|
const char* keysym = ascii_to_key_sym(ascii_key);
|
||
|
if(!keysym)
|
||
|
{
|
||
|
// get virtual keys
|
||
|
keysym = qt_key_to_key_sym(static_cast<Qt::Key>(event->key()));
|
||
|
}
|
||
|
|
||
|
if(!keysym)
|
||
|
{
|
||
|
keysym = "None";
|
||
|
}
|
||
|
|
||
|
// give interactor event information
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetKeyEventInformation(
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton),
|
||
|
ascii_key, event->count(), keysym);
|
||
|
#else
|
||
|
iren->SetKeyEventInformation(
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier),
|
||
|
ascii_key, event->count(), keysym);
|
||
|
#endif
|
||
|
|
||
|
// invoke vtk event
|
||
|
iren->InvokeEvent(vtkCommand::KeyPressEvent, event);
|
||
|
|
||
|
// invoke char event only for ascii characters
|
||
|
if(ascii_key)
|
||
|
iren->InvokeEvent(vtkCommand::CharEvent, event);
|
||
|
}
|
||
|
|
||
|
/*! handle key release event
|
||
|
*/
|
||
|
void QVTKWidget::keyReleaseEvent(QKeyEvent* event)
|
||
|
{
|
||
|
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// get key and keysym info
|
||
|
#if QT_VERSION < 0x040000
|
||
|
int ascii_key = event->text().length() ? event->text().unicode()->latin1() : 0;
|
||
|
#else
|
||
|
int ascii_key = event->text().length() ? event->text().unicode()->toLatin1() : 0;
|
||
|
#endif
|
||
|
const char* keysym = ascii_to_key_sym(ascii_key);
|
||
|
if(!keysym)
|
||
|
{
|
||
|
// get virtual keys
|
||
|
keysym = qt_key_to_key_sym((Qt::Key)event->key());
|
||
|
}
|
||
|
|
||
|
if(!keysym)
|
||
|
{
|
||
|
keysym = "None";
|
||
|
}
|
||
|
|
||
|
// give event information to interactor
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetKeyEventInformation(
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton),
|
||
|
ascii_key, event->count(), keysym);
|
||
|
#else
|
||
|
iren->SetKeyEventInformation(
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier),
|
||
|
ascii_key, event->count(), keysym);
|
||
|
#endif
|
||
|
|
||
|
// invoke vtk event
|
||
|
iren->InvokeEvent(vtkCommand::KeyReleaseEvent, event);
|
||
|
}
|
||
|
|
||
|
#ifndef QT_NO_WHEELEVENT
|
||
|
void QVTKWidget::wheelEvent(QWheelEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// VTK supports wheel mouse events only in version 4.5 or greater
|
||
|
#if defined(QVTK_HAVE_VTK_4_5)
|
||
|
|
||
|
// give event information to interactor
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton ));
|
||
|
#else
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier ));
|
||
|
#endif
|
||
|
|
||
|
// invoke vtk event
|
||
|
// if delta is positive, it is a forward wheel event
|
||
|
if(event->delta() > 0)
|
||
|
iren->InvokeEvent(vtkCommand::MouseWheelForwardEvent, event);
|
||
|
else
|
||
|
iren->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, event);
|
||
|
|
||
|
#else
|
||
|
QWidget::wheelEvent(event);
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void QVTKWidget::focusInEvent(QFocusEvent*)
|
||
|
{
|
||
|
// These prevent updates when the window
|
||
|
// gains or loses focus. By default, Qt
|
||
|
// does an update because the color group's
|
||
|
// active status changes. We don't even use
|
||
|
// color groups so we do nothing here.
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::focusOutEvent(QFocusEvent*)
|
||
|
{
|
||
|
// These prevent updates when the window
|
||
|
// gains or loses focus. By default, Qt
|
||
|
// does an update because the color group's
|
||
|
// active status changes. We don't even use
|
||
|
// color groups so we do nothing here.
|
||
|
}
|
||
|
|
||
|
|
||
|
void QVTKWidget::contextMenuEvent(QContextMenuEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// give interactor the event information
|
||
|
#if QT_VERSION < 0x040000
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->state() & Qt::ControlButton),
|
||
|
(event->state() & Qt::ShiftButton ));
|
||
|
#else
|
||
|
iren->SetEventInformationFlipY(event->x(), event->y(),
|
||
|
(event->modifiers() & Qt::ControlModifier),
|
||
|
(event->modifiers() & Qt::ShiftModifier ));
|
||
|
#endif
|
||
|
|
||
|
// invoke event and pass qt event for additional data as well
|
||
|
iren->InvokeEvent(QVTKWidget::ContextMenuEvent, event);
|
||
|
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::dragEnterEvent(QDragEnterEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// invoke event and pass qt event for additional data as well
|
||
|
iren->InvokeEvent(QVTKWidget::DragEnterEvent, event);
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::dragMoveEvent(QDragMoveEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// give interactor the event information
|
||
|
iren->SetEventInformationFlipY(event->pos().x(), event->pos().y());
|
||
|
|
||
|
// invoke event and pass qt event for additional data as well
|
||
|
iren->InvokeEvent(QVTKWidget::DragMoveEvent, event);
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::dragLeaveEvent(QDragLeaveEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// invoke event and pass qt event for additional data as well
|
||
|
iren->InvokeEvent(QVTKWidget::DragLeaveEvent, event);
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::dropEvent(QDropEvent* event)
|
||
|
{
|
||
|
vtkRenderWindowInteractor* iren = NULL;
|
||
|
if(this->mRenWin)
|
||
|
iren = this->mRenWin->GetInteractor();
|
||
|
|
||
|
if(!iren || !iren->GetEnabled())
|
||
|
return;
|
||
|
|
||
|
// give interactor the event information
|
||
|
iren->SetEventInformationFlipY(event->pos().x(), event->pos().y());
|
||
|
|
||
|
// invoke event and pass qt event for additional data as well
|
||
|
iren->InvokeEvent(QVTKWidget::DropEvent, event);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*! handle reparenting of widgets
|
||
|
*/
|
||
|
#if QT_VERSION < 0x040000
|
||
|
void QVTKWidget::reparent(QWidget* parent, Qt::WFlags f, const QPoint& p, bool showit)
|
||
|
{
|
||
|
this->markCachedImageAsDirty();
|
||
|
|
||
|
#if defined(QVTK_HAVE_VTK_4_5)
|
||
|
if (this->mRenWin)
|
||
|
{
|
||
|
// Finalize the window to remove graphics resources associated with
|
||
|
// this window
|
||
|
if(this->mRenWin->GetMapped())
|
||
|
this->mRenWin->Finalize();
|
||
|
|
||
|
// have QWidget reparent as normal, but don't show
|
||
|
QWidget::reparent(parent, f, p, false);
|
||
|
|
||
|
x11_setup_window();
|
||
|
|
||
|
// connect to new window
|
||
|
#if defined(Q_WS_MAC)
|
||
|
this->mRenWin->SetWindowId(reinterpret_cast<void*>(this->handle()));
|
||
|
#else
|
||
|
this->mRenWin->SetWindowId( reinterpret_cast<void*>(this->winId()));
|
||
|
#endif
|
||
|
|
||
|
// start up the window to create graphics resources for this window
|
||
|
if(isVisible())
|
||
|
this->mRenWin->Start();
|
||
|
}
|
||
|
|
||
|
// show if requested
|
||
|
if(showit)
|
||
|
show();
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void QVTKWidget::showEvent(QShowEvent* event)
|
||
|
{
|
||
|
this->markCachedImageAsDirty();
|
||
|
|
||
|
QWidget::showEvent(event);
|
||
|
}
|
||
|
|
||
|
QPaintEngine* QVTKWidget::paintEngine() const
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*! allocation method for Qt/VTK interactor
|
||
|
*/
|
||
|
vtkStandardNewMacro(QVTKInteractor);
|
||
|
|
||
|
/*! constructor for Qt/VTK interactor
|
||
|
*/
|
||
|
QVTKInteractor::QVTKInteractor()
|
||
|
{
|
||
|
QObject::connect(&mTimer, SIGNAL(timeout()), this, SLOT(TimerEvent()) );
|
||
|
}
|
||
|
|
||
|
/*! start method for interactor
|
||
|
*/
|
||
|
void QVTKInteractor::Start()
|
||
|
{
|
||
|
vtkErrorMacro(<<"QVTKInteractor cannot control the event loop.");
|
||
|
}
|
||
|
|
||
|
/*! terminate the application
|
||
|
*/
|
||
|
void QVTKInteractor::TerminateApp()
|
||
|
{
|
||
|
// we are in a GUI so let's terminate the GUI the normal way
|
||
|
//qApp->exit();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*! handle timer event
|
||
|
*/
|
||
|
void QVTKInteractor::TimerEvent()
|
||
|
{
|
||
|
if ( !this->GetEnabled() )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
this->InvokeEvent(vtkCommand::TimerEvent, NULL);
|
||
|
}
|
||
|
|
||
|
/*! constructor
|
||
|
*/
|
||
|
QVTKInteractor::~QVTKInteractor()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*! create Qt timer with an interval of 10 msec.
|
||
|
*/
|
||
|
int QVTKInteractor::CreateTimer(int timer_type)
|
||
|
{
|
||
|
if(timer_type == VTKI_TIMER_FIRST)
|
||
|
{
|
||
|
mTimer.start(10);
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*! destroy timer
|
||
|
*/
|
||
|
int QVTKInteractor::DestroyTimer()
|
||
|
{
|
||
|
mTimer.stop();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***** keysym stuff below *****
|
||
|
|
||
|
static const char *AsciiToKeySymTable[] = {
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, "Tab", 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
"space", "exclam", "quotedbl", "numbersign",
|
||
|
"dollar", "percent", "ampersand", "quoteright",
|
||
|
"parenleft", "parenright", "asterisk", "plus",
|
||
|
"comma", "minus", "period", "slash",
|
||
|
"0", "1", "2", "3", "4", "5", "6", "7",
|
||
|
"8", "9", "colon", "semicolon", "less", "equal", "greater", "question",
|
||
|
"at", "A", "B", "C", "D", "E", "F", "G",
|
||
|
"H", "I", "J", "K", "L", "M", "N", "O",
|
||
|
"P", "Q", "R", "S", "T", "U", "V", "W",
|
||
|
"X", "Y", "Z", "bracketleft",
|
||
|
"backslash", "bracketright", "asciicircum", "underscore",
|
||
|
"quoteleft", "a", "b", "c", "d", "e", "f", "g",
|
||
|
"h", "i", "j", "k", "l", "m", "n", "o",
|
||
|
"p", "q", "r", "s", "t", "u", "v", "w",
|
||
|
"x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete",
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||
|
|
||
|
const char* ascii_to_key_sym(int i)
|
||
|
{
|
||
|
return AsciiToKeySymTable[i];
|
||
|
}
|
||
|
|
||
|
#define QVTK_HANDLE(x,y) \
|
||
|
case x : \
|
||
|
ret = y; \
|
||
|
break;
|
||
|
|
||
|
const char* qt_key_to_key_sym(Qt::Key i)
|
||
|
{
|
||
|
const char* ret = 0;
|
||
|
switch(i)
|
||
|
{
|
||
|
// Cancel
|
||
|
QVTK_HANDLE(Qt::Key_Backspace, "BackSpace")
|
||
|
QVTK_HANDLE(Qt::Key_Tab, "Tab")
|
||
|
#if QT_VERSION < 0x040000
|
||
|
QVTK_HANDLE(Qt::Key_BackTab, "Tab")
|
||
|
#else
|
||
|
QVTK_HANDLE(Qt::Key_Backtab, "Tab")
|
||
|
#endif
|
||
|
//QVTK_HANDLE(Qt::Key_Clear, "Clear")
|
||
|
QVTK_HANDLE(Qt::Key_Return, "Return")
|
||
|
QVTK_HANDLE(Qt::Key_Enter, "Return")
|
||
|
QVTK_HANDLE(Qt::Key_Shift, "Shift_L")
|
||
|
QVTK_HANDLE(Qt::Key_Control, "Control_L")
|
||
|
QVTK_HANDLE(Qt::Key_Alt, "Alt_L")
|
||
|
QVTK_HANDLE(Qt::Key_Pause, "Pause")
|
||
|
QVTK_HANDLE(Qt::Key_CapsLock, "Caps_Lock")
|
||
|
QVTK_HANDLE(Qt::Key_Escape, "Escape")
|
||
|
QVTK_HANDLE(Qt::Key_Space, "space")
|
||
|
//QVTK_HANDLE(Qt::Key_Prior, "Prior")
|
||
|
//QVTK_HANDLE(Qt::Key_Next, "Next")
|
||
|
QVTK_HANDLE(Qt::Key_End, "End")
|
||
|
QVTK_HANDLE(Qt::Key_Home, "Home")
|
||
|
QVTK_HANDLE(Qt::Key_Left, "Left")
|
||
|
QVTK_HANDLE(Qt::Key_Up, "Up")
|
||
|
QVTK_HANDLE(Qt::Key_Right, "Right")
|
||
|
QVTK_HANDLE(Qt::Key_Down, "Down")
|
||
|
|
||
|
// Select
|
||
|
// Execute
|
||
|
QVTK_HANDLE(Qt::Key_SysReq, "Snapshot")
|
||
|
QVTK_HANDLE(Qt::Key_Insert, "Insert")
|
||
|
QVTK_HANDLE(Qt::Key_Delete, "Delete")
|
||
|
QVTK_HANDLE(Qt::Key_Help, "Help")
|
||
|
QVTK_HANDLE(Qt::Key_0, "0")
|
||
|
QVTK_HANDLE(Qt::Key_1, "1")
|
||
|
QVTK_HANDLE(Qt::Key_2, "2")
|
||
|
QVTK_HANDLE(Qt::Key_3, "3")
|
||
|
QVTK_HANDLE(Qt::Key_4, "4")
|
||
|
QVTK_HANDLE(Qt::Key_5, "5")
|
||
|
QVTK_HANDLE(Qt::Key_6, "6")
|
||
|
QVTK_HANDLE(Qt::Key_7, "7")
|
||
|
QVTK_HANDLE(Qt::Key_8, "8")
|
||
|
QVTK_HANDLE(Qt::Key_9, "9")
|
||
|
QVTK_HANDLE(Qt::Key_A, "a")
|
||
|
QVTK_HANDLE(Qt::Key_B, "b")
|
||
|
QVTK_HANDLE(Qt::Key_C, "c")
|
||
|
QVTK_HANDLE(Qt::Key_D, "d")
|
||
|
QVTK_HANDLE(Qt::Key_E, "e")
|
||
|
QVTK_HANDLE(Qt::Key_F, "f")
|
||
|
QVTK_HANDLE(Qt::Key_G, "g")
|
||
|
QVTK_HANDLE(Qt::Key_H, "h")
|
||
|
QVTK_HANDLE(Qt::Key_I, "i")
|
||
|
QVTK_HANDLE(Qt::Key_J, "h")
|
||
|
QVTK_HANDLE(Qt::Key_K, "k")
|
||
|
QVTK_HANDLE(Qt::Key_L, "l")
|
||
|
QVTK_HANDLE(Qt::Key_M, "m")
|
||
|
QVTK_HANDLE(Qt::Key_N, "n")
|
||
|
QVTK_HANDLE(Qt::Key_O, "o")
|
||
|
QVTK_HANDLE(Qt::Key_P, "p")
|
||
|
QVTK_HANDLE(Qt::Key_Q, "q")
|
||
|
QVTK_HANDLE(Qt::Key_R, "r")
|
||
|
QVTK_HANDLE(Qt::Key_S, "s")
|
||
|
QVTK_HANDLE(Qt::Key_T, "t")
|
||
|
QVTK_HANDLE(Qt::Key_U, "u")
|
||
|
QVTK_HANDLE(Qt::Key_V, "v")
|
||
|
QVTK_HANDLE(Qt::Key_W, "w")
|
||
|
QVTK_HANDLE(Qt::Key_X, "x")
|
||
|
QVTK_HANDLE(Qt::Key_Y, "y")
|
||
|
QVTK_HANDLE(Qt::Key_Z, "z")
|
||
|
// KP_0 - KP_9
|
||
|
QVTK_HANDLE(Qt::Key_Asterisk, "asterisk")
|
||
|
QVTK_HANDLE(Qt::Key_Plus, "plus")
|
||
|
// bar
|
||
|
QVTK_HANDLE(Qt::Key_Minus, "minus")
|
||
|
QVTK_HANDLE(Qt::Key_Period, "period")
|
||
|
QVTK_HANDLE(Qt::Key_Slash, "slash")
|
||
|
QVTK_HANDLE(Qt::Key_F1, "F1")
|
||
|
QVTK_HANDLE(Qt::Key_F2, "F2")
|
||
|
QVTK_HANDLE(Qt::Key_F3, "F3")
|
||
|
QVTK_HANDLE(Qt::Key_F4, "F4")
|
||
|
QVTK_HANDLE(Qt::Key_F5, "F5")
|
||
|
QVTK_HANDLE(Qt::Key_F6, "F6")
|
||
|
QVTK_HANDLE(Qt::Key_F7, "F7")
|
||
|
QVTK_HANDLE(Qt::Key_F8, "F8")
|
||
|
QVTK_HANDLE(Qt::Key_F9, "F9")
|
||
|
QVTK_HANDLE(Qt::Key_F10, "F10")
|
||
|
QVTK_HANDLE(Qt::Key_F11, "F11")
|
||
|
QVTK_HANDLE(Qt::Key_F12, "F12")
|
||
|
QVTK_HANDLE(Qt::Key_F13, "F13")
|
||
|
QVTK_HANDLE(Qt::Key_F14, "F14")
|
||
|
QVTK_HANDLE(Qt::Key_F15, "F15")
|
||
|
QVTK_HANDLE(Qt::Key_F16, "F16")
|
||
|
QVTK_HANDLE(Qt::Key_F17, "F17")
|
||
|
QVTK_HANDLE(Qt::Key_F18, "F18")
|
||
|
QVTK_HANDLE(Qt::Key_F19, "F19")
|
||
|
QVTK_HANDLE(Qt::Key_F20, "F20")
|
||
|
QVTK_HANDLE(Qt::Key_F21, "F21")
|
||
|
QVTK_HANDLE(Qt::Key_F22, "F22")
|
||
|
QVTK_HANDLE(Qt::Key_F23, "F23")
|
||
|
QVTK_HANDLE(Qt::Key_F24, "F24")
|
||
|
QVTK_HANDLE(Qt::Key_NumLock, "Num_Lock")
|
||
|
QVTK_HANDLE(Qt::Key_ScrollLock, "Scroll_Lock")
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// X11 stuff near the bottom of the file
|
||
|
// to prevent namespace collisions with Qt headers
|
||
|
|
||
|
#if defined Q_WS_X11
|
||
|
#if defined(VTK_USE_OPENGL_LIBRARY) || (!defined(QVTK_HAVE_VTK_4_5) && defined(OPENGL_LIBRARY))
|
||
|
#include "vtkXOpenGLRenderWindow.h"
|
||
|
#endif
|
||
|
#ifdef VTK_USE_MANGLED_MESA
|
||
|
#include "vtkXMesaRenderWindow.h"
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
void QVTKWidget::x11_setup_window()
|
||
|
{
|
||
|
#if defined Q_WS_X11
|
||
|
|
||
|
// this whole function is to allow this window to have a
|
||
|
// different colormap and visual than the rest of the Qt application
|
||
|
// this is very important if Qt's default visual and colormap is
|
||
|
// not enough to get a decent graphics window
|
||
|
|
||
|
|
||
|
// save widget states
|
||
|
bool tracking = this->hasMouseTracking();
|
||
|
#if QT_VERSION < 0x040000
|
||
|
FocusPolicy focus_policy = focusPolicy();
|
||
|
#else
|
||
|
Qt::FocusPolicy focus_policy = focusPolicy();
|
||
|
#endif
|
||
|
bool visible = isVisible();
|
||
|
if(visible)
|
||
|
hide();
|
||
|
|
||
|
|
||
|
// get visual and colormap from VTK
|
||
|
XVisualInfo* vi = 0;
|
||
|
Colormap cmap = 0;
|
||
|
Display* display = reinterpret_cast<Display*>(mRenWin->GetGenericDisplayId());
|
||
|
|
||
|
// check ogl and mesa and get information we need to create a decent window
|
||
|
#if defined(VTK_USE_OPENGL_LIBRARY) || (!defined(QVTK_HAVE_VTK_4_5) && defined(OPENGL_LIBRARY))
|
||
|
vtkXOpenGLRenderWindow* ogl_win = vtkXOpenGLRenderWindow::SafeDownCast(mRenWin);
|
||
|
if(ogl_win)
|
||
|
{
|
||
|
vi = ogl_win->GetDesiredVisualInfo();
|
||
|
cmap = ogl_win->GetDesiredColormap();
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef VTK_USE_MANGLED_MESA
|
||
|
if(!vi)
|
||
|
{
|
||
|
vtkXMesaRenderWindow* mgl_win = vtkXMesaRenderWindow::SafeDownCast(mRenWin);
|
||
|
if(mgl_win)
|
||
|
{
|
||
|
vi = mgl_win->GetDesiredVisualInfo();
|
||
|
cmap = mgl_win->GetDesiredColormap();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// can't get visual, oh well.
|
||
|
// continue with Qt's default visual as it usually works
|
||
|
if(!vi)
|
||
|
{
|
||
|
if(visible)
|
||
|
show();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// create the X window based on information VTK gave us
|
||
|
XSetWindowAttributes attrib;
|
||
|
attrib.colormap = cmap;
|
||
|
attrib.border_pixel = BlackPixel(display, DefaultScreen(display));
|
||
|
|
||
|
Window parent = RootWindow(display, DefaultScreen(display));
|
||
|
if(parentWidget())
|
||
|
parent = parentWidget()->winId();
|
||
|
|
||
|
XWindowAttributes a;
|
||
|
XGetWindowAttributes(display, this->winId(), &a);
|
||
|
|
||
|
Window win = XCreateWindow(display, parent, a.x, a.y, a.width, a.height,
|
||
|
0, vi->depth, InputOutput, vi->visual,
|
||
|
CWBorderPixel|CWColormap, &attrib);
|
||
|
|
||
|
// backup colormap stuff
|
||
|
Window *cmw;
|
||
|
Window *cmwret;
|
||
|
int count;
|
||
|
if ( XGetWMColormapWindows(display, topLevelWidget()->winId(), &cmwret, &count) )
|
||
|
{
|
||
|
cmw = new Window[count+1];
|
||
|
memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count );
|
||
|
XFree( (char *)cmwret );
|
||
|
int i;
|
||
|
for ( i=0; i<count; i++ )
|
||
|
{
|
||
|
if ( cmw[i] == winId() )
|
||
|
{
|
||
|
cmw[i] = win;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( i >= count )
|
||
|
cmw[count++] = win;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
count = 1;
|
||
|
cmw = new Window[count];
|
||
|
cmw[0] = win;
|
||
|
}
|
||
|
|
||
|
|
||
|
// tell Qt to initialize anything it needs to for this window
|
||
|
create(win);
|
||
|
|
||
|
// restore colormaps
|
||
|
XSetWMColormapWindows( display, topLevelWidget()->winId(), cmw, count );
|
||
|
|
||
|
delete [] cmw;
|
||
|
|
||
|
XFlush(display);
|
||
|
|
||
|
// restore widget states
|
||
|
this->setMouseTracking(tracking);
|
||
|
#if QT_VERSION < 0x040000
|
||
|
setBackgroundMode( Qt::NoBackground );
|
||
|
#else
|
||
|
this->setAttribute(Qt::WA_NoBackground);
|
||
|
this->setAttribute(Qt::WA_PaintOnScreen);
|
||
|
#endif
|
||
|
setFocusPolicy(focus_policy);
|
||
|
if(visible)
|
||
|
show();
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if defined (Q_WS_MAC) && QT_VERSION >= 0x040000
|
||
|
OSStatus QVTKWidget::DirtyRegionProcessor(EventHandlerCallRef, EventRef event, void* wid)
|
||
|
{
|
||
|
QVTKWidget* widget = reinterpret_cast<QVTKWidget*>(wid);
|
||
|
UInt32 event_kind = GetEventKind(event);
|
||
|
UInt32 event_class = GetEventClass(event);
|
||
|
if(event_class == 'cute' && event_kind == 20)
|
||
|
static_cast<vtkCarbonRenderWindow*>(widget->GetRenderWindow())->UpdateGLRegion();
|
||
|
return eventNotHandledErr;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if defined (Q_WS_MAC) && QT_VERSION < 0x040000
|
||
|
|
||
|
// gotta do some special stuff on the MAC to make it work right
|
||
|
// this stuff will need changing when using Qt4 with HIViews
|
||
|
|
||
|
#include <AGL/agl.h>
|
||
|
|
||
|
void QVTKWidget::macFixRect()
|
||
|
{
|
||
|
AGLContext context = static_cast<vtkCarbonRenderWindow*>(this->GetRenderWindow())->GetContextId();
|
||
|
|
||
|
if(!this->isTopLevel())
|
||
|
{
|
||
|
GLint bufRect[4];
|
||
|
|
||
|
// always do AGL_BUFFER_RECT if we have a parent
|
||
|
if(!aglIsEnabled(context, AGL_BUFFER_RECT))
|
||
|
aglEnable(context, AGL_BUFFER_RECT);
|
||
|
|
||
|
// get the clip region
|
||
|
QRegion clip = this->clippedRegion();
|
||
|
QRect clip_rect = clip.boundingRect();
|
||
|
|
||
|
// get the position of this widget with respect to the top level widget
|
||
|
QPoint mp(posInWindow(this));
|
||
|
int win_height = this->topLevelWidget()->height();
|
||
|
win_height -= win_height - this->topLevelWidget()->clippedRegion(FALSE).boundingRect().height();
|
||
|
|
||
|
// give the position and size to agl
|
||
|
bufRect[0] = mp.x();
|
||
|
bufRect[1] = win_height -(mp.y() + this->height());
|
||
|
bufRect[2] = this->width();
|
||
|
bufRect[3] = this->height();
|
||
|
aglSetInteger(context, AGL_BUFFER_RECT, bufRect);
|
||
|
|
||
|
if(clip_rect.isEmpty())
|
||
|
{
|
||
|
// no clipping, disable it
|
||
|
if(!aglIsEnabled(context, AGL_CLIP_REGION))
|
||
|
aglDisable(context, AGL_CLIP_REGION);
|
||
|
|
||
|
bufRect[0] = 0;
|
||
|
bufRect[1] = 0;
|
||
|
bufRect[2] = 0;
|
||
|
bufRect[3] = 0;
|
||
|
aglSetInteger(context, AGL_BUFFER_RECT, bufRect);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// we are clipping, so lets enable it
|
||
|
if(!aglIsEnabled(context, AGL_CLIP_REGION))
|
||
|
aglEnable(context, AGL_CLIP_REGION);
|
||
|
|
||
|
// give agl the clip region
|
||
|
aglSetInteger(context, AGL_CLIP_REGION, (const GLint*)clip.handle(TRUE));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// update the context
|
||
|
aglUpdateContext(context);
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::setRegionDirty(bool b)
|
||
|
{
|
||
|
// the region is dirty and needs redrawn, but not yet
|
||
|
// signal that it needs to be done when it is possible
|
||
|
QWidget::setRegionDirty(b);
|
||
|
QTimer::singleShot(1, this, SLOT(internalMacFixRect()));
|
||
|
|
||
|
}
|
||
|
|
||
|
void QVTKWidget::macWidgetChangedWindow()
|
||
|
{
|
||
|
macFixRect();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// slot to update the draw region and draw the scene
|
||
|
void QVTKWidget::internalMacFixRect()
|
||
|
{
|
||
|
#if defined(Q_WS_MAC) && QT_VERSION < 0x040000
|
||
|
this->macFixRect();
|
||
|
this->update();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void dirty_cache(vtkObject *caller, unsigned long,
|
||
|
void *clientdata, void *)
|
||
|
{
|
||
|
QVTKWidget *widget = reinterpret_cast<QVTKWidget *>(clientdata);
|
||
|
widget->markCachedImageAsDirty();
|
||
|
|
||
|
vtkRenderWindow *renwin = vtkRenderWindow::SafeDownCast(caller);
|
||
|
if (renwin)
|
||
|
{
|
||
|
if ( widget->isAutomaticImageCacheEnabled()
|
||
|
&& ( renwin->GetDesiredUpdateRate()
|
||
|
< widget->maxRenderRateForImageCache() ) )
|
||
|
{
|
||
|
widget->saveImageToCache();
|
||
|
}
|
||
|
}
|
||
|
}
|