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