Salome HOME
allow auto loading of light modules when opening study file
[modules/gui.git] / src / SalomeApp / SalomeApp_VisualState.cxx
1 // Copyright (C) 2007-2015  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     //DEBTRACE("---");
180     if ( !module ) continue;
181     //DEBTRACE("--- " << module->name().toStdString());
182
183
184     if ( LightApp_Module* lModule = dynamic_cast<LightApp_Module*>( module ) ) {
185       //DEBTRACE("AP_MODULES_LIST append " << lModule->moduleName().toStdString());
186       ip->append( "AP_MODULES_LIST", lModule->moduleName().toStdString() );
187       if ( SalomeApp_Module* sModule = dynamic_cast<SalomeApp_Module*>( module ) )
188         sModule->storeVisualParameters( savePoint );
189     }
190   }
191
192   // set default name of new savePoint
193   study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );
194
195   if (aLocked) study->studyDS()->GetProperties()->SetLocked(true);
196
197   return savePoint;
198 }
199
200 /*!
201   Restores the visual parameters of the viewers
202 */
203 void SalomeApp_VisualState::restoreState(int savePoint)
204 {
205   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
206   if ( !study )
207     return;
208
209   _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(),
210                                                                        savePoint );
211   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
212
213   qApp->installEventFilter( this );
214
215   //Remove all already existent veiwers and their views
216   //myApp->clearViewManagers();
217   myApp->clearKnownViewManagers();
218
219   //Restore the viewers and view windows
220   int nbViewers = ip->nbValues( "AP_VIEWERS_LIST" );
221   SUIT_ViewWindow* viewWin = 0;
222
223   // parameters of view windows are stored in a map for restoring after restoring of the workstack
224   QMap<SUIT_ViewWindow*, QString> viewersParameters;
225
226   for ( int i = 0; i < nbViewers; i++ )
227   {
228     std::string viewerEntry = ip->getValue( "AP_VIEWERS_LIST", i );
229     std::vector<std::string> veiewerParams = ip->parseValue(viewerEntry,'_');
230     std::string type = veiewerParams[0];
231     std::string viewerID = veiewerParams[1];
232     SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
233     if ( !vm )
234       continue; //Unknown viewer
235
236     int nbViews = (ip->nbValues(viewerEntry))/2;
237
238     //Create nbViews-1 view (-1 because 1 view is created by createViewManager)
239     for ( int i = 1; i< nbViews; i++ )
240     {
241       SUIT_ViewWindow* aView = vm->createViewWindow();
242       aView->show();
243     }
244
245     int viewCount = vm->getViewsCount();
246     if ( viewCount != nbViews )
247     {
248       printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
249       continue;
250     }
251
252     //Resize the views, set their captions and apply visual parameters.
253     QVector<SUIT_ViewWindow*> views = vm->getViews();
254     for ( int i = 0, j = 0; i<viewCount; i++, j+=2 )
255     {
256       viewWin = views[i];
257       if ( !viewWin )
258         continue;
259
260       // wait untill the window is really shown.  This step fixes MANY bugs..
261       //      while ( !vm->isVisible() )
262       //        qApp->processEvents();
263
264       viewWin->setWindowTitle( ip->getValue( viewerEntry, j ).c_str() );
265
266       //      printf ( "VP for viewWin \"%s\": %s\n", viewerEntry.c_str(), ip->getValue(viewerEntry, j+1).c_str() );
267       viewersParameters[ viewWin ] = ip->getValue( viewerEntry, j + 1 ).c_str();
268       //viewWin->setVisualParameters(ip->getValue(viewerEntry, j+1).c_str());
269     }
270   }
271
272   qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );
273
274   // restore modules' visual parameters
275   std::vector<std::string> v = ip->getValues( "AP_MODULES_LIST" );
276   for ( int i = 0; i < v.size(); i++ )
277   {
278     myApp->activateModule( v[i].c_str() );
279     if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
280       module->restoreVisualParameters( savePoint );
281   }
282
283   // new view windows may have been created in  module->restoreVisualParameters() [GAUSS]
284   // so here we store their visual parameters for later restoring..
285   QList<SUIT_ViewManager*> lst;
286   myApp->viewManagers( lst );
287   for ( QList<SUIT_ViewManager*>::iterator itVM = lst.begin(); itVM != lst.end(); ++itVM )
288   {
289     SUIT_ViewManager* aVM = *itVM;
290     if ( !aVM )
291       continue;
292
293     int view_count = aVM->getViewsCount();
294     QVector<SUIT_ViewWindow*> views = aVM->getViews();
295     for ( int i = 0; i < view_count; i++ )
296     {
297       if ( !viewersParameters.contains( views[i] ) )
298       {
299         viewersParameters[ views[i] ] = views[i]->getVisualParameters();
300         //      printf ( "store VP for viewWin \"%s\": %s\n", views[i]->name(), views[i]->getVisualParameters().toLatin1().constData() );
301       }
302     }
303   }
304
305   // activate module that was active on save
306   QString activeModuleName( ip->getProperty("AP_ACTIVE_MODULE" ).c_str() );
307   if ( !activeModuleName.isEmpty() )
308     myApp->activateModule( activeModuleName );
309
310   // setting unique names for view windows in order to restore positions of view windows inside
311   // workstack's structure (see below).  During save the same naming algorithm was used,
312   // so the same views will get the same names.
313   nameViewWindows( lst );
314
315   qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );
316
317   // restore workstack parameters.  should be done after module's restoreVisualParameters(), because
318   // some modules can create their own viewers (like VISU creates GaussViewers)
319   if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
320   {
321     QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
322     workstack->restoreState( QByteArray::fromHex( QByteArray( ip->getProperty( "AP_WORKSTACK_INFO" ).c_str() ) ), 0 );
323   }
324
325   // restore visual parameters of view windows.  it must be done AFTER restoring workstack.
326   // also set active view
327   std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
328   QMap<SUIT_ViewWindow*, QString>::Iterator mapIt;
329   for ( mapIt = viewersParameters.begin(); mapIt != viewersParameters.end(); ++mapIt ) {
330     mapIt.key()->setVisualParameters( mapIt.value() );
331     if ( activeViewName == mapIt.key()->objectName().toStdString() )
332       mapIt.key()->setFocus();
333   }
334
335   qApp->removeEventFilter( this );
336
337   //  for ( it.toFirst(); it.current(); ++it ) {
338   //    int view_count = it.current()->getViewsCount();
339   //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
340   //    for ( int i = 0; i < view_count; i++ )
341   //      views[i]->setVisualParameters( viewersParameters[ views[i]->name() ] );
342   //  }
343
344   // set focus to previously saved active view window
345   //  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
346   //  for ( it.toFirst(); it.current(); ++it ) {
347   //    int view_count = it.current()->getViewsCount();
348   //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
349   //    for ( int i = 0; i < view_count; i++ )  {
350   //      if ( activeViewName == views[i]->name() )
351   //    views[i]->setFocus();
352   //    }
353   //  }
354 }
355
356 /*!
357   Custom event filter
358 */
359 bool SalomeApp_VisualState::eventFilter( QObject* o, QEvent* e )
360 {
361   // eat keyboard and mouse events
362   QEvent::Type aType = e->type();
363   if ( aType == QEvent::MouseButtonDblClick ||
364        aType == QEvent::MouseButtonPress ||
365        aType == QEvent::MouseButtonRelease ||
366        aType == QEvent::MouseMove ||
367        aType == QEvent::KeyPress ||
368        aType == QEvent::KeyRelease )
369     return true;
370
371   return QObject::eventFilter( o, e );
372 }