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