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