Salome HOME
bad592deedd2444f57fa8706e32827b28e3f1219
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_CalculationOp.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_CalculationOp.h"
20
21 #include "HYDROGUI_DataModel.h"
22 #include "HYDROGUI_CalculationDlg.h"
23 #include "HYDROGUI_Module.h"
24 #include "HYDROGUI_Tool.h"
25 #include "HYDROGUI_UpdateFlags.h"
26 #include "HYDROGUI_Zone.h"
27 #include "HYDROGUI_Region.h"
28
29 #include <HYDROData_PolylineXY.h>
30 #include <HYDROData_ShapesGroup.h>
31 #include <HYDROData_Iterator.h>
32 #include <HYDROData_ImmersibleZone.h>
33 #include <HYDROData_Object.h>
34 #include <HYDROData_Tool.h>
35
36 #include <OCCViewer_ViewManager.h>
37 #include <OCCViewer_ViewModel.h>
38 #include <OCCViewer_ViewWindow.h>
39
40 #include <LightApp_Application.h>
41 #include <LightApp_UpdateFlags.h>
42 #include <LightApp_SelectionMgr.h>
43 #include <LightApp_DataOwner.h>
44
45 #include <SUIT_MessageBox.h>
46 #include <SUIT_Desktop.h>
47 #include <SUIT_DataBrowser.h>
48
49 #include <QApplication>
50 #include <QKeySequence>
51 #include <QShortcut>
52
53 HYDROGUI_CalculationOp::HYDROGUI_CalculationOp( HYDROGUI_Module* theModule, bool theIsEdit )
54 : HYDROGUI_Operation( theModule ),
55   myIsEdit( theIsEdit ),
56   myActiveViewManager( NULL ),
57   myPreviewViewManager( NULL ),
58   myShowGeomObjects( true ),
59   myShowZones( false )
60 {
61   setName( myIsEdit ? tr( "EDIT_CALCULATION" ) : tr( "CREATE_CALCULATION" ) );
62 }
63
64 HYDROGUI_CalculationOp::~HYDROGUI_CalculationOp()
65 {
66   closePreview();
67 }
68
69 void HYDROGUI_CalculationOp::startOperation()
70 {
71   HYDROGUI_Operation::startOperation();
72   
73   // Begin transaction
74   startDocOperation();
75
76   HYDROGUI_CalculationDlg* aPanel = 
77     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
78   if ( !aPanel )
79     return;
80
81   SUIT_DataBrowser* aOb = ((LightApp_Application*)module()->application())->objectBrowser();
82   QList<QShortcut*> aShortcuts = aOb->findChildren<QShortcut*>();
83   QShortcut* aShortcut;
84   foreach( aShortcut, aShortcuts )
85   {
86     if ( aShortcut->key() == 
87       QKeySequence(((LightApp_Application*)module()->application())->objectBrowser()->shortcutKey( 
88       SUIT_DataBrowser::RenameShortcut ) ) )
89     {
90       aShortcut->setEnabled( false );
91     }
92   }
93
94   aPanel->reset();
95   QStringList aList;
96   QStringList anEntryList;
97   HYDROData_SequenceOfObjects aSeq = HYDROGUI_Tool::GetGeometryObjects( module() );
98   getNamesAndEntries( aSeq, aList, anEntryList );
99   aPanel->setAllGeomObjects( aList, anEntryList );
100
101   // Get all polylines
102   aList.clear();
103   anEntryList.clear();
104   HYDROData_Iterator anIter( doc(), KIND_POLYLINEXY );
105   Handle(HYDROData_PolylineXY) aPolylineObj;
106   QString aPolylineName;
107   for ( ; anIter.More(); anIter.Next() )
108   {
109     aPolylineObj = Handle(HYDROData_PolylineXY)::DownCast( anIter.Current() );
110
111     if ( !aPolylineObj.IsNull() && aPolylineObj->IsClosed() )
112     { 
113       // Check the polyline shape
114       TopoDS_Shape aPolylineShape = aPolylineObj->GetShape();
115       if ( !aPolylineShape.IsNull() && aPolylineShape.ShapeType() == TopAbs_WIRE ) {
116         aPolylineName = aPolylineObj->GetName();
117         if ( !aPolylineName.isEmpty() )
118         {
119           aList.append( aPolylineName );
120           anEntryList.append( HYDROGUI_DataObject::dataObjectEntry( aPolylineObj ) );
121         }
122       }
123     }
124   }
125   aPanel->setPolylineNames( aList, anEntryList );
126
127   QString anObjectName = HYDROGUI_Tool::GenerateObjectName( module(), tr( "DEFAULT_CALCULATION_CASE_NAME" ) );
128
129   myEditedObject.Nullify();
130   if ( myIsEdit )
131   {
132     myEditedObject = Handle(HYDROData_CalculationCase)::DownCast( HYDROGUI_Tool::GetSelectedObject( module() ) );
133     if ( !myEditedObject.IsNull() )
134     {
135       aPanel->setMode( myEditedObject->GetAssignmentMode() );
136       anObjectName = myEditedObject->GetName();
137       aPolylineObj = myEditedObject->GetBoundaryPolyline();
138       if ( aPolylineObj.IsNull() )
139       {
140         aPanel->setBoundary( QString() );
141       }
142       else
143       {
144         aPolylineName = aPolylineObj->GetName();
145         aPanel->setBoundary( aPolylineName );
146       }
147
148       aSeq = myEditedObject->GetGeometryObjects();
149       getNamesAndEntries( aSeq, aList, anEntryList );
150       aPanel->includeGeomObjects( aList );
151
152       // set rules
153       HYDROData_ListOfRules aRules;
154       Handle(HYDROData_Object) anObject1, anObject2;
155       HYDROData_PriorityType aPriority;
156       HYDROData_Zone::MergeAltitudesType aMergeType;
157       for ( int anIndex = 0; ; anIndex++ )
158       {
159         if ( myEditedObject->GetRule( anIndex, anObject1, aPriority, anObject2, aMergeType ) ) {
160           HYDROData_CustomRule aRule;
161           aRule.Object1 = anObject1;
162           aRule.Object2 = anObject2;
163           aRule.Priority = aPriority;
164           aRule.MergeType = aMergeType;
165
166           aRules << aRule;
167         }
168         else
169           break;
170       }
171       aPanel->setRules( aRules );
172     }
173   }
174   else
175   {
176     myEditedObject =
177       Handle(HYDROData_CalculationCase)::DownCast( doc()->CreateObject( KIND_CALCULATION ) );
178     myEditedObject->SetName( anObjectName );
179     myEditedObject->SetAssignmentMode( (HYDROData_CalculationCase::AssignmentMode)aPanel->getMode() );
180   }
181
182   aPanel->setObjectName( anObjectName );
183   aPanel->setEditedObject( myEditedObject );
184
185   createPreview();
186 }
187
188 void HYDROGUI_CalculationOp::getNamesAndEntries( const HYDROData_SequenceOfObjects& theSeq, 
189                                                 QStringList& theNames, QStringList& theEntries ) const
190 {
191  
192   theNames.clear();
193   theEntries.clear();
194   HYDROData_SequenceOfObjects::Iterator anIter( theSeq );
195   for ( ; anIter.More(); anIter.Next() )
196   {
197     Handle(HYDROData_Entity) anEntity = anIter.Value();
198     //if ( !HYDROData_Tool::IsGeometryObject( anEntity ) )
199     //  continue;
200
201     theNames.append( anEntity->GetName() );
202     theEntries.append( HYDROGUI_DataObject::dataObjectEntry( anEntity ) );
203   }
204 }
205
206 void HYDROGUI_CalculationOp::abortOperation()
207 {
208   closePreview();
209   // Abort transaction
210   abortDocOperation();
211   HYDROGUI_Operation::abortOperation();
212   module()->getApp()->updateObjectBrowser();
213 }
214
215 void HYDROGUI_CalculationOp::commitOperation()
216 {
217   closePreview();
218   // Commit transaction
219   commitDocOperation();
220   HYDROGUI_Operation::commitOperation();
221 }
222
223 HYDROGUI_InputPanel* HYDROGUI_CalculationOp::createInputPanel() const
224 {
225   HYDROGUI_CalculationDlg* aPanel = new HYDROGUI_CalculationDlg( module(), getName() );
226
227   // Connect signals and slots
228   connect( aPanel, SIGNAL( changeMode( int ) ), SLOT( onChangeMode( int ) ) );
229   connect( aPanel, SIGNAL( addObjects() ), SLOT( onAddObjects() ) );
230   connect( aPanel, SIGNAL( removeObjects() ), SLOT( onRemoveObjects() ) );
231   connect( aPanel, SIGNAL( addGroups() ), SLOT( onAddGroups() ) );
232   connect( aPanel, SIGNAL( removeGroups() ), SLOT( onRemoveGroups() ) );
233   connect( aPanel, SIGNAL( orderChanged( bool& ) ), SLOT( onOrderChanged( bool& ) ) );
234   connect( aPanel, SIGNAL( Next( const int ) ), SLOT( onNext( const int ) ) );
235   connect( aPanel, SIGNAL( Back( const int ) ), SLOT( onBack( const int ) ) );
236   //connect( aPanel, SIGNAL( clicked( SUIT_DataObject* ) ), SLOT( onSelected( SUIT_DataObject* ) ) );
237   connect( aPanel, SIGNAL( setMergeType( int, QString& ) ), SLOT( onSetMergeType( int, QString& ) ) );
238   connect( aPanel, SIGNAL( moveZones( SUIT_DataObject*, const QList<SUIT_DataObject*>& ) ),
239     SLOT( onMoveZones( SUIT_DataObject*, const QList<SUIT_DataObject*>& ) ) );
240   connect( aPanel, SIGNAL( createRegion( const QList<SUIT_DataObject*>& ) ),
241     SLOT( onCreateRegion( const QList<SUIT_DataObject*>& ) ) );
242   connect( aPanel, SIGNAL( clickedInZonesBrowser( SUIT_DataObject* ) ),
243     SLOT( onClickedInZonesBrowser( SUIT_DataObject* ) ) );
244   connect( aPanel, SIGNAL( objectsSelected() ), 
245            SLOT( onObjectsSelected() ) );
246   connect( aPanel, SIGNAL( boundarySelected( const QString & ) ), 
247     SLOT( onBoundarySelected( const QString & ) ) );
248
249   return aPanel;
250 }
251
252 void HYDROGUI_CalculationOp::onBoundarySelected ( const QString & theObjName )
253 {
254   bool anIsToUpdateViewer = false;
255
256   // Remove the old boundary from the operation viewer
257   Handle(HYDROData_PolylineXY) aPrevPolyline = 
258     myEditedObject->GetBoundaryPolyline();
259   if ( !aPrevPolyline.IsNull() )
260   {
261     setObjectVisibility( aPrevPolyline, false );
262     anIsToUpdateViewer = true;
263   }
264
265   // Set the selected boundary polyline to the calculation case
266   Handle(HYDROData_PolylineXY) aNewPolyline = Handle(HYDROData_PolylineXY)::DownCast(
267     HYDROGUI_Tool::FindObjectByName( module(), theObjName, KIND_POLYLINEXY ) );
268   myEditedObject->SetBoundaryPolyline( aNewPolyline );
269
270   if ( myPreviewViewManager )
271   {
272     OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer();
273     if ( aViewer )
274     {
275       if ( !aNewPolyline.IsNull() )
276       {
277         Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
278         if ( !aCtx.IsNull() )
279         {
280           setObjectVisibility( aNewPolyline, true );
281           anIsToUpdateViewer = true;
282         }
283       }
284
285       if ( anIsToUpdateViewer )
286         module()->update( UF_OCCViewer );
287     }
288   }
289 }
290
291 void HYDROGUI_CalculationOp::onObjectsSelected()
292 {
293   HYDROGUI_CalculationDlg* aPanel = 
294     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
295
296   QStringList aSelectedObjs = aPanel->getSelectedGeomObjects();
297   QMap<QString, bool> aSelectedObjsMap;
298   foreach( QString aName, aSelectedObjs )
299     aSelectedObjsMap[aName] = true;
300
301
302   // Select the appropriate geometry object shape in the viewer
303   selectionMgr()->clearSelected();
304
305   // Unhighlight all objects except selected
306   HYDROGUI_Shape* aShape = 0, *aLastShape = 0;
307   Handle(HYDROData_Entity) anEntity;
308   HYDROData_SequenceOfObjects aSeq = myEditedObject->GetGeometryObjects();
309   HYDROData_SequenceOfObjects::Iterator anIter( aSeq );
310   bool isSelected;
311   QString aName;
312   for ( ; anIter.More(); anIter.Next() )
313   {
314     anEntity = anIter.Value();
315     if ( !anEntity.IsNull() )
316     {
317       aShape = module()->getObjectShape( HYDROGUI_Module::VMR_PreviewCaseZones, anEntity );
318       if ( aShape )
319       {
320         aName = anEntity->GetName();
321         isSelected = aSelectedObjsMap.contains( aName );
322         aShape->highlight( isSelected, false );
323         aShape->update( false, false );
324         aLastShape = aShape;
325       }
326     }
327   }
328   if( aLastShape )
329     aLastShape->update( true, false );
330 }
331
332 void HYDROGUI_CalculationOp::onClickedInZonesBrowser( SUIT_DataObject* theItem )
333 {
334   HYDROGUI_Region* aRegionItem = dynamic_cast<HYDROGUI_Region*>(theItem);
335   HYDROGUI_Zone* aZoneItem;
336   selectionMgr()->clearSelected();
337   if ( aRegionItem )
338   {
339     // Select a region in preview
340     SUIT_DataOwnerPtrList aList( true );
341     DataObjectList aZones = aRegionItem->children();
342     for ( int i = 0; i < aZones.length(); i++ )
343     {
344       aZoneItem = dynamic_cast<HYDROGUI_Zone*>(aZones.at(i));
345       if ( aZoneItem )
346       {
347         aList.append( SUIT_DataOwnerPtr( new LightApp_DataOwner( aZoneItem->entry() ) ) );
348       }
349     }
350     selectionMgr()->setSelected( aList );
351   }
352   else
353   {
354     // select a single zone
355     aZoneItem = dynamic_cast<HYDROGUI_Zone*>(theItem);
356     if ( aZoneItem )
357     {
358       SUIT_DataOwnerPtrList aList( true );
359       aList.append( SUIT_DataOwnerPtr( new LightApp_DataOwner( aZoneItem->entry() ) ) );
360       selectionMgr()->setSelected( aList );
361     }
362   }
363 }
364
365 void HYDROGUI_CalculationOp::onMoveZones( SUIT_DataObject* theRegionItem, const QList<SUIT_DataObject*>& theZonesList )
366 {
367   HYDROGUI_Region* aRegion = dynamic_cast<HYDROGUI_Region*>(theRegionItem);
368   if ( aRegion )
369   {
370     QList<HYDROGUI_Zone*> aZonesList;
371     HYDROGUI_Zone* aZone;
372     // Get a list of dropped zones
373     for ( int i = 0; i < theZonesList.length(); i++ )
374     {
375       aZone = dynamic_cast<HYDROGUI_Zone*>( theZonesList.at( i ) );
376       if ( aZone )
377       {
378         aZonesList.append( aZone );
379       }
380     }
381     if ( aZonesList.length() > 0 )
382     {
383       aRegion->addZones( aZonesList );
384       HYDROGUI_CalculationDlg* aPanel = 
385         ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
386       if ( aPanel )
387       {
388         aPanel->refreshZonesBrowser();
389       }
390       createPreview();
391     }
392   }
393 }
394
395 void HYDROGUI_CalculationOp::onCreateRegion( const QList<SUIT_DataObject*>& theZonesList )
396 {
397   QList<HYDROGUI_Zone*> aZonesList;
398   HYDROGUI_Zone* aZone;
399   // Get a list of dropped zones
400   for ( int i = 0; i < theZonesList.length(); i++ )
401   {
402     aZone = dynamic_cast<HYDROGUI_Zone*>( theZonesList.at( i ) );
403     if ( aZone )
404     {
405       aZonesList.append( aZone );
406     }
407   }
408   if ( aZonesList.length() > 0 )
409   {
410     module()->getDataModel()->createNewRegion( myEditedObject, aZonesList );
411     HYDROGUI_CalculationDlg* aPanel = 
412       ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
413     if ( aPanel )
414     {
415       aPanel->refreshZonesBrowser();
416     }
417     createPreview();
418   }
419 }
420
421 void HYDROGUI_CalculationOp::onSetMergeType( int theMergeType, QString& theAltitudeName )
422 {
423   HYDROGUI_CalculationDlg* aPanel = 
424     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
425   if ( aPanel )
426   {
427     HYDROGUI_Zone* aZone = aPanel->getCurrentZone();
428     if ( aZone )
429     {
430       aZone->setMergeType( theMergeType, theAltitudeName );
431       HYDROGUI_Shape* aShape = module()->getObjectShape( HYDROGUI_Module::VMR_PreviewCaseZones, aZone->modelObject() );
432       if ( aShape )
433       {
434         aShape->update( true, false );
435       }
436     }
437     aPanel->refreshZonesBrowser();
438   }
439 }
440
441 void HYDROGUI_CalculationOp::onAddObjects()
442 {
443   HYDROGUI_CalculationDlg* aPanel = 
444     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
445   if ( !aPanel )
446     return;
447
448   // Add geometry objects selected in the module browser to the calculation case
449   QStringList aSelectedList = aPanel->getSelectedAvailableGeomObjects();
450   if ( aSelectedList.isEmpty() || !confirmRegionsChange() )
451     return;
452
453   QStringList anAddedList;
454   for (int i = 0; i < aSelectedList.length(); i++)
455   {
456     Handle(HYDROData_Object) anObject = Handle(HYDROData_Object)::DownCast( 
457       HYDROGUI_Tool::FindObjectByName( module(), aSelectedList.at( i ) ) );
458     if ( anObject.IsNull() )
459       continue;
460
461     if ( myEditedObject->AddGeometryObject( anObject ) )
462       anAddedList.append( anObject->GetName() );
463   }
464
465   if ( !anAddedList.isEmpty() )
466   {
467     aPanel->includeGeomObjects( anAddedList );
468     createPreview();
469   }
470 }
471
472 void HYDROGUI_CalculationOp::onRemoveObjects()
473 {
474   // Remove selected objects from the calculation case
475   HYDROGUI_CalculationDlg* aPanel = 
476     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
477   if ( !aPanel )
478     return;
479
480   QStringList aSelectedList = aPanel->getSelectedGeomObjects();
481   if ( aSelectedList.isEmpty() || !confirmRegionsChange() )
482     return;
483
484   for (int i = 0; i < aSelectedList.length(); i++)
485   {
486     Handle(HYDROData_Object) anObject = Handle(HYDROData_Object)::DownCast( 
487       HYDROGUI_Tool::FindObjectByName( module(), aSelectedList.at(i) ) );
488     if ( anObject.IsNull() )
489       continue;
490
491     setObjectVisibility( anObject, false );
492     myEditedObject->RemoveGeometryObject( anObject );
493   }
494
495   module()->update( UF_OCCViewer );
496   aPanel->excludeGeomObjects( aSelectedList );
497 }
498
499 bool HYDROGUI_CalculationOp::confirmRegionsChange() const
500 {
501   // Check if the case is already modified or not
502   bool isConfirmed = myEditedObject->IsMustBeUpdated();
503   if ( !isConfirmed )
504   {
505     // If not modified check if the case has already defined regions with zones
506     HYDROData_SequenceOfObjects aSeq = myEditedObject->GetRegions();
507     if ( aSeq.Length() > 0 )
508     {
509       // If there are already defined zones then ask a user to confirm zones recalculation
510       isConfirmed = ( SUIT_MessageBox::question( module()->getApp()->desktop(),
511                                tr( "REGIONS_CHANGED" ),
512                                tr( "CONFIRM_SPLITTING_ZONES_RECALCULATION_REGIONS" ),
513                                QMessageBox::Yes | QMessageBox::No,
514                                QMessageBox::No ) == QMessageBox::Yes );
515     }
516     else
517     {
518       isConfirmed = true; // No regions - no zones - nothing to recalculate
519     }
520   }
521   return isConfirmed;
522 }
523
524 bool HYDROGUI_CalculationOp::confirmOrderChange() const
525 {
526   // Check if the case is already modified or not
527   bool isConfirmed = myEditedObject->IsMustBeUpdated();
528   if ( !isConfirmed )
529   {
530     // If not modified check if the case has already defined regions with zones
531     HYDROData_SequenceOfObjects aSeq = myEditedObject->GetRegions();
532     if ( aSeq.Length() > 0 )
533     {
534       // If there are already defined zones then ask a user to confirm zones recalculation
535       isConfirmed = ( SUIT_MessageBox::question( module()->getApp()->desktop(),
536                                tr( "ORDER_CHANGED" ),
537                                tr( "CONFIRM_SPLITTING_ZONES_RECALCULATION_REGIONS" ),
538                                QMessageBox::Yes | QMessageBox::No,
539                                QMessageBox::No ) == QMessageBox::Yes );
540     }
541     else
542     {
543       isConfirmed = true; // No regions - no zones - nothing to recalculate
544     }
545   }
546   return isConfirmed;
547 }
548
549 bool HYDROGUI_CalculationOp::confirmModeChange() const
550 {
551   // Check if the case is already modified or not
552   bool isConfirmed = myEditedObject->IsMustBeUpdated();
553   if ( !isConfirmed )
554   {
555     // If not modified check if the case has already defined regions with zones
556     HYDROData_SequenceOfObjects aSeq = myEditedObject->GetRegions();
557     if ( aSeq.Length() > 0 )
558     {
559       // If there are already defined zones then ask a user to confirm zones recalculation
560       isConfirmed = ( SUIT_MessageBox::question( module()->getApp()->desktop(),
561                                tr( "MODE_CHANGED" ),
562                                tr( "CONFIRM_SPLITTING_ZONES_RECALCULATION_MODE" ),
563                                QMessageBox::Yes | QMessageBox::No,
564                                QMessageBox::No ) == QMessageBox::Yes );
565     }
566     else
567     {
568       isConfirmed = true; // No regions - no zones - nothing to recalculate
569     }
570   }
571   return isConfirmed;
572 }
573
574 bool HYDROGUI_CalculationOp::confirmContinueWithWarning( const HYDROData_Warning& theWarning ) const
575 {
576   HYDROData_WarningType aType = theWarning.Type;
577   if ( aType == WARN_OK ) {
578     return true;
579   }
580
581   QString aTitle;
582   QString aMsg;
583   switch ( aType )
584   {
585     case WARN_EMPTY_REGIONS:
586       aTitle = tr( "EMPTY_REGIONS" );
587       aMsg = tr( "CONFIRM_CONTINUE_WITH_OBJECTS_NOT_INCLUDED_TO_REGION" ).arg( theWarning.Data );
588       break;
589     default:
590       aTitle = tr( "WARNING" );
591       aMsg = theWarning.Data;
592   }
593
594
595   int anAnswer = SUIT_MessageBox::warning( module()->getApp()->desktop(),
596                                            aTitle, aMsg,
597                                            QMessageBox::Yes | QMessageBox::No,
598                                            QMessageBox::No );
599
600   return ( anAnswer == QMessageBox::Yes );
601 }
602
603 bool HYDROGUI_CalculationOp::processApply( int&     theUpdateFlags,
604                                            QString& theErrorMsg,
605                                            QStringList& theBrowseObjectsEntries )
606 {
607   HYDROGUI_CalculationDlg* aPanel = 
608     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
609   if ( !aPanel )
610     return false;
611
612   if( !myIsEdit )
613   {
614     QString anEntry = HYDROGUI_DataObject::dataObjectEntry( myEditedObject );
615     theBrowseObjectsEntries.append( anEntry );
616   }
617
618   // For manual mode priority rules are redundant
619   if ( aPanel->getMode() == HYDROData_CalculationCase::MANUAL ) {
620     myEditedObject->ClearRules( false );
621   }
622  
623   theUpdateFlags = UF_Model | UF_OCCViewer | UF_OCC_Forced | UF_VTKViewer | UF_VTK_Forced | UF_VTK_Init;
624
625   return true;
626 }
627
628 void HYDROGUI_CalculationOp::onApply()
629 {
630   // Check warnings
631   HYDROData_Warning aWarning = myEditedObject->GetLastWarning();
632   if ( aWarning.Type != WARN_OK ) {
633     if ( !confirmContinueWithWarning( aWarning ) ) {
634       // Go back to the first page
635       HYDROGUI_CalculationDlg* aPanel = 
636         ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
637       if ( aPanel ) {
638         aPanel->onFirstPage();
639       }
640       return;
641     }
642   }
643
644   QApplication::setOverrideCursor( Qt::WaitCursor );
645
646   int anUpdateFlags = 0;
647   QString anErrorMsg;
648   QStringList aBrowseObjectsEntries;
649
650   bool aResult = false;
651   
652   try
653   {
654     aResult = processApply( anUpdateFlags, anErrorMsg, aBrowseObjectsEntries );
655   }
656   catch ( Standard_Failure )
657   {
658     Handle(Standard_Failure) aFailure = Standard_Failure::Caught();
659     anErrorMsg = aFailure->GetMessageString();
660     aResult = false;
661   }
662   catch ( ... )
663   {
664     aResult = false;
665   }
666   
667   QApplication::restoreOverrideCursor();
668
669   if ( aResult )
670   {
671     module()->update( anUpdateFlags );
672     commit();
673     browseObjects( aBrowseObjectsEntries );
674   }
675   else
676   {
677     abort();
678     QString aMsg = tr( "INPUT_VALID_DATA" );
679     if( !anErrorMsg.isEmpty() )
680       aMsg.prepend( anErrorMsg + "\n" );
681     SUIT_MessageBox::critical( module()->getApp()->desktop(),
682                                tr( "INSUFFICIENT_INPUT_DATA" ),
683                                aMsg ); 
684   }
685 }
686
687 void HYDROGUI_CalculationOp::onNext( const int theIndex )
688 {
689   if( theIndex==1 )
690   {
691     setAvailableGroups();
692   }
693   else if( theIndex==2 )
694   {
695     HYDROGUI_CalculationDlg* aPanel = 
696       ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
697     if ( !aPanel )
698       return;
699
700     QApplication::setOverrideCursor( Qt::WaitCursor );
701
702     setGeomObjectsVisible( false );
703   
704     QString aNewCaseName = aPanel->getObjectName();
705     QString anOldCaseName = myEditedObject->GetName();
706     bool isNameChanged = anOldCaseName != aNewCaseName;
707   
708     bool anIsToUpdateOb = isNameChanged;
709
710     // At first we must to update the case name because of 
711     // automatic names generation for regions and zones
712     myEditedObject->SetName( aNewCaseName );
713     
714     // Set parameters for automatic mode
715     int aMode = aPanel->getMode();
716     if ( aMode == HYDROData_CalculationCase::AUTOMATIC )
717     {
718       // Set objects in the specified order
719       if( myEditedObject->IsMustBeUpdated() )
720       {
721         myEditedObject->RemoveGeometryObjects();
722         foreach ( const QString& aName, aPanel->getAllGeomObjects() )
723         {
724           Handle(HYDROData_Object) anObject = Handle(HYDROData_Object)::DownCast( 
725             HYDROGUI_Tool::FindObjectByName( module(), aName ) );
726           if ( anObject.IsNull() )
727           {
728             continue;
729           }
730           myEditedObject->AddGeometryObject( anObject );
731         }
732
733         // Clear priority rules
734         //@ASL if ( myEditedObject->GetRulesCount() > 0 ) {
735           myEditedObject->ClearRules( true );
736         //@ASL }
737         // Set priority rules
738         foreach ( const HYDROData_CustomRule& aRule, aPanel->getRules() ) {
739           myEditedObject->AddRule( aRule.Object1, aRule.Priority,
740                                   aRule.Object2, aRule.MergeType );
741         }
742       }
743     }
744     aPanel->setEditZonesEnabled( aMode == HYDROData_CalculationCase::MANUAL );
745          
746     if ( myEditedObject->IsMustBeUpdated() )
747     {
748       myShowZones = true;
749       myEditedObject->Update();
750       
751       AssignDefaultZonesColors();
752
753       //aPanel->setEditedObject( myEditedObject );
754       aPanel->refreshZonesBrowser();
755     
756       closePreview();
757       createPreview();
758
759       anIsToUpdateOb = true;
760     }
761     else
762     {
763       setZonesVisible( true );
764
765       if ( isNameChanged ) {
766         module()->getDataModel()->updateObjectTree( myEditedObject );
767       }
768     }
769
770     if ( anIsToUpdateOb ) {
771       SUIT_DataBrowser* anObjBrowser = ((LightApp_Application*)module()->application())->objectBrowser();
772       if ( anObjBrowser ) {
773         anObjBrowser->updateTree( module()->getDataModel()->getDataObject( myEditedObject ), false );
774       }
775     }
776
777     QApplication::restoreOverrideCursor();
778   }
779 }
780
781 void HYDROGUI_CalculationOp::onBack( const int theIndex )
782 {
783   setGeomObjectsVisible( theIndex != 2 );
784   setZonesVisible( false );
785 }
786
787 void HYDROGUI_CalculationOp::setZonesVisible( bool theIsVisible )
788 {
789   myShowZones = theIsVisible;
790   HYDROData_SequenceOfObjects aRegions = myEditedObject->GetRegions();
791   HYDROData_SequenceOfObjects::Iterator aRegionsIter( aRegions );
792   HYDROData_SequenceOfObjects aZones;
793   Handle(HYDROData_Region) aRegion;
794   if ( myPreviewViewManager ) 
795   {
796     if ( OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer() )
797     {
798       Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
799       if ( !aCtx.IsNull() )
800       {
801         for ( ; aRegionsIter.More(); aRegionsIter.Next() )
802         {
803           aRegion = Handle(HYDROData_Region)::DownCast( aRegionsIter.Value() );
804           if ( !aRegion.IsNull() )
805           {
806             aZones = aRegion->GetZones();
807             HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
808             for ( ; aZonesIter.More(); aZonesIter.Next() )
809             {
810               setObjectVisibility( aZonesIter.Value(), theIsVisible );
811             }
812           }
813         }
814       }
815
816       module()->update( UF_OCCViewer );
817     }
818   }
819 }
820
821 void HYDROGUI_CalculationOp::setGeomObjectsVisible( bool theIsVisible )
822 {
823   myShowGeomObjects = theIsVisible;
824
825   HYDROData_SequenceOfObjects aSeq = myEditedObject->GetGeometryObjects();
826
827   HYDROData_SequenceOfObjects::Iterator anIter( aSeq );
828   for ( ; anIter.More(); anIter.Next() ) {
829     setObjectVisibility( anIter.Value(), theIsVisible );
830   }
831 }
832
833 void HYDROGUI_CalculationOp::AssignDefaultZonesColors()
834 {
835   HYDROData_SequenceOfObjects aRegions = myEditedObject->GetRegions();
836   HYDROData_SequenceOfObjects::Iterator aRegionsIter( aRegions );
837   HYDROData_SequenceOfObjects aZones;
838   Handle(HYDROData_Region) aRegion;
839   if ( myPreviewViewManager ) 
840   {
841     if ( OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer() )
842     {
843       Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
844       if ( !aCtx.IsNull() )
845       {
846         int aCounter = 0;        
847         for ( ; aRegionsIter.More(); aRegionsIter.Next() )
848         {
849           aRegion = Handle(HYDROData_Region)::DownCast( aRegionsIter.Value() );
850           if ( !aRegion.IsNull() )
851           {
852             aZones = aRegion->GetZones();
853             HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
854             for ( ; aZonesIter.More(); aZonesIter.Next() )
855             {
856               // Zone
857               Handle(HYDROData_Zone) aZone = Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
858               if ( !aZone.IsNull() )
859               {
860                 QColor aFillingColor = GenerateDefaultZonesColor(++aCounter);
861                 while (aFillingColor == Qt::red)
862                   aFillingColor = GenerateDefaultZonesColor(++aCounter);
863                 
864                 aZone->SetColor(aFillingColor);
865               }
866             }
867           }
868         }
869       }
870     }
871   }
872 }
873
874 QColor HYDROGUI_CalculationOp::GenerateDefaultZonesColor( int theIndex,
875                                                           float theSaturation/* = 0.5*/,
876                                                           float theValue/* = 0.95*/ ) const
877 {
878   float aGoldenRatioConjugate = (float)(360./582.);
879   float aHue = (float)rand();
880   aHue += aGoldenRatioConjugate*theIndex;
881   aHue -= floor(aHue);
882
883   float aR = 0., aG = 0., aB = 0.;
884   int aHueInt = (int)(aHue*6.);
885   float aF = aHue*6. - aHueInt;
886   float aP = theValue * (1. - theSaturation);
887   float aQ = theValue * (1. - aF*theSaturation);
888   float aT = theValue * (1. - (1. - aF) * theSaturation);
889   switch (aHueInt)
890   {
891   case 0: { aR = theValue; aG = aT; aB = aP; break; }
892   case 1: { aR = aQ; aG = theValue; aB = aP; break; }
893   case 2: { aR = aP; aG = theValue; aB = aT; break; }
894   case 3: { aR = aP; aG = aQ; aB = theValue; break; }
895   case 4: { aR = aT; aG = aP; aB = theValue; break; }
896   case 5: { aR = theValue; aG = aP; aB = aQ; break; }
897   default: break;
898   }
899
900   QColor aColor = QColor( (int)(aR*256.), (int)(aG*256.), (int)(aB*256.) );
901   return ( aColor.isValid() ? aColor : HYDROData_ImmersibleZone::DefaultFillingColor() );
902 }
903
904 void HYDROGUI_CalculationOp::createPreview()
905 {
906   LightApp_Application* anApp = module()->getApp();
907   HYDROData_SequenceOfObjects aSeq;
908   if ( myShowGeomObjects ) {
909     aSeq.Append( myEditedObject->GetGeometryObjects() );
910   }
911   Handle(HYDROData_Entity) anEntity;
912
913   if ( myShowZones )
914   {
915     // Gather zones for displaying
916     HYDROData_SequenceOfObjects aRegions = myEditedObject->GetRegions();
917     HYDROData_SequenceOfObjects::Iterator aRegionsIter( aRegions );
918     HYDROData_SequenceOfObjects aZones;
919     Handle(HYDROData_Region) aRegion;
920     for ( ; aRegionsIter.More(); aRegionsIter.Next() )
921     {
922       anEntity = aRegionsIter.Value();
923       if ( !anEntity.IsNull() )
924       {
925         aRegion = Handle(HYDROData_Region)::DownCast( anEntity );
926         if ( !aRegion.IsNull() )
927         {
928           aZones = aRegion->GetZones();
929           aSeq.Append( aZones );
930         }
931       }
932     }
933   }
934
935   // Get a boundary polyline if any
936   aSeq.Append( myEditedObject->GetBoundaryPolyline() );
937
938   module()->removeViewShapes( HYDROGUI_Module::VMR_PreviewCaseZones );
939
940   if ( !myActiveViewManager )
941   {
942     if ( aSeq.IsEmpty() )
943       return;
944
945     myActiveViewManager = anApp->activeViewManager();
946   }
947
948   if ( !myPreviewViewManager )
949   {
950     myPreviewViewManager = ::qobject_cast<OCCViewer_ViewManager*>( 
951       anApp->createViewManager( OCCViewer_Viewer::Type() ) );
952     if ( myPreviewViewManager )
953     {
954       connect( myPreviewViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
955                this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) );
956
957       module()->setViewManagerRole( myPreviewViewManager, HYDROGUI_Module::VMR_PreviewCaseZones );
958       myPreviewViewManager->setTitle( tr( "PREVIEW_CASE_ZONES" ) );
959     }
960   }
961
962   if ( !myPreviewViewManager )
963     return;
964
965   if ( OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer() )
966   {
967     Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
968     if ( !aCtx.IsNull() )
969     {
970       HYDROData_SequenceOfObjects::Iterator anIter( aSeq );
971       for ( ; anIter.More(); anIter.Next() )
972       {
973         setObjectVisibility( anIter.Value(), true );
974       }
975
976       //Process the draw events for viewer
977       QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
978       if ( OCCViewer_ViewWindow* vw = (OCCViewer_ViewWindow*)myPreviewViewManager->getActiveView() )
979         vw->onTopView();
980     }
981
982     module()->update( UF_OCCViewer | UF_FitAll );
983   }
984 }
985
986 void HYDROGUI_CalculationOp::setObjectVisibility( Handle(HYDROData_Entity) theEntity, const bool theIsVisible )
987 {
988   if ( theEntity.IsNull() || !myPreviewViewManager ) {
989     return;
990   }
991
992   OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer();
993   if ( aViewer ) {
994     module()->setObjectVisible( (size_t)aViewer, theEntity, theIsVisible );
995   }
996 }
997
998 void HYDROGUI_CalculationOp::onLastViewClosed( SUIT_ViewManager* theViewManager )
999 {
1000   closePreview();
1001 }
1002
1003 void HYDROGUI_CalculationOp::closePreview()
1004 {
1005   SUIT_DataBrowser* aOb = ((LightApp_Application*)module()->application())->objectBrowser();
1006   QList<QShortcut*> aShortcuts = aOb->findChildren<QShortcut*>();
1007   QShortcut* aShortcut;
1008   foreach( aShortcut, aShortcuts )
1009   {
1010     if ( aShortcut->key() == 
1011       QKeySequence( ((LightApp_Application*)module()->application())->objectBrowser()->shortcutKey( 
1012       SUIT_DataBrowser::RenameShortcut ) ) )
1013     {
1014       aShortcut->setEnabled( true );
1015     }
1016   }
1017
1018
1019   if( myPreviewViewManager )
1020   {
1021     // Hide all the displayed objects in the preview view
1022     OCCViewer_Viewer* aViewer = myPreviewViewManager->getOCCViewer();
1023     if ( aViewer ) {
1024       size_t aViewId = (size_t)aViewer;
1025       HYDROData_Iterator anIterator( doc() );
1026       for( ; anIterator.More(); anIterator.Next() ) {
1027         Handle(HYDROData_Entity) anObject = anIterator.Current();
1028         if( !anObject.IsNull() ) {
1029           module()->setObjectVisible( aViewId, anObject, false );
1030         }
1031       }
1032     }
1033
1034     disconnect( myPreviewViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
1035                 this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) );
1036
1037     module()->getApp()->removeViewManager( myPreviewViewManager ); // myPreviewViewManager is deleted here
1038     myPreviewViewManager = NULL;
1039   }
1040
1041   if( myActiveViewManager )
1042   {
1043     HYDROGUI_Tool::SetActiveViewManager( module(), myActiveViewManager );
1044     myActiveViewManager = NULL;
1045   }
1046 }
1047
1048 void HYDROGUI_CalculationOp::setAvailableGroups()
1049 {
1050   HYDROGUI_CalculationDlg* aPanel = 
1051       ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
1052
1053   HYDROData_SequenceOfObjects aSeq = myEditedObject->GetGeometryGroups();
1054   QStringList aList, anEntryList;
1055   getNamesAndEntries( aSeq, aList, anEntryList );
1056
1057   QStringList aGroupsNames;
1058
1059   HYDROData_SequenceOfObjects anObjs = myEditedObject->GetGeometryObjects();
1060   for( int anIndex = 1, aLength = anObjs.Length(); anIndex <= aLength; anIndex++ )
1061   {
1062     Handle_HYDROData_Object anObj = Handle_HYDROData_Object::DownCast( anObjs.Value( anIndex ) );
1063     HYDROData_SequenceOfObjects aGroups = anObj->GetGroups();
1064     for( int aGIndex = 1, aGLength = aGroups.Length(); aGIndex <= aGLength; aGIndex++ )
1065     {
1066       Handle_HYDROData_ShapesGroup aGroup = Handle_HYDROData_ShapesGroup::DownCast( aGroups.Value( aGIndex ) );
1067       aGroupsNames.append( aGroup->GetName() );
1068     }
1069   }
1070   if( myEditedObject->IsMustBeUpdated() ) {
1071     for( int anIndex = 1, aLength = aSeq.Length(); anIndex <= aLength; anIndex++ ) {
1072       Handle(HYDROData_ShapesGroup) aGeomGroup =
1073         Handle(HYDROData_ShapesGroup)::DownCast( aSeq.Value( anIndex ) );
1074       if ( !aGeomGroup.IsNull() && !aGroupsNames.contains( aGeomGroup->GetName() ) ) {
1075         myEditedObject->RemoveGeometryGroup( aGeomGroup );
1076       }
1077     }
1078   }
1079
1080   aPanel->setAvailableGroups( aGroupsNames );
1081   aPanel->includeGroups( aList );
1082
1083   bool isUpdated = myEditedObject->IsMustBeUpdated();
1084 }
1085
1086 void HYDROGUI_CalculationOp::onAddGroups()
1087 {
1088   HYDROGUI_CalculationDlg* aPanel = 
1089     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
1090   if ( !aPanel )
1091     return;
1092
1093   // Add geometry objects selected in the module browser to the calculation case
1094   QStringList aSelectedList = aPanel->getSelectedAvailableGroups();
1095   if ( aSelectedList.isEmpty() || !confirmRegionsChange() )
1096     return;
1097
1098   QStringList anAddedList;
1099   for (int i = 0; i < aSelectedList.length(); i++)
1100   {
1101     Handle(HYDROData_ShapesGroup) aGroup = Handle(HYDROData_ShapesGroup)::DownCast( 
1102       HYDROGUI_Tool::FindObjectByName( module(), aSelectedList.at( i ) ) );
1103     if ( aGroup.IsNull() )
1104       continue;
1105
1106     if ( myEditedObject->AddGeometryGroup( aGroup ) )
1107       anAddedList.append( aGroup->GetName() );
1108   }
1109
1110   if ( !anAddedList.isEmpty() )
1111   {
1112     aPanel->includeGroups( anAddedList );
1113   }
1114 }
1115
1116 void HYDROGUI_CalculationOp::onRemoveGroups()
1117 {
1118   // Remove selected objects from the calculation case
1119   HYDROGUI_CalculationDlg* aPanel = 
1120     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
1121   if ( !aPanel )
1122     return;
1123
1124   QStringList aSelectedList = aPanel->getSelectedGroups();
1125   if ( aSelectedList.isEmpty() || !confirmRegionsChange() )
1126     return;
1127
1128   for (int i = 0; i < aSelectedList.length(); i++)
1129   {
1130     Handle(HYDROData_ShapesGroup) aGroup = Handle(HYDROData_ShapesGroup)::DownCast( 
1131       HYDROGUI_Tool::FindObjectByName( module(), aSelectedList.at(i) ) );
1132     if ( aGroup.IsNull() )
1133       continue;
1134
1135     myEditedObject->RemoveGeometryGroup( aGroup );
1136   }
1137
1138   aPanel->excludeGroups( aSelectedList );
1139 }
1140
1141 void HYDROGUI_CalculationOp::onChangeMode( int theMode )
1142 {
1143   HYDROGUI_CalculationDlg* aPanel = 
1144     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
1145   if ( !aPanel )
1146     return;
1147
1148   if ( !confirmModeChange() ) {
1149     aPanel->setMode( myEditedObject->GetAssignmentMode() );
1150     return;
1151   }
1152
1153   myEditedObject->SetAssignmentMode( (HYDROData_CalculationCase::AssignmentMode)theMode );
1154   aPanel->setMode( theMode );
1155 }
1156
1157 void HYDROGUI_CalculationOp::onOrderChanged( bool& isConfirmed )
1158 {
1159   HYDROGUI_CalculationDlg* aPanel = 
1160     ::qobject_cast<HYDROGUI_CalculationDlg*>( inputPanel() );
1161   if ( !aPanel )
1162     return;
1163
1164   isConfirmed = confirmOrderChange();
1165   if( isConfirmed )
1166     myEditedObject->SetToUpdate( true );
1167 }