]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Merged with OCC_visual_parameters_2006 branch. It consists development of persistent...
authorasv <asv@opencascade.com>
Tue, 7 Mar 2006 15:50:46 +0000 (15:50 +0000)
committerasv <asv@opencascade.com>
Tue, 7 Mar 2006 15:50:46 +0000 (15:50 +0000)
40 files changed:
idl/SALOME_Session.idl
src/GLViewer/GLViewer_ViewFrame.cxx
src/GLViewer/GLViewer_ViewFrame.h
src/LightApp/resources/LightApp_msg_en.po
src/OCCViewer/OCCViewer_ViewWindow.cxx
src/OCCViewer/OCCViewer_ViewWindow.h
src/Plot2d/Plot2d_ViewFrame.cxx
src/Plot2d/Plot2d_ViewFrame.h
src/Plot2d/Plot2d_ViewWindow.cxx
src/Plot2d/Plot2d_ViewWindow.h
src/Qtx/Makefile.in
src/Qtx/QtxWorkstack.cxx
src/Qtx/QtxWorkstack.h
src/SUIT/SUIT_DataObject.cxx
src/SUIT/SUIT_Study.cxx
src/SUIT/SUIT_Study.h
src/SUIT/SUIT_TreeSync.h
src/SUIT/SUIT_ViewWindow.cxx
src/SUIT/SUIT_ViewWindow.h
src/SVTK/SVTK_ViewWindow.cxx
src/SVTK/SVTK_ViewWindow.h
src/SalomeApp/Makefile.in
src/SalomeApp/SalomeApp_Application.cxx
src/SalomeApp/SalomeApp_Application.h
src/SalomeApp/SalomeApp_DataModel.cxx
src/SalomeApp/SalomeApp_DataModel.h
src/SalomeApp/SalomeApp_DataObject.cxx
src/SalomeApp/SalomeApp_DataObject.h
src/SalomeApp/SalomeApp_Module.cxx
src/SalomeApp/SalomeApp_Module.h
src/SalomeApp/SalomeApp_Study.cxx
src/SalomeApp/SalomeApp_Study.h
src/SalomeApp/SalomeApp_VisualState.cxx [new file with mode: 0644]
src/SalomeApp/SalomeApp_VisualState.h [new file with mode: 0644]
src/SalomeApp/resources/SalomeApp.xml
src/SalomeApp/resources/SalomeApp_msg_en.po
src/Session/Session_Session_i.cxx
src/Session/Session_Session_i.hxx
src/VTKViewer/VTKViewer_ViewWindow.cxx
src/VTKViewer/VTKViewer_ViewWindow.h

index 3086194eec2e4b80a62f450c6bf9e8900c53ccad..f067b753ab40e07388d6d860868de7d13f26552c 100644 (file)
@@ -105,6 +105,9 @@ module SALOME
     Get Active study ID
 */
     long GetActiveStudyId();
+/*!
+    Restores a state of the study at theSavePoint
+*/
+    boolean restoreVisualState(in long theSavePoint);
   } ;
-
 } ;
index 6600bb35f6690cd3127030a756654761c9447426..a466d7b2f91813081ec6390fdf196b0f1992b8f4 100644 (file)
@@ -547,3 +547,37 @@ void GLViewer_ViewFrame::wheelEvent( QWheelEvent* e )
     break;
   }
 }
+
+/*! The method returns the visual parameters of this view as a formated string
+ */
+QString GLViewer_ViewFrame::getVisualParameters()
+{
+  QString retStr;
+  if ( myVP && myVP->inherits( "GLViewer_ViewPort2d" ) ) {
+    GLViewer_ViewPort2d* vp2d = (GLViewer_ViewPort2d*)myVP;
+    GLfloat xSc, ySc, xPan, yPan;
+    vp2d->getScale( xSc, ySc );
+    vp2d->getPan( xPan, yPan );
+    retStr.sprintf( "%.12e*%.12e*%.12e*%.12e", xSc, ySc, xPan, yPan );
+  }
+  return retStr;
+}
+
+/* The method restors visual parameters of this view from a formated string
+ */
+void GLViewer_ViewFrame::setVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = QStringList::split( '*', parameters, true );
+  if ( myVP && myVP->inherits( "GLViewer_ViewPort2d" ) && paramsLst.size() == 4) {
+    GLViewer_ViewPort2d* vp2d = (GLViewer_ViewPort2d*)myVP;
+
+    GLfloat xSc, ySc, xPan, yPan;
+    xSc = paramsLst[0].toDouble();
+    ySc = paramsLst[1].toDouble();
+    xPan = paramsLst[2].toDouble();
+    yPan = paramsLst[3].toDouble();
+
+    vp2d->getGLWidget()->setScale( xSc, ySc, 1. );
+    vp2d->getGLWidget()->setPan( xPan, yPan, 0. );
+  }
+}
index d90dfd3f5ddcb6b4b25512bb245df9fb4cc9795c..8b9267a426f91537b5355bd8d0b9b2b655ef63e6 100644 (file)
@@ -72,6 +72,9 @@ public:
   QSize                   sizeHint() const;
   
   virtual void            onUpdate( int );
+
+  virtual QString         getVisualParameters();
+  virtual void            setVisualParameters( const QString& parameters );  
   
 signals:
   void                    vfDrawExternal( QPainter* );
index c5b364d565aa6908759ba22c408057dd83e6d2ba..09f9013322051153fd4e8f49cb5fc1b0b84845f3 100644 (file)
@@ -322,3 +322,9 @@ msgstr "&Cancel"
 
 msgid "LightApp_ModuleDlg::ActivateComponent_DESCRIPTION"
 msgstr "Create, open or load study."
+
+msgid "LightApp_NameDlg::TLT_RENAME"
+msgstr "Rename"
+
+msgid "LightApp_NameDlg::NAME_LBL"
+msgstr "Name: "
index 4900fd9de51ef680d34f8bdfaf908b7383989030..dbd2618b68992499665918c424e6def5fc522e40 100755 (executable)
@@ -851,37 +851,7 @@ void OCCViewer_ViewWindow::onClipping( bool on )
 //****************************************************************
 void OCCViewer_ViewWindow::onMemorizeView()
 {
-  double centerX, centerY, projX, projY, projZ, twist;
-  double atX, atY, atZ, eyeX, eyeY, eyeZ;
-
-  Handle(V3d_View) aView3d = myViewPort->getView();
-
-  aView3d->Center( centerX, centerY );
-  aView3d->Proj( projX, projY, projZ );
-  aView3d->At( atX, atY, atZ );
-  aView3d->Eye( eyeX, eyeY, eyeZ );
-  twist = aView3d->Twist();
-
-  viewAspect params;
-  QString aName = QTime::currentTime().toString() + QString::fromLatin1( " h:m:s" );
-
-  params.scale    = aView3d->Scale();
-  params.centerX  = centerX;
-  params.centerY  = centerY;
-  params.projX    = projX;
-  params.projY    = projY;
-  params.projZ    = projZ;
-  params.twist    = twist;
-  params.atX      = atX;
-  params.atY      = atY;
-  params.atZ      = atZ;
-  params.eyeX     = eyeX;
-  params.eyeY     = eyeY;
-  params.eyeZ     = eyeZ;
-  params.name    = aName;
-
-  myModel->appendViewAspect( params );
-
+  myModel->appendViewAspect( getViewParams() );
 }
 
 //****************************************************************
@@ -904,11 +874,11 @@ void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem )
        Standard_Boolean prev = aView3d->SetImmediateUpdate( Standard_False );
        aView3d->SetScale( anItem.scale );
        aView3d->SetCenter( anItem.centerX, anItem.centerY );
-       aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ );
        aView3d->SetTwist( anItem.twist );
        aView3d->SetAt( anItem.atX, anItem.atY, anItem.atZ );
        aView3d->SetImmediateUpdate( prev );
        aView3d->SetEye( anItem.eyeX, anItem.eyeY, anItem.eyeZ );
+       aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ );
                
        myRestoreFlag = 0;
 }
@@ -980,3 +950,77 @@ void  OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x,  const dou
   v->Update();
   v->Redraw();
 }
+
+/*! The method returns the visual parameters of this view as a viewAspect object
+ */
+viewAspect OCCViewer_ViewWindow::getViewParams() const
+{
+  double centerX, centerY, projX, projY, projZ, twist;
+  double atX, atY, atZ, eyeX, eyeY, eyeZ;
+
+  Handle(V3d_View) aView3d = myViewPort->getView();
+
+  aView3d->Center( centerX, centerY );
+  aView3d->Proj( projX, projY, projZ );
+  aView3d->At( atX, atY, atZ );
+  aView3d->Eye( eyeX, eyeY, eyeZ );
+  twist = aView3d->Twist();
+
+  QString aName = QTime::currentTime().toString() + QString::fromLatin1( " h:m:s" );
+
+  viewAspect params;
+  params.scale    = aView3d->Scale();
+  params.centerX  = centerX;
+  params.centerY  = centerY;
+  params.projX    = projX;
+  params.projY    = projY;
+  params.projZ    = projZ;
+  params.twist    = twist;
+  params.atX      = atX;
+  params.atY      = atY;
+  params.atZ      = atZ;
+  params.eyeX     = eyeX;
+  params.eyeY     = eyeY;
+  params.eyeZ     = eyeZ;
+  params.name    = aName;
+
+  return params;
+}
+
+
+/*! The method returns the visual parameters of this view as a formated string
+ */
+QString OCCViewer_ViewWindow::getVisualParameters()
+{
+  viewAspect params = getViewParams();
+  QString retStr;
+  retStr.sprintf( "%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e", params.scale,
+                 params.centerX, params.centerY, params.projX, params.projY, params.projZ, params.twist,
+                 params.atX, params.atY, params.atZ, params.eyeX, params.eyeY, params.eyeZ );
+  return retStr;
+}
+
+/* The method restors visual parameters of this view from a formated string
+ */
+void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = QStringList::split( '*', parameters, true );
+  if ( paramsLst.size() == 13 ) {
+    viewAspect params;
+    params.scale    = paramsLst[0].toDouble();
+    params.centerX  = paramsLst[1].toDouble();
+    params.centerY  = paramsLst[2].toDouble();
+    params.projX    = paramsLst[3].toDouble();
+    params.projY    = paramsLst[4].toDouble();
+    params.projZ    = paramsLst[5].toDouble();
+    params.twist    = paramsLst[6].toDouble();
+    params.atX      = paramsLst[7].toDouble();
+    params.atY      = paramsLst[8].toDouble();
+    params.atZ      = paramsLst[9].toDouble();
+    params.eyeX     = paramsLst[10].toDouble();
+    params.eyeY     = paramsLst[11].toDouble();
+    params.eyeZ     = paramsLst[12].toDouble();
+
+    performRestoring( params );
+  }
+}
index b4f2bc8dbee214a351c32a6417925f72edadf392..b6bda965a519a1d39348da8eadcb122a12a5f6fb 100755 (executable)
@@ -62,6 +62,9 @@ public:
 
   void setCuttingPlane( bool on, const double x = 0 , const double y = 0 , const double z = 0,
                                  const double dx = 0, const double dy = 0, const double dz = 1);
+
+  virtual QString   getVisualParameters();
+  virtual void      setVisualParameters( const QString& parameters );
  
 public slots:
   void onFrontView();
@@ -119,6 +122,8 @@ protected:
  
   virtual OperationType getButtonState(QMouseEvent* theEvent);
 
+  viewAspect getViewParams() const;
+
   OperationType         myOperation;
   OCCViewer_Viewer*     myModel;
   OCCViewer_ViewPort3d* myViewPort;
index 30a25e808f68853833e321690b2a62d4fcd12739..35f4b5888cd7f093b7c22010c49e02da74c52153 100755 (executable)
@@ -1918,3 +1918,43 @@ bool Plot2d_ViewFrame::print( const QString& file, const QString& format ) const
   return res;
 #endif
 }
+
+QString Plot2d_ViewFrame::getVisualParameters()
+{
+  double xmin, xmax, ymin, ymax, y2min, y2max;
+  getFitRanges( xmin, xmax, ymin, ymax, y2min, y2max );
+  QString retStr;
+  retStr.sprintf( "%d*%d*%d*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e", myXMode,
+                 myYMode, mySecondY, xmin, xmax, ymin, ymax, y2min, y2max );
+  return retStr; 
+}
+
+void Plot2d_ViewFrame::setVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = QStringList::split( '*', parameters, true );
+  if ( paramsLst.size() == 9 ) {
+    double xmin, xmax, ymin, ymax, y2min, y2max;
+    myXMode = paramsLst[0].toInt();
+    myYMode = paramsLst[1].toInt();
+    mySecondY = (bool)paramsLst[2].toInt();
+    xmin =  paramsLst[3].toDouble();
+    xmax =  paramsLst[4].toDouble();
+    ymin =  paramsLst[5].toDouble();
+    ymax =  paramsLst[6].toDouble();
+    y2min = paramsLst[7].toDouble();
+    y2max = paramsLst[8].toDouble();
+
+    if (mySecondY)
+      setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
+    setHorScaleMode( myXMode, /*update=*/false );
+    setVerScaleMode( myYMode, /*update=*/false );
+    
+    if (mySecondY) {
+      QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
+      myYDistance2 = yMap2.d2() - yMap2.d1();
+    }
+
+    fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
+    fitData( 0, xmin, xmax, ymin, ymax, y2min, y2max );
+  }  
+}
index 51faa089840b9f1244884e880a5cda584c5980f7..5d1faccb51a8c968787fb352c7fbeab6d09c676e 100755 (executable)
@@ -118,6 +118,9 @@ public:
 
   virtual bool print( const QString& file, const QString& format ) const;
 
+  QString getVisualParameters();
+  void    setVisualParameters( const QString& parameters );
+
 protected:
   int     testOperation( const QMouseEvent& );
   void    readPreferences();
index 5c558ea0fb21e689596ce80f454a791bc2dec426..017e8fada8a5cbd7139bd0b562a58c3fa2fb4842 100755 (executable)
@@ -465,3 +465,17 @@ QString Plot2d_ViewWindow::filter() const
 {
   return SUIT_ViewWindow::filter() + ";;" + tr( "POSTSCRIPT_FILES" );
 }
+
+/*! The method returns the visual parameters of this view as a formated string
+ */
+QString Plot2d_ViewWindow::getVisualParameters()
+{
+  return myViewFrame->getVisualParameters();
+}
+
+/* The method restors visual parameters of this view from a formated string
+ */
+void Plot2d_ViewWindow::setVisualParameters( const QString& parameters )
+{
+  myViewFrame->setVisualParameters( parameters );
+}
index 571d692bf599445df6813cd2ad43dbfbef7be8a3..ec0e5bf64d363c4639d43461651b0e8d8d45174b 100755 (executable)
@@ -46,6 +46,9 @@ public:
   QToolBar*         getToolBar() { return myToolBar; };
   void              contextMenuPopup( QPopupMenu* thePopup );
 
+  virtual QString   getVisualParameters();
+  virtual void      setVisualParameters( const QString& parameters );
+
 protected:
   virtual QImage    dumpView();
   virtual QString   filter() const;
index aa682b59d199c117ebd7c93802e53e5219770b62..02f58984b5ba1dfb5c938a33d34c0c8fd9033bf1 100755 (executable)
@@ -1,4 +1,5 @@
-#  File   : Makefile.in\r#  Author : Vladimir Klyachin (OCN)
+#  File   : Makefile.in
+#  Author : Vladimir Klyachin (OCN)
 #  Module : suit
 #  $Header$
 
index c267236f297b9494f5baefc58cb92c88187f3e44..5e01f08e865c4bb8194885c733e66833a05dfc25 100644 (file)
 #include <qapplication.h>
 #include <qinputdialog.h>
 #include <qevent.h>
+#include <qregexp.h>
 
 #define DARK_COLOR_LIGHT      250
+
 /*!
     Class: QtxWorkstack [Public]
     Descr:
@@ -1131,6 +1133,266 @@ void QtxWorkstack::updateState( QSplitter* split )
     split->hide();
 }
 
+void QtxWorkstack::splitterInfo( QSplitter* split, QString& info ) const
+{
+  if ( !split )
+    return;
+
+  const QObjectList* objs = split->children();
+  if ( objs )
+  {
+    // make up a sizes string: integer values are separated by ':' char
+    QValueList<int> sizes = split->sizes();
+    QString sizesStr;
+    for ( QValueList<int>::Iterator sIt = sizes.begin(); sIt != sizes.end(); ++sIt ) {
+      if ( *sIt > 1 ) // size 1 pixel usually means empty Workstack area, which will NOT be re-created,
+       sizesStr += QString( ":%1" ).arg( *sIt );  // so we don't need to store its size
+    }
+    if ( !sizesStr.isEmpty() ) // cut the first ':'
+      sizesStr = sizesStr.right( sizesStr.length()-1 );    
+
+    // count all QSplitter-s and QtxWorkstackArea-s
+    //    int nChilds( 0 );
+    //    QObjectListIt it( *objs );
+    //    for ( ; it.current(); ++it )
+    //    {
+    //      if ( it.current()->inherits( "QSplitter" ) ||
+    //           it.current()->inherits( "QtxWorkstackArea" ) )
+    // nChilds++;
+    //    }
+      
+    info += QString( "(splitter orientation=%1 sizes=%3 " ).arg( split->orientation() ).arg( sizesStr );
+    
+    for ( QObjectListIt it( *objs ); it.current(); ++it )
+    {
+      if ( it.current()->inherits( "QSplitter" ) )
+       splitterInfo( (QSplitter*)it.current(), info );
+      else if ( it.current()->inherits( "QtxWorkstackArea" ) ) {
+       QtxWorkstackArea* area = (QtxWorkstackArea*)it.current();
+       if ( area->isEmpty() )
+         continue;
+       info += QString( "(views active='%1'" ).arg( area->activeWidget()->name() );
+       QWidgetList views = area->widgetList();
+       for ( QWidgetListIt wIt( views ); wIt.current(); ++wIt )
+         info += QString( " '%1'" ).arg( wIt.current()->name() );
+       info += ')';
+      }
+    }
+  }
+  info += ')';
+}
+
+
+// cuts starting '(' symbol and ending '(' symbol
+void cutBrackets( QString& parameters )
+{
+  if ( !parameters.isEmpty() && parameters[0] == '(' && parameters[parameters.length()-1] == ')' )
+    parameters = parameters.mid( 1, parameters.length()-2 );
+}
+
+// for strings like "(splitter orientation=0 children=2 sizes=332:478" returns values of
+// parameters.  For example, getValue( example, "children" ) returns "2"
+// getValue( example, "sizes" ) returns "332:478"
+QString getValue( const QString& str, const QString& valName )
+{
+  int i = str.find( valName );
+  if ( i != -1 ) {
+    int equal_i = str.find( '=', i );
+    if ( equal_i != -1 ) {
+      int space_i = str.find( ' ', ++equal_i );
+      if ( space_i != -1 )
+       return str.mid( equal_i, space_i-equal_i );
+    }
+  }
+  return QString( "" );
+}
+
+// checks format of splitter parameters string
+bool checkFormat( const QString& parameters )
+{
+  QString params( parameters );
+  // 1. begins and ends with brackets
+  bool ok = ( params[0] == '(' && params[params.length()-1] == ')' );
+  if ( !ok ) return ok;
+  ::cutBrackets( params );
+  // 2. has splitter word
+  ok = ( params.left( 8 ) == "splitter" );
+  if ( !ok ) return ok;
+  // 3. has children?  = '(' is found
+  int i = params.find( '(' );
+  ok = i != -1;
+  if ( !ok ) return ok;
+  params = params.left( i ); // cut all children, they will be checked later
+  // 4. has orientation word and correct value
+  ::getValue( params, "orientation" ).toInt( &ok );
+  if ( !ok ) return ok;
+  // 5. has sizes word and values
+  ok = ! ::getValue( params, "sizes" ).isEmpty();
+  if ( !ok ) return ok;
+  // 6. check children -> number of '(' == number of ')' in original string
+  ok = ( parameters.contains( '(' ) == parameters.contains( ')' ) );
+  return ok;
+}
+
+// returns children of splitter in a list.  Children are separated by '(' and ')' symbols
+QStringList getChildren( const QString& str )
+{
+  QStringList lst;
+  if ( !str.startsWith( "(" ) )
+    return lst;
+  
+  int i = 1,
+  nOpen = 1, // count brackets: '(' increments nOpen, ')' decrements
+  start = 0;
+  while ( i < str.length() ) {
+    if ( str[i] == '(' ) {
+      nOpen++;
+      if ( nOpen == 1 )
+       start = i;
+    }
+    else if ( str[i] == ')' ) {
+      nOpen--;
+      if ( nOpen == 0 ) 
+       lst.append( str.mid( start, i-start+1 ) );
+    }
+    i++;
+  }
+
+  return lst;
+}
+
+// for a string like "views active='AnotherView' 'GLView' 'AnotherView'"
+// getViewName( example, 0 ) returns "GLView", 
+// getViewName( example, 1 ) -> "AnotherView", etc.
+QString getViewName( const QString& str, int i )
+{
+  QRegExp exp( "\\s'\\w+'" );
+  int start = 0; // start index of view name in the string
+  int num = 0 ; // index of found match
+  while ( ( start = exp.search( str, start ) ) != -1 && num < i ) {
+    start += exp.matchedLength();
+    num ++;
+  }
+  if ( start != -1 )      // +2 and -3 avoid starting space and starting and ending ' symbols
+    return str.mid( start+2, exp.matchedLength()-3 );
+
+  return QString( "" );
+}
+
+// returns widget with given name
+QWidget* getView( const QWidget* parent, const QString& aName )
+{
+  QWidget* view = 0;
+  QObjectList *l = parent->topLevelWidget()->queryList( "QWidget", aName, false, true );
+  if ( !l->isEmpty() )
+    view = dynamic_cast<QWidget*>( l->first() );
+  delete l;
+  return view;
+}
+
+// installs a splitter described by given parameters string
+void QtxWorkstack::setSplitter( QSplitter* splitter, const QString& parameters, QMap< QSplitter*, QValueList<int> >& sMap )
+{
+  if ( !::checkFormat( parameters ) ) {
+    printf( "\nInvalid format of workstack parameters.  Positions of viewers can not be restored.\n" );
+    return;
+  }
+
+  QString params( parameters );
+  ::cutBrackets( params );
+
+  // get splitter sizes and store it in the map for future setting
+  QValueList<int> sizes;
+  QStringList sizesLst = QStringList::split( ':', ::getValue( params, "sizes" ) );
+  for ( QStringList::Iterator it = sizesLst.begin(); it != sizesLst.end(); ++it )
+    sizes.append( (*it).toInt() );
+  sMap[ splitter ] = sizes;
+
+  // set orientation of splitter
+  int orient = ::getValue( params, "orientation" ).toInt();
+  splitter->setOrientation( (Qt::Orientation)orient );
+
+  // get children
+  QString options = params.left( params.find( '(' ) );
+  QString childrenStr = params.right( params.length()-options.length() );
+  QStringList children = ::getChildren( childrenStr );
+
+  // debug output..
+  //  printf (" splitter orient=%d, sizes_count=%d, children=%d\n", orient, sizes.count(), children.count() ); 
+  //  for ( QStringList::Iterator tit = children.begin(); tit != children.end(); ++tit ) 
+  //    printf ("   |-> child = [%s]\n", (*tit).latin1() );
+
+  for ( QStringList::Iterator it = children.begin(); it != children.end(); ++it ) {
+    if ( (*it).startsWith( "(splitter" ) ) {
+      QSplitter* newSplitter = new QSplitter( splitter );
+      setSplitter( newSplitter, *it, sMap );
+    }
+    else if ( (*it).startsWith( "(views" ) ) {
+      QtxWorkstackArea* newArea = createArea( splitter );
+      QString activeViewName = ::getValue( *it, "active" );
+      QWidget* activeView( 0 );
+      activeViewName = activeViewName.mid( 1, activeViewName.length()-2 ); // chop off ' symbols
+      int i = 0;
+      QString viewName = ::getViewName( *it, i );
+      while ( !viewName.isEmpty() ) {
+       if ( QWidget* view = ::getView( splitter, viewName ) ) {
+         newArea->insertWidget( view );
+         if ( activeViewName == view->name() )
+           activeView = view;
+       }
+       viewName = ::getViewName( *it, ++i );
+      }
+      if ( activeView )
+       newArea->setActiveWidget( activeView );
+    }
+  }
+}
+
+// Restore workstack's configuration stored in 'parameters' string
+QtxWorkstack& QtxWorkstack::operator<<( const QString& parameters )
+{
+  // clear the main splitter - remove all child splitters and empty areas from it
+  QPtrList<QSplitter> splitList;
+  QPtrList<QtxWorkstackArea> areaList;
+  splitters( mySplit, splitList, false );
+  areas( mySplit, areaList, false );
+  for ( QPtrListIterator<QSplitter> iter( splitList ); iter.current(); ++iter )
+    delete iter.current();
+  for ( QPtrListIterator<QtxWorkstackArea> it( areaList ); it.current(); ++it ) 
+    if ( it.current()->isEmpty() )
+      delete it.current();
+
+  // restore splitter recursively
+  QMap< QSplitter*, QValueList<int> > sMap;
+  setSplitter( mySplit, parameters, sMap );  
+
+  // now mySplit may contains empty area (where all views were located before restoring)
+  // in order setSize to work correctly we have to exclude this area
+  areaList.clear();
+  areas( mySplit, areaList, false );
+  for ( QPtrListIterator<QtxWorkstackArea> delIt( areaList ); delIt.current(); ++delIt ) 
+    if ( delIt.current()->isEmpty() )
+      delete delIt.current();
+
+  qApp->processEvents();
+
+  // restore splitters' sizes (map of sizes is filled in setSplitters)
+  for ( QMap< QSplitter*, QValueList<int> >::Iterator it = sMap.begin(); it != sMap.end(); ++it )
+    it.key()->setSizes( it.data() );
+
+  return (*this);
+}
+
+// Example of string produced by operator>> :
+// "(splitter orientation=0 sizes=186:624 (views active='OCCViewer_0_0' 'OCCViewer_0_0')
+// (views active='VTKViewer_0_0' 'VTKViewer_0_0'))"
+QtxWorkstack& QtxWorkstack::operator>>( QString& outParameters )
+{
+  splitterInfo( mySplit, outParameters );
+  return (*this);
+}
+
+
 /*!
     Class: QtxWorkstackArea [Internal]
     Descr:
index 8157a2a814acfb4f3d912522755d751777ee3fa9..36b4382bde524afc874d817630a22831ad423f77 100644 (file)
@@ -81,6 +81,10 @@ public:
   void SetRelativePosition( QWidget* wid, const Qt::Orientation o, const double pos );
   void SetRelativePositionInSplitter( QWidget* wid, const double pos );
 
+  // asv: Store/Restore visual parameters - geometry of inner windows
+  QtxWorkstack& operator<<( const QString& );
+  QtxWorkstack& operator>>( QString& );
+
 signals:
   void                windowActivated( QWidget* );
 
@@ -125,7 +129,10 @@ private:
   void                distributeSpace( QSplitter* ) const;
   int                 setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
                                                           const int need_pos, const int splitter_pos );
-
+  
+  void                splitterInfo( QSplitter*, QString& ) const;
+  void                setSplitter( QSplitter*, const QString&, QMap< QSplitter*,QValueList<int> >& );
+  
 private:
   QWidget*            myWin;
   QtxWorkstackArea*   myArea;
index afc3446f3f43daad7ea5db8058f0532b4d1b3280..ddb393817477bcc0d174c5b6792e05e7eca808b3 100755 (executable)
@@ -22,8 +22,6 @@
 
 #include "SUIT_DataObjectKey.h"
 
-#include <iostream> // for cout in dump()
-
 /*!
     Constructor
 */
@@ -491,7 +489,7 @@ SUIT_DataObjectKey* SUIT_DataObject::key() const
 void SUIT_DataObject::dump( const int indent ) const
 {
   QString strIndent = QString().fill( ' ', indent ); // indentation string 
-  std::cout << strIndent << name() << std::endl;     // dump to cout
+  printf( "%s%s\n", strIndent.latin1(), name().latin1() );
   for ( DataObjectListIterator it( myChildren ); it.current(); ++it ) // iterate all children
     it.current()->dump( indent + 2 );  // dump every child with indent + 2 spaces
 }
index 2f83179c4655966d56b8fd458e7de08a701a4bd3..995aede9e7fbc98adddfbbc9a9a29fa301c21fa6 100755 (executable)
@@ -510,3 +510,18 @@ bool SUIT_Study::hasTransaction() const
 {
   return false;
 }
+
+/*!
+ * \brief Stores the study state
+*/
+int SUIT_Study::storeState()
+{
+  return -1;
+}
+/*!
+ * \brief Restores the study state
+*/
+void SUIT_Study::restoreState(int savePoint)
+{
+}
index c1163cc6c5049d0b2556c808a279e3e8a183a44c..da090c8a0eea896480917b4a61ae5e75df1d15f3 100755 (executable)
@@ -75,6 +75,9 @@ public:
   bool              suspend( SUIT_Operation* );
   bool              resume( SUIT_Operation* );
 
+  virtual int       storeState();
+  virtual void      restoreState(int savePoint);
+
 signals:
   void              studyModified( SUIT_Study* );
 
index d38f6fcdfcc02c8203cfbdc9ae8cf7572c7e592a..19bdf4edd645c9f5220e8efc6b7bca1537721c18 100644 (file)
@@ -38,10 +38,12 @@ const typename QValueList<TrgItem>::const_iterator findEqual( const QValueList<T
 template <class SrcItem, class TrgItem, class TreeData>
 TrgItem synchronize( const SrcItem& r1, const TrgItem& r2, const TreeData& td )
 {
-  //  printf( "--- synchronize : %d ---\n", ++gSync );
-
   if( td.isEqual( r1, r2 ) )
   {
+    // update items themselves
+    td.updateItem( r2 );
+
+    // iterate 'siblings' (direct children) 
     QValueList< DiffItem< SrcItem, TrgItem > > d;
     diffSiblings( r1, r2, d, td );
 
index bd4c32e69b7c278483c1b5d2caea1588637e1dfd..3b013f679d202bf1a7c550edee5c3ab58184c682 100755 (executable)
@@ -158,3 +158,12 @@ void SUIT_ViewWindow::onAccelAction( int _action )
 void SUIT_ViewWindow::action( const int  )
 {
 }
+
+QString   SUIT_ViewWindow::getVisualParameters()
+{
+  return "empty";
+}
+void SUIT_ViewWindow::setVisualParameters( const QString& parameters )
+{
+}
index 1ac79a504d8472736c7a33d68088b6ff34d23db4..200deb1c4d88f869be1ca7dc9d2da2d4aa3577e6 100755 (executable)
@@ -52,6 +52,9 @@ public:
 
   void              onAccelAction( int );
 
+  virtual QString   getVisualParameters();
+  virtual void      setVisualParameters( const QString& parameters );
+
 public slots:
   virtual void      onDumpView();
 
index 2e536541bdbafd6db69ce93c8b3c94005b957352..69e5eae4a358d6cc5180222f903ed9c5b23e6a0e 100755 (executable)
@@ -597,3 +597,99 @@ SVTK_ViewWindow
     myMainWindow->InvokeEvent( anEvent, 0 );
   }
 }
+
+/*! The method returns the visual parameters of this view as a formated string
+ */
+QString
+SVTK_ViewWindow
+::getVisualParameters()
+{
+  double pos[3], focalPnt[3], viewUp[3], parScale, scale[3];
+
+  vtkCamera* camera = getRenderer()->GetActiveCamera();
+  camera->GetPosition( pos );
+  camera->GetFocalPoint( focalPnt );
+  camera->GetViewUp( viewUp );
+  parScale = camera->GetParallelScale();
+  GetScale( scale );
+
+  QString retStr;
+  retStr.sprintf( "%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e", 
+                 pos[0], pos[1], pos[2], focalPnt[0], focalPnt[1], focalPnt[2], viewUp[0], viewUp[1], 
+                 viewUp[2], parScale, scale[0], scale[1], scale[2] );
+  return retStr;
+}
+
+/* The method restores visual parameters of this view or postpones it untill the view is shown
+ */
+void
+SVTK_ViewWindow
+::setVisualParameters( const QString& parameters )
+{
+  SVTK_RenderWindowInteractor* anInteractor = getMainWindow()->GetInteractor();
+  if ( anInteractor->isVisible() ) {
+    doSetVisualParameters( parameters ); 
+  }
+  else {
+    myVisualParams = parameters;
+    anInteractor->installEventFilter(this);
+  }
+}
+
+/* The method restores visual parameters of this view from a formated string
+ */
+void
+SVTK_ViewWindow
+::doSetVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = QStringList::split( '*', parameters, true );
+  if ( paramsLst.size() == 13 ) {
+    // 'reading' list of parameters
+    double pos[3], focalPnt[3], viewUp[3], parScale, scale[3];
+    pos[0] = paramsLst[0].toDouble();
+    pos[1] = paramsLst[1].toDouble();
+    pos[2] = paramsLst[2].toDouble();
+    focalPnt[0] = paramsLst[3].toDouble();
+    focalPnt[1] = paramsLst[4].toDouble();
+    focalPnt[2] = paramsLst[5].toDouble();
+    viewUp[0] = paramsLst[6].toDouble();
+    viewUp[1] = paramsLst[7].toDouble();
+    viewUp[2] = paramsLst[8].toDouble();
+    parScale = paramsLst[9].toDouble();
+    scale[0] = paramsLst[10].toDouble();
+    scale[1] = paramsLst[11].toDouble();
+    scale[2] = paramsLst[12].toDouble();
+    
+    // applying parameters
+    vtkCamera* camera = getRenderer()->GetActiveCamera();
+    camera->SetPosition( pos );
+    camera->SetFocalPoint( focalPnt );
+    camera->SetViewUp( viewUp );
+    camera->SetParallelScale( parScale );
+    SetScale( scale );
+
+    //    resize( size() );
+
+    //    getRenderer()->ResetCameraClippingRange();
+    //    Repaint();
+    //    getMainWindow()->GetRenderer()->GetTransform()->SetMatrixScale( scale[0], scale[1], scale[2] );
+  }
+}
+
+
+//================================================================
+// Function : eventFilter
+/*! Purpose : delayed setVisualParameters
+*/
+//================================================================
+bool SVTK_ViewWindow::eventFilter( QObject* theWatched, QEvent* theEvent )
+{
+  if ( theEvent->type() == QEvent::Show && theWatched->inherits( "SVTK_RenderWindowInteractor" ) ) {
+    SVTK_RenderWindowInteractor* anInteractor = (SVTK_RenderWindowInteractor*)theWatched;
+    if ( anInteractor->isVisible() ) {
+      doSetVisualParameters( myVisualParams );
+      anInteractor->removeEventFilter( this ); // theWatched = RenderWindowInteractor
+    }
+  }
+  return SUIT_ViewWindow::eventFilter( theWatched, theEvent );
+}
index 1eb88a77379365f368e42d88d41efc1dbe425e90..51e50ac4574d72fa80773e249c2662de811fed12 100755 (executable)
@@ -242,6 +242,19 @@ class SVTK_EXPORT SVTK_ViewWindow : public SUIT_ViewWindow
   void
   SetSelectionTolerance(const double& theTolNodes = 0.025, 
                        const double& theTolCell = 0.001);
+
+  //! Methods to save/restore visual parameters of a view (pan, zoom, etc.)
+  virtual 
+  QString   
+  getVisualParameters();
+  
+  virtual
+  void
+  setVisualParameters( const QString& parameters );
+
+  virtual
+  bool
+  eventFilter( QObject*, QEvent* );
   
 public slots:
   virtual
@@ -326,12 +339,17 @@ protected:
   Initialize(SVTK_View* theView,
             SVTK_ViewModelBase* theModel);
 
+  void
+  doSetVisualParameters( const QString& );
+
   QImage dumpView();
   virtual void action( const int );
 
   SVTK_View* myView;
   SVTK_MainWindow* myMainWindow;
   SVTK_ViewModelBase* myModel;
+
+  QString myVisualParams; // used for delayed setting of view parameters 
 };
 
 #ifdef WIN32
index cb3ce909e8ddd7aa2fbbcb32c539a5c642455cbf..8913a2b442d564607a964553b2ce49f2544ab9f7 100755 (executable)
@@ -25,7 +25,8 @@ EXPORT_HEADERS= SalomeApp.h \
                SalomeApp_Filter.h \
                SalomeApp_TypeFilter.h \
                SalomeApp_StudyPropertiesDlg.h \
-               SalomeApp_CheckFileDlg.h
+               SalomeApp_CheckFileDlg.h \
+               SalomeApp_VisualState.h
 
 # .po files to transform in .qm
 PO_FILES = SalomeApp_images.po \
@@ -48,7 +49,8 @@ LIB_SRC= SalomeApp_Module.cxx \
         SalomeApp_TypeFilter.cxx \
         SalomeApp_StudyPropertiesDlg.cxx \
         SalomeApp_ListView.cxx \
-        SalomeApp_CheckFileDlg.cxx
+        SalomeApp_CheckFileDlg.cxx \
+        SalomeApp_VisualState.cxx
 
 LIB_MOC = SalomeApp_Application.h \
          SalomeApp_DataModel.h \
index afe4b2b8737371050e588ad9198c35dcb883e2d7..76cabcd3f370a869d49e4db2a1f859359ebbb423 100644 (file)
 #include "SalomeApp_DataModel.h"
 #include "SalomeApp_DataObject.h"
 #include "SalomeApp_EventFilter.h"
+#include "SalomeApp_VisualState.h"
 
 #include "SalomeApp_StudyPropertiesDlg.h"
 
-#include "SalomeApp_CheckFileDlg.h"
-
 #include "LightApp_Application.h"
 #include "LightApp_Preferences.h"
 #include "LightApp_WidgetContainer.h"
 #include "LightApp_SelectionMgr.h"
+#include "LightApp_NameDlg.h"
 
 #include "STD_LoadStudiesDlg.h"
 
 #include <qcombobox.h>
 #include <qlistbox.h>
 #include <qregexp.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+
+#include "SALOMEDS_StudyManager.hxx"
+#include "SALOMEDS_SObject.hxx"
+#include "SALOMEDS_IParameters.hxx"
 
 #include "SALOME_ListIteratorOfListIO.hxx"
 #include "SALOME_ListIO.hxx"
@@ -98,6 +105,11 @@ void SalomeApp_Application::createActions()
 
   SUIT_Desktop* desk = desktop();
   
+  //! Save GUI state
+  createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIconSet(),
+               tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
+               0, desk, false, this, SLOT( onSaveGUIState() ) );
+
   //! Dump study
   createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIconSet(),
                tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
@@ -125,6 +137,7 @@ void SalomeApp_Application::createActions()
 
   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
 
+  createMenu( SaveGUIStateId, fileMenu, 10, -1 );
   createMenu( DumpStudyId, fileMenu, 10, -1 );
   createMenu( separator(), fileMenu, -1, 15, -1 );
   createMenu( LoadScriptId, fileMenu, 10, -1 );
@@ -361,8 +374,12 @@ void SalomeApp_Application::onSelectionChanged()
          _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
 
          if ( so ) {
-          canCopy = studyMgr()->CanCopy(so);
-          canPaste = studyMgr()->CanPaste(so);
+           SALOMEDS_SObject* aSO = dynamic_cast<SALOMEDS_SObject*>(so.get());
+
+           if ( aSO ) {
+             canCopy = studyMgr()->CanCopy(so);
+             canPaste = studyMgr()->CanPaste(so);
+           }
          }
        }
      }
@@ -454,14 +471,41 @@ void SalomeApp_Application::updateCommandsStatus()
   if ( a )
     a->setEnabled( activeStudy() );
 
+  // Properties menu
   a = action( PropertiesId );
   if( a )
     a->setEnabled( activeStudy() );
 
+  // Save GUI state menu
+  a = action( SaveGUIStateId );
+  if( a )
+    a->setEnabled( activeStudy() );
+
   // update state of Copy/Paste menu items
   onSelectionChanged();
 }
 
+/*
+  Class       : DumpStudyFileDlg
+  Description : Private class used in Dump Study operation.  Consists 2 check boxes: 
+                "Publish in study" and "Save GUI parameters"
+*/
+class DumpStudyFileDlg : public SUIT_FileDlg
+{
+public:
+  DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true ) 
+  {
+    QHBox* hB = new QHBox( this );
+    myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY"), hB );
+    mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE"), hB );
+    QPushButton* pb = new QPushButton(this);      
+    addWidgets( new QLabel("", this), hB, pb );
+    pb->hide();    
+  }
+  QCheckBox* myPublishChk;
+  QCheckBox* mySaveGUIChk;
+};
+
 /*!Private SLOT. On dump study.*/
 void SalomeApp_Application::onDumpStudy( )
 {
@@ -472,23 +516,34 @@ void SalomeApp_Application::onDumpStudy( )
   QStringList aFilters;
   aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
 
-  SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg( desktop(), false, tr("PUBLISH_IN_STUDY"), true, true);
+  DumpStudyFileDlg* fd = new DumpStudyFileDlg( desktop() );
   fd->setCaption( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
   fd->setFilters( aFilters );
-  fd->SetChecked(true);
+  fd->myPublishChk->setChecked( true );
+  fd->mySaveGUIChk->setChecked( true );
   fd->exec();
   QString aFileName = fd->selectedFile();
-  bool toPublish = fd->IsChecked();
+  bool toPublish = fd->myPublishChk->isChecked();
+  bool toSaveGUI = fd->mySaveGUIChk->isChecked();
   delete fd;
 
-  if(!aFileName.isEmpty()) {
+  if ( !aFileName.isEmpty() ) {
     QFileInfo aFileInfo(aFileName);
-    bool res = aStudy->DumpStudy( aFileInfo.dirPath( true ).latin1(), aFileInfo.baseName().latin1(), toPublish );
+    int savePoint;
+    if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
+      SALOMEDS_IParameters::setDumpPython(appStudy->studyDS());
+      savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
+      //prefix = SALOMEDS_IParameters::getStudyScript(appStudy->studyDS(), appStudy->getVisualComponentName(), savePoint);
+      
+    }
+    bool res = aStudy->DumpStudy( aFileInfo.dirPath( true ).latin1(), aFileInfo.baseName().latin1(), toPublish);
+    if ( toSaveGUI ) 
+      appStudy->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
     if ( !res )
-    SUIT_MessageBox::warn1 ( desktop(),
-                            QObject::tr("WRN_WARNING"),
-                            tr("WRN_DUMP_STUDY_FAILED"),
-                            QObject::tr("BUT_OK") );
+      SUIT_MessageBox::warn1 ( desktop(),
+                              QObject::tr("WRN_WARNING"),
+                              tr("WRN_DUMP_STUDY_FAILED"),
+                              QObject::tr("BUT_OK") );
   }
 }
 
@@ -524,6 +579,16 @@ void SalomeApp_Application::onLoadScript( )
   }
 }
 
+/*!Private SLOT. On save GUI state.*/
+void SalomeApp_Application::onSaveGUIState()
+{
+  SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
+  if ( !appStudy ) return;
+
+  SalomeApp_VisualState( this ).storeState();
+  updateObjectBrowser( false );
+}
+
 /*!Gets file filter.
  *\retval QString "(*.hdf)"
  */
@@ -584,6 +649,11 @@ void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
                          LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_%d", i ) );
   }
   pref->setItemProperty( defCols, "columns", 1 );
+
+  // adding preference to LightApp_Application handled preferences..  a bit of hacking with resources..
+  int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
+  int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
+  pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
 }
 
 /*!Update desktop title.*/
@@ -691,6 +761,15 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QPopupMenu* t
   LightApp_SelectionMgr* mgr = selectionMgr();
   mgr->selectedObjects( aList, QString::null, false );
 
+  // add GUI state commands: restore, rename
+  if ( aList.Extent() == 1 && aList.First()->hasEntry() && 
+       QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
+    thePopup->insertSeparator();
+    thePopup->insertItem( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
+    thePopup->insertItem( tr( "MEN_RENAME_VS" ),  this, SLOT( onRenameGUIState() ) );
+    thePopup->insertItem( tr( "MEN_DELETE_VS" ),  this, SLOT( onDeleteGUIState() ) );
+  }
+
   // "Delete reference" item should appear only for invalid references
 
   // isInvalidRefs will be true, if at least one of selected objects is invalid reference
@@ -725,6 +804,10 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QPopupMenu* t
   if (aList.Extent() != 1)
     return;
   Handle(SALOME_InteractiveObject) aIObj = aList.First();
+  // check if item is a "GUI state" item (also a first level object)
+  QString entry( aIObj->getEntry() );
+  if ( entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) )
+    return;
   QString aModuleName(aIObj->getComponentDataType());
   QString aModuleTitle = moduleTitle(aModuleName);
   CAM_Module* currentModule = activeModule();
@@ -733,10 +816,63 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QPopupMenu* t
   thePopup->insertItem( tr( "MEN_OPENWITH" ), this, SLOT( onOpenWith() ) );
 }
 
+/*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
+void updateSavePointDataObjects( OB_Browser* ob, SalomeApp_Study* study )
+{
+  if ( !study || !ob )
+    return;
+
+  // find GUI states root object
+  SUIT_DataObject* guiRootObj = 0;
+  DataObjectList ch; 
+  study->root()->children( ch ); 
+  DataObjectList::const_iterator it = ch.begin(), last = ch.end();
+  for ( ; it != last ; ++it ) {
+    if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) )
+      guiRootObj = *it;
+  }
+  std::vector<int> savePoints = study->getSavePoints();
+  // case 1: no more save points but they existed in study's tree
+  if ( savePoints.empty() && guiRootObj ) {
+    delete guiRootObj;
+    return;
+  }
+  // case 2: no more save points but root does not exist either
+  if ( savePoints.empty() && !guiRootObj )
+    return;
+  // case 3: save points but no root for them - create it
+  if ( !savePoints.empty() && !guiRootObj )
+    guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
+  // case 4: everything already exists..  nothing to do..
+
+  // store data objects in a map id-to-DataObject
+  QMap<int,SalomeApp_SavePointObject*> mapDO;
+  ch.clear(); 
+  guiRootObj->children( ch ); 
+  for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
+    SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
+    if ( dobj )
+      mapDO[dobj->getId()] = dobj;
+  }
+
+  // iterate new save points.  if DataObject with such ID not found in map - create DataObject
+  // if in the map - remove it from map.  
+  for ( int i = 0; i < savePoints.size(); i++ )
+    if ( !mapDO.contains( savePoints[i] ) )
+      new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
+    else {
+      ob->updateTree( mapDO[ savePoints[i] ] );
+      mapDO.remove( savePoints[i] );
+    }
+  // delete DataObjects that are still in the map -- their IDs were not found in data model
+  for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
+    delete it.data();
+}
+
 /*!Update obect browser:
  1.if 'updateModels' true, update existing data models;
  2. update "non-existing" (not loaded yet) data models;
- 3. update object browser if it existing */
+ 3. update object browser if it exists */
 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
 {
   // update "non-existing" (not loaded yet) data models
@@ -761,16 +897,16 @@ void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
         //SalomeApp_DataModel::BuildTree( aComponent, study->root(), study, /*skipExisitng=*/true );
       }
     }
+    // create data objects that correspond to GUI state save points
+    ::updateSavePointDataObjects( objectBrowser(), study );
   }
 
   // update existing data models (already loaded SComponents)
   LightApp_Application::updateObjectBrowser( updateModels );
 
-/*  if ( objectBrowser() )
-  {
-    objectBrowser()->updateGeometry();
-    objectBrowser()->updateTree();
-  }*/
+  // -- debug -- 
+  //  if ( study && study->root() )
+  //    study->root()->dump();
 }
 
 /*!Display Catalog Genenerator dialog */
@@ -832,3 +968,73 @@ void SalomeApp_Application::onDblClick( QListViewItem* it )
     }
   }
 }
+
+SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
+{
+  return createViewManager(type);
+}
+
+
+/*!Global utility funciton, returns selected GUI Save point object's ID */
+int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
+{
+  SALOME_ListIO aList;
+  selMgr->selectedObjects( aList );
+  Handle(SALOME_InteractiveObject) aIObj = aList.First();
+  QString entry( aIObj->getEntry() );
+  QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
+  if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
+    return -1;
+  bool ok; // conversion to integer is ok?
+  int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
+  return ok ? savePoint : -1;
+}
+
+/*!Called on Restore GUI State popup command*/
+void SalomeApp_Application::onRestoreGUIState()
+{
+  int savePoint = ::getSelectedSavePoint( selectionMgr() );
+  if ( savePoint == -1 ) 
+    return;  
+  SalomeApp_VisualState( this ).restoreState( savePoint );
+}
+
+/*!Called on Rename GUI State popup command*/
+void SalomeApp_Application::onRenameGUIState()
+{
+  int savePoint = ::getSelectedSavePoint( selectionMgr() );
+  if ( savePoint == -1 ) 
+    return;  
+  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
+  if ( !study ) 
+    return;
+
+  QString newName = LightApp_NameDlg::getName( desktop(), study->getNameOfSavePoint( savePoint ) );
+  if ( !newName.isNull() && !newName.isEmpty() ) {
+    study->setNameOfSavePoint( savePoint, newName );
+    updateSavePointDataObjects( objectBrowser(), study );
+  }
+}
+
+
+/*!Called on Delete GUI State popup command*/
+void SalomeApp_Application::onDeleteGUIState()
+{
+  int savePoint = ::getSelectedSavePoint( selectionMgr() );
+  if ( savePoint == -1 ) 
+    return;  
+  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
+  if ( !study ) 
+    return;
+  
+  study->removeSavePoint( savePoint );
+  updateSavePointDataObjects( objectBrowser(), study );
+}
+
+/*!Called on Save study operation*/
+void SalomeApp_Application::onStudySaved( SUIT_Study* study )
+{
+  updateObjectBrowser( false );
+  LightApp_Application::onStudySaved( study );
+}
+
index 2462e557b770edd06345a45f22b3cbc1a88fad7c..1ea58679eb6a245d0f959b8ec1e339e9f2ad19d1 100644 (file)
@@ -46,7 +46,7 @@ class SALOMEAPP_EXPORT SalomeApp_Application : public LightApp_Application
 
 public:
   enum { DumpStudyId = LightApp_Application::UserID, LoadScriptId, PropertiesId,
-         CatalogGenId, RegDisplayId, UserID };
+         CatalogGenId, RegDisplayId, SaveGUIStateId, UserID };
 
 public:
   SalomeApp_Application();
@@ -66,6 +66,8 @@ public:
   static SALOME_LifeCycleCORBA*       lcc();
   static QString                      defaultEngineIOR();
 
+  SUIT_ViewManager*                   newViewManager(const QString&);
+
 public slots:
   virtual bool                        onOpenDoc( const QString& );
   virtual void                        onLoadDoc();
@@ -73,6 +75,9 @@ public slots:
   virtual void                        onCopy();
   virtual void                        onPaste();
 
+protected slots:
+  void                                onStudySaved( SUIT_Study* );
+
 protected:
   virtual void                        createActions();
   virtual SUIT_Study*                 createNewStudy();
@@ -83,17 +88,21 @@ protected:
 
   virtual void                        createPreferences( LightApp_Preferences* );
   virtual void                        updateDesktopTitle();
-
+  
 private slots:
   void                                onDeleteInvalidReferences();
   void                                onDblClick( QListViewItem* );
   void                                onProperties();
   void                                onDumpStudy();
   void                                onLoadScript(); 
+  void                                onSaveGUIState(); 
+  void                                onDeleteGUIState(); 
 
   void                                onCatalogGen();
   void                                onRegDisplay();
   void                                onOpenWith();
+  void                                onRestoreGUIState();
+  void                                onRenameGUIState();
 };
 
 #ifdef WIN32
index 5fcae7b7b2651a3cdfa44c522d8205d5499347cc..b31708a57bc870ad7b6d4efc530dfaa159387678 100644 (file)
@@ -285,31 +285,7 @@ SUIT_DataObject* SalomeApp_DataModel::synchronize( const _PTR( SComponent )& sob
 
   SalomeApp_DataModelSync sync( study->studyDS(), study->root() );
 
-  //  QString srcName = sobj ? sobj->GetName().c_str() : "";
-  //  QString trgName = ( suitObj && !suitObj->name().isNull() ) ? suitObj->name() : "";
-  //  printf( "--- SalomeApp_DataModel::syncronize() calls synchronize()_1: src = %s, trg = %s ---\n",  srcName.latin1(), trgName.latin1() );
-
-  SUIT_DataObject* o = ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
-//  showTree( o );
-  return o;
-}
-
-//================================================================
-// Function : synchronize
-/*! Purpose  : synchronizes kernel tree and suit data tree starting from 'sobj' and 'obj' correspondly */
-//================================================================
-SUIT_DataObject* SalomeApp_DataModel::synchronize( const _PTR( SObject )& sobj, SUIT_DataObject* obj,
-                                                  SalomeApp_Study* study )
-{
-  if( !study )
-    return 0;
-  SalomeApp_DataModelSync sync( study->studyDS(), study->root() );
-
-  //  QString srcName = sobj ? sobj->GetName().c_str() : "";
-  //  QString trgName = ( obj && !obj->name().isNull() ) ? obj->name() : "";
-  //  printf( "--- SalomeApp_DataModel::syncronize() calls synchronize()_2: src = s, trg = %s ---\n",  srcName.latin1(), trgName.latin1() );
-
-  return ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, obj, sync );
+  return ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
 }
 
 //================================================================
index 62e649bc36ad4abd1213390716e5a89e688d9836..7452cd366c19abe5ef371687a57ea87bb8b501f9 100644 (file)
@@ -27,10 +27,9 @@ class SALOMEAPP_EXPORT SalomeApp_DataModel : public LightApp_DataModel
 
 public:
   static SUIT_DataObject*             synchronize( const _PTR( SComponent )&, SalomeApp_Study* );
-  static SUIT_DataObject*             synchronize( const _PTR( SObject )&, SUIT_DataObject*, SalomeApp_Study* );
 
-                                      SalomeApp_DataModel ( CAM_Module* theModule );
-  virtual                             ~SalomeApp_DataModel();
+  SalomeApp_DataModel ( CAM_Module* theModule );
+  virtual ~SalomeApp_DataModel();
 
   virtual bool                        open( const QString&, CAM_Study*, QStringList );
   virtual bool                        create( CAM_Study* );
index ef7b8df7b6289f991b54d3395ffeae683f85dc59..5bb857865100a6368ff0f3a9f4a8ec24170ba30e 100644 (file)
@@ -21,6 +21,8 @@
 #include "SalomeApp_Study.h"
 #include "LightApp_RootObject.h"
 
+#include <CAM_DataObject.h>
+
 #include <SUIT_Application.h>
 #include <SUIT_ResourceMgr.h>
 #include <SUIT_DataObjectKey.h>
@@ -371,3 +373,50 @@ QString SalomeApp_ModuleObject::name() const
   return SalomeApp_DataObject::name();
 }
 
+/*
+       Class: SalomeApp_SavePointObject
+       Level: Public
+*/
+
+/*!Constructor.Initialize by \a parent.*/
+SalomeApp_SavePointObject::SalomeApp_SavePointObject( SUIT_DataObject* _parent, const int id, SalomeApp_Study* study )
+  : LightApp_DataObject( _parent ), CAM_DataObject( _parent ), // IMPORTANT TO CALL ALL VIRTUAL CONSTRUCTORS!
+    myId( id ),
+    myStudy( study )
+{
+}
+
+/*!Destructor. Do nothing.*/
+SalomeApp_SavePointObject::~SalomeApp_SavePointObject()
+{
+}
+
+/*!Returns save points ID */
+int SalomeApp_SavePointObject::getId() const
+{
+  return myId;
+}
+
+/*!Returns "invalid" entry, which does not correspond to any object in data structure
+  but indicates that it is a save point object  */
+QString SalomeApp_SavePointObject::entry() const
+{
+  return QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( myId );
+}
+
+/*!Returns displayed name of object */
+QString SalomeApp_SavePointObject::name() const
+{
+  return myStudy->getNameOfSavePoint( myId );
+}
+
+QPixmap SalomeApp_SavePointObject::icon() const
+{
+  return QPixmap();
+}
+
+QString SalomeApp_SavePointObject::toolTip() const
+{
+  return QObject::tr( "SAVE_POINT_OBJECT_TOOLTIP" ).arg( name() );
+}
+
index 15a1d96bfdb99bfcb5125695625feb8d29e2b37e..33cf78d67b370f5cd1e1747d2fbd0c023b99ae9b 100644 (file)
@@ -82,7 +82,45 @@ public:
   SalomeApp_ModuleObject( CAM_DataModel*, const _PTR(SObject)&, SUIT_DataObject* = 0 );
   virtual ~SalomeApp_ModuleObject();
 
-  virtual QString        name() const;
+  virtual QString                 name() const;
+};
+
+/*!
+ * SalomeApp_SavePointObject - class that represents persistent visual_state object
+ * these objects are stored in data model, but NOT in SObjects structure, so we
+ * must handle them separately using this special class for them
+ */
+
+class SALOMEAPP_EXPORT SalomeApp_SavePointObject : public virtual LightApp_DataObject
+{
+public:
+  SalomeApp_SavePointObject( SUIT_DataObject* parent, const int, SalomeApp_Study* study );
+  virtual ~SalomeApp_SavePointObject();
+  
+  virtual QString                 entry() const;
+
+  virtual QString                 name() const;
+  virtual QPixmap                 icon() const;
+  virtual QString                 toolTip() const;
+
+  int                             getId() const;
+
+private:
+  int                             myId;
+  SalomeApp_Study*                myStudy;
+};
+
+/*!
+ * SalomeApp_SavePointRootObject - class that represents parent object for visual_state objects
+ */
+
+class SALOMEAPP_EXPORT SalomeApp_SavePointRootObject : public SUIT_DataObject
+{
+public:
+  SalomeApp_SavePointRootObject( SUIT_DataObject* parent ) : SUIT_DataObject( parent ) {}
+  
+  virtual QString                 name() const   { return QObject::tr( "SAVE_POINT_ROOT_NAME" ); }
+  virtual QString                 toolTip() const{ return QObject::tr( "SAVE_POINT_ROOT_TOOLTIP" ); }
 };
 
 #endif
index 9284a579204aae09eaf81fb49d8effd0acea6b1a..b22992cf4daadf35ef64e9f05c12719cf3875d05 100644 (file)
@@ -11,6 +11,7 @@
 #include "LightApp_Selection.h"
 #include "LightApp_Operation.h"
 #include "LightApp_Preferences.h"
+//#include "LightApp_Displayer.h"
 
 #include "CAM_DataModel.h"
 
 #include <SALOME_ListIO.hxx>
 #include <SALOME_ListIteratorOfListIO.hxx>
 #include <SALOME_InteractiveObject.hxx>
+//#include <SALOME_Actor.h>
+
+//#include "SALOMEDS_IParameters.hxx"
 
 #include <SUIT_Session.h>
+#include <SUIT_ViewModel.h>
+
+#include <SVTK_ViewWindow.h>
+//#include <SVTK_ViewModel.h>
+//#include <SVTK_MainWindow.h>
+//#include <SVTK_RenderWindowInteractor.h>
 
 #include <qstring.h>
 #include <qmap.h>
 
+//#include <vtkActorCollection.h>
+//#include <vtkRenderer.h>
+
 /*!Constructor.*/
 SalomeApp_Module::SalomeApp_Module( const QString& name )
 : LightApp_Module( name )
@@ -97,3 +110,24 @@ void SalomeApp_Module::extractContainers( const SALOME_ListIO& source, SALOME_Li
     dest.Append( obj );
   }
 }
+
+/*!
+ * \brief Virtual public
+ *
+ * This method is called just before the study document is saved, so the module has a possibility
+ * to store visual parameters in AttributeParameter attribue(s)
+ */
+void SalomeApp_Module::storeVisualParameters(int savePoint)
+{
+}
+
+/*!
+ * \brief Virtual public
+ *
+ * This method is called after the study document is opened, so the module has a possibility to restore
+ * visual parameters
+ */
+void SalomeApp_Module::restoreVisualParameters(int savePoint)
+{
+}
+
index 433d918fd0b9e9e6d542d3e7ba3a461f85985869..7346e85375883a04edf1126d307c8e780c431ba4 100644 (file)
@@ -10,8 +10,6 @@
 
 #include <LightApp_Module.h>
 
-#include <string>
-
 class CAM_DataModel;
 class SalomeApp_Application;
 class LightApp_Operation;
@@ -41,6 +39,9 @@ public:
 
   SalomeApp_Application*              getApp() const;
 
+  virtual void                        storeVisualParameters(int savePoint);
+  virtual void                        restoreVisualParameters(int savePoint);
+
 protected:
   virtual CAM_DataModel*              createDataModel();
   virtual LightApp_Selection*         createSelection() const;
index f3de086605ec8967f99fd10910cd16004f4c8833..3a41ac01a8d2a16f9333ef55ae886d03b9846caf 100644 (file)
@@ -23,6 +23,7 @@
 #include "SalomeApp_DataObject.h"
 #include "SalomeApp_Application.h"
 #include "SalomeApp_Engine_i.hxx"
+#include "SalomeApp_VisualState.h"
 
 #include "LightApp_RootObject.h"
 
 #include <SUIT_ResourceMgr.h>
 
 #include <qptrlist.h>
+#include <qapplication.h>
+#include <qdict.h>
 
 #include "utilities.h"
-#include "string.h"
-#include "vector.h"
+#include <iostream.h>
+#include <string>
+#include <vector>
+
+#include <SUIT_Session.h>
 
 #include "SALOMEDS_Tool.hxx"
 
+#include "SALOMEDS_IParameters.hxx"
+
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SALOME_Exception)
 
+using namespace std;
+
 /*!
   Constructor.
 */
@@ -130,6 +140,14 @@ bool SalomeApp_Study::openDocument( const QString& theFileName )
   
   emit opened( this );
   study->IsSaved(true);
+
+  bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
+  if ( restore ) {
+    std::vector<int> savePoints = getSavePoints();
+    if ( savePoints.size() > 0 )
+      SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
+  }
+
   return res;
 }
 
@@ -167,6 +185,13 @@ bool SalomeApp_Study::loadDocument( const QString& theStudyName )
   bool res = CAM_Study::openDocument( theStudyName );
   emit opened( this );
 
+  bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
+  if ( restore ) {
+    std::vector<int> savePoints = getSavePoints();
+    if ( savePoints.size() > 0 )
+      SalomeApp_VisualState( (SalomeApp_Application*)application() ).restoreState( savePoints[savePoints.size()-1] );
+  }
+
   //SRN: BugID IPAL9021: End
 
   return res;
@@ -178,6 +203,10 @@ bool SalomeApp_Study::loadDocument( const QString& theStudyName )
 //=======================================================================
 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
 {
+  bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
+  if ( store )
+    SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
+  
   ModelList list; dataModels( list );
 
   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
@@ -214,6 +243,10 @@ bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
 //=======================================================================
 bool SalomeApp_Study::saveDocument()
 {
+  bool store = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true );
+  if ( store )
+    SalomeApp_VisualState( (SalomeApp_Application*)application() ).storeState();
+
   ModelList list; dataModels( list );
 
   SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)list.first();
@@ -221,7 +254,7 @@ bool SalomeApp_Study::saveDocument()
   for ( ; aModel; aModel = (SalomeApp_DataModel*)list.next() ) {
     listOfFiles.clear();
     aModel->save(listOfFiles);
-    if ( !listOfFiles.isEmpty() )
+    if ( !listOfFiles.isEmpty() ) 
       saveModuleData(aModel->module()->name(), listOfFiles);
   }
 
@@ -629,3 +662,77 @@ void SalomeApp_Study::components( QStringList& comps ) const
     comps.append( aComponent->ComponentDataType().c_str() );
   }
 }
+
+//================================================================
+// Function : getSavePoints
+/*! Purpose : returns a list of saved points' IDs
+*/
+//================================================================
+std::vector<int> SalomeApp_Study::getSavePoints()
+{
+  std::vector<int> v;
+
+  _PTR(SObject) so = studyDS()->FindComponent("Interface Applicative");
+  if(!so) return v;
+
+  _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
+  _PTR(ChildIterator) anIter ( studyDS()->NewChildIterator( so ) );
+  for(; anIter->More(); anIter->Next())
+  {
+    _PTR(SObject) val( anIter->Value() );
+    _PTR(GenericAttribute) genAttr;
+    if(builder->FindAttribute(val, genAttr, "AttributeParameter")) v.push_back(val->Tag());
+  }
+
+  return v;
+}
+
+//================================================================
+// Function :removeSavePoint
+/*! Purpose : remove a given save point
+*/
+//================================================================
+void SalomeApp_Study::removeSavePoint(int savePoint)
+{
+  if(savePoint <= 0) return;
+ _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
+  _PTR(SObject) so = AP->GetSObject();
+  _PTR(StudyBuilder) builder = studyDS()->NewBuilder();
+  builder->RemoveObjectWithChildren(so);
+}
+
+//================================================================
+// Function : getNameOfSavePoint
+/*! Purpose : returns a name of save point
+*/
+//================================================================
+QString SalomeApp_Study::getNameOfSavePoint(int savePoint)
+{
+  _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
+  SALOMEDS_IParameters ip(AP);
+  return ip.getProperty("AP_SAVEPOINT_NAME");
+}
+
+//================================================================
+// Function : setNameOfSavePoint
+/*! Purpose : sets a name of save point
+*/
+//================================================================
+void SalomeApp_Study::setNameOfSavePoint(int savePoint, const QString& nameOfSavePoint)
+{
+  _PTR(AttributeParameter) AP = studyDS()->GetCommonParameters(getVisualComponentName(), savePoint);
+  SALOMEDS_IParameters ip(AP);
+  ip.setProperty("AP_SAVEPOINT_NAME", nameOfSavePoint.latin1());
+}
+
+//================================================================
+// Function : getVisualComponentName
+/*! Purpose : returns a name of the component where visual
+ *             parameters are stored
+*/
+//================================================================
+std::string SalomeApp_Study::getVisualComponentName()
+{
+  return "Interface Applicative";
+}
+
index c07d205280d6fc2d96a23643f73a6cc221c6705c..b3edd25641592bdad3a84fef09b761eec294f5e2 100644 (file)
@@ -22,6 +22,7 @@
 #include "SalomeApp.h"
 
 #include <LightApp_Study.h>
+#include <string>
 
 #ifdef WIN32
 #pragma warning( disable:4251 )
@@ -66,6 +67,12 @@ public:
   virtual void        children( const QString&, QStringList& ) const;
   virtual void        components( QStringList& ) const;
 
+  std::vector<int>    getSavePoints();
+  void                removeSavePoint(int savePoint);
+  QString             getNameOfSavePoint(int savePoint);
+  void                setNameOfSavePoint(int savePoint, const QString& nameOfSavePoint);
+  virtual std::string getVisualComponentName();
+
 protected:
   virtual void        saveModuleData ( QString theModuleName, QStringList theListOfFiles );
   virtual void        openModuleData ( QString theModuleName, QStringList& theListOfFiles );
diff --git a/src/SalomeApp/SalomeApp_VisualState.cxx b/src/SalomeApp/SalomeApp_VisualState.cxx
new file mode 100644 (file)
index 0000000..ff00dbc
--- /dev/null
@@ -0,0 +1,295 @@
+// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/
+//
+#include "SalomeApp_VisualState.h"
+
+#include "SalomeApp_Module.h"
+#include "SalomeApp_Study.h"
+#include "SalomeApp_Application.h"
+
+#include <SUIT_ResourceMgr.h>
+#include <QtxWorkstack.h>
+
+#include <STD_TabDesktop.h>
+
+#include <qptrlist.h>
+#include <qapplication.h>
+#include <qdict.h>
+
+#include <SALOMEDS_IParameters.hxx>
+
+#include <vector>
+#include <string>
+
+/*!
+  Constructor.
+*/
+SalomeApp_VisualState::SalomeApp_VisualState( SalomeApp_Application* app )
+  : myApp( app )
+{
+}  
+
+/*!
+  Destructor.
+*/
+SalomeApp_VisualState::~SalomeApp_VisualState()
+{
+}
+
+//================================================================
+// Function : nameViewWindows
+/*! Purpose : set names of all view windows in given list.  This is used
+//  in order to apply the same naming algorithm when saving and restoring
+//  view windows.  Names of view windows must be the same before saving
+//  workstack (splitters) information, and before its restoring! 
+//  Naming rule: ViewerType_IndexOfViewerOfThisType_IndexOfViewInThisViewer
+//               VTKViewer_0_0
+//               OCCViewer_0_0  OCCViewer_0_1  OCCViewer_0_2
+//               VTKViewer_1_0
+*/
+//================================================================
+void nameViewWindows( const ViewManagerList& lst )
+{
+  QDict<int> viewersCounter; // map viewerType - to - index_of_this_viewer_type
+  viewersCounter.setAutoDelete( true );
+  for ( QPtrListIterator<SUIT_ViewManager> it(lst); it.current(); ++it) {
+    int view_count = it.current()->getViewsCount();
+    QString vType = it.current()->getType();
+    if ( !view_count )
+      continue; //No views is opened in the viewer
+    
+    int* viewerID = viewersCounter[ vType ];
+    if ( !viewerID ) {
+      viewerID = new int( 0 );
+      viewersCounter.insert( vType, viewerID );
+    }
+    else
+      ++(*viewerID);
+
+    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
+    for ( int i = 0; i < view_count; i++ )  {
+      QString vName = QString( "%1_%2_%3" ).arg( vType ).arg( *viewerID ).arg( i );
+      views[i]->setName( vName );
+    }
+  }
+}
+
+//================================================================
+// Function : storeState
+/*! Purpose : store the visual parameters of the viewers
+*/
+//================================================================
+int SalomeApp_VisualState::storeState()
+{
+  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
+  if ( !study )
+    return -1;
+
+  int savePoint = 1;
+  std::vector<int> savePoints = study->getSavePoints();
+  //Calculate a new savePoint number = the last save point number + 1
+  if ( savePoints.size() > 0) 
+    savePoint = savePoints[savePoints.size()-1] + 1;
+
+  _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName(), savePoint );
+  SALOMEDS_IParameters ip( ap );
+
+  ViewManagerList lst;
+  myApp->viewManagers( lst );
+
+  // setting unique names for view windows in order to save this view inside 
+  // workstack's structure (see below).  On restore the views with the same names will
+  // be placed to the same place inside the workstack's splitters.
+  nameViewWindows( lst );
+
+  // store active window's name
+  SUIT_ViewWindow* win = myApp->desktop()->activeWindow();  
+  if ( win )
+    ip.setProperty("AP_ACTIVE_VIEW", win->name() );
+
+  int viewerID = 0;
+  SUIT_ViewManager* vm = 0;
+  for (QPtrListIterator<SUIT_ViewManager> it( lst ); it.current(); ++it ) {
+    vm = it.current();
+    int view_count = vm->getViewsCount();
+    if ( !view_count ) 
+      continue; //No views is opened in the viewer
+      
+    std::string viewerEntry = QString( "%1_%2" ).arg( vm->getType() ).arg( ++viewerID ).latin1();
+    ip.append("AP_VIEWERS_LIST", viewerEntry);
+    
+    QPtrVector<SUIT_ViewWindow> views = vm->getViews();
+    for(int i = 0; i<view_count; i++) {
+      ip.append( viewerEntry, views[i]->caption() );
+      ip.append( viewerEntry, views[i]->getVisualParameters().latin1() );
+    }
+  }
+
+  //Save information about split areas
+  if ( myApp->desktop()->inherits( "STD_TabDesktop" ) ) {
+    QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
+    QString workstackInfo;
+    (*workstack) >> workstackInfo;
+    ip.setProperty( "AP_WORKSTACK_INFO", workstackInfo.latin1() );
+  }
+  
+  //Save a name of the active module
+  if ( CAM_Module* activeModule = myApp->activeModule() ) 
+    ip.setProperty( "AP_ACTIVE_MODULE", activeModule->moduleName().latin1() );
+
+  //Store visual parameters of the modules
+  QPtrList<CAM_Module> mlist; 
+  myApp->modules( mlist );
+  CAM_Module* module = 0;
+  for ( module = mlist.first(); module; module = mlist.next() ) {
+    if ( SalomeApp_Module* sModule = dynamic_cast<SalomeApp_Module*>( module ) ) {
+      ip.append( "AP_MODULES_LIST", sModule->moduleName().latin1() );
+      sModule->storeVisualParameters( savePoint );
+    }
+  }
+
+  // set default name of new savePoint
+  study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );
+  
+  return savePoint;
+}
+
+//================================================================
+// Function : restoreState
+/*! Purpose : restore the visual parameters of the viewers
+*/
+//================================================================
+void SalomeApp_VisualState::restoreState(int savePoint)
+{
+  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
+  if ( !study )
+    return;
+
+  _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName(), savePoint );
+  SALOMEDS_IParameters ip(ap);
+
+  //Remove all already existent veiwers and their views
+  ViewManagerList lst;
+  myApp->viewManagers( lst );
+  for ( QPtrListIterator<SUIT_ViewManager> it(lst); it.current(); ++it )
+    myApp->removeViewManager( it.current() );
+
+  //Restore the viewers and view windows
+  int nbViewers = ip.nbValues( "AP_VIEWERS_LIST" );
+  SUIT_ViewWindow* viewWin = 0;
+
+  for ( int i = 0; i < nbViewers; i++ ) {
+    std::string viewerEntry = ip.getValue( "AP_VIEWERS_LIST", i );
+    std::vector<std::string> veiewerParams = ip.parseValue(viewerEntry,'_');
+    std::string type = veiewerParams[0];
+    std::string viewerID = veiewerParams[1];
+    SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
+    if ( !vm ) 
+      continue; //Unknown viewer
+    
+    int nbViews = (ip.nbValues(viewerEntry))/2;
+    
+    //Create nbViews-1 view (-1 because 1 view is created by createViewManager)
+    for ( int i = 1; i< nbViews; i++ ) { 
+      SUIT_ViewWindow* aView = vm->createViewWindow();
+      aView->show();
+    }
+
+    int viewCount = vm->getViewsCount();
+    if (viewCount != nbViews) {
+      printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
+      continue;
+    }
+
+    //Resize the views, set their captions and apply visual parameters.
+    QPtrVector<SUIT_ViewWindow> views = vm->getViews();  
+    for (int i = 0, j = 0; i<viewCount; i++, j++) {
+      viewWin = views[i];
+      if ( !viewWin ) 
+       continue;
+
+      // wait untill the window is really shown.  This step fixes MANY bugs..
+      while ( !viewWin->isVisible() )
+       qApp->processEvents();
+      
+      viewWin->setCaption(ip.getValue(viewerEntry, j).c_str());
+      viewWin->setVisualParameters(ip.getValue(viewerEntry, j+1).c_str());
+    }
+  }
+
+  // restore modules' visual parameters
+  std::vector<std::string> v = ip.getValues("AP_MODULES_LIST");
+  for ( int i = 0; i < v.size(); i++ ) {
+    myApp->activateModule( v[i].c_str() );
+    if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
+      module->restoreVisualParameters( savePoint );
+  }
+
+  // activate module that was active on save
+  QString activeModuleName( ip.getProperty("AP_ACTIVE_MODULE" ).c_str() );
+  if ( !activeModuleName.isEmpty() ) 
+    myApp->activateModule( activeModuleName );
+
+  // setting unique names for view windows in order to restore positions of view windows inside 
+  // workstack's structure (see below).  During save the same naming algorithm was used, 
+  // so the same views will get the same names.
+  lst.clear();
+  myApp->viewManagers(lst);
+  nameViewWindows( lst );
+
+  // work-around to bug of setting visual parameters of views: all view windows now have
+  // correct visual parameters, bug after restoring the workstack the visual parameters 
+  // are messted, and must be re-set again.  So here we store them in a map and set them
+  // later back again.  why we don't store these parameters in a map on views creation?
+  // because 1) names of view windows are not set at that time 2) some view windows
+  // are created by modules' restoreVisualParameters (like Gauss Viewers), which is NOT here..
+  QMap<QString, QString> viewersParameters;
+  QPtrListIterator<SUIT_ViewManager> it( lst );
+  for ( ; it.current(); ++it ) {
+    int view_count = it.current()->getViewsCount();
+    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
+    for ( int i = 0; i < view_count; i++ )
+      viewersParameters[ views[i]->name() ] = views[i]->getVisualParameters();
+  }  
+
+  // restore workstack parameters.  should be done after module's restoreVisualParameters(), because
+  // some modules can create their own viewers (like VISU creates GaussViewers)
+  if ( myApp->desktop()->inherits( "STD_TabDesktop" ) ) {
+    QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
+    (*workstack) << ip.getProperty( "AP_WORKSTACK_INFO" ).c_str();
+  }
+
+  // restore visual parameters of view windows.  it must be done AFTER restoring workstack.
+  for ( it.toFirst(); it.current(); ++it ) {
+    int view_count = it.current()->getViewsCount();
+    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
+    for ( int i = 0; i < view_count; i++ )
+      views[i]->setVisualParameters( viewersParameters[ views[i]->name() ] );
+  }
+
+  // set focus to previously saved active view window
+  std::string activeViewName = ip.getProperty("AP_ACTIVE_VIEW");
+  for ( it.toFirst(); it.current(); ++it ) {
+    int view_count = it.current()->getViewsCount();
+    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
+    for ( int i = 0; i < view_count; i++ )  {
+      if ( activeViewName == views[i]->name() )
+       views[i]->setFocus();
+    }
+  }
+}
diff --git a/src/SalomeApp/SalomeApp_VisualState.h b/src/SalomeApp/SalomeApp_VisualState.h
new file mode 100644 (file)
index 0000000..aa96a83
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/
+//
+#ifndef SALOMEAPP_VISUALSTATE_H
+#define SALOMEAPP_VISUALSTATE_H
+
+#ifdef WIN32
+#pragma warning( disable:4251 )
+#endif
+
+#include "SalomeApp.h"
+
+class SalomeApp_Application;
+
+class SALOMEAPP_EXPORT SalomeApp_VisualState
+{
+public:
+  SalomeApp_VisualState( SalomeApp_Application* );
+  virtual ~SalomeApp_VisualState();
+
+  virtual int            storeState();
+  virtual void           restoreState( int savePoint );
+
+protected:
+  SalomeApp_Application* myApp;
+};
+
+#ifdef WIN32
+#pragma warning( default:4251 )
+#endif
+
+#endif 
index 1d965463bbe49f18d65d797a40a224b19dd6dda3..3fa77b587fbd3d12c37de96fb63587d61f691dc6 100644 (file)
@@ -59,7 +59,8 @@
     <parameter name="font" value="Helvetic,12" />
   </section>
   <section name="Study">
-    <parameter name="store_positions" value="false" />
+    <parameter name="store_positions"          value="false" />
+    <parameter name="store_visual_state"       value="false" />
   </section>
   <section name="GEOM">
     <parameter name="name"       value="Geometry"/>
index a739779d2805bfbf389326b6cecd7974b7416812..0e484c4e91bfd09f02ee41aa5b28271665c237c4 100644 (file)
@@ -42,6 +42,15 @@ msgstr "&Dump study..."
 msgid "SalomeApp_Application::PRP_DESK_FILE_DUMP_STUDY"
 msgstr "Dumps study to the python script"
 
+msgid "SalomeApp_Application::TOT_DESK_FILE_SAVE_GUI_STATE"
+msgstr "Save GUI state"
+
+msgid "SalomeApp_Application::MEN_DESK_FILE_SAVE_GUI_STATE"
+msgstr "Save GUI state..."
+
+msgid "SalomeApp_Application::PRP_DESK_FILE_SAVE_GUI_STATE"
+msgstr "Saves current state of viewers, displayed objects, etc."
+
 msgid "SalomeApp_Application::TOT_DESK_FILE_LOAD_SCRIPT"
 msgstr "Load python script"
 
@@ -102,6 +111,17 @@ msgstr "Activate Module"
 msgid "SalomeApp_Application::MEN_DELETE_INVALID_REFERENCE"
 msgstr "Delete Invalid Reference"
 
+msgid "SalomeApp_Application::PREF_STORE_VISUAL_STATE"
+msgstr "Store/restore last GUI state"
+
+//=======================================================================================
+
+msgid "PUBLISH_IN_STUDY"
+msgstr "Publish in study"
+
+msgid "SAVE_GUI_STATE"
+msgstr "Save GUI state"
+
 //=======================================================================================
 
 msgid "SalomeApp_Application::MEN_WINDOWS_NEW"
@@ -190,3 +210,25 @@ msgstr "Publish in study"
 msgid "SalomeApp_Application::WRN_DUMP_STUDY_FAILED"
 msgstr "Dump study failed"
 
+msgid "SAVE_POINT_OBJECT_TOOLTIP"
+msgstr "Saved GUI state: %1"
+
+msgid "SAVE_POINT_DEF_NAME"
+msgstr "GUI state: "
+
+msgid "SAVE_POINT_ROOT_TOOLTIP"
+msgstr "Persistent GUI states"
+
+msgid "SAVE_POINT_ROOT_NAME"
+msgstr "GUI states"
+
+//=======================================================================================
+
+msgid "SalomeApp_Application::MEN_RESTORE_VS"
+msgstr "Restore"
+
+msgid "SalomeApp_Application::MEN_RENAME_VS"
+msgstr "Rename"
+
+msgid "SalomeApp_Application::MEN_DELETE_VS"
+msgstr "Delete"
index 41869b4d3a234262345768a0a0f8b56ad555010e..1a9662eea467dccda36069ff6ecb7a04ef3199bd 100755 (executable)
@@ -213,3 +213,27 @@ CORBA::Long SALOME_Session_i::GetActiveStudyId()
   }
   return aStudyId;
 }
+
+bool SALOME_Session_i::restoreVisualState(CORBA::Long theSavePoint)
+{
+  class TEvent: public SALOME_Event {
+    int _savePoint;
+  public:
+    TEvent(int savePoint) { _savePoint = savePoint; }
+    virtual void Execute() {
+      SUIT_Study* study = SUIT_Session::session()->activeApplication()->activeStudy();
+      if ( study ) {
+       study->restoreState(_savePoint);
+      }
+    }
+  };
+  
+  if(SUIT_Session::session() && SUIT_Session::session()->activeApplication() ) {
+    SUIT_Study* study = SUIT_Session::session()->activeApplication()->activeStudy();
+    if(!study) SUIT_Session::session()->activeApplication()->createEmptyStudy();      
+    ProcessVoidEvent( new TEvent(theSavePoint) );
+    return true;
+  }
+  return false;
+}
index c9815a42d6a602fa7b01f2321ae9df9d30982f17..6a7f403615d2303602c9a2b84a1bc53d3f307fc1 100755 (executable)
@@ -67,6 +67,9 @@ public:
   
   void ping(){};
 
+  //! Restors a visual state of the study at theSavePoint
+  bool restoreVisualState(CORBA::Long theSavePoint);
+
 protected:
 
   //! Naming service interface
index d4500095a314523e6bee492b6484f8b5280d5e92..14459080395a8d0d7d87ecde8075d59c494ae263 100755 (executable)
@@ -559,3 +559,54 @@ QImage VTKViewer_ViewWindow::dumpView()
   QPixmap px = QPixmap::grabWindow( myRenderWindow->winId() );
   return px.convertToImage();
 }
+
+/*! The method returns the visual parameters of this view as a formated string
+ */
+QString VTKViewer_ViewWindow::getVisualParameters()
+{
+  double pos[3], focalPnt[3], viewUp[3], parScale, scale[3];
+
+  vtkCamera* camera = myRenderer->GetActiveCamera();
+  camera->GetPosition( pos );
+  camera->GetFocalPoint( focalPnt );
+  camera->GetViewUp( viewUp );
+  parScale = camera->GetParallelScale();
+  GetScale( scale );
+
+  QString retStr;
+  retStr.sprintf( "%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e", 
+                 pos[0], pos[1], pos[2], focalPnt[0], focalPnt[1], focalPnt[2], viewUp[0], viewUp[1], 
+                 viewUp[2], parScale, scale[0], scale[1], scale[2] );
+  return retStr;
+}
+
+/* The method restors visual parameters of this view from a formated string
+ */
+void VTKViewer_ViewWindow::setVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = QStringList::split( '*', parameters, true );
+  if ( paramsLst.size() == 13 ) {
+    double pos[3], focalPnt[3], viewUp[3], parScale, scale[3];
+    pos[0] = paramsLst[0].toDouble();
+    pos[1] = paramsLst[1].toDouble();
+    pos[2] = paramsLst[2].toDouble();
+    focalPnt[0] = paramsLst[3].toDouble();
+    focalPnt[1] = paramsLst[4].toDouble();
+    focalPnt[2] = paramsLst[5].toDouble();
+    viewUp[0] = paramsLst[6].toDouble();
+    viewUp[1] = paramsLst[7].toDouble();
+    viewUp[2] = paramsLst[8].toDouble();
+    parScale = paramsLst[9].toDouble();
+    scale[0] = paramsLst[10].toDouble();
+    scale[1] = paramsLst[11].toDouble();
+    scale[2] = paramsLst[12].toDouble();
+
+    vtkCamera* camera = myRenderer->GetActiveCamera();
+    camera->SetPosition( pos );
+    camera->SetFocalPoint( focalPnt );
+    camera->SetViewUp( viewUp );
+    camera->SetParallelScale( parScale );
+    myTransform->SetMatrixScale( scale[0], scale[1], scale[2] );
+    myRWInteractor->Render();
+  }
+}
index 951d96d4cbb7d39632c47385fd2657fcffca2436..5c02b79a6ecdabda7a25679a9522553b174c777a 100755 (executable)
@@ -70,6 +70,9 @@ public:
   void AddActor( VTKViewer_Actor*, bool update = false );
   void RemoveActor( VTKViewer_Actor*, bool update = false);
 
+  virtual QString   getVisualParameters();
+  virtual void      setVisualParameters( const QString& parameters );
+
 public slots:
   void onFrontView();
   void onBackView();