Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[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_elements_page.html#?"; //Adding_edges
502     break;
503   case QUAD_TRIANGLE:
504     aNumRows = 3;
505     myNbCorners = 3;
506     myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_triangles
507     break;
508   case QUAD_QUADRANGLE:
509     aNumRows = 4;
510     myNbCorners = 4;
511     myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_quadrangles
512     break;
513   case QUAD_TETRAHEDRON:
514     aNumRows = 6;
515     myNbCorners = 4;
516     myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_tetrahedrons
517     break;
518   case QUAD_PYRAMID:
519     aNumRows = 8;
520     myNbCorners = 5;
521     myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_pyramids
522     break;
523   case QUAD_PENTAHEDRON:
524     aNumRows = 9;
525     myNbCorners = 6;
526     myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_pentahedrons
527     break; 
528   case QUAD_HEXAHEDRON:
529     aNumRows = 12;
530     myNbCorners = 8;
531     myHelpFileName = "adding_quadratic_elements_page.html#?"; //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                 QString platform;
700 #ifdef WIN32
701                 platform = "winapplication";
702 #else
703                 platform = "application";
704 #endif
705     SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
706                            QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
707                            arg(app->resourceMgr()->stringValue("ExternalBrowser", platform)).arg(myHelpFileName),
708                            QObject::tr("BUT_OK"));
709   }
710 }
711
712 //=================================================================================
713 // function : onTextChange()
714 // purpose  :
715 //=================================================================================
716 void SMESHGUI_AddQuadraticElementDlg::onTextChange (const QString& theNewText)
717 {
718   if (myBusy) return;
719   myBusy = true;
720   
721   buttonOk->setEnabled(false);
722   buttonApply->setEnabled(false);
723
724   mySimulation->SetVisibility(false);
725
726   // hilight entered nodes
727   SMDS_Mesh* aMesh = 0;
728   if (myActor)
729     aMesh = myActor->GetObject()->GetMesh();
730
731   if (aMesh) {
732     TColStd_MapOfInteger newIndices;
733     
734     QStringList aListId = QStringList::split(" ", theNewText, false);
735     bool allOk = true;
736     for (int i = 0; i < aListId.count(); i++) {
737       if( const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() ) )
738         newIndices.Add( n->GetID() );
739       else
740         {
741           allOk = false;
742           break;
743         }
744     }
745     
746     mySelector->AddOrRemoveIndex( myActor->getIO(), newIndices, false );
747     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
748       aViewWindow->highlight( myActor->getIO(), true, true );
749     
750     if ( sender() == myCornerNodes )
751       UpdateTable( allOk );
752   }
753   
754   if( IsValid() ) {
755     buttonOk->setEnabled(true);
756     buttonApply->setEnabled(true);
757   }
758
759   if ( sender() == myTable )
760     displaySimulation();
761   
762   myBusy = false;
763 }
764
765 //=================================================================================
766 // function : SelectionIntoArgument()
767 // purpose  : Called when selection has changed
768 //=================================================================================
769 void SMESHGUI_AddQuadraticElementDlg::SelectionIntoArgument()
770 {
771   if (myBusy) return;
772   
773   if ( myIsEditCorners )
774     {
775       // clear
776       myActor = 0;
777       
778       myBusy = true;
779       myCornerNodes->setText("");
780       myBusy = false;
781       
782       if (!GroupButtons->isEnabled()) // inactive
783         return;
784       
785       buttonOk->setEnabled(false);
786       buttonApply->setEnabled(false);
787       
788       mySimulation->SetVisibility(false);
789       
790       // get selected mesh
791       SALOME_ListIO aList;
792       mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
793       
794       if (aList.Extent() != 1)
795         {
796           UpdateTable();
797           return;
798         }
799       
800       Handle(SALOME_InteractiveObject) anIO = aList.First();
801       myMesh = SMESH::GetMeshByIO(anIO);
802       if (myMesh->_is_nil())
803         return;
804       
805       myActor = SMESH::FindActorByEntry(anIO->getEntry());
806   
807     }
808   
809   if (!myActor)
810     return;
811   
812   // get selected nodes
813   QString aString = "";
814   int nbNodes = SMESH::GetNameOfSelectedNodes(mySelector,myActor->getIO(),aString);
815   
816   if ( myIsEditCorners )
817     {
818       myBusy = true;
819       myCornerNodes->setText(aString);
820       myBusy = false;
821       
822       UpdateTable();
823     }
824   else if ( myTable->isEnabled() && nbNodes == 1 )
825     {
826       myBusy = true;
827       int theRow = myTable->currentRow(), theCol = myTable->currentColumn();
828       if ( theCol == 1 )
829         myTable->setText(theRow, 1, aString);
830       myBusy = false;
831     }
832   
833   if ( IsValid() )
834     {
835       buttonOk->setEnabled( true );
836       buttonApply->setEnabled( true );
837     }
838
839   displaySimulation();
840 }
841
842 //=================================================================================
843 // function : displaySimulation()
844 // purpose  :
845 //=================================================================================
846 void SMESHGUI_AddQuadraticElementDlg::displaySimulation()
847 {
848   if (!myIsEditCorners) {
849     SMESH::TElementSimulation::TVTKIds anIds;
850     
851     // Collect ids from the dialog
852     int anID;
853     bool ok;
854     int aDisplayMode = VTK_SURFACE;
855
856     if ( myType == QUAD_EDGE )
857       {
858         anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(0, 0).toInt() ) );
859         anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(0, 2).toInt() ) );
860         anID = (myTable->text(0, 1)).toInt(&ok);
861         if (!ok) anID = (myTable->text(0, 0)).toInt();
862         anIds.push_back( myActor->GetObject()->GetNodeVTKId(anID) );
863         aDisplayMode = VTK_WIREFRAME;
864       }
865     else
866       {
867         for ( int row = 0; row < myNbCorners; row++ )
868           anIds.push_back( myActor->GetObject()->GetNodeVTKId( myTable->text(row, 0).toInt() ) );
869         
870         for ( int row = 0; row < myTable->numRows(); row++ )
871           {
872             anID = (myTable->text(row, 1)).toInt(&ok);
873             if (!ok) {
874               anID = (myTable->text(row, 0)).toInt();
875               aDisplayMode = VTK_WIREFRAME;
876             }
877             anIds.push_back( myActor->GetObject()->GetNodeVTKId(anID) );
878           }
879       }
880     
881     mySimulation->SetPosition(myActor,myType,anIds,aDisplayMode,myReverseCB->isChecked());
882     SMESH::UpdateView();
883   }
884 }
885
886 //=================================================================================
887 // function : SetEditCorners()
888 // purpose  :
889 //=================================================================================
890 void SMESHGUI_AddQuadraticElementDlg::SetEditCorners()
891 {
892   myCornerNodes->setFocus();
893   myIsEditCorners = true;
894   
895   SelectionIntoArgument();
896 }
897
898 //=================================================================================
899 // function : DeactivateActiveDialog()
900 // purpose  :
901 //=================================================================================
902 void SMESHGUI_AddQuadraticElementDlg::DeactivateActiveDialog()
903 {
904   if (GroupConstructors->isEnabled()) {
905     GroupConstructors->setEnabled(false);
906     GroupArguments->setEnabled(false);
907     GroupButtons->setEnabled(false);
908     mySimulation->SetVisibility(false);
909     mySMESHGUI->ResetState();
910     mySMESHGUI->SetActiveDialogBox(0);
911   }
912 }
913
914 //=================================================================================
915 // function : ActivateThisDialog()
916 // purpose  :
917 //=================================================================================
918 void SMESHGUI_AddQuadraticElementDlg::ActivateThisDialog()
919 {
920   /* Emit a signal to deactivate the active dialog */
921   mySMESHGUI->EmitSignalDeactivateDialog();
922
923   GroupConstructors->setEnabled(true);
924   GroupArguments->setEnabled(true);
925   GroupButtons->setEnabled(true);
926
927   SMESH::SetPointRepresentation(true);
928
929   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
930     aViewWindow->SetSelectionMode( NodeSelection );
931   SelectionIntoArgument();
932 }
933
934 //=================================================================================
935 // function : enterEvent()
936 // purpose  :
937 //=================================================================================
938 void SMESHGUI_AddQuadraticElementDlg::enterEvent (QEvent*)
939 {
940   if (GroupConstructors->isEnabled())
941     return;
942   ActivateThisDialog();
943   return;
944 }
945
946 //=================================================================================
947 // function : closeEvent()
948 // purpose  :
949 //=================================================================================
950 void SMESHGUI_AddQuadraticElementDlg::closeEvent (QCloseEvent*)
951 {
952   /* same than click on cancel button */
953   ClickOnCancel();
954   return;
955 }
956
957 //=================================================================================
958 // function : hideEvent()
959 // purpose  : caused by ESC key
960 //=================================================================================
961 void SMESHGUI_AddQuadraticElementDlg::hideEvent (QHideEvent*)
962 {
963   if (!isMinimized())
964     ClickOnCancel();
965 }
966
967 //=================================================================================
968 // function : onReverse()
969 // purpose  :
970 //=================================================================================
971 void SMESHGUI_AddQuadraticElementDlg::onReverse (int state)
972 {
973   if (!IsValid())
974     return;
975
976   if (state >= 0) {
977     mySimulation->SetVisibility(false);
978     displaySimulation();
979   }
980 }
981
982
983 //=================================================================================
984 // function : IsValid()
985 // purpose  :
986 //=================================================================================
987 bool SMESHGUI_AddQuadraticElementDlg::IsValid()
988 {
989   SMDS_Mesh* aMesh = 0;
990   if (myActor)
991     aMesh = myActor->GetObject()->GetMesh();
992   if (!aMesh)
993     return false;
994
995   bool ok;
996   
997   for ( int row = 0; row < myTable->numRows(); row++ )
998     {
999       int anID =  (myTable->text(row, 1)).toInt(&ok);
1000       if ( !ok )
1001         return false;
1002       
1003       const SMDS_MeshNode * aNode = aMesh->FindNode(anID);
1004       if ( !aNode )
1005         return false;
1006     }
1007   
1008   return true;
1009 }
1010
1011 //=================================================================================
1012 // function : UpdateTable()
1013 // purpose  :
1014 //=================================================================================
1015 void SMESHGUI_AddQuadraticElementDlg::UpdateTable( bool theConersValidity )
1016 {
1017   QStringList aListCorners = QStringList::split(" ", myCornerNodes->text(), false);
1018   
1019   if ( aListCorners.count() == myNbCorners && theConersValidity )
1020     {
1021       myTable->setEnabled( true );
1022       
1023       // clear the Middle column 
1024       for ( int row = 0; row < myTable->numRows(); row++ )
1025         myTable->setText( row, 1, "");
1026       
1027       int* aFirstColIds;
1028       int* aLastColIds;
1029
1030       switch (myType) {
1031       case QUAD_EDGE:
1032         aFirstColIds = FirstEdgeIds;
1033         aLastColIds  = LastEdgeIds;
1034         break;
1035       case QUAD_TRIANGLE:
1036         aFirstColIds = FirstTriangleIds;
1037         aLastColIds  = LastTriangleIds;
1038         break;
1039       case QUAD_QUADRANGLE:
1040         aFirstColIds = FirstQuadrangleIds;
1041         aLastColIds  = LastQuadrangleIds;
1042         break;
1043       case QUAD_TETRAHEDRON:
1044         aFirstColIds = FirstTetrahedronIds;
1045         aLastColIds  = LastTetrahedronIds;
1046         break;
1047       case QUAD_PYRAMID:
1048         aFirstColIds = FirstPyramidIds;
1049         aLastColIds  = LastPyramidIds;
1050         break;
1051       case QUAD_PENTAHEDRON:
1052         aFirstColIds = FirstPentahedronIds;
1053         aLastColIds  = LastPentahedronIds;
1054         break; 
1055       case QUAD_HEXAHEDRON:
1056         aFirstColIds = FirstHexahedronIds;
1057         aLastColIds  = LastHexahedronIds;
1058         break;
1059       }
1060       
1061       // fill the First and the Last columns
1062       for (int i = 0, iEnd = myTable->numRows(); i < iEnd; i++)
1063         myTable->setText( i, 0, aListCorners[ aFirstColIds[i] ] );
1064       
1065       for (int i = 0, iEnd = myTable->numRows(); i < iEnd; i++)
1066         myTable->setText( i, 2, aListCorners[ aLastColIds[i] ] );
1067     }
1068   else
1069     {
1070       // clear table
1071       for ( int row = 0; row < myTable->numRows(); row++ )
1072         for ( int col = 0; col < myTable->numCols(); col++ )
1073           myTable->setText(row, col, "");
1074       
1075       myTable->setEnabled( false );
1076     }
1077 }
1078
1079
1080 //=================================================================================
1081 // function : onTableActivate()
1082 // purpose  :
1083 //=================================================================================
1084 void SMESHGUI_AddQuadraticElementDlg::onCellDoubleClicked( int theRow, int theCol, int theButton, const QPoint& theMousePos )
1085 {
1086   if ( theButton == 1 && theCol == 1 )
1087     myIsEditCorners = false;
1088   
1089   displaySimulation();
1090   return;
1091 }
1092
1093
1094 //=================================================================================
1095 // function : onCellTextChange()
1096 // purpose  :
1097 //=================================================================================
1098 void SMESHGUI_AddQuadraticElementDlg::onCellTextChange(int theRow, int theCol)
1099 {
1100   onTextChange( myTable->text(theRow, theCol) );
1101 }
1102
1103
1104 QWidget* SMESHGUI_IdEditItem::createEditor() const
1105 {
1106   QLineEdit *aLineEdit = new QLineEdit(text(), table()->viewport());
1107   aLineEdit->setValidator( new SMESHGUI_IdValidator(table()->viewport(), "validator", 1) );
1108   return aLineEdit;
1109 }
1110
1111 //=================================================================================
1112 // function : keyPressEvent()
1113 // purpose  :
1114 //=================================================================================
1115 void SMESHGUI_AddQuadraticElementDlg::keyPressEvent( QKeyEvent* e )
1116 {
1117   QDialog::keyPressEvent( e );
1118   if ( e->isAccepted() )
1119     return;
1120
1121   if ( e->key() == Key_F1 )
1122     {
1123       e->accept();
1124       ClickOnHelp();
1125     }
1126 }