Salome HOME
IPAL54425: Quadrangle mapping fails on a quadrangle face with a seam
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_QuadrangleParamWdg.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 //  File   : StdMeshersGUI_QuadrangleParamWdg.cxx
20 //  Author : Open CASCADE S.A.S. (jfa)
21 //  SMESH includes
22
23 #include "StdMeshersGUI_QuadrangleParamWdg.h"
24
25 #include "SMESHGUI.h"
26 #include "SMESHGUI_SpinBox.h"
27 #include "SMESHGUI_Utils.h"
28 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
29
30 #include <GEOMBase.h>
31 #include <LightApp_SelectionMgr.h>
32 #include <SALOME_ListIO.hxx>
33 #include <SUIT_ResourceMgr.h>
34
35 // Qt includes
36 #include <QButtonGroup>
37 #include <QFrame>
38 #include <QGridLayout>
39 #include <QGroupBox>
40 #include <QLabel>
41 #include <QLineEdit>
42 #include <QListWidget>
43 #include <QListWidgetItem>
44 #include <QPushButton>
45 #include <QRadioButton>
46 #include <QTreeWidget>
47 #include <QVBoxLayout>
48
49 // IDL includes
50 #include <SALOMEconfig.h>
51 #include CORBA_CLIENT_HEADER(SMESH_BasicHypothesis)
52 #include CORBA_CLIENT_HEADER(GEOM_Gen)
53
54
55 #define SPACING 6
56 #define MARGIN 11
57
58 enum { TAB_TRANSITION, TAB_VERTEX, TAB_CORNERS, TAB_ENF_POINTS };
59
60 //================================================================================
61 // function : Constructor
62 // purpose  :
63 //================================================================================
64
65 StdMeshersGUI_QuadrangleParamCreator::StdMeshersGUI_QuadrangleParamCreator(const QString& aHypType)
66   : StdMeshersGUI_StdHypothesisCreator( aHypType )
67 {
68 }
69
70 //=======================================================================
71 //function : helpPage
72 //purpose  : 
73 //=======================================================================
74
75 QString  StdMeshersGUI_QuadrangleParamCreator::helpPage() const
76 {
77   return "2d_meshing_hypo.html#hypo-quad-params-anchor";
78 }
79
80 //=======================================================================
81 //function : buildFrame
82 //purpose  :
83 //=======================================================================
84
85 QFrame*  StdMeshersGUI_QuadrangleParamCreator::buildFrame()
86 {
87   QFrame* fr = new QFrame();
88
89   QGridLayout* lay = new QGridLayout( fr );
90   lay->setMargin( MARGIN );
91   lay->setSpacing( SPACING );
92   int row = 0;
93
94   myName = 0;
95   if ( isCreation() )
96   {
97     myName = new QLineEdit( fr );
98     QLabel* nameLab = new QLabel( tr("SMESH_NAME"));
99     lay->addWidget( nameLab, row, 0 );
100     lay->addWidget( myName,  row, 1 );
101     ++row;
102   }
103
104   // Transition type
105
106   myTypeWdg = new StdMeshersGUI_QuadrangleParamWdg( fr );
107
108   // Vertexes
109
110   myVertexSelWdg = new StdMeshersGUI_SubShapeSelectorWdg( fr, TopAbs_VERTEX );
111   myVertexSelWdg->layout()->setMargin( MARGIN );
112
113   // Enforced Points
114
115   QWidget* pointsFrame = new QWidget( fr );
116   QVBoxLayout* pointsLay = new QVBoxLayout( pointsFrame );
117   pointsLay->setMargin(MARGIN);
118   pointsLay->setSpacing(SPACING);
119
120   // shapes
121   QGroupBox* shapesGroup = new QGroupBox( tr("SHAPES"), pointsFrame );
122   myShapesList = new QListWidget( shapesGroup );
123   myAddShapeBut = new QPushButton( tr("SMESH_BUT_ADD"), shapesGroup );
124   QPushButton* remShapeBut = new QPushButton( tr("SMESH_BUT_REMOVE"), shapesGroup );
125   //
126   QGridLayout* shapesLay = new QGridLayout( shapesGroup );
127   shapesLay->setMargin(MARGIN);
128   shapesLay->setSpacing(SPACING);
129   shapesLay->addWidget( myShapesList,  0, 0, 3, 2 );
130   shapesLay->addWidget( myAddShapeBut, 0, 2 );
131   shapesLay->addWidget( remShapeBut,   1, 2 );
132   shapesLay->setColumnStretch( 0, 1 );
133   shapesLay->setRowStretch   ( 2, 1 );
134
135   // coords
136   QGroupBox* coordsGroup = new QGroupBox( tr("POINTS"), pointsFrame );
137   myCoordsTreeWdg = new QTreeWidget( coordsGroup );
138   myCoordsTreeWdg->setColumnCount ( 3 );
139   myCoordsTreeWdg->setHeaderLabels( QStringList() << "X" << "Y" << "Z" );
140   myCoordsTreeWdg->setItemDelegate( new ItemDelegate( myCoordsTreeWdg ));
141   QPushButton* addCoordBut = new QPushButton( tr("SMESH_BUT_ADD"), coordsGroup );
142   QPushButton* remCoordBut = new QPushButton( tr("SMESH_BUT_REMOVE"), coordsGroup );
143   //
144   QGridLayout* coordsLay = new QGridLayout( coordsGroup );
145   coordsLay->setMargin(MARGIN);
146   coordsLay->setSpacing(SPACING);
147   coordsLay->addWidget( myCoordsTreeWdg, 0, 0, 3, 2 );
148   coordsLay->addWidget( addCoordBut,     0, 2 );
149   coordsLay->addWidget( remCoordBut,     1, 2 );
150   coordsLay->setColumnStretch( 0, 1 );
151   coordsLay->setRowStretch   ( 2, 1 );
152
153   pointsLay->addWidget( shapesGroup );
154   pointsLay->addWidget( coordsGroup );
155
156   // Corners
157
158   myCornersSelWdg = new StdMeshersGUI_SubShapeSelectorWdg( fr, TopAbs_VERTEX );
159   myCornersSelWdg->layout()->setMargin( MARGIN );
160
161   // Tabs
162   myTabs = new QTabWidget( fr );
163   myTabs->addTab( myTypeWdg,       tr("TRANSITION"));
164   myTabs->addTab( myVertexSelWdg,  tr("SMESH_BASE_VERTEX"));
165   myTabs->addTab( myCornersSelWdg, tr("CORNERS"));
166   myTabs->addTab( pointsFrame,     tr("ENF_NODES"));
167
168   lay->addWidget( myTabs, row, 0, 2, 3 );
169
170   // signals
171   connect( myTypeWdg,     SIGNAL( typeChanged(int)),   SLOT( onTypeChanged(int)));
172   connect( myAddShapeBut, SIGNAL( clicked()),          SLOT( onAddShape() ));
173   connect( remShapeBut,   SIGNAL( clicked()),          SLOT( onRemoveShape() ));
174   connect( addCoordBut,   SIGNAL( clicked()),          SLOT( onAddPoint() ));
175   connect( remCoordBut,   SIGNAL( clicked()),          SLOT( onRemovePoint() ));
176   connect( myTabs,        SIGNAL( currentChanged(int)),SLOT( onTabChanged(int)));
177
178   LightApp_SelectionMgr* selMgr = SMESHGUI::GetSMESHGUI()->selectionMgr();
179   connect( selMgr, SIGNAL(currentSelectionChanged()), SLOT( onSelectionChanged()));
180
181   return fr;
182 }
183
184 //=======================================================================
185 //function : retrieveParams
186 //purpose  :
187 //=======================================================================
188
189 void StdMeshersGUI_QuadrangleParamCreator::retrieveParams() const
190 {
191   StdMeshers::StdMeshers_QuadrangleParams_var h =
192     StdMeshers::StdMeshers_QuadrangleParams::_narrow( initParamsHypothesis() );
193
194   // name
195   if( myName )
196     myName->setText( hypName() );
197
198   // main shape
199   myVertexSelWdg->SetMaxSize(1);
200   QString anEntry    = SMESHGUI_GenericHypothesisCreator::getShapeEntry();
201   QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry();
202   if ( anEntry.isEmpty() )
203     anEntry = h->GetObjectEntry();
204   myVertexSelWdg->SetGeomShapeEntry(anEntry,aMainEntry);
205   myCornersSelWdg->SetGeomShapeEntry(anEntry,aMainEntry);
206
207   if ( !isCreation())
208   {
209     // type
210     myTypeWdg->SetType(int(h->GetQuadType()));
211
212     // vertex
213     int vertID = h->GetTriaVertex();
214     if (vertID > 0) {
215       SMESH::long_array_var aVec = new SMESH::long_array;
216       aVec->length(1);
217       aVec[0] = vertID;
218       myVertexSelWdg->SetListOfIDs(aVec);
219     }
220
221     // corners
222     SMESH::long_array_var aVec = h->GetCorners();
223     myCornersSelWdg->SetListOfIDs( aVec );
224
225     // enforced nodes
226     GEOM::ListOfGO_var     shapes;
227     SMESH::nodes_array_var points;
228     h->GetEnforcedNodes( shapes, points );
229     for ( size_t i = 0; i < shapes->length(); ++i )
230     {
231       CORBA::String_var name  = shapes[i]->GetName();
232       CORBA::String_var entry = shapes[i]->GetStudyEntry();
233       QListWidgetItem* item = new QListWidgetItem( name.in() );
234       item->setData( Qt::UserRole, entry.in() );
235       myShapesList->addItem( item );
236     }
237     for ( size_t i = 0; i < points->length(); ++i )
238     {
239       QTreeWidgetItem* item = new QTreeWidgetItem
240         ( QStringList()
241           << QString::number( points[i].x )
242           << QString::number( points[i].y )
243           << QString::number( points[i].z ));
244       item->setFlags( item->flags() | Qt::ItemIsEditable );
245       myCoordsTreeWdg->addTopLevelItem( item );
246     }
247   }
248   ((StdMeshersGUI_QuadrangleParamCreator*) this)->onSelectionChanged();
249 }
250
251 //=======================================================================
252 //function : storeParams
253 //purpose  :
254 //=======================================================================
255
256 QString  StdMeshersGUI_QuadrangleParamCreator::storeParams() const
257 {
258   StdMeshers::StdMeshers_QuadrangleParams_var h =
259     StdMeshers::StdMeshers_QuadrangleParams::_narrow( hypothesis() );
260
261   // name
262   if( myName )
263     SMESH::SetName( SMESH::FindSObject( h ), myName->text().toUtf8().constData() );
264
265   // transition
266   h->SetQuadType( StdMeshers::QuadType( myTypeWdg->GetType()) );
267
268   // vertex
269   if ( myVertexSelWdg->GetListSize() > 0 )
270   {
271     h->SetTriaVertex( myVertexSelWdg->GetListOfIDs()[0] ); // getlist must be called once
272     h->SetObjectEntry( myVertexSelWdg->GetMainShapeEntry() );
273   }
274   else
275   {
276     h->SetTriaVertex( -1 );
277   }
278
279   // corners
280   h->SetCorners( myCornersSelWdg->GetListOfIDs() );
281
282   // enfored nodes
283
284   GEOM::ListOfGO_var goList = new GEOM::ListOfGO;
285   int nbShapes = 0;
286   goList->length( myShapesList->count() );
287   for ( int i = 0; i < myShapesList->count(); ++i )
288   {
289     QListWidgetItem* item = myShapesList->item(i);
290     QString         entry = item->data( Qt::UserRole ).toString();
291     Handle(SALOME_InteractiveObject) io =
292       new SALOME_InteractiveObject( entry.toStdString().c_str(), "GEOM" );
293     GEOM::GEOM_Object_var go = GEOMBase::ConvertIOinGEOMObject( io );
294     if ( !go->_is_nil() )
295       goList[ nbShapes++ ] = go;
296   }
297   goList->length( nbShapes );
298   
299   SMESH::nodes_array_var points = new SMESH::nodes_array;
300   points->length( myCoordsTreeWdg->topLevelItemCount() );
301   for ( int i = 0; i < myCoordsTreeWdg->topLevelItemCount(); ++i )
302   {
303     QTreeWidgetItem* item = myCoordsTreeWdg->topLevelItem( i );
304     points[i].x = item->text(0).toInt();
305     points[i].y = item->text(1).toInt();
306     points[i].z = item->text(2).toInt();
307   }
308   h->SetEnforcedNodes( goList, points );
309
310   return "";
311 }
312
313 //=======================================================================
314 //function : onTypeChanged
315 //purpose  :
316 //=======================================================================
317
318 void StdMeshersGUI_QuadrangleParamCreator::onTypeChanged(int type)
319 {
320   myTabs->setTabEnabled( TAB_ENF_POINTS, ( type != StdMeshers::QUAD_REDUCED ));
321 }
322
323 //=======================================================================
324 //function : onAddShape
325 //purpose  : 
326 //=======================================================================
327
328 void StdMeshersGUI_QuadrangleParamCreator::onAddShape()
329 {
330   if ( !mySelectedShapeIO.IsNull() )
331   {
332     QListWidgetItem* item = new QListWidgetItem( mySelectedShapeIO->getName() );
333     item->setData( Qt::UserRole, mySelectedShapeIO->getEntry() );
334     myShapesList->addItem( item );
335     mySelectedShapeIO.Nullify();
336     myAddShapeBut->setEnabled( false );
337   }
338 }
339
340 //=======================================================================
341 //function : onRemoveShape
342 //purpose  : 
343 //=======================================================================
344
345 void StdMeshersGUI_QuadrangleParamCreator::onRemoveShape()
346 {
347   if ( QListWidgetItem * item = myShapesList->currentItem() )
348     delete item;
349   onSelectionChanged();
350 }
351
352 //=======================================================================
353 //function : onAddPoint
354 //purpose  : 
355 //=======================================================================
356
357 void StdMeshersGUI_QuadrangleParamCreator::onAddPoint()
358 {
359   QTreeWidgetItem* item = new QTreeWidgetItem( QStringList() << "0" << "0" << "0" );
360   item->setFlags( item->flags() | Qt::ItemIsEditable );
361   myCoordsTreeWdg->addTopLevelItem( item );
362 }
363
364 //=======================================================================
365 //function : onRemovePoint
366 //purpose  :
367 //=======================================================================
368
369 void StdMeshersGUI_QuadrangleParamCreator::onRemovePoint()
370 {
371   if ( myCoordsTreeWdg->topLevelItemCount() )
372     delete myCoordsTreeWdg->currentItem();
373 }
374
375 //=======================================================================
376 //function : onSelectionChanged
377 //purpose  : 
378 //=======================================================================
379
380 void StdMeshersGUI_QuadrangleParamCreator::onSelectionChanged()
381 {
382   mySelectedShapeIO.Nullify();
383
384   // find a sole selected geometry
385   LightApp_SelectionMgr* selMgr = SMESHGUI::GetSMESHGUI()->selectionMgr();
386   SALOME_ListIO          selList;
387   selMgr->selectedObjects( selList );
388   SALOME_ListIteratorOfListIO selIt( selList );
389   for ( ; selIt.More(); selIt.Next() )
390   {
391     GEOM::GEOM_Object_var go = GEOMBase::ConvertIOinGEOMObject( selIt.Value() );
392     if ( !go->_is_nil() )
393     {
394       if ( !mySelectedShapeIO.IsNull() )
395       {
396         mySelectedShapeIO.Nullify();
397         break;
398       }
399       mySelectedShapeIO = selIt.Value();
400       if ( !mySelectedShapeIO->getName() || !mySelectedShapeIO->getName()[0] )
401         mySelectedShapeIO.Nullify();
402     }
403   }
404   // check if a selected geometry is not already in myShapesList
405   if ( !mySelectedShapeIO.IsNull() )
406   {
407     for ( int i = 0; i < myShapesList->count(); ++i )
408       if ( myShapesList->item(i)->data( Qt::UserRole ) == mySelectedShapeIO->getEntry() )
409       {
410         mySelectedShapeIO.Nullify();
411         break;
412       }
413   }
414   myAddShapeBut->setEnabled( !mySelectedShapeIO.IsNull() );
415 }
416
417 //=======================================================================
418 //function : onTabChanged
419 //purpose  : 
420 //=======================================================================
421
422 void StdMeshersGUI_QuadrangleParamCreator::onTabChanged(int i)
423 {
424   myVertexSelWdg->ShowPreview( i == TAB_VERTEX );
425   myCornersSelWdg->ShowPreview( i == TAB_CORNERS );
426 }
427
428 //================================================================================
429 // function : Constructor
430 // purpose  :
431 //================================================================================
432
433 StdMeshersGUI_QuadrangleParamWdg::StdMeshersGUI_QuadrangleParamWdg (QWidget * parent)
434   : QWidget(parent), myType(0)
435 {
436   myType = new QButtonGroup (this);
437
438   QGridLayout* typeLay = new QGridLayout( this );
439
440   typeLay->setMargin(MARGIN);
441   typeLay->setSpacing(SPACING);
442
443   QString aTypeKey ("SMESH_QUAD_TYPE_%1");
444   QString aPictKey ("ICON_StdMeshers_Quadrangle_Params_%1");
445
446   int itype = 0;
447   for (; itype < int(StdMeshers::QUAD_NB_TYPES); itype++) {
448     QRadioButton* rbi = new QRadioButton (tr(aTypeKey.arg(itype).toLatin1()), this);
449     QPixmap pmi (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr(aPictKey.arg(itype).toLatin1())));
450     QLabel* pli = new QLabel (this);
451     pli->setPixmap(pmi);
452     typeLay->addWidget(rbi, itype, 0, 1, 1);
453     typeLay->addWidget(pli, itype, 1, 1, 1);
454     myType->addButton(rbi, itype);
455   }
456   myType->button(0)->setChecked(true);
457
458   setLayout(typeLay);
459   setMinimumWidth(300);
460
461   connect( myType, SIGNAL( buttonClicked(int)), this, SIGNAL( typeChanged(int)));
462 }
463
464 //================================================================================
465 // function : Destructor
466 // purpose  :
467 //================================================================================
468 StdMeshersGUI_QuadrangleParamWdg::~StdMeshersGUI_QuadrangleParamWdg()
469 {
470 }
471
472 //=================================================================================
473 // function : SetType
474 // purpose  :
475 //=================================================================================
476 void StdMeshersGUI_QuadrangleParamWdg::SetType (int theType)
477 {
478   myType->button(theType)->setChecked(true);
479 }
480
481 //=================================================================================
482 // function : GetType
483 // purpose  :
484 //=================================================================================
485 int StdMeshersGUI_QuadrangleParamWdg::GetType()
486 {
487   return myType->checkedId();
488 }
489
490 //================================================================================
491 /*!
492   \brief Constructor
493 */
494 StdMeshersGUI_QuadrangleParamCreator::
495 ItemDelegate::ItemDelegate( QObject* parent ) : QItemDelegate( parent )
496 {
497 }
498 //================================================================================
499 /*!
500   \brief Create item editor widget
501 */
502 QWidget* StdMeshersGUI_QuadrangleParamCreator::
503 ItemDelegate::createEditor( QWidget*                    parent,
504                             const QStyleOptionViewItem& option,
505                             const QModelIndex&          index ) const
506 {
507   SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
508   sb->RangeStepAndValidator( COORD_MIN, COORD_MAX, 10 );
509   return sb;
510 }