Salome HOME
8456928f772b1cd96094c5d28c172ea1186fbcc9
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshPatternDlg.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 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_MeshPatternDlg.cxx
24 // Author : Sergey LITONIN, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_MeshPatternDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_CreatePatternDlg.h"
31 #include "SMESHGUI_PatternWidget.h"
32 #include "SMESHGUI_Utils.h"
33 #include "SMESHGUI_VTKUtils.h"
34 #include "SMESHGUI_PatternUtils.h"
35 #include "SMESHGUI_GEOMGenUtils.h"
36
37 #include <SMESH_Actor.h>
38 #include <SMESH_ActorUtils.h>
39 #include <SMESH_NumberFilter.hxx>
40
41 #include <SMDS_Mesh.hxx>
42 #include <SMDS_MeshElement.hxx>
43
44 // SALOME GUI includes
45 #include <SUIT_ResourceMgr.h>
46 #include <SUIT_Desktop.h>
47 #include <SUIT_FileDlg.h>
48 #include <SUIT_Session.h>
49 #include <SUIT_MessageBox.h>
50
51 #include <LightApp_SelectionMgr.h>
52 #include <SalomeApp_Tools.h>
53 #include <LightApp_Application.h>
54 #include <SalomeApp_IntSpinBox.h>
55
56 #include <SALOME_ListIO.hxx>
57
58 #include <SVTK_ViewModel.h>
59 #include <SVTK_ViewWindow.h>
60 #include <VTKViewer_CellLocationsArray.h>
61
62 // SALOME KERNEL includes 
63 #include <SALOMEDS_SObject.hxx>
64
65 // OCCT includes
66 #include <TColStd_MapOfInteger.hxx>
67
68 // Qt includes
69 #include <QFrame>
70 #include <QVBoxLayout>
71 #include <QHBoxLayout>
72 #include <QGridLayout>
73 #include <QLineEdit>
74 #include <QPushButton>
75 #include <QGroupBox>
76 #include <QLabel>
77 #include <QRadioButton>
78 #include <QCheckBox>
79 #include <QButtonGroup>
80 #include <QList>
81 #include <QDir>
82 #include <QFileDialog>
83 #include <QFileInfo>
84 #include <QFile>
85 #include <QKeyEvent>
86
87 // VTK includes
88 #include <vtkIdList.h>
89 #include <vtkCellArray.h>
90 #include <vtkUnsignedCharArray.h>
91 #include <vtkUnstructuredGrid.h>
92 #include <vtkDataSetMapper.h>
93 #include <vtkProperty.h>
94
95 #define SPACING 6
96 #define MARGIN  11
97
98 /*!
99  *  Class       : SMESHGUI_MeshPatternDlg
100  *  Description : Dialog to specify filters for VTK viewer
101  */
102
103 //=======================================================================
104 // name    : SMESHGUI_MeshPatternDlg::SMESHGUI_MeshPatternDlg
105 // Purpose : Constructor
106 //=======================================================================
107 SMESHGUI_MeshPatternDlg::SMESHGUI_MeshPatternDlg( SMESHGUI* theModule )
108   : QDialog( SMESH::GetDesktop( theModule ) ),
109     mySMESHGUI( theModule ),
110     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
111     myBusy( false ),
112     myCreationDlg( 0 )
113 {
114   setModal( false );
115   setWindowTitle( tr( "CAPTION" ) );
116
117   QVBoxLayout* aDlgLay = new QVBoxLayout( this );
118   aDlgLay->setMargin( MARGIN );
119   aDlgLay->setSpacing( SPACING );
120
121   QWidget* aMainFrame = createMainFrame  ( this );
122   QWidget* aBtnFrame  = createButtonFrame( this );
123
124   aDlgLay->addWidget( aMainFrame );
125   aDlgLay->addWidget( aBtnFrame );
126
127   aDlgLay->setStretchFactor( aMainFrame, 1 );
128
129   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
130
131   myHelpFileName = "pattern_mapping_page.html";
132
133   Init();
134 }
135
136 //=======================================================================
137 // name    : SMESHGUI_MeshPatternDlg::createMainFrame
138 // Purpose : Create frame containing dialog's input fields
139 //=======================================================================
140 QWidget* SMESHGUI_MeshPatternDlg::createMainFrame (QWidget* theParent)
141 {
142   SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI );
143   QPixmap iconSlct ( mgr->loadPixmap( "SMESH", tr( "ICON_SELECT" ) ) );
144   QPixmap icon2d   ( mgr->loadPixmap( "SMESH", tr( "ICON_PATTERN_2d" ) ) );
145   QPixmap icon3d   ( mgr->loadPixmap( "SMESH", tr( "ICON_PATTERN_3d" ) ) );
146   QPixmap iconOpen ( mgr->loadPixmap( "STD",   tr( "ICON_FILE_OPEN" ) ) );
147
148   QPixmap iconSample2d ( mgr->loadPixmap( "SMESH", tr( "ICON_PATTERN_SAMPLE_2D" ) ) );
149   QPixmap iconSample3d ( mgr->loadPixmap( "SMESH", tr( "ICON_PATTERN_SAMPLE_3D" ) ) );
150
151   QWidget* aMainGrp = new QWidget( theParent );
152
153   QVBoxLayout* aMainGrpLayout = new QVBoxLayout( aMainGrp );
154   aMainGrpLayout->setMargin( 0 );
155   aMainGrpLayout->setSpacing( SPACING );
156
157   // Pattern type group
158
159   QGroupBox* aTypeGrp = new QGroupBox( tr( "PATTERN_TYPE" ), aMainGrp );
160   QHBoxLayout* aTypeGrpLayout = new QHBoxLayout( aTypeGrp );
161   aTypeGrpLayout->setMargin( MARGIN );
162   aTypeGrpLayout->setSpacing( SPACING );
163
164   mySwitch2d = new QRadioButton( aTypeGrp );
165   mySwitch3d = new QRadioButton( aTypeGrp );
166   mySwitch2d->setIcon( icon2d );
167   mySwitch3d->setIcon( icon3d );
168
169   myTypeGrp = new QButtonGroup( aMainGrp );
170   myTypeGrp->addButton( mySwitch2d, Type_2d );
171   myTypeGrp->addButton( mySwitch3d, Type_3d );
172
173   // ... layout widgets
174
175   aTypeGrpLayout->addWidget( mySwitch2d );
176   aTypeGrpLayout->addWidget( mySwitch3d );
177
178   // Mesh group
179
180   QGroupBox* aMeshGrp = new QGroupBox( tr( "SMESH_MESH" ), aMainGrp );
181   QHBoxLayout* aMeshGrpLayout = new QHBoxLayout( aMeshGrp );
182   aMeshGrpLayout->setMargin( MARGIN );
183   aMeshGrpLayout->setSpacing( SPACING );
184
185   QLabel* aMeshLab = new QLabel( tr( "SMESH_MESH" ), aMeshGrp );
186   mySelBtn[ Mesh ] = new QPushButton( aMeshGrp );
187   mySelBtn[ Mesh ]->setIcon( iconSlct );
188   mySelEdit[ Mesh ] = new QLineEdit( aMeshGrp );
189   mySelEdit[ Mesh ]->setReadOnly( true );
190
191   // ... layout widgets
192
193   aMeshGrpLayout->addWidget( aMeshLab );
194   aMeshGrpLayout->addWidget( mySelBtn[ Mesh ] );
195   aMeshGrpLayout->addWidget( mySelEdit[ Mesh ] );
196
197   // Pattern group
198
199   QGroupBox* aPatGrp = new QGroupBox( tr( "PATTERN" ), aMainGrp );
200   QGridLayout* aPatGrpLayout = new QGridLayout( aPatGrp );
201   aPatGrpLayout->setMargin( MARGIN );
202   aPatGrpLayout->setSpacing( SPACING );
203
204   // ... Pattern name
205
206   QLabel* aNameLab = new QLabel( tr( "PATTERN" ), aPatGrp );
207   myName = new QLineEdit( aPatGrp );
208   myName->setReadOnly( true );
209   myOpenBtn = new QPushButton( aPatGrp );
210   myOpenBtn->setIcon( iconOpen );
211   myNewBtn = new QPushButton( tr( "NEW" ), aPatGrp );
212
213   // ... Mode selection check box
214   myRefine = new QCheckBox( tr( "REFINE" ), aPatGrp );
215
216   // ... selection widgets for Apply to geom mode
217   myGeomGrp = new QFrame( aPatGrp );
218   myGeomGrp->setFrameStyle( QFrame::NoFrame );
219   QGridLayout* myGeomGrpLayout = new QGridLayout( myGeomGrp );
220   myGeomGrpLayout->setMargin( 0 );
221   myGeomGrpLayout->setSpacing( SPACING );
222
223   for ( int i = Object; i <= Vertex2; i++ ) {
224     mySelLbl[ i ] = new QLabel( myGeomGrp );
225     mySelBtn[ i ] = new QPushButton( myGeomGrp );
226     mySelBtn[ i ]->setIcon( iconSlct );
227     mySelEdit[ i ] = new QLineEdit( myGeomGrp );
228     mySelEdit[ i ]->setReadOnly( true );
229     myGeomGrpLayout->addWidget( mySelLbl[ i ],  i - Object, 0 );
230     myGeomGrpLayout->addWidget( mySelBtn[ i ],  i - Object, 1 );
231     myGeomGrpLayout->addWidget( mySelEdit[ i ], i - Object, 2 );
232   }
233
234   // ... Widgets for refinement of existing mesh elements
235
236   myRefineGrp = new QFrame( aPatGrp );
237   myRefineGrp->setFrameStyle( QFrame::NoFrame );
238
239   QGridLayout* myRefineGrpLayout = new QGridLayout( myRefineGrp );
240   myRefineGrpLayout->setMargin( 0 );
241   myRefineGrpLayout->setSpacing( SPACING );
242
243   mySelLbl[ Ids ] = new QLabel( myRefineGrp );
244   mySelBtn[ Ids ] = new QPushButton( myRefineGrp );
245   mySelBtn[ Ids ]->setIcon( iconSlct );
246   mySelEdit[ Ids ] = new QLineEdit( myRefineGrp );
247
248   QLabel* aNodeLbl = new QLabel( tr( "NODE_1" ), myRefineGrp );
249   myNode1          = new SalomeApp_IntSpinBox( myRefineGrp );
250   myNode2Lbl       = new QLabel( tr( "NODE_2" ), myRefineGrp );
251   myNode2          = new SalomeApp_IntSpinBox( myRefineGrp );
252
253   myRefineGrpLayout->addWidget( mySelLbl[ Ids ],  0, 0 );
254   myRefineGrpLayout->addWidget( mySelBtn[ Ids ],  0, 1 );
255   myRefineGrpLayout->addWidget( mySelEdit[ Ids ], 0, 2 );
256   myRefineGrpLayout->addWidget( aNodeLbl,         1, 0 );
257   myRefineGrpLayout->addWidget( myNode1,          1, 1, 1, 2 );
258   myRefineGrpLayout->addWidget( myNode2Lbl,       2, 0 );
259   myRefineGrpLayout->addWidget( myNode2,          2, 1, 1, 2 );
260
261   // ... reverse check box
262   myReverseChk = new QCheckBox( tr( "REVERSE" ), aPatGrp );
263
264   // ... CreatePoly check box
265   myCreatePolygonsChk = new QCheckBox( tr( "CREATE_POLYGONS_NEAR_BOUNDARY" ), aPatGrp );
266   myCreatePolyedrsChk = new QCheckBox( tr( "CREATE_POLYEDRS_NEAR_BOUNDARY" ), aPatGrp );
267
268   // ... Pictures 2d and 3d
269
270   myPicture2d = new SMESHGUI_PatternWidget( aPatGrp );
271   myPicture2d->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
272
273   myPicture3d = new QLabel( aPatGrp );
274   myPicture3d->setPixmap( iconSample3d );
275   myPicture3d->setScaledContents( false );
276   myPicture3d->setAlignment( Qt::AlignCenter );
277   myPicture3d->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
278
279   // ... preview check box
280
281   myPreviewChk = new QCheckBox( tr( "PREVIEW" ), aPatGrp );
282
283   // ... layout widgets 
284
285   aPatGrpLayout->addWidget( aNameLab,            0, 0 );
286   aPatGrpLayout->addWidget( myName,              0, 1 );
287   aPatGrpLayout->addWidget( myOpenBtn,           0, 2 );
288   aPatGrpLayout->addWidget( myNewBtn,            0, 3 );
289   aPatGrpLayout->addWidget( myRefine,            1, 0, 1, 4 );
290   aPatGrpLayout->addWidget( myRefine,            1, 0, 1, 4 );
291   aPatGrpLayout->addWidget( myGeomGrp,           2, 0, 1, 4 );
292   aPatGrpLayout->addWidget( myRefineGrp,         3, 0, 1, 4 );
293   aPatGrpLayout->addWidget( myReverseChk,        4, 0, 1, 4 );
294   aPatGrpLayout->addWidget( myCreatePolygonsChk, 5, 0, 1, 4 );
295   aPatGrpLayout->addWidget( myCreatePolyedrsChk, 6, 0, 1, 4 );
296   aPatGrpLayout->addWidget( myPicture2d,         7, 0, 1, 4 );
297   aPatGrpLayout->addWidget( myPicture3d,         8, 0, 1, 4 );
298   aPatGrpLayout->addWidget( myPreviewChk,        9, 0, 1, 4 );
299
300   // main layout
301   
302   aMainGrpLayout->addWidget( aTypeGrp );
303   aMainGrpLayout->addWidget( aMeshGrp );
304   aMainGrpLayout->addWidget( aPatGrp );
305
306   // Connect signals and slots
307
308   connect(myTypeGrp, SIGNAL(buttonClicked(int)), SLOT(onTypeChanged(int)));
309   connect(myOpenBtn, SIGNAL(clicked()),    SLOT(onOpen()));
310   connect(myNewBtn,  SIGNAL(clicked()),    SLOT(onNew()));
311
312   connect(myReverseChk, SIGNAL(toggled(bool)), SLOT(onReverse(bool)));
313   connect(myPreviewChk, SIGNAL(toggled(bool)), SLOT(onPreview(bool)));
314   connect(myRefine,     SIGNAL(toggled(bool)), SLOT(onModeToggled(bool)));
315
316   connect(myNode1, SIGNAL(valueChanged(int)), SLOT(onNodeChanged(int)));
317   connect(myNode2, SIGNAL(valueChanged(int)), SLOT(onNodeChanged(int)));
318
319   connect(mySelEdit[Ids], SIGNAL(textChanged(const QString&)), SLOT(onTextChanged(const QString&)));
320
321   QMap< int, QPushButton* >::iterator anIter;
322   for (anIter = mySelBtn.begin(); anIter != mySelBtn.end(); ++anIter)
323     connect(*anIter, SIGNAL(clicked()), SLOT(onSelInputChanged()));
324
325   return aMainGrp;
326 }
327
328 //=======================================================================
329 // name    : SMESHGUI_MeshPatternDlg::createButtonFrame
330 // Purpose : Create frame containing buttons
331 //=======================================================================
332 QWidget* SMESHGUI_MeshPatternDlg::createButtonFrame (QWidget* theParent)
333 {
334   QFrame* aFrame = new QFrame(theParent);
335   aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
336
337   myOkBtn     = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), aFrame);
338   myApplyBtn  = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
339   myCloseBtn  = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
340   myHelpBtn   = new QPushButton(tr("SMESH_BUT_HELP"),  aFrame);
341
342   QHBoxLayout* aLay = new QHBoxLayout( aFrame );
343   aLay->setMargin( MARGIN );
344   aLay->setSpacing( SPACING );
345
346   aLay->addWidget(myOkBtn);
347   aLay->addWidget(myApplyBtn);
348   aLay->addSpacing( 10 );
349   aLay->addStretch();
350   aLay->addWidget(myCloseBtn);
351   aLay->addWidget(myHelpBtn);
352
353   connect(myOkBtn,    SIGNAL(clicked()), SLOT(onOk()));
354   connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
355   connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
356   connect(myHelpBtn,  SIGNAL(clicked()), SLOT(onHelp()));
357
358   return aFrame;
359 }
360
361 //=======================================================================
362 // name    : SMESHGUI_MeshPatternDlg::~SMESHGUI_MeshPatternDlg
363 // Purpose : Destructor
364 //=======================================================================
365 SMESHGUI_MeshPatternDlg::~SMESHGUI_MeshPatternDlg()
366 {
367 }
368
369 //=======================================================================
370 // name    : SMESHGUI_MeshPatternDlg::Init
371 // Purpose : Init dialog fields, connect signals and slots, show dialog
372 //=======================================================================
373 void SMESHGUI_MeshPatternDlg::Init()
374 {
375   myPattern = SMESH::GetPattern();
376   myPreviewActor = 0;
377   myIsCreateDlgOpen = false;
378   mySelInput = Mesh;
379   myType = -1;
380   myNbPoints = -1;
381   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
382   myMesh = SMESH::SMESH_Mesh::_nil();
383
384   myMeshShape = GEOM::GEOM_Object::_nil();
385   myGeomObj[ Object  ] = GEOM::GEOM_Object::_nil();
386   myGeomObj[ Vertex1 ] = GEOM::GEOM_Object::_nil();
387   myGeomObj[ Vertex2 ] = GEOM::GEOM_Object::_nil();
388
389   // selection and SMESHGUI
390   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
391   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
392   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
393
394   myTypeGrp->button(Type_2d)->setChecked(true);
395   onTypeChanged(Type_2d);
396   onModeToggled(isRefine());
397
398   updateGeometry();
399
400   resize(minimumSize());
401
402   activateSelection();
403   onSelectionDone();
404
405   this->show();
406 }
407
408 //=======================================================================
409 // name    : SMESHGUI_MeshPatternDlg::isValid
410 // Purpose : Verify validity of entry data
411 //=======================================================================
412 bool SMESHGUI_MeshPatternDlg::isValid (const bool theMess)
413 {
414   if (isRefine())
415   {
416     QString msg;
417     bool ok = true;
418     ok = myNode1->isValid( msg, theMess ) && ok;
419     if (myType == Type_3d)
420       ok = myNode2->isValid( msg, theMess ) && ok;
421     if( !ok ) {
422       if( theMess ) {
423         QString str( tr( "SMESH_INCORRECT_INPUT" ) );
424         if ( !msg.isEmpty() )
425           str += "\n" + msg;
426         SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
427       }
428       return false;
429     }
430   }
431
432   QList<int> ids;
433   if ((isRefine() &&
434        (myMesh->_is_nil() || !getIds(ids) || getNode(false) < 0 ||
435         myType == Type_3d && (getNode(true) < 0 || getNode(false) == getNode(true))))
436       ||
437       (!isRefine() &&
438        (myMesh->_is_nil() || myMeshShape->_is_nil() || myGeomObj[ Object ]->_is_nil() ||
439         myGeomObj[ Vertex1 ]->_is_nil() || myType == Type_3d && myGeomObj[ Vertex2 ]->_is_nil())))
440   {
441     if (theMess)
442       SUIT_MessageBox::information(this, tr("SMESH_INSUFFICIENT_DATA"),
443                                    tr("SMESHGUI_INVALID_PARAMETERS"));
444     return false;
445   }
446
447   if ( myName->text().isEmpty() ) {
448     if (theMess)
449       SUIT_MessageBox::information(this, tr("SMESH_INSUFFICIENT_DATA"),
450                                    tr("SMESHGUI_INVALID_PARAMETERS"));
451     return false;
452   }
453
454   return true;
455 }
456
457 //=======================================================================
458 // name    : SMESHGUI_MeshPatternDlg::onApply
459 // Purpose : SLOT called when "Apply" button pressed.
460 //=======================================================================
461 bool SMESHGUI_MeshPatternDlg::onApply()
462 {
463   try {
464     if (!isValid())
465       return false;
466
467     erasePreview();
468
469     if (isRefine()) { // Refining existing mesh elements
470       QList<int> ids;
471       getIds(ids);
472       SMESH::long_array_var varIds = new SMESH::long_array();
473       varIds->length(ids.count());
474       int i = 0;
475       for (QList<int>::iterator it = ids.begin(); it != ids.end(); ++it)
476         varIds[i++] = *it;
477       myType == Type_2d
478         ? myPattern->ApplyToMeshFaces  (myMesh, varIds, getNode(false), myReverseChk->isChecked())
479         : myPattern->ApplyToHexahedrons(myMesh, varIds, getNode(false), getNode(true));
480
481       QStringList aParameters;
482       aParameters << myNode1->text();
483       if(myType == Type_3d )
484         aParameters << myNode2->text();
485       myMesh->SetParameters( SMESHGUI::JoinObjectParameters(aParameters) );
486
487     } else { // Applying a pattern to geometrical object
488       if (myType == Type_2d)
489         myPattern->ApplyToFace(myGeomObj[Object], myGeomObj[Vertex1], myReverseChk->isChecked());
490       else
491         myPattern->ApplyTo3DBlock(myGeomObj[Object], myGeomObj[Vertex1], myGeomObj[Vertex2]);
492     }
493
494     bool toCreatePolygons = myCreatePolygonsChk->isChecked();
495     bool toCreatePolyedrs = myCreatePolyedrsChk->isChecked();
496     if ( myPattern->MakeMesh( myMesh, toCreatePolygons, toCreatePolyedrs ) ) {
497       //mySelectionMgr->clearSelected();
498       bool autoUpdate = SMESHGUI::automaticUpdate();
499       if (!isRefine() && autoUpdate) {
500         _PTR(SObject) aSO = SMESH::FindSObject(myMesh.in());
501         SMESH_Actor* anActor = SMESH::FindActorByEntry(aSO->GetID().c_str());
502         if (!anActor) {
503           anActor = SMESH::CreateActor(aSO->GetStudy(), aSO->GetID().c_str());
504           if (anActor) {
505             SMESH::DisplayActor(SMESH::GetActiveWindow(), anActor);
506             SMESH::FitAll();
507           }
508         }
509       }
510       mySelectionMgr->clearSelected();
511       SMESH::UpdateView();
512
513       mySMESHGUI->updateObjBrowser(true);
514
515       mySelEdit[ Ids ]->setText("");
516
517       return true;
518     } else {
519       SUIT_MessageBox::information(this, tr("SMESH_ERROR"),
520                                    tr("SMESH_OPERATION_FAILED"));
521       return false;
522     }
523   } catch (const SALOME::SALOME_Exception& S_ex) {
524     SalomeApp_Tools::QtCatchCorbaException(S_ex);
525   } catch (...) {
526   }
527
528   return false;
529 }
530
531 //=======================================================================
532 // name    : SMESHGUI_MeshPatternDlg::onOk
533 // Purpose : SLOT called when "Ok" button pressed.
534 //=======================================================================
535 void SMESHGUI_MeshPatternDlg::onOk()
536 {
537   if (onApply())
538     onClose();
539 }
540
541 //=======================================================================
542 // name    : SMESHGUI_MeshPatternDlg::onClose
543 // Purpose : SLOT called when "Close" button pressed. Close dialog
544 //=======================================================================
545 void SMESHGUI_MeshPatternDlg::onClose()
546 {
547   mySelectionMgr->clearFilters();
548   SMESH::SetPickable();
549   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
550     aViewWindow->SetSelectionMode(ActorSelection);
551   disconnect(mySelectionMgr, 0, this, 0);
552   disconnect(mySMESHGUI, 0, this, 0);
553   mySMESHGUI->ResetState();
554   erasePreview();
555   reject();
556 }
557
558 //=================================================================================
559 // function : onHelp()
560 // purpose  :
561 //=================================================================================
562 void SMESHGUI_MeshPatternDlg::onHelp()
563 {
564   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
565   if (app) 
566     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
567   else {
568                 QString platform;
569 #ifdef WIN32
570                 platform = "winapplication";
571 #else
572                 platform = "application";
573 #endif
574     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
575                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
576                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
577                                                                  platform)).
578                              arg(myHelpFileName));
579   }
580 }
581
582 //=======================================================================
583 // name    : SMESHGUI_MeshPatternDlg::onSelectionDone
584 // Purpose : SLOT called when selection changed
585 //=======================================================================
586 void SMESHGUI_MeshPatternDlg::onSelectionDone()
587 {
588   if (myBusy)
589     return;
590
591   try {
592     if (mySelInput == Mesh) {
593       SALOME_ListIO aList;
594       mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
595       if (aList.Extent() != 1)
596         return;
597
598       // Retrieve mesh from selection
599       Handle(SALOME_InteractiveObject) anIO = aList.First();
600       SMESH::SMESH_Mesh_var aMesh = SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(anIO);
601       if (aMesh->_is_nil())
602         return;
603
604       // Get geom object corresponding to the mesh
605       _PTR(SObject) aSO = SMESH::FindSObject(aMesh.in());
606       myMeshShape = SMESH::GetGeom(aSO);
607
608       // Clear fields of geom objects if mesh was changed
609       if (myMesh != aMesh) {
610         for (int i = Object; i <= Ids; i++) {
611           myGeomObj[ i ] = GEOM::GEOM_Object::_nil();
612           mySelEdit[ i ]->setText("");
613         }
614       }
615
616       myMesh = aMesh;
617
618       // Set name of mesh in line edit
619       QString aName;
620       SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aName);
621       mySelEdit[ Mesh ]->setText(aName);
622
623     } else if (mySelInput == Ids) {
624       SALOME_ListIO aList;
625       mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
626       if (aList.Extent() != 1)
627         return;
628
629       QString anIds;
630       if (!SMESH::GetNameOfSelectedElements(mySelector, aList.First(), anIds))
631         anIds = "";
632
633       myBusy = true;
634       mySelEdit[ Ids ]->setText(anIds);
635       myBusy = false;
636
637     } else {
638       SALOME_ListIO aList;
639       mySelectionMgr->selectedObjects(aList, SVTK_Viewer::Type());
640       if (aList.Extent() != 1)
641         return;
642
643       // Get geom object from selection
644       Handle(SALOME_InteractiveObject) anIO = aList.First();
645       GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
646       if (anObj->_is_nil())
647         return;
648
649       // Clear fields of vertexes if face or 3d block was changed
650       if (anObj != myGeomObj[ mySelInput ] && mySelInput == Object) {
651         for (int i = Vertex1; i <= Vertex2; i++) {
652           myGeomObj[ i ] = GEOM::GEOM_Object::_nil();
653           mySelEdit[ i ]->setText("");
654         }
655       }
656
657       myGeomObj[ mySelInput ] = anObj;
658
659       // Set name of geom object in line edit
660       QString aName;
661       SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aName);
662       mySelEdit[ mySelInput ]->setText(aName);
663     }
664   } catch (const SALOME::SALOME_Exception& S_ex) {
665     SalomeApp_Tools::QtCatchCorbaException(S_ex);
666     resetSelInput();
667   } catch (...) {
668     resetSelInput();
669   }
670
671   updateWgState();
672   displayPreview();
673 }
674
675 //=======================================================================
676 // name    : SMESHGUI_MeshPatternDlg::resetSelInput
677 // Purpose : Reset fields corresponding to the current selection input
678 //=======================================================================
679 void SMESHGUI_MeshPatternDlg::resetSelInput()
680 {
681   if (mySelInput == Mesh)
682   {
683     myMesh = SMESH::SMESH_Mesh::_nil();
684     myMeshShape = GEOM::GEOM_Object::_nil();
685   }
686
687   else
688     myGeomObj[ mySelInput ] = GEOM::GEOM_Object::_nil();
689
690   mySelEdit[ mySelInput ]->setText("");
691 }
692
693 //=======================================================================
694 // name    : SMESHGUI_MeshPatternDlg::onDeactivate
695 // Purpose : SLOT called when dialog must be deativated
696 //=======================================================================
697 void SMESHGUI_MeshPatternDlg::onDeactivate()
698 {
699   mySelectionMgr->clearFilters();
700   //if (myReverseChk->isChecked())
701   //  erasePreview();
702   disconnect(mySelectionMgr, 0, this, 0);
703   setEnabled(false);
704 }
705
706 //=======================================================================
707 // name    : SMESHGUI_MeshPatternDlg::enterEvent
708 // Purpose : Event filter
709 //=======================================================================
710 void SMESHGUI_MeshPatternDlg::enterEvent (QEvent*)
711 {
712   if (myIsCreateDlgOpen)
713     return;
714
715   if (myReverseChk->isChecked())
716     displayPreview();
717   mySMESHGUI->EmitSignalDeactivateDialog();
718   setEnabled(true);
719   activateSelection();
720   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
721   onTextChanged(mySelEdit[Ids]->text());
722 }
723
724 //=======================================================================
725 // name    : SMESHGUI_MeshPatternDlg::closeEvent
726 // Purpose :
727 //=======================================================================
728 void SMESHGUI_MeshPatternDlg::closeEvent (QCloseEvent*)
729 {
730   onClose();
731 }
732
733 //=======================================================================
734 // name    : SMESHGUI_MeshPatternDlg::onSelInputChanged
735 // Purpose : SLOT. Called when -> button clicked.
736 //           Change current selection input field
737 //=======================================================================
738 void SMESHGUI_MeshPatternDlg::onSelInputChanged()
739 {
740   const QObject* aSender = sender();
741   for (int i = Mesh; i <= Ids; i++)
742     if (aSender == mySelBtn[ i ])
743       mySelInput = i;
744
745   activateSelection();
746   onSelectionDone();
747 }
748
749 //=======================================================================
750 // name    : SMESHGUI_MeshPatternDlg::prepareFilters
751 // Purpose : Prepare filters for dialog
752 //=======================================================================
753 QStringList SMESHGUI_MeshPatternDlg::prepareFilters() const
754 {
755   static QStringList aList;
756   if (aList.isEmpty())
757   {
758     aList.append(tr("PATTERN_FILT"));
759     //aList.append(tr("ALL_FILES_FILTER"));
760   }
761
762   return aList;
763 }
764
765 //=======================================================================
766 // name    : SMESHGUI_MeshPatternDlg::autoExtension
767 // Purpose : Append extension to the file name
768 //=======================================================================
769 QString SMESHGUI_MeshPatternDlg::autoExtension (const QString& theFileName) const
770 {
771   QString anExt = theFileName.section('.', -1);
772   return anExt != "smp" && anExt != "SMP" ? theFileName + ".smp" : theFileName;
773 }
774
775 //=======================================================================
776 // name    : SMESHGUI_MeshPatternDlg::onOpen
777 // Purpose : SLOT. Called when "Open" button clicked.
778 //           Displays file open dialog
779 //=======================================================================
780 void SMESHGUI_MeshPatternDlg::onOpen()
781 {
782   SUIT_FileDlg* aDlg = new SUIT_FileDlg (this, true);
783   aDlg->setWindowTitle(tr("LOAD_PATTERN"));
784   aDlg->setFileMode(QFileDialog::ExistingFile);
785   aDlg->setFilters(prepareFilters());
786   if (!myName->text().isEmpty())
787     aDlg->selectFile(myName->text() + ".smp");
788   QPushButton* anOkBtn = qFindChild<QPushButton*>( aDlg, "OK" );
789   if (anOkBtn != 0)
790     anOkBtn->setText(tr("SMESH_BUT_OK"));
791
792   if (aDlg->exec() != Accepted)
793     return;
794
795   QString fName = aDlg->selectedFile();
796   if (fName.isEmpty())
797     return;
798
799   if (QFileInfo(fName).suffix().isEmpty())
800     fName = autoExtension(fName);
801
802   fName = QDir::convertSeparators(fName);
803
804   QString prev = QDir::convertSeparators(myName->text());
805   if (prev == fName)
806     return;
807
808   // Read string from file
809   QFile aFile(fName);
810   if (!aFile.open(QIODevice::ReadOnly)) {
811     SUIT_MessageBox::information(this, tr("SMESH_ERROR"),
812                                  tr("ERROR_OF_OPENING"));
813     return;
814   }
815
816   QByteArray aDataArray = aFile.readAll();
817   if (aDataArray.isEmpty()) {
818     SUIT_MessageBox::information(this, tr("SMESH_ERROR"),
819                                  tr("ERROR_OF_READING"));
820     return;
821   }
822
823   if (loadFromFile(aDataArray))
824     myName->setText(QFileInfo(fName).completeBaseName());
825
826   updateWgState();
827   displayPreview();
828 }
829
830 //=======================================================================
831 // name    : SMESHGUI_MeshPatternDlg::onCloseCreationDlg
832 // Purpose : SLOT. Called when "Pattern creation" dialog closed with "Close"
833 //=======================================================================
834 void SMESHGUI_MeshPatternDlg::onCloseCreationDlg()
835 {
836   setEnabled(true);
837   myIsCreateDlgOpen = false;
838 }
839
840 //=======================================================================
841 // name    : SMESHGUI_MeshPatternDlg::onOkCreationDlg
842 // Purpose : SLOT. Called when "Pattern creation" dialog closed with OK
843 //           or SAVE buttons. Initialize myPattern field. Redisplay preview
844 //=======================================================================
845 void SMESHGUI_MeshPatternDlg::onOkCreationDlg()
846 {
847   myPattern = SMESH::SMESH_Pattern::_duplicate(myCreationDlg->GetPattern());
848   myName->setText(myCreationDlg->GetPatternName());
849
850   updateWgState();
851   displayPreview();
852
853   setEnabled(true);
854   myIsCreateDlgOpen = false;
855 }
856
857 //=======================================================================
858 // name    : SMESHGUI_MeshPatternDlg::onNew
859 // Purpose : SLOT. Called when "New..." button clicked. Create new pattern
860 //=======================================================================
861 void SMESHGUI_MeshPatternDlg::onNew()
862 {
863   setEnabled(false);
864   myIsCreateDlgOpen = true;
865   if (myCreationDlg == 0)
866   {
867     myCreationDlg = new SMESHGUI_CreatePatternDlg( mySMESHGUI, myType);
868     connect(myCreationDlg, SIGNAL(NewPattern()), SLOT(onOkCreationDlg()));
869     connect(myCreationDlg, SIGNAL(Close()), SLOT(onCloseCreationDlg()));
870   }
871   else
872     myCreationDlg->Init(myType);
873
874   myCreationDlg->SetMesh(myMesh);
875   myCreationDlg->show();
876 }
877
878 //=======================================================================
879 // name    : SMESHGUI_MeshPatternDlg::onReverse
880 // Purpose : SLOT. Called when state of "Reverse order..." checkbox chaged
881 //           Calculate new points of the mesh to be created. Redisplay preview
882 //=======================================================================
883 void SMESHGUI_MeshPatternDlg::onReverse (bool)
884 {
885   displayPreview();
886 }
887
888 //=======================================================================
889
890 // name    : SMESHGUI_MeshPatternDlg::onPreview
891 // Purpose : SLOT. Called when state of "Preview" checkbox changed
892 //           Display/Erase preview
893 //=======================================================================
894 void SMESHGUI_MeshPatternDlg::onPreview (bool)
895 {
896   displayPreview();
897 }
898
899 //=======================================================================
900 // name    : SMESHGUI_MeshPatternDlg::displayPreview
901 // Purpose : Display preview
902 //=======================================================================
903 void SMESHGUI_MeshPatternDlg::displayPreview()
904 {
905   try {
906     // Redisplay preview in dialog
907     SMESH::point_array_var pnts = myPattern->GetPoints();
908     SMESH::long_array_var keyPoints = myPattern->GetKeyPoints();
909     SMESH::array_of_long_array_var elemPoints = myPattern->GetElementPoints(false);
910
911     if (pnts->length()       == 0 ||
912         keyPoints->length()  == 0 ||
913         elemPoints->length() == 0) {
914       erasePreview();
915       return;
916     } else {
917       PointVector aPoints(pnts->length());
918       QVector<int> aKeyPoints(keyPoints->length());
919       ConnectivityVector anElemPoints(elemPoints->length());
920
921       for (int i = 0, n = pnts->length(); i < n; i++)
922         aPoints[ i ] = pnts[ i ];
923
924       for (int i2 = 0, n2 = keyPoints->length(); i2 < n2; i2++)
925         aKeyPoints[ i2 ] = keyPoints[ i2 ];
926
927       for (int i3 = 0, n3 = elemPoints->length(); i3 < n3; i3++) {
928         QVector<int> aVec(elemPoints[ i3 ].length());
929         for (int i4 = 0, n4 = elemPoints[ i3 ].length(); i4 < n4; i4++)
930           aVec[ i4 ] = elemPoints[ i3 ][ i4 ];
931
932         anElemPoints[ i3 ] = aVec;
933       }
934
935       myPicture2d->SetPoints(aPoints, aKeyPoints, anElemPoints);
936     }
937
938     // Redisplay preview in 3D viewer
939     if (myPreviewActor != 0) {
940       if (SVTK_ViewWindow* vf = SMESH::GetCurrentVtkView()) {
941         vf->RemoveActor(myPreviewActor);
942         vf->Repaint();
943       }
944       myPreviewActor->Delete();
945       myPreviewActor = 0;
946     }
947
948     if (!myPreviewChk->isChecked() || !isValid(false))
949       return;
950
951     vtkUnstructuredGrid* aGrid = getGrid();
952     if (aGrid == 0)
953       return;
954
955     // Create and display actor
956     vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
957     aMapper->SetInput(aGrid);
958
959     myPreviewActor = SALOME_Actor::New();
960     myPreviewActor->PickableOff();
961     myPreviewActor->SetMapper(aMapper);
962
963     vtkProperty* aProp = vtkProperty::New();
964     aProp->SetRepresentationToWireframe();
965     aProp->SetColor(250, 0, 250);
966     if (SMESH::FindActorByObject(myMesh))
967       aProp->SetLineWidth( SMESH::GetFloat( "SMESH:element_width", 1 ) + 1 );
968     else
969       aProp->SetLineWidth(1);
970     myPreviewActor->SetProperty(aProp);
971
972     myPreviewActor->SetRepresentation(3);
973
974     SMESH::GetCurrentVtkView()->AddActor(myPreviewActor);
975     SMESH::GetCurrentVtkView()->Repaint();
976
977     aProp->Delete();
978     aGrid->Delete();
979   } catch (const SALOME::SALOME_Exception& S_ex) {
980     SalomeApp_Tools::QtCatchCorbaException(S_ex);
981     erasePreview();
982   } catch (...) {
983     erasePreview();
984   }
985 }
986
987 //=======================================================================
988 // name    : SMESHGUI_MeshPatternDlg::erasePreview
989 // Purpose : Erase preview
990 //=======================================================================
991 void SMESHGUI_MeshPatternDlg::erasePreview()
992 {
993   // Erase preview in 2D viewer
994   myPicture2d->SetPoints(PointVector(), QVector<int>(), ConnectivityVector());
995
996   // Erase preview in 3D viewer
997   if (myPreviewActor == 0)
998     return;
999
1000
1001   if (SVTK_ViewWindow* vf = SMESH::GetCurrentVtkView())
1002   {
1003     vf->RemoveActor(myPreviewActor);
1004     vf->Repaint();
1005   }
1006   myPreviewActor->Delete();
1007   myPreviewActor = 0;
1008 }
1009
1010 //=======================================================================
1011 // name    : SMESHGUI_MeshPatternDlg::updateWgState
1012 // Purpose : Enable/disable selection widgets
1013 //=======================================================================
1014 void SMESHGUI_MeshPatternDlg::updateWgState()
1015 {
1016   if (myMesh->_is_nil()) {
1017     for (int i = Object; i <= Ids; i++) {
1018       mySelBtn [ i ]->setEnabled(false);
1019       mySelEdit[ i ]->setEnabled(false);
1020       mySelEdit[ i ]->setText("");
1021     }
1022     myNode1->setEnabled(false);
1023     myNode2->setEnabled(false);
1024     myNode1->setRange(0, 0);
1025     myNode2->setRange(0, 0);
1026   } else {
1027     mySelBtn [ Object ]->setEnabled(true);
1028     mySelEdit[ Object ]->setEnabled(true);
1029     mySelBtn [ Ids ]   ->setEnabled(true);
1030     mySelEdit[ Ids ]   ->setEnabled(true);
1031
1032     if (myGeomObj[ Object ]->_is_nil()) {
1033       for (int i = Vertex1; i <= Vertex2; i++) {
1034         mySelBtn [ i ]->setEnabled(false);
1035         mySelEdit[ i ]->setEnabled(false);
1036         mySelEdit[ i ]->setText("");
1037       }
1038     } else {
1039       for (int i = Object; i <= Vertex2; i++) {
1040         mySelBtn [ i ]->setEnabled(true);
1041         mySelEdit[ i ]->setEnabled(true);
1042       }
1043     }
1044
1045     QList<int> ids;
1046     if (!CORBA::is_nil(myPattern)/* && getIds(ids)*/) {
1047       SMESH::long_array_var keyPoints = myPattern->GetKeyPoints();
1048       if (keyPoints->length()) {
1049         myNode1->setEnabled(true);
1050         myNode2->setEnabled(true);
1051         myNode1->setRange(1, keyPoints->length());
1052         myNode2->setRange(1, keyPoints->length());
1053         return;
1054       }
1055     }
1056
1057     myNode1->setEnabled(false);
1058     myNode2->setEnabled(false);
1059     myNode1->setRange(0, 0);
1060     myNode2->setRange(0, 0);
1061   }
1062 }
1063
1064 //=======================================================================
1065 // name    : SMESHGUI_MeshPatternDlg::activateSelection
1066 // Purpose : Activate selection in accordance with current selection input
1067 //=======================================================================
1068 void SMESHGUI_MeshPatternDlg::activateSelection()
1069 {
1070   mySelectionMgr->clearFilters();
1071   if (mySelInput == Ids) {
1072     SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh);
1073     if (anActor)
1074       SMESH::SetPickable(anActor);
1075
1076     if (myType == Type_2d)
1077       {
1078         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1079           aViewWindow->SetSelectionMode(FaceSelection);
1080       }
1081     else
1082       {
1083         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1084           aViewWindow->SetSelectionMode(CellSelection);
1085       }
1086   }
1087   else {
1088     SMESH::SetPickable();
1089     //mySelectionMgr->setSelectionModes(ActorSelection);
1090     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1091       aViewWindow->SetSelectionMode(ActorSelection);
1092   }
1093
1094   if (mySelInput == Object && !myMeshShape->_is_nil()) {
1095     if (myType == Type_2d) {
1096       if (myNbPoints > 0)
1097         mySelectionMgr->installFilter
1098           (new SMESH_NumberFilter ("GEOM", TopAbs_VERTEX, myNbPoints, TopAbs_FACE, myMeshShape));
1099       else
1100         mySelectionMgr->installFilter
1101           (new SMESH_NumberFilter ("GEOM", TopAbs_SHAPE, myNbPoints, TopAbs_FACE, myMeshShape));
1102     } else {
1103       TColStd_MapOfInteger aTypes;
1104       aTypes.Add(TopAbs_SHELL);
1105       aTypes.Add(TopAbs_SOLID);
1106       mySelectionMgr->installFilter
1107         (new SMESH_NumberFilter ("GEOM", TopAbs_FACE, 6, aTypes, myMeshShape, true));
1108     }
1109   } else if ((mySelInput == Vertex1 || mySelInput == Vertex2) && !myGeomObj[ Object ]->_is_nil()) {
1110     mySelectionMgr->installFilter
1111       (new SMESH_NumberFilter ("GEOM", TopAbs_SHAPE, 1, TopAbs_VERTEX, myGeomObj[ Object ]));
1112   } else {
1113   }
1114 }
1115
1116 //=======================================================================
1117 // name    : SMESHGUI_MeshPatternDlg::loadFromFile
1118 // Purpose : Load pattern from file
1119 //=======================================================================
1120 bool SMESHGUI_MeshPatternDlg::loadFromFile (const QString& theName)
1121 {
1122   try {
1123     SMESH::SMESH_Pattern_var aPattern = SMESH::GetPattern();
1124
1125     if (!aPattern->LoadFromFile(theName.toLatin1().data()) ||
1126         myType == Type_2d && !aPattern->Is2D()) {
1127       SMESH::SMESH_Pattern::ErrorCode aCode = aPattern->GetErrorCode();
1128       QString aMess;
1129       if      (aCode == SMESH::SMESH_Pattern::ERR_READ_NB_POINTS     ) aMess = tr("ERR_READ_NB_POINTS");
1130       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_POINT_COORDS  ) aMess = tr("ERR_READ_POINT_COORDS");
1131       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_TOO_FEW_POINTS) aMess = tr("ERR_READ_TOO_FEW_POINTS");
1132       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_3D_COORD      ) aMess = tr("ERR_READ_3D_COORD");
1133       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_NO_KEYPOINT   ) aMess = tr("ERR_READ_NO_KEYPOINT");
1134       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_BAD_INDEX     ) aMess = tr("ERR_READ_BAD_INDEX");
1135       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_ELEM_POINTS   ) aMess = tr("ERR_READ_ELEM_POINTS");
1136       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_NO_ELEMS      ) aMess = tr("ERR_READ_NO_ELEMS");
1137       else if (aCode == SMESH::SMESH_Pattern::ERR_READ_BAD_KEY_POINT ) aMess = tr("ERR_READ_BAD_KEY_POINT");
1138       else                                                             aMess = tr("ERROR_OF_LOADING");
1139
1140       SUIT_MessageBox::information(this, tr("SMESH_ERROR"), aMess);
1141       return false;
1142     } else {
1143       myPattern = aPattern;
1144       return true;
1145     }
1146   } catch (const SALOME::SALOME_Exception& S_ex) {
1147     SalomeApp_Tools::QtCatchCorbaException(S_ex);
1148     SUIT_MessageBox::information(this, tr("SMESH_ERROR"),
1149                                  tr("ERROR_OF_LOADING") );
1150     return false;
1151   }
1152 }
1153
1154 //=======================================================================
1155 // name    : SMESHGUI_MeshPatternDlg::onTypeChanged
1156 // Purpose : SLOT. Called when pattern type changed.
1157 //           Change dialog's look and feel
1158 //=======================================================================
1159 void SMESHGUI_MeshPatternDlg::onTypeChanged (int theType)
1160 {
1161   if (myType == theType)
1162     return;
1163
1164   myType = theType;
1165
1166   myNbPoints = -1;
1167   myGeomObj[ Object  ] = GEOM::GEOM_Object::_nil();
1168   myGeomObj[ Vertex1 ] = GEOM::GEOM_Object::_nil();
1169   myGeomObj[ Vertex2 ] = GEOM::GEOM_Object::_nil();
1170   myPattern = SMESH::GetPattern();
1171
1172   myName->setText("");
1173   mySelEdit[ Object  ]->setText("");
1174   mySelEdit[ Vertex1 ]->setText("");
1175   mySelEdit[ Vertex2 ]->setText("");
1176   mySelEdit[ Ids ]    ->setText("");
1177   myCreatePolygonsChk->show();
1178   myCreatePolyedrsChk->show();
1179
1180   if (theType == Type_2d) {
1181     // Geom widgets
1182     mySelLbl [ Vertex2 ]->hide();
1183     mySelBtn [ Vertex2 ]->hide();
1184     mySelEdit[ Vertex2 ]->hide();
1185     myReverseChk->show();
1186     myPicture2d->show();
1187     myPicture3d->hide();
1188     mySelLbl[ Object  ]->setText(tr("FACE"));
1189     mySelLbl[ Vertex1 ]->setText(tr("VERTEX"));
1190     // Refine widgets
1191     mySelLbl[ Ids ]->setText(tr("MESH_FACES"));
1192     myNode2Lbl->hide();
1193     myNode2   ->hide();
1194   } else {
1195     // Geom widgets
1196     mySelLbl [ Vertex2 ]->show();
1197     mySelBtn [ Vertex2 ]->show();
1198     mySelEdit[ Vertex2 ]->show();
1199     myReverseChk->hide();
1200     myPicture2d->hide();
1201     myPicture3d->show();
1202     mySelLbl[ Object  ]->setText(tr("3D_BLOCK"));
1203     mySelLbl[ Vertex1 ]->setText(tr("VERTEX1"));
1204     mySelLbl[ Vertex2 ]->setText(tr("VERTEX2"));
1205     // Refine widgets
1206     mySelLbl[ Ids ]->setText(tr("MESH_VOLUMES"));
1207     myNode2Lbl->show();
1208     myNode2   ->show();
1209   }
1210
1211   mySelInput = Mesh;
1212   activateSelection();
1213   updateWgState();
1214   displayPreview();
1215 }
1216
1217 //=======================================================================
1218 // name    : SMESHGUI_MeshPatternDlg::getGrid
1219 // Purpose : Get unstructured grid for pattern
1220 //=======================================================================
1221 vtkUnstructuredGrid* SMESHGUI_MeshPatternDlg::getGrid()
1222 {
1223   try {
1224     // Get points from pattern
1225     SMESH::point_array_var pnts;
1226     QList<int> ids;
1227     if (isRefine() && getIds(ids)) {
1228       SMESH::long_array_var varIds = new SMESH::long_array();
1229       varIds->length(ids.count());
1230       int i = 0;
1231       for (QList<int>::iterator it = ids.begin(); it != ids.end(); ++it)
1232         varIds[i++] = *it;
1233       pnts = myType == Type_2d
1234         ? myPattern->ApplyToMeshFaces  (myMesh, varIds, getNode(false), myReverseChk->isChecked())
1235         : myPattern->ApplyToHexahedrons(myMesh, varIds, getNode(false), getNode(true));
1236     } else {
1237       pnts = myType == Type_2d
1238         ? myPattern->ApplyToFace   (myGeomObj[ Object ], myGeomObj[ Vertex1 ], myReverseChk->isChecked())
1239       : myPattern->ApplyTo3DBlock(myGeomObj[ Object ], myGeomObj[ Vertex1 ], myGeomObj[ Vertex2 ]);
1240     }
1241
1242     SMESH::array_of_long_array_var elemPoints = myPattern->GetElementPoints(true);
1243
1244     if (pnts->length() == 0 || elemPoints->length() == 0)
1245       return 0;
1246
1247     // to do : to be removed /////////////////////////////////////////////
1248
1249 #ifdef DEB_SLN
1250     for (int i1 = 0, n1 = pnts->length(); i1 < n1; i1++)
1251       printf("%d: %g %g %g\n", i1, pnts[ i1 ].x, pnts[ i1 ].y, pnts[ i1 ].z);
1252
1253     printf("\nELEMENTS : \n");
1254     for (int i2 = 0, n2 = elemPoints->length(); i2 < n2; i2++)
1255     {
1256
1257       printf("%d: ", i2);
1258       for (int i3 = 0, n3 = elemPoints[ i2 ].length(); i3 < n3; i3++)
1259         printf("%d ", elemPoints[ i2 ][ i3 ]);
1260
1261       printf("\n");
1262
1263     }
1264 #endif
1265     //////////////////////////////////////////////////////////////////////
1266
1267     // Calculate number of points used for cell
1268     vtkIdType aNbCells = elemPoints->length();
1269     vtkIdType aCellsSize = 0;
1270     for (int i = 0, n = elemPoints->length(); i < n; i++)
1271       aCellsSize += elemPoints[ i ].length();
1272
1273     // Create unstructured grid and other  usefull arrays
1274     vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
1275
1276     vtkCellArray* aConnectivity = vtkCellArray::New();
1277     aConnectivity->Allocate(aCellsSize, 0);
1278
1279     vtkPoints* aPoints = vtkPoints::New();
1280     aPoints->SetNumberOfPoints(pnts->length());
1281
1282     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
1283     aCellTypesArray->SetNumberOfComponents(1);
1284     aCellTypesArray->Allocate(aNbCells * aCellTypesArray->GetNumberOfComponents());
1285
1286     vtkIdList *anIdList = vtkIdList::New();
1287
1288     // Fill array of points
1289     for (int p = 0, nbPnt = pnts->length(); p < nbPnt; p++)
1290       aPoints->SetPoint(p, pnts[ p ].x, pnts[ p ].y, pnts[ p ].z);
1291
1292     for (int e = 0, nbElem = elemPoints->length(); e < nbElem; e++) {
1293       int nbPoints = elemPoints[ e ].length();
1294       anIdList->SetNumberOfIds(nbPoints);
1295       for (int i = 0; i < nbPoints; i++)
1296         anIdList->SetId(i, elemPoints[ e ][ i ]);
1297
1298       aConnectivity->InsertNextCell(anIdList);
1299
1300       if      (nbPoints == 3) aCellTypesArray->InsertNextValue(VTK_TRIANGLE);
1301       else if (nbPoints == 5) aCellTypesArray->InsertNextValue(VTK_PYRAMID);
1302       else if (nbPoints == 6) aCellTypesArray->InsertNextValue(VTK_WEDGE);
1303       else if (nbPoints == 8) aCellTypesArray->InsertNextValue(VTK_HEXAHEDRON);
1304       else if (nbPoints == 4 && myType == Type_2d) aCellTypesArray->InsertNextValue(VTK_QUAD);
1305       else if (nbPoints == 4 && myType == Type_3d) aCellTypesArray->InsertNextValue(VTK_TETRA);
1306       else aCellTypesArray->InsertNextValue(VTK_EMPTY_CELL);
1307     }
1308
1309     VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
1310     aCellLocationsArray->SetNumberOfComponents(1);
1311     aCellLocationsArray->SetNumberOfTuples(aNbCells);
1312
1313     aConnectivity->InitTraversal();
1314     for (vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell(npts, pts); idType++)
1315       aCellLocationsArray->SetValue(idType, aConnectivity->GetTraversalLocation(npts));
1316
1317     aGrid->SetPoints(aPoints);
1318     aGrid->SetCells(aCellTypesArray, aCellLocationsArray,aConnectivity);
1319
1320     aConnectivity->Delete();
1321     aPoints->Delete();
1322     aCellTypesArray->Delete();
1323     anIdList->Delete();
1324     aCellLocationsArray->Delete();
1325
1326     return aGrid;
1327   } catch (...) {
1328     return 0;
1329   }
1330 }
1331
1332 //=======================================================================
1333 // name    : onModeToggled
1334 // Purpose :
1335 //=======================================================================
1336 void SMESHGUI_MeshPatternDlg::onModeToggled (bool on)
1337 {
1338   on ? myRefineGrp->show() : myRefineGrp->hide();
1339   on ? myGeomGrp->hide()   : myGeomGrp->show();
1340
1341   displayPreview();
1342 }
1343
1344 //=======================================================================
1345 // name    : isRefine
1346 // Purpose :
1347 //=======================================================================
1348 bool SMESHGUI_MeshPatternDlg::isRefine() const
1349 {
1350   return myRefine->isChecked();
1351 }
1352
1353 //=======================================================================
1354 // name    : onTextChanged
1355 // Purpose :
1356 //=======================================================================
1357 void SMESHGUI_MeshPatternDlg::onTextChanged (const QString& theNewText)
1358 {
1359   if (myBusy || !isRefine())
1360     return;
1361
1362   myBusy = true;
1363
1364   if (mySelInput != Ids) {
1365     mySelInput = Ids;
1366     activateSelection();
1367   }
1368
1369   // hilight entered elements/nodes
1370   SMDS_Mesh* aMesh = 0;
1371   SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh);
1372   if (anActor)
1373     aMesh = anActor->GetObject()->GetMesh();
1374
1375   if (aMesh) {
1376     QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
1377
1378     TColStd_MapOfInteger newIndices;
1379
1380     for (int i = 0; i < aListId.count(); i++) {
1381       const SMDS_MeshElement * e = aMesh->FindElement(aListId[ i ].toInt());
1382       if (e && e->GetType() == (myType == Type_2d ? SMDSAbs_Face : SMDSAbs_Volume))
1383         newIndices.Add(e->GetID());
1384     }
1385     mySelector->AddOrRemoveIndex( anActor->getIO(), newIndices, false);
1386     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1387       aViewWindow->highlight( anActor->getIO(), true, true );
1388   }
1389
1390   myBusy = false;
1391
1392   displayPreview();
1393 }
1394
1395 //=======================================================================
1396 // name    : onNodeChanged
1397 // Purpose :
1398 //=======================================================================
1399 void SMESHGUI_MeshPatternDlg::onNodeChanged (int value)
1400 {
1401   if (myType == Type_3d) {
1402     SalomeApp_IntSpinBox* first = (SalomeApp_IntSpinBox*)sender();
1403     SalomeApp_IntSpinBox* second = first == myNode1 ? myNode2 : myNode1;
1404     int secondVal = second->value();
1405     if (secondVal == value) {
1406       secondVal = value == second->maximum() ? second->minimum() : value + 1;
1407       bool blocked = second->signalsBlocked();
1408       second->blockSignals(true);
1409       second->setValue(secondVal);
1410       second->blockSignals(blocked);
1411     }
1412   }
1413
1414   displayPreview();
1415 }
1416
1417 //=======================================================================
1418 // name    : getIds
1419 // Purpose :
1420 //=======================================================================
1421 bool SMESHGUI_MeshPatternDlg::getIds (QList<int>& ids) const
1422 {
1423   ids.clear();
1424   QStringList strIds = mySelEdit[Ids]->text().split(" ", QString::SkipEmptyParts );
1425   bool isOk;
1426   int val;
1427   for (QStringList::iterator it = strIds.begin(); it != strIds.end(); ++it) {
1428     val = (*it).toInt(&isOk);
1429     if (isOk)
1430       ids.append(val);
1431   }
1432
1433   return ids.count();
1434 }
1435
1436 //=======================================================================
1437 // name    : getNode1
1438 // Purpose :
1439 //=======================================================================
1440 int SMESHGUI_MeshPatternDlg::getNode (bool second) const
1441 {
1442   return second ? myNode2->value() - 1 : myNode1->value() - 1;
1443 }
1444
1445 //=================================================================================
1446 // function : keyPressEvent()
1447 // purpose  :
1448 //=================================================================================
1449 void SMESHGUI_MeshPatternDlg::keyPressEvent( QKeyEvent* e )
1450 {
1451   QDialog::keyPressEvent( e );
1452   if ( e->isAccepted() )
1453     return;
1454
1455   if ( e->key() == Qt::Key_F1 )
1456     {
1457       e->accept();
1458       onHelp();
1459     }
1460 }