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