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