Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / SalomeApp / SalomeApp_VisualState.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "SalomeApp_VisualState.h"
23
24 #include "SalomeApp_Module.h"
25 #include "SalomeApp_Study.h"
26 #include "SalomeApp_Application.h"
27
28 //#include <SUIT_ResourceMgr.h>
29 #include <SUIT_ViewManager.h>
30 #include <SUIT_ViewWindow.h>
31 #include <QtxWorkstack.h>
32
33 #include <STD_TabDesktop.h>
34
35 #include <QList>
36 #include <QApplication>
37 #include <QMultiHash>
38
39 #include <SALOMEDSClient_ClientFactory.hxx>//?
40 #include <SALOMEDSClient_IParameters.hxx>//?
41
42 #include <vector>//?
43 #include <string>//?
44
45 /*!
46   Constructor.
47 */
48 SalomeApp_VisualState::SalomeApp_VisualState( SalomeApp_Application* app )
49   : QObject(),
50     myApp( app )
51 {
52 }  
53
54 /*!
55   Destructor.
56 */
57 SalomeApp_VisualState::~SalomeApp_VisualState()
58 {
59 }
60
61 /*!
62   Sets names of all view windows in given list.  This is used
63   in order to apply the same naming algorithm when saving and restoring
64   view windows.  Names of view windows must be the same before saving
65   workstack (splitters) information, and before its restoring! 
66   Naming rule: ViewerType_IndexOfViewerOfThisType_IndexOfViewInThisViewer
67                VTKViewer_0_0
68                OCCViewer_0_0  OCCViewer_0_1  OCCViewer_0_2
69                VTKViewer_1_0
70 */
71 void nameViewWindows( const ViewManagerList& lst )
72 {
73   QMultiHash<QString,int> viewersCounter; // map viewerType - to - index_of_this_viewer_type
74   QListIterator<SUIT_ViewManager*> it(lst);
75   SUIT_ViewManager* aVM = 0;
76   while ( it.hasNext() ) {
77     aVM = it.next();
78     if ( !aVM ) continue;
79
80     int view_count = aVM->getViewsCount();
81     QString vType = aVM->getType();
82     if ( !view_count )
83       continue; //No views is opened in the viewer
84     
85     int viewerID = viewersCounter.value( vType );
86     if ( !viewerID ) {
87       viewerID = 0;
88       viewersCounter.insert( vType, viewerID );
89     }
90     else
91       ++viewerID;
92
93     QVector<SUIT_ViewWindow*> views = aVM->getViews();
94     for ( int i = 0; i < view_count; i++ )  {
95       QString vName = QString( "%1_%2_%3" ).arg( vType ).arg( viewerID ).arg( i );
96       views[i]->setObjectName( vName );
97     }
98   }
99   viewersCounter.clear();
100 }
101
102 /*!
103   Stores the visual parameters of the viewers
104 */
105 int SalomeApp_VisualState::storeState()
106 {
107   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
108   if ( !study )
109     return -1;
110
111   int savePoint = 1;
112   std::vector<int> savePoints = study->getSavePoints();
113   //Calculate a new savePoint number = the last save point number + 1
114   if ( savePoints.size() > 0) 
115     savePoint = savePoints[savePoints.size()-1] + 1;
116
117   _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName(), savePoint );
118   _PTR(IParameters) ip = ClientFactory::getIParameters( ap );
119
120   ViewManagerList lst;
121   myApp->viewManagers( lst );
122
123   // setting unique names for view windows in order to save this view inside 
124   // workstack's structure (see below).  On restore the views with the same names will
125   // be placed to the same place inside the workstack's splitters.
126   nameViewWindows( lst );
127
128   // store active window's name
129   SUIT_ViewWindow* win = myApp->desktop()->activeWindow();  
130   if ( win )
131     ip->setProperty("AP_ACTIVE_VIEW", win->objectName().toStdString() );
132
133   int viewerID = 0;
134   SUIT_ViewManager* vm = 0;
135   QListIterator<SUIT_ViewManager*> it( lst );
136   while ( it.hasNext() ) {
137     vm = it.next();
138     if ( !vm ) continue;
139
140     int view_count = vm->getViewsCount();
141     if ( !view_count ) 
142       continue; //No views is opened in the viewer
143       
144     std::string viewerEntry = QString( "%1_%2" ).arg( vm->getType() ).arg( ++viewerID ).toStdString();
145     ip->append("AP_VIEWERS_LIST", viewerEntry);
146     
147     QVector<SUIT_ViewWindow*> views = vm->getViews();
148     for(int i = 0; i<view_count; i++) {
149       ip->append( viewerEntry, views[i]->windowTitle().toStdString() );
150       ip->append( viewerEntry, views[i]->getVisualParameters().toStdString() );
151     }
152   }
153
154   //Save information about split areas
155   if ( myApp->desktop()->inherits( "STD_TabDesktop" ) ) {
156     QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
157     QString workstackInfo;
158     (*workstack) >> workstackInfo;
159     ip->setProperty( "AP_WORKSTACK_INFO", workstackInfo.toStdString() );
160   }
161   
162   //Save a name of the active module
163   if ( CAM_Module* activeModule = myApp->activeModule() ) 
164     ip->setProperty( "AP_ACTIVE_MODULE", activeModule->moduleName().toStdString() );
165
166   //Store visual parameters of the modules
167   QList<CAM_Module*> mlist; 
168   myApp->modules( mlist );
169   QListIterator<CAM_Module*> itM( mlist );
170   CAM_Module* module = 0;
171   while ( itM.hasNext() ) {
172     module = itM.next();
173     if ( !module ) continue;
174
175     if ( SalomeApp_Module* sModule = dynamic_cast<SalomeApp_Module*>( module ) ) {
176       ip->append( "AP_MODULES_LIST", sModule->moduleName().toStdString() );
177       sModule->storeVisualParameters( savePoint );
178     }
179   }
180
181   // set default name of new savePoint
182   study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );
183   
184   return savePoint;
185 }
186
187 /*!
188   Restores the visual parameters of the viewers
189 */
190 void SalomeApp_VisualState::restoreState(int savePoint)
191 {
192   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
193   if ( !study )
194     return;
195
196   _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName(), savePoint );
197   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
198
199   qApp->installEventFilter( this );
200
201   //Remove all already existent veiwers and their views
202   ViewManagerList lst;
203   myApp->viewManagers( lst );
204   QListIterator<SUIT_ViewManager*> it(lst);
205   while ( it.hasNext() ) {
206     myApp->removeViewManager( it.next() );
207     qApp->processEvents();
208   }
209   //Restore the viewers and view windows
210   int nbViewers = ip->nbValues( "AP_VIEWERS_LIST" );
211   SUIT_ViewWindow* viewWin = 0;
212
213   // parameters of view windows are stored in a map for restoring after restoring of the workstack
214   QMap<SUIT_ViewWindow*, QString> viewersParameters;
215   
216   for ( int i = 0; i < nbViewers; i++ ) {
217     std::string viewerEntry = ip->getValue( "AP_VIEWERS_LIST", i );
218     std::vector<std::string> veiewerParams = ip->parseValue(viewerEntry,'_');
219     std::string type = veiewerParams[0];
220     std::string viewerID = veiewerParams[1];
221     SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
222     if ( !vm ) 
223       continue; //Unknown viewer
224     
225     int nbViews = (ip->nbValues(viewerEntry))/2;
226     
227     //Create nbViews-1 view (-1 because 1 view is created by createViewManager)
228     for ( int i = 1; i< nbViews; i++ ) { 
229       SUIT_ViewWindow* aView = vm->createViewWindow();
230       aView->show();
231     }
232
233     int viewCount = vm->getViewsCount();
234     if (viewCount != nbViews) {
235       printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
236       continue;
237     }
238
239     //Resize the views, set their captions and apply visual parameters.
240     QVector<SUIT_ViewWindow*> views = vm->getViews();  
241     for (int i = 0, j = 0; i<viewCount; i++, j+=2) {
242       viewWin = views[i];
243       if ( !viewWin ) 
244         continue;
245
246       // wait untill the window is really shown.  This step fixes MANY bugs..
247       while ( !vm->isVisible() )
248         qApp->processEvents();
249       
250       viewWin->setWindowTitle(ip->getValue(viewerEntry, j).c_str());
251       
252       //      printf ( "VP for viewWin \"%s\": %s\n", viewerEntry.c_str(), ip->getValue(viewerEntry, j+1).c_str() );
253       viewersParameters[ viewWin ] = ip->getValue(viewerEntry, j+1).c_str();
254       //viewWin->setVisualParameters(ip->getValue(viewerEntry, j+1).c_str());
255     }
256   }
257
258   // restore modules' visual parameters
259   std::vector<std::string> v = ip->getValues("AP_MODULES_LIST");
260   for ( int i = 0; i < v.size(); i++ ) {
261     myApp->activateModule( v[i].c_str() );
262     if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
263       module->restoreVisualParameters( savePoint );
264   }
265
266   // new view windows may have been created in  module->restoreVisualParameters() [GAUSS]
267   // so here we store their visual parameters for later restoring..
268   lst.clear();
269   myApp->viewManagers(lst);
270   QListIterator<SUIT_ViewManager*> itVM( lst );
271   SUIT_ViewManager* aVM = 0;
272   while ( itVM.hasNext() ) {
273     aVM = itVM.next();
274     if ( !aVM ) continue;
275
276     int view_count = aVM->getViewsCount();
277     QVector<SUIT_ViewWindow*> views = aVM->getViews();
278     for ( int i = 0; i < view_count; i++ ) {
279       if ( !viewersParameters.contains( views[i] ) ) {
280         viewersParameters[ views[i] ] = views[i]->getVisualParameters();
281         //      printf ( "store VP for viewWin \"%s\": %s\n", views[i]->name(), views[i]->getVisualParameters().toLatin1().constData() );
282       }
283     }
284   }  
285
286   // activate module that was active on save
287   QString activeModuleName( ip->getProperty("AP_ACTIVE_MODULE" ).c_str() );
288   if ( !activeModuleName.isEmpty() ) 
289     myApp->activateModule( activeModuleName );
290
291   // setting unique names for view windows in order to restore positions of view windows inside 
292   // workstack's structure (see below).  During save the same naming algorithm was used, 
293   // so the same views will get the same names.
294   nameViewWindows( lst );
295
296   // restore workstack parameters.  should be done after module's restoreVisualParameters(), because
297   // some modules can create their own viewers (like VISU creates GaussViewers)
298   if ( myApp->desktop()->inherits( "STD_TabDesktop" ) ) {
299     QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
300     (*workstack) << ip->getProperty( "AP_WORKSTACK_INFO" ).c_str();
301   }
302
303   // restore visual parameters of view windows.  it must be done AFTER restoring workstack.
304   // also set active view
305   std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
306   QMap<SUIT_ViewWindow*, QString>::Iterator mapIt;
307   for ( mapIt = viewersParameters.begin(); mapIt != viewersParameters.end(); ++mapIt ) {
308     mapIt.key()->setVisualParameters( mapIt.value() );
309     if ( activeViewName == mapIt.key()->objectName().toStdString() )
310       mapIt.key()->setFocus();
311   }
312
313   qApp->removeEventFilter( this );
314   
315   //  for ( it.toFirst(); it.current(); ++it ) {
316   //    int view_count = it.current()->getViewsCount();
317   //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
318   //    for ( int i = 0; i < view_count; i++ )
319   //      views[i]->setVisualParameters( viewersParameters[ views[i]->name() ] );
320   //  }
321
322   // set focus to previously saved active view window
323   //  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
324   //  for ( it.toFirst(); it.current(); ++it ) {
325   //    int view_count = it.current()->getViewsCount();
326   //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
327   //    for ( int i = 0; i < view_count; i++ )  {
328   //      if ( activeViewName == views[i]->name() )
329   //    views[i]->setFocus();
330   //    }
331   //  }
332 }
333
334 /*!
335   Custom event filter
336 */
337 bool SalomeApp_VisualState::eventFilter( QObject* o, QEvent* e )
338 {
339   // eat keyboard and mouse events
340   QEvent::Type aType = e->type();
341   if ( aType == QEvent::MouseButtonDblClick ||
342        aType == QEvent::MouseButtonPress ||
343        aType == QEvent::MouseButtonRelease ||
344        aType == QEvent::MouseMove ||
345        aType == QEvent::KeyPress ||
346        aType == QEvent::KeyRelease )
347     return true;
348   
349   return QObject::eventFilter( o, e );
350 }