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