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