Salome HOME
Merge remote-tracking branch 'origin/BR_1334_MPROF' into BR_2017
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_ProfileOp.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_Module.h>
20 #include <HYDROGUI_ProfileOp.h>
21 #include <HYDROGUI_ProfileDlg.h>
22 #include <HYDROGUI_Tool2.h>
23 #include <HYDROGUI_UpdateFlags.h>
24 #include <HYDROGUI_DataObject.h>
25 #include <HYDROData_Document.h>
26 #include <HYDROData_Profile.h>
27 #include <HYDROGUI_CurveCreatorProfile.h>
28 #include <HYDROGUI_DeleteOp.h>
29 #include <HYDROData_Tool.h>
30 #include <CurveCreator_Displayer.hxx>
31 #include <HYDROData_Entity.h>
32 #include <QSet>
33
34 #include <LightApp_Application.h>
35 #include <LightApp_SelectionMgr.h>
36 #include <LightApp_UpdateFlags.h>
37
38 #include <OCCViewer_ViewManager.h>
39 #include <OCCViewer_ViewModel.h>
40 #include <OCCViewer_ViewWindow.h>
41
42 #include <OCCViewer_AISSelector.h>
43
44 #include <Precision.hxx>
45
46 //static int ZValueIncrement = 0;
47
48 static void ProfileUZToCurveCrProfile(const Handle(HYDROData_ProfileUZ)& aProfileUZ, 
49   HYDROGUI_CurveCreatorProfile* outProfile)
50 {
51   CurveCreator::Coordinates aCurveCoords;
52   CurveCreator::SectionsMap aSectionsMap;
53
54   HYDROData_ProfileUZ::PointsList aSectPointsList = aProfileUZ->GetPoints();
55   CurveCreator::PosPointsList aPoints;
56   for ( int k = 1, aNbPoints = aSectPointsList.Size(); k <= aNbPoints; ++k )
57   {
58     const HYDROData_ProfileUZ::Point& aSectPoint = aSectPointsList.Value( k );
59     aCurveCoords.clear();
60     aCurveCoords.push_back( aSectPoint.X() );
61     aCurveCoords.push_back( aSectPoint.Y() );
62
63     CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( k, aCurveCoords );
64     aPoints.push_back( aPosPoint );
65   }
66
67   aSectionsMap[0] = aPoints;
68   outProfile->addPointsInternal( aSectionsMap );
69
70   HYDROData_ProfileUZ::SectionType aSectType = aProfileUZ->GetSectionType( 0 );
71
72   CurveCreator::SectionType aCurveType = CurveCreator::Polyline;
73   if( aSectType == HYDROData_ProfileUZ::SECTION_SPLINE )
74     aCurveType = CurveCreator::Spline;
75
76   outProfile->setSectionType( 0, aCurveType );
77 }
78
79 static int CurveCrProfileToHProfile(const HYDROGUI_CurveCreatorProfile* outProfile, 
80   Handle(HYDROData_Profile) theProfileObj,
81   const QString theProfileName,
82   bool IsEdit)
83 {
84   if( theProfileObj.IsNull() )
85     return 0;
86
87   Handle(HYDROData_ProfileUZ) aProfileUZ = theProfileObj->GetProfileUZ();
88   if ( aProfileUZ.IsNull() )
89     return 0;
90
91   theProfileObj->SetName(theProfileName);
92
93   HYDROData_ProfileUZ::PointsList aProfileParamPoints;
94
95   Handle(TColgp_HArray1OfPnt) aCurveCoords = outProfile->GetDifferentPoints( 0 );
96   if ( aCurveCoords.IsNull() || aCurveCoords->Size() <= 2 )
97     return -1;
98
99   for ( int k = aCurveCoords->Lower(); k <= aCurveCoords->Upper() ; k++ )
100   {
101     HYDROData_ProfileUZ::Point aProfileParamPoint;
102
103     aProfileParamPoint.SetX( aCurveCoords->Value( k ).X() );
104     aProfileParamPoint.SetY( aCurveCoords->Value( k ).Y() );
105
106     aProfileParamPoints.Append( aProfileParamPoint );
107   }
108   theProfileObj->SetParametricPoints( aProfileParamPoints );
109
110   HYDROData_ProfileUZ::SectionType aSectType = HYDROData_ProfileUZ::SECTION_POLYLINE;
111   if ( outProfile->getSectionType( 0 ) == CurveCreator::Spline )
112     aSectType = HYDROData_ProfileUZ::SECTION_SPLINE;
113
114   aProfileUZ->SetSectionType( 0, aSectType );
115
116   if ( !IsEdit )
117     theProfileObj->SetBorderColor( theProfileObj->DefaultBorderColor() );
118
119   // At first we update the child u,z profile object
120   aProfileUZ->Changed( HYDROData_Entity::Geom_2d );
121   aProfileUZ->Update();
122
123   // And now we update our edited object
124   theProfileObj->Update();
125   return 1;
126 }
127
128 HYDROGUI_ProfileOp::HYDROGUI_ProfileOp( HYDROGUI_Module* theModule, bool theIsEdit )
129 : HYDROGUI_Operation( theModule ), myIsEdit(theIsEdit), 
130    myDisplayer (NULL), mySingleProfileMode (false)
131 {
132   setName( theIsEdit ? tr( "EDIT_PROFILE" ) : tr( "CREATE_PROFILE" ) );
133 }
134
135 HYDROGUI_ProfileOp::~HYDROGUI_ProfileOp()
136 {
137   erasePreview();
138 }
139
140 /**
141  * Redirect the delete action to input panel
142  */
143 void HYDROGUI_ProfileOp::deleteSelected()
144 {
145   HYDROGUI_ProfileDlg* aPanel = (HYDROGUI_ProfileDlg*)inputPanel();
146   aPanel->deleteSelected();
147 }
148
149 /**
150  * Checks whether there are some to delete
151  */
152 #include <CurveCreator_Widget.h>
153 bool HYDROGUI_ProfileOp::deleteEnabled()
154 {
155   HYDROGUI_ProfileDlg* aPanel = (HYDROGUI_ProfileDlg*)inputPanel();
156   return aPanel->deleteEnabled();
157 }
158
159 void HYDROGUI_ProfileOp::startOperation()
160 {
161   if (!myProfiles.empty())
162   {
163     for (int i = 0; i < myProfiles.size(); i++)
164     {
165       delete myProfiles[i];
166       myProfiles[i] = NULL;
167     }
168     myProfiles.clear();
169   }
170
171   if (!myIsEdit)
172     myEditedObjects.Clear();
173
174   if (myCurveToProfile.IsEmpty())
175     myCurveToProfile.Clear();
176
177   if( myIsEdit && isApplyAndClose() )
178     myEditedObjects = HYDROGUI_Tool::GetSelectedObjects(module());
179
180   int lenP = myEditedObjects.Length();  
181   myProfiles.resize(lenP == 0 ? 1 : myEditedObjects.Length());
182   for (int i = 0; i < myProfiles.size(); i++)
183     myProfiles[i] = new HYDROGUI_CurveCreatorProfile();
184
185   mySingleProfileMode = myEditedObjects.IsEmpty() || lenP == 1;  
186   HYDROGUI_Operation::startOperation();
187
188   HYDROGUI_ProfileDlg* aPanel = (HYDROGUI_ProfileDlg*)inputPanel();
189   aPanel->myEditorWidget->setCurve(NULL);
190   aPanel->reset();
191   setPreviewManager( aPanel->viewManager() );
192   setCursor();
193
194   aPanel->SetSingleProfileMode(mySingleProfileMode); 
195   QMap<HYDROGUI_CurveCreatorProfile*, QColor> CurveToColor;
196   if( lenP )
197   {
198     for (int i = 1; i <= lenP; i++)
199     {
200       Handle(HYDROData_Profile) aCProfile = Handle(HYDROData_Profile)::DownCast(myEditedObjects(i)); 
201       QString aProfileName;
202       if( !aCProfile.IsNull() )
203       {
204         Handle(HYDROData_ProfileUZ) aProfileUZ = aCProfile->GetProfileUZ( false );
205         if ( !aProfileUZ.IsNull() )
206         {
207           HYDROGUI_CurveCreatorProfile* CP = new HYDROGUI_CurveCreatorProfile();
208           myProfiles[i-1] = CP;
209           ProfileUZToCurveCrProfile(aProfileUZ, CP);
210           myCurveToProfile.Bind(CP, aCProfile);
211         }
212       }
213     }
214     int ext = myCurveToProfile.Extent(); //ext should be equal to lenP
215     QVector<QColor> PColors;
216     if (!mySingleProfileMode)
217       HYDROData_Tool::GenerateRepeatableRandColors(ext, PColors);
218     else
219       PColors << QColor(0,0,255); //default color
220
221     for (int i = 0; i < myProfiles.size(); i++)
222     {
223       HYDROGUI_CurveCreatorProfile* CC = myProfiles[i];
224       const Handle(HYDROData_Profile)& CP = myCurveToProfile.Find(CC);
225       const QColor& CurCol = PColors[i]; 
226       CurveToColor[CC] = CurCol;
227       const QString& profName = CP->GetName();
228       const QColor& PColor = CurCol;
229       if (!mySingleProfileMode)
230         aPanel->addProfileName(profName, PColor);
231       else
232         aPanel->setProfileName(profName);
233     }
234   }
235
236   if (!myIsEdit)
237   {
238     QString aProfileName = HYDROGUI_Tool::GenerateObjectName( module(), tr( "DEFAULT_PROFILE_NAME" ) );
239     aPanel->setProfileName( aProfileName );
240   }
241
242   if (!myProfiles.empty())
243   {
244     aPanel->setProfile( myProfiles[0] );
245     aPanel->setProfilesPointer( &myProfiles );
246   }
247   displayPreviews(CurveToColor, 0, myProfiles.size(), true, true );
248 }
249
250 void HYDROGUI_ProfileOp::onAddProfiles()
251 {
252   if( !myIsEdit )
253     return;
254
255   QSet<QString> edObjNamesMap;
256   for (int i = 1; i <= myEditedObjects.Length(); i++)
257     edObjNamesMap.insert( myEditedObjects(i)->GetName());
258
259   HYDROData_SequenceOfObjects aSelectedObj = HYDROGUI_Tool::GetSelectedObjects( module() );;
260   int ExistingProfLen = myEditedObjects.Length();
261   for (int i = 1; i <= aSelectedObj.Length(); i++)
262   {
263     Handle(HYDROData_Entity) CurProf = Handle(HYDROData_Entity)::DownCast(aSelectedObj(i));
264     if (CurProf.IsNull())
265       continue;
266     if (!edObjNamesMap.contains(CurProf->GetName()))
267       myEditedObjects.Append(CurProf);
268   }
269
270   int NewLen = myEditedObjects.Length();
271   myProfiles.resize(myEditedObjects.Length());
272   for (int i = myProfiles.size() - 1; i < myEditedObjects.Length(); i++)
273     myProfiles[i] = new HYDROGUI_CurveCreatorProfile();
274     
275   HYDROGUI_ProfileDlg* aPanel = (HYDROGUI_ProfileDlg*)inputPanel();  
276   QMap<HYDROGUI_CurveCreatorProfile*, QColor> CurveToColor;
277   if( NewLen - ExistingProfLen )
278   {
279     //TODO move to ext func!
280     for (int i = ExistingProfLen + 1; i <= NewLen; i++)
281     {
282       Handle(HYDROData_Profile) aCProfile = Handle(HYDROData_Profile)::DownCast(myEditedObjects(i)); 
283       QString aProfileName;
284       if( !aCProfile.IsNull() )
285       {
286         Handle(HYDROData_ProfileUZ) aProfileUZ = aCProfile->GetProfileUZ( false );
287         if ( !aProfileUZ.IsNull() )
288         {
289           HYDROGUI_CurveCreatorProfile* CP = new HYDROGUI_CurveCreatorProfile();
290           myProfiles[i-1] = CP;
291           ProfileUZToCurveCrProfile(aProfileUZ, CP);
292           myCurveToProfile.Bind(CP, aCProfile);            
293         }
294       }
295     }
296     //int ext = myCurveToProfile.Extent(); //ext should be equal to lenP
297     QVector<QColor> PColors;
298     HYDROData_Tool::GenerateRepeatableRandColors(NewLen - ExistingProfLen, PColors);
299
300     for (int i = ExistingProfLen; i < NewLen; i++)
301     {
302       HYDROGUI_CurveCreatorProfile* CC = myProfiles[i];
303       const Handle(HYDROData_Profile)& CP = myCurveToProfile.Find(CC);
304       const QColor& CurCol = PColors[i-ExistingProfLen]; 
305       CurveToColor[CC] = CurCol;
306       const QString& profName = CP->GetName();
307       const QColor& PColor = CurCol;
308       if (!mySingleProfileMode)
309         aPanel->addProfileName(profName, PColor);
310       else
311         aPanel->setProfileName(profName);
312     }
313   }
314   displayPreviews(CurveToColor, ExistingProfLen, NewLen, false, false);
315 }
316
317 void HYDROGUI_ProfileOp::abortOperation()
318 {
319   erasePreview();
320   restoreCursor();
321
322   HYDROGUI_Operation::abortOperation();
323 }
324
325 void HYDROGUI_ProfileOp::commitOperation()
326 {
327   erasePreview();
328   restoreCursor();
329
330   HYDROGUI_Operation::commitOperation();
331 }
332
333 HYDROGUI_InputPanel* HYDROGUI_ProfileOp::createInputPanel() const
334 {
335   HYDROGUI_ProfileDlg* aDlg = new HYDROGUI_ProfileDlg( module(), getName(), mySingleProfileMode );
336   connect( aDlg, SIGNAL( AddProfiles() ), this, 
337     SLOT( onAddProfiles() ) );
338   connect( aDlg, SIGNAL( RemoveProfile(int) ), this, 
339     SLOT( onRemoveProfile(int) ) );  
340   return aDlg;
341 }
342
343 bool HYDROGUI_ProfileOp::processApply( int& theUpdateFlags,
344                                        QString& theErrorMsg,
345                                        QStringList& theBrowseObjectsEntries )
346 {
347   HYDROGUI_ProfileDlg* aPanel = ::qobject_cast<HYDROGUI_ProfileDlg*>( inputPanel() );
348   if ( !aPanel )
349     return false;
350
351   QStringList aProfileNames = aPanel->getProfileNames();
352   QVector<QString> aProfileNamesFiltered;
353   int i = 0;
354   foreach (QString profName, aProfileNames)
355   {
356     i++;
357     if ( profName.isEmpty() )
358     {
359       theErrorMsg = tr( "INCORRECT_OBJECT_NAME" ); //?
360       continue;
361     }
362     Handle(HYDROData_Entity) anObject = HYDROGUI_Tool::FindObjectByName( module(), profName );
363     if( !myIsEdit || (!anObject.IsNull() && myEditedObjects(i)->GetName() != anObject->GetName() ) )
364     {
365       profName = HYDROData_Tool::GenerateObjectName(doc(), "Profile");
366       //theErrorMsg = tr( "OBJECT_EXISTS_IN_DOCUMENT" ).arg( profName );
367       continue;
368     }
369     aProfileNamesFiltered.append(profName);
370   }
371   //  
372   theUpdateFlags = UF_Model;
373   if (myIsEdit)
374   {
375     for (int i = 1; i <= myEditedObjects.Size(); i++)
376     {
377       Handle(HYDROData_Profile) HProf = Handle(HYDROData_Profile)::DownCast(myEditedObjects(i));
378       int stat = CurveCrProfileToHProfile(myProfiles[i-1], HProf, aProfileNamesFiltered[i-1], true);
379       if (stat == 0)
380         continue;
381       else if (stat == -1)
382       {    
383         theErrorMsg = tr( "NUMBER_OF_PROFILE_POINTS_INCORRECT" ); //TODO resolve this
384         continue;
385       }    
386       module()->setIsToUpdate( HProf );
387     }
388     theUpdateFlags |= UF_OCCViewer | UF_OCC_Forced | UF_VTKViewer;
389   }
390   else
391   {
392     Handle(HYDROData_Profile) aNewProfileObj = Handle(HYDROData_Profile)::DownCast( doc()->CreateObject( KIND_PROFILE ) ); 
393     int stat = CurveCrProfileToHProfile(myProfiles[0], aNewProfileObj, aProfileNamesFiltered[0], false);
394     if (stat == 0)
395       return false;
396     else if (stat == -1)
397     {    
398       theErrorMsg = tr( "NUMBER_OF_PROFILE_POINTS_INCORRECT" );
399       return false;
400     }    
401     module()->setIsToUpdate( aNewProfileObj );
402     QString anEntry = HYDROGUI_DataObject::dataObjectEntry( aNewProfileObj );
403     theBrowseObjectsEntries.append( anEntry );
404   }
405
406   return true;
407 }
408
409 /*void HYDROGUI_ProfileOp::displayPreview()
410 {
411  /* HYDROGUI_ProfileDlg* aPanel = dynamic_cast<HYDROGUI_ProfileDlg*>( inputPanel() );
412   if( aPanel )
413   {
414     Handle(AIS_InteractiveContext) aCtx = aPanel->getAISContext();
415     if( !aCtx.IsNull() )
416     {
417       CurveCreator_Displayer* aDisplayer = new CurveCreator_Displayer( aCtx );
418       myProfile->setDisplayer( aDisplayer );
419       aDisplayer->display( myProfile->getAISObject( true ), true );
420     }
421   }
422 }*/
423
424 void HYDROGUI_ProfileOp::displayPreviews(
425   const QMap<HYDROGUI_CurveCreatorProfile*, QColor>& CurveToColor,
426   int firstIndProf, int lastIndProf, bool createNewDisplayer, bool SwitchToFirstProf)
427 {
428   HYDROGUI_ProfileDlg* aPanel = dynamic_cast<HYDROGUI_ProfileDlg*>( inputPanel() );
429   if( aPanel )
430   {
431     Handle(AIS_InteractiveContext) aCtx = aPanel->getAISContext();
432     if( !aCtx.IsNull() )
433     {
434       if (myDisplayer)
435       {
436         //delete myDisplayer;
437         //myDisplayer = NULL;
438       }
439       if (createNewDisplayer)
440         myDisplayer = new CurveCreator_Displayer( aCtx );
441       for (int i = firstIndProf; i < lastIndProf; i++ )
442       {
443         HYDROGUI_CurveCreatorProfile* CC = myProfiles[i];
444         QColor QCurCol = QColor(0,0,255); //def color
445         if (myIsEdit)
446           QCurCol = CurveToColor[CC];
447         Quantity_Color CurOCCCol = HYDROData_Tool::toOccColor(QCurCol);
448         CC->setDisplayer( myDisplayer );
449         CC->myPointAspectColor = CurOCCCol;
450         CC->myCurveColor = CurOCCCol;
451         CC->myLineWidth = 1;
452         myDisplayer->display( CC->getAISObject( true ), true );
453       }
454     }
455     if (SwitchToFirstProf && !myProfiles.empty())
456       aPanel->switchToFirstProfile();
457   }
458 }
459
460 void HYDROGUI_ProfileOp::erasePreview()
461 {
462   HYDROGUI_ProfileDlg* aPanel = dynamic_cast<HYDROGUI_ProfileDlg*>( inputPanel() );
463   //CurveCreator_Displayer* aDisplayer = myProfiles[0] ? myProfile[0]->getDisplayer() : 0;
464   if( aPanel && myDisplayer )
465   {
466     Handle(AIS_InteractiveContext) aCtx = aPanel->getAISContext();
467     if( !aCtx.IsNull() )
468     {
469       myDisplayer->eraseAll( true );
470     }
471   }
472   myCurveToProfile.Clear();
473 }
474
475 void HYDROGUI_ProfileOp::onRemoveProfile(int index)
476 {
477   if (index >= myProfiles.size() )
478     return;
479
480   if (!myIsEdit)
481     return;
482
483   HYDROGUI_CurveCreatorProfile* CP = myProfiles[index];
484   myProfiles.erase (myProfiles.begin()+index);
485   myEditedObjects.Remove(index+1);
486   myCurveToProfile.UnBind(CP);
487
488   HYDROGUI_ProfileDlg* aPanel = (HYDROGUI_ProfileDlg*)inputPanel();
489   //aPanel->reset();
490   //setPreviewManager( aPanel->viewManager() );
491   //setCursor();
492
493   aPanel->BlockProfileNameSignals(true);
494   aPanel->eraseProfile(index);
495
496   Handle(AIS_InteractiveContext) aCtx = aPanel->getAISContext();
497   if( !aCtx.IsNull() && myDisplayer)
498     myDisplayer->erase( CP->getAISObject(false), true);
499   CP->SetEraseAllState(false);
500   delete CP;
501   int selectedInd = aPanel->GetProfileSelectionIndex();
502   if (selectedInd > -1)
503     aPanel->SwitchToProfile(selectedInd);
504   aPanel->BlockProfileNameSignals(false);
505 }
506
507 bool HYDROGUI_ProfileOp::isValid( SUIT_Operation* theOtherOp ) const
508 {
509   HYDROGUI_DeleteOp* aDelOp = dynamic_cast<HYDROGUI_DeleteOp*>( theOtherOp );
510   if( aDelOp )
511     return true;
512   else
513     return false;
514 }