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