Salome HOME
PAL13330( When mesh generation does not success, trace where )
[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; // NOT SUPPORTED IN VTK4.2
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 ( theIds.size() > 8 ? !theReverse : theReverse ) {
240           ReverseConnectivity( theIds, theType );
241         }
242       }
243             
244       myGrid->Reset();
245       vtkIdList *anIds = vtkIdList::New();
246       
247       for (int i = 0, iEnd = theIds.size(); i < iEnd; i++) {
248         anIds->InsertId(i,theIds[i]);
249         //std::cout << i<< ": " << theIds[i] << std::endl;
250       }
251       
252       myGrid->InsertNextCell(aType,anIds);
253       anIds->Delete();
254       
255       myGrid->Modified();
256
257       myPreviewActor->GetMapper()->Update();
258       myPreviewActor->SetRepresentation( theMode );
259       SetVisibility(true);
260
261       // restore normal orientation
262       if ( aType == VTK_CONVEX_POINT_SET ) {
263         if ( theReverse  && theMode == VTK_SURFACE ) {
264           //myPreviewActor->GetProperty()->SetColor( myRGB[0], myRGB[1], myRGB[2] );
265         }
266       }
267     }
268
269
270     void SetVisibility (bool theVisibility)
271     {
272       myPreviewActor->SetVisibility(theVisibility);
273       RepaintCurrentView();
274     }
275
276
277     ~TElementSimulation()
278     {
279       if (FindVtkViewWindow(myApplication->activeViewManager(), myViewWindow)) {
280         myVTKViewWindow->RemoveActor(myPreviewActor);
281       }
282       myPreviewActor->Delete();
283
284       myMapper->RemoveAllInputs();
285       myMapper->Delete();
286
287       myGrid->Delete();
288
289 //       myProp->Delete();
290 //       myBackProp->Delete();
291     }
292   };
293 }
294
295
296 // Define the sequences of ids
297 static int FirstEdgeIds[] = {0};
298 static int LastEdgeIds[] =  {1};
299
300 static int FirstTriangleIds[] = {0,1,2};
301 static int LastTriangleIds[] =  {1,2,0};
302
303 static int FirstQuadrangleIds[] = {0,1,2,3};
304 static int LastQuadrangleIds[] =  {1,2,3,0};
305
306 static int FirstTetrahedronIds[] = {0,1,2,3,3,3};
307 static int LastTetrahedronIds[] =  {1,2,0,0,1,2};
308
309 static int FirstPyramidIds[] = {0,1,2,3,4,4,4,4};
310 static int LastPyramidIds[] =  {1,2,3,0,0,1,2,3};
311
312 static int FirstPentahedronIds[] = {0,1,2,3,4,5,0,1,2};
313 static int LastPentahedronIds[] =  {1,2,0,4,5,3,3,4,5};
314
315 static int FirstHexahedronIds[] = {0,1,2,3,4,5,6,7,0,1,2,3};
316 static int LastHexahedronIds[] =  {1,2,3,0,5,6,7,4,4,5,6,7};
317
318
319
320 //=================================================================================
321 // function : SMESHGUI_AddQuadraticElementDlg()
322 // purpose  : constructor
323 //=================================================================================
324 SMESHGUI_AddQuadraticElementDlg::SMESHGUI_AddQuadraticElementDlg( SMESHGUI* theModule,
325                                                                   const int theType,
326                                                                   const char* name,
327                                                                   bool modal, WFlags fl)
328      : QDialog( SMESH::GetDesktop( theModule ), name, modal, WStyle_Customize | WStyle_NormalBorder |
329                 WStyle_Title | WStyle_SysMenu | Qt::WDestructiveClose),
330      mySMESHGUI( theModule ),
331      mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
332      myType( theType )
333 {
334   SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>
335     (SUIT_Session::session()->activeApplication());
336   
337   mySimulation = new SMESH::TElementSimulation (anApp);
338   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
339
340   QString anElementName;
341
342   switch ( myType ) {
343   case QUAD_EDGE:
344     anElementName = QString("QUADRATIC_EDGE");
345     break;
346   case QUAD_TRIANGLE:
347     anElementName = QString("QUADRATIC_TRIANGLE");
348     break; 
349   case QUAD_QUADRANGLE:
350     anElementName = QString("QUADRATIC_QUADRANGLE");
351     break;
352   case QUAD_TETRAHEDRON:
353     anElementName = QString("QUADRATIC_TETRAHEDRON");
354     break;
355   case QUAD_PYRAMID:
356     anElementName = QString("QUADRATIC_PYRAMID");
357     break;
358   case QUAD_PENTAHEDRON:
359     anElementName = QString("QUADRATIC_PENTAHEDRON");
360     break;
361   case QUAD_HEXAHEDRON:
362     anElementName = QString("QUADRATIC_HEXAHEDRON");
363     break;
364   default:
365     myType = QUAD_EDGE;
366     anElementName = QString("QUADRATIC_EDGE");
367   }
368
369   QString iconName           = tr(QString("ICON_DLG_%1").arg(anElementName));
370   QString caption            = tr(QString("SMESH_ADD_%1_TITLE").arg(anElementName));
371   QString argumentsGrTitle   = tr(QString("SMESH_ADD_%1").arg(anElementName));
372   QString constructorGrTitle = tr(QString("SMESH_%1").arg(anElementName));
373   
374   QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", iconName));
375   QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
376
377   if (!name)
378     setName("SMESHGUI_AddQuadraticElementDlg");
379   setCaption(caption);
380   
381   setSizeGripEnabled(TRUE);
382   QGridLayout* aDialogLayout = new QGridLayout(this);
383   aDialogLayout->setSpacing(6);
384   aDialogLayout->setMargin(11);
385
386   /***************************************************************/
387   GroupConstructors = new QButtonGroup(this, "GroupConstructors");
388   GroupConstructors->setTitle(constructorGrTitle);
389
390   GroupConstructors->setExclusive(TRUE);
391   GroupConstructors->setColumnLayout(0, Qt::Vertical);
392   GroupConstructors->layout()->setSpacing(0);
393   GroupConstructors->layout()->setMargin(0);
394   GroupConstructors->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
395   QGridLayout* aGroupConstructorsLayout = new QGridLayout(GroupConstructors->layout());
396   aGroupConstructorsLayout->setAlignment(Qt::AlignTop);
397   aGroupConstructorsLayout->setSpacing(6);
398   aGroupConstructorsLayout->setMargin(11);
399   myRadioButton1 = new QRadioButton(GroupConstructors, "myRadioButton1");
400   myRadioButton1->setText(tr("" ));
401   myRadioButton1->setPixmap(image0);
402   myRadioButton1->setChecked(TRUE);
403   myRadioButton1->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, myRadioButton1->sizePolicy().hasHeightForWidth()));
404   aGroupConstructorsLayout->addWidget(myRadioButton1, 0, 0);
405   aGroupConstructorsLayout->addItem( new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 1);
406   aDialogLayout->addWidget(GroupConstructors, 0, 0);
407
408   /***************************************************************/
409   GroupArguments = new QGroupBox(this, "GroupArguments");
410   GroupArguments->setTitle(argumentsGrTitle);
411   GroupArguments->setColumnLayout(0, Qt::Vertical);
412   GroupArguments->layout()->setSpacing(0);
413   GroupArguments->layout()->setMargin(0);
414   GroupArguments->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding));
415   QGridLayout* aGroupArgumentsLayout = new QGridLayout(GroupArguments->layout());
416   aGroupArgumentsLayout->setAlignment(Qt::AlignTop);
417   aGroupArgumentsLayout->setSpacing(6);
418   aGroupArgumentsLayout->setMargin(11);
419   QLabel* aCornerNodesLabel = new QLabel(GroupArguments, "aCornerNodesLabel");
420   aCornerNodesLabel->setText(tr("SMESH_CORNER_NODES" ));
421   aGroupArgumentsLayout->addWidget(aCornerNodesLabel, 0, 0);
422   mySelectButton = new QPushButton(GroupArguments, "mySelectButton");
423   mySelectButton->setPixmap(image1);
424   aGroupArgumentsLayout->addWidget(mySelectButton, 0, 1);
425   myCornerNodes = new QLineEdit(GroupArguments, "myCornerNodes");
426   aGroupArgumentsLayout->addWidget(myCornerNodes, 0, 2);
427
428   myTable = new QTable(GroupArguments);
429   aGroupArgumentsLayout->addMultiCellWidget(myTable, 1, 1, 0, 2);
430  
431   myReverseCB = new QCheckBox(GroupArguments, "myReverseCB");
432   myReverseCB->setText(tr("SMESH_REVERSE" ));
433   aGroupArgumentsLayout->addWidget(myReverseCB, 2, 0);
434  
435   aDialogLayout->addWidget(GroupArguments, 1, 0);
436
437   
438   /***************************************************************/
439   GroupButtons = new QGroupBox(this, "GroupButtons");
440   GroupButtons->setColumnLayout(0, Qt::Vertical);
441   GroupButtons->layout()->setSpacing(0);
442   GroupButtons->layout()->setMargin(0);
443   GroupButtons->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
444   QGridLayout* aGroupButtonsLayout = new QGridLayout(GroupButtons->layout());
445   aGroupButtonsLayout->setAlignment(Qt::AlignTop);
446   aGroupButtonsLayout->setSpacing(6);
447   aGroupButtonsLayout->setMargin(11);
448   buttonCancel = new QPushButton(GroupButtons, "buttonCancel");
449   buttonCancel->setText(tr("SMESH_BUT_CLOSE" ));
450   buttonCancel->setAutoDefault(TRUE);
451   aGroupButtonsLayout->addWidget(buttonCancel, 0, 3);
452   buttonApply = new QPushButton(GroupButtons, "buttonApply");
453   buttonApply->setText(tr("SMESH_BUT_APPLY" ));
454   buttonApply->setAutoDefault(TRUE);
455   aGroupButtonsLayout->addWidget(buttonApply, 0, 1);
456   aGroupButtonsLayout->addItem( new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 2);
457   buttonOk = new QPushButton(GroupButtons, "buttonOk");
458   buttonOk->setText(tr("SMESH_BUT_OK" ));
459   buttonOk->setAutoDefault(TRUE);
460   buttonOk->setDefault(TRUE);
461   aGroupButtonsLayout->addWidget(buttonOk, 0, 0);
462   buttonHelp = new QPushButton(GroupButtons, "buttonHelp");
463   buttonHelp->setText(tr("SMESH_BUT_HELP" ));
464   buttonHelp->setAutoDefault(TRUE);
465   aGroupButtonsLayout->addWidget(buttonHelp, 0, 4);
466
467   aDialogLayout->addWidget(GroupButtons, 2, 0);
468
469   Init(); /* Initialisations */
470 }
471
472 //=================================================================================
473 // function : ~SMESHGUI_AddQuadraticElementDlg()
474 // purpose  : Destroys the object and frees any allocated resources
475 //=================================================================================
476 SMESHGUI_AddQuadraticElementDlg::~SMESHGUI_AddQuadraticElementDlg()
477 {
478   // no need to delete child widgets, Qt does it all for us
479   delete mySimulation;
480 }
481
482 //=================================================================================
483 // function : Init()
484 // purpose  :
485 //=================================================================================
486 void SMESHGUI_AddQuadraticElementDlg::Init()
487 {
488   GroupArguments->show();
489   myRadioButton1->setChecked(TRUE);
490   myIsEditCorners = true;
491   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
492   
493   myActor = 0;
494
495   int aNumRows;
496
497   switch (myType) {
498   case QUAD_EDGE:
499     aNumRows = 1;
500     myNbCorners = 2;
501     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_edges
502     break;
503   case QUAD_TRIANGLE:
504     aNumRows = 3;
505     myNbCorners = 3;
506     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_triangles
507     break;
508   case QUAD_QUADRANGLE:
509     aNumRows = 4;
510     myNbCorners = 4;
511     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_quadrangles
512     break;
513   case QUAD_TETRAHEDRON:
514     aNumRows = 6;
515     myNbCorners = 4;
516     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_tetrahedrons
517     break;
518   case QUAD_PYRAMID:
519     aNumRows = 8;
520     myNbCorners = 5;
521     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_pyramids
522     break;
523   case QUAD_PENTAHEDRON:
524     aNumRows = 9;
525     myNbCorners = 6;
526     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_pentahedrons
527     break; 
528   case QUAD_HEXAHEDRON:
529     aNumRows = 12;
530     myNbCorners = 8;
531     myHelpFileName = "/adding_quadratic_nodes_and_elements.htm#?"; //Adding_hexahedrons
532     break;
533   }
534     
535   myCornerNodes->setValidator(new SMESHGUI_IdValidator(this, "validator", myNbCorners));
536
537   /* initialize table */
538   myTable->setNumCols(3);
539   myTable->setNumRows(aNumRows);
540
541   QStringList aColLabels;
542   aColLabels.append(tr("SMESH_FIRST"));
543   aColLabels.append(tr("SMESH_MIDDLE"));
544   aColLabels.append(tr("SMESH_LAST"));
545   myTable->setColumnLabels(aColLabels);
546   
547   for ( int col = 0; col < myTable->numCols(); col++ )
548     myTable->setColumnWidth(col, 80);
549
550   myTable->setColumnReadOnly(0, true);
551   myTable->setColumnReadOnly(2, true);
552
553   myTable->setEnabled( false );
554   
555   for ( int row = 0; row < myTable->numRows(); row++ )
556     {
557       SMESHGUI_IdEditItem* anEditItem = new SMESHGUI_IdEditItem( myTable, QTableItem::OnTyping, "" );
558       anEditItem->setReplaceable(false);
559       myTable->setItem(row, 1, anEditItem);
560     }
561   
562   /* signals and slots connections */
563   connect(mySelectButton, SIGNAL(clicked()), SLOT(SetEditCorners()));
564   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(SelectionIntoArgument()));
565   connect(myTable,        SIGNAL(doubleClicked(int, int, int, const QPoint&)), SLOT(onCellDoubleClicked(int, int, int, const QPoint&)));
566   connect(myTable,        SIGNAL(valueChanged (int, int)), SLOT(onCellTextChange(int, int)));
567   connect(myCornerNodes,  SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
568   connect(myReverseCB,    SIGNAL(stateChanged(int)), SLOT(onReverse(int)));
569
570   connect(buttonOk, SIGNAL(clicked()),     SLOT(ClickOnOk()));
571   connect(buttonCancel, SIGNAL(clicked()), SLOT(ClickOnCancel()));
572   connect(buttonApply, SIGNAL(clicked()),  SLOT(ClickOnApply()));
573   connect(buttonHelp, SIGNAL(clicked()),   SLOT(ClickOnHelp()));
574
575   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
576   connect(mySMESHGUI, SIGNAL (SignalStudyFrameChanged()), SLOT(ClickOnCancel()));
577
578   this->show(); // displays Dialog
579
580   // set selection mode
581   SMESH::SetPointRepresentation(true);
582
583   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
584     aViewWindow->SetSelectionMode( NodeSelection );
585
586   myBusy = false;
587
588   SetEditCorners();
589 }
590
591 //=================================================================================
592 // function : ClickOnApply()
593 // purpose  :
594 //=================================================================================
595 void SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
596 {
597   if (IsValid() && !mySMESHGUI->isActiveStudyLocked()) {
598     myBusy = true;
599     
600     vector<int> anIds;
601
602     switch (myType) {
603     case QUAD_EDGE:
604       anIds.push_back(myTable->text(0, 0).toInt());
605       anIds.push_back(myTable->text(0, 2).toInt());
606       anIds.push_back(myTable->text(0, 1).toInt());
607       break;
608     case QUAD_TRIANGLE:
609     case QUAD_QUADRANGLE:
610     case QUAD_TETRAHEDRON:
611     case QUAD_PYRAMID:
612     case QUAD_PENTAHEDRON:
613     case QUAD_HEXAHEDRON:
614       for ( int row = 0; row < myNbCorners; row++ )
615         anIds.push_back(myTable->text(row, 0).toInt());
616       for ( int row = 0; row < myTable->numRows(); row++ )
617         anIds.push_back(myTable->text(row, 1).toInt());
618       break;
619     }
620     if ( myReverseCB->isChecked())
621       SMESH::ReverseConnectivity( anIds, myType );
622     
623     int aNumberOfIds =  anIds.size();
624     SMESH::long_array_var anArrayOfIdeces = new SMESH::long_array;
625     anArrayOfIdeces->length( aNumberOfIds );
626     
627     for (int i = 0; i < aNumberOfIds; i++)
628       anArrayOfIdeces[i] = anIds[ i ];
629
630     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
631     switch (myType) {
632     case QUAD_EDGE:
633       aMeshEditor->AddEdge(anArrayOfIdeces.inout()); break;
634     case QUAD_TRIANGLE:
635     case QUAD_QUADRANGLE:
636       aMeshEditor->AddFace(anArrayOfIdeces.inout()); break;
637     case QUAD_TETRAHEDRON:
638     case QUAD_PYRAMID:
639     case QUAD_PENTAHEDRON: 
640     case QUAD_HEXAHEDRON:
641       aMeshEditor->AddVolume(anArrayOfIdeces.inout()); break;
642     }
643     
644     SALOME_ListIO aList; aList.Append( myActor->getIO() );
645     mySelector->ClearIndex();
646     mySelectionMgr->setSelectedObjects( aList, false );
647
648     SMESH::UpdateView();
649     mySimulation->SetVisibility(false);
650     
651     buttonOk->setEnabled(false);
652     buttonApply->setEnabled(false);
653
654     UpdateTable();
655     SetEditCorners();
656
657     myBusy = false;
658   }
659 }
660
661 //=================================================================================
662 // function : ClickOnOk()
663 // purpose  :
664 //=================================================================================
665 void SMESHGUI_AddQuadraticElementDlg::ClickOnOk()
666 {
667   ClickOnApply();
668   ClickOnCancel();
669   return;
670 }
671
672 //=================================================================================
673 // function : ClickOnCancel()
674 // purpose  :
675 //=================================================================================
676 void SMESHGUI_AddQuadraticElementDlg::ClickOnCancel()
677 {
678   mySelectionMgr->clearSelected();
679   mySimulation->SetVisibility(false);
680   SMESH::SetPointRepresentation(false);
681   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
682     aViewWindow->SetSelectionMode( ActorSelection );
683   disconnect(mySelectionMgr, 0, this, 0);
684   mySMESHGUI->ResetState();
685   reject();
686   return;
687 }
688
689 //=================================================================================
690 // function : ClickOnHelp()
691 // purpose  :
692 //=================================================================================
693 void SMESHGUI_AddQuadraticElementDlg::ClickOnHelp()
694 {
695   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
696   if (app) 
697     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
698   else {
699     SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
700                            QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
701                            arg(app->resourceMgr()->stringValue("ExternalBrowser", "application")).arg(myHelpFileName),
702                            QObject::tr("BUT_OK"));
703   }
704 }
705
706 //=================================================================================
707 // function : onTextChange()
708 // purpose  :
709 //=================================================================================
710 void SMESHGUI_AddQuadraticElementDlg::onTextChange (const QString& theNewText)
711 {
712   if (myBusy) return;
713   myBusy = true;
714   
715   buttonOk->setEnabled(false);
716   buttonApply->setEnabled(false);
717
718   mySimulation->SetVisibility(false);
719
720   // hilight entered nodes
721   SMDS_Mesh* aMesh = 0;
722   if (myActor)
723     aMesh = myActor->GetObject()->GetMesh();
724
725   if (aMesh) {
726     TColStd_MapOfInteger newIndices;
727     
728     QStringList aListId = QStringList::split(" ", theNewText, false);
729     bool allOk = true;
730     for (int i = 0; i < aListId.count(); i++) {
731       if( const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() ) )
732         newIndices.Add( n->GetID() );
733       else
734         {
735           allOk = false;
736           break;
737         }
738     }
739     
740     mySelector->AddOrRemoveIndex( myActor->getIO(), newIndices, false );
741     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
742       aViewWindow->highlight( myActor->getIO(), true, true );
743     
744     if ( sender() == myCornerNodes )
745       UpdateTable( allOk );
746   }
747   
748   if( IsValid() ) {
749     buttonOk->setEnabled(true);
750     buttonApply->setEnabled(true);
751   }
752
753   if ( sender() == myTable )
754     displaySimulation();
755   
756   myBusy = false;
757 }
758
759 //=================================================================================
760 // function : SelectionIntoArgument()
761 // purpose  : Called when selection has changed
762 //=================================================================================
763 void SMESHGUI_AddQuadraticElementDlg::SelectionIntoArgument()
764 {
765   if (myBusy) return;
766   
767   if ( myIsEditCorners )
768     {
769       // clear
770       myActor = 0;
771       
772       myBusy = true;
773       myCornerNodes->setText("");
774       myBusy = false;
775       
776       if (!GroupButtons->isEnabled()) // inactive
777         return;
778       
779       buttonOk->setEnabled(false);
780       buttonApply->setEnabled(false);
781       
782       mySimulation->SetVisibility(false);
783       
784       // get selected mesh
785       SALOME_ListIO aList;
786       mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
787       
788       if (aList.Extent() != 1)
789         {
790           UpdateTable();
791           return;
792         }
793       
794       Handle(SALOME_InteractiveObject) anIO = aList.First();
795       myMesh = SMESH::GetMeshByIO(anIO);
796       if (myMesh->_is_nil())
797         return;
798       
799       myActor = SMESH::FindActorByEntry(anIO->getEntry());
800   
801     }
802   
803   if (!myActor)
804     return;
805   
806   // get selected nodes
807   QString aString = "";
808   int nbNodes = SMESH::GetNameOfSelectedNodes(mySelector,myActor->getIO(),aString);
809   
810   if ( myIsEditCorners )
811     {
812       myBusy = true;
813       myCornerNodes->setText(aString);
814       myBusy = false;
815       
816       UpdateTable();
817     }
818   else if ( myTable->isEnabled() && nbNodes == 1 )
819     {
820       myBusy = true;
821       int theRow = myTable->currentRow(), theCol = myTable->currentColumn();
822       if ( theCol == 1 )
823         myTable->setText(theRow, 1, aString);
824       myBusy = false;
825     }
826   
827   if ( IsValid() )
828     {
829       buttonOk->setEnabled( true );
830       buttonApply->setEnabled( true );
831     }
832
833   displaySimulation();
834 }
835
836 //=================================================================================
837 // function : displaySimulation()
838 // purpose  :
839 //=================================================================================
840 void SMESHGUI_AddQuadraticElementDlg::displaySimulation()
841 {
842   if (!myIsEditCorners) {
843     SMESH::TElementSimulation::TVTKIds anIds;
844     
845     // Collect ids from the dialog
846     int anID;
847     bool ok;
848     int aDisplayMode = VTK_SURFACE;
849
850     if ( myType == QUAD_EDGE )
851       {
852         anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(0, 0).toInt() ) );
853         anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(0, 2).toInt() ) );
854         anID = (myTable->text(0, 1)).toInt(&ok);
855         if (!ok) anID = (myTable->text(0, 0)).toInt();
856         anIds.push_back( myActor->GetObject()->GetNodeVTKId(anID) );
857         aDisplayMode = VTK_WIREFRAME;
858       }
859     else
860       {
861         for ( int row = 0; row < myNbCorners; row++ )
862           anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(row, 0).toInt() ) );
863         
864         for ( int row = 0; row < myTable->numRows(); row++ )
865           {
866             anID = (myTable->text(row, 1)).toInt(&ok);
867             if (!ok) {
868               anID = (myTable->text(row, 0)).toInt();
869               aDisplayMode = VTK_WIREFRAME;
870             }
871             anIds.push_back( myActor->GetObject()->GetNodeVTKId(anID) );
872           }
873       }
874     
875     mySimulation->SetPosition(myActor,myType,anIds,aDisplayMode,myReverseCB->isChecked());
876     SMESH::UpdateView();
877   }
878 }
879
880 //=================================================================================
881 // function : SetEditCorners()
882 // purpose  :
883 //=================================================================================
884 void SMESHGUI_AddQuadraticElementDlg::SetEditCorners()
885 {
886   myCornerNodes->setFocus();
887   myIsEditCorners = true;
888   
889   SelectionIntoArgument();
890 }
891
892 //=================================================================================
893 // function : DeactivateActiveDialog()
894 // purpose  :
895 //=================================================================================
896 void SMESHGUI_AddQuadraticElementDlg::DeactivateActiveDialog()
897 {
898   if (GroupConstructors->isEnabled()) {
899     GroupConstructors->setEnabled(false);
900     GroupArguments->setEnabled(false);
901     GroupButtons->setEnabled(false);
902     mySimulation->SetVisibility(false);
903     mySMESHGUI->ResetState();
904     mySMESHGUI->SetActiveDialogBox(0);
905   }
906 }
907
908 //=================================================================================
909 // function : ActivateThisDialog()
910 // purpose  :
911 //=================================================================================
912 void SMESHGUI_AddQuadraticElementDlg::ActivateThisDialog()
913 {
914   /* Emit a signal to deactivate the active dialog */
915   mySMESHGUI->EmitSignalDeactivateDialog();
916
917   GroupConstructors->setEnabled(true);
918   GroupArguments->setEnabled(true);
919   GroupButtons->setEnabled(true);
920
921   SMESH::SetPointRepresentation(true);
922
923   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
924     aViewWindow->SetSelectionMode( NodeSelection );
925   SelectionIntoArgument();
926 }
927
928 //=================================================================================
929 // function : enterEvent()
930 // purpose  :
931 //=================================================================================
932 void SMESHGUI_AddQuadraticElementDlg::enterEvent (QEvent*)
933 {
934   if (GroupConstructors->isEnabled())
935     return;
936   ActivateThisDialog();
937   return;
938 }
939
940 //=================================================================================
941 // function : closeEvent()
942 // purpose  :
943 //=================================================================================
944 void SMESHGUI_AddQuadraticElementDlg::closeEvent (QCloseEvent*)
945 {
946   /* same than click on cancel button */
947   ClickOnCancel();
948   return;
949 }
950
951 //=================================================================================
952 // function : hideEvent()
953 // purpose  : caused by ESC key
954 //=================================================================================
955 void SMESHGUI_AddQuadraticElementDlg::hideEvent (QHideEvent*)
956 {
957   if (!isMinimized())
958     ClickOnCancel();
959 }
960
961 //=================================================================================
962 // function : onReverse()
963 // purpose  :
964 //=================================================================================
965 void SMESHGUI_AddQuadraticElementDlg::onReverse (int state)
966 {
967   if (!IsValid())
968     return;
969
970   if (state >= 0) {
971     mySimulation->SetVisibility(false);
972     displaySimulation();
973   }
974 }
975
976
977 //=================================================================================
978 // function : IsValid()
979 // purpose  :
980 //=================================================================================
981 bool SMESHGUI_AddQuadraticElementDlg::IsValid()
982 {
983   SMDS_Mesh* aMesh = 0;
984   if (myActor)
985     aMesh = myActor->GetObject()->GetMesh();
986   if (!aMesh)
987     return false;
988
989   bool ok;
990   
991   for ( int row = 0; row < myTable->numRows(); row++ )
992     {
993       int anID =  (myTable->text(row, 1)).toInt(&ok);
994       if ( !ok )
995         return false;
996       
997       const SMDS_MeshNode * aNode = aMesh->FindNode(anID);
998       if ( !aNode )
999         return false;
1000     }
1001   
1002   return true;
1003 }
1004
1005 //=================================================================================
1006 // function : UpdateTable()
1007 // purpose  :
1008 //=================================================================================
1009 void SMESHGUI_AddQuadraticElementDlg::UpdateTable( bool theConersValidity )
1010 {
1011   QStringList aListCorners = QStringList::split(" ", myCornerNodes->text(), false);
1012   
1013   if ( aListCorners.count() == myNbCorners && theConersValidity )
1014     {
1015       myTable->setEnabled( true );
1016       
1017       // clear the Middle column 
1018       for ( int row = 0; row < myTable->numRows(); row++ )
1019         myTable->setText( row, 1, "");
1020       
1021       int* aFirstColIds;
1022       int* aLastColIds;
1023
1024       switch (myType) {
1025       case QUAD_EDGE:
1026         aFirstColIds = FirstEdgeIds;
1027         aLastColIds  = LastEdgeIds;
1028         break;
1029       case QUAD_TRIANGLE:
1030         aFirstColIds = FirstTriangleIds;
1031         aLastColIds  = LastTriangleIds;
1032         break;
1033       case QUAD_QUADRANGLE:
1034         aFirstColIds = FirstQuadrangleIds;
1035         aLastColIds  = LastQuadrangleIds;
1036         break;
1037       case QUAD_TETRAHEDRON:
1038         aFirstColIds = FirstTetrahedronIds;
1039         aLastColIds  = LastTetrahedronIds;
1040         break;
1041       case QUAD_PYRAMID:
1042         aFirstColIds = FirstPyramidIds;
1043         aLastColIds  = LastPyramidIds;
1044         break;
1045       case QUAD_PENTAHEDRON:
1046         aFirstColIds = FirstPentahedronIds;
1047         aLastColIds  = LastPentahedronIds;
1048         break; 
1049       case QUAD_HEXAHEDRON:
1050         aFirstColIds = FirstHexahedronIds;
1051         aLastColIds  = LastHexahedronIds;
1052         break;
1053       }
1054       
1055       // fill the First and the Last columns
1056       for (int i = 0, iEnd = myTable->numRows(); i < iEnd; i++)
1057         myTable->setText( i, 0, aListCorners[ aFirstColIds[i] ] );
1058       
1059       for (int i = 0, iEnd = myTable->numRows(); i < iEnd; i++)
1060         myTable->setText( i, 2, aListCorners[ aLastColIds[i] ] );
1061     }
1062   else
1063     {
1064       // clear table
1065       for ( int row = 0; row < myTable->numRows(); row++ )
1066         for ( int col = 0; col < myTable->numCols(); col++ )
1067           myTable->setText(row, col, "");
1068       
1069       myTable->setEnabled( false );
1070     }
1071 }
1072
1073
1074 //=================================================================================
1075 // function : onTableActivate()
1076 // purpose  :
1077 //=================================================================================
1078 void SMESHGUI_AddQuadraticElementDlg::onCellDoubleClicked( int theRow, int theCol, int theButton, const QPoint& theMousePos )
1079 {
1080   if ( theButton == 1 && theCol == 1 )
1081     myIsEditCorners = false;
1082   
1083   displaySimulation();
1084   return;
1085 }
1086
1087
1088 //=================================================================================
1089 // function : onCellTextChange()
1090 // purpose  :
1091 //=================================================================================
1092 void SMESHGUI_AddQuadraticElementDlg::onCellTextChange(int theRow, int theCol)
1093 {
1094   onTextChange( myTable->text(theRow, theCol) );
1095 }
1096
1097
1098 QWidget* SMESHGUI_IdEditItem::createEditor() const
1099 {
1100   QLineEdit *aLineEdit = new QLineEdit(text(), table()->viewport());
1101   aLineEdit->setValidator( new SMESHGUI_IdValidator(table()->viewport(), "validator", 1) );
1102   return aLineEdit;
1103 }
1104
1105 //=================================================================================
1106 // function : keyPressEvent()
1107 // purpose  :
1108 //=================================================================================
1109 void SMESHGUI_AddQuadraticElementDlg::keyPressEvent( QKeyEvent* e )
1110 {
1111   QDialog::keyPressEvent( e );
1112   if ( e->isAccepted() )
1113     return;
1114
1115   if ( e->key() == Key_F1 )
1116     {
1117       e->accept();
1118       ClickOnHelp();
1119     }
1120 }