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