Salome HOME
refs #417: showing new objects
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_VisualStateOp.cxx
1 // Copyright (C) 2007-2013  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
23 #include "HYDROGUI_VisualStateOp.h"
24
25 #include "HYDROGUI_Module.h"
26 #include "HYDROGUI_Tool.h"
27 #include "HYDROGUI_UpdateFlags.h"
28
29 #include <HYDROData_Document.h>
30 #include <HYDROData_VisualState.h>
31
32 #include <GraphicsView_Viewer.h>
33
34 #include <LightApp_Application.h>
35
36 #include <QtxWorkstack.h>
37
38 #include <STD_TabDesktop.h>
39
40 #include <SUIT_Desktop.h>
41 #include <SUIT_ViewManager.h>
42 #include <SUIT_ViewWindow.h>
43
44 #include <QApplication>
45
46 HYDROGUI_VisualStateOp::HYDROGUI_VisualStateOp( HYDROGUI_Module* theModule,
47                                                 const bool theIsLoad )
48 : HYDROGUI_Operation( theModule ),
49   myIsLoad( theIsLoad )
50 {
51   setName( theIsLoad ? tr( "LOAD_VISUAL_STATE" ) : tr( "SAVE_VISUAL_STATE" ) );
52 }
53
54 HYDROGUI_VisualStateOp::~HYDROGUI_VisualStateOp()
55 {
56 }
57
58 void HYDROGUI_VisualStateOp::startOperation()
59 {
60   HYDROGUI_Operation::startOperation();
61
62   if( !myIsLoad )
63     startDocOperation();
64
65   bool aResult = false;
66   if( myIsLoad )
67     aResult = loadVisualState();
68   else
69     aResult = saveVisualState();
70
71   if( aResult )
72   {
73     if( !myIsLoad )
74       commitDocOperation();
75     commit();
76   }
77   else
78   {
79     if( !myIsLoad )
80       abortDocOperation();
81     abort();
82   }
83 }
84
85 bool HYDROGUI_VisualStateOp::saveVisualState()
86 {
87   LightApp_Application* anApp = module()->getApp();
88
89   Handle(HYDROData_VisualState) aVisualState =
90     Handle(HYDROData_VisualState)::DownCast( HYDROGUI_Tool::GetSelectedObject( module() ) );
91   if( aVisualState.IsNull() )
92   {
93     // Create new visual state
94     aVisualState = Handle(HYDROData_VisualState)::DownCast( doc()->CreateObject( KIND_VISUAL_STATE ) );
95     if( aVisualState.IsNull() )
96       return false;
97
98     QString aName = HYDROGUI_Tool::GenerateObjectName( module(), tr( "DEFAULT_VISUAL_STATE_NAME" ) );
99     aVisualState->SetName( aName );
100   }
101
102   // Store parameters.
103   PropertyMap aPropertyMap;
104
105   // A. Setting unique names for view windows in order to save this view inside
106   // workstack's structure (see below). On restore the views with the same names will
107   // be placed to the same place inside the workstack's splitters.
108   ViewManagerList aViewManagerList;
109   anApp->viewManagers( aViewManagerList );
110   nameViewWindows( aViewManagerList );
111
112   // B. Store active window.
113   if( SUIT_ViewWindow* aViewWindow = anApp->desktop()->activeWindow() )
114     setVisualProperty( aPropertyMap, "AP_ACTIVE_VIEW", aViewWindow->objectName() );
115
116   // C. Store view properties.
117   int aViewerId = 0;
118   QListIterator<SUIT_ViewManager*> anIter( aViewManagerList );
119   while( anIter.hasNext() )
120   {
121     if( SUIT_ViewManager* aViewManager = anIter.next() )
122     {
123       size_t aViewId = (size_t)aViewManager->getViewModel();
124       if( SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView() )
125       {
126         QString aType = aViewManager->getType();
127         QString aViewerEntry = QString( "%1_%2" ).arg( aType ).arg( ++aViewerId );
128         setVisualProperty( aPropertyMap, "AP_VIEWERS_LIST", aViewerEntry, true );
129
130         setVisualProperty( aPropertyMap, aViewerEntry, aViewWindow->windowTitle(), true );
131         setVisualProperty( aPropertyMap, aViewerEntry, aViewWindow->getVisualParameters(), true );
132
133         // C1. Store parameters of presentations.
134         HYDROData_SequenceOfObjects aSeq;
135         if( aType == GraphicsView_Viewer::Type() )
136           HYDROGUI_Tool::GetPrsSubObjects( module(), aSeq );
137
138         for( int anObjIndex = 1, aLength = aSeq.Length(); anObjIndex <= aLength; anObjIndex++ )
139         {
140           Handle(HYDROData_Entity) anObject = aSeq.Value( anObjIndex );
141           if( !anObject.IsNull() )
142           {
143             // Format: "Name|Visibility[|CoordX|CoordY]"
144             QString aParameters = anObject->GetName();
145
146             int aVisibility = (int)( module()->isObjectVisible( aViewId, anObject ) );
147             aParameters.append( QString( "|%1" ).arg( aVisibility ) );
148
149             setVisualProperty( aPropertyMap, aViewerEntry, aParameters, true );
150           }
151         }
152       }
153     }
154   }
155
156   // D. Store split areas.
157   if( anApp->desktop()->inherits( "STD_TabDesktop" ) )
158   {
159     QtxWorkstack* aWorkstack = ( (STD_TabDesktop*)anApp->desktop() )->workstack();
160     QByteArray aWorkstackState = aWorkstack->saveState( 0 );
161     QString aWorkstackInfo = aWorkstackState.toHex();
162     setVisualProperty( aPropertyMap, "AP_WORKSTACK_INFO", aWorkstackInfo );
163   }
164
165   // E. Store module preferences.
166   //ouv: currently, nothing to do
167
168   QString aState = encodePropertyMap( aPropertyMap );
169   //printf( "--- SetState -----------\n" );
170   //printf( "%s\n", qPrintable( aState ) );
171   //printf( "------------------------\n" );
172   aVisualState->SetState( aState.toStdString() );
173
174   module()->update( UF_Model );
175
176   return true;
177 }
178
179 bool HYDROGUI_VisualStateOp::loadVisualState()
180 {
181   LightApp_Application* anApp = module()->getApp();
182
183   Handle(HYDROData_VisualState) aVisualState =
184     Handle(HYDROData_VisualState)::DownCast( HYDROGUI_Tool::GetSelectedObject( module() ) );
185   if( aVisualState.IsNull() )
186     return false;
187
188   QString aState = QString::fromStdString( aVisualState->GetState() );
189   //printf( "--- GetState -----------\n" );
190   //printf( "%s\n", qPrintable( aState ) );
191   //printf( "------------------------\n" );
192   PropertyMap aPropertyMap = decodePropertyMap( aState );
193
194   // Restore parameters.
195
196   // Preparation. Remove the existing viewers.
197   anApp->clearViewManagers();
198
199   // E. Restore module preferences
200   //ouv: currently, nothing to do
201
202   // C. Restore view properties (step 1).
203   QMap<SUIT_ViewWindow*, QString> aViewParameters;
204   int aNbViewers = nbVisualProperties( aPropertyMap, "AP_VIEWERS_LIST" );
205   for( int anIndex = 0; anIndex < aNbViewers; anIndex++ )
206   {
207     QString aViewerEntry = getVisualProperty( aPropertyMap, "AP_VIEWERS_LIST", anIndex );
208     QString aType = aViewerEntry.section( '_', 0, -2 );
209     QString aViewerId = aViewerEntry.section( '_', -1 ); // unused
210     if( SUIT_ViewManager* aViewManager = anApp->createViewManager( aType ) )
211     {
212       size_t aViewId = (size_t)aViewManager->getViewModel();
213       if( SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView() )
214       {
215         // Wait until the window is really shown. This step fixes MANY bugs.
216         //while( !aViewManager->isVisible() )
217         //  qApp->processEvents();
218
219         int aNbViewerProps = nbVisualProperties( aPropertyMap, aViewerEntry );
220
221         aViewWindow->setWindowTitle( getVisualProperty( aPropertyMap, aViewerEntry, 0 ) );
222
223         // Parameters of view windows are restoring after the workstack (see below).
224         aViewParameters[ aViewWindow ] = getVisualProperty( aPropertyMap, aViewerEntry, 1 );
225
226         // C1. Restore parameters of presentations.
227         QMap< QString, QStringList > anObject2ParametersMap;
228         for( int aPropIndex1 = 2; aPropIndex1 < aNbViewerProps; aPropIndex1++ )
229         {
230           QString aProperty = getVisualProperty( aPropertyMap, aViewerEntry, aPropIndex1 );
231           QStringList aParameters = aProperty.split( "|" );
232           if( aParameters.count() > 1 )
233           {
234             QString aName = aParameters.front();
235             aParameters.pop_front();
236             anObject2ParametersMap[ aName ] = aParameters;
237           }
238         }
239
240         HYDROData_SequenceOfObjects aSeq;
241         if( aType == GraphicsView_Viewer::Type() )
242           HYDROGUI_Tool::GetPrsSubObjects( module(), aSeq );
243
244         for( int anObjIndex = 1, aLength = aSeq.Length(); anObjIndex <= aLength; anObjIndex++ )
245         {
246           Handle(HYDROData_Entity) anObject = aSeq.Value( anObjIndex );
247           if( !anObject.IsNull() )
248           {
249             QString aName = anObject->GetName();
250             if( anObject2ParametersMap.find( aName ) != anObject2ParametersMap.end() )
251             {
252               QStringList aParameters = anObject2ParametersMap[ aName ];
253               int aParamCount = aParameters.count();
254               QVector<bool> anIsOk( aParamCount, false );
255
256               int aParamIndex = -1;
257               if( aParamCount - aParamIndex - 1 >= 1 )
258               {
259                 bool anIsVisible = aParameters[ aParamIndex ].toInt( &anIsOk[ ++aParamIndex ] );
260                 if( anIsOk[ 0 ] )
261                   module()->setObjectVisible( aViewId, anObject, anIsVisible );
262               }
263             }
264           }
265         }
266       }
267     }
268   }
269
270   // A. Setting unique names for view windows in order to restore positions of view windows inside
271   // workstack's structure (see below). During save the same naming algorithm was used,
272   // so the same views will get the same names.
273   ViewManagerList aViewManagerList;
274   anApp->viewManagers( aViewManagerList );
275   nameViewWindows( aViewManagerList );
276
277   qApp->processEvents();
278
279   // D. Restore split areas.
280   QtxWorkstack* aWorkstack = 0;
281   if( anApp->desktop()->inherits( "STD_TabDesktop" ) )
282   {
283     if( aWorkstack = ((STD_TabDesktop*)anApp->desktop())->workstack() )
284     {
285       QString aWorkstackInfo = getVisualProperty( aPropertyMap, "AP_WORKSTACK_INFO" );
286       QByteArray aWorkstackState = QByteArray::fromHex( aWorkstackInfo.toLatin1() );
287       aWorkstack->restoreState( aWorkstackState, 0 );
288     }
289   }
290
291   qApp->processEvents();
292
293   // C. Restore view properties (step 2).
294   // B. Restore active window. (currently doesn't work)
295   QString anActiveViewName = getVisualProperty( aPropertyMap, "AP_ACTIVE_VIEW" );
296   QMap<SUIT_ViewWindow*, QString>::Iterator aMapIter;
297   for( aMapIter = aViewParameters.begin(); aMapIter != aViewParameters.end(); ++aMapIter )
298   {
299     if( SUIT_ViewWindow* aViewWindow = aMapIter.key() )
300     {
301       aViewWindow->setVisualParameters( aMapIter.value() );
302       if( anActiveViewName == aViewWindow->objectName() )
303         if( aWorkstack )
304           aWorkstack->setActiveWindow( aViewWindow );
305     }
306   }
307
308   module()->update( UF_Viewer );
309
310   return true;
311 }
312
313 void HYDROGUI_VisualStateOp::nameViewWindows( const ViewManagerList& theList )
314 {
315   QMap<QString, int> aViewersCounter;
316   for( ViewManagerList::const_iterator anIter = theList.begin(); anIter != theList.end(); ++anIter )
317   {
318     SUIT_ViewManager* aViewManager = *anIter;
319     if( !aViewManager )
320       continue;
321
322     int aViewCount = aViewManager->getViewsCount();
323     QString aType = aViewManager->getType();
324     if( !aViewCount )
325       continue;
326
327     if( !aViewersCounter.contains( aType ) )
328       aViewersCounter.insert( aType, 0 );
329
330     int& aViewerId = aViewersCounter[ aType ];
331
332     QVector<SUIT_ViewWindow*> aViews = aViewManager->getViews();
333     for( int i = 0; i < aViewCount; i++ )
334     {
335       QString aName = QString( "%1_%2_%3" ).arg( aType ).arg( aViewerId ).arg( i );
336       aViews[i]->setObjectName( aName );
337     }
338     aViewerId++;
339   }
340 }
341
342 QString HYDROGUI_VisualStateOp::encodePropertyMap( const PropertyMap& thePropertyMap )
343 {
344   QStringList aPropertyDataStringList;
345   PropertyMapIterator anIter( thePropertyMap );
346   while( anIter.hasNext() )
347   {
348     QString aPropertyName = anIter.next().key();
349     QStringList aPropertyData = anIter.value();
350
351     if( !aPropertyData.isEmpty() )
352     {
353       aPropertyData.prepend( aPropertyName );
354       QString aPropertyDataString = aPropertyData.join( "||" );
355       aPropertyDataStringList.append( aPropertyDataString );
356     }
357   }
358
359   QString aResult = aPropertyDataStringList.join( "|||" );
360   return aResult;
361 }
362
363 HYDROGUI_VisualStateOp::PropertyMap
364 HYDROGUI_VisualStateOp::decodePropertyMap( const QString& theString )
365 {
366   PropertyMap aPropertyMap;
367   QStringList aPropertyDataStringList = theString.split( "|||" );
368   QStringListIterator anIter( aPropertyDataStringList );
369   while( anIter.hasNext() )
370   {
371     QString aPropertyDataString = anIter.next();
372     QStringList aPropertyData = aPropertyDataString.split( "||" );
373     if( aPropertyData.count() >= 2 )
374     {
375       QString aPropertyName = aPropertyData.front();
376       aPropertyData.pop_front();
377       aPropertyMap[ aPropertyName ] = aPropertyData;
378     }
379   }
380   return aPropertyMap;
381 }
382
383 void HYDROGUI_VisualStateOp::setVisualProperty( PropertyMap& thePropertyMap,
384                                                 const QString& thePropertyName,
385                                                 const QString& thePropertyData,
386                                                 const bool theIsAppend )
387 {
388   QStringList& aPropertyDataList = thePropertyMap[ thePropertyName ];
389   if( !theIsAppend )
390     aPropertyDataList.clear();
391   aPropertyDataList.append( thePropertyData );
392 }
393
394 QString HYDROGUI_VisualStateOp::getVisualProperty( const PropertyMap& thePropertyMap,
395                                                    const QString& thePropertyName,
396                                                    int theIndex )
397 {
398   PropertyMap::const_iterator anIter = thePropertyMap.find( thePropertyName );
399   if( anIter != thePropertyMap.end() )
400   {
401     const QStringList aPropertyData = anIter.value();
402     if( theIndex >= 0 && theIndex < aPropertyData.count() )
403       return aPropertyData[ theIndex ];
404   }
405   return QString();
406 }
407
408 int HYDROGUI_VisualStateOp::nbVisualProperties( const PropertyMap& thePropertyMap,
409                                                 const QString& thePropertyName )
410 {
411   PropertyMap::const_iterator anIter = thePropertyMap.find( thePropertyName );
412   if( anIter != thePropertyMap.end() )
413   {
414     const QStringList aPropertyData = anIter.value();
415     return aPropertyData.count();
416   }
417   return 0;
418 }