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