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 "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   // -----------------------------------------------------------------------
397   /*!
398    * \brief Return text describing a subshape
399    */
400   bool getSelectedRows(QTable* table, list< int > & rows)
401   {
402     rows.clear();
403     int nbSel = table->numSelections();
404     for ( int i = 0; i < nbSel; ++i )
405     {
406       QTableSelection selected = table->selection(i);
407       if ( !selected.isActive() ) continue;
408       for ( int row = selected.topRow(); row <= selected.bottomRow(); ++row )
409         rows.push_back( row );
410     }
411     return !rows.empty();
412   }
413   
414 } // namespace SMESH
415
416
417 // =========================================================================================
418 /*!
419  * \brief Dialog to compute a mesh and show computation errors
420  */
421 //=======================================================================
422
423 SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg(): SMESHGUI_Dialog( 0, false, true, OK | Help )
424 {
425   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame(), 0, SPACING);
426
427   QFrame* aMainFrame = createMainFrame  (mainFrame());
428
429   aDlgLay->addWidget(aMainFrame);
430
431   aDlgLay->setStretchFactor(aMainFrame, 1);
432 }
433
434 //=======================================================================
435 // function : createMainFrame()
436 // purpose  : Create frame containing dialog's fields
437 //=======================================================================
438
439 #define CASE2HEADER(enum) case enum: header = QObject::tr( #enum "_HEADER" ); break;
440
441 QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent)
442 {
443   QFrame* aFrame = new QFrame(theParent);
444
445   SUIT_ResourceMgr* rm = resourceMgr();
446   QPixmap iconCompute (rm->loadPixmap("SMESH", tr("ICON_COMPUTE")));
447
448   // constructor
449
450   QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("CONSTRUCTOR"), aFrame);
451   aPixGrp->setExclusive(TRUE);
452   QRadioButton* aRBut = new QRadioButton(aPixGrp);
453   aRBut->setPixmap(iconCompute);
454   aRBut->setChecked(TRUE);
455
456   // Mesh Info
457
458   QGroupBox* infoGrp = new QGroupBox( 2, Qt::Horizontal,
459                                       tr("SMESH_MESHINFO_TITLE"), aFrame, "infoGrp" );
460   QLabel* nodeLabel = new QLabel(tr("SMESH_MESHINFO_NODES"), infoGrp );
461   myNbNodesLabel    = new QLabel("0", infoGrp );
462   QLabel* edgeLabel = new QLabel(tr("SMESH_MESHINFO_EDGES"), infoGrp );
463   myNbEdgesLabel    = new QLabel("0", infoGrp );
464   QLabel* faceLabel = new QLabel(tr("SMESH_MESHINFO_FACES"), infoGrp);
465   myNbFacesLabel    = new QLabel("0", infoGrp );
466   QLabel* volumeLbl = new QLabel(tr("SMESH_MESHINFO_VOLUMES"), infoGrp);
467   myNbVolumLabel    = new QLabel("0", infoGrp );
468
469   // errors
470
471   QGroupBox* errorGrp = new QGroupBox(tr("ERRORS"), aFrame, "errorGrBox");
472   myTable      = new QTable( 1, NB_COLUMNS, errorGrp, "myTable");
473   myShowBtn    = new QPushButton(tr("SHOW_SHAPE"), errorGrp, "myShowBtn");
474   myPublishBtn = new QPushButton(tr("PUBLISH_SHAPE"), errorGrp, "myPublishBtn");
475
476   myTable->setReadOnly( TRUE );
477   myTable->hideColumn( COL_PUBLISHED );
478   myTable->hideColumn( COL_SHAPEID );
479   myTable->setColumnStretchable( COL_ERROR, 1 );
480   for ( int col = 0; col < NB_COLUMNS; ++col ) {
481     QString header;
482     switch ( col ) {
483     CASE2HEADER( COL_ALGO     );
484     CASE2HEADER( COL_SHAPE    );
485     CASE2HEADER( COL_ERROR    );
486     CASE2HEADER( COL_SHAPEID  );
487     CASE2HEADER( COL_PUBLISHED);
488     }
489     myTable->horizontalHeader()->setLabel( col, header );
490   }
491
492   errorGrp->setColumnLayout(0, Qt::Vertical);
493   errorGrp->layout()->setSpacing(0);
494   errorGrp->layout()->setMargin(0);
495   QGridLayout* grpLayout = new QGridLayout(errorGrp->layout());
496   grpLayout->setAlignment(Qt::AlignTop);
497   grpLayout->setSpacing(SPACING);
498   grpLayout->setMargin(MARGIN);
499   grpLayout->addMultiCellWidget( myTable,   0, 2, 0, 0 );
500   grpLayout->addWidget         ( myShowBtn,    0, 1 );
501   grpLayout->addWidget         ( myPublishBtn, 1, 1 );
502   grpLayout->setRowStretch( 2, 1 );
503
504   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
505   aLay->addWidget( aPixGrp );
506   aLay->addWidget( infoGrp );
507   aLay->addWidget( errorGrp );
508   aLay->setStretchFactor( errorGrp, 1 );
509
510   return aFrame;
511 }
512 //================================================================================
513 /*!
514  * \brief Show mesh info
515  */
516 //================================================================================
517
518 void SMESHGUI_ComputeDlg::SetMeshInfo(int nbNodes, int nbEdges, int nbFaces, int nbVolums)
519 {
520   myNbNodesLabel->setText(QString("%1").arg(nbNodes));
521   myNbEdgesLabel->setText(QString("%1").arg(nbEdges));
522   myNbFacesLabel->setText(QString("%1").arg(nbFaces));
523   myNbVolumLabel->setText(QString("%1").arg(nbVolums));
524 }
525
526 //================================================================================
527 /*!
528  * \brief Constructor
529 */
530 //================================================================================
531
532 SMESHGUI_ComputeOp::SMESHGUI_ComputeOp()
533 {
534   myDlg = new SMESHGUI_ComputeDlg;
535   myTShapeDisplayer = new TShapeDisplayer();
536
537   // connect signals and slots
538   connect(myDlg->myShowBtn,    SIGNAL (clicked()), SLOT(onPreviewShape()));
539   connect(myDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape()));
540   connect(table(),SIGNAL(selectionChanged()), SLOT(currentCellChanged()));
541 }
542
543 //=======================================================================
544 // function : startOperation()
545 // purpose  : Init dialog fields, connect signals and slots, show dialog
546 //=======================================================================
547
548 void SMESHGUI_ComputeOp::startOperation()
549 {
550   SMESHGUI_Operation::startOperation();
551
552   SMESH::SMESH_Mesh_var          aMesh;
553   SMESH::compute_error_array_var anErrors;
554
555   myMainShape = GEOM::GEOM_Object::_nil();
556
557   // COMPUTE MESH
558
559   bool computeFailed = true;
560   int nbNodes = 0, nbEdges = 0, nbFaces = 0, nbVolums = 0;
561
562   LightApp_SelectionMgr *Sel = selectionMgr();
563   SALOME_ListIO selected; Sel->selectedObjects( selected );
564
565   int nbSel = selected.Extent();
566   if (nbSel != 1) {
567     SUIT_MessageBox::warn1(desktop(),
568                            tr("SMESH_WRN_WARNING"),
569                            tr("SMESH_WRN_NO_AVAILABLE_DATA"),
570                            tr("SMESH_BUT_OK"));
571     onCancel();
572     return;
573   }
574
575   Handle(SALOME_InteractiveObject) IObject = selected.First();
576   aMesh = SMESH::GetMeshByIO(IObject);
577   if (!aMesh->_is_nil()) {
578     myMainShape = aMesh->GetShapeToMesh();
579     if ( !myMainShape->_is_nil() ) {
580       SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
581       SMESH::algo_error_array_var errors = gen->GetAlgoState(aMesh,myMainShape);
582       if ( errors->length() > 0 ) {
583         SUIT_MessageBox::warn1(desktop(), tr("SMESH_WRN_WARNING"),
584                                SMESH::GetMessageOnAlgoStateErrors( errors.in() ),
585                                tr("SMESH_BUT_OK"));
586         onCancel();
587         return;
588       }
589       try {
590         if (gen->Compute(aMesh, myMainShape)) {
591           computeFailed = false;
592         }
593         else {
594           anErrors = gen->GetComputeErrors( aMesh, myMainShape );
595 //           if ( anErrors->length() == 0 ) {
596 //             SUIT_MessageBox::warn1(desktop(),
597 //                                    tr("SMESH_WRN_WARNING"),
598 //                                    tr("SMESH_WRN_COMPUTE_FAILED"),
599 //                                    tr("SMESH_BUT_OK"));
600 //             onCancel();
601 //             return;
602 //           }
603         }
604         nbNodes = aMesh->NbNodes();
605         nbEdges = aMesh->NbEdges();
606         nbFaces = aMesh->NbFaces();
607         nbVolums = aMesh->NbVolumes();
608         _PTR(SObject) aMeshSObj = SMESH::FindSObject(aMesh);
609         SMESH::ModifiedMesh(aMeshSObj, !computeFailed, nbNodes == 0);
610       }
611       catch(const SALOME::SALOME_Exception & S_ex){
612         SalomeApp_Tools::QtCatchCorbaException(S_ex);
613       }
614       update( UF_ObjBrowser | UF_Model );
615
616       if ( getSMESHGUI()->automaticUpdate() ) {
617         SVTK_ViewWindow* aVTKView = SMESH::GetViewWindow(getSMESHGUI(), true);
618         if (aVTKView) {
619           int anId = study()->id();
620           TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId, IObject->getEntry());
621           if (aVisualObj) {
622             aVisualObj->Update();
623             SMESH_Actor* anActor = SMESH::FindActorByEntry(IObject->getEntry());
624             if (!anActor) {
625               anActor = SMESH::CreateActor(studyDS(), IObject->getEntry());
626               if (anActor) {
627                 SMESH::DisplayActor(aVTKView, anActor); //apo
628                 SMESH::FitAll();
629               }
630             }
631             SMESH::RepaintCurrentView();
632             Sel->setSelectedObjects( selected );
633           }
634         }
635       }
636     }
637   }
638
639   // SHOW Mesh Infos
640
641   myDlg->SetMeshInfo( nbNodes, nbEdges, nbFaces, nbVolums);
642   myDlg->setCaption(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED"));
643
644   // SHOW ERRORS
645
646   bool noError = ( !anErrors.operator->() || anErrors->length() == 0 );
647
648   QTable* tbl = myDlg->myTable;
649
650   if ( noError )
651   {
652     tbl->setNumRows(0);
653   }
654   else
655   {
656     // fill table of errors
657     tbl->setNumRows( anErrors->length() );
658     bool hasShape = aMesh->HasShapeToMesh();
659     if ( !hasShape ) tbl->hideColumn( COL_SHAPE );
660     else             tbl->showColumn( COL_SHAPE );
661     tbl->setColumnWidth( COL_ERROR, 200 );
662
663     for ( int row = 0; row < anErrors->length(); ++row )
664     {
665       SMESH::ComputeError & err = anErrors[ row ];
666       tbl->setText( row, COL_ALGO,    err.algoName.in() );
667       tbl->setText( row, COL_ERROR,   errorText( err.code, err.comment.in() ));
668       tbl->setText( row, COL_SHAPEID, QString("%1").arg( err.subShapeID ));
669
670       QString text = hasShape ? shapeText( err.subShapeID, myMainShape ) : QString("");
671       tbl->setText( row, COL_SHAPE,   text );
672
673       text = ( !hasShape || getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : "";
674       tbl->setText( row, COL_PUBLISHED, text ); // if text=="", "PUBLISH" button enabled
675
676       tbl->item( row, COL_ERROR )->setWordWrap( TRUE );
677       tbl->adjustRow( row );
678     }
679     tbl->adjustColumn( COL_ALGO );
680     tbl->adjustColumn( COL_SHAPE );
681
682     tbl->setCurrentCell(0,0);
683     currentCellChanged(); // to update buttons
684   }
685
686   myDlg->show();
687 }
688
689 //================================================================================
690 /*!
691  * \brief Stops operation
692  */
693 //================================================================================
694
695 void SMESHGUI_ComputeOp::stopOperation()
696 {
697   SMESHGUI_Operation::stopOperation();
698   myTShapeDisplayer->SetVisibility( false );
699 }
700
701 //================================================================================
702 /*!
703  * \brief publish selected subshape
704  */
705 //================================================================================
706
707 void SMESHGUI_ComputeOp::onPublishShape()
708 {
709   GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
710   SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
711
712   list< int > rows;
713   list< int >::iterator row;
714   getSelectedRows( table(), rows );
715   for ( row = rows.begin(); row != rows.end(); ++row )
716   {
717     int curSub = table()->text(*row, COL_SHAPEID).toInt();
718     GEOM::GEOM_Object_var shape = getSubShape( curSub, myMainShape );
719     if ( !shape->_is_nil() && ! getSubShapeSO( curSub, myMainShape ))
720     {
721       if ( !getSubShapeSO( 1, myMainShape )) // the main shape not published
722       {
723         QString name = GEOMBase::GetDefaultName( shapeTypeName( myMainShape, "MAIN_SHAPE" ));
724         SALOMEDS::SObject_var so =
725           geomGen->AddInStudy( study, myMainShape, name, GEOM::GEOM_Object::_nil());
726         // look for myMainShape in the table
727         for ( int r = 0, nr = table()->numRows(); r < nr; ++r ) {
728           if ( table()->text(r, COL_SHAPEID) == "1" ) {
729             if ( so->_is_nil() ) {
730               table()->setText( r, COL_SHAPE, so->GetName() );
731               table()->setText( r, COL_PUBLISHED, so->GetID() );
732             }
733             break;
734           }
735         }
736         if ( curSub == 1 ) continue;
737       }
738       QString name = GEOMBase::GetDefaultName( shapeTypeName( shape, "ERROR_SHAPE" ));
739       SALOMEDS::SObject_var so = geomGen->AddInStudy( study, shape, name, myMainShape);
740       if ( !so->_is_nil() ) {
741         table()->setText( *row, COL_SHAPE, so->GetName() );
742         table()->setText( *row, COL_PUBLISHED, so->GetID() );
743       }
744     }
745   }
746   getSMESHGUI()->getApp()->updateObjectBrowser();
747   currentCellChanged(); // to update buttons
748 }
749
750 //================================================================================
751 /*!
752  * \brief SLOT called when a selected cell in table() changed
753  */
754 //================================================================================
755
756 void SMESHGUI_ComputeOp::currentCellChanged()
757 {
758   myTShapeDisplayer->SetVisibility( false );
759
760   bool publishEnable = 0, showEnable = 0, showOnly = 1;
761   list< int > rows;
762   list< int >::iterator row;
763   getSelectedRows( table(), rows );
764   for ( row = rows.begin(); row != rows.end(); ++row )
765   {
766     bool hasData     = ( !table()->text(*row, COL_SHAPE).isEmpty() );
767     bool isPublished = ( !table()->text(*row, COL_PUBLISHED).isEmpty() );
768     if ( hasData && !isPublished )
769       publishEnable = true;
770
771     int curSub = table()->text(*row, COL_SHAPEID).toInt();
772     bool prsReady = myTShapeDisplayer->HasReadyActorsFor( curSub, myMainShape );
773     if ( prsReady ) {
774       myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
775       showOnly = false;
776     }
777     else {
778       showEnable = true;
779     }
780   }
781   myDlg->myPublishBtn->setEnabled( publishEnable );
782   myDlg->myShowBtn->setEnabled( showEnable );
783 }
784
785 //================================================================================
786 /*!
787  * \brief update preview
788  */
789 //================================================================================
790
791 void SMESHGUI_ComputeOp::onPreviewShape()
792 {
793   if ( myTShapeDisplayer )
794   {
795     SUIT_OverrideCursor aWaitCursor;
796     list< int > rows;
797     list< int >::iterator row;
798     getSelectedRows( table(), rows );
799
800     bool showOnly = true;
801     for ( row = rows.begin(); row != rows.end(); ++row )
802     {
803       int curSub = table()->text(*row, COL_SHAPEID).toInt();
804       if ( curSub > 0 ) {
805         myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
806         showOnly = false;
807       }
808     }
809     currentCellChanged(); // to update buttons
810   }
811 }
812
813 //================================================================================
814 /*!
815  * \brief Destructor
816  */
817 //================================================================================
818
819 SMESHGUI_ComputeOp::~SMESHGUI_ComputeOp()
820 {
821   if ( myTShapeDisplayer ) delete myTShapeDisplayer;
822 }
823
824 //================================================================================
825 /*!
826  * \brief Gets dialog of this operation
827  * \retval LightApp_Dialog* - pointer to dialog of this operation
828  */
829 //================================================================================
830
831 LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const
832 {
833   return myDlg;
834 }
835
836 //================================================================================
837 /*!
838  * \brief perform it's intention action: compute mesh
839  */
840 //================================================================================
841
842 bool SMESHGUI_ComputeOp::onApply()
843 {
844   return true;
845 }
846
847 //================================================================================
848 /*!
849  * \brief Return a table
850  */
851 //================================================================================
852
853 QTable* SMESHGUI_ComputeOp::table()
854 {
855   return myDlg->myTable;
856 }