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