Salome HOME
PAL11988. add reverse connectivity for QUAD_EDGE
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_AddQuadraticElementDlg.cxx
1 #include "SMESHGUI_AddQuadraticElementDlg.h"
2
3 #include "SMESHGUI.h"
4 #include "SMESHGUI_Utils.h"
5 #include "SMESHGUI_VTKUtils.h"
6 #include "SMESHGUI_MeshUtils.h"
7 #include "SMESHGUI_IdValidator.h"
8 #include "SMESH_ActorUtils.h"
9
10 #include "SMDS_Mesh.hxx"
11 #include "SMESH_Actor.h"
12
13 #include "SUIT_Session.h"
14 #include "SUIT_MessageBox.h"
15
16 #include "SVTK_Selection.h"
17 #include "SVTK_Selector.h"
18 #include "SALOME_ListIO.hxx"
19 #include "SALOME_ListIteratorOfListIO.hxx"
20
21 #include "SalomeApp_Study.h"
22 #include "SalomeApp_Application.h"
23
24 #include "SVTK_ViewModel.h"
25 #include "SVTK_ViewWindow.h"
26
27 #include "utilities.h"
28
29 // OCCT Includes
30 #include <TColStd_MapOfInteger.hxx>
31 #include <TColStd_IndexedMapOfInteger.hxx>
32
33 // VTK Includes
34 #include <vtkCell.h>
35 #include <vtkIdList.h>
36 #include <vtkIntArray.h>
37 #include <vtkCellArray.h>
38 #include <vtkUnsignedCharArray.h>
39 #include <vtkUnstructuredGrid.h>
40 #include <vtkDataSetMapper.h>
41 #include <vtkProperty.h>
42
43 #include <vtkQuadraticEdge.h>
44 #include <vtkQuadraticTriangle.h>
45 #include <vtkQuadraticQuad.h>
46 #include <vtkQuadraticHexahedron.h>
47 #include <vtkQuadraticTetra.h>
48
49 // QT Includes
50 #include <qbuttongroup.h>
51 #include <qgroupbox.h>
52 #include <qlabel.h>
53 #include <qlineedit.h>
54 #include <qpushbutton.h>
55 #include <qradiobutton.h>
56 #include <qlayout.h>
57 #include <qpixmap.h>
58 #include <qcheckbox.h>
59
60 // STL includes
61 #include <list>
62
63 using namespace std;
64
65 namespace SMESH {
66
67   void ReverseConnectivity( vector<int> & ids, int type )
68   {
69     // for reverse connectivity of other types keeping the first id, see
70     // void SMESH_VisualObjDef::buildElemPrs() in SMESH_Object.cxx:900
71     const int* conn = 0;
72    
73     switch ( type ) {
74     case QUAD_TETRAHEDRON: {
75       static int aConn[] = {0,2,1,3,6,5,4,7,9,8};
76       conn = aConn;
77       break;
78     }
79     case QUAD_PYRAMID: {
80       static int aConn[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
81       conn = aConn;
82       break;
83     }
84     case QUAD_PENTAHEDRON: {
85       static int aConn[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
86       conn = aConn;
87       break;
88     }
89     case QUAD_HEXAHEDRON: {
90       static int aConn[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
91       conn = aConn;
92       break;
93     }
94     case QUAD_EDGE: {
95       static int aConn[] = {1,0,2};
96       conn = aConn;
97       break;
98     }
99     default:;
100     }
101     if ( !conn ) {
102       reverse( ids.begin(), ids.end() );
103     }
104     else {
105       vector<int> aRevIds( ids.size() );
106       for ( int i = 0; i < ids.size(); i++)
107         aRevIds[ i ] = ids[ conn[ i ]];
108       ids = aRevIds;
109     }
110   }
111
112   class TElementSimulation {
113     SalomeApp_Application* myApplication;
114     SUIT_ViewWindow* myViewWindow;
115     SVTK_ViewWindow* myVTKViewWindow;
116
117     SALOME_Actor* myPreviewActor;
118     vtkDataSetMapper* myMapper;
119     vtkUnstructuredGrid* myGrid;
120     //vtkProperty* myBackProp, *myProp;
121
122     float anRGB[3], aBackRGB[3];
123
124   public:
125     TElementSimulation (SalomeApp_Application* theApplication)
126     {
127       myApplication = theApplication;
128       SUIT_ViewManager* mgr = theApplication->activeViewManager();
129       if (!mgr) return;
130       myViewWindow = mgr->getActiveView();
131       myVTKViewWindow = GetVtkViewWindow(myViewWindow);
132
133       myGrid = vtkUnstructuredGrid::New();
134
135       // Create and display actor
136       myMapper = vtkDataSetMapper::New();
137       myMapper->SetInput(myGrid);
138
139       myPreviewActor = SALOME_Actor::New();
140       myPreviewActor->PickableOff();
141       myPreviewActor->VisibilityOff();
142       myPreviewActor->SetMapper(myMapper);
143
144       vtkProperty* myProp = vtkProperty::New();
145       GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) );
146       myProp->SetColor( anRGB[0], anRGB[1], anRGB[2] );
147       myPreviewActor->SetProperty( myProp );
148       myProp->Delete();
149
150       vtkProperty* myBackProp = vtkProperty::New();
151       GetColor( "SMESH", "backface_color", aBackRGB[0], aBackRGB[1], aBackRGB[2], QColor( 0, 0, 255 ) );
152       myBackProp->SetColor( aBackRGB[0], aBackRGB[1], aBackRGB[2] );
153       myPreviewActor->SetBackfaceProperty( myBackProp );
154       myBackProp->Delete();
155
156       myVTKViewWindow->AddActor(myPreviewActor);
157     }
158
159     typedef std::vector<vtkIdType> TVTKIds;
160     void SetPosition (SMESH_Actor* theActor,
161                       const int    theType,
162                       TVTKIds&     theIds,
163                       const int    theMode,
164                       const bool   theReverse)
165     {
166       vtkUnstructuredGrid *aGrid = theActor->GetUnstructuredGrid();
167       myGrid->SetPoints(aGrid->GetPoints());
168
169       //add points
170
171       vtkIdType aType = 0;
172
173       switch (theType) {
174       case QUAD_EDGE:
175         aType = VTK_QUADRATIC_EDGE;
176         break;
177       case QUAD_TRIANGLE:
178         aType = VTK_QUADRATIC_TRIANGLE; 
179         break;
180       case QUAD_QUADRANGLE:
181         aType = VTK_QUADRATIC_QUAD; 
182         break;
183       case QUAD_TETRAHEDRON:
184         aType = VTK_QUADRATIC_TETRA; 
185         break;
186       case QUAD_PYRAMID:
187         //aType = VTK_QUADRATIC_PYRAMID; // NOT SUPPORTED IN VTK4.2
188         aType = VTK_CONVEX_POINT_SET;
189         break;
190       case QUAD_PENTAHEDRON:
191         //aType = VTK_QUADRATIC_WEDGE; // NOT SUPPORTED IN VTK4.2
192         aType = VTK_CONVEX_POINT_SET;
193         break; 
194       case QUAD_HEXAHEDRON:
195         aType = VTK_QUADRATIC_HEXAHEDRON;
196         break;
197       }
198
199       // take care of orientation
200       if ( aType == VTK_CONVEX_POINT_SET ) {
201         if ( theReverse && theMode == VTK_SURFACE ) {
202           //myPreviewActor->GetProperty()->SetColor( aBackRGB[0], aBackRGB[1], aBackRGB[2] );
203         }
204       }
205       else {
206         // VTK cell connectivity opposites the MED one
207         if ( !theReverse ) {
208           ReverseConnectivity( theIds, theType );
209         }
210       }
211             
212       myGrid->Reset();
213       vtkIdList *anIds = vtkIdList::New();
214       
215       for (int i = 0, iEnd = theIds.size(); i < iEnd; i++) {
216         anIds->InsertId(i,theIds[i]);
217         //std::cout << i<< ": " << theIds[i] << std::endl;
218       }
219       
220       myGrid->InsertNextCell(aType,anIds);
221       anIds->Delete();
222       
223       myGrid->Modified();
224
225       myPreviewActor->GetMapper()->Update();
226       myPreviewActor->SetRepresentation( theMode );
227       SetVisibility(true);
228
229       // restore normal orientation
230       if ( aType == VTK_CONVEX_POINT_SET ) {
231         if ( theReverse  && theMode == VTK_SURFACE ) {
232           //myPreviewActor->GetProperty()->SetColor( anRGB[0], anRGB[1], anRGB[2] );
233         }
234       }
235     }
236
237
238     void SetVisibility (bool theVisibility)
239     {
240       myPreviewActor->SetVisibility(theVisibility);
241       RepaintCurrentView();
242     }
243
244
245     ~TElementSimulation()
246     {
247       if (FindVtkViewWindow(myApplication->activeViewManager(), myViewWindow)) {
248         myVTKViewWindow->RemoveActor(myPreviewActor);
249       }
250       myPreviewActor->Delete();
251
252       myMapper->RemoveAllInputs();
253       myMapper->Delete();
254
255       myGrid->Delete();
256
257 //       myProp->Delete();
258 //       myBackProp->Delete();
259     }
260   };
261 }
262
263
264 // Define the sequences of ids
265 static int FirstEdgeIds[] = {0};
266 static int LastEdgeIds[] =  {1};
267
268 static int FirstTriangleIds[] = {0,1,2};
269 static int LastTriangleIds[] =  {1,2,0};
270
271 static int FirstQuadrangleIds[] = {0,1,2,3};
272 static int LastQuadrangleIds[] =  {1,2,3,0};
273
274 static int FirstTetrahedronIds[] = {0,1,2,3,3,3};
275 static int LastTetrahedronIds[] =  {1,2,0,0,1,2};
276
277 static int FirstPyramidIds[] = {0,1,2,3,4,4,4,4};
278 static int LastPyramidIds[] =  {1,2,3,0,0,1,2,3};
279
280 static int FirstPentahedronIds[] = {0,1,2,3,4,5,0,1,2};
281 static int LastPentahedronIds[] =  {1,2,0,4,5,3,3,4,5};
282
283 static int FirstHexahedronIds[] = {0,1,2,3,4,5,6,7,0,1,2,3};
284 static int LastHexahedronIds[] =  {1,2,3,0,5,6,7,4,4,5,6,7};
285
286
287
288 //=================================================================================
289 // function : SMESHGUI_AddQuadraticElementDlg()
290 // purpose  : constructor
291 //=================================================================================
292 SMESHGUI_AddQuadraticElementDlg::SMESHGUI_AddQuadraticElementDlg( SMESHGUI* theModule,
293                                                                   const int theType,
294                                                                   const char* name,
295                                                                   bool modal, WFlags fl)
296      : QDialog( SMESH::GetDesktop( theModule ), name, modal, WStyle_Customize | WStyle_NormalBorder |
297                 WStyle_Title | WStyle_SysMenu | Qt::WDestructiveClose),
298      mySMESHGUI( theModule ),
299      mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
300      myType( theType )
301 {
302   SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>
303     (SUIT_Session::session()->activeApplication());
304   
305   mySimulation = new SMESH::TElementSimulation (anApp);
306   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
307
308   QString anElementName;
309
310   switch ( myType ) {
311   case QUAD_EDGE:
312     anElementName = QString("QUADRATIC_EDGE");
313     break;
314   case QUAD_TRIANGLE:
315     anElementName = QString("QUADRATIC_TRIANGLE");
316     break; 
317   case QUAD_QUADRANGLE:
318     anElementName = QString("QUADRATIC_QUADRANGLE");
319     break;
320   case QUAD_TETRAHEDRON:
321     anElementName = QString("QUADRATIC_TETRAHEDRON");
322     break;
323   case QUAD_PYRAMID:
324     anElementName = QString("QUADRATIC_PYRAMID");
325     break;
326   case QUAD_PENTAHEDRON:
327     anElementName = QString("QUADRATIC_PENTAHEDRON");
328     break;
329   case QUAD_HEXAHEDRON:
330     anElementName = QString("QUADRATIC_HEXAHEDRON");
331     break;
332   default:
333     myType = QUAD_EDGE;
334     anElementName = QString("QUADRATIC_EDGE");
335   }
336
337   QString iconName           = tr(QString("ICON_DLG_%1").arg(anElementName));
338   QString caption            = tr(QString("SMESH_ADD_%1_TITLE").arg(anElementName));
339   QString argumentsGrTitle   = tr(QString("SMESH_ADD_%1").arg(anElementName));
340   QString constructorGrTitle = tr(QString("SMESH_%1").arg(anElementName));
341   
342   QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", iconName));
343   QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
344
345   if (!name)
346     setName("SMESHGUI_AddQuadraticElementDlg");
347   setCaption(caption);
348   
349   setSizeGripEnabled(TRUE);
350   QGridLayout* aDialogLayout = new QGridLayout(this);
351   aDialogLayout->setSpacing(6);
352   aDialogLayout->setMargin(11);
353
354   /***************************************************************/
355   GroupConstructors = new QButtonGroup(this, "GroupConstructors");
356   GroupConstructors->setTitle(constructorGrTitle);
357
358   GroupConstructors->setExclusive(TRUE);
359   GroupConstructors->setColumnLayout(0, Qt::Vertical);
360   GroupConstructors->layout()->setSpacing(0);
361   GroupConstructors->layout()->setMargin(0);
362   GroupConstructors->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
363   QGridLayout* aGroupConstructorsLayout = new QGridLayout(GroupConstructors->layout());
364   aGroupConstructorsLayout->setAlignment(Qt::AlignTop);
365   aGroupConstructorsLayout->setSpacing(6);
366   aGroupConstructorsLayout->setMargin(11);
367   myRadioButton1 = new QRadioButton(GroupConstructors, "myRadioButton1");
368   myRadioButton1->setText(tr("" ));
369   myRadioButton1->setPixmap(image0);
370   myRadioButton1->setChecked(TRUE);
371   myRadioButton1->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, myRadioButton1->sizePolicy().hasHeightForWidth()));
372   aGroupConstructorsLayout->addWidget(myRadioButton1, 0, 0);
373   aGroupConstructorsLayout->addItem( new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 1);
374   aDialogLayout->addWidget(GroupConstructors, 0, 0);
375
376   /***************************************************************/
377   GroupArguments = new QGroupBox(this, "GroupArguments");
378   GroupArguments->setTitle(argumentsGrTitle);
379   GroupArguments->setColumnLayout(0, Qt::Vertical);
380   GroupArguments->layout()->setSpacing(0);
381   GroupArguments->layout()->setMargin(0);
382   GroupArguments->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding));
383   QGridLayout* aGroupArgumentsLayout = new QGridLayout(GroupArguments->layout());
384   aGroupArgumentsLayout->setAlignment(Qt::AlignTop);
385   aGroupArgumentsLayout->setSpacing(6);
386   aGroupArgumentsLayout->setMargin(11);
387   QLabel* aCornerNodesLabel = new QLabel(GroupArguments, "aCornerNodesLabel");
388   aCornerNodesLabel->setText(tr("SMESH_CORNER_NODES" ));
389   aGroupArgumentsLayout->addWidget(aCornerNodesLabel, 0, 0);
390   mySelectButton = new QPushButton(GroupArguments, "mySelectButton");
391   mySelectButton->setPixmap(image1);
392   aGroupArgumentsLayout->addWidget(mySelectButton, 0, 1);
393   myCornerNodes = new QLineEdit(GroupArguments, "myCornerNodes");
394   aGroupArgumentsLayout->addWidget(myCornerNodes, 0, 2);
395
396   myTable = new QTable(GroupArguments);
397   aGroupArgumentsLayout->addMultiCellWidget(myTable, 1, 1, 0, 2);
398  
399   myReverseCB = new QCheckBox(GroupArguments, "myReverseCB");
400   myReverseCB->setText(tr("SMESH_REVERSE" ));
401   aGroupArgumentsLayout->addWidget(myReverseCB, 2, 0);
402  
403   aDialogLayout->addWidget(GroupArguments, 1, 0);
404
405   
406   /***************************************************************/
407   GroupButtons = new QGroupBox(this, "GroupButtons");
408   GroupButtons->setColumnLayout(0, Qt::Vertical);
409   GroupButtons->layout()->setSpacing(0);
410   GroupButtons->layout()->setMargin(0);
411   GroupButtons->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
412   QGridLayout* aGroupButtonsLayout = new QGridLayout(GroupButtons->layout());
413   aGroupButtonsLayout->setAlignment(Qt::AlignTop);
414   aGroupButtonsLayout->setSpacing(6);
415   aGroupButtonsLayout->setMargin(11);
416   buttonCancel = new QPushButton(GroupButtons, "buttonCancel");
417   buttonCancel->setText(tr("SMESH_BUT_CLOSE" ));
418   buttonCancel->setAutoDefault(TRUE);
419   aGroupButtonsLayout->addWidget(buttonCancel, 0, 3);
420   buttonApply = new QPushButton(GroupButtons, "buttonApply");
421   buttonApply->setText(tr("SMESH_BUT_APPLY" ));
422   buttonApply->setAutoDefault(TRUE);
423   aGroupButtonsLayout->addWidget(buttonApply, 0, 1);
424   aGroupButtonsLayout->addItem( new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 2);
425   buttonOk = new QPushButton(GroupButtons, "buttonOk");
426   buttonOk->setText(tr("SMESH_BUT_OK" ));
427   buttonOk->setAutoDefault(TRUE);
428   buttonOk->setDefault(TRUE);
429   aGroupButtonsLayout->addWidget(buttonOk, 0, 0);
430   buttonHelp = new QPushButton(GroupButtons, "buttonHelp");
431   buttonHelp->setText(tr("SMESH_BUT_HELP" ));
432   buttonHelp->setAutoDefault(TRUE);
433   aGroupButtonsLayout->addWidget(buttonHelp, 0, 4);
434
435   aDialogLayout->addWidget(GroupButtons, 2, 0);
436
437   Init(); /* Initialisations */
438 }
439
440 //=================================================================================
441 // function : ~SMESHGUI_AddQuadraticElementDlg()
442 // purpose  : Destroys the object and frees any allocated resources
443 //=================================================================================
444 SMESHGUI_AddQuadraticElementDlg::~SMESHGUI_AddQuadraticElementDlg()
445 {
446   // no need to delete child widgets, Qt does it all for us
447   delete mySimulation;
448 }
449
450 //=================================================================================
451 // function : Init()
452 // purpose  :
453 //=================================================================================
454 void SMESHGUI_AddQuadraticElementDlg::Init()
455 {
456   GroupArguments->show();
457   myRadioButton1->setChecked(TRUE);
458   myIsEditCorners = true;
459   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
460   
461   myActor = 0;
462
463   int aNumRows;
464
465   switch (myType) {
466   case QUAD_EDGE:
467     aNumRows = 1;
468     myNbCorners = 2;
469     myHelpFileName = "/files/adding_nodes_and_elements.htm#?"; //Adding_edges
470     break;
471   case QUAD_TRIANGLE:
472     aNumRows = 3;
473     myNbCorners = 3;
474     myHelpFileName = "/files/adding_nodes_and_elements.htm#?"; //Adding_triangles
475     break;
476   case QUAD_QUADRANGLE:
477     aNumRows = 4;
478     myNbCorners = 4;
479     myHelpFileName = "/files/adding_nodes_and_elements.htm#?"; //Adding_quadrangles
480     break;
481   case QUAD_TETRAHEDRON:
482     aNumRows = 6;
483     myNbCorners = 4;
484     myHelpFileName = "/files/adding_nodes_and_elements.htm#?"; //Adding_tetrahedrons
485     break;
486   case QUAD_PYRAMID:
487     aNumRows = 8;
488     myNbCorners = 5;
489     myHelpFileName = "/files/adding_nodes_and_elements.htm#?";
490     break;
491   case QUAD_PENTAHEDRON:
492     aNumRows = 9;
493     myNbCorners = 6;
494     myHelpFileName = "/files/adding_nodes_and_elements.htm#?";
495     break; 
496   case QUAD_HEXAHEDRON:
497     aNumRows = 12;
498     myNbCorners = 8;
499     myHelpFileName = "/files/adding_nodes_and_elements.htm#?"; //Adding_hexahedrons
500     break;
501   }
502     
503   myCornerNodes->setValidator(new SMESHGUI_IdValidator(this, "validator", myNbCorners));
504
505   /* initialize table */
506   myTable->setNumCols(3);
507   myTable->setNumRows(aNumRows);
508
509   QStringList aColLabels;
510   aColLabels.append(tr("SMESH_FIRST"));
511   aColLabels.append(tr("SMESH_MIDDLE"));
512   aColLabels.append(tr("SMESH_LAST"));
513   myTable->setColumnLabels(aColLabels);
514   
515   for ( int col = 0; col < myTable->numCols(); col++ )
516     myTable->setColumnWidth(col, 80);
517
518   myTable->setColumnReadOnly(0, true);
519   myTable->setColumnReadOnly(2, true);
520
521   myTable->setEnabled( false );
522   
523   for ( int row = 0; row < myTable->numRows(); row++ )
524     {
525       SMESHGUI_IdEditItem* anEditItem = new SMESHGUI_IdEditItem( myTable, QTableItem::OnTyping, "" );
526       anEditItem->setReplaceable(false);
527       myTable->setItem(row, 1, anEditItem);
528     }
529   
530   /* signals and slots connections */
531   connect(mySelectButton, SIGNAL(clicked()), SLOT(SetEditCorners()));
532   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(SelectionIntoArgument()));
533   connect(myTable,        SIGNAL(doubleClicked(int, int, int, const QPoint&)), SLOT(onCellDoubleClicked(int, int, int, const QPoint&)));
534   connect(myTable,        SIGNAL(valueChanged (int, int)), SLOT(onCellTextChange(int, int)));
535   connect(myCornerNodes,  SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
536   connect(myReverseCB,    SIGNAL(stateChanged(int)), SLOT(onReverse(int)));
537
538   connect(buttonOk, SIGNAL(clicked()),     SLOT(ClickOnOk()));
539   connect(buttonCancel, SIGNAL(clicked()), SLOT(ClickOnCancel()));
540   connect(buttonApply, SIGNAL(clicked()),  SLOT(ClickOnApply()));
541   connect(buttonHelp, SIGNAL(clicked()),   SLOT(ClickOnHelp()));
542
543   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
544   connect(mySMESHGUI, SIGNAL (SignalStudyFrameChanged()), SLOT(ClickOnCancel()));
545
546   this->show(); // displays Dialog
547
548   // set selection mode
549   SMESH::SetPointRepresentation(true);
550
551   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
552     aViewWindow->SetSelectionMode( NodeSelection );
553
554   myBusy = false;
555
556   SetEditCorners();
557 }
558
559 //=================================================================================
560 // function : ClickOnApply()
561 // purpose  :
562 //=================================================================================
563 void SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
564 {
565   if (IsValid() && !mySMESHGUI->isActiveStudyLocked()) {
566     myBusy = true;
567     
568     vector<int> anIds;
569
570     switch (myType) {
571     case QUAD_EDGE:
572       anIds.push_back(myTable->text(0, 0).toInt());
573       anIds.push_back(myTable->text(0, 2).toInt());
574       anIds.push_back(myTable->text(0, 1).toInt());
575       break;
576     case QUAD_TRIANGLE:
577     case QUAD_QUADRANGLE:
578     case QUAD_TETRAHEDRON:
579     case QUAD_PYRAMID:
580     case QUAD_PENTAHEDRON:
581     case QUAD_HEXAHEDRON:
582       for ( int row = 0; row < myNbCorners; row++ )
583         anIds.push_back(myTable->text(row, 0).toInt());
584       for ( int row = 0; row < myTable->numRows(); row++ )
585         anIds.push_back(myTable->text(row, 1).toInt());
586       break;
587     }
588     if ( myReverseCB->isChecked())
589       SMESH::ReverseConnectivity( anIds, myType );
590     
591     int aNumberOfIds =  anIds.size();
592     SMESH::long_array_var anArrayOfIdeces = new SMESH::long_array;
593     anArrayOfIdeces->length( aNumberOfIds );
594     
595     for (int i = 0; i < aNumberOfIds; i++)
596       anArrayOfIdeces[i] = anIds[ i ];
597
598     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
599     switch (myType) {
600     case QUAD_EDGE:
601       aMeshEditor->AddEdge(anArrayOfIdeces.inout()); break;
602     case QUAD_TRIANGLE:
603     case QUAD_QUADRANGLE:
604       aMeshEditor->AddFace(anArrayOfIdeces.inout()); break;
605     case QUAD_TETRAHEDRON:
606     case QUAD_PYRAMID:
607     case QUAD_PENTAHEDRON: 
608     case QUAD_HEXAHEDRON:
609       aMeshEditor->AddVolume(anArrayOfIdeces.inout()); break;
610     }
611     
612     SALOME_ListIO aList; aList.Append( myActor->getIO() );
613     mySelector->ClearIndex();
614     mySelectionMgr->setSelectedObjects( aList, false );
615
616     SMESH::UpdateView();
617     mySimulation->SetVisibility(false);
618     
619     buttonOk->setEnabled(false);
620     buttonApply->setEnabled(false);
621
622     UpdateTable();
623     SetEditCorners();
624
625     myBusy = false;
626   }
627 }
628
629 //=================================================================================
630 // function : ClickOnOk()
631 // purpose  :
632 //=================================================================================
633 void SMESHGUI_AddQuadraticElementDlg::ClickOnOk()
634 {
635   ClickOnApply();
636   ClickOnCancel();
637   return;
638 }
639
640 //=================================================================================
641 // function : ClickOnCancel()
642 // purpose  :
643 //=================================================================================
644 void SMESHGUI_AddQuadraticElementDlg::ClickOnCancel()
645 {
646   mySelectionMgr->clearSelected();
647   mySimulation->SetVisibility(false);
648   SMESH::SetPointRepresentation(false);
649   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
650     aViewWindow->SetSelectionMode( ActorSelection );
651   disconnect(mySelectionMgr, 0, this, 0);
652   mySMESHGUI->ResetState();
653   reject();
654   return;
655 }
656
657 //=================================================================================
658 // function : ClickOnHelp()
659 // purpose  :
660 //=================================================================================
661 void SMESHGUI_AddQuadraticElementDlg::ClickOnHelp()
662 {
663   SalomeApp_Application* app = (SalomeApp_Application*)(SUIT_Session::session()->activeApplication());
664   if (app) 
665     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
666   else {
667     SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
668                            QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
669                            arg(app->resourceMgr()->stringValue("ExternalBrowser", "application")).arg(myHelpFileName),
670                            QObject::tr("BUT_OK"));
671   }
672 }
673
674 //=================================================================================
675 // function : onTextChange()
676 // purpose  :
677 //=================================================================================
678 void SMESHGUI_AddQuadraticElementDlg::onTextChange (const QString& theNewText)
679 {
680   if (myBusy) return;
681   myBusy = true;
682   
683   buttonOk->setEnabled(false);
684   buttonApply->setEnabled(false);
685
686   mySimulation->SetVisibility(false);
687
688   // hilight entered nodes
689   SMDS_Mesh* aMesh = 0;
690   if (myActor)
691     aMesh = myActor->GetObject()->GetMesh();
692
693   if (aMesh) {
694     TColStd_MapOfInteger newIndices;
695     
696     QStringList aListId = QStringList::split(" ", theNewText, false);
697     bool allOk = true;
698     for (int i = 0; i < aListId.count(); i++) {
699       if( const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() ) )
700         newIndices.Add( n->GetID() );
701       else
702         {
703           allOk = false;
704           break;
705         }
706     }
707     
708     mySelector->AddOrRemoveIndex( myActor->getIO(), newIndices, false );
709     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
710       aViewWindow->highlight( myActor->getIO(), true, true );
711     
712     if ( sender() == myCornerNodes )
713       UpdateTable( allOk );
714   }
715   
716   if( IsValid() ) {
717     buttonOk->setEnabled(true);
718     buttonApply->setEnabled(true);
719   }
720
721   if ( sender() == myTable )
722     displaySimulation();
723   
724   myBusy = false;
725 }
726
727 //=================================================================================
728 // function : SelectionIntoArgument()
729 // purpose  : Called when selection has changed
730 //=================================================================================
731 void SMESHGUI_AddQuadraticElementDlg::SelectionIntoArgument()
732 {
733   if (myBusy) return;
734   
735   if ( myIsEditCorners )
736     {
737       // clear
738       myActor = 0;
739       
740       myBusy = true;
741       myCornerNodes->setText("");
742       myBusy = false;
743       
744       if (!GroupButtons->isEnabled()) // inactive
745         return;
746       
747       buttonOk->setEnabled(false);
748       buttonApply->setEnabled(false);
749       
750       mySimulation->SetVisibility(false);
751       
752       // get selected mesh
753       SALOME_ListIO aList;
754       mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
755       
756       if (aList.Extent() != 1)
757         {
758           UpdateTable();
759           return;
760         }
761       
762       Handle(SALOME_InteractiveObject) anIO = aList.First();
763       myMesh = SMESH::GetMeshByIO(anIO);
764       if (myMesh->_is_nil())
765         return;
766       
767       myActor = SMESH::FindActorByEntry(anIO->getEntry());
768   
769     }
770   
771   if (!myActor)
772     return;
773   
774   // get selected nodes
775   QString aString = "";
776   int nbNodes = SMESH::GetNameOfSelectedNodes(mySelector,myActor->getIO(),aString);
777   
778   if ( myIsEditCorners )
779     {
780       myBusy = true;
781       myCornerNodes->setText(aString);
782       myBusy = false;
783       
784       UpdateTable();
785     }
786   else if ( myTable->isEnabled() && nbNodes == 1 )
787     {
788       myBusy = true;
789       int theRow = myTable->currentRow(), theCol = myTable->currentColumn();
790       if ( theCol == 1 )
791         myTable->setText(theRow, 1, aString);
792       myBusy = false;
793     }
794   
795   if ( IsValid() )
796     {
797       buttonOk->setEnabled( true );
798       buttonApply->setEnabled( true );
799     }
800
801   displaySimulation();
802 }
803
804 //=================================================================================
805 // function : displaySimulation()
806 // purpose  :
807 //=================================================================================
808 void SMESHGUI_AddQuadraticElementDlg::displaySimulation()
809 {
810   if (!myIsEditCorners) {
811     SMESH::TElementSimulation::TVTKIds anIds;
812     
813     // Collect ids from the dialog
814     int anID;
815     bool ok;
816     int aDisplayMode = VTK_SURFACE;
817
818     if ( myType == QUAD_EDGE )
819       {
820         anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(0, 0).toInt() ) );
821         anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(0, 2).toInt() ) );
822         anID = (myTable->text(0, 1)).toInt(&ok);
823         if (!ok) anID = (myTable->text(0, 0)).toInt();
824         anIds.push_back( myActor->GetObject()->GetNodeVTKId(anID) );
825         aDisplayMode = VTK_WIREFRAME;
826       }
827     else
828       {
829         for ( int row = 0; row < myNbCorners; row++ )
830           anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(row, 0).toInt() ) );
831         
832         for ( int row = 0; row < myTable->numRows(); row++ )
833           {
834             anID = (myTable->text(row, 1)).toInt(&ok);
835             if (!ok) {
836               anID = (myTable->text(row, 0)).toInt();
837               aDisplayMode = VTK_WIREFRAME;
838             }
839             anIds.push_back( myActor->GetObject()->GetNodeVTKId(anID) );
840           }
841       }
842     
843     mySimulation->SetPosition(myActor,myType,anIds,aDisplayMode,myReverseCB->isChecked());
844     SMESH::UpdateView();
845   }
846 }
847
848 //=================================================================================
849 // function : SetEditCorners()
850 // purpose  :
851 //=================================================================================
852 void SMESHGUI_AddQuadraticElementDlg::SetEditCorners()
853 {
854   myCornerNodes->setFocus();
855   myIsEditCorners = true;
856   
857   SelectionIntoArgument();
858 }
859
860 //=================================================================================
861 // function : DeactivateActiveDialog()
862 // purpose  :
863 //=================================================================================
864 void SMESHGUI_AddQuadraticElementDlg::DeactivateActiveDialog()
865 {
866   if (GroupConstructors->isEnabled()) {
867     GroupConstructors->setEnabled(false);
868     GroupArguments->setEnabled(false);
869     GroupButtons->setEnabled(false);
870     mySimulation->SetVisibility(false);
871     mySMESHGUI->ResetState();
872     mySMESHGUI->SetActiveDialogBox(0);
873   }
874 }
875
876 //=================================================================================
877 // function : ActivateThisDialog()
878 // purpose  :
879 //=================================================================================
880 void SMESHGUI_AddQuadraticElementDlg::ActivateThisDialog()
881 {
882   /* Emit a signal to deactivate the active dialog */
883   mySMESHGUI->EmitSignalDeactivateDialog();
884
885   GroupConstructors->setEnabled(true);
886   GroupArguments->setEnabled(true);
887   GroupButtons->setEnabled(true);
888
889   SMESH::SetPointRepresentation(true);
890
891   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
892     aViewWindow->SetSelectionMode( NodeSelection );
893   SelectionIntoArgument();
894 }
895
896 //=================================================================================
897 // function : enterEvent()
898 // purpose  :
899 //=================================================================================
900 void SMESHGUI_AddQuadraticElementDlg::enterEvent (QEvent*)
901 {
902   if (GroupConstructors->isEnabled())
903     return;
904   ActivateThisDialog();
905   return;
906 }
907
908 //=================================================================================
909 // function : closeEvent()
910 // purpose  :
911 //=================================================================================
912 void SMESHGUI_AddQuadraticElementDlg::closeEvent (QCloseEvent*)
913 {
914   /* same than click on cancel button */
915   ClickOnCancel();
916   return;
917 }
918
919 //=================================================================================
920 // function : hideEvent()
921 // purpose  : caused by ESC key
922 //=================================================================================
923 void SMESHGUI_AddQuadraticElementDlg::hideEvent (QHideEvent*)
924 {
925   if (!isMinimized())
926     ClickOnCancel();
927 }
928
929 //=================================================================================
930 // function : onReverse()
931 // purpose  :
932 //=================================================================================
933 void SMESHGUI_AddQuadraticElementDlg::onReverse (int state)
934 {
935   if (!IsValid())
936     return;
937
938   if (state >= 0) {
939     mySimulation->SetVisibility(false);
940     displaySimulation();
941   }
942 }
943
944
945 //=================================================================================
946 // function : IsValid()
947 // purpose  :
948 //=================================================================================
949 bool SMESHGUI_AddQuadraticElementDlg::IsValid()
950 {
951   SMDS_Mesh* aMesh = 0;
952   if (myActor)
953     aMesh = myActor->GetObject()->GetMesh();
954   if (!aMesh)
955     return false;
956
957   bool ok;
958   
959   for ( int row = 0; row < myTable->numRows(); row++ )
960     {
961       int anID =  (myTable->text(row, 1)).toInt(&ok);
962       if ( !ok )
963         return false;
964       
965       const SMDS_MeshNode * aNode = aMesh->FindNode(anID);
966       if ( !aNode )
967         return false;
968     }
969   
970   return true;
971 }
972
973 //=================================================================================
974 // function : UpdateTable()
975 // purpose  :
976 //=================================================================================
977 void SMESHGUI_AddQuadraticElementDlg::UpdateTable( bool theConersValidity )
978 {
979   QStringList aListCorners = QStringList::split(" ", myCornerNodes->text(), false);
980   
981   if ( aListCorners.count() == myNbCorners && theConersValidity )
982     {
983       myTable->setEnabled( true );
984       
985       // clear the Middle column 
986       for ( int row = 0; row < myTable->numRows(); row++ )
987         myTable->setText( row, 1, "");
988       
989       int* aFirstColIds;
990       int* aLastColIds;
991
992       switch (myType) {
993       case QUAD_EDGE:
994         aFirstColIds = FirstEdgeIds;
995         aLastColIds  = LastEdgeIds;
996         break;
997       case QUAD_TRIANGLE:
998         aFirstColIds = FirstTriangleIds;
999         aLastColIds  = LastTriangleIds;
1000         break;
1001       case QUAD_QUADRANGLE:
1002         aFirstColIds = FirstQuadrangleIds;
1003         aLastColIds  = LastQuadrangleIds;
1004         break;
1005       case QUAD_TETRAHEDRON:
1006         aFirstColIds = FirstTetrahedronIds;
1007         aLastColIds  = LastTetrahedronIds;
1008         break;
1009       case QUAD_PYRAMID:
1010         aFirstColIds = FirstPyramidIds;
1011         aLastColIds  = LastPyramidIds;
1012         break;
1013       case QUAD_PENTAHEDRON:
1014         aFirstColIds = FirstPentahedronIds;
1015         aLastColIds  = LastPentahedronIds;
1016         break; 
1017       case QUAD_HEXAHEDRON:
1018         aFirstColIds = FirstHexahedronIds;
1019         aLastColIds  = LastHexahedronIds;
1020         break;
1021       }
1022       
1023       // fill the First and the Last columns
1024       for (int i = 0, iEnd = myTable->numRows(); i < iEnd; i++)
1025         myTable->setText( i, 0, aListCorners[ aFirstColIds[i] ] );
1026       
1027       for (int i = 0, iEnd = myTable->numRows(); i < iEnd; i++)
1028         myTable->setText( i, 2, aListCorners[ aLastColIds[i] ] );
1029     }
1030   else
1031     {
1032       // clear table
1033       for ( int row = 0; row < myTable->numRows(); row++ )
1034         for ( int col = 0; col < myTable->numCols(); col++ )
1035           myTable->setText(row, col, "");
1036       
1037       myTable->setEnabled( false );
1038     }
1039 }
1040
1041
1042 //=================================================================================
1043 // function : onTableActivate()
1044 // purpose  :
1045 //=================================================================================
1046 void SMESHGUI_AddQuadraticElementDlg::onCellDoubleClicked( int theRow, int theCol, int theButton, const QPoint& theMousePos )
1047 {
1048   if ( theButton == 1 && theCol == 1 )
1049     myIsEditCorners = false;
1050   
1051   displaySimulation();
1052   return;
1053 }
1054
1055
1056 //=================================================================================
1057 // function : onCellTextChange()
1058 // purpose  :
1059 //=================================================================================
1060 void SMESHGUI_AddQuadraticElementDlg::onCellTextChange(int theRow, int theCol)
1061 {
1062   onTextChange( myTable->text(theRow, theCol) );
1063 }
1064
1065
1066 QWidget* SMESHGUI_IdEditItem::createEditor() const
1067 {
1068   QLineEdit *aLineEdit = new QLineEdit(text(), table()->viewport());
1069   aLineEdit->setValidator( new SMESHGUI_IdValidator(table()->viewport(), "validator", 1) );
1070   return aLineEdit;
1071 }