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