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