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