Salome HOME
Merge branch V7_3_1_BR
[modules/gui.git] / src / SalomeApp / SalomeApp_VisualState.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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
23 #include "SalomeApp_VisualState.h"
24
25 #include "SalomeApp_Module.h"
26 #include "SalomeApp_Study.h"
27 #include "SalomeApp_Application.h"
28
29 //#include <SUIT_ResourceMgr.h>
30 #include <SUIT_ViewManager.h>
31 #include <SUIT_ViewWindow.h>
32 #include <QtxWorkstack.h>
33
34 #include <STD_TabDesktop.h>
35
36 #include <QList>
37 #include <QApplication>
38 #include <QMultiHash>
39
40 #include <SALOMEDSClient_ClientFactory.hxx>//?
41 #include <SALOMEDSClient_IParameters.hxx>//?
42
43 #include <vector>//?
44 #include <string>//?
45 #include <cstdio>
46
47 /*!
48   Constructor.
49 */
50 SalomeApp_VisualState::SalomeApp_VisualState( SalomeApp_Application* app )
51   : QObject(),
52     myApp( app )
53 {
54 }
55
56 /*!
57   Destructor.
58 */
59 SalomeApp_VisualState::~SalomeApp_VisualState()
60 {
61 }
62
63 /*!
64   Sets names of all view windows in given list.  This is used
65   in order to apply the same naming algorithm when saving and restoring
66   view windows.  Names of view windows must be the same before saving
67   workstack (splitters) information, and before its restoring!
68   Naming rule: ViewerType_IndexOfViewerOfThisType_IndexOfViewInThisViewer
69                VTKViewer_0_0
70                OCCViewer_0_0  OCCViewer_0_1  OCCViewer_0_2
71                VTKViewer_1_0
72 */
73 void nameViewWindows( const ViewManagerList& lst )
74 {
75   QMap<QString, int> viewersCounter;
76   for ( QList<SUIT_ViewManager*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
77   {
78     SUIT_ViewManager* aVM = *it;
79     if ( !aVM )
80       continue;
81
82     int view_count = aVM->getViewsCount();
83     QString vType = aVM->getType();
84     if ( !view_count )
85       continue; //No views is opened in the viewer
86
87     if ( !viewersCounter.contains( vType ) )
88       viewersCounter.insert( vType, 0 );
89
90     int& viewerID = viewersCounter[vType];
91
92     QVector<SUIT_ViewWindow*> views = aVM->getViews();
93     for ( int i = 0; i < view_count; i++ )
94     {
95       QString vName = QString( "%1_%2_%3" ).arg( vType ).arg( viewerID ).arg( i );
96       views[i]->setObjectName( vName );
97     }
98     viewerID++;
99   }
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   // unlock study if it is locked
112   bool aLocked = study->studyDS()->GetProperties()->IsLocked();
113   if (aLocked) study->studyDS()->GetProperties()->SetLocked(false);
114
115   int savePoint = 1;
116   std::vector<int> savePoints = study->getSavePoints();
117   //Calculate a new savePoint number = the last save point number + 1
118   if ( savePoints.size() > 0)
119     savePoint = savePoints[savePoints.size()-1] + 1;
120
121   _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(), 
122                                                                        savePoint );
123   _PTR(IParameters) ip = ClientFactory::getIParameters( ap );
124
125   ViewManagerList lst;
126   myApp->viewManagers( lst );
127
128   // setting unique names for view windows in order to save this view inside
129   // workstack's structure (see below).  On restore the views with the same names will
130   // be placed to the same place inside the workstack's splitters.
131   nameViewWindows( lst );
132
133   // store active window's name
134   SUIT_ViewWindow* win = myApp->desktop()->activeWindow();
135   if ( win )
136     ip->setProperty("AP_ACTIVE_VIEW", win->objectName().toStdString() );
137
138   int viewerID = 0;
139   SUIT_ViewManager* vm = 0;
140   QListIterator<SUIT_ViewManager*> it( lst );
141   while ( it.hasNext() ) {
142     vm = it.next();
143     if ( !vm ) continue;
144
145     int view_count = vm->getViewsCount();
146     if ( !view_count )
147       continue; //No views is opened in the viewer
148
149     std::string viewerEntry = QString( "%1_%2" ).arg( vm->getType() ).arg( ++viewerID ).toStdString();
150     ip->append("AP_VIEWERS_LIST", viewerEntry);
151
152     QVector<SUIT_ViewWindow*> views = vm->getViews();
153     for(int i = 0; i<view_count; i++) {
154       ip->append( viewerEntry, views[i]->windowTitle().toStdString() );
155       ip->append( viewerEntry, views[i]->getVisualParameters().toStdString() );
156     }
157   }
158
159   //Save information about split areas
160   if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
161   {
162     QString workstackInfo;
163     QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
164     QByteArray geomState = workstack->saveState( 0 );
165     ip->setProperty( "AP_WORKSTACK_INFO", QString( geomState.toHex() ).toStdString() );
166   }
167
168   //Save a name of the active module
169   if ( CAM_Module* activeModule = myApp->activeModule() )
170     ip->setProperty( "AP_ACTIVE_MODULE", activeModule->moduleName().toStdString() );
171
172   //Store visual parameters of the modules
173   QList<CAM_Module*> mlist;
174   myApp->modules( mlist );
175   QListIterator<CAM_Module*> itM( mlist );
176   CAM_Module* module = 0;
177   while ( itM.hasNext() ) {
178     module = itM.next();
179     if ( !module ) continue;
180
181     if ( SalomeApp_Module* sModule = dynamic_cast<SalomeApp_Module*>( module ) ) {
182       ip->append( "AP_MODULES_LIST", sModule->moduleName().toStdString() );
183       sModule->storeVisualParameters( savePoint );
184     }
185   }
186
187   // set default name of new savePoint
188   study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );
189
190   if (aLocked) study->studyDS()->GetProperties()->SetLocked(true);
191
192   return savePoint;
193 }
194
195 /*!
196   Restores the visual parameters of the viewers
197 */
198 void SalomeApp_VisualState::restoreState(int savePoint)
199 {
200   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
201   if ( !study )
202     return;
203
204   _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(),
205                                                                        savePoint );
206   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
207
208   qApp->installEventFilter( this );
209
210   //Remove all already existent veiwers and their views
211   //myApp->clearViewManagers();
212   myApp->clearKnownViewManagers();
213
214   //Restore the viewers and view windows
215   int nbViewers = ip->nbValues( "AP_VIEWERS_LIST" );
216   SUIT_ViewWindow* viewWin = 0;
217
218   // parameters of view windows are stored in a map for restoring after restoring of the workstack
219   QMap<SUIT_ViewWindow*, QString> viewersParameters;
220
221   for ( int i = 0; i < nbViewers; i++ )
222   {
223     std::string viewerEntry = ip->getValue( "AP_VIEWERS_LIST", i );
224     std::vector<std::string> veiewerParams = ip->parseValue(viewerEntry,'_');
225     std::string type = veiewerParams[0];
226     std::string viewerID = veiewerParams[1];
227     SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
228     if ( !vm )
229       continue; //Unknown viewer
230
231     int nbViews = (ip->nbValues(viewerEntry))/2;
232
233     //Create nbViews-1 view (-1 because 1 view is created by createViewManager)
234     for ( int i = 1; i< nbViews; i++ )
235     {
236       SUIT_ViewWindow* aView = vm->createViewWindow();
237       aView->show();
238     }
239
240     int viewCount = vm->getViewsCount();
241     if ( viewCount != nbViews )
242     {
243       printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
244       continue;
245     }
246
247     //Resize the views, set their captions and apply visual parameters.
248     QVector<SUIT_ViewWindow*> views = vm->getViews();
249     for ( int i = 0, j = 0; i<viewCount; i++, j+=2 )
250     {
251       viewWin = views[i];
252       if ( !viewWin )
253         continue;
254
255       // wait untill the window is really shown.  This step fixes MANY bugs..
256       //      while ( !vm->isVisible() )
257       //        qApp->processEvents();
258
259       viewWin->setWindowTitle( ip->getValue( viewerEntry, j ).c_str() );
260
261       //      printf ( "VP for viewWin \"%s\": %s\n", viewerEntry.c_str(), ip->getValue(viewerEntry, j+1).c_str() );
262       viewersParameters[ viewWin ] = ip->getValue( viewerEntry, j + 1 ).c_str();
263       //viewWin->setVisualParameters(ip->getValue(viewerEntry, j+1).c_str());
264     }
265   }
266
267   qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );
268
269   // restore modules' visual parameters
270   std::vector<std::string> v = ip->getValues( "AP_MODULES_LIST" );
271   for ( int i = 0; i < v.size(); i++ )
272   {
273     myApp->activateModule( v[i].c_str() );
274     if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
275       module->restoreVisualParameters( savePoint );
276   }
277
278   // new view windows may have been created in  module->restoreVisualParameters() [GAUSS]
279   // so here we store their visual parameters for later restoring..
280   QList<SUIT_ViewManager*> lst;
281   myApp->viewManagers( lst );
282   for ( QList<SUIT_ViewManager*>::iterator itVM = lst.begin(); itVM != lst.end(); ++itVM )
283   {
284     SUIT_ViewManager* aVM = *itVM;
285     if ( !aVM )
286       continue;
287
288     int view_count = aVM->getViewsCount();
289     QVector<SUIT_ViewWindow*> views = aVM->getViews();
290     for ( int i = 0; i < view_count; i++ )
291     {
292       if ( !viewersParameters.contains( views[i] ) )
293       {
294         viewersParameters[ views[i] ] = views[i]->getVisualParameters();
295         //      printf ( "store VP for viewWin \"%s\": %s\n", views[i]->name(), views[i]->getVisualParameters().toLatin1().constData() );
296       }
297     }
298   }
299
300   // activate module that was active on save
301   QString activeModuleName( ip->getProperty("AP_ACTIVE_MODULE" ).c_str() );
302   if ( !activeModuleName.isEmpty() )
303     myApp->activateModule( activeModuleName );
304
305   // setting unique names for view windows in order to restore positions of view windows inside
306   // workstack's structure (see below).  During save the same naming algorithm was used,
307   // so the same views will get the same names.
308   nameViewWindows( lst );
309
310   qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );
311
312   // restore workstack parameters.  should be done after module's restoreVisualParameters(), because
313   // some modules can create their own viewers (like VISU creates GaussViewers)
314   if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
315   {
316     QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
317     workstack->restoreState( QByteArray::fromHex( QByteArray( ip->getProperty( "AP_WORKSTACK_INFO" ).c_str() ) ), 0 );
318   }
319
320   // restore visual parameters of view windows.  it must be done AFTER restoring workstack.
321   // also set active view
322   std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
323   QMap<SUIT_ViewWindow*, QString>::Iterator mapIt;
324   for ( mapIt = viewersParameters.begin(); mapIt != viewersParameters.end(); ++mapIt ) {
325     mapIt.key()->setVisualParameters( mapIt.value() );
326     if ( activeViewName == mapIt.key()->objectName().toStdString() )
327       mapIt.key()->setFocus();
328   }
329
330   qApp->removeEventFilter( this );
331
332   //  for ( it.toFirst(); it.current(); ++it ) {
333   //    int view_count = it.current()->getViewsCount();
334   //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
335   //    for ( int i = 0; i < view_count; i++ )
336   //      views[i]->setVisualParameters( viewersParameters[ views[i]->name() ] );
337   //  }
338
339   // set focus to previously saved active view window
340   //  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
341   //  for ( it.toFirst(); it.current(); ++it ) {
342   //    int view_count = it.current()->getViewsCount();
343   //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
344   //    for ( int i = 0; i < view_count; i++ )  {
345   //      if ( activeViewName == views[i]->name() )
346   //    views[i]->setFocus();
347   //    }
348   //  }
349 }
350
351 /*!
352   Custom event filter
353 */
354 bool SalomeApp_VisualState::eventFilter( QObject* o, QEvent* e )
355 {
356   // eat keyboard and mouse events
357   QEvent::Type aType = e->type();
358   if ( aType == QEvent::MouseButtonDblClick ||
359        aType == QEvent::MouseButtonPress ||
360        aType == QEvent::MouseButtonRelease ||
361        aType == QEvent::MouseMove ||
362        aType == QEvent::KeyPress ||
363        aType == QEvent::KeyRelease )
364     return true;
365
366   return QObject::eventFilter( o, e );
367 }