Salome HOME
3d9a35d8bb6f1c7f14cf4f4c909b5c692d121e46
[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 #include <qhbox.h>
79 #include <qhgroupbox.h>
80
81 #include <vtkProperty.h>
82
83 // IDL Headers
84 #include <SALOMEconfig.h>
85 #include CORBA_SERVER_HEADER(SMESH_Gen)
86 #include CORBA_SERVER_HEADER(SMESH_Mesh)
87
88 #include <vector>
89 #include <set>
90
91
92 #define SPACING 5
93 #define MARGIN  10
94
95 #define COLONIZE(str)   (QString(str).contains(":") > 0 ? QString(str) : QString(str) + " :" )
96
97 #define _SEPARATOR(father) \
98 {\
99   /*new QLabel(father); new QLabel(father); new QLabel(father)*/;\
100   (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\
101   (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\
102   (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\
103   (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\
104 }
105
106 enum TCol { COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, NB_COLUMNS };
107
108 using namespace SMESH;
109
110 namespace SMESH {
111   
112   // =========================================================================================
113   /*!
114    * \brief Class showing shapes without publishing
115    */
116   // =========================================================================================
117
118   class TShapeDisplayer
119   {
120   public:
121     // -----------------------------------------------------------------------
122     TShapeDisplayer(): myViewWindow(0)
123     {
124       myProperty = vtkProperty::New();
125       myProperty->SetRepresentationToWireframe();
126       myProperty->SetColor( 250, 0, 250 );
127       myProperty->SetAmbientColor( 250, 0, 250 );
128       myProperty->SetDiffuseColor( 250, 0, 250 );
129       //myProperty->SetSpecularColor( 250, 0, 250 );
130       myProperty->SetLineWidth( 5 );
131     }
132     // -----------------------------------------------------------------------
133     ~TShapeDisplayer()
134     {
135       DeleteActors();
136       myProperty->Delete();
137     }
138     // -----------------------------------------------------------------------
139     void DeleteActors()
140     {
141       if ( hasViewWindow() ) {
142         TActorIterator actorIt = actorIterator();
143         while ( actorIt.more() )
144           if (VTKViewer_Actor* anActor = actorIt.next()) {
145             myViewWindow->RemoveActor( anActor );
146             //anActor->Delete();
147           }
148       }
149       myIndexToShape.Clear();
150       myActors.clear();
151       myShownActors.clear();
152       myBuiltSubs.clear();
153     }
154     // -----------------------------------------------------------------------
155     void SetVisibility (bool theVisibility)
156     {
157       TActorIterator actorIt = shownIterator();
158       while ( actorIt.more() )
159         if (VTKViewer_Actor* anActor = actorIt.next())
160           anActor->SetVisibility(theVisibility);
161       SMESH::RepaintCurrentView();
162     }
163     // -----------------------------------------------------------------------
164     bool HasReadyActorsFor (int subShapeID, GEOM::GEOM_Object_var aMainShape )
165     {
166       string mainEntry;
167       if ( !aMainShape->_is_nil() )
168         mainEntry = aMainShape->GetStudyEntry();
169       return ( myMainEntry == mainEntry &&
170                myBuiltSubs.find( subShapeID ) != myBuiltSubs.end() );
171     }
172     // -----------------------------------------------------------------------
173     void Show( int subShapeID, GEOM::GEOM_Object_var aMainShape, bool only = false)
174     {
175       SVTK_ViewWindow* aViewWindow  = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() );
176       string mainEntry;
177       if ( !aMainShape->_is_nil() )
178         mainEntry = aMainShape->GetStudyEntry();
179       if ( myMainEntry != mainEntry || aViewWindow != myViewWindow ) { // remove actors
180         DeleteActors();
181         TopoDS_Shape aShape;
182         if ( !aMainShape->_is_nil() && GEOMBase::GetShape(aMainShape, aShape)) {
183           checkTriangulation( aShape );
184           TopExp::MapShapes(aShape, myIndexToShape);
185           myActors.resize( myIndexToShape.Extent(), 0 );
186           myShownActors.reserve( myIndexToShape.Extent() );
187         }
188         myMainEntry  = mainEntry;
189         myViewWindow = aViewWindow;
190       }
191       if ( only ) { // hide shown actors
192         TActorIterator actorIt = shownIterator();
193         while ( actorIt.more() )
194           if (VTKViewer_Actor* anActor = actorIt.next())
195             anActor->SetVisibility(false);
196         myShownActors.clear();
197       }
198       // find actors to show
199       TopoDS_Shape aShape = myIndexToShape( subShapeID );
200       if ( !aShape.IsNull() ) {
201         TopAbs_ShapeEnum type( aShape.ShapeType() >= TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE );
202         for ( TopExp_Explorer exp( aShape, type ); exp.More(); exp.Next() ) {
203           //checkTriangulation( exp.Current() );
204           if ( GEOM_Actor* anActor = getActor( exp.Current() ))
205             myShownActors.push_back( anActor );
206         }
207         if ( type == TopAbs_FACE ) {
208           for ( TopExp_Explorer exp( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) {
209             const TopoDS_Edge & edge = TopoDS::Edge( exp.Current() );
210             if ( !BRep_Tool::Degenerated( edge ))
211               if ( GEOM_Actor* anActor = getActor( exp.Current() ))
212                 myShownActors.push_back( anActor );
213           }
214         }
215       }
216       myBuiltSubs.insert( subShapeID );
217       SetVisibility(true);
218     }
219     // -----------------------------------------------------------------------
220
221   private:
222
223     typedef std::vector<GEOM_Actor*> TActorVec;
224     TActorVec                  myActors;
225     TActorVec                  myShownActors;
226     TopTools_IndexedMapOfShape myIndexToShape;
227     string                     myMainEntry;
228     SVTK_ViewWindow*           myViewWindow;
229     vtkProperty*               myProperty;
230     std::set<int>              myBuiltSubs;
231
232     // -----------------------------------------------------------------------
233     typedef SMDS_SetIterator< GEOM_Actor*, TActorVec::const_iterator> TActorIterator;
234     TActorIterator actorIterator() {
235       return TActorIterator( myActors.begin(), myActors.end() );
236     }
237     TActorIterator shownIterator() {
238       return TActorIterator( myShownActors.begin(), myShownActors.end() );
239     }
240     // -----------------------------------------------------------------------
241     GEOM_Actor* getActor(const TopoDS_Shape& shape)
242     {
243       int index = myIndexToShape.FindIndex( shape ) - 1;
244       if ( index < 0 || index >= myActors.size() )
245         return 0;
246       GEOM_Actor* & actor = myActors[ index ];
247       if ( !actor ) {
248         actor = GEOM_Actor::New();
249         if ( actor ) {
250           actor->setInputShape(shape,0,0);
251           //actor->SetProperty(myProperty);
252           actor->SetShadingProperty(myProperty);
253           actor->SetWireframeProperty(myProperty);
254           actor->SetPreviewProperty(myProperty);
255           actor->PickableOff();
256           //         if ( shape.ShapeType() == TopAbs_EDGE )
257           //           actor->SubShapeOn();
258           myViewWindow->AddActor( actor );
259         }
260       }
261       return actor;
262     }
263     // -----------------------------------------------------------------------
264     void checkTriangulation(const TopoDS_Shape& shape)
265     {
266       TopLoc_Location aLoc;
267       Standard_Boolean alreadymesh = Standard_True;
268       TopExp_Explorer ex(shape, TopAbs_FACE);
269       if ( ex.More() )
270         for (; ex.More(); ex.Next()) {
271           const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
272           Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
273           if(aPoly.IsNull()) { alreadymesh = Standard_False; break; }
274         }
275       else
276         for (ex.Init(shape, TopAbs_EDGE); ex.More(); ex.Next()) {
277           const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
278           Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, aLoc);
279           if(aPoly.IsNull()) { alreadymesh = Standard_False; break; }
280         }
281       if (alreadymesh) return;
282       // Compute default deflection
283       Bnd_Box B;
284       BRepBndLib::Add(shape, B);
285       Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
286       B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
287       double deflection = Max( aXmax-aXmin , Max ( aYmax-aYmin , aZmax-aZmin)) * 0.01 *4;
288       BRepMesh_IncrementalMesh MESH(shape,deflection);
289     }
290     // -----------------------------------------------------------------------
291     bool hasViewWindow() const
292     {
293       if ( !myViewWindow ) return false;
294
295       if ( SalomeApp_Application* anApp = SMESHGUI::GetSMESHGUI()->getApp() )
296         return FindVtkViewWindow( anApp->getViewManager(SVTK_Viewer::Type(), false ),
297                                   myViewWindow );
298       return false;
299     }
300   };
301
302   // =========================================================================================
303   /*!
304    * \brief Return text describing an error
305    */
306 #define CASE2TEXT(enum) case SMESH::enum: text = QObject::tr( #enum ); break;
307   QString errorText(int errCode, const char* comment)
308   {
309     QString text;
310     switch ( errCode ) {
311       CASE2TEXT( COMPERR_OK            );
312       CASE2TEXT( COMPERR_BAD_INPUT_MESH);
313       CASE2TEXT( COMPERR_STD_EXCEPTION );
314       CASE2TEXT( COMPERR_OCC_EXCEPTION );
315       CASE2TEXT( COMPERR_SLM_EXCEPTION );
316       CASE2TEXT( COMPERR_EXCEPTION     );
317       CASE2TEXT( COMPERR_MEMORY_PB     );
318       CASE2TEXT( COMPERR_BAD_SHAPE     );
319     case SMESH::COMPERR_ALGO_FAILED:
320       if ( strlen(comment) == 0 )
321         text = QObject::tr("COMPERR_ALGO_FAILED");
322       break;
323     default:
324       text = QString("#%1").arg( -errCode );
325     }
326     if ( text.length() > 0 ) text += ". ";
327     return text + comment;
328   }
329   // -----------------------------------------------------------------------
330   /*!
331    * \brief Return SO of a subshape
332    */
333   _PTR(SObject) getSubShapeSO( int subShapeID, GEOM::GEOM_Object_var aMainShape)
334   {
335     _PTR(SObject) so = SMESH::FindSObject(aMainShape);
336     if ( subShapeID == 1 || !so )
337       return so;
338     _PTR(ChildIterator) it;
339     if (_PTR(Study) study = SMESH::GetActiveStudyDocument())
340       it =  study->NewChildIterator(so);
341     _PTR(SObject) subSO;
342     if ( it ) {
343       for ( it->InitEx(true); !subSO && it->More(); it->Next() ) {
344         GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>( it->Value() );
345         if ( !geom->_is_nil() ) {
346           GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
347           if ( list->length() == 1 && list[0] == subShapeID )
348             subSO = it->Value();
349         }
350       }
351     }
352     return subSO;
353   }
354   // -----------------------------------------------------------------------
355   /*!
356    * \brief Return subshape by ID
357    */
358   GEOM::GEOM_Object_ptr getSubShape( int subShapeID, GEOM::GEOM_Object_var aMainShape)
359   {
360     GEOM::GEOM_Object_var aSubShape;
361     if ( subShapeID == 1 )
362       aSubShape = aMainShape;
363     else if ( _PTR(SObject) so = getSubShapeSO( subShapeID, aMainShape ))
364       aSubShape = SMESH::SObjectToInterface<GEOM::GEOM_Object>( so );
365     else
366       aSubShape = SMESH::GetSubShape( aMainShape, subShapeID );
367     return aSubShape._retn();
368   }
369   // -----------------------------------------------------------------------
370   /*!
371    * \brief Return shape type name
372    */
373 #define CASE2NAME(enum) case GEOM::enum: name = QObject::tr( "GEOM_" #enum ); break;
374   QString shapeTypeName(GEOM::GEOM_Object_var aShape, const char* dflt = "" )
375   {
376     QString name = dflt;
377     if ( !aShape->_is_nil() ) {
378       switch ( aShape->GetShapeType() ) {
379       CASE2NAME( VERTEX    );
380       CASE2NAME( EDGE      );
381       CASE2NAME( WIRE      );
382       CASE2NAME( FACE      );
383       CASE2NAME( SHELL     );
384       CASE2NAME( SOLID     );
385       CASE2NAME( COMPSOLID );
386       CASE2NAME( COMPOUND  );
387       default:;
388       }
389     }
390     return name;
391   }
392   // -----------------------------------------------------------------------
393   /*!
394    * \brief Return text describing a subshape
395    */
396   QString shapeText(int subShapeID, GEOM::GEOM_Object_var aMainShape )
397   {
398     QString text;
399     if ( _PTR(SObject) aSO = getSubShapeSO( subShapeID, aMainShape ))
400       text = aSO->GetName();
401     else {
402       text = QString("#%1").arg( subShapeID );
403       QString typeName = shapeTypeName( getSubShape( subShapeID, aMainShape ));
404       if ( typeName.length() )
405         text += QString(" (%1)").arg(typeName);
406     }
407     return text;
408   }
409   // -----------------------------------------------------------------------
410   /*!
411    * \brief Return text describing a subshape
412    */
413   bool getSelectedRows(QTable* table, list< int > & rows)
414   {
415     rows.clear();
416     int nbSel = table->numSelections();
417     for ( int i = 0; i < nbSel; ++i )
418     {
419       QTableSelection selected = table->selection(i);
420       if ( !selected.isActive() ) continue;
421       for ( int row = selected.topRow(); row <= selected.bottomRow(); ++row )
422         rows.push_back( row );
423     }
424     return !rows.empty();
425   }
426
427 } // namespace SMESH
428
429
430 // =========================================================================================
431 /*!
432  * \brief Box showing mesh info
433  */
434 // =========================================================================================
435
436 SMESHGUI_MeshInfosBox::SMESHGUI_MeshInfosBox(const bool full, QWidget* theParent)
437   :QGroupBox( 4, Qt::Horizontal, tr("SMESH_MESHINFO_TITLE"), theParent ), myFull( full )
438 {
439   // title
440   QLabel* lab1 = new QLabel(this);
441   QLabel* lab2 = new QLabel(tr("SMESH_MESHINFO_ORDER0"), this );
442   QLabel* lab3 = new QLabel(tr("SMESH_MESHINFO_ORDER1"), this );
443   QLabel* lab4 = new QLabel(tr("SMESH_MESHINFO_ORDER2"), this );
444
445   QFont italic = lab1->font(); italic.setItalic(true);
446   QFont bold   = lab1->font(); bold.setBold(true);
447
448   lab1->setMinimumWidth(100); lab1->setFont( italic );
449   lab2->setMinimumWidth(100); lab2->setFont( italic );
450   lab3->setMinimumWidth(100); lab3->setFont( italic );
451   lab4->setMinimumWidth(100); lab4->setFont( italic );
452
453   if ( myFull )
454   {
455     // nodes
456     (new QLabel(COLONIZE(tr("SMESH_MESHINFO_NODES")), this ))->setFont( bold );
457     myNbNode = new QLabel( this );
458     new QLabel(this);
459     new QLabel(this);
460
461     _SEPARATOR(this);
462
463     // edges
464     (new QLabel(COLONIZE(tr("SMESH_MESHINFO_EDGES")), this ))->setFont( bold );
465     myNbEdge = new QLabel( this );
466     myNbLinEdge = new QLabel( this );
467     myNbQuadEdge = new QLabel( this );
468
469     _SEPARATOR(this);
470
471     // faces
472     (new QLabel(COLONIZE(tr("SMESH_MESHINFO_FACES")), this))->setFont( bold );
473     myNbFace     = new QLabel( this );
474     myNbLinFace  = new QLabel( this );
475     myNbQuadFace = new QLabel( this );
476     // triangles
477     new QLabel(COLONIZE(tr("SMESH_MESHINFO_TRIANGLES")), this );
478     myNbTrai     = new QLabel( this );
479     myNbLinTrai  = new QLabel( this );
480     myNbQuadTrai = new QLabel( this );
481     // quadrangles
482     new QLabel(COLONIZE(tr("SMESH_MESHINFO_QUADRANGLES")), this );
483     myNbQuad     = new QLabel( this );
484     myNbLinQuad  = new QLabel( this );
485     myNbQuadQuad = new QLabel( this );
486     // poligones
487     new QLabel(COLONIZE(tr("SMESH_MESHINFO_POLYGONES")), this );
488     myNbPolyg    = new QLabel( this );
489     new QLabel("",this );
490     new QLabel("", this );
491
492     _SEPARATOR(this);
493
494     // volumes
495     (new QLabel(COLONIZE(tr("SMESH_MESHINFO_VOLUMES")), this))->setFont( bold );
496     myNbVolum     = new QLabel( this );
497     myNbLinVolum  = new QLabel( this );
498     myNbQuadVolum = new QLabel( this );
499     // tetras
500     new QLabel(COLONIZE(tr("SMESH_MESHINFO_TETRAS")), this );
501     myNbTetra     = new QLabel( this );
502     myNbLinTetra  = new QLabel( this );
503     myNbQuadTetra = new QLabel( this );
504     // hexas
505     new QLabel(COLONIZE(tr("SMESH_MESHINFO_HEXAS")), this );
506     myNbHexa      = new QLabel( this );
507     myNbLinHexa   = new QLabel( this );
508     myNbQuadHexa  = new QLabel( this );
509     // pyras
510     new QLabel(COLONIZE(tr("SMESH_MESHINFO_PYRAS")), this );
511     myNbPyra      = new QLabel( this );
512     myNbLinPyra   = new QLabel( this );
513     myNbQuadPyra  = new QLabel( this );
514     // prisms
515     new QLabel(COLONIZE(tr("SMESH_MESHINFO_PRISMS")), this );
516     myNbPrism     = new QLabel( this );
517     myNbLinPrism  = new QLabel( this );
518     myNbQuadPrism = new QLabel( this );
519     // polyedres
520     new QLabel(COLONIZE(tr("SMESH_MESHINFO_POLYEDRES")), this );
521     myNbPolyh     = new QLabel( this );
522     new QLabel("", this );
523     new QLabel("", this );
524   }
525   else
526   {
527     // nodes
528     new QLabel(COLONIZE(tr("SMESH_MESHINFO_NODES")), this );
529     myNbNode      = new QLabel( this );
530     new QLabel(this);
531     new QLabel(this);
532
533     // edges
534     new QLabel(COLONIZE(tr("SMESH_MESHINFO_EDGES")), this );
535     myNbEdge      = new QLabel( this );
536     myNbLinEdge   = new QLabel( this );
537     myNbQuadEdge  = new QLabel( this );
538
539     // faces
540     new QLabel(COLONIZE(tr("SMESH_MESHINFO_FACES")), this);
541     myNbFace      = new QLabel( this );
542     myNbLinFace   = new QLabel( this );
543     myNbQuadFace  = new QLabel( this );
544
545     // volumes
546     new QLabel(COLONIZE(tr("SMESH_MESHINFO_VOLUMES")), this);
547     myNbVolum     = new QLabel( this );
548     myNbLinVolum  = new QLabel( this );
549     myNbQuadVolum = new QLabel( this );
550   }
551 }
552
553 // =========================================================================================
554 /*!
555  * \brief Set mesh info
556  */
557 // =========================================================================================
558
559 void SMESHGUI_MeshInfosBox::SetInfoByMesh(SMESH::SMESH_Mesh_var mesh)
560 {
561   const SMESH::ElementOrder lin = SMESH::ORDER_LINEAR;
562   int nbTot, nbLin;
563
564   // nodes
565   myNbNode     ->setText( QString("%1").arg( mesh->NbNodes() ));
566
567   // edges
568   nbTot = mesh->NbEdges(), nbLin = mesh->NbEdgesOfOrder(lin);
569   myNbEdge     ->setText( QString("%1").arg( nbTot ));
570   myNbLinEdge  ->setText( QString("%1").arg( nbLin ));
571   myNbQuadEdge ->setText( QString("%1").arg( nbTot - nbLin ));
572
573   // faces
574   nbTot = mesh->NbFaces(), nbLin = mesh->NbFacesOfOrder(lin);
575   myNbFace     ->setText( QString("%1").arg( nbTot ));
576   myNbLinFace  ->setText( QString("%1").arg( nbLin ));
577   myNbQuadFace ->setText( QString("%1").arg( nbTot - nbLin ));
578
579   // volumes
580   nbTot = mesh->NbVolumes(), nbLin = mesh->NbVolumesOfOrder(lin);
581   myNbVolum    ->setText( QString("%1").arg( nbTot ));
582   myNbLinVolum ->setText( QString("%1").arg( nbLin ));
583   myNbQuadVolum->setText( QString("%1").arg( nbTot - nbLin ));
584
585   if ( myFull )
586   {
587     // triangles
588     nbTot = mesh->NbTriangles(), nbLin = mesh->NbTrianglesOfOrder(lin);
589     myNbTrai     ->setText( QString("%1").arg( nbTot ));
590     myNbLinTrai  ->setText( QString("%1").arg( nbLin ));
591     myNbQuadTrai ->setText( QString("%1").arg( nbTot - nbLin ));
592     // quadrangles
593     nbTot = mesh->NbQuadrangles(), nbLin = mesh->NbQuadranglesOfOrder(lin);
594     myNbQuad     ->setText( QString("%1").arg( nbTot ));
595     myNbLinQuad  ->setText( QString("%1").arg( nbLin ));
596     myNbQuadQuad ->setText( QString("%1").arg( nbTot - nbLin ));
597     // poligones
598     myNbPolyg    ->setText( QString("%1").arg( mesh->NbPolygons() ));
599
600     // tetras
601     nbTot = mesh->NbTetras(), nbLin = mesh->NbTetrasOfOrder(lin);
602     myNbTetra    ->setText( QString("%1").arg( nbTot ));
603     myNbLinTetra ->setText( QString("%1").arg( nbLin ));
604     myNbQuadTetra->setText( QString("%1").arg( nbTot - nbLin ));
605     // hexas
606     nbTot = mesh->NbHexas(), nbLin = mesh->NbHexasOfOrder(lin);
607     myNbHexa     ->setText( QString("%1").arg( nbTot ));
608     myNbLinHexa  ->setText( QString("%1").arg( nbLin ));
609     myNbQuadHexa ->setText( QString("%1").arg( nbTot - nbLin ));
610     // pyras
611     nbTot = mesh->NbPyramids(), nbLin = mesh->NbPyramidsOfOrder(lin);
612     myNbPyra     ->setText( QString("%1").arg( nbTot ));
613     myNbLinPyra  ->setText( QString("%1").arg( nbLin ));
614     myNbQuadPyra ->setText( QString("%1").arg( nbTot - nbLin ));
615     // prisms
616     nbTot = mesh->NbPrisms(), nbLin = mesh->NbPrismsOfOrder(lin);
617     myNbPrism    ->setText( QString("%1").arg( nbTot ));
618     myNbLinPrism ->setText( QString("%1").arg( nbLin ));
619     myNbQuadPrism->setText( QString("%1").arg( nbTot - nbLin ));
620     // polyedres
621     myNbPolyh    ->setText( QString("%1").arg( mesh->NbPolyhedrons() ));
622   }
623 }
624
625 // =========================================================================================
626 /*!
627  * \brief Dialog to compute a mesh and show computation errors
628  */
629 //=======================================================================
630
631 SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg(): SMESHGUI_Dialog( 0, false, true, OK/* | Help*/ )
632 {
633   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame(), 0, SPACING);
634
635   QFrame* aMainFrame = createMainFrame  (mainFrame());
636
637   aDlgLay->addWidget(aMainFrame);
638
639   aDlgLay->setStretchFactor(aMainFrame, 1);
640 }
641
642 //=======================================================================
643 // function : createMainFrame()
644 // purpose  : Create frame containing dialog's fields
645 //=======================================================================
646
647 #define CASE2HEADER(enum) case enum: header = QObject::tr( #enum "_HEADER" ); break;
648
649 QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent)
650 {
651   QFrame* aFrame = new QFrame(theParent);
652
653   SUIT_ResourceMgr* rm = resourceMgr();
654   QPixmap iconCompute (rm->loadPixmap("SMESH", tr("ICON_COMPUTE")));
655
656   // constructor
657
658   QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("CONSTRUCTOR"), aFrame);
659   aPixGrp->setExclusive(TRUE);
660   QRadioButton* aRBut = new QRadioButton(aPixGrp);
661   aRBut->setPixmap(iconCompute);
662   aRBut->setChecked(TRUE);
663
664   // Mesh name
665
666   QHGroupBox* nameBox = new QHGroupBox(tr("SMESH_MESHINFO_NAME"), aFrame );
667   myMeshName = new QLabel(nameBox);
668
669   // Mesh Info
670
671   myBriefInfo = new SMESHGUI_MeshInfosBox(false, aFrame);
672   myFullInfo  = new SMESHGUI_MeshInfosBox(true,  aFrame);
673
674   // errors
675
676   myErrorGroup = new QGroupBox(tr("ERRORS"), aFrame, "errorGrBox");
677   myTable      = new QTable( 1, NB_COLUMNS, myErrorGroup, "myTable");
678   myShowBtn    = new QPushButton(tr("SHOW_SHAPE"), myErrorGroup, "myShowBtn");
679   myPublishBtn = new QPushButton(tr("PUBLISH_SHAPE"), myErrorGroup, "myPublishBtn");
680
681   myTable->setReadOnly( TRUE );
682   myTable->hideColumn( COL_PUBLISHED );
683   myTable->hideColumn( COL_SHAPEID );
684   myTable->setColumnStretchable( COL_ERROR, 1 );
685   for ( int col = 0; col < NB_COLUMNS; ++col ) {
686     QString header;
687     switch ( col ) {
688     CASE2HEADER( COL_ALGO     );
689     CASE2HEADER( COL_SHAPE    );
690     CASE2HEADER( COL_ERROR    );
691     CASE2HEADER( COL_SHAPEID  );
692     CASE2HEADER( COL_PUBLISHED);
693     }
694     myTable->horizontalHeader()->setLabel( col, header );
695   }
696
697   myErrorGroup->setColumnLayout(0, Qt::Vertical);
698   myErrorGroup->layout()->setSpacing(0);
699   myErrorGroup->layout()->setMargin(0);
700   QGridLayout* grpLayout = new QGridLayout(myErrorGroup->layout());
701   grpLayout->setAlignment(Qt::AlignTop);
702   grpLayout->setSpacing(SPACING);
703   grpLayout->setMargin(MARGIN);
704   grpLayout->addMultiCellWidget( myTable,   0, 2, 0, 0 );
705   grpLayout->addWidget         ( myShowBtn,    0, 1 );
706   grpLayout->addWidget         ( myPublishBtn, 1, 1 );
707   grpLayout->setRowStretch( 2, 1 );
708
709   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
710   aLay->addWidget( aPixGrp );
711   aLay->addWidget( nameBox );
712   aLay->addWidget( myBriefInfo );
713   aLay->addWidget( myFullInfo );
714   aLay->addWidget( myErrorGroup );
715   aLay->setStretchFactor( myErrorGroup, 1 );
716
717   return aFrame;
718 }
719
720 //================================================================================
721 /*!
722  * \brief Constructor
723 */
724 //================================================================================
725
726 SMESHGUI_ComputeOp::SMESHGUI_ComputeOp()
727 {
728   myDlg = new SMESHGUI_ComputeDlg;
729   myTShapeDisplayer = new TShapeDisplayer();
730   myHelpFileName = "/files/about_meshes.htm";
731
732   // connect signals and slots
733   connect(myDlg->myShowBtn,    SIGNAL (clicked()), SLOT(onPreviewShape()));
734   connect(myDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape()));
735   connect(table(),SIGNAL(selectionChanged()), SLOT(currentCellChanged()));
736 }
737
738 //=======================================================================
739 // function : startOperation()
740 // purpose  : Init dialog fields, connect signals and slots, show dialog
741 //=======================================================================
742
743 void SMESHGUI_ComputeOp::startOperation()
744 {
745   SMESHGUI_Operation::startOperation();
746
747   SMESH::SMESH_Mesh_var          aMesh;
748   SMESH::compute_error_array_var anErrors;
749
750   myMainShape = GEOM::GEOM_Object::_nil();
751
752   // COMPUTE MESH
753
754   bool computeFailed = true;
755   int nbNodes = 0, nbEdges = 0, nbFaces = 0, nbVolums = 0;
756
757   LightApp_SelectionMgr *Sel = selectionMgr();
758   SALOME_ListIO selected; Sel->selectedObjects( selected );
759
760   int nbSel = selected.Extent();
761   if (nbSel != 1) {
762     SUIT_MessageBox::warn1(desktop(),
763                            tr("SMESH_WRN_WARNING"),
764                            tr("SMESH_WRN_NO_AVAILABLE_DATA"),
765                            tr("SMESH_BUT_OK"));
766     onCancel();
767     return;
768   }
769
770   Handle(SALOME_InteractiveObject) IObject = selected.First();
771   aMesh = SMESH::GetMeshByIO(IObject);
772   if (!aMesh->_is_nil()) {
773     myMainShape = aMesh->GetShapeToMesh();
774     if ( !myMainShape->_is_nil() ) {
775       SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
776       SMESH::algo_error_array_var errors = gen->GetAlgoState(aMesh,myMainShape);
777       if ( errors->length() > 0 ) {
778         SUIT_MessageBox::warn1(desktop(), tr("SMESH_WRN_WARNING"),
779                                SMESH::GetMessageOnAlgoStateErrors( errors.in() ),
780                                tr("SMESH_BUT_OK"));
781         onCancel();
782         return;
783       }
784       try {
785         if (gen->Compute(aMesh, myMainShape)) {
786           computeFailed = false;
787         }
788         else {
789           anErrors = gen->GetComputeErrors( aMesh, myMainShape );
790 //           if ( anErrors->length() == 0 ) {
791 //             SUIT_MessageBox::warn1(desktop(),
792 //                                    tr("SMESH_WRN_WARNING"),
793 //                                    tr("SMESH_WRN_COMPUTE_FAILED"),
794 //                                    tr("SMESH_BUT_OK"));
795 //             onCancel();
796 //             return;
797 //           }
798         }
799         if ( _PTR(SObject) aMeshSObj = SMESH::FindSObject(aMesh)) {
800           SMESH::ModifiedMesh(aMeshSObj, !computeFailed, aMesh->NbNodes() == 0);
801           myDlg->myMeshName->setText( aMeshSObj->GetName() );
802         }
803       }
804       catch(const SALOME::SALOME_Exception & S_ex){
805         SalomeApp_Tools::QtCatchCorbaException(S_ex);
806       }
807       update( UF_ObjBrowser | UF_Model );
808
809       if ( getSMESHGUI()->automaticUpdate() ) {
810         SVTK_ViewWindow* aVTKView = SMESH::GetViewWindow(getSMESHGUI(), true);
811         if (aVTKView) {
812           int anId = study()->id();
813           TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId, IObject->getEntry());
814           if (aVisualObj) {
815             aVisualObj->Update();
816             SMESH_Actor* anActor = SMESH::FindActorByEntry(IObject->getEntry());
817             if (!anActor) {
818               anActor = SMESH::CreateActor(studyDS(), IObject->getEntry());
819               if (anActor) {
820                 SMESH::DisplayActor(aVTKView, anActor); //apo
821                 SMESH::FitAll();
822               }
823             }
824             SMESH::RepaintCurrentView();
825             Sel->setSelectedObjects( selected );
826           }
827         }
828       }
829     }
830   }
831   else {
832     SUIT_MessageBox::warn1(desktop(),
833                            tr("SMESH_WRN_WARNING"),
834                            tr("SMESH_WRN_NO_AVAILABLE_DATA"),
835                            tr("SMESH_BUT_OK"));
836     onCancel();
837     return;
838   }
839
840   myDlg->setCaption(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED"));
841
842   // SHOW ERRORS
843
844   bool noError = ( !anErrors.operator->() || anErrors->length() == 0 );
845
846   QTable* tbl = myDlg->myTable;
847
848   if ( noError )
849   {
850     //tbl->setNumRows(0);
851     myDlg->myFullInfo->SetInfoByMesh( aMesh );
852     myDlg->myFullInfo->show();
853     myDlg->myBriefInfo->hide();
854     myDlg->myErrorGroup->hide();
855   }
856   else
857   {
858     myDlg->myBriefInfo->SetInfoByMesh( aMesh );
859     myDlg->myBriefInfo->show();
860     myDlg->myFullInfo->hide();
861     myDlg->myErrorGroup->show();
862
863     // fill table of errors
864     tbl->setNumRows( anErrors->length() );
865     bool hasShape = aMesh->HasShapeToMesh();
866     if ( !hasShape ) tbl->hideColumn( COL_SHAPE );
867     else             tbl->showColumn( COL_SHAPE );
868     tbl->setColumnWidth( COL_ERROR, 200 );
869
870     for ( int row = 0; row < anErrors->length(); ++row )
871     {
872       SMESH::ComputeError & err = anErrors[ row ];
873       tbl->setText( row, COL_ALGO,    err.algoName.in() );
874       tbl->setText( row, COL_ERROR,   errorText( err.code, err.comment.in() ));
875       tbl->setText( row, COL_SHAPEID, QString("%1").arg( err.subShapeID ));
876
877       QString text = hasShape ? shapeText( err.subShapeID, myMainShape ) : QString("");
878       tbl->setText( row, COL_SHAPE,   text );
879
880       text = ( !hasShape || getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : "";
881       tbl->setText( row, COL_PUBLISHED, text ); // if text=="", "PUBLISH" button enabled
882
883       tbl->item( row, COL_ERROR )->setWordWrap( TRUE );
884       tbl->adjustRow( row );
885     }
886     tbl->adjustColumn( COL_ALGO );
887     tbl->adjustColumn( COL_SHAPE );
888
889     tbl->setCurrentCell(0,0);
890     currentCellChanged(); // to update buttons
891   }
892
893   myDlg->show();
894 }
895
896 //================================================================================
897 /*!
898  * \brief Stops operation
899  */
900 //================================================================================
901
902 void SMESHGUI_ComputeOp::stopOperation()
903 {
904   SMESHGUI_Operation::stopOperation();
905   myTShapeDisplayer->SetVisibility( false );
906 }
907
908 //================================================================================
909 /*!
910  * \brief publish selected subshape
911  */
912 //================================================================================
913
914 void SMESHGUI_ComputeOp::onPublishShape()
915 {
916   GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
917   SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
918
919   list< int > rows;
920   list< int >::iterator row;
921   getSelectedRows( table(), rows );
922   for ( row = rows.begin(); row != rows.end(); ++row )
923   {
924     int curSub = table()->text(*row, COL_SHAPEID).toInt();
925     GEOM::GEOM_Object_var shape = getSubShape( curSub, myMainShape );
926     if ( !shape->_is_nil() && ! getSubShapeSO( curSub, myMainShape ))
927     {
928       if ( !getSubShapeSO( 1, myMainShape )) // the main shape not published
929       {
930         QString name = GEOMBase::GetDefaultName( shapeTypeName( myMainShape, "MAIN_SHAPE" ));
931         SALOMEDS::SObject_var so =
932           geomGen->AddInStudy( study, myMainShape, name, GEOM::GEOM_Object::_nil());
933         // look for myMainShape in the table
934         for ( int r = 0, nr = table()->numRows(); r < nr; ++r ) {
935           if ( table()->text(r, COL_SHAPEID) == "1" ) {
936             if ( so->_is_nil() ) {
937               table()->setText( r, COL_SHAPE, so->GetName() );
938               table()->setText( r, COL_PUBLISHED, so->GetID() );
939             }
940             break;
941           }
942         }
943         if ( curSub == 1 ) continue;
944       }
945       QString name = GEOMBase::GetDefaultName( shapeTypeName( shape, "ERROR_SHAPE" ));
946       SALOMEDS::SObject_var so = geomGen->AddInStudy( study, shape, name, myMainShape);
947       if ( !so->_is_nil() ) {
948         table()->setText( *row, COL_SHAPE, so->GetName() );
949         table()->setText( *row, COL_PUBLISHED, so->GetID() );
950       }
951     }
952   }
953   getSMESHGUI()->getApp()->updateObjectBrowser();
954   currentCellChanged(); // to update buttons
955 }
956
957 //================================================================================
958 /*!
959  * \brief SLOT called when a selected cell in table() changed
960  */
961 //================================================================================
962
963 void SMESHGUI_ComputeOp::currentCellChanged()
964 {
965   myTShapeDisplayer->SetVisibility( false );
966
967   bool publishEnable = 0, showEnable = 0, showOnly = 1;
968   list< int > rows;
969   list< int >::iterator row;
970   getSelectedRows( table(), rows );
971   for ( row = rows.begin(); row != rows.end(); ++row )
972   {
973     bool hasData     = ( !table()->text(*row, COL_SHAPE).isEmpty() );
974     bool isPublished = ( !table()->text(*row, COL_PUBLISHED).isEmpty() );
975     if ( hasData && !isPublished )
976       publishEnable = true;
977
978     int curSub = table()->text(*row, COL_SHAPEID).toInt();
979     bool prsReady = myTShapeDisplayer->HasReadyActorsFor( curSub, myMainShape );
980     if ( prsReady ) {
981       myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
982       showOnly = false;
983     }
984     else {
985       showEnable = true;
986     }
987   }
988   myDlg->myPublishBtn->setEnabled( publishEnable );
989   myDlg->myShowBtn->setEnabled( showEnable );
990 }
991
992 //================================================================================
993 /*!
994  * \brief update preview
995  */
996 //================================================================================
997
998 void SMESHGUI_ComputeOp::onPreviewShape()
999 {
1000   if ( myTShapeDisplayer )
1001   {
1002     SUIT_OverrideCursor aWaitCursor;
1003     list< int > rows;
1004     list< int >::iterator row;
1005     getSelectedRows( table(), rows );
1006
1007     bool showOnly = true;
1008     for ( row = rows.begin(); row != rows.end(); ++row )
1009     {
1010       int curSub = table()->text(*row, COL_SHAPEID).toInt();
1011       if ( curSub > 0 ) {
1012         myTShapeDisplayer->Show( curSub, myMainShape, showOnly );
1013         showOnly = false;
1014       }
1015     }
1016     currentCellChanged(); // to update buttons
1017   }
1018 }
1019
1020 //================================================================================
1021 /*!
1022  * \brief Destructor
1023  */
1024 //================================================================================
1025
1026 SMESHGUI_ComputeOp::~SMESHGUI_ComputeOp()
1027 {
1028   if ( myTShapeDisplayer ) delete myTShapeDisplayer;
1029 }
1030
1031 //================================================================================
1032 /*!
1033  * \brief Gets dialog of this operation
1034  * \retval LightApp_Dialog* - pointer to dialog of this operation
1035  */
1036 //================================================================================
1037
1038 LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const
1039 {
1040   return myDlg;
1041 }
1042
1043 //================================================================================
1044 /*!
1045  * \brief perform it's intention action: compute mesh
1046  */
1047 //================================================================================
1048
1049 bool SMESHGUI_ComputeOp::onApply()
1050 {
1051   return true;
1052 }
1053
1054 //================================================================================
1055 /*!
1056  * \brief Return a table
1057  */
1058 //================================================================================
1059
1060 QTable* SMESHGUI_ComputeOp::table()
1061 {
1062   return myDlg->myTable;
1063 }