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