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