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