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