Salome HOME
PAL13330( When mesh generation does not success, trace where )
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ComputeDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : SMESHGUI_ComputeDlg.cxx
25 //  Author : Edward AGAPOV
26 //  Module : SMESH
27
28 #include "SMESHGUI_ComputeDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_GEOMGenUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
35 #include "SMESHGUI_HypothesesUtils.h"
36
37 #include "SMDS_SetIterator.hxx"
38
39 #include "GEOMBase.h"
40 #include "GEOM_Actor.h"
41
42 #include "LightApp_SelectionMgr.h"
43 #include "LightApp_UpdateFlags.h"
44 #include "SALOMEDSClient_SObject.hxx"
45 #include "SALOME_ListIO.hxx"
46 #include "SVTK_ViewWindow.h"
47 #include "SalomeApp_Tools.h"
48 #include "SalomeApp_Application.h"
49 #include "SUIT_ResourceMgr.h"
50 #include "SUIT_OverrideCursor.h"
51 #include "SUIT_MessageBox.h"
52 #include "SUIT_Desktop.h"
53 #include "SUIT_Study.h"
54 #include "OB_Browser.h"
55
56 // OCCT Includes
57 #include <BRep_Tool.hxx>
58 #include <TopExp.hxx>
59 #include <TopExp_Explorer.hxx>
60 #include <TopTools_IndexedMapOfShape.hxx>
61 #include <TopoDS.hxx>
62
63 #include <TopLoc_Location.hxx>
64 #include <Poly_Triangulation.hxx>
65 #include <Bnd_Box.hxx>
66 #include <BRepBndLib.hxx>
67 #include <BRepMesh_IncrementalMesh.hxx>
68
69 // QT Includes
70 #include <qframe.h>
71 #include <qlayout.h>
72 #include <qpushbutton.h>
73 #include <qlabel.h>
74 #include <qbuttongroup.h>
75 #include <qradiobutton.h>
76 #include <qtable.h>
77
78 #include <vtkProperty.h>
79
80 // IDL Headers
81 #include <SALOMEconfig.h>
82 #include CORBA_SERVER_HEADER(SMESH_Gen)
83 #include CORBA_SERVER_HEADER(SMESH_Mesh)
84
85 #include <vector>
86 #include <set>
87
88
89 #define SPACING 5
90 #define MARGIN  10
91
92 enum TCol { COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, NB_COLUMNS };
93
94 using namespace SMESH;
95
96 namespace SMESH {
97   
98   // =========================================================================================
99   /*!
100    * \brief Class showing shapes without publishing
101    */
102   // =========================================================================================
103
104   class TShapeDisplayer
105   {
106   public:
107     // -----------------------------------------------------------------------
108     TShapeDisplayer(): myViewWindow(0)
109     {
110       myProperty = vtkProperty::New();
111       myProperty->SetRepresentationToWireframe();
112       myProperty->SetColor( 250, 0, 250 );
113       myProperty->SetAmbientColor( 250, 0, 250 );
114       myProperty->SetDiffuseColor( 250, 0, 250 );
115       //myProperty->SetSpecularColor( 250, 0, 250 );
116       myProperty->SetLineWidth( 5 );
117     }
118     // -----------------------------------------------------------------------
119     ~TShapeDisplayer()
120     {
121       DeleteActors();
122       myProperty->Delete();
123     }
124     // -----------------------------------------------------------------------
125     void DeleteActors()
126     {
127       TActorIterator actorIt = actorIterator();
128       while ( actorIt.more() )
129         if (VTKViewer_Actor* anActor = actorIt.next()) {
130           myViewWindow->RemoveActor( anActor );
131           //anActor->Delete();
132         }
133       myIndexToShape.Clear();
134       myActors.clear();
135       myShownActors.clear();
136       myBuiltSubs.clear();
137     }
138     // -----------------------------------------------------------------------
139     void SetVisibility (bool theVisibility)
140     {
141       TActorIterator actorIt = shownIterator();
142       while ( actorIt.more() )
143         if (VTKViewer_Actor* anActor = actorIt.next())
144           anActor->SetVisibility(theVisibility);
145       SMESH::RepaintCurrentView();
146     }
147     // -----------------------------------------------------------------------
148     bool HasReadyActorsFor (int subShapeID, GEOM::GEOM_Object_var aMainShape )
149     {
150       string mainEntry;
151       if ( !aMainShape->_is_nil() )
152         mainEntry = aMainShape->GetStudyEntry();
153       return ( myMainEntry == mainEntry &&
154                myBuiltSubs.find( subShapeID ) != myBuiltSubs.end() );
155     }
156     // -----------------------------------------------------------------------
157     void Show( int subShapeID, GEOM::GEOM_Object_var aMainShape, bool only = false)
158     {
159       SVTK_ViewWindow* aViewWindow  = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() );
160       string mainEntry;
161       if ( !aMainShape->_is_nil() )
162         mainEntry = aMainShape->GetStudyEntry();
163       if ( myMainEntry != mainEntry || aViewWindow != myViewWindow ) { // remove actors
164         DeleteActors();
165         TopoDS_Shape aShape;
166         if ( !aMainShape->_is_nil() && GEOMBase::GetShape(aMainShape, aShape)) {
167           checkTriangulation( aShape );
168           TopExp::MapShapes(aShape, myIndexToShape);
169           myActors.resize( myIndexToShape.Extent(), 0 );
170           myShownActors.reserve( myIndexToShape.Extent() );
171         }
172         myMainEntry  = mainEntry;
173         myViewWindow = aViewWindow;
174       }
175       if ( only ) { // hide shown actors
176         TActorIterator actorIt = shownIterator();
177         while ( actorIt.more() )
178           if (VTKViewer_Actor* anActor = actorIt.next())
179             anActor->SetVisibility(false);
180         myShownActors.clear();
181       }
182       // find actors to show
183       TopoDS_Shape aShape = myIndexToShape( subShapeID );
184       if ( !aShape.IsNull() ) {
185         TopAbs_ShapeEnum type( aShape.ShapeType() >= TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE );
186         for ( TopExp_Explorer exp( aShape, type ); exp.More(); exp.Next() ) {
187           //checkTriangulation( exp.Current() );
188           if ( GEOM_Actor* anActor = getActor( exp.Current() ))
189             myShownActors.push_back( anActor );
190         }
191         if ( type == TopAbs_FACE ) {
192           for ( TopExp_Explorer exp( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) {
193             const TopoDS_Edge & edge = TopoDS::Edge( exp.Current() );
194             if ( !BRep_Tool::Degenerated( edge ))
195               if ( GEOM_Actor* anActor = getActor( exp.Current() ))
196                 myShownActors.push_back( anActor );
197           }
198         }
199       }
200       myBuiltSubs.insert( subShapeID );
201       SetVisibility(true);
202     }
203     // -----------------------------------------------------------------------
204
205   private:
206
207     typedef std::vector<GEOM_Actor*> TActorVec;
208     TActorVec                  myActors;
209     TActorVec                  myShownActors;
210     TopTools_IndexedMapOfShape myIndexToShape;
211     string                     myMainEntry;
212     SVTK_ViewWindow*           myViewWindow;
213     vtkProperty*               myProperty;
214     std::set<int>              myBuiltSubs;
215
216     // -----------------------------------------------------------------------
217     typedef SMDS_SetIterator< GEOM_Actor*, TActorVec::const_iterator> TActorIterator;
218     TActorIterator actorIterator() {
219       return TActorIterator( myActors.begin(), myActors.end() );
220     }
221     TActorIterator shownIterator() {
222       return TActorIterator( myShownActors.begin(), myShownActors.end() );
223     }
224     // -----------------------------------------------------------------------
225     GEOM_Actor* getActor(const TopoDS_Shape& shape)
226     {
227       int index = myIndexToShape.FindIndex( shape ) - 1;
228       if ( index < 0 || index >= myActors.size() )
229         return 0;
230       GEOM_Actor* & actor = myActors[ index ];
231       if ( !actor ) {
232         actor = GEOM_Actor::New();
233         if ( actor ) {
234           actor->setInputShape(shape,0,0);
235           //actor->SetProperty(myProperty);
236           actor->SetShadingProperty(myProperty);
237           actor->SetWireframeProperty(myProperty);
238           actor->SetPreviewProperty(myProperty);
239           actor->PickableOff();
240           //         if ( shape.ShapeType() == TopAbs_EDGE )
241           //           actor->SubShapeOn();
242           myViewWindow->AddActor( actor );
243         }
244       }
245       return actor;
246     }
247     // -----------------------------------------------------------------------
248     void checkTriangulation(const TopoDS_Shape& shape)
249     {
250       TopLoc_Location aLoc;
251       Standard_Boolean alreadymesh = Standard_True;
252       TopExp_Explorer ex(shape, TopAbs_FACE);
253       if ( ex.More() )
254         for (; ex.More(); ex.Next()) {
255           const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
256           Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
257           if(aPoly.IsNull()) { alreadymesh = Standard_False; break; }
258         }
259       else
260         for (ex.Init(shape, TopAbs_EDGE); ex.More(); ex.Next()) {
261           const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
262           Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, aLoc);
263           if(aPoly.IsNull()) { alreadymesh = Standard_False; break; }
264         }
265       if (alreadymesh) return;
266       // Compute default deflection
267       Bnd_Box B;
268       BRepBndLib::Add(shape, B);
269       Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
270       B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
271       double deflection = Max( aXmax-aXmin , Max ( aYmax-aYmin , aZmax-aZmin)) * 0.01 *4;
272       BRepMesh_IncrementalMesh MESH(shape,deflection);
273     }
274   };
275
276   // =========================================================================================
277   /*!
278    * \brief Return text describing an error
279    */
280 #define CASE2TEXT(enum) case SMESH::enum: text = QObject::tr( #enum ); break;
281   QString errorText(int errCode, const char* comment)
282   {
283     QString text;
284     switch ( errCode ) {
285       CASE2TEXT( COMPERR_OK            );
286       CASE2TEXT( COMPERR_BAD_INPUT_MESH);
287       CASE2TEXT( COMPERR_STD_EXCEPTION );
288       CASE2TEXT( COMPERR_OCC_EXCEPTION );
289       CASE2TEXT( COMPERR_SLM_EXCEPTION );
290       CASE2TEXT( COMPERR_EXCEPTION     );
291       CASE2TEXT( COMPERR_MEMORY_PB     );
292       CASE2TEXT( COMPERR_BAD_SHAPE     );
293     case SMESH::COMPERR_ALGO_FAILED:
294       if ( strlen(comment) == 0 )
295         text = QObject::tr("COMPERR_ALGO_FAILED");
296       break;
297     default:
298       text = QString("#%1").arg( -errCode );
299     }
300     if ( text.length() > 0 ) text += ". ";
301     return text + comment;
302   }
303   // -----------------------------------------------------------------------
304   /*!
305    * \brief Return SO of a subshape
306    */
307   _PTR(SObject) getSubShapeSO( int subShapeID, GEOM::GEOM_Object_var aMainShape)
308   {
309     _PTR(SObject) so = SMESH::FindSObject(aMainShape);
310     if ( subShapeID == 1 || !so )
311       return so;
312     _PTR(ChildIterator) it;
313     if (_PTR(Study) study = SMESH::GetActiveStudyDocument())
314       it =  study->NewChildIterator(so);
315     _PTR(SObject) subSO;
316     if ( it ) {
317       for ( it->InitEx(true); !subSO && it->More(); it->Next() ) {
318         GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>( it->Value() );
319         if ( !geom->_is_nil() ) {
320           GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
321           if ( list->length() == 1 && list[0] == subShapeID )
322             subSO = it->Value();
323         }
324       }
325     }
326     return subSO;
327   }
328   // -----------------------------------------------------------------------
329   /*!
330    * \brief Return subshape by ID
331    */
332   GEOM::GEOM_Object_ptr getSubShape( int subShapeID, GEOM::GEOM_Object_var aMainShape)
333   {
334     GEOM::GEOM_Object_var aSubShape;
335     if ( subShapeID == 1 )
336       aSubShape = aMainShape;
337     else if ( _PTR(SObject) so = getSubShapeSO( subShapeID, aMainShape ))
338       aSubShape = SMESH::SObjectToInterface<GEOM::GEOM_Object>( so );
339     else
340       aSubShape = SMESH::GetSubShape( aMainShape, subShapeID );
341     return aSubShape._retn();
342   }
343   // -----------------------------------------------------------------------
344   /*!
345    * \brief Return shape type name
346    */
347 #define CASE2NAME(enum) case GEOM::enum: name = QObject::tr( "GEOM_" #enum ); break;
348   QString shapeTypeName(GEOM::GEOM_Object_var aShape, const char* dflt = "" )
349   {
350     QString name = dflt;
351     if ( !aShape->_is_nil() ) {
352       switch ( aShape->GetShapeType() ) {
353       CASE2NAME( VERTEX    );
354       CASE2NAME( EDGE      );
355       CASE2NAME( WIRE      );
356       CASE2NAME( FACE      );
357       CASE2NAME( SHELL     );
358       CASE2NAME( SOLID     );
359       CASE2NAME( COMPSOLID );
360       CASE2NAME( COMPOUND  );
361       default:;
362       }
363     }
364     return name;
365   }
366   // -----------------------------------------------------------------------
367   /*!
368    * \brief Return text describing a subshape
369    */
370   QString shapeText(int subShapeID, GEOM::GEOM_Object_var aMainShape )
371   {
372     QString text;
373     if ( _PTR(SObject) aSO = getSubShapeSO( subShapeID, aMainShape ))
374       text = aSO->GetName();
375     else {
376       text = QString("#%1").arg( subShapeID );
377       QString typeName = shapeTypeName( getSubShape( subShapeID, aMainShape ));
378       if ( typeName.length() )
379         text += QString(" (%1)").arg(typeName);
380     }
381     return text;
382   }
383 } // namespace SMESH
384
385
386 // =========================================================================================
387 /*!
388  * \brief Dialog to compute a mesh and show computation errors
389  */
390 //=======================================================================
391
392 SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg(): SMESHGUI_Dialog( 0, false, true, OK | Help )
393 {
394   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame(), 0, SPACING);
395
396   QFrame* aMainFrame = createMainFrame  (mainFrame());
397
398   aDlgLay->addWidget(aMainFrame);
399
400   aDlgLay->setStretchFactor(aMainFrame, 1);
401 }
402
403 //=======================================================================
404 // function : createMainFrame()
405 // purpose  : Create frame containing dialog's fields
406 //=======================================================================
407
408 #define CASE2HEADER(enum) case enum: header = QObject::tr( #enum "_HEADER" ); break;
409
410 QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent)
411 {
412   QFrame* aFrame = new QFrame(theParent);
413
414   SUIT_ResourceMgr* rm = resourceMgr();
415   QPixmap iconCompute (rm->loadPixmap("SMESH", tr("ICON_COMPUTE")));
416
417   // constructor
418
419   QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("CONSTRUCTOR"), aFrame);
420   aPixGrp->setExclusive(TRUE);
421   QRadioButton* aRBut = new QRadioButton(aPixGrp);
422   aRBut->setPixmap(iconCompute);
423   aRBut->setChecked(TRUE);
424
425   // Mesh Info
426
427   QGroupBox* infoGrp = new QGroupBox( 2, Qt::Horizontal,
428                                       tr("SMESH_MESHINFO_TITLE"), aFrame, "infoGrp" );
429   QLabel* nodeLabel = new QLabel(tr("SMESH_MESHINFO_NODES"), infoGrp );
430   myNbNodesLabel    = new QLabel("0", infoGrp );
431   QLabel* edgeLabel = new QLabel(tr("SMESH_MESHINFO_EDGES"), infoGrp );
432   myNbEdgesLabel    = new QLabel("0", infoGrp );
433   QLabel* faceLabel = new QLabel(tr("SMESH_MESHINFO_FACES"), infoGrp);
434   myNbFacesLabel    = new QLabel("0", infoGrp );
435   QLabel* volumeLbl = new QLabel(tr("SMESH_MESHINFO_VOLUMES"), infoGrp);
436   myNbVolumLabel    = new QLabel("0", infoGrp );
437
438   // errors
439
440   QGroupBox* errorGrp = new QGroupBox(tr("ERRORS"), aFrame, "errorGrBox");
441   myTable      = new QTable( 1, NB_COLUMNS, errorGrp, "myTable");
442   myShowBtn    = new QPushButton(tr("SHOW_SHAPE"), errorGrp, "myShowBtn");
443   myPublishBtn = new QPushButton(tr("PUBLISH_SHAPE"), errorGrp, "myPublishBtn");
444
445   myTable->setReadOnly( TRUE );
446   myTable->hideColumn( COL_PUBLISHED );
447   myTable->hideColumn( COL_SHAPEID );
448   myTable->setColumnStretchable( COL_ERROR, 1 );
449   for ( int col = 0; col < NB_COLUMNS; ++col ) {
450     QString header;
451     switch ( col ) {
452     CASE2HEADER( COL_ALGO     );
453     CASE2HEADER( COL_SHAPE    );
454     CASE2HEADER( COL_ERROR    );
455     CASE2HEADER( COL_SHAPEID  );
456     CASE2HEADER( COL_PUBLISHED);
457     }
458     myTable->horizontalHeader()->setLabel( col, header );
459   }
460
461   errorGrp->setColumnLayout(0, Qt::Vertical);
462   errorGrp->layout()->setSpacing(0);
463   errorGrp->layout()->setMargin(0);
464   QGridLayout* grpLayout = new QGridLayout(errorGrp->layout());
465   grpLayout->setAlignment(Qt::AlignTop);
466   grpLayout->setSpacing(SPACING);
467   grpLayout->setMargin(MARGIN);
468   grpLayout->addMultiCellWidget( myTable,   0, 2, 0, 0 );
469   grpLayout->addWidget         ( myShowBtn,    0, 1 );
470   grpLayout->addWidget         ( myPublishBtn, 1, 1 );
471   grpLayout->setRowStretch( 2, 1 );
472
473   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
474   aLay->addWidget( aPixGrp );
475   aLay->addWidget( infoGrp );
476   aLay->addWidget( errorGrp );
477   aLay->setStretchFactor( errorGrp, 1 );
478
479   return aFrame;
480 }
481 //================================================================================
482 /*!
483  * \brief Show mesh info
484  */
485 //================================================================================
486
487 void SMESHGUI_ComputeDlg::SetMeshInfo(int nbNodes, int nbEdges, int nbFaces, int nbVolums)
488 {
489   myNbNodesLabel->setText(QString("%1").arg(nbNodes));
490   myNbEdgesLabel->setText(QString("%1").arg(nbEdges));
491   myNbFacesLabel->setText(QString("%1").arg(nbFaces));
492   myNbVolumLabel->setText(QString("%1").arg(nbVolums));
493 }
494
495 //================================================================================
496 /*!
497  * \brief Constructor
498 */
499 //================================================================================
500
501 SMESHGUI_ComputeOp::SMESHGUI_ComputeOp()
502 {
503   myDlg = new SMESHGUI_ComputeDlg;
504   myTShapeDisplayer = new TShapeDisplayer();
505
506   // connect signals and slots
507   connect(myDlg->myShowBtn,    SIGNAL (clicked()), SLOT(onPreviewShape()));
508   connect(myDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape()));
509   connect(table(),SIGNAL(selectionChanged()), SLOT(currentCellChanged()));
510 }
511
512 //=======================================================================
513 // function : startOperation()
514 // purpose  : Init dialog fields, connect signals and slots, show dialog
515 //=======================================================================
516
517 void SMESHGUI_ComputeOp::startOperation()
518 {
519   SMESHGUI_Operation::startOperation();
520
521   SMESH::SMESH_Mesh_var          aMesh;
522   SMESH::compute_error_array_var anErrors;
523
524   myMainShape = GEOM::GEOM_Object::_nil();
525
526   // COMPUTE MESH
527
528   bool computeFailed = true;
529   int nbNodes = 0, nbEdges = 0, nbFaces = 0, nbVolums = 0;
530
531   LightApp_SelectionMgr *Sel = selectionMgr();
532   SALOME_ListIO selected; Sel->selectedObjects( selected );
533
534   int nbSel = selected.Extent();
535   if (nbSel != 1) {
536     SUIT_MessageBox::warn1(desktop(),
537                            tr("SMESH_WRN_WARNING"),
538                            tr("SMESH_WRN_NO_AVAILABLE_DATA"),
539                            tr("SMESH_BUT_OK"));
540     onCancel();
541     return;
542   }
543
544   Handle(SALOME_InteractiveObject) IObject = selected.First();
545   aMesh = SMESH::GetMeshByIO(IObject);
546   if (!aMesh->_is_nil()) {
547     myMainShape = aMesh->GetShapeToMesh();
548     if ( !myMainShape->_is_nil() ) {
549       SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
550       SMESH::algo_error_array_var errors = gen->GetAlgoState(aMesh,myMainShape);
551       if ( errors->length() > 0 ) {
552         SUIT_MessageBox::warn1(desktop(), tr("SMESH_WRN_WARNING"),
553                                SMESH::GetMessageOnAlgoStateErrors( errors.in() ),
554                                tr("SMESH_BUT_OK"));
555         onCancel();
556         return;
557       }
558       try {
559         if (gen->Compute(aMesh, myMainShape)) {
560           computeFailed = false;
561         }
562         else {
563           anErrors = gen->GetComputeErrors( aMesh, myMainShape );
564 //           if ( anErrors->length() == 0 ) {
565 //             SUIT_MessageBox::warn1(desktop(),
566 //                                    tr("SMESH_WRN_WARNING"),
567 //                                    tr("SMESH_WRN_COMPUTE_FAILED"),
568 //                                    tr("SMESH_BUT_OK"));
569 //             onCancel();
570 //             return;
571 //           }
572         }
573         nbNodes = aMesh->NbNodes();
574         nbEdges = aMesh->NbEdges();
575         nbFaces = aMesh->NbFaces();
576         nbVolums = aMesh->NbVolumes();
577         _PTR(SObject) aMeshSObj = SMESH::FindSObject(aMesh);
578         SMESH::ModifiedMesh(aMeshSObj, !computeFailed, nbNodes == 0);
579       }
580       catch(const SALOME::SALOME_Exception & S_ex){
581         SalomeApp_Tools::QtCatchCorbaException(S_ex);
582       }
583       update( UF_ObjBrowser | UF_Model );
584
585       if ( getSMESHGUI()->automaticUpdate() ) {
586         SVTK_ViewWindow* aVTKView = SMESH::GetViewWindow(getSMESHGUI(), true);
587         if (aVTKView) {
588           int anId = study()->id();
589           TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId, IObject->getEntry());
590           if (aVisualObj) {
591             aVisualObj->Update();
592             SMESH_Actor* anActor = SMESH::FindActorByEntry(IObject->getEntry());
593             if (!anActor) {
594               anActor = SMESH::CreateActor(studyDS(), IObject->getEntry());
595               if (anActor) {
596                 SMESH::DisplayActor(aVTKView, anActor); //apo
597                 SMESH::FitAll();
598               }
599             }
600             SMESH::RepaintCurrentView();
601             Sel->setSelectedObjects( selected );
602           }
603         }
604       }
605     }
606   }
607
608   // SHOW Mesh Infos
609
610   myDlg->SetMeshInfo( nbNodes, nbEdges, nbFaces, nbVolums);
611   myDlg->setCaption(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED"));
612
613   // SHOW ERRORS
614
615   bool noError = ( !anErrors.operator->() || anErrors->length() == 0 );
616
617   QTable* tbl = myDlg->myTable;
618
619   if ( noError )
620   {
621     tbl->setNumRows(0);
622   }
623   else
624   {
625     // fill table of errors
626     tbl->setNumRows( anErrors->length() );
627     bool hasShape = aMesh->HasShapeToMesh();
628     if ( !hasShape ) tbl->hideColumn( COL_SHAPE );
629     else             tbl->showColumn( COL_SHAPE );
630     tbl->setColumnWidth( COL_ERROR, 200 );
631
632     for ( int row = 0; row < anErrors->length(); ++row )
633     {
634       SMESH::ComputeError & err = anErrors[ row ];
635       tbl->setText( row, COL_ALGO,    err.algoName.in() );
636       tbl->setText( row, COL_ERROR,   errorText( err.code, err.comment.in() ));
637       tbl->setText( row, COL_SHAPEID, QString("%1").arg( err.subShapeID ));
638
639       QString text = hasShape ? shapeText( err.subShapeID, myMainShape ) : QString("");
640       tbl->setText( row, COL_SHAPE,   text );
641
642       text = ( !hasShape || getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : "";
643       tbl->setText( row, COL_PUBLISHED, text ); // if text=="", "PUBLISH" button enabled
644
645       tbl->item( row, COL_ERROR )->setWordWrap( TRUE );
646       tbl->adjustRow( row );
647     }
648     tbl->adjustColumn( COL_ALGO );
649     tbl->adjustColumn( COL_SHAPE );
650
651     tbl->setCurrentCell(0,0);
652     currentCellChanged(); // to update buttons
653   }
654
655   myDlg->show();
656 }
657
658 //================================================================================
659 /*!
660  * \brief Stops operation
661  */
662 //================================================================================
663
664 void SMESHGUI_ComputeOp::stopOperation()
665 {
666   SMESHGUI_Operation::stopOperation();
667   myTShapeDisplayer->SetVisibility( false );
668 }
669
670 //================================================================================
671 /*!
672  * \brief publish selected subshape
673  */
674 //================================================================================
675
676 void SMESHGUI_ComputeOp::onPublishShape()
677 {
678   GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
679   SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
680
681   int nbSel = table()->numSelections();
682   for ( int i = 0; i < nbSel; ++i ) {
683     QTableSelection selected = table()->selection(i);
684     if ( !selected.isActive() ) continue;
685     for ( int row = selected.topRow(); row <= selected.bottomRow(); ++row )
686     {
687       bool isPublished = ( !table()->text(row, COL_PUBLISHED).isEmpty() );
688       if ( !isPublished ) {
689         int curSub = table()->text(row, COL_SHAPEID).toInt();
690         GEOM::GEOM_Object_var shape = getSubShape( curSub, myMainShape );
691         if ( !shape->_is_nil() && ! getSubShapeSO( curSub, myMainShape ))
692         {
693           QString name = GEOMBase::GetDefaultName( shapeTypeName( shape, "ERROR_SHAPE" ));
694           SALOMEDS::SObject_var so = geomGen->AddInStudy( study, shape, name, myMainShape);
695           if ( !so->_is_nil() ) {
696             table()->setText( row, COL_SHAPE, so->GetName() );
697             table()->setText( row, COL_PUBLISHED, so->GetID() );
698           }
699         }
700       }
701     }
702   }
703   getSMESHGUI()->getApp()->updateObjectBrowser();
704   currentCellChanged(); // to update buttons
705 }
706
707 //================================================================================
708 /*!
709  * \brief SLOT called when a selected cell in table() changed
710  */
711 //================================================================================
712
713 void SMESHGUI_ComputeOp::currentCellChanged()
714 {
715   myTShapeDisplayer->SetVisibility( false );
716
717   bool publishEnable = 0, showEnable = 0, showOnly = 1;
718   int nbSel = table()->numSelections();
719   for ( int i = 0; i < nbSel; ++i )
720   {
721     QTableSelection selected = table()->selection(i);
722     if ( !selected.isActive() ) continue;
723     for ( int row = selected.topRow(); row <= selected.bottomRow(); ++row )
724     {
725       bool hasData     = ( !table()->text(row, COL_SHAPE).isEmpty() );
726       bool isPublished = ( !table()->text(row, COL_PUBLISHED).isEmpty() );
727       if ( hasData && !isPublished )
728         publishEnable = true;
729
730       int curSub = table()->text(row, COL_SHAPEID).toInt();
731       bool prsReady = myTShapeDisplayer->HasReadyActorsFor( curSub, myMainShape );
732       if ( prsReady ) {
733         myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
734         showOnly = false;
735       }
736       else {
737         showEnable = true;
738       }
739     }
740   }
741   myDlg->myPublishBtn->setEnabled( publishEnable );
742   myDlg->myShowBtn->setEnabled( showEnable );
743 }
744
745 //================================================================================
746 /*!
747  * \brief update preview
748  */
749 //================================================================================
750
751 void SMESHGUI_ComputeOp::onPreviewShape()
752 {
753   if ( myTShapeDisplayer )
754   {
755     SUIT_OverrideCursor aWaitCursor;
756     bool showOnly = true;
757     int nbSel = table()->numSelections();
758     for ( int i = 0; i < nbSel; ++i )
759     {
760       QTableSelection selected = table()->selection(i);
761       if ( !selected.isActive() ) continue;
762       for ( int row = selected.topRow(); row <= selected.bottomRow(); ++row )
763       {
764         int curSub = table()->text(row, COL_SHAPEID).toInt();
765         if ( curSub > 0 ) {
766           myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
767           showOnly = false;
768         }
769       }
770     }
771     currentCellChanged(); // to update buttons
772   }
773 }
774
775 //================================================================================
776 /*!
777  * \brief Destructor
778 */
779 //================================================================================
780
781 SMESHGUI_ComputeOp::~SMESHGUI_ComputeOp()
782 {
783   if ( myTShapeDisplayer ) delete myTShapeDisplayer;
784 }
785
786 //================================================================================
787 /*!
788  * \brief Gets dialog of this operation
789  * \retval LightApp_Dialog* - pointer to dialog of this operation
790  */
791 //================================================================================
792
793 LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const
794 {
795   return myDlg;
796 }
797
798 //================================================================================
799 /*!
800  * \brief perform it's intention action: compute mesh
801  */
802 //================================================================================
803
804 bool SMESHGUI_ComputeOp::onApply()
805 {
806   return true;
807 }
808
809 //================================================================================
810 /*!
811  * \brief Return a table
812  */
813 //================================================================================
814
815 QTable* SMESHGUI_ComputeOp::table()
816 {
817   return myDlg->myTable;
818 }