Salome HOME
b774599d47b6cc2ac69ce204f0f7b94ca26f1bf0
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ComputeDlg.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File   : SMESHGUI_ComputeDlg.cxx
21 // Author : Edward AGAPOV, Open CASCADE S.A.S.
22 // SMESH includes
23 //
24 #include "SMESHGUI_ComputeDlg.h"
25
26 #include "SMDS_Mesh.hxx"
27 #include "SMDS_SetIterator.hxx"
28 #include "SMESHGUI.h"
29 #include "SMESHGUI_GEOMGenUtils.h"
30 #include "SMESHGUI_HypothesesUtils.h"
31 #include "SMESHGUI_MeshEditPreview.h"
32 #include "SMESHGUI_MeshInfosBox.h"
33 #include "SMESHGUI_MeshOrderDlg.h"
34 #include "SMESHGUI_MeshOrderOp.h"
35 #include "SMESHGUI_MeshUtils.h"
36 #include "SMESHGUI_VTKUtils.h"
37 #include "SMESH_Actor.h"
38 #include "SMESH_ActorUtils.h"
39
40 // SALOME GEOM includes
41 #include <GEOMBase.h>
42 #include <GEOM_Actor.h>
43 #include <GEOM_wrap.hxx>
44
45 // SALOME GUI includes
46 #include <LightApp_SelectionMgr.h>
47 #include <LightApp_UpdateFlags.h>
48 #include <QtxComboBox.h>
49 #include <SALOME_ListIO.hxx>
50 #include <SUIT_Desktop.h>
51 #include <SUIT_MessageBox.h>
52 #include <SUIT_OverrideCursor.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SUIT_Session.h>
55 #include <SVTK_ViewModel.h>
56 #include <SVTK_ViewWindow.h>
57 #include <SalomeApp_Application.h>
58
59 // SALOME KERNEL includes
60 #include <SALOMEDS_SObject.hxx>
61 #include <SALOMEDSClient_SObject.hxx>
62 #include <SALOMEDS_wrap.hxx>
63 #include "utilities.h"
64
65 #include CORBA_SERVER_HEADER(SMESH_Group)
66
67 // OCCT includes
68 #include <BRepBndLib.hxx>
69 #include <BRepMesh_IncrementalMesh.hxx>
70 #include <BRep_Tool.hxx>
71 #include <Bnd_Box.hxx>
72 #include <Poly_Triangulation.hxx>
73 #include <TopExp.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopLoc_Location.hxx>
76 #include <TopTools_IndexedMapOfShape.hxx>
77 #include <TopoDS.hxx>
78
79 #include <Standard_ErrorHandler.hxx>
80
81 // Qt includes
82 #include <QFrame>
83 #include <QPushButton>
84 #include <QLabel>
85 #include <QRadioButton>
86 #include <QTableWidget>
87 #include <QHeaderView>
88 #include <QGridLayout>
89 #include <QHBoxLayout>
90 #include <QVBoxLayout>
91 #include <QButtonGroup>
92 #include <QCloseEvent>
93 #include <QTimerEvent>
94 #include <QProgressBar>
95
96 // VTK includes
97 #include <vtkProperty.h>
98
99 // STL includes
100 #include <vector>
101 #include <set>
102
103 #ifndef WIN32
104 #include <sys/sysinfo.h>
105 #endif
106
107 #define SPACING 6
108 #define MARGIN  11
109
110 #define COLONIZE(str)   (QString(str).contains(":") > 0 ? QString(str) : QString(str) + " :" )
111
112 enum TCol {
113   COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, COL_BAD_MESH, NB_COLUMNS
114 };
115
116 //using namespace SMESH;
117
118 namespace SMESH
119 {
120   //=============================================================================
121   /*!
122    * \brief Allocate some memory at construction and release it at destruction.
123    * Is used to be able to continue working after mesh generation or visualization
124    * break due to lack of memory
125    */
126   //=============================================================================
127
128   struct MemoryReserve
129   {
130     char* myBuf;
131     MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M
132     void release() { delete [] myBuf; myBuf = 0; }
133     ~MemoryReserve() { release(); }
134   };
135
136   // =========================================================================================
137   /*!
138    * \brief Class showing shapes without publishing
139    */
140   // =========================================================================================
141
142   class TShapeDisplayer
143   {
144   public:
145     // -----------------------------------------------------------------------
146     TShapeDisplayer(): myViewWindow(0)
147     {
148       myProperty = vtkProperty::New();
149       myProperty->SetRepresentationToWireframe();
150       myProperty->SetColor( 250, 0, 250 );
151       myProperty->SetAmbientColor( 250, 0, 250 );
152       myProperty->SetDiffuseColor( 250, 0, 250 );
153       //myProperty->SetSpecularColor( 250, 0, 250 );
154       myProperty->SetLineWidth( 5 );
155     }
156     // -----------------------------------------------------------------------
157     ~TShapeDisplayer()
158     {
159       DeleteActors();
160       myProperty->Delete();
161     }
162     // -----------------------------------------------------------------------
163     void DeleteActors()
164     {
165       if ( hasViewWindow() ) {
166         TActorIterator actorIt = actorIterator();
167         while ( actorIt.more() )
168           if (VTKViewer_Actor* anActor = actorIt.next()) {
169             myViewWindow->RemoveActor( anActor );
170             //anActor->Delete();
171           }
172       }
173       myIndexToShape.Clear();
174       myActors.clear();
175       myShownActors.clear();
176       myBuiltSubs.clear();
177     }
178     // -----------------------------------------------------------------------
179     void SetVisibility (bool theVisibility)
180     {
181       TActorIterator actorIt = shownIterator();
182       while ( actorIt.more() )
183         if (VTKViewer_Actor* anActor = actorIt.next())
184           anActor->SetVisibility(theVisibility);
185       SMESH::RepaintCurrentView();
186     }
187     // -----------------------------------------------------------------------
188     bool HasReadyActorsFor (int subShapeID, GEOM::GEOM_Object_var aMainShape )
189     {
190       std::string mainEntry;
191       if ( !aMainShape->_is_nil() )
192         mainEntry = aMainShape->GetStudyEntry();
193       return ( myMainEntry == mainEntry &&
194                myBuiltSubs.find( subShapeID ) != myBuiltSubs.end() );
195     }
196     // -----------------------------------------------------------------------
197     void Show( int subShapeID, GEOM::GEOM_Object_var aMainShape, bool only = false)
198     {
199       SVTK_ViewWindow* aViewWindow  = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() );
200       SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
201       std::string mainEntry;
202       if ( !aMainShape->_is_nil() )
203         mainEntry = aMainShape->GetStudyEntry();
204       if ( myMainEntry != mainEntry || aViewWindow != myViewWindow ) { // remove actors
205         DeleteActors();
206         TopoDS_Shape aShape;
207         if ( !aMainShape->_is_nil() && GEOMBase::GetShape(aMainShape, aShape)) {
208           checkTriangulation( aShape );
209           TopExp::MapShapes(aShape, myIndexToShape);
210           myActors.resize( myIndexToShape.Extent(), 0 );
211           myShownActors.reserve( myIndexToShape.Extent() );
212         }
213         myMainEntry  = mainEntry;
214         myViewWindow = aViewWindow;
215       }
216       if ( only ) { // hide shown actors
217         TActorIterator actorIt = shownIterator();
218         while ( actorIt.more() )
219           if (VTKViewer_Actor* anActor = actorIt.next())
220             anActor->SetVisibility(false);
221         myShownActors.clear();
222       }
223       // find actors to show
224       TopoDS_Shape aShape = myIndexToShape( subShapeID );
225       if ( !aShape.IsNull() ) {
226         TopAbs_ShapeEnum type( aShape.ShapeType() >= TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE );
227         for ( TopExp_Explorer exp( aShape, type ); exp.More(); exp.Next() ) {
228           //checkTriangulation( exp.Current() );
229           if ( GEOM_Actor* anActor = getActor( exp.Current() ) ) {
230             int UNbIsos = resMgr->integerValue( "Geometry", "iso_number_u", 1);
231             int VNbIsos = resMgr->integerValue( "Geometry", "iso_number_v", 1);
232             int aNbIsos[2] = { UNbIsos ? UNbIsos : 1, VNbIsos ? VNbIsos : 1 };
233             anActor->SetNbIsos( aNbIsos );
234             myShownActors.push_back( anActor );
235           }
236         }
237         if ( type == TopAbs_FACE ) {
238           for ( TopExp_Explorer exp( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) {
239             const TopoDS_Edge & edge = TopoDS::Edge( exp.Current() );
240             if ( !BRep_Tool::Degenerated( edge ))
241               if ( GEOM_Actor* anActor = getActor( exp.Current() ))
242                 myShownActors.push_back( anActor );
243           }
244         }
245       }
246       myBuiltSubs.insert( subShapeID );
247       SetVisibility(true);
248     }
249     // -----------------------------------------------------------------------
250
251   private:
252
253     typedef std::vector<GEOM_Actor*> TActorVec;
254     TActorVec                  myActors;
255     TActorVec                  myShownActors;
256     TopTools_IndexedMapOfShape myIndexToShape;
257     std::string                myMainEntry;
258     SVTK_ViewWindow*           myViewWindow;
259     vtkProperty*               myProperty;
260     std::set<int>              myBuiltSubs;
261
262     // -----------------------------------------------------------------------
263     typedef SMDS_SetIterator< GEOM_Actor*, TActorVec::const_iterator> TActorIterator;
264     TActorIterator actorIterator() {
265       return TActorIterator( myActors.begin(), myActors.end() );
266     }
267     TActorIterator shownIterator() {
268       return TActorIterator( myShownActors.begin(), myShownActors.end() );
269     }
270     // -----------------------------------------------------------------------
271     GEOM_Actor* getActor(const TopoDS_Shape& shape)
272     {
273       int index = myIndexToShape.FindIndex( shape ) - 1;
274       if ( index < 0 || index >= myActors.size() )
275         return 0;
276       GEOM_Actor* & actor = myActors[ index ];
277       if ( !actor ) {
278         actor = GEOM_Actor::New();
279         if ( actor ) {
280           actor->SetShape(shape,0,0);
281           actor->SetProperty(myProperty);
282           actor->SetShadingProperty(myProperty);
283           actor->SetWireframeProperty(myProperty);
284           actor->SetPreviewProperty(myProperty);
285           actor->PickableOff();
286           //         if ( shape.ShapeType() == TopAbs_EDGE )
287           //           actor->SubShapeOn();
288           myViewWindow->AddActor( actor );
289         }
290       }
291       return actor;
292     }
293     // -----------------------------------------------------------------------
294     void checkTriangulation(const TopoDS_Shape& shape)
295     {
296       TopLoc_Location aLoc;
297       Standard_Boolean alreadymesh = Standard_True;
298       TopExp_Explorer ex(shape, TopAbs_FACE);
299       if ( ex.More() )
300         for ( ; ex.More(); ex.Next()) {
301           const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
302           Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
303           if(aPoly.IsNull()) { alreadymesh = Standard_False; break; }
304         }
305       else
306         for (ex.Init(shape, TopAbs_EDGE); ex.More(); ex.Next()) {
307           const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
308           Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, aLoc);
309           if(aPoly.IsNull()) { alreadymesh = Standard_False; break; }
310         }
311       if (alreadymesh) return;
312       // Compute default deflection
313       Bnd_Box B;
314       BRepBndLib::Add(shape, B);
315       Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
316       B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
317       double deflection = Max( aXmax-aXmin, Max ( aYmax-aYmin, aZmax-aZmin)) * 0.01 *4;
318       BRepMesh_IncrementalMesh MESH(shape,deflection);
319     }
320     // -----------------------------------------------------------------------
321     bool hasViewWindow() const
322     {
323       if ( !myViewWindow ) return false;
324
325       if ( SalomeApp_Application* anApp = SMESHGUI::GetSMESHGUI()->getApp() )
326         return FindVtkViewWindow( anApp->getViewManager(SVTK_Viewer::Type(), false ),
327                                   myViewWindow );
328       return false;
329     }
330   };
331
332   // =========================================================================================
333   /*!
334    * \brief Return text describing an error
335    */
336 #define CASE2TEXT(enum) case SMESH::enum: text = QObject::tr( #enum ); break;
337   QString errorText(int errCode, const char* comment)
338   {
339     QString text;
340     switch ( errCode ) {
341       CASE2TEXT( COMPERR_OK               );
342       CASE2TEXT( COMPERR_BAD_INPUT_MESH   );
343       CASE2TEXT( COMPERR_STD_EXCEPTION    );
344       CASE2TEXT( COMPERR_OCC_EXCEPTION    );
345     case SMESH::COMPERR_SLM_EXCEPTION: break; // avoid double "Salome exception"
346       CASE2TEXT( COMPERR_EXCEPTION        );
347       CASE2TEXT( COMPERR_MEMORY_PB        );
348       CASE2TEXT( COMPERR_BAD_SHAPE        );
349       CASE2TEXT( COMPERR_CANCELED         );
350       CASE2TEXT( COMPERR_NO_MESH_ON_SHAPE );
351       CASE2TEXT( COMPERR_BAD_PARMETERS    );
352     case SMESH::COMPERR_ALGO_FAILED:
353       if ( strlen(comment) == 0 )
354         text = QObject::tr("COMPERR_ALGO_FAILED");
355       break;
356     case SMESH::COMPERR_WARNING:
357       text = QObject::tr( (comment && strlen(comment)) ? "COMPERR_WARNING" : "COMPERR_UNKNOWN");
358       break;
359     default:
360       text = QString("#%1").arg( -errCode );
361     }
362     if ( text.length() > 0 ) text += ". ";
363     return text + comment;
364   }
365   // -----------------------------------------------------------------------
366   /*!
367    * \brief Return SO of a sub-shape
368    */
369   _PTR(SObject) getSubShapeSO( int subShapeID, GEOM::GEOM_Object_var aMainShape)
370   {
371     _PTR(SObject) so = SMESH::FindSObject(aMainShape);
372     if ( subShapeID == 1 || !so )
373       return so;
374     _PTR(ChildIterator) it;
375     if (_PTR(Study) study = SMESH::GetActiveStudyDocument())
376       it =  study->NewChildIterator(so);
377     _PTR(SObject) subSO;
378     if ( it ) {
379       for ( it->InitEx(true); !subSO && it->More(); it->Next() ) {
380         GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>( it->Value() );
381         if ( !geom->_is_nil() ) {
382           GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
383           if ( list->length() == 1 && list[0] == subShapeID )
384           {
385             GEOM::GEOM_Object_var mainGO = geom->GetMainShape();
386             if ( aMainShape->IsSame( mainGO ))
387               subSO = it->Value();
388           }
389         }
390       }
391     }
392     return subSO;
393   }
394   // -----------------------------------------------------------------------
395   /*!
396    * \brief Return sub-shape by ID. WARNING: UnRegister() must be called on a result
397    */
398   GEOM::GEOM_Object_ptr getSubShape( int subShapeID, GEOM::GEOM_Object_var aMainShape)
399   {
400     GEOM::GEOM_Object_var aSubShape;
401     if ( subShapeID == 1 ) {
402       aSubShape = aMainShape;
403       aSubShape->Register();
404     }
405     else if ( _PTR(SObject) so = getSubShapeSO( subShapeID, aMainShape )) {
406       aSubShape = SMESH::SObjectToInterface<GEOM::GEOM_Object>( so );
407       aSubShape->Register();
408     }
409     else {
410       aSubShape = SMESH::GetSubShape( aMainShape, subShapeID );
411       // future call of UnRegister() will delete a servant of this new object
412     }
413     return aSubShape._retn();
414   }
415   // -----------------------------------------------------------------------
416   /*!
417    * \brief Return shape type name
418    */
419 #define CASE2NAME(enum) case GEOM::enum: name = QObject::tr( "GEOM_" #enum ); break;
420   QString shapeTypeName(GEOM::GEOM_Object_var aShape, const char* dflt = "" )
421   {
422     QString name = dflt;
423     if ( !aShape->_is_nil() ) {
424       switch ( aShape->GetShapeType() ) {
425       CASE2NAME( VERTEX    );
426       CASE2NAME( EDGE      );
427       CASE2NAME( WIRE      );
428       CASE2NAME( FACE      );
429       CASE2NAME( SHELL     );
430       CASE2NAME( SOLID     );
431       CASE2NAME( COMPSOLID );
432       CASE2NAME( COMPOUND  );
433       default:;
434       }
435     }
436     return name;
437   }
438   // -----------------------------------------------------------------------
439   /*!
440    * \brief Return text describing a sub-shape
441    */
442   QString shapeText(int subShapeID, GEOM::GEOM_Object_var aMainShape )
443   {
444     QString text;
445     if ( _PTR(SObject) aSO = getSubShapeSO( subShapeID, aMainShape )) {
446       text  = aSO->GetName().c_str();
447       text += QString(" (%1)").arg( aSO->GetID().c_str() );
448     }
449     else {
450       text = QString("#%1").arg( subShapeID );
451       GEOM::GEOM_Object_wrap shape = getSubShape( subShapeID, aMainShape );
452       QString typeName = shapeTypeName( shape );
453       if ( typeName.length() )
454         text += QString(" (%1)").arg(typeName);
455     }
456     return text;
457   }
458   // -----------------------------------------------------------------------
459   /*!
460    * \brief Return a list of selected rows
461    */
462   int getSelectedRows(QTableWidget* table, QList<int>& rows)
463   {
464     rows.clear();
465     QList<QTableWidgetSelectionRange> selRanges = table->selectedRanges();
466     QTableWidgetSelectionRange range;
467     foreach( range, selRanges )
468     {
469       for ( int row = range.topRow(); row <= range.bottomRow(); ++row )
470         if ( !rows.count( row ))
471              rows.append( row );
472     }
473     if ( rows.isEmpty() && table->currentRow() > -1 )
474       if ( !rows.count( table->currentRow() ))
475         rows.append( table->currentRow() );
476
477     return rows.count();
478   }
479
480 } // namespace SMESH
481
482
483 // =========================================================================================
484 /*!
485  * \brief Dialog to compute a mesh and show computation errors
486  */
487 //=======================================================================
488
489 SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg( QWidget* parent, bool ForEval )
490  : SMESHGUI_Dialog( parent, false, true, Close/* | Help*/ )
491 {
492   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
493   aDlgLay->setMargin( 0 );
494   aDlgLay->setSpacing( SPACING );
495
496   QFrame* aMainFrame = createMainFrame(mainFrame(),ForEval);
497
498   aDlgLay->addWidget(aMainFrame);
499
500   aDlgLay->setStretchFactor(aMainFrame, 1);
501 }
502
503 // =========================================================================================
504 /*!
505  * \brief Destructor
506  */
507 //=======================================================================
508
509 SMESHGUI_ComputeDlg::~SMESHGUI_ComputeDlg()
510 {
511 }
512
513 //=======================================================================
514 // function : createMainFrame()
515 // purpose  : Create frame containing dialog's fields
516 //=======================================================================
517
518 QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval)
519 {
520   QFrame* aFrame = new QFrame(theParent);
521
522   SUIT_ResourceMgr* rm = resourceMgr();
523   QPixmap iconCompute (rm->loadPixmap("SMESH", tr("ICON_COMPUTE")));
524
525   // constructor
526
527   QGroupBox* aPixGrp;
528   if(ForEval) {
529     aPixGrp = new QGroupBox(tr("EVAL_DLG"), aFrame);
530   }
531   else {
532     aPixGrp = new QGroupBox(tr("CONSTRUCTOR"), aFrame);
533   }
534   QButtonGroup* aBtnGrp = new QButtonGroup(this);
535   QHBoxLayout* aPixGrpLayout = new QHBoxLayout(aPixGrp);
536   aPixGrpLayout->setMargin(MARGIN); aPixGrpLayout->setSpacing(SPACING);
537
538   QRadioButton* aRBut = new QRadioButton(aPixGrp);
539   aRBut->setIcon(iconCompute);
540   aRBut->setChecked(true);
541   aPixGrpLayout->addWidget(aRBut);
542   aBtnGrp->addButton(aRBut, 0);
543
544   // Mesh name
545
546   QGroupBox* nameBox = new QGroupBox(tr("SMESH_MESHINFO_NAME"), aFrame );
547   QHBoxLayout* nameBoxLayout = new QHBoxLayout(nameBox);
548   nameBoxLayout->setMargin(MARGIN); nameBoxLayout->setSpacing(SPACING);
549   myMeshName = new QLabel(nameBox);
550   nameBoxLayout->addWidget(myMeshName);
551
552   // Mesh Info
553
554   myBriefInfo = new SMESHGUI_MeshInfosBox(false, aFrame);
555   myFullInfo  = new SMESHGUI_MeshInfosBox(true,  aFrame);
556
557   // Computation errors
558
559   myCompErrorGroup = new QGroupBox(tr("ERRORS"), aFrame);
560   myWarningLabel = new QLabel(QString("<b>%1</b>").arg(tr("COMPUTE_WARNING")), myCompErrorGroup);
561   myTable        = new QTableWidget( 1, NB_COLUMNS, myCompErrorGroup);
562   myShowBtn      = new QPushButton(tr("SHOW_SHAPE"), myCompErrorGroup);
563   myPublishBtn   = new QPushButton(tr("PUBLISH_SHAPE"), myCompErrorGroup);
564   myBadMeshBtn   = new QPushButton(tr("SHOW_BAD_MESH"), myCompErrorGroup);
565   myBadMeshToGroupBtn = new QPushButton(tr("GROUP_OF_BAD_MESH"), myCompErrorGroup);
566
567   //myTable->setReadOnly( true ); // VSR: check
568   myTable->setEditTriggers( QAbstractItemView::NoEditTriggers );
569   myTable->hideColumn( COL_PUBLISHED );
570   myTable->hideColumn( COL_SHAPEID );
571   myTable->hideColumn( COL_BAD_MESH );
572   myTable->horizontalHeader()->setResizeMode( COL_ERROR, QHeaderView::Interactive );
573   myTable->setWordWrap( true );
574   myTable->horizontalHeader()->setStretchLastSection( true );
575   myTable->setMinimumWidth( 500 );
576
577   QStringList headers;
578   headers << tr( "COL_ALGO_HEADER" );
579   headers << tr( "COL_SHAPE_HEADER" );
580   headers << tr( "COL_ERROR_HEADER" );
581   headers << tr( "COL_SHAPEID_HEADER" );
582   headers << tr( "COL_PUBLISHED_HEADER" );
583
584   myTable->setHorizontalHeaderLabels( headers );
585
586   // layouting
587   QGridLayout* grpLayout = new QGridLayout(myCompErrorGroup);
588   grpLayout->setSpacing(SPACING);
589   grpLayout->setMargin(MARGIN);
590   grpLayout->addWidget( myWarningLabel,      0, 0, 1, 4 );
591   grpLayout->addWidget( myTable,             1, 0, 1, 4 );
592   grpLayout->addWidget( myShowBtn,           2, 0 );
593   grpLayout->addWidget( myPublishBtn,        2, 1 );
594   grpLayout->addWidget( myBadMeshBtn,        2, 2 );
595   grpLayout->addWidget( myBadMeshToGroupBtn, 2, 3 );
596   grpLayout->setColumnStretch( 3, 1 );
597
598   // Hypothesis definition errors
599
600   myHypErrorGroup = new QGroupBox(tr("SMESH_WRN_MISSING_PARAMETERS"), aFrame);
601   QHBoxLayout* myHypErrorGroupLayout = new QHBoxLayout(myHypErrorGroup);
602   myHypErrorGroupLayout->setMargin(MARGIN);
603   myHypErrorGroupLayout->setSpacing(SPACING);
604   myHypErrorLabel = new QLabel(myHypErrorGroup);
605   myHypErrorGroupLayout->addWidget(myHypErrorLabel);
606
607   // Memory Lack Label
608
609   myMemoryLackGroup = new QGroupBox(tr("ERRORS"), aFrame);
610   QVBoxLayout* myMemoryLackGroupLayout = new QVBoxLayout(myMemoryLackGroup);
611   myMemoryLackGroupLayout->setMargin(MARGIN);
612   myMemoryLackGroupLayout->setSpacing(SPACING);
613   QLabel* memLackLabel = new QLabel(tr("MEMORY_LACK"), myMemoryLackGroup);
614   QFont bold = memLackLabel->font(); bold.setBold(true);
615   memLackLabel->setFont( bold );
616   memLackLabel->setMinimumWidth(300);
617   myMemoryLackGroupLayout->addWidget(memLackLabel);
618
619   // add all widgets to aFrame
620   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
621   aLay->setMargin( MARGIN );
622   aLay->setSpacing( SPACING );
623   aLay->addWidget( aPixGrp );
624   aLay->addWidget( nameBox );
625   aLay->addWidget( myBriefInfo );
626   aLay->addWidget( myFullInfo );
627   aLay->addWidget( myHypErrorGroup );
628   aLay->addWidget( myCompErrorGroup );
629   aLay->addWidget( myMemoryLackGroup );
630   aLay->setStretchFactor( myCompErrorGroup, 1 );
631
632   ((QPushButton*) button( OK ))->setDefault( true );
633
634   return aFrame;
635 }
636
637 //================================================================================
638 /*!
639  * \brief Constructor
640 */
641 //================================================================================
642
643 SMESHGUI_BaseComputeOp::SMESHGUI_BaseComputeOp()
644   : SMESHGUI_Operation(), myCompDlg( 0 )
645 {
646   myTShapeDisplayer = new SMESH::TShapeDisplayer();
647   myBadMeshDisplayer = 0;
648
649   //myHelpFileName = "/files/about_meshes.htm"; // V3
650   myHelpFileName = "about_meshes_page.html"; // V4
651 }
652
653 SMESH::SMESH_Mesh_ptr SMESHGUI_BaseComputeOp::getMesh()
654 {
655   LightApp_SelectionMgr* Sel = selectionMgr();
656   SALOME_ListIO selected; Sel->selectedObjects( selected );
657   Handle(SALOME_InteractiveObject) anIO = selected.First();
658   SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(anIO);
659   return myMesh->_is_nil() ? aMesh._retn() : SMESH::SMESH_Mesh::_duplicate( myMesh );
660 }
661
662 //================================================================================
663 /*!
664  * \brief Start operation
665  * \purpose Init dialog fields, connect signals and slots, show dialog
666  */
667 //================================================================================
668
669 void SMESHGUI_BaseComputeOp::startOperation()
670 {
671   // create compute dialog if not created before
672   computeDlg();
673
674   myMesh      = SMESH::SMESH_Mesh::_nil();
675   myMainShape = GEOM::GEOM_Object::_nil();
676
677   // check selection
678   LightApp_SelectionMgr *Sel = selectionMgr();
679   SALOME_ListIO selected; Sel->selectedObjects( selected );
680
681   int nbSel = selected.Extent();
682   if (nbSel != 1) {
683     SUIT_MessageBox::warning(desktop(),
684                              tr("SMESH_WRN_WARNING"),
685                              tr("SMESH_WRN_NO_AVAILABLE_DATA"));
686     onCancel();
687     return;
688   }
689
690   myIObject = selected.First();
691   myMesh = SMESH::GetMeshByIO(myIObject);
692   if (myMesh->_is_nil()) {
693     SUIT_MessageBox::warning(desktop(),
694                              tr("SMESH_WRN_WARNING"),
695                              tr("SMESH_WRN_NO_AVAILABLE_DATA"));
696     onCancel();
697     return;
698   }
699   myMainShape = myMesh->GetShapeToMesh();
700
701   SMESHGUI_Operation::startOperation();
702 }
703
704 //================================================================================
705 //================================================================================
706
707 SMESHGUI_ComputeDlg_QThread::SMESHGUI_ComputeDlg_QThread(SMESH::SMESH_Gen_var gen,
708                                                          SMESH::SMESH_Mesh_var mesh,
709                                                          GEOM::GEOM_Object_var mainShape)
710 {
711   myResult = false;
712   myGen = gen;
713   myMesh = mesh;
714   myMainShape = mainShape;
715 }
716
717 void SMESHGUI_ComputeDlg_QThread::run()
718 {
719   myResult = myGen->Compute(myMesh, myMainShape);
720 }
721
722 bool SMESHGUI_ComputeDlg_QThread::result()
723 {
724   return myResult;
725 }
726
727 void SMESHGUI_ComputeDlg_QThread::cancel()
728 {
729   myGen->CancelCompute(myMesh, myMainShape);
730 }
731
732 //================================================================================
733 //================================================================================
734
735 SMESHGUI_ComputeDlg_QThreadQDialog::SMESHGUI_ComputeDlg_QThreadQDialog(QWidget             * parent,
736                                                                        SMESH::SMESH_Gen_var  gen,
737                                                                        SMESH::SMESH_Mesh_var mesh,
738                                                                        GEOM::GEOM_Object_var mainShape)
739   : QDialog(parent,
740             Qt::WindowSystemMenuHint |
741             Qt::WindowCloseButtonHint |
742             Qt::Dialog |
743             Qt::WindowMaximizeButtonHint),
744     qthread(gen, mesh, mainShape)
745 {
746   // --
747   setWindowTitle(tr("TITLE"));
748   setMinimumWidth( 200 );
749
750   cancelButton = new QPushButton(tr("CANCEL"));
751   cancelButton->setDefault(true);
752   cancelButton->setCheckable(true);
753
754   QLabel * nbNodesName = new QLabel(tr("SMESH_MESHINFO_NODES"), this );
755   QLabel * nbElemsName = new QLabel(tr("SMESH_MESHINFO_ELEMENTS"), this );
756   nbNodesLabel = new QLabel("0", this );
757   nbElemsLabel = new QLabel("0", this );
758 #ifndef WIN32
759   QLabel * freeRAMName = new QLabel(tr("SMESH_FREERAM"), this );
760   freeRAMLabel = new QLabel("", this );
761 #endif
762   progressBar  = new QProgressBar(this);
763   progressBar->setMinimum( 0 );
764   progressBar->setMaximum( 1000 );
765
766   QGridLayout* layout = new QGridLayout(this);
767   layout->setMargin( MARGIN );
768   layout->setSpacing( SPACING );
769   int row = 0;
770   layout->addWidget(nbNodesName,  row,   0);
771   layout->addWidget(nbNodesLabel, row++, 1);
772   layout->addWidget(nbElemsName,  row,   0);
773   layout->addWidget(nbElemsLabel, row++, 1);
774 #ifndef WIN32
775   layout->addWidget(freeRAMName,  row,   0);
776   layout->addWidget(freeRAMLabel, row++, 1);
777 #endif
778   layout->addWidget(progressBar,  row++, 0, 1, 2);
779   layout->addWidget(cancelButton, row++, 0, 1, 2);
780   adjustSize();
781   update();
782
783   connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancel()));
784   // --
785   startTimer(300); // millisecs
786   qthread.start();
787 }
788
789 bool SMESHGUI_ComputeDlg_QThreadQDialog::result()
790 {
791   return qthread.result();
792 }
793
794 void SMESHGUI_ComputeDlg_QThreadQDialog::onCancel()
795 {
796   qthread.cancel();
797   cancelButton->setText( tr("CANCELING"));
798   cancelButton->setEnabled(false);
799 }
800
801 void SMESHGUI_ComputeDlg_QThreadQDialog::timerEvent(QTimerEvent *event)
802 {
803   if ( !cancelButton->isChecked() ) // not yet cancelled
804     progressBar->setValue( progressBar->maximum() * qthread.getMesh()->GetComputeProgress() );
805
806   if(qthread.isFinished())
807   {
808     close();
809   }
810   else
811   {
812     nbNodesLabel->setText( QString("%1").arg( qthread.getMesh()->NbNodes() ));
813     nbElemsLabel->setText( QString("%1").arg( qthread.getMesh()->NbElements() ));
814 #ifndef WIN32
815     struct sysinfo si;
816     const int err = sysinfo( &si );
817     if ( err )
818       freeRAMLabel->setText("");
819     else
820       freeRAMLabel->setText( tr("SMESH_GIGABYTE").arg
821                              ( si.freeram * si.mem_unit /1024./1024./1024., 0, 'f', 2 ));
822 #endif
823   }
824   event->accept();
825 }
826
827 void SMESHGUI_ComputeDlg_QThreadQDialog::closeEvent(QCloseEvent *event)
828 {
829   if(qthread.isRunning())
830   {
831       event->ignore();
832       return;
833     }
834   event->accept();
835 }
836
837 //================================================================================
838 /*!
839  * \brief computeMesh()
840 */
841 //================================================================================
842
843 void SMESHGUI_BaseComputeOp::computeMesh()
844 {
845   // COMPUTE MESH
846
847   SMESH::MemoryReserve aMemoryReserve;
848
849   SMESH::compute_error_array_var aCompErrors;
850   QString                        aHypErrors;
851
852   bool computeFailed = true, memoryLack = false;
853
854   _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh);
855   if ( !aMeshSObj ) // IPAL 21340
856     return;
857   bool hasShape = myMesh->HasShapeToMesh();
858   bool shapeOK = myMainShape->_is_nil() ? !hasShape : hasShape;
859   if ( shapeOK )
860   {
861     myCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() );
862     SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
863     SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape);
864     if ( errors->length() > 0 ) {
865       aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() );
866     }
867     if ( myMesh->HasModificationsToDiscard() && // issue 0020693
868          SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ),
869                                     tr( "FULL_RECOMPUTE_QUESTION" ),
870                                     tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 1, 0 ) == 0 )
871       myMesh->Clear();
872     SUIT_OverrideCursor aWaitCursor;
873     try {
874 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
875       OCC_CATCH_SIGNALS;
876 #endif
877       SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myMainShape);
878       qthreaddialog.exec();
879       computeFailed = !qthreaddialog.result();
880     }
881     catch(const SALOME::SALOME_Exception & S_ex) {
882       memoryLack = true;
883     }
884     try {
885 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
886       OCC_CATCH_SIGNALS;
887 #endif
888       aCompErrors = gen->GetComputeErrors( myMesh, myMainShape );
889       // check if there are memory problems
890       for ( int i = 0; (i < aCompErrors->length()) && !memoryLack; ++i )
891         memoryLack = ( aCompErrors[ i ].code == SMESH::COMPERR_MEMORY_PB );
892     }
893     catch(const SALOME::SALOME_Exception & S_ex) {
894       memoryLack = true;
895     }
896
897     if ( !memoryLack && !SMDS_Mesh::CheckMemory(true) ) { // has memory to show dialog boxes?
898       memoryLack = true;
899     }
900
901     // NPAL16631: if ( !memoryLack )
902     {
903       SMESH::ModifiedMesh( aMeshSObj,
904                            !computeFailed && aHypErrors.isEmpty(),
905                            myMesh->NbNodes() == 0);
906       update( UF_ObjBrowser | UF_Model );
907
908       // SHOW MESH
909       // NPAL16631: if ( getSMESHGUI()->automaticUpdate() )
910       SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
911       bool limitExceeded;
912       long limitSize = resMgr->integerValue( "SMESH", "update_limit", 500000 );
913       int entities = SMESH_Actor::eAllEntity;
914       int hidden = 0;
915       long nbElements = 0;
916       if ( !memoryLack )
917       {
918         // List of objects that will be updated automatically
919         QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > > aListToUpdate;
920         SMESH::SMESH_IDSource_var aMeshObj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( aMeshSObj );
921         // put Mesh into list
922         aListToUpdate.append( QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) >(aMeshObj, aMeshSObj) );
923         SMESH::submesh_array_var aSubMeshes = myMesh->GetSubMeshes();
924         // put SubMeshes into list
925         for ( int i = 0; i < aSubMeshes->length(); i++ ) {
926           SMESH::SMESH_subMesh_var sm = aSubMeshes[i];
927           if ( CORBA::is_nil( sm ) ) continue;
928           _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm );
929           if ( !smSObj ) continue;
930           SMESH::SMESH_IDSource_var aSubMeshObj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( smSObj );
931           aListToUpdate.append( QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) >(aSubMeshObj, smSObj) );
932         }
933         // put Groups into list
934         SMESH::ListOfGroups_var  aGroups = myMesh->GetGroups();
935         for ( size_t i = 0; i < aGroups->length(); ++i ) {
936           SMESH::SMESH_GroupBase_var aGrp = aGroups[i];
937           if ( CORBA::is_nil( aGrp ) ) continue;
938           SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
939           SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
940           SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
941           if ( !aStdGroup->_is_nil() ) continue; // don't update the standalone groups
942           _PTR(SObject) aGroupSO = SMESH::FindSObject( aGrp );
943           if ( !aGroupSO ) continue;
944           SMESH::SMESH_IDSource_var aGroupObj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( aGroupSO );
945           aListToUpdate.append( QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) >(aGroupObj, aGroupSO) );
946         }
947
948         // update mesh, sub-mesh and groups, if it's possible
949         QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > >::iterator anIter;
950         for( anIter = aListToUpdate.begin(); anIter != aListToUpdate.end(); anIter++ ) {
951           SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second ));
952           if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) )
953           {
954             try {
955 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
956               OCC_CATCH_SIGNALS;
957 #endif
958               bool toDisplay = false;
959
960               if ( !aMesh->_is_nil() ) { // display a mesh only
961                 toDisplay = true;
962                 SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh );
963                 if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true );    
964                 if ( anActor ) // actor is not created for an empty mesh
965                 {
966                   anActor->SetEntityMode( entities );
967                   SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
968                 }
969               }
970               Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
971                 ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() );
972               SMESH::Update(anIO, toDisplay);
973
974               if ( limitExceeded && !aMesh->_is_nil() )
975               {
976                 QStringList hiddenMsg;
977                 if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" );
978                 if ( hidden & SMESH_Actor::eEdges )      hiddenMsg << tr( "SMESH_EDGES" );
979                 if ( hidden & SMESH_Actor::eFaces )      hiddenMsg << tr( "SMESH_FACES" );
980                 if ( hidden & SMESH_Actor::eVolumes )    hiddenMsg << tr( "SMESH_VOLUMES" );
981                 if ( hidden & SMESH_Actor::eBallElem )   hiddenMsg << tr( "SMESH_BALLS" );
982                 SUIT_MessageBox::warning( desktop(),
983                                           tr( "SMESH_WRN_WARNING" ),
984                                           tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) );
985               }
986             }
987             catch (...) {
988 #ifdef _DEBUG_
989               MESSAGE ( "Exception thrown during mesh visualization" );
990 #endif
991               if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
992                 SMESH::OnVisuException();
993               }
994               else {
995                 memoryLack = true;
996               }
997             }
998           }
999           else if ( limitExceeded && !aMesh->_is_nil() )
1000           {
1001             SUIT_MessageBox::warning( desktop(),
1002                                       tr( "SMESH_WRN_WARNING" ),
1003                                       tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) );
1004           }
1005         }
1006       }
1007       LightApp_SelectionMgr *Sel = selectionMgr();
1008       if ( Sel )
1009       {
1010         SALOME_ListIO selected;
1011         selected.Append( myIObject );
1012         Sel->setSelectedObjects( selected );
1013       }
1014     }
1015   }
1016
1017   if ( memoryLack )
1018     aMemoryReserve.release();
1019
1020   myCompDlg->setWindowTitle(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED"));
1021
1022   // SHOW ERRORS
1023   
1024   bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 );
1025   bool noHypoError = ( aHypErrors.isEmpty() );
1026
1027   SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
1028   int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" );
1029
1030   bool isShowResultDlg = true;
1031   switch( aNotifyMode ) {
1032   case 0: // show the mesh computation result dialog NEVER
1033     isShowResultDlg = false;
1034     commit();
1035     break;
1036   case 1: // show the mesh computation result dialog if there are some errors
1037     if ( memoryLack || !noCompError || !noHypoError )
1038       isShowResultDlg = true;
1039     else
1040     {
1041       isShowResultDlg = false;
1042       commit();
1043     }
1044     break;
1045   default: // show the result dialog after each mesh computation
1046     isShowResultDlg = true;
1047   }
1048
1049   // SHOW RESULTS
1050   if ( isShowResultDlg )
1051     showComputeResult( memoryLack, noCompError,aCompErrors, noHypoError, aHypErrors );
1052 }
1053
1054 void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack,
1055                                                 const bool theNoCompError,
1056                                                 SMESH::compute_error_array_var& theCompErrors,
1057                                                 const bool theNoHypoError,
1058                                                 const QString& theHypErrors )
1059 {
1060   bool hasShape = myMesh->HasShapeToMesh();
1061   SMESHGUI_ComputeDlg* aCompDlg = computeDlg();
1062   aCompDlg->myMemoryLackGroup->hide();
1063
1064   if ( theMemoryLack )
1065   {
1066     aCompDlg->myMemoryLackGroup->show();
1067     aCompDlg->myFullInfo->hide();
1068     aCompDlg->myBriefInfo->hide();
1069     aCompDlg->myHypErrorGroup->hide();
1070     aCompDlg->myCompErrorGroup->hide();
1071   }
1072   else if ( theNoCompError && theNoHypoError )
1073   {
1074     SMESH::long_array_var aRes = myMesh->GetMeshInfo();
1075     aCompDlg->myFullInfo->SetMeshInfo( aRes );
1076     aCompDlg->myFullInfo->show();
1077     aCompDlg->myBriefInfo->hide();
1078     aCompDlg->myHypErrorGroup->hide();
1079     aCompDlg->myCompErrorGroup->hide();
1080   }
1081   else
1082   {
1083     bool onlyWarnings = !theNoCompError; // == valid mesh computed but there are errors reported
1084     for ( int i = 0; i < theCompErrors->length() && onlyWarnings; ++i )
1085       onlyWarnings = ( theCompErrors[ i ].code == SMESH::COMPERR_WARNING ||
1086                        theCompErrors[ i ].code == SMESH::COMPERR_NO_MESH_ON_SHAPE );
1087
1088     // full or brief mesh info
1089     SMESH::long_array_var aRes = myMesh->GetMeshInfo();
1090     if ( onlyWarnings ) {
1091       aCompDlg->myFullInfo->SetMeshInfo( aRes );
1092       aCompDlg->myFullInfo->show();
1093       aCompDlg->myBriefInfo->hide();
1094     } else {
1095       aCompDlg->myBriefInfo->SetMeshInfo( aRes );
1096       aCompDlg->myBriefInfo->show();
1097       aCompDlg->myFullInfo->hide();
1098     }
1099
1100     // pbs of hypo dfinitions
1101     if ( theNoHypoError ) {
1102       aCompDlg->myHypErrorGroup->hide();
1103     } else {
1104       aCompDlg->myHypErrorGroup->show();
1105       aCompDlg->myHypErrorLabel->setText( theHypErrors );
1106     }
1107
1108     // table of errors
1109     if ( theNoCompError )
1110     {
1111       aCompDlg->myCompErrorGroup->hide();
1112     }
1113     else
1114     {
1115       aCompDlg->myCompErrorGroup->show();
1116
1117       if ( onlyWarnings )
1118         aCompDlg->myWarningLabel->show();
1119       else
1120         aCompDlg->myWarningLabel->hide();
1121
1122       if ( !hasShape ) {
1123         aCompDlg->myPublishBtn->hide();
1124         aCompDlg->myShowBtn->hide();
1125       }
1126       else {
1127         aCompDlg->myPublishBtn->show();
1128         aCompDlg->myShowBtn->show();
1129       }
1130
1131       // fill table of errors
1132       QTableWidget* tbl = aCompDlg->myTable;
1133       tbl->setRowCount( theCompErrors->length() );
1134       if ( !hasShape ) tbl->hideColumn( COL_SHAPE );
1135       else             tbl->showColumn( COL_SHAPE );
1136       tbl->setColumnWidth( COL_ERROR, 200 );
1137
1138       bool hasBadMesh = false;
1139       for ( int row = 0; row < theCompErrors->length(); ++row )
1140       {
1141         SMESH::ComputeError & err = theCompErrors[ row ];
1142
1143         QString text = err.algoName.in();
1144         if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) );
1145         else tbl->item( row, COL_ALGO )->setText( text );
1146
1147         text = SMESH::errorText( err.code, err.comment.in() );
1148         if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) );
1149         else tbl->item( row, COL_ERROR )->setText( text );
1150
1151         text = QString("%1").arg( err.subShapeID );
1152         if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) );
1153         else tbl->item( row, COL_SHAPEID )->setText( text );
1154
1155         text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString("");
1156         if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) );
1157         else tbl->item( row, COL_SHAPE )->setText( text );
1158
1159         text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : "";
1160         if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) );
1161         else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled
1162
1163         text = err.hasBadMesh ? "hasBadMesh" : "";
1164         if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) );
1165         else tbl->item( row, COL_BAD_MESH )->setText( text );
1166         if ( err.hasBadMesh ) hasBadMesh = true;
1167
1168         //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ???
1169         tbl->resizeRowToContents( row );
1170       }
1171       tbl->resizeColumnToContents( COL_ALGO );
1172       tbl->resizeColumnToContents( COL_SHAPE );
1173       tbl->setWordWrap( true );
1174
1175       if ( hasBadMesh ) {
1176         aCompDlg->myBadMeshBtn->show();
1177         aCompDlg->myBadMeshToGroupBtn->show();
1178       }
1179       else {
1180         aCompDlg->myBadMeshBtn->hide();
1181         aCompDlg->myBadMeshToGroupBtn->hide();
1182       }
1183       tbl->setCurrentCell(0,0);
1184       currentCellChanged(); // to update buttons
1185     }
1186   }
1187   // show dialog and wait, becase Compute can be invoked from Preview operation
1188   //aCompDlg->exec(); // this way it becomes modal - impossible to rotate model in the Viewer
1189   aCompDlg->show();
1190 }
1191
1192 //================================================================================
1193 /*!
1194  * \brief Stops operation
1195  */
1196 //================================================================================
1197
1198 void SMESHGUI_BaseComputeOp::stopOperation()
1199 {
1200   SMESHGUI_Operation::stopOperation();
1201   if ( myTShapeDisplayer )
1202     myTShapeDisplayer->SetVisibility( false );
1203   if ( myBadMeshDisplayer ) {
1204     myBadMeshDisplayer->SetVisibility( false );
1205     // delete it in order not to have problems at its destruction when the viewer
1206     // where it worked is dead due to e.g. study closing
1207     delete myBadMeshDisplayer;
1208     myBadMeshDisplayer = 0;
1209   }
1210   myIObject.Nullify();
1211 }
1212
1213 //================================================================================
1214 /*!
1215  * \brief publish selected sub-shape
1216  */
1217 //================================================================================
1218
1219 void SMESHGUI_BaseComputeOp::onPublishShape()
1220 {
1221   GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
1222   SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
1223
1224   QStringList entryList;
1225   QList<int> rows;
1226   SMESH::getSelectedRows( table(), rows );
1227   int row;
1228   foreach ( row, rows )
1229   {
1230     int curSub = table()->item(row, COL_SHAPEID)->text().toInt();
1231     GEOM::GEOM_Object_wrap shape = SMESH::getSubShape( curSub, myMainShape );
1232     if ( !shape->_is_nil() && ! SMESH::getSubShapeSO( curSub, myMainShape ))
1233     {
1234       if ( !SMESH::getSubShapeSO( 1, myMainShape )) // the main shape not published
1235       {
1236         QString name = GEOMBase::GetDefaultName( SMESH::shapeTypeName( myMainShape, "MAIN_SHAPE" ));
1237         SALOMEDS::SObject_wrap so =
1238           geomGen->AddInStudy( study, myMainShape, name.toLatin1().data(), GEOM::GEOM_Object::_nil());
1239         // look for myMainShape in the table
1240         for ( int r = 0, nr = table()->rowCount(); r < nr; ++r ) {
1241           if ( table()->item( r, COL_SHAPEID )->text() == "1" ) {
1242             if ( so->_is_nil() ) {
1243               CORBA::String_var name  = so->GetName();
1244               CORBA::String_var entry = so->GetID();
1245               QString       shapeText = QString("%1 (%2)").arg( name.in() ).arg( entry.in() );
1246               table()->item( r, COL_SHAPE     )->setText( shapeText );
1247               table()->item( r, COL_PUBLISHED )->setText( entry.in() );
1248             }
1249             break;
1250           }
1251         }
1252         if ( curSub == 1 ) continue;
1253       }
1254       QString name = GEOMBase::GetDefaultName( SMESH::shapeTypeName( shape, "ERROR_SHAPE" ));
1255       SALOMEDS::SObject_wrap so = geomGen->AddInStudy( study, shape, name.toLatin1().data(), myMainShape);
1256       if ( !so->_is_nil() ) {
1257         CORBA::String_var name  = so->GetName();
1258         CORBA::String_var entry = so->GetID();
1259         QString       shapeText = QString("%1 (%2)").arg( name.in() ).arg( entry.in() );
1260         table()->item( row, COL_SHAPE     )->setText( shapeText );
1261         table()->item( row, COL_PUBLISHED )->setText( entry.in() );
1262         entryList.push_back( entry.in() );
1263       }
1264     }
1265   }
1266   getSMESHGUI()->getApp()->updateObjectBrowser();
1267   getSMESHGUI()->getApp()->browseObjects( entryList, /*isApplyAndClose=*/true );
1268
1269   currentCellChanged(); // to update buttons
1270 }
1271
1272 //================================================================================
1273 /*!
1274  * \brief show mesh elements preventing computation of a submesh of current row
1275  */
1276 //================================================================================
1277
1278 void SMESHGUI_BaseComputeOp::onShowBadMesh()
1279 {
1280   myTShapeDisplayer->SetVisibility( false );
1281   QList<int> rows;
1282   if ( SMESH::getSelectedRows( table(), rows ) == 1 ) {
1283     bool hasBadMesh = ( !table()->item(rows.front(), COL_BAD_MESH)->text().isEmpty() );
1284     if ( hasBadMesh ) {
1285       int curSub = table()->item(rows.front(), COL_SHAPEID)->text().toInt();
1286       SMESHGUI* gui = getSMESHGUI();
1287       SMESH::SMESH_Gen_var gen = gui->GetSMESHGen();
1288       SVTK_ViewWindow*    view = SMESH::GetViewWindow( gui );
1289       if ( myBadMeshDisplayer ) delete myBadMeshDisplayer;
1290       myBadMeshDisplayer = new SMESHGUI_MeshEditPreview( view );
1291       SMESH::MeshPreviewStruct_var aMeshData = gen->GetBadInputElements(myMesh,curSub);
1292       double aPointSize = SMESH::GetFloat("SMESH:node_size",3);
1293       double aLineWidth = SMESH::GetFloat("SMESH:element_width",1);
1294       vtkProperty* prop = vtkProperty::New();
1295       prop->SetLineWidth( aLineWidth * 3 );
1296       prop->SetPointSize( aPointSize * 3 );
1297       prop->SetColor( 250, 0, 250 );
1298       myBadMeshDisplayer->GetActor()->SetProperty( prop );
1299       myBadMeshDisplayer->SetData( aMeshData._retn() );
1300       prop->Delete();
1301     }
1302   }
1303 }
1304
1305 //================================================================================
1306 /*!
1307  * \brief create groups of bad mesh elements preventing computation of a submesh of current row
1308  */
1309 //================================================================================
1310
1311 void SMESHGUI_BaseComputeOp::onGroupOfBadMesh()
1312 {
1313   QList<int> rows;
1314   SMESH::getSelectedRows( table(), rows );
1315   int row;
1316   foreach ( row, rows )
1317   {
1318     bool hasBadMesh = ( !table()->item(row, COL_BAD_MESH)->text().isEmpty() );
1319     if ( hasBadMesh ) {
1320       int     curSub = table()->item(rows.front(), COL_SHAPEID)->text().toInt();
1321       QString grName = table()->item(rows.front(), COL_SHAPE)->text();
1322       if ( grName.isEmpty() ) grName = "bad mesh";
1323       else                    grName = "bad mesh of " + grName;
1324       SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
1325       SMESH::ListOfGroups_var groups
1326         ( gen->MakeGroupsOfBadInputElements(myMesh,curSub,grName.toLatin1().data()) );
1327       update( UF_ObjBrowser | UF_Model );
1328       if( LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( application() ))
1329       {
1330         QStringList anEntryList;
1331         for ( size_t i = 0; i < groups->length(); ++i )
1332           if ( _PTR(SObject) so = SMESH::FindSObject( groups[i] ))
1333             anEntryList.append( so->GetID().c_str() );
1334
1335         if ( !anEntryList.isEmpty())
1336           anApp->browseObjects( anEntryList, true, false );
1337       }
1338     }
1339   }
1340 }
1341
1342 //================================================================================
1343 /*!
1344  * \brief SLOT called when a selected cell in table() changed
1345  */
1346 //================================================================================
1347
1348 void SMESHGUI_BaseComputeOp::currentCellChanged()
1349 {
1350   myTShapeDisplayer->SetVisibility( false );
1351   if ( myBadMeshDisplayer )
1352     myBadMeshDisplayer->SetVisibility( false );
1353
1354   bool publishEnable = 0, showEnable = 0, showOnly = 1, hasBadMesh = 0;
1355   QList<int> rows;
1356   int nbSelected = SMESH::getSelectedRows( table(), rows );
1357   int row;
1358   foreach ( row, rows )
1359   {
1360     bool hasData     = ( !table()->item( row, COL_SHAPE )->text().isEmpty() );
1361     bool isPublished = ( !table()->item( row, COL_PUBLISHED )->text().isEmpty() );
1362     if ( hasData && !isPublished )
1363       publishEnable = true;
1364
1365     int curSub = table()->item( row, COL_SHAPEID )->text().toInt();
1366     bool prsReady = myTShapeDisplayer->HasReadyActorsFor( curSub, myMainShape );
1367     if ( prsReady ) {
1368       myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
1369       showOnly = false;
1370     }
1371     else {
1372       showEnable = true;
1373     }
1374
1375     if ( !table()->item(row, COL_BAD_MESH)->text().isEmpty() )
1376       hasBadMesh = true;
1377   }
1378   myCompDlg->myPublishBtn->setEnabled( publishEnable );
1379   myCompDlg->myShowBtn   ->setEnabled( showEnable );
1380   myCompDlg->myBadMeshBtn->setEnabled( hasBadMesh && ( nbSelected == 1 ));
1381   myCompDlg->myBadMeshToGroupBtn->setEnabled( hasBadMesh && ( nbSelected == 1 ));
1382 }
1383
1384 //================================================================================
1385 /*!
1386  * \brief update preview
1387  */
1388 //================================================================================
1389
1390 void SMESHGUI_BaseComputeOp::onPreviewShape()
1391 {
1392   if ( myTShapeDisplayer )
1393   {
1394     SUIT_OverrideCursor aWaitCursor;
1395     QList<int> rows;
1396     SMESH::getSelectedRows( table(), rows );
1397
1398     bool showOnly = true;
1399     int row;
1400     foreach ( row, rows )
1401     {
1402       int curSub = table()->item( row, COL_SHAPEID )->text().toInt();
1403       if ( curSub > 0 ) {
1404         myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
1405         showOnly = false;
1406       }
1407     }
1408     currentCellChanged(); // to update buttons
1409   }
1410 }
1411
1412 //================================================================================
1413 /*!
1414  * \brief Destructor
1415  */
1416 //================================================================================
1417
1418 SMESHGUI_BaseComputeOp::~SMESHGUI_BaseComputeOp()
1419 {
1420   delete myCompDlg;
1421   myCompDlg = 0;
1422   delete myTShapeDisplayer;
1423   if ( myBadMeshDisplayer )
1424     delete myBadMeshDisplayer;
1425 }
1426
1427 //================================================================================
1428 /*!
1429  * \brief Gets dialog of compute operation
1430  * \retval SMESHGUI_ComputeDlg* - pointer to dialog of this operation
1431  */
1432 //================================================================================
1433
1434 SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::computeDlg() const
1435 {
1436   if ( !myCompDlg )
1437   {
1438     SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this;
1439     me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), false );
1440     // connect signals and slots
1441     connect(myCompDlg->myShowBtn,           SIGNAL (clicked()), SLOT(onPreviewShape()));
1442     connect(myCompDlg->myPublishBtn,        SIGNAL (clicked()), SLOT(onPublishShape()));
1443     connect(myCompDlg->myBadMeshBtn,        SIGNAL (clicked()), SLOT(onShowBadMesh()));
1444     connect(myCompDlg->myBadMeshToGroupBtn, SIGNAL (clicked()), SLOT(onGroupOfBadMesh()));
1445
1446     QTableWidget* aTable = me->table();
1447     connect(aTable, SIGNAL(itemSelectionChanged()), SLOT(currentCellChanged()));
1448     connect(aTable, SIGNAL(currentCellChanged(int,int,int,int)), SLOT(currentCellChanged()));
1449   }
1450   return myCompDlg;
1451 }
1452
1453 //================================================================================
1454 /*!
1455  * \brief returns from compute mesh result dialog
1456  */
1457 //================================================================================
1458
1459 bool SMESHGUI_BaseComputeOp::onApply()
1460 {
1461   return true;
1462 }
1463
1464 //================================================================================
1465 /*!
1466  * \brief Return a table
1467  */
1468 //================================================================================
1469
1470 QTableWidget* SMESHGUI_BaseComputeOp::table()
1471 {
1472   return myCompDlg->myTable;
1473 }
1474
1475
1476 //================================================================================
1477 /*!
1478  * \brief Constructor
1479 */
1480 //================================================================================
1481
1482 SMESHGUI_ComputeOp::SMESHGUI_ComputeOp()
1483  : SMESHGUI_BaseComputeOp()
1484 {
1485 }
1486
1487
1488 //================================================================================
1489 /*!
1490  * \brief Desctructor
1491 */
1492 //================================================================================
1493
1494 SMESHGUI_ComputeOp::~SMESHGUI_ComputeOp()
1495 {
1496 }
1497
1498 //================================================================================
1499 /*!
1500  * \brief perform it's intention action: compute mesh
1501  */
1502 //================================================================================
1503
1504 void SMESHGUI_ComputeOp::startOperation()
1505 {
1506   SMESHGUI_BaseComputeOp::startOperation();
1507   if (myMesh->_is_nil())
1508     return;
1509   computeMesh();
1510 }
1511
1512 //================================================================================
1513 /*!
1514  * \brief check the same operations on the same mesh
1515  */
1516 //================================================================================
1517
1518 bool SMESHGUI_BaseComputeOp::isValid(  SUIT_Operation* theOp  ) const
1519 {
1520   SMESHGUI_BaseComputeOp* baseOp = dynamic_cast<SMESHGUI_BaseComputeOp*>( theOp );
1521   bool ret = true;
1522   if ( !myMesh->_is_nil() && baseOp ) {
1523     SMESH::SMESH_Mesh_var aMesh = baseOp->getMesh();
1524     if ( !aMesh->_is_nil() && aMesh->GetId() == myMesh->GetId() ) ret = false;
1525   }
1526   return ret;
1527 }
1528
1529 //================================================================================
1530 /*!
1531  * \brief Gets dialog of this operation
1532  * \retval LightApp_Dialog* - pointer to dialog of this operation
1533  */
1534 //================================================================================
1535
1536 LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const
1537 {
1538   return computeDlg();
1539 }
1540
1541 //================================================================================
1542 /*!
1543  * \brief Constructor
1544 */
1545 //================================================================================
1546
1547 SMESHGUI_PrecomputeOp::SMESHGUI_PrecomputeOp()
1548  : SMESHGUI_BaseComputeOp(),
1549  myDlg( 0 ),
1550  myOrderMgr( 0 ),
1551  myActiveDlg( 0 ),
1552  myPreviewDisplayer( 0 )
1553 {
1554   myHelpFileName = "constructing_meshes_page.html#preview_mesh_anchor";
1555 }
1556
1557 //================================================================================
1558 /*!
1559  * \brief Destructor
1560  */
1561 //================================================================================
1562
1563 SMESHGUI_PrecomputeOp::~SMESHGUI_PrecomputeOp()
1564 {
1565   delete myDlg;
1566   myDlg = 0;
1567   delete myOrderMgr;
1568   myOrderMgr = 0;
1569   myActiveDlg = 0;
1570   if ( myPreviewDisplayer )
1571     delete myPreviewDisplayer;
1572   myPreviewDisplayer = 0;
1573 }
1574
1575 //================================================================================
1576 /*!
1577  * \brief Gets current dialog of this operation
1578  * \retval LightApp_Dialog* - pointer to dialog of this operation
1579  */
1580 //================================================================================
1581
1582 LightApp_Dialog* SMESHGUI_PrecomputeOp::dlg() const
1583 {
1584   return myActiveDlg;
1585 }
1586
1587 //================================================================================
1588 /*!
1589  * \brief perform it's intention action: prepare data
1590  */
1591 //================================================================================
1592
1593 void SMESHGUI_PrecomputeOp::startOperation()
1594 {
1595   if ( !myDlg )
1596   {
1597     myDlg = new SMESHGUI_PrecomputeDlg( desktop() );
1598     
1599     // connect signals
1600     connect( myDlg, SIGNAL( preview() ), this, SLOT( onPreview() ) );
1601     connect( myDlg, SIGNAL( dlgOk() ), this, SLOT( onCompute() ) );
1602     connect( myDlg, SIGNAL( dlgApply() ), this, SLOT( onCompute() ) );
1603   }
1604   myActiveDlg = myDlg;
1605
1606   // connect signal to compute dialog. which will be shown after Compute mesh operation
1607   SMESHGUI_ComputeDlg* cmpDlg = computeDlg();
1608   if ( cmpDlg )
1609   {
1610     // disconnect signals
1611     disconnect( cmpDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) );
1612     disconnect( cmpDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) );
1613     disconnect( cmpDlg, SIGNAL( dlgCancel() ), this, SLOT( onCancel() ) );
1614     disconnect( cmpDlg, SIGNAL( dlgClose() ), this, SLOT( onCancel() ) );
1615     disconnect( cmpDlg, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) );
1616
1617     // connect signals
1618     if( cmpDlg->testButtonFlags( QtxDialog::OK ) )
1619       connect( cmpDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) );
1620     if( cmpDlg->testButtonFlags( QtxDialog::Apply ) )
1621       connect( cmpDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) );
1622     if( cmpDlg->testButtonFlags( QtxDialog::Help ) )
1623       connect( cmpDlg, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) );
1624     if( cmpDlg->testButtonFlags( QtxDialog::Cancel ) )
1625       connect( cmpDlg, SIGNAL( dlgCancel() ), this, SLOT( onCancel() ) );
1626     if( cmpDlg->testButtonFlags( QtxDialog::Close ) )
1627       connect( cmpDlg, SIGNAL( dlgClose() ), this, SLOT( onCancel() ) );
1628   }
1629
1630   SMESHGUI_BaseComputeOp::startOperation();
1631   if (myMesh->_is_nil())
1632     return;
1633
1634   if (myDlg->getPreviewMode() == -1)
1635   {
1636     // nothing to preview
1637     SUIT_MessageBox::warning(desktop(),
1638                              tr("SMESH_WRN_WARNING"),
1639                              tr("SMESH_WRN_NOTHING_PREVIEW"));
1640     onCancel();
1641     return;
1642   }
1643
1644   // disconnect slot from preview dialog to have Apply from results of compute operation only 
1645   disconnect( myDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) );
1646   disconnect( myDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) );
1647
1648   myDlg->show();
1649 }
1650
1651 //================================================================================
1652 /*!
1653  * \brief Stops operation
1654  */
1655 //================================================================================
1656
1657 void SMESHGUI_PrecomputeOp::stopOperation()
1658 {
1659   if ( myPreviewDisplayer )
1660   {
1661     myPreviewDisplayer->SetVisibility( false );
1662     delete myPreviewDisplayer;
1663     myPreviewDisplayer = 0;
1664   }
1665   myMapShapeId.clear();
1666   SMESHGUI_BaseComputeOp::stopOperation();
1667 }
1668
1669 //================================================================================
1670 /*!
1671  * \brief reinitialize dialog after operaiton become active again
1672  */
1673 //================================================================================
1674
1675 void SMESHGUI_PrecomputeOp::resumeOperation()
1676 {
1677   if ( myActiveDlg == myDlg )
1678     initDialog();
1679   SMESHGUI_BaseComputeOp::resumeOperation();
1680 }
1681
1682 //================================================================================
1683 /*!
1684  * \brief perform it's intention action: reinitialise dialog
1685  */
1686 //================================================================================
1687
1688 void SMESHGUI_PrecomputeOp::initDialog()
1689 {
1690   QList<int> modes;
1691
1692   QMap<int, int> modeMap;
1693   _PTR(SObject)  pMesh = studyDS()->FindObjectID( myIObject->getEntry() );
1694   getAssignedAlgos( pMesh, modeMap );
1695   if ( modeMap.contains( SMESH::DIM_3D ) )
1696   {
1697     if ( modeMap.contains( SMESH::DIM_2D ) )
1698       modes.append( SMESH::DIM_2D );
1699     if ( modeMap.contains( SMESH::DIM_1D ) )
1700       modes.append( SMESH::DIM_1D );
1701   }
1702   else if ( modeMap.contains( SMESH::DIM_2D ) )
1703   {
1704     if ( modeMap.contains( SMESH::DIM_1D ) )
1705       modes.append( SMESH::DIM_1D );
1706   }
1707
1708   myOrderMgr = new SMESHGUI_MeshOrderMgr( myDlg->getMeshOrderBox() );
1709   myOrderMgr->SetMesh( myMesh );
1710   bool isOrder = myOrderMgr->GetMeshOrder(myPrevOrder);
1711   myDlg->getMeshOrderBox()->setShown(isOrder);
1712   if ( !isOrder ) {
1713     delete myOrderMgr;
1714     myOrderMgr = 0;
1715   }
1716
1717   myDlg->setPreviewModes( modes );
1718 }
1719
1720 //================================================================================
1721 /*!
1722  * \brief detect asigned mesh algorithms
1723  */
1724 //================================================================================
1725
1726 void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
1727                                              QMap<int,int>& theModeMap)
1728 {
1729   _PTR(SObject)          aHypRoot;
1730   _PTR(GenericAttribute) anAttr;
1731   int aPart = SMESH::Tag_RefOnAppliedAlgorithms;
1732   if ( theMesh && theMesh->FindSubObject( aPart, aHypRoot ) )
1733   {
1734     _PTR(ChildIterator) anIter =
1735       SMESH::GetActiveStudyDocument()->NewChildIterator( aHypRoot );
1736     for ( ; anIter->More(); anIter->Next() )
1737     {
1738       _PTR(SObject) anObj = anIter->Value();
1739       _PTR(SObject) aRefObj;
1740       if ( anObj->ReferencedObject( aRefObj ) )
1741         anObj = aRefObj;
1742       else
1743         continue;
1744       
1745       if ( anObj->FindAttribute( anAttr, "AttributeName" ) )
1746       {
1747         CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
1748         if ( CORBA::is_nil( aVar ) )
1749           continue;
1750         
1751         for( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
1752         {
1753           SMESH::SMESH_Algo_var algo;
1754           switch(dim) {
1755           case SMESH::DIM_1D: algo = SMESH::SMESH_1D_Algo::_narrow( aVar ); break;
1756           case SMESH::DIM_2D: algo = SMESH::SMESH_2D_Algo::_narrow( aVar ); break;
1757           case SMESH::DIM_3D: algo = SMESH::SMESH_3D_Algo::_narrow( aVar ); break;
1758           default: break;
1759           }
1760           if ( !algo->_is_nil() )
1761             theModeMap[ dim ] = 0;
1762         }
1763       }
1764     }
1765   }
1766 }
1767
1768 //================================================================================
1769 /*!
1770  * \brief perform it's intention action: compute mesh
1771  */
1772 //================================================================================
1773
1774 void SMESHGUI_PrecomputeOp::onCompute()
1775 {
1776   myDlg->hide();
1777   if (myOrderMgr && myOrderMgr->IsOrderChanged())
1778     myOrderMgr->SetMeshOrder();
1779   myMapShapeId.clear();
1780   myActiveDlg = computeDlg();
1781   computeMesh();
1782 }
1783
1784 //================================================================================
1785 /*!
1786  * \brief perform it's intention action: compute mesh
1787  */
1788 //================================================================================
1789
1790 void SMESHGUI_PrecomputeOp::onCancel()
1791 {
1792   QObject* curDlg = sender();
1793   if ( curDlg == computeDlg() && myActiveDlg == myDlg )
1794   {
1795     // return from error messages
1796     myDlg->show();
1797     return;
1798   }
1799
1800   bool isRestoreOrder = false;
1801   if ( myActiveDlg == myDlg  && !myMesh->_is_nil() && myMapShapeId.count() )
1802   {
1803     // ask to remove already computed mesh elements
1804     if ( SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ),
1805                                     tr( "CLEAR_SUBMESH_QUESTION" ),
1806                                     tr( "SMESH_BUT_DELETE" ), tr( "SMESH_BUT_NO" ), 0, 1 ) == 0 )
1807     {
1808       // remove all submeshes for collected shapes
1809       QMap<int,int>::const_iterator it = myMapShapeId.constBegin();
1810       for ( ; it != myMapShapeId.constEnd(); ++it )
1811         myMesh->ClearSubMesh( *it );
1812       isRestoreOrder = true;
1813     }
1814   }
1815
1816   // return previous mesh order
1817   if (myOrderMgr && myOrderMgr->IsOrderChanged()) {
1818     if (!isRestoreOrder)
1819       isRestoreOrder = 
1820         (SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ),
1821                                     tr( "SMESH_REJECT_MESH_ORDER" ),
1822                                     tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 ) == 0);
1823     if (isRestoreOrder)
1824       myOrderMgr->SetMeshOrder(myPrevOrder);
1825   }
1826
1827   delete myOrderMgr;
1828   myOrderMgr = 0;
1829
1830   myMapShapeId.clear();
1831   SMESHGUI_BaseComputeOp::onCancel();
1832 }
1833
1834 //================================================================================
1835 /*!
1836  * \brief perform it's intention action: preview mesh
1837  */
1838 //================================================================================
1839
1840 void SMESHGUI_PrecomputeOp::onPreview()
1841 {
1842   if ( !myDlg || myMesh->_is_nil() || myMainShape->_is_nil() )
1843     return;
1844
1845   _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh);
1846   if ( !aMeshSObj )
1847     return;
1848
1849   // set modified submesh priority if any
1850   if (myOrderMgr && myOrderMgr->IsOrderChanged())
1851     myOrderMgr->SetMeshOrder();
1852
1853   // Compute preview of mesh, 
1854   // i.e. compute mesh till indicated dimension
1855   int dim = myDlg->getPreviewMode();
1856   
1857   SMESH::MemoryReserve aMemoryReserve;
1858   
1859   SMESH::compute_error_array_var aCompErrors;
1860   QString                        aHypErrors;
1861
1862   bool computeFailed = true, memoryLack = false;
1863
1864   SMESHGUI_ComputeDlg* aCompDlg = computeDlg();
1865     aCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() );
1866
1867   SMESHGUI* gui = getSMESHGUI();
1868   SMESH::SMESH_Gen_var gen = gui->GetSMESHGen();
1869   SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape);
1870   if ( errors->length() > 0 ) {
1871     aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() );
1872   }
1873
1874   SUIT_OverrideCursor aWaitCursor;
1875
1876   SVTK_ViewWindow*    view = SMESH::GetViewWindow( gui );
1877   if ( myPreviewDisplayer ) delete myPreviewDisplayer;
1878   myPreviewDisplayer = new SMESHGUI_MeshEditPreview( view );
1879   
1880   SMESH::long_array_var aShapesId = new SMESH::long_array();
1881   try {
1882 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1883     OCC_CATCH_SIGNALS;
1884 #endif
1885       
1886     SMESH::MeshPreviewStruct_var previewData =
1887       gen->Precompute(myMesh, myMainShape, (SMESH::Dimension)dim, aShapesId);
1888
1889     SMESH::MeshPreviewStruct* previewRes = previewData._retn();
1890     if ( previewRes && previewRes->nodesXYZ.length() > 0 )
1891     {
1892       computeFailed = false;
1893       myPreviewDisplayer->SetData( previewRes );
1894       // append shape indeces with computed mesh entities
1895       for ( int i = 0, n = aShapesId->length(); i < n; i++ )
1896         myMapShapeId[ aShapesId[ i ] ] = 0;
1897     }
1898     else
1899       myPreviewDisplayer->SetVisibility(false);
1900   }
1901   catch(const SALOME::SALOME_Exception & S_ex){
1902     memoryLack = true;
1903     myPreviewDisplayer->SetVisibility(false);
1904   }
1905
1906   try {
1907 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1908     OCC_CATCH_SIGNALS;
1909 #endif
1910     aCompErrors = gen->GetComputeErrors( myMesh, myMainShape );
1911     // check if there are memory problems
1912     for ( int i = 0; (i < aCompErrors->length()) && !memoryLack; ++i )
1913       memoryLack = ( aCompErrors[ i ].code == SMESH::COMPERR_MEMORY_PB );
1914   }
1915   catch(const SALOME::SALOME_Exception & S_ex){
1916     memoryLack = true;
1917   }
1918
1919   if ( memoryLack )
1920     aMemoryReserve.release();
1921
1922   bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 );
1923   bool noHypoError = ( aHypErrors.isEmpty() );
1924
1925   SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( gui );
1926   int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" );
1927
1928   bool isShowError = true;
1929   switch( aNotifyMode ) {
1930   case 0: // show the mesh computation result dialog NEVER
1931     isShowError = false;
1932     break;
1933   case 1: // show the mesh computation result dialog if there are some errors
1934   default: // show the result dialog after each mesh computation
1935     if ( !computeFailed && !memoryLack && noCompError && noHypoError )
1936       isShowError = false;
1937     break;
1938   }
1939
1940   aWaitCursor.suspend();
1941   // SHOW ERRORS
1942   if ( isShowError )
1943   {
1944     myDlg->hide();
1945     aCompDlg->setWindowTitle(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED"));
1946     showComputeResult( memoryLack, noCompError, aCompErrors, noHypoError, aHypErrors );
1947   }
1948 }
1949
1950
1951 //================================================================================
1952 /*!
1953  * \brief Constructor
1954 */
1955 //================================================================================
1956
1957 SMESHGUI_PrecomputeDlg::SMESHGUI_PrecomputeDlg( QWidget* parent )
1958  : SMESHGUI_Dialog( parent, false, false, OK | Cancel | Help ),
1959    myOrderBox(0)
1960 {
1961   setWindowTitle( tr( "CAPTION" ) );
1962
1963   setButtonText( OK, tr( "COMPUTE" ) );
1964   QFrame* main = mainFrame();
1965
1966   QVBoxLayout* layout = new QVBoxLayout( main );
1967
1968   myOrderBox = new SMESHGUI_MeshOrderBox( main );
1969   layout->addWidget(myOrderBox);
1970
1971   QFrame* frame = new QFrame( main );
1972   layout->setMargin(0); layout->setSpacing(0);
1973   layout->addWidget( frame );
1974
1975   QHBoxLayout* frameLay = new QHBoxLayout( frame );
1976   frameLay->setMargin(0); frameLay->setSpacing(SPACING);
1977   
1978   myPreviewMode = new QtxComboBox( frame );
1979   frameLay->addWidget( myPreviewMode );
1980
1981   myPreviewBtn = new QPushButton( tr( "PREVIEW" ), frame );
1982   frameLay->addWidget( myPreviewBtn );
1983
1984   connect( myPreviewBtn, SIGNAL( clicked( bool ) ), this, SIGNAL( preview() ) );
1985 }
1986
1987 //================================================================================
1988 /*!
1989  * \brief Destructor
1990 */
1991 //================================================================================
1992
1993 SMESHGUI_PrecomputeDlg::~SMESHGUI_PrecomputeDlg()
1994 {
1995 }
1996
1997 //================================================================================
1998 /*!
1999  * \brief Sets available preview modes
2000 */
2001 //================================================================================
2002
2003 void SMESHGUI_PrecomputeDlg::setPreviewModes( const QList<int>& theModes )
2004 {
2005   myPreviewMode->clear();
2006   QList<int>::const_iterator it = theModes.constBegin();
2007   for ( int i = 0; it != theModes.constEnd(); ++it, i++ )
2008   {
2009     QString mode = QString( "PREVIEW_%1" ).arg( *it );
2010     myPreviewMode->addItem( tr( mode.toLatin1().data() ) );
2011     myPreviewMode->setId( i, *it );
2012   }
2013   myPreviewBtn->setEnabled( !theModes.isEmpty() );
2014 }
2015
2016 //================================================================================
2017 /*!
2018  * \brief Returns current preview mesh mode
2019 */
2020 //================================================================================
2021
2022 int SMESHGUI_PrecomputeDlg::getPreviewMode() const
2023 {
2024   return myPreviewMode->currentId();
2025 }
2026
2027 //================================================================================
2028 /*!
2029  * \brief Returns current preview mesh mode
2030 */
2031 //================================================================================
2032
2033 SMESHGUI_MeshOrderBox* SMESHGUI_PrecomputeDlg::getMeshOrderBox() const
2034 {
2035   return myOrderBox;
2036 }
2037
2038
2039 //================================================================================
2040 /*!
2041  * \brief Constructor
2042 */
2043 //================================================================================
2044
2045 SMESHGUI_EvaluateOp::SMESHGUI_EvaluateOp()
2046  : SMESHGUI_BaseComputeOp()
2047 {
2048 }
2049
2050
2051 //================================================================================
2052 /*!
2053  * \brief Desctructor
2054 */
2055 //================================================================================
2056
2057 SMESHGUI_EvaluateOp::~SMESHGUI_EvaluateOp()
2058 {
2059 }
2060
2061 //================================================================================
2062 /*!
2063  * \brief perform it's intention action: compute mesh
2064  */
2065 //================================================================================
2066
2067 void SMESHGUI_EvaluateOp::startOperation()
2068 {
2069   SMESHGUI_BaseComputeOp::evaluateDlg();
2070   SMESHGUI_BaseComputeOp::startOperation();
2071   if (myMesh->_is_nil())
2072     return;
2073   evaluateMesh();
2074 }
2075
2076 //================================================================================
2077 /*!
2078  * \brief Gets dialog of this operation
2079  * \retval LightApp_Dialog* - pointer to dialog of this operation
2080  */
2081 //================================================================================
2082
2083 LightApp_Dialog* SMESHGUI_EvaluateOp::dlg() const
2084 {
2085   return evaluateDlg();
2086 }
2087
2088 //================================================================================
2089 /*!
2090  * \brief evaluateMesh()
2091 */
2092 //================================================================================
2093
2094 void SMESHGUI_BaseComputeOp::evaluateMesh()
2095 {
2096   // EVALUATE MESH
2097
2098   SMESH::MemoryReserve aMemoryReserve;
2099
2100   SMESH::compute_error_array_var aCompErrors;
2101   QString                        aHypErrors;
2102
2103   bool evaluateFailed = true, memoryLack = false;
2104   SMESH::long_array_var aRes;
2105
2106   _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh);
2107   if ( !aMeshSObj ) //  IPAL21340
2108     return;
2109
2110   bool hasShape = myMesh->HasShapeToMesh();
2111   bool shapeOK = myMainShape->_is_nil() ? !hasShape : hasShape;
2112   if ( shapeOK )
2113   {
2114     myCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() );
2115     SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
2116     SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape);
2117     if ( errors->length() > 0 ) {
2118       aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() );
2119     }
2120     SUIT_OverrideCursor aWaitCursor;
2121     try {
2122 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2123       OCC_CATCH_SIGNALS;
2124 #endif
2125       aRes = gen->Evaluate(myMesh, myMainShape);
2126     }
2127     catch(const SALOME::SALOME_Exception & S_ex){
2128       memoryLack = true;
2129     }
2130
2131     try {
2132 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2133       OCC_CATCH_SIGNALS;
2134 #endif
2135       aCompErrors = gen->GetComputeErrors( myMesh, myMainShape );
2136     }
2137     catch(const SALOME::SALOME_Exception & S_ex){
2138       memoryLack = true;
2139     }
2140   }
2141
2142   if ( memoryLack )
2143     aMemoryReserve.release();
2144
2145   evaluateFailed =  ( aCompErrors->length() > 0 );
2146   myCompDlg->setWindowTitle(tr( evaluateFailed ? "SMESH_WRN_EVALUATE_FAILED" : "SMESH_EVALUATE_SUCCEED"));
2147
2148   // SHOW ERRORS
2149   
2150   bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 );
2151   bool noHypoError = ( aHypErrors.isEmpty() );
2152
2153   //SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
2154   //int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" );
2155
2156   bool isShowResultDlg = true;
2157   //if( noHypoError )
2158   //switch( aNotifyMode ) {
2159   //case 0: // show the mesh computation result dialog NEVER
2160   //isShowResultDlg = false;
2161   //commit();
2162   //break;
2163   //case 1: // show the mesh computation result dialog if there are some errors
2164   //if ( memoryLack || !noHypoError )
2165   //  isShowResultDlg = true;
2166   //else
2167   //{
2168   //  isShowResultDlg = false;
2169   //  commit();
2170   //}
2171   //break;
2172   //default: // show the result dialog after each mesh computation
2173   //isShowResultDlg = true;
2174   //}
2175
2176   // SHOW RESULTS
2177   if ( isShowResultDlg )
2178     showEvaluateResult( aRes, memoryLack, noCompError, aCompErrors,
2179                         noHypoError, aHypErrors);
2180 }
2181
2182
2183 void SMESHGUI_BaseComputeOp::showEvaluateResult(const SMESH::long_array& theRes,
2184                                                 const bool theMemoryLack,
2185                                                 const bool theNoCompError,
2186                                                 SMESH::compute_error_array_var& theCompErrors,
2187                                                 const bool theNoHypoError,
2188                                                 const QString& theHypErrors)
2189 {
2190   bool hasShape = myMesh->HasShapeToMesh();
2191   SMESHGUI_ComputeDlg* aCompDlg = evaluateDlg();
2192   aCompDlg->myMemoryLackGroup->hide();
2193
2194   if ( theMemoryLack )
2195   {
2196     aCompDlg->myMemoryLackGroup->show();
2197     aCompDlg->myFullInfo->hide();
2198     aCompDlg->myBriefInfo->hide();
2199     aCompDlg->myHypErrorGroup->hide();
2200     aCompDlg->myCompErrorGroup->hide();
2201   }
2202   else if ( theNoCompError && theNoHypoError )
2203   {
2204     aCompDlg->myFullInfo->SetMeshInfo( theRes );
2205     aCompDlg->myFullInfo->show();
2206     aCompDlg->myBriefInfo->hide();
2207     aCompDlg->myHypErrorGroup->hide();
2208     aCompDlg->myCompErrorGroup->hide();
2209   }
2210   else
2211   {
2212     QTableWidget* tbl = aCompDlg->myTable;
2213     aCompDlg->myBriefInfo->SetMeshInfo( theRes );
2214     aCompDlg->myBriefInfo->show();
2215     aCompDlg->myFullInfo->hide();
2216
2217     if ( theNoHypoError ) {
2218       aCompDlg->myHypErrorGroup->hide();
2219     }
2220     else {
2221       aCompDlg->myHypErrorGroup->show();
2222       aCompDlg->myHypErrorLabel->setText( theHypErrors );
2223     }
2224
2225     if ( theNoCompError ) {
2226       aCompDlg->myCompErrorGroup->hide();
2227     }
2228     else {
2229       aCompDlg->myCompErrorGroup->show();
2230
2231       aCompDlg->myPublishBtn->hide();
2232       aCompDlg->myShowBtn->hide();
2233
2234       // fill table of errors
2235       tbl->setRowCount( theCompErrors->length() );
2236       if ( !hasShape ) tbl->hideColumn( COL_SHAPE );
2237       else             tbl->showColumn( COL_SHAPE );
2238       tbl->setColumnWidth( COL_ERROR, 200 );
2239
2240       bool hasBadMesh = false;
2241       for ( int row = 0; row < theCompErrors->length(); ++row )
2242       {
2243         SMESH::ComputeError & err = theCompErrors[ row ];
2244
2245         QString text = err.algoName.in();
2246         if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) );
2247         else tbl->item( row, COL_ALGO )->setText( text );
2248
2249         text = SMESH::errorText( err.code, err.comment.in() );
2250         if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) );
2251         else tbl->item( row, COL_ERROR )->setText( text );
2252
2253         text = QString("%1").arg( err.subShapeID );
2254         if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) );
2255         else tbl->item( row, COL_SHAPEID )->setText( text );
2256
2257         text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString("");
2258         if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) );
2259         else tbl->item( row, COL_SHAPE )->setText( text );
2260
2261         text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : "";
2262         if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) );
2263         else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled
2264
2265         text = err.hasBadMesh ? "hasBadMesh" : "";
2266         if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) );
2267         else tbl->item( row, COL_BAD_MESH )->setText( text );
2268         if ( err.hasBadMesh ) hasBadMesh = true;
2269
2270         //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ???
2271         tbl->resizeRowToContents( row );
2272       }
2273       tbl->resizeColumnToContents( COL_ALGO );
2274       tbl->resizeColumnToContents( COL_SHAPE );
2275       tbl->setWordWrap( true );
2276
2277       if ( hasBadMesh )
2278       {
2279         aCompDlg->myBadMeshBtn->show();
2280         aCompDlg->myBadMeshToGroupBtn->show();
2281       }
2282       else
2283       {
2284         aCompDlg->myBadMeshBtn->hide();
2285         aCompDlg->myBadMeshToGroupBtn->hide();
2286       }
2287       tbl->setCurrentCell(0,0);
2288       currentCellChanged(); // to update buttons
2289     }
2290   }
2291   // show dialog and wait, becase Compute can be invoked from Preview operation
2292   //aCompDlg->exec(); // this way it becomes modal - impossible to rotate model in the Viewer
2293   aCompDlg->show();
2294 }
2295
2296
2297 //================================================================================
2298 /*!
2299  * \brief Gets dialog of evaluate operation
2300  * \retval SMESHGUI_ComputeDlg* - pointer to dialog of this operation
2301  */
2302 //================================================================================
2303
2304 SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::evaluateDlg() const
2305 {
2306   if ( !myCompDlg )
2307   {
2308     SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this;
2309     me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), true );
2310     // connect signals and slots
2311     connect(myCompDlg->myShowBtn,    SIGNAL (clicked()), SLOT(onPreviewShape()));
2312     connect(myCompDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape()));
2313     connect(myCompDlg->myBadMeshBtn, SIGNAL (clicked()), SLOT(onShowBadMesh()));
2314     QTableWidget* aTable = me->table();
2315     connect(aTable, SIGNAL(itemSelectionChanged()), SLOT(currentCellChanged()));
2316     connect(aTable, SIGNAL(currentCellChanged(int,int,int,int)), SLOT(currentCellChanged()));
2317   }
2318   return myCompDlg;
2319 }
2320