Salome HOME
Editing of calculation zones corrected (Feature #10).
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_CalculationOp.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_CalculationOp.h"
24
25 #include "HYDROGUI_DataModel.h"
26 #include "HYDROGUI_CalculationDlg.h"
27 #include "HYDROGUI_Module.h"
28 #include "HYDROGUI_Tool.h"
29 #include "HYDROGUI_UpdateFlags.h"
30
31 #include <HYDROData_Polyline.h>
32 #include <HYDROData_Iterator.h>
33
34 #include <OCCViewer_ViewManager.h>
35 #include <OCCViewer_ViewModel.h>
36 #include <OCCViewer_ViewWindow.h>
37
38 #include <LightApp_Application.h>
39 #include <LightApp_UpdateFlags.h>
40
41 #include <QApplication>
42
43 HYDROGUI_CalculationOp::HYDROGUI_CalculationOp( HYDROGUI_Module* theModule, bool theIsEdit )
44 : HYDROGUI_Operation( theModule ),
45   myIsEdit( theIsEdit ),
46   myActiveViewManager( NULL ),
47   myPreviewViewManager( NULL )
48 {
49   setName( myIsEdit ? tr( "EDIT_CALCULATION" ) : tr( "CREATE_CALCULATION" ) );
50 }
51
52 HYDROGUI_CalculationOp::~HYDROGUI_CalculationOp()
53 {
54   closePreview();
55 }
56
57 void HYDROGUI_CalculationOp::startOperation()
58 {
59   HYDROGUI_Operation::startOperation();
60
61   HYDROGUI_CalculationDlg* aPanel = 
62     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
63   if ( !aPanel )
64     return;
65
66   mySplittedZones.clear();
67   aPanel->reset();
68
69   QString anObjectName = HYDROGUI_Tool::GenerateObjectName( module(), "Case" );
70
71   QStringList aSelectedZones, aSplittedZones;
72
73   myEditedObject.Nullify();
74   if ( myIsEdit )
75   {
76     myEditedObject = Handle(HYDROData_Calculation)::DownCast( HYDROGUI_Tool::GetSelectedObject( module() ) );
77     if ( !myEditedObject.IsNull() )
78     {
79       anObjectName = myEditedObject->GetName();
80
81       Handle(HYDROData_Polyline) aBoundaryPolyline = myEditedObject->GetBoundaryPolyline();
82       if ( !aBoundaryPolyline.IsNull() )
83       {
84         QString aPolylineName = aBoundaryPolyline->GetName();
85         aPanel->setPolylineName( aPolylineName );
86       }
87
88       HYDROData_SequenceOfObjects aRefZones = myEditedObject->GetZones();
89       HYDROData_SequenceOfObjects::Iterator anIter( aRefZones );
90       for ( ; anIter.More(); anIter.Next() )
91       {
92         Handle(HYDROData_Zone) aRefZone = 
93           Handle(HYDROData_Zone)::DownCast( anIter.Value() );
94         if ( aRefZone.IsNull() )
95           continue;
96
97         QString aRefZoneName = aRefZone->GetName();
98         if ( aRefZoneName.isEmpty() )
99           continue;
100
101         aSelectedZones.append( aRefZoneName );
102       }
103
104       HYDROData_SequenceOfObjects aSplitZones = myEditedObject->GetSplittedZones();
105       anIter.Init( aSplitZones );
106       for ( ; anIter.More(); anIter.Next() )
107       {
108         Handle(HYDROData_Zone) aSplitZone = 
109           Handle(HYDROData_Zone)::DownCast( anIter.Value() );
110         if ( aSplitZone.IsNull() )
111           continue;
112
113         QString aSplitZoneName = aSplitZone->GetName();
114         if ( aSplitZoneName.isEmpty() )
115           continue;
116
117         SplittedZone aSplittedZone;
118         aSplittedZone.SplitData.Path = aSplitZone->GetPainterPath();
119         // aSplittedZone.SplitData.ZoneNames ???
120
121         aSplittedZone.FillingColor = aSplitZone->GetFillingColor();
122         aSplittedZone.BorderColor  = aSplitZone->GetBorderColor();
123
124         aSplittedZone.ZoneName = aSplitZoneName;
125
126         Handle(HYDROData_Polyline) aZonePolyline = aSplitZone->GetPolyline();
127         if ( !aZonePolyline.IsNull() )
128           aSplittedZone.PolylineName = aZonePolyline->GetName();
129
130         aSplittedZone.DataZone = aSplitZone;
131
132         mySplittedZones.append( aSplittedZone );
133
134         aSplittedZones.append( aSplitZoneName );
135       }
136     }
137   }
138
139   // collect information about existing zones
140   QStringList aZones;
141
142   HYDROData_Iterator anIter( doc(), KIND_ZONE );
143   for ( ; anIter.More(); anIter.Next() )
144   {
145     Handle(HYDROData_Zone) aZoneObj = 
146       Handle(HYDROData_Zone)::DownCast( anIter.Current() );
147     if ( aZoneObj.IsNull() )
148       continue;
149
150     QString aZoneName = aZoneObj->GetName();
151     if ( aZoneName.isEmpty() )
152       continue;
153
154     aZones.append( aZoneName );
155   }
156
157   aPanel->setObjectName( anObjectName );
158
159   aPanel->setZones( aZones );
160   aPanel->setSelectedZones( aSelectedZones );
161   aPanel->setSplittedZones( aSplittedZones );
162
163   createPreview();
164 }
165
166 void HYDROGUI_CalculationOp::abortOperation()
167 {
168   closePreview();
169
170   HYDROGUI_Operation::abortOperation();
171 }
172
173 void HYDROGUI_CalculationOp::commitOperation()
174 {
175   closePreview();
176
177   HYDROGUI_Operation::commitOperation();
178 }
179
180 HYDROGUI_InputPanel* HYDROGUI_CalculationOp::createInputPanel() const
181 {
182   HYDROGUI_CalculationDlg* aPanel = new HYDROGUI_CalculationDlg( module(), getName() );
183
184   // Connect signals and slots
185   connect( aPanel, SIGNAL( SplitZones() ), this, SLOT( onSplitZones() ) );
186
187   return aPanel;
188 }
189
190 bool HYDROGUI_CalculationOp::processApply( int&     theUpdateFlags,
191                                            QString& theErrorMsg )
192 {
193   HYDROGUI_CalculationDlg* aPanel = 
194     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
195   if ( !aPanel )
196     return false;
197
198   QString anObjectName = aPanel->getObjectName().simplified();
199   if ( anObjectName.isEmpty() )
200   {
201     theErrorMsg = tr( "INCORRECT_OBJECT_NAME" );
202     return false;
203   }
204
205   // check that there are no other objects with the same name in the document
206   if( !myIsEdit || ( !myEditedObject.IsNull() && myEditedObject->GetName() != anObjectName ) )
207   {
208     Handle(HYDROData_Object) anObject = HYDROGUI_Tool::FindObjectByName( module(), anObjectName );
209     if ( !anObject.IsNull() )
210     {
211       theErrorMsg = tr( "OBJECT_EXISTS_IN_DOCUMENT" ).arg( anObjectName );
212       return false;
213     }
214   }
215
216   Handle(HYDROData_Document) aDocument = doc();
217
218   Handle(HYDROData_Calculation) aCalculObj = myIsEdit ? myEditedObject :
219     Handle(HYDROData_Calculation)::DownCast( aDocument->CreateObject( KIND_CALCULATION ) );
220   if ( aCalculObj.IsNull() )
221     return false;
222
223   aCalculObj->SetName( anObjectName );
224
225   QString aPolylineName = aPanel->getPolylineName();
226   Handle(HYDROData_Polyline) aBndPolyline = Handle(HYDROData_Polyline)::DownCast(
227       HYDROGUI_Tool::FindObjectByName( module(), aPolylineName, KIND_POLYLINE ) );
228
229   aCalculObj->SetBoundaryPolyline( aBndPolyline );
230
231   QStringList aRefZoneNames = aPanel->getSelectedZones();
232   HYDROData_SequenceOfObjects aRefZones = 
233     HYDROGUI_Tool::FindObjectsByNames( module(), aRefZoneNames, KIND_ZONE );
234
235   aCalculObj->SetZones( aRefZones );
236
237   HYDROData_SequenceOfObjects aSplittedZones;
238
239   SplittedZonesList::iterator anIter = mySplittedZones.begin();
240   for ( ; anIter != mySplittedZones.end(); ++anIter )
241   {
242     const SplittedZone& aSplittedZone = *anIter;
243
244     if ( !aSplittedZone.DataZone.IsNull() )
245     {
246       //No need to create new but use old zone
247       aSplittedZones.Append( aSplittedZone.DataZone );
248       continue;
249     }
250
251     Handle(HYDROData_Polyline) aPolyline =
252       Handle(HYDROData_Polyline)::DownCast( aDocument->CreateObject( KIND_POLYLINE ) );
253     Handle(HYDROData_Zone) aDataZone =
254       Handle(HYDROData_Zone)::DownCast( aDocument->CreateObject( KIND_ZONE ) );
255
256     if( aPolyline.IsNull() || aDataZone.IsNull() )
257       continue;
258
259     // Fill the polyline data
260     aPolyline->SetName( aSplittedZone.PolylineName );
261     aPolyline->setDimension( 2 );
262
263     QList<PolylineSection> aPolylineData;
264     for( int i = 0, n = aSplittedZone.SplitData.Path.elementCount(); i < n; i++ )
265     {
266       const QPainterPath::Element anElement = aSplittedZone.SplitData.Path.elementAt( i );
267       switch( anElement.type )
268       {
269         case QPainterPath::MoveToElement:
270           aPolylineData.append( PolylineSection() );
271           break;
272         case QPainterPath::LineToElement:
273           if( !aPolylineData.isEmpty() )
274           {
275             PolylineSection& aSection = aPolylineData.last();
276             aSection.myCoords << anElement.x;
277             aSection.myCoords << anElement.y;
278           }
279           break;
280         case QPainterPath::CurveToElement: // currently not supported
281         default:
282           break;
283       }
284     }
285     aPolyline->setPolylineData( aPolylineData );
286
287     // Fill the zone data
288     aDataZone->SetName( aSplittedZone.ZoneName );
289     aDataZone->SetPolyline( aPolyline );
290     aDataZone->SetBorderColor( aSplittedZone.BorderColor );
291     aDataZone->SetFillingColor( aSplittedZone.FillingColor );
292
293     aSplittedZones.Append( aDataZone );
294   }
295
296   aCalculObj->SetSplittedZones( aSplittedZones );
297
298   theUpdateFlags = UF_Model;
299
300   return true;
301 }
302
303 void HYDROGUI_CalculationOp::onSplitZones()
304 {
305   mySplittedZones.clear();
306
307   HYDROGUI_CalculationDlg* aPanel = 
308     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
309   if ( !aPanel )
310     return;
311
312   QApplication::setOverrideCursor( Qt::WaitCursor );
313
314   QString aPolylineName = aPanel->getPolylineName();
315   Handle(HYDROData_Polyline) aBndPolyline = Handle(HYDROData_Polyline)::DownCast(
316       HYDROGUI_Tool::FindObjectByName( module(), aPolylineName, KIND_POLYLINE ) );
317
318   QStringList aZoneNames = aPanel->getSelectedZones();
319   HYDROData_SequenceOfObjects aZones = 
320     HYDROGUI_Tool::FindObjectsByNames( module(), aZoneNames, KIND_ZONE );
321
322   QStringList aResSplittedZones;
323
324   HYDROGUI_SplitZonesTool::SplitDataList aSplittedZones =
325     HYDROGUI_SplitZonesTool::SplitZones( aZones, aBndPolyline );
326
327   QString aSplitZonesPrefix = aPanel->getSplitZonesPrefix();
328   QStringList aUsedNames;
329
330   HYDROGUI_SplitZonesTool::SplitDataListIterator anIter( aSplittedZones );
331   while( anIter.hasNext() )
332   {
333     SplittedZone aSplittedZone;
334     aSplittedZone.SplitData = anIter.next();
335
336     aSplittedZone.FillingColor = HYDROGUI_Tool::GenerateFillingColor( module(), aSplittedZone.SplitData.ZoneNames );
337     aSplittedZone.BorderColor  = QColor( HYDROData_Zone::DefaultBorderColor() );
338
339     aSplittedZone.ZoneName = HYDROGUI_Tool::GenerateObjectName( module(), aSplitZonesPrefix + "Zone", aUsedNames );
340     aSplittedZone.PolylineName = HYDROGUI_Tool::GenerateObjectName( module(), aSplitZonesPrefix + "Poly", aUsedNames );
341
342     aUsedNames.append( aSplittedZone.ZoneName );
343     aUsedNames.append( aSplittedZone.PolylineName );
344
345     aResSplittedZones.append( aSplittedZone.ZoneName );
346
347     mySplittedZones.append( aSplittedZone );
348   }
349
350   aPanel->setSplittedZones( aResSplittedZones );
351   
352   createPreview();
353
354   QApplication::restoreOverrideCursor();
355 }
356
357 void HYDROGUI_CalculationOp::createPreview()
358 {
359   LightApp_Application* anApp = module()->getApp();
360
361   if ( !myActiveViewManager )
362   {
363     if ( mySplittedZones.isEmpty() )
364       return;
365
366     myActiveViewManager = anApp->activeViewManager();
367   }
368
369   if ( !myPreviewViewManager )
370   {
371     myPreviewViewManager = ::qobject_cast<OCCViewer_ViewManager*>( 
372       anApp->createViewManager( OCCViewer_Viewer::Type() ) );
373     if ( myPreviewViewManager )
374     {
375       connect( myPreviewViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
376                this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) );
377
378       module()->setViewManagerRole( myPreviewViewManager, HYDROGUI_Module::VMR_PreviewCaseZones );
379       myPreviewViewManager->setTitle( tr( "PREVIEW_CASE_ZONES" ) );
380     }
381   }
382
383   if ( !myPreviewViewManager )
384     return;
385
386   if ( OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer() )
387   {
388     Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
389     if ( !aCtx.IsNull() )
390     {
391       SplittedZonesList::iterator anIter = mySplittedZones.begin();
392       for ( ; anIter != mySplittedZones.end(); ++anIter )
393       {
394         SplittedZone& aSplittedZone = *anIter;
395         if ( aSplittedZone.Shape )
396           delete aSplittedZone.Shape;
397
398         aSplittedZone.Shape = new HYDROGUI_Shape( aCtx );
399
400         aSplittedZone.Shape->setFillingColor( aSplittedZone.FillingColor, false );
401         aSplittedZone.Shape->setBorderColor( aSplittedZone.BorderColor, false );
402         aSplittedZone.Shape->setPath( aSplittedZone.SplitData.Path, true );
403       }
404
405       //Process the draw events for viewer
406       QApplication::processEvents();
407       if ( OCCViewer_ViewWindow* vw = (OCCViewer_ViewWindow*)myPreviewViewManager->getActiveView() )
408         vw->onTopView();
409     }
410   }
411 }
412
413 void HYDROGUI_CalculationOp::onLastViewClosed( SUIT_ViewManager* theViewManager )
414 {
415   closePreview();
416 }
417
418 void HYDROGUI_CalculationOp::closePreview()
419 {
420   SplittedZonesList::iterator anIter= mySplittedZones.begin();
421   for ( ; anIter != mySplittedZones.end(); ++anIter )
422   {
423     SplittedZone& aSplittedZone = *anIter;
424     if ( aSplittedZone.Shape )
425     {
426       delete aSplittedZone.Shape;
427       aSplittedZone.Shape = NULL;
428     }
429   }
430
431   if( myPreviewViewManager )
432   {
433     disconnect( myPreviewViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
434                 this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) );
435
436     module()->getApp()->removeViewManager( myPreviewViewManager ); // myPreviewViewManager is deleted here
437     myPreviewViewManager = NULL;
438   }
439
440   if( myActiveViewManager )
441   {
442     HYDROGUI_Tool::SetActiveViewManager( module(), myActiveViewManager );
443     myActiveViewManager = NULL;
444   }
445 }
446
447