Salome HOME
0023083: [CEA 1400] Be able to active stereo in OCC view and to choose which kind...
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewWindow.cxx
index 4f38b4110457ec4c72197a4a339772a760272b08..6d03da7df0ddb8e68acd2c8b67194df9a5a9e718 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -35,8 +35,6 @@
 #include "OCCViewer_CubeAxesDlg.h"
 #include "OCCViewer_ClippingDlg.h"
 
-#include <Basics_OCCTVersion.hxx>
-
 #include <SUIT_Desktop.h>
 #include <SUIT_Session.h>
 #include <SUIT_ViewManager.h>
@@ -49,7 +47,7 @@
 #include <QtxMultiAction.h>
 #include <QtxRubberBand.h>
 
-#include <OpenGLUtils_FrameBuffer.h>
+#include <Basics_OCCTVersion.hxx>
 
 #include <QPainter>
 #include <QTime>
@@ -57,6 +55,7 @@
 #include <QKeyEvent>
 #include <QMouseEvent>
 #include <QApplication>
+#include <QActionGroup>
 #include <QMenu>
 
 #include <AIS_ListOfInteractive.hxx>
 #include <GProp_GProps.hxx>
 #include <TopoDS.hxx>
 
+#include <Graphic3d_SequenceOfHClipPlane.hxx>
+#include <Graphic3d_ClipPlane.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGLUtils_FrameBuffer.h>
+
 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
 #include <Graphic3d_MapOfStructure.hxx>
 #include <Graphic3d_Structure.hxx>
 #include <Graphic3d_ExportFormat.hxx>
+#if OCC_VERSION_LARGE > 0x06090000
+#include <Graphic3d_StereoMode.hxx>
+#include <Graphic3d_RenderingParams.hxx>
+#endif
+
 
 #include <Visual3d_View.hxx>
 #include <V3d_Plane.hxx>
@@ -83,9 +92,6 @@
 #include <gp_GTrsf.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
 
-#include <Graphic3d_SequenceOfHClipPlane.hxx>
-#include <Graphic3d_ClipPlane.hxx>
-
 #include <Image_PixMap.hxx>
 
 #include <Standard_Version.hxx>
@@ -104,6 +110,12 @@ static QEvent* l_mbPressEvent = 0;
 
 #include <GL/gl.h>
 
+// To avoid conflict between KeyPress from the X.h (define KeyPress 2)
+// and QEvent::KeyPress (qevent.h)
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
 const char* imageZoomCursor[] = {
 "32 32 3 1",
 ". c None",
@@ -236,7 +248,7 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop*     theDesktop,
   myScalingDlg = 0;
   mySetRotationPointDlg = 0;
   myRectBand = 0;
-  
+
   IsSketcherStyle = false;
   myIsKeyFree = false;
 
@@ -248,9 +260,9 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop*     theDesktop,
   myPreselectionEnabled = true;
   mySelectionEnabled = true;
 
+  myCursorIsHand = false;
 
   clearViewAspects();
-  
 }
 
 /*!
@@ -299,7 +311,7 @@ void OCCViewer_ViewWindow::initLayout()
   QtxAction* anAction = dynamic_cast<QtxAction*>( toolMgr()->action( GraduatedAxesId ) );
   myCubeAxesDlg = new OCCViewer_CubeAxesDlg( anAction, this, "OCCViewer_CubeAxesDlg" );
   myCubeAxesDlg->initialize();
-  
+
   connect( myViewPort, SIGNAL( vpTransformed( OCCViewer_ViewPort* ) ), this, SLOT( emitViewModified() ) );
 }
 
@@ -363,14 +375,26 @@ bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e )
     case QEvent::Wheel:
       {
         QWheelEvent* aEvent = (QWheelEvent*) e;
-  myViewPort->startZoomAtPoint( aEvent->x(), aEvent->y() );
-  double delta = (double)( aEvent->delta() ) / ( 15 * 8 );
-  int x  = aEvent->x();
-  int y  = aEvent->y();
-  int x1 = (int)( aEvent->x() + width()*delta/100 );
-  int y1 = (int)( aEvent->y() + height()*delta/100 );
-  myViewPort->zoom( x, y, x1, y1 );
-  myViewPort->getView()->ZFitAll();
+
+        if ( aEvent->modifiers().testFlag(Qt::ControlModifier) ) {
+          Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
+          if ( isPreselectionEnabled() && ic->HasOpenedContext() ) {
+            if ( aEvent->delta() > 0 ) {
+              ic->HilightNextDetected( myViewPort->getView() );
+            } else {
+              ic->HilightPreviousDetected( myViewPort->getView() );
+            }
+          }
+        } else {
+          myViewPort->startZoomAtPoint( aEvent->x(), aEvent->y() );
+          double delta = (double)( aEvent->delta() ) / ( 15 * 8 );
+          int x  = aEvent->x();
+          int y  = aEvent->y();
+          int x1 = (int)( aEvent->x() + width()*delta/100 );
+          int y1 = (int)( aEvent->y() + height()*delta/100 );
+          myViewPort->zoom( x, y, x1, y1 );
+          myViewPort->getView()->ZFitAll();
+        }
       }
       return true;
 
@@ -413,10 +437,10 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
   int anInteractionStyle = interactionStyle();
 
   // in "key free" interaction style zoom operation is activated by two buttons (simultaneously pressed),
-  // which are assigned for pan and rotate - these operations are activated immediately after pressing 
+  // which are assigned for pan and rotate - these operations are activated immediately after pressing
   // of the first button, so it is necessary to switch to zoom when the second button is pressed
   bool aSwitchToZoom = false;
-  if ( anInteractionStyle == SUIT_ViewModel::KEY_FREE && 
+  if ( anInteractionStyle == SUIT_ViewModel::KEY_FREE &&
        ( myOperation == PANVIEW || myOperation == ROTATE ) ) {
     aSwitchToZoom = getButtonState( theEvent, anInteractionStyle ) == ZOOMVIEW;
   }
@@ -558,7 +582,7 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
 void OCCViewer_ViewWindow::activateZoom()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                /* save old cursor */
+    saveCursor();                /* save old cursor */
 
   if ( myOperation != ZOOMVIEW ) {
     QPixmap zoomPixmap (imageZoomCursor);
@@ -577,7 +601,7 @@ void OCCViewer_ViewWindow::activateZoom()
 void OCCViewer_ViewWindow::activatePanning()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                // save old cursor
+    saveCursor();                // save old cursor
 
   if ( myOperation != PANVIEW ) {
     QCursor panCursor (Qt::SizeAllCursor);
@@ -594,7 +618,7 @@ void OCCViewer_ViewWindow::activatePanning()
 void OCCViewer_ViewWindow::activateRotation()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                // save old cursor
+    saveCursor();                // save old cursor
 
   if ( myOperation != ROTATE ) {
     QPixmap rotatePixmap (imageRotateCursor);
@@ -651,7 +675,17 @@ bool OCCViewer_ViewWindow::computeGravityCenter( double& theX, double& theY, dou
       continue;
     }
 
+#if OCC_VERSION_LARGE > 0x06070100
+    Bnd_Box aBox = aStructure->MinMaxValues();
+    aXmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X();
+    aYmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y();
+    aZmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z();
+    aXmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().X();
+    aYmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Y();
+    aZmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Z();
+#else
     aStructure->MinMaxValues( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+#endif
 
     // Infinite structures are skipped
     Standard_Real aLIM = ShortRealLast() - 1.0;
@@ -794,7 +828,7 @@ void OCCViewer_ViewWindow::activateStartPointSelection( TopAbs_ShapeEnum theShap
   {
     QCursor handCursor (Qt::PointingHandCursor);
     myCursorIsHand = true;
-    myCursor = cursor();
+    saveCursor();
     myViewPort->setCursor( handCursor );
   }
   myRotationPointSelection = true;
@@ -813,7 +847,7 @@ void OCCViewer_ViewWindow::activateGlobalPanning()
     QCursor glPanCursor (globalPanPixmap);
     myCurScale = aView3d->Scale();
     aView3d->FitAll(0.01, false);
-    myCursor = cursor();                // save old cursor
+    saveCursor();                // save old cursor
     myViewPort->fitAll(); // fits view before selecting a new scene center
     if( setTransformRequested( PANGLOBAL ) )
       myViewPort->setCursor( glPanCursor );
@@ -828,7 +862,7 @@ void OCCViewer_ViewWindow::activateGlobalPanning()
 void OCCViewer_ViewWindow::activateWindowFit()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                /* save old cursor */
+    saveCursor();                /* save old cursor */
 
   if ( myOperation != WINDOWFIT ) {
     QCursor handCursor (Qt::PointingHandCursor);
@@ -847,7 +881,7 @@ bool OCCViewer_ViewWindow::setTransformRequested( OperationType op )
 {
   bool ok = transformEnabled( op );
   myOperation = ok ? op : NOTHING;
-  myViewPort->setMouseTracking( myOperation == NOTHING );  
+  myViewPort->setMouseTracking( myOperation == NOTHING );
   return ok;
 }
 
@@ -923,7 +957,7 @@ void OCCViewer_ViewWindow::vpMouseMoveEvent( QMouseEvent* theEvent )
           if ( !myCursorIsHand )        {   // we are going to sketch a rectangle
             QCursor handCursor (Qt::PointingHandCursor);
             myCursorIsHand = true;
-            myCursor = cursor();
+            saveCursor();
             myViewPort->setCursor( handCursor );
           }
         }
@@ -1083,7 +1117,7 @@ void OCCViewer_ViewWindow::drawRect()
     //myRectBand->setPalette(palette);
   }
   //myRectBand->hide();
-  
+
   myRectBand->setUpdatesEnabled ( false );
   QRect aRect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
   myRectBand->initGeometry( aRect );
@@ -1123,7 +1157,7 @@ void OCCViewer_ViewWindow::createActions()
 {
   if( !toolMgr()->isEmpty() )
     return;
-  
+
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
 
   QtxAction* aAction;
@@ -1148,7 +1182,14 @@ void OCCViewer_ViewWindow::createActions()
   aAction->setStatusTip(tr("DSC_FITRECT"));
   connect(aAction, SIGNAL(triggered()), this, SLOT(activateWindowFit()));
   toolMgr()->registerAction( aAction, FitRectId );
-  
+
+  // FitSelection
+  aAction = new QtxAction(tr("MNU_FITSELECTION"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FITSELECTION" ) ),
+                           tr( "MNU_FITSELECTION" ), 0, this);
+  aAction->setStatusTip(tr("DSC_FITSELECTION"));
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onFitSelection()));
+  toolMgr()->registerAction( aAction, FitSelectionId );
+
   // Zoom
   aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ZOOM" ) ),
                            tr( "MNU_ZOOM_VIEW" ), 0, this);
@@ -1213,7 +1254,7 @@ void OCCViewer_ViewWindow::createActions()
   connect(aAction, SIGNAL(triggered()), this, SLOT(onBottomView()));
   this->addAction(aAction);
   toolMgr()->registerAction( aAction, BottomId );
-  
+
   aAction = new QtxAction(tr("MNU_LEFT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_LEFT" ) ),
                            tr( "MNU_LEFT_VIEW" ), 0, this, false, "Viewers:Left view");
   aAction->setStatusTip(tr("DSC_LEFT_VIEW"));
@@ -1244,6 +1285,41 @@ void OCCViewer_ViewWindow::createActions()
   this->addAction(aAction);
   toolMgr()->registerAction( aAction, ClockWiseId );
 
+  // Projection mode group
+
+  // - orthographic projection
+  aAction = new QtxAction(tr("MNU_ORTHOGRAPHIC_MODE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_ORTHOGRAPHIC" ) ),
+                          tr( "MNU_ORTHOGRAPHIC_MODE" ), 0, this);
+  aAction->setStatusTip(tr("DSC_ORTHOGRAPHIC_MODE"));
+  aAction->setCheckable(true);
+  //connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onProjectionType()));
+  toolMgr()->registerAction( aAction, OrthographicId );
+
+  // - perspective projection
+  aAction = new QtxAction(tr("MNU_PERSPECTIVE_MODE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_PERSPECTIVE" ) ),
+                          tr( "MNU_PERSPECTIVE_MODE" ), 0, this);
+  aAction->setStatusTip(tr("DSC_PERSPECTIVE_MODE"));
+  aAction->setCheckable(true);
+  //connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onProjectionType()));
+  toolMgr()->registerAction( aAction, PerspectiveId );
+#if OCC_VERSION_LARGE > 0x06090000
+  // - stereo projection
+  aAction = new QtxAction(tr("MNU_STEREO_MODE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_STEREO" ) ),
+                          tr( "MNU_STEREO_MODE" ), 0, this);
+  aAction->setStatusTip(tr("DSC_STEREO_MODE"));
+  aAction->setCheckable(true);
+  toolMgr()->registerAction( aAction, StereoId );
+  //connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onProjectionType()));
+#endif
+  // - add exclusive action group
+  QActionGroup* aProjectionGroup = new QActionGroup( this );
+  aProjectionGroup->addAction( toolMgr()->action( OrthographicId ) );
+  aProjectionGroup->addAction( toolMgr()->action( PerspectiveId ) );
+#if OCC_VERSION_LARGE > 0x06090000
+  aProjectionGroup->addAction( toolMgr()->action( StereoId ) );
+#endif
+  connect(aProjectionGroup, SIGNAL(triggered(QAction*)), this, SLOT(onProjectionType()));
+
   // Reset
   aAction = new QtxAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_RESET" ) ),
                            tr( "MNU_RESET_VIEW" ), 0, this, false, "Viewers:Reset view");
@@ -1312,7 +1388,7 @@ void OCCViewer_ViewWindow::createActions()
   connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onSwitchSelection(bool)));
   toolMgr()->registerAction( aAction, SwitchSelectionId );
 
-  // Graduated axes 
+  // Graduated axes
   aAction = new QtxAction(tr("MNU_GRADUATED_AXES"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_GRADUATED_AXES" ) ),
                            tr( "MNU_GRADUATED_AXES" ), 0, this);
   aAction->setStatusTip(tr("DSC_GRADUATED_AXES"));
@@ -1358,7 +1434,7 @@ void OCCViewer_ViewWindow::createActions()
     toolMgr()->registerAction( aAction, ReturnTo3dViewId );
   }
 
-  // Synchronize View 
+  // Synchronize View
   toolMgr()->registerAction( synchronizeAction(), SynchronizeId );
 }
 
@@ -1397,6 +1473,9 @@ void OCCViewer_ViewWindow::createToolBar()
   QtxMultiAction* aScaleAction = new QtxMultiAction( this );
   aScaleAction->insertAction( toolMgr()->action( FitAllId ) );
   aScaleAction->insertAction( toolMgr()->action( FitRectId ) );
+#if OCC_VERSION_LARGE > 0x06090000
+  aScaleAction->insertAction( toolMgr()->action( FitSelectionId ) );
+#endif
   aScaleAction->insertAction( toolMgr()->action( ZoomId ) );
   toolMgr()->append( aScaleAction, tid );
 
@@ -1421,6 +1500,10 @@ void OCCViewer_ViewWindow::createToolBar()
     toolMgr()->append( AntiClockWiseId, tid );
     toolMgr()->append( ClockWiseId, tid );
 
+    toolMgr()->append( OrthographicId, tid );
+    toolMgr()->append( PerspectiveId, tid );
+    toolMgr()->append( StereoId, tid );
+
     toolMgr()->append( ResetId, tid );
   }
 
@@ -1431,7 +1514,7 @@ void OCCViewer_ViewWindow::createToolBar()
 
   toolMgr()->append( toolMgr()->separator(), tid );
   toolMgr()->append( CloneId, tid );
-  
+
   toolMgr()->append( toolMgr()->separator(), tid );
   toolMgr()->append( ClippingId, tid );
   toolMgr()->append( AxialScaleId, tid );
@@ -1554,10 +1637,30 @@ void OCCViewer_ViewWindow::onResetView()
   myViewPort->getView()->Reset( false );
   myViewPort->fitAll( false, true, false );
   myViewPort->getView()->SetImmediateUpdate( upd );
+  onProjectionType(); // needed to apply projection type properly after reset
   myViewPort->getView()->Update();
   emit vpTransformationFinished( RESETVIEW );
 }
 
+/*!
+  \brief Perform "reset view" transformation.
+
+  Sets default orientation of the viewport camera.
+*/
+void OCCViewer_ViewWindow::onProjectionType()
+{
+  emit vpTransformationStarted( PROJECTION );
+  if (toolMgr()->action( OrthographicId )->isChecked())
+    setProjectionType( Orthographic);
+  if (toolMgr()->action( PerspectiveId )->isChecked())
+    setProjectionType( Perspective);
+#if OCC_VERSION_LARGE > 0x06090000
+  if (toolMgr()->action( StereoId )->isChecked())
+    setProjectionType( Stereo);
+#endif
+  emit vpTransformationFinished( PROJECTION );
+}
+
 /*!
   \brief Perform "fit all" transformation.
 */
@@ -1568,6 +1671,18 @@ void OCCViewer_ViewWindow::onFitAll()
   emit vpTransformationFinished( FITALLVIEW );
 }
 
+/*!
+  \brief Perform "fit selection" transformation.
+*/
+void OCCViewer_ViewWindow::onFitSelection()
+{
+  emit vpTransformationStarted( FITSELECTION );
+#if OCC_VERSION_LARGE > 0x06090000
+  myModel->getAISContext()->FitSelected( getViewPort()->getView() );
+#endif
+  emit vpTransformationFinished( FITSELECTION );
+}
+
 /*!
   \brief Called if 'change rotation point' operation is activated.
   \param on action state
@@ -1618,7 +1733,7 @@ void OCCViewer_ViewWindow::onAxialScale()
 {
   if ( !myScalingDlg )
     myScalingDlg = new OCCViewer_AxialScaleDlg( this );
-  
+
   if ( !myScalingDlg->isVisible() )
   {
     myScalingDlg->Update();
@@ -1721,7 +1836,7 @@ void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem, bool base
 
     myModel->setTrihedronShown( anItem.isVisible );
     myModel->setTrihedronSize( anItem.size );
-        
+
     // graduated trihedron
     bool anIsVisible = anItem.gtIsVisible;
     OCCViewer_AxisWidget::AxisData anAxisData[3];
@@ -1816,7 +1931,7 @@ void OCCViewer_ViewWindow::onSwitchSelection( bool on )
 {
   mySelectionEnabled = on;
   myModel->setSelectionOptions( myModel->isPreselectionEnabled(), isSelectionEnabled() );
-  
+
   // update action state if method is called outside
 
   // preselection
@@ -1903,22 +2018,23 @@ QImage OCCViewer_ViewWindow::dumpView()
   Handle(V3d_View) view = myViewPort->getView();
   if ( view.IsNull() )
     return QImage();
-  
+
   int aWidth = myViewPort->width();
   int aHeight = myViewPort->height();
 
   // rnv: An old approach to dump the OCCViewer content
   //      Now used OCCT built-in procedure.
-  /*     
+  /*
   QApplication::syncX();
   view->Redraw(); // In order to reactivate GL context
   //view->Update();
 
+#ifndef DISABLE_GLVIEWER
   OpenGLUtils_FrameBuffer aFrameBuffer;
   if( aFrameBuffer.init( aWidth, aHeight ) )
   {
     QImage anImage( aWidth, aHeight, QImage::Format_RGB32 );
-   
+
     glPushAttrib( GL_VIEWPORT_BIT );
     glViewport( 0, 0, aWidth, aHeight );
     aFrameBuffer.bind();
@@ -1946,8 +2062,9 @@ QImage OCCViewer_ViewWindow::dumpView()
 
   glReadPixels( p.x(), p.y(), aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE,
                 data);
+#endif
   */
-  
+
   Image_PixMap aPix;
   view->ToPixMap(aPix,aWidth, aHeight,Graphic3d_BT_RGBA);
 
@@ -1956,8 +2073,8 @@ QImage OCCViewer_ViewWindow::dumpView()
   return anImage;
 }
 
-bool OCCViewer_ViewWindow::dumpViewToFormat( const QImage& img, 
-                                             const QString& fileName, 
+bool OCCViewer_ViewWindow::dumpViewToFormat( const QImage& img,
+                                             const QString& fileName,
                                              const QString& format )
 {
   if ( format != "PS" && format != "EPS")
@@ -2007,7 +2124,7 @@ void OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x,  const doub
     gp_Pln pln (gp_Pnt(x, y, z), gp_Dir(dx, dy, dz));
     double a, b, c, d;
     pln.Coefficients(a, b, c, d);
-    
+
     Graphic3d_SequenceOfHClipPlane aPlanes = view->GetClipPlanes();
     if(aPlanes.Size() > 0 ) {
       Graphic3d_SequenceOfHClipPlane::Iterator anIter (aPlanes);
@@ -2414,7 +2531,7 @@ void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
     params.isVisible = data.count() > idx ? data[idx++].toInt()    : 1;
     params.size      = data.count() > idx ? data[idx++].toDouble() : 100.0;
   }
-  performRestoring( params );  
+  performRestoring( params );
   setBackground( bgData );
   myModel->setClipPlanes(aClipPlanes);
 }
@@ -2444,6 +2561,18 @@ void OCCViewer_ViewWindow::hideEvent( QHideEvent* theEvent )
 }
 
 
+/*!
+    Save old cursor. [ protected ]
+*/
+void OCCViewer_ViewWindow::saveCursor()
+{
+  QCursor* aCursor = NULL;
+  if ( myViewPort )
+    aCursor = myViewPort->getDefaultCursor();
+  myCursor = ( aCursor ? *aCursor : cursor() );
+}
+
+
 /*!
     Creates default sketcher. [ virtual protected ]
 */
@@ -2646,8 +2775,8 @@ void OCCViewer_ViewWindow::setMaximized(bool toMaximize, bool toSendSignal)
   QAction* anAction2 =  toolMgr()->action( ReturnTo3dViewId );
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
   if ( toMaximize ) {
-    anAction->setText( tr( "MNU_MINIMIZE_VIEW" ) );  
-    anAction->setToolTip( tr( "MNU_MINIMIZE_VIEW" ) );  
+    anAction->setText( tr( "MNU_MINIMIZE_VIEW" ) );
+    anAction->setToolTip( tr( "MNU_MINIMIZE_VIEW" ) );
     anAction->setIcon( aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_MINIMIZE" ) ) );
     anAction->setStatusTip( tr( "DSC_MINIMIZE_VIEW" ) );
     if ( anAction2 && my2dMode != No2dMode ) toolMgr()->show( ReturnTo3dViewId );
@@ -2656,8 +2785,8 @@ void OCCViewer_ViewWindow::setMaximized(bool toMaximize, bool toSendSignal)
     }
   }
   else {
-    anAction->setText( tr( "MNU_MAXIMIZE_VIEW" ) );  
-    anAction->setToolTip( tr( "MNU_MAXIMIZE_VIEW" ) );  
+    anAction->setText( tr( "MNU_MAXIMIZE_VIEW" ) );
+    anAction->setToolTip( tr( "MNU_MAXIMIZE_VIEW" ) );
     anAction->setIcon( aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_MAXIMIZE" ) ) );
     anAction->setStatusTip( tr( "DSC_MAXIMIZE_VIEW" ) );
     if ( anAction2 && my2dMode != No2dMode ) toolMgr()->hide( ReturnTo3dViewId );
@@ -2673,13 +2802,13 @@ bool OCCViewer_ViewWindow::isMaximized() const
 }
 
 void OCCViewer_ViewWindow::setSketcherStyle( bool enable )
-{ 
-  IsSketcherStyle = enable; 
+{
+  IsSketcherStyle = enable;
 }
 
-bool OCCViewer_ViewWindow::isSketcherStyle() const 
-{ 
-  return IsSketcherStyle; 
+bool OCCViewer_ViewWindow::isSketcherStyle() const
+{
+  return IsSketcherStyle;
 }
 
 
@@ -2688,12 +2817,330 @@ void OCCViewer_ViewWindow::set2dMode(Mode2dType theType)
   my2dMode = theType;
 }
 
-// obsolete   
+void OCCViewer_ViewWindow::setProjectionType( int mode )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    if (mode == Perspective) {
+      myModel->setProjectionType(Perspective);
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Perspective );
+    }
+    if (mode == Orthographic) {
+      myModel->setProjectionType(Orthographic);
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Orthographic );
+    }
+  #if OCC_VERSION_LARGE > 0x06090000
+    if (mode == Stereo) {
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Stereo );
+      SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+      setStereoType( aResMgr->integerValue( "OCCViewer", "stereo_type", 0 ) );
+      setAnaglyphFilter( aResMgr->integerValue( "OCCViewer", "anaglyph_filter", 0 ) );
+      setReverseStereo( aResMgr->booleanValue( "OCCViewer", "reverse_stereo", false ) );
+      setVSync( aResMgr->booleanValue( "OCCViewer", "enable_vsync", true ) );
+      setQuadBufferSupport( aResMgr->booleanValue( "OCCViewer", "enable_quad_buffer_support", false ) );
+    }
+  #endif
+    aView3d->Redraw();
+    onViewFitAll();
+  }
+  // update action state if method is called outside
+  QtxAction* anOrthographicAction = dynamic_cast<QtxAction*>( toolMgr()->action( OrthographicId ) );
+  QtxAction* aPerspectiveAction = dynamic_cast<QtxAction*>( toolMgr()->action( PerspectiveId ) );
+#if OCC_VERSION_LARGE > 0x06090000
+  QtxAction* aStereoAction = dynamic_cast<QtxAction*>( toolMgr()->action( StereoId ) );
+#endif
+  if ( mode == Orthographic && !anOrthographicAction->isChecked() ) {
+         anOrthographicAction->setChecked( true );
+    #if OCC_VERSION_LARGE > 0x06090000
+         aStereoAction->setChecked( false );
+    #endif
+  }
+  if ( mode == Perspective && !aPerspectiveAction->isChecked() ) {
+         aPerspectiveAction->setChecked( true );
+    #if OCC_VERSION_LARGE > 0x06090000
+         aStereoAction->setChecked( false );
+    #endif
+  }
+#if OCC_VERSION_LARGE > 0x06090000
+  if ( mode == Stereo ) {
+    aStereoAction->setChecked( true );
+    if ( anOrthographicAction->isEnabled() ) {
+      anOrthographicAction->setEnabled( false );
+      anOrthographicAction->setChecked( false );
+      aStereoAction->setChecked( false );
+    }
+    else {
+      anOrthographicAction->setEnabled( true );
+      aStereoAction->setChecked( false );
+      anOrthographicAction->setChecked(myModel->projectionType() == Orthographic);
+    }
+    if ( aPerspectiveAction->isEnabled() ) {
+      aPerspectiveAction->setEnabled( false );
+      aPerspectiveAction->setChecked( true );
+    #if OCC_VERSION_LARGE > 0x06090000
+      if ( isQuadBufferSupport() && !isOpenGlStereoSupport() && stereoType() == QuadBuffer )
+        SUIT_MessageBox::warning( 0, tr( "WRN_WARNING" ),  tr( "WRN_SUPPORT_QUAD_BUFFER" ) );
+    #endif
+    }
+    else {
+      aPerspectiveAction->setEnabled( true );
+      aStereoAction->setChecked( false );
+      aPerspectiveAction->setChecked(myModel->projectionType() == Perspective);
+      onProjectionType();
+    }
+  }
+  else {
+    if ( !anOrthographicAction->isEnabled() )
+      anOrthographicAction->setEnabled( true );
+    if ( !aPerspectiveAction->isEnabled() )
+      aPerspectiveAction->setEnabled( true );
+  }
+#endif
+}
+
+int OCCViewer_ViewWindow::projectionType() const
+{
+  int mode = Orthographic;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Perspective)
+      mode = Perspective;
+    if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Orthographic)
+      mode = Orthographic;
+  #if OCC_VERSION_LARGE > 0x06090000
+    if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
+      mode = Stereo;
+  #endif
+  }
+  return mode;
+}
+
+void OCCViewer_ViewWindow::setStereoType( int type )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    aParams->StereoMode = (Graphic3d_StereoMode)type;
+  #endif
+  }
+}
+
+int OCCViewer_ViewWindow::stereoType() const
+{
+  int type = QuadBuffer;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    type = (OCCViewer_ViewWindow::StereoType)aParams->StereoMode;
+  #endif
+  }
+  return type;
+}
+
+void OCCViewer_ViewWindow::setAnaglyphFilter( int type )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    if (type == RedCyan)
+      aParams->AnaglyphFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
+    if (type == YellowBlue)
+      aParams->AnaglyphFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
+    if (type == GreenMagenta)
+      aParams->AnaglyphFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
+  #endif
+  }
+}
+
+int OCCViewer_ViewWindow::anaglyphFilter() const
+{
+  int type = RedCyan;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    if (aParams->AnaglyphFilter == Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized)
+      type = RedCyan;
+    if (aParams->AnaglyphFilter == Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized)
+      type = YellowBlue;
+    if (aParams->AnaglyphFilter == Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple)
+      type = GreenMagenta;
+  #endif
+  }
+  return type;
+}
+
+void OCCViewer_ViewWindow::setStereographicFocus( int type, double value )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    aCamera->SetZFocus( (Graphic3d_Camera::FocusType) type, value );
+  #endif
+  }
+}
+
+int OCCViewer_ViewWindow::stereographicFocusType() const
+{
+  int type = Relative;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    type = (OCCViewer_ViewWindow::FocusIODType)aCamera->ZFocusType();
+  #endif
+  }
+  return type;
+}
+
+double OCCViewer_ViewWindow::stereographicFocusValue() const
+{
+  double value = 1.0;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    value = aCamera->ZFocus();
+  #endif
+  }
+  return value;
+}
+
+void OCCViewer_ViewWindow::setInterocularDistance( int type, double value )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    aCamera->SetIOD( (Graphic3d_Camera::IODType) type, value );
+  #endif
+  }
+}
+
+int OCCViewer_ViewWindow::interocularDistanceType() const
+{
+  int type = Relative;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    type = (OCCViewer_ViewWindow::FocusIODType)aCamera->GetIODType();
+  #endif
+  }
+  return type;
+}
+
+double OCCViewer_ViewWindow::interocularDistanceValue() const
+{
+  double value = 0.05;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    value = aCamera->IOD();
+  #endif
+  }
+  return value;
+}
+
+void OCCViewer_ViewWindow::setReverseStereo( bool reverse )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    aParams->ToReverseStereo = reverse;
+  #endif
+  }
+}
+
+bool OCCViewer_ViewWindow::isReverseStereo() const
+{
+  int reverse = false;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    reverse = aParams->ToReverseStereo;
+  #endif
+  }
+  return reverse;
+}
+
+void OCCViewer_ViewWindow::setVSync( bool enable )
+{
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    aCaps->swapInterval = enable;
+  #endif
+  }
+}
+
+bool OCCViewer_ViewWindow::isVSync() const
+{
+  int enable = true;
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    enable = aCaps->swapInterval;
+  #endif
+  }
+  return enable;
+}
+
+void OCCViewer_ViewWindow::setQuadBufferSupport( bool enable )
+{
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    aCaps->contextStereo = enable;
+  #endif
+  }
+}
+
+bool OCCViewer_ViewWindow::isQuadBufferSupport() const
+{
+  int enable = true;
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+  #if OCC_VERSION_LARGE > 0x06090000
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    enable = aCaps->contextStereo;
+  #endif
+  }
+  return enable;
+}
+
+
+bool OCCViewer_ViewWindow::isOpenGlStereoSupport() const
+{
+  GLboolean support[1];
+  glGetBooleanv (GL_STEREO, support);
+  if ( support[0] )
+    return true;
+  return false;
+}
+
+// obsolete
 QColor OCCViewer_ViewWindow::backgroundColor() const
 {
   return myViewPort ? myViewPort->backgroundColor() : Qt::black;
 }
-   
+
 // obsolete
 void OCCViewer_ViewWindow::setBackgroundColor( const QColor& theColor )
 {
@@ -2704,7 +3151,7 @@ Qtx::BackgroundData OCCViewer_ViewWindow::background() const
 {
   return myViewPort ? myViewPort->background() : Qtx::BackgroundData();
 }
-   
+
 void OCCViewer_ViewWindow::setBackground( const Qtx::BackgroundData& theBackground )
 {
   if ( myViewPort ) myViewPort->setBackground( theBackground );
@@ -3006,7 +3453,7 @@ void OCCViewer_ViewWindow::onClipping (bool theIsOn)
 {
   if(!myModel) return;
   OCCViewer_ClippingDlg* aClippingDlg = myModel->getClippingDlg();
-  
+
   if (theIsOn) {
     if (!aClippingDlg) {
       aClippingDlg = new OCCViewer_ClippingDlg (this, myModel);