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