Salome HOME
0022523: [CEA 1096] Add a colomn "biquadratic" in "Mesh Information"
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshInfo.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESHGUI_MeshInfo.cxx
23 //  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
24
25 #include "SMESHGUI_MeshInfo.h"
26
27 #include "SMDSAbs_ElementType.hxx"
28 #include "SMDS_BallElement.hxx"
29 #include "SMDS_EdgePosition.hxx"
30 #include "SMDS_FacePosition.hxx"
31 #include "SMDS_Mesh.hxx"
32 #include "SMESHDS_Mesh.hxx"
33 #include "SMESHGUI.h"
34 #include "SMESHGUI_FilterUtils.h"
35 #include "SMESHGUI_IdValidator.h"
36 #include "SMESHGUI_SpinBox.h"
37 #include "SMESHGUI_Utils.h"
38 #include "SMESHGUI_VTKUtils.h"
39 #include "SMESH_Actor.h"
40
41 #include <LightApp_SelectionMgr.h>
42 #include <SUIT_FileDlg.h>
43 #include <SUIT_OverrideCursor.h>
44 #include <SUIT_ResourceMgr.h>
45 #include <SUIT_Session.h>
46 #include <SVTK_ViewWindow.h>
47
48 #include <SALOMEDSClient_Study.hxx>
49 #include <SalomeApp_Study.h>
50
51 #include <QApplication>
52 #include <QButtonGroup>
53 #include <QCheckBox>
54 #include <QContextMenuEvent>
55 #include <QGridLayout>
56 #include <QHBoxLayout>
57 #include <QHeaderView>
58 #include <QItemDelegate>
59 #include <QKeyEvent>
60 #include <QLabel>
61 #include <QLineEdit>
62 #include <QMenu>
63 #include <QPushButton>
64 #include <QToolButton>
65 #include <QRadioButton>
66 #include <QTextStream>
67 #include <QTabWidget>
68 #include <QTextBrowser>
69 #include <QVBoxLayout>
70
71 #include "utilities.h"
72
73 #include <SALOMEconfig.h>
74 #include CORBA_SERVER_HEADER(GEOM_Gen)
75
76 namespace {
77
78 const int SPACING      = 6;
79 const int MARGIN       = 9;
80 const int MAXITEMS     = 10;
81 const int GROUPS_ID    = 100;
82 const int SUBMESHES_ID = 200;
83 const int SPACING_INFO = 2;
84
85 enum InfoRole {
86   TypeRole = Qt::UserRole + 10,
87   IdRole,
88 };
89
90 enum InfoType {
91   NodeConnectivity = 100,
92   ElemConnectivity,
93 };
94 } // namesapce
95
96 /*!
97   \class ExtraWidget
98   \internal
99 */
100 class ExtraWidget : public QWidget
101 {
102 public:
103   ExtraWidget( QWidget*, bool = false );
104   ~ExtraWidget();
105
106   void updateControls( int, int, int = MAXITEMS );
107
108 public:
109   QLabel*      current;
110   QPushButton* prev;
111   QPushButton* next;
112   bool         brief;
113 };
114
115 ExtraWidget::ExtraWidget( QWidget* parent, bool b ) : QWidget( parent ), brief( b )
116 {
117   current = new QLabel( this );
118   current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
119   prev = new QPushButton( tr( "<<" ), this );
120   next = new QPushButton( tr( ">>" ), this );
121   QHBoxLayout* hbl = new QHBoxLayout( this );
122   hbl->setContentsMargins( 0, SPACING, 0, 0 );
123   hbl->setSpacing( SPACING );
124   hbl->addStretch();
125   hbl->addWidget( current );
126   hbl->addWidget( prev );
127   hbl->addWidget( next );
128 }
129
130 ExtraWidget::~ExtraWidget()
131 {
132 }
133
134 void ExtraWidget::updateControls( int total, int index, int blockSize )
135 {
136   setVisible( total > blockSize );
137   QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
138   current->setText( format.arg( index*blockSize+1 ).arg( qMin( index*blockSize+blockSize, total ) ).arg( total ) );
139   prev->setEnabled( index > 0 );
140   next->setEnabled( (index+1)*blockSize < total );
141 }
142
143 /*!
144   \class DumpFileDlg
145   \brief Customization of standard "Save file" dialog box for dump info operation
146   \internal
147 */
148
149 class DumpFileDlg : public SUIT_FileDlg
150 {
151 public:
152   DumpFileDlg( QWidget* parent );
153
154   QCheckBox* myBaseChk;
155   QCheckBox* myElemChk;
156   QCheckBox* myAddChk;
157   QCheckBox* myCtrlChk;
158 };
159
160 /*!
161   \brief Constructor
162   \internal
163 */
164 DumpFileDlg::DumpFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
165 {
166   QGridLayout* grid = ::qobject_cast<QGridLayout *>( layout() );
167   if ( grid ) {
168     QWidget* hB = new QWidget( this );
169     myBaseChk = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_BASE_INFO" ), hB );
170     myElemChk = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ELEM_INFO" ), hB );
171     myAddChk  = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ADD_INFO" ),  hB );
172     myCtrlChk = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_CTRL_INFO" ), hB );
173
174     QGridLayout* layout = new QGridLayout( hB );
175     layout->addWidget( myBaseChk, 0, 0 );
176     layout->addWidget( myElemChk, 0, 1 );
177     layout->addWidget( myAddChk, 1, 0 );
178     layout->addWidget( myCtrlChk, 1, 1 );
179
180     QPushButton* pb = new QPushButton( this );
181
182     int row = grid->rowCount();
183     grid->addWidget( new QLabel( "", this ), row, 0 );
184     grid->addWidget( hB, row, 1, 1, 3 );
185     grid->addWidget( pb, row, 5 );
186
187     pb->hide();
188   }
189 }
190
191 /*!
192   \brief Get depth of the tree item
193   \internal
194   \param theItem tree widget item
195   \return item's depth in tree widget (where top-level items have zero depth)
196 */
197 static int itemDepth( QTreeWidgetItem* item )
198 {
199   int d = 0;
200   QTreeWidgetItem* p = item->parent();
201   while ( p ) {
202     d++;
203     p = p->parent();
204   }
205   return d;
206 }
207
208 /*!
209   \class SMESHGUI_MeshInfo
210   \brief Base mesh information widget
211   
212   Displays the base information about mesh object: mesh, sub-mesh, group or arbitrary ID source.
213 */
214
215 /*!
216   \brief Constructor.
217   \param parent parent widget
218 */
219 SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
220   : QFrame( parent ), myWidgets( iElementsEnd )
221 {
222   setFrameStyle( StyledPanel | Sunken );
223
224   QGridLayout* l = new QGridLayout( this );
225   l->setMargin( MARGIN );
226   l->setSpacing( SPACING );
227
228   int index = 0;
229
230   // object
231   QLabel* aNameLab     = new QLabel( tr( "NAME_LAB" ), this );
232   QLabel* aName        = createField();
233   aName->setMinimumWidth( 150 );
234   QLabel* aObjLab      = new QLabel( tr( "OBJECT_LAB" ), this );
235   QLabel* aObj         = createField();
236   aObj->setMinimumWidth( 150 );
237   myWidgets[ index++ ] << aNameLab << aName;
238   myWidgets[ index++ ] << aObjLab  << aObj;
239
240   // nodes
241   QWidget* aNodesLine  = createLine();
242   QLabel*  aNodesLab   = new QLabel( tr( "NODES_LAB" ), this );
243   QLabel*  aNodes      = createField();
244   myWidgets[ index++ ] << aNodesLine;
245   myWidgets[ index++ ] << aNodesLab << aNodes;
246
247   // elements
248   QWidget* aElemLine   = createLine();
249   QLabel*  aElemLab    = new QLabel( tr( "ELEMENTS_LAB" ),     this );
250   QLabel*  aElemTotal  = new QLabel( tr( "TOTAL_LAB" ),        this );
251   QLabel*  aElemLin    = new QLabel( tr( "LINEAR_LAB" ),       this );
252   QLabel*  aElemQuad   = new QLabel( tr( "QUADRATIC_LAB" ),    this );
253   QLabel*  aElemBiQuad = new QLabel( tr( "BI_QUADRATIC_LAB" ), this );
254   myWidgets[ index++ ] << aElemLine;
255   myWidgets[ index++ ] << aElemLab << aElemTotal << aElemLin << aElemQuad << aElemBiQuad;
256
257   // ... Number elements
258   QWidget* aNbLine     = createLine(); 
259   QLabel*  aNbTotal    = createField();
260   QLabel*  aNbLin      = createField();
261   QLabel*  aNbQuad     = createField();
262   QLabel*  aNbBiQuad   = createField();
263   myWidgets[ index++ ] << aNbLine;
264   myWidgets[ index++ ] << new QLabel( "", this ) << aNbTotal << aNbLin << aNbQuad << aNbBiQuad;
265
266   // ... 0D elements
267   QWidget* a0DLine     = createLine();
268   QLabel*  a0DLab      = new QLabel( tr( "0D_LAB" ), this );
269   QLabel*  a0DTotal    = createField();
270   myWidgets[ index++ ] << a0DLine;
271   myWidgets[ index++ ] << a0DLab << a0DTotal;
272
273   // ... Ball elements
274   QWidget* aBallLine     = createLine();
275   QLabel*  aBallLab      = new QLabel( tr( "BALL_LAB" ), this );
276   QLabel*  aBallTotal    = createField();
277   myWidgets[ index++ ] << aBallLine;
278   myWidgets[ index++ ] << aBallLab << aBallTotal;
279
280   // ... 1D elements
281   QWidget* a1DLine     = createLine();
282   QLabel*  a1DLab      = new QLabel( tr( "1D_LAB" ), this );
283   QLabel*  a1DTotal    = createField();
284   QLabel*  a1DLin      = createField();
285   QLabel*  a1DQuad     = createField();
286   myWidgets[ index++ ] << a1DLine;
287   myWidgets[ index++ ] << a1DLab << a1DTotal << a1DLin << a1DQuad;
288
289   // ... 2D elements
290   QWidget* a2DLine      = createLine();
291   QLabel*  a2DLab       = new QLabel( tr( "2D_LAB" ), this );
292   QLabel*  a2DTotal     = createField();
293   QLabel*  a2DLin       = createField();
294   QLabel*  a2DQuad      = createField();
295   QLabel*  a2DBiQuad    = createField();
296   QLabel*  a2DTriLab    = new QLabel( tr( "TRIANGLES_LAB" ), this );
297   QLabel*  a2DTriTotal  = createField();
298   QLabel*  a2DTriLin    = createField();
299   QLabel*  a2DTriQuad   = createField();
300   QLabel*  a2DTriBiQuad = createField();
301   QLabel*  a2DQuaLab    = new QLabel( tr( "QUADRANGLES_LAB" ), this );
302   QLabel*  a2DQuaTotal  = createField();
303   QLabel*  a2DQuaLin    = createField();
304   QLabel*  a2DQuaQuad   = createField();
305   QLabel*  a2DQuaBiQuad = createField();
306   QLabel*  a2DPolLab    = new QLabel( tr( "POLYGONS_LAB" ), this );
307   QLabel*  a2DPolTotal  = createField();
308   myWidgets[ index++ ] << a2DLine;
309   myWidgets[ index++ ] << a2DLab    << a2DTotal    << a2DLin    << a2DQuad    << a2DBiQuad;
310   myWidgets[ index++ ] << a2DTriLab << a2DTriTotal << a2DTriLin << a2DTriQuad << a2DTriBiQuad;
311   myWidgets[ index++ ] << a2DQuaLab << a2DQuaTotal << a2DQuaLin << a2DQuaQuad << a2DQuaBiQuad;
312   myWidgets[ index++ ] << a2DPolLab << a2DPolTotal;
313
314   // ... 3D elements
315   QWidget* a3DLine      = createLine();
316   QLabel*  a3DLab       = new QLabel( tr( "3D_LAB" ), this );
317   QLabel*  a3DTotal     = createField();
318   QLabel*  a3DLin       = createField();
319   QLabel*  a3DQuad      = createField();
320   QLabel*  a3DBiQuad    = createField();
321   QLabel*  a3DTetLab    = new QLabel( tr( "TETRAHEDRONS_LAB" ), this );
322   QLabel*  a3DTetTotal  = createField();
323   QLabel*  a3DTetLin    = createField();
324   QLabel*  a3DTetQuad   = createField();
325   QLabel*  a3DHexLab    = new QLabel( tr( "HEXAHEDONRS_LAB" ), this );
326   QLabel*  a3DHexTotal  = createField();
327   QLabel*  a3DHexLin    = createField();
328   QLabel*  a3DHexQuad   = createField();
329   QLabel*  a3DHexBiQuad = createField();
330   QLabel*  a3DPyrLab    = new QLabel( tr( "PYRAMIDS_LAB" ), this );
331   QLabel*  a3DPyrTotal  = createField();
332   QLabel*  a3DPyrLin    = createField();
333   QLabel*  a3DPyrQuad   = createField();
334   QLabel*  a3DPriLab    = new QLabel( tr( "PRISMS_LAB" ), this );
335   QLabel*  a3DPriTotal  = createField();
336   QLabel*  a3DPriLin    = createField();
337   QLabel*  a3DPriQuad   = createField();
338   QLabel*  a3DHexPriLab   = new QLabel( tr( "HEX_PRISMS_LAB" ), this );
339   QLabel*  a3DHexPriTotal = createField();
340   QLabel*  a3DPolLab    = new QLabel( tr( "POLYHEDRONS_LAB" ), this );
341   QLabel*  a3DPolTotal  = createField();
342   myWidgets[ index++ ] << a3DLine;
343   myWidgets[ index++ ] << a3DLab    << a3DTotal    << a3DLin    << a3DQuad    << a3DBiQuad;
344   myWidgets[ index++ ] << a3DTetLab << a3DTetTotal << a3DTetLin << a3DTetQuad;
345   myWidgets[ index++ ] << a3DHexLab << a3DHexTotal << a3DHexLin << a3DHexQuad << a3DHexBiQuad;
346   myWidgets[ index++ ] << a3DPyrLab << a3DPyrTotal << a3DPyrLin << a3DPyrQuad;
347   myWidgets[ index++ ] << a3DPriLab << a3DPriTotal << a3DPriLin << a3DPriQuad;
348   myWidgets[ index++ ] << a3DHexPriLab << a3DHexPriTotal;
349   myWidgets[ index++ ] << a3DPolLab << a3DPolTotal;
350
351   myLoadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
352   myLoadBtn->setAutoDefault( true );
353   connect( myLoadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
354   
355   setFontAttributes( aNameLab,    Bold );
356   setFontAttributes( aObjLab,     Bold );
357   setFontAttributes( aNodesLab,   Bold );
358   setFontAttributes( aElemLab,    Bold );
359   setFontAttributes( aElemTotal,  Italic );
360   setFontAttributes( aElemLin,    Italic );
361   setFontAttributes( aElemQuad,   Italic );
362   setFontAttributes( aElemBiQuad, Italic );
363   setFontAttributes( a0DLab,      Bold );
364   setFontAttributes( aBallLab,    Bold );
365   setFontAttributes( a1DLab,      Bold );
366   setFontAttributes( a2DLab,      Bold );
367   setFontAttributes( a3DLab,      Bold );
368
369   l->addWidget( aNameLab,     0, 0 );
370   l->addWidget( aName,        0, 1, 1, 4 );
371   l->addWidget( aObjLab,      1, 0 );
372   l->addWidget( aObj,         1, 1, 1, 4 );
373   l->addWidget( aNodesLine,   2, 0, 1, 5 );
374   l->addWidget( aNodesLab,    3, 0 );
375   l->addWidget( aNodes,       3, 1 );
376   l->addWidget( aElemLine,    4, 0, 1, 5 );
377   l->addWidget( aElemLab,     5, 0 );
378   l->addWidget( aElemTotal,   5, 1 );
379   l->addWidget( aElemLin,     5, 2 );
380   l->addWidget( aElemQuad,    5, 3 );
381   l->addWidget( aElemBiQuad,  5, 4 );
382   l->addWidget( aNbLine,      6, 1, 1, 4 );
383   l->addWidget( aNbTotal,     7, 1 );
384   l->addWidget( aNbLin,       7, 2 );
385   l->addWidget( aNbQuad,      7, 3 );
386   l->addWidget( aNbBiQuad,    7, 4 );
387   l->addWidget( a0DLine,      8, 1, 1, 4 );
388   l->addWidget( a0DLab,       9, 0 );
389   l->addWidget( a0DTotal,     9, 1 );
390   l->addWidget( aBallLine,    10, 1, 1, 4 );
391   l->addWidget( aBallLab,     11, 0 );
392   l->addWidget( aBallTotal,   11, 1 );
393   l->addWidget( a1DLine,      12, 1, 1, 4 );
394   l->addWidget( a1DLab,       13, 0 );
395   l->addWidget( a1DTotal,     13, 1 );
396   l->addWidget( a1DLin,       13, 2 );
397   l->addWidget( a1DQuad,      13, 3 );
398   l->addWidget( a2DLine,      14, 1, 1, 4 );
399   l->addWidget( a2DLab,       15, 0 );
400   l->addWidget( a2DTotal,     15, 1 );
401   l->addWidget( a2DLin,       15, 2 );
402   l->addWidget( a2DQuad,      15, 3 );
403   l->addWidget( a2DBiQuad,    15, 4 );
404   l->addWidget( a2DTriLab,    16, 0 );
405   l->addWidget( a2DTriTotal,  16, 1 );
406   l->addWidget( a2DTriLin,    16, 2 );
407   l->addWidget( a2DTriQuad,   16, 3 );
408   l->addWidget( a2DTriBiQuad, 16, 4 );
409   l->addWidget( a2DQuaLab,    17, 0 );
410   l->addWidget( a2DQuaTotal,  17, 1 );
411   l->addWidget( a2DQuaLin,    17, 2 );
412   l->addWidget( a2DQuaQuad,   17, 3 );
413   l->addWidget( a2DQuaBiQuad, 17, 4 );
414   l->addWidget( a2DPolLab,    18, 0 );
415   l->addWidget( a2DPolTotal,  18, 1 );
416   l->addWidget( a3DLine,      19, 1, 1, 4 );
417   l->addWidget( a3DLab,       20, 0 );
418   l->addWidget( a3DTotal,     20, 1 );
419   l->addWidget( a3DLin,       20, 2 );
420   l->addWidget( a3DQuad,      20, 3 );
421   l->addWidget( a3DBiQuad,    20, 4 );
422   l->addWidget( a3DTetLab,    21, 0 );
423   l->addWidget( a3DTetTotal,  21, 1 );
424   l->addWidget( a3DTetLin,    21, 2 );
425   l->addWidget( a3DTetQuad,   21, 3 );
426   l->addWidget( a3DHexLab,    22, 0 );
427   l->addWidget( a3DHexTotal,  22, 1 );
428   l->addWidget( a3DHexLin,    22, 2 );
429   l->addWidget( a3DHexQuad,   22, 3 );
430   l->addWidget( a3DHexBiQuad, 22, 4 );
431   l->addWidget( a3DPyrLab,    23, 0 );
432   l->addWidget( a3DPyrTotal,  23, 1 );
433   l->addWidget( a3DPyrLin,    23, 2 );
434   l->addWidget( a3DPyrQuad,   23, 3 );
435   l->addWidget( a3DPriLab,    24, 0 );
436   l->addWidget( a3DPriTotal,  24, 1 );
437   l->addWidget( a3DPriLin,    24, 2 );
438   l->addWidget( a3DPriQuad,   24, 3 );
439   l->addWidget( a3DHexPriLab,   25, 0 );
440   l->addWidget( a3DHexPriTotal, 25, 1 );
441   l->addWidget( a3DPolLab,    26, 0 );
442   l->addWidget( a3DPolTotal,  26, 1 );
443   l->addWidget( myLoadBtn,    28, 1, 1, 4 );
444
445   l->setColumnStretch( 0, 0 );
446   l->setColumnStretch( 1, 5 );
447   l->setColumnStretch( 2, 5 );
448   l->setColumnStretch( 3, 5 );
449   l->setColumnStretch( 4, 5 );
450   l->setRowStretch( 27, 5 );
451
452   clear();
453 }
454
455 /*!
456   \brief Destructor
457 */
458 SMESHGUI_MeshInfo::~SMESHGUI_MeshInfo()
459 {
460 }
461
462 /*!
463   \brief Show information on the mesh object.
464   \param obj object being processed (mesh, sub-mesh, group, ID source)
465 */
466 void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
467 {
468   clear();
469   if ( !CORBA::is_nil( obj ) ) {
470     _PTR(SObject) sobj = SMESH::ObjectToSObject( obj );
471     if ( sobj ) 
472       myWidgets[iName][iSingle]->setProperty( "text", sobj->GetName().c_str() );
473     SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
474     SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
475     SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
476     if ( !aMesh->_is_nil() ) {
477       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_MESH" ) );
478     }
479     else if ( !aSubMesh->_is_nil() ) {
480       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_SUBMESH" ) );
481     }
482     else if ( !aGroup->_is_nil() ) {
483       QString objType;
484       switch( aGroup->GetType() ) {
485       case SMESH::NODE:  objType = tr( "OBJECT_GROUP_NODES"   );break;
486       case SMESH::EDGE:  objType = tr( "OBJECT_GROUP_EDGES"   );break;
487       case SMESH::FACE:  objType = tr( "OBJECT_GROUP_FACES"   );break;
488       case SMESH::VOLUME:objType = tr( "OBJECT_GROUP_VOLUMES" );break;
489       case SMESH::ELEM0D:objType = tr( "OBJECT_GROUP_0DELEMS" );break;
490       case SMESH::BALL:  objType = tr( "OBJECT_GROUP_BALLS"   );break;
491       default:           objType = tr( "OBJECT_GROUP"         );break;
492       }
493       myWidgets[iObject][iSingle]->setProperty( "text", objType );
494     }
495     SMESH::long_array_var info = obj->GetMeshInfo();
496     myWidgets[iNodes][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Node] ) );
497     myWidgets[i0D][iTotal]    ->setProperty( "text", QString::number( info[SMDSEntity_0D] ) );
498     myWidgets[iBalls][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Ball] ) );
499     long nbEdges = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
500     myWidgets[i1D][iTotal]    ->setProperty( "text", QString::number( nbEdges ) );
501     myWidgets[i1D][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Edge] ) );
502     myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Edge] ) );
503     long nbTriangles     = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_BiQuad_Triangle];
504     long nbQuadrangles   = info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
505     long nb2DLinear      = info[SMDSEntity_Triangle]        + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
506     long nb2DQuadratic   = info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_Quad_Quadrangle];
507     long nb2DBiQuadratic = info[SMDSEntity_BiQuad_Triangle] + info[SMDSEntity_BiQuad_Quadrangle];
508
509     myWidgets[i2D][iTotal]                  ->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ));
510     myWidgets[i2D][iLinear]                 ->setProperty( "text", QString::number( nb2DLinear ) );
511     myWidgets[i2D][iQuadratic]              ->setProperty( "text", QString::number( nb2DQuadratic ) );
512     myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", QString::number( nb2DBiQuadratic ) );
513     myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", QString::number( nbTriangles ) );
514     myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", QString::number( info[SMDSEntity_Triangle] ) );
515     myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Triangle] ) );
516     myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_BiQuad_Triangle] ) );
517     myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", QString::number( nbQuadrangles ) );
518     myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
519     myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Quadrangle] ) );
520     myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_BiQuad_Quadrangle] ) );
521     myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
522     long nbTetrahedrons  = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra];
523     long nbHexahedrons   = info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa];
524     long nbPyramids      = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
525     long nbPrisms        = info[SMDSEntity_Penta]   + info[SMDSEntity_Quad_Penta];
526     long nb3DLinear      = info[SMDSEntity_Tetra]      + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra] + info[SMDSEntity_Hexagonal_Prism];
527     long nb3DQuadratic   = info[SMDSEntity_Quad_Tetra] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_Quad_Pyramid] + info[SMDSEntity_Quad_Penta];
528     long nb3DBiQuadratic = info[SMDSEntity_TriQuad_Hexa];
529     myWidgets[i3D][iTotal]                  ->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
530     myWidgets[i3D][iLinear]                 ->setProperty( "text", QString::number( nb3DLinear ) );
531     myWidgets[i3D][iQuadratic]              ->setProperty( "text", QString::number( nb3DQuadratic ) );
532     myWidgets[i3D][iBiQuadratic]            ->setProperty( "text", QString::number( nb3DBiQuadratic ) );
533     myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", QString::number( nbTetrahedrons ) );
534     myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", QString::number( info[SMDSEntity_Tetra] ) );
535     myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Tetra] ) );
536     myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", QString::number( nbHexahedrons ) );
537     myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", QString::number( info[SMDSEntity_Hexa] ) );
538     myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Hexa] ) );
539     myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_TriQuad_Hexa] ) );
540     myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", QString::number( nbPyramids ) );
541     myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", QString::number( info[SMDSEntity_Pyramid] ) );
542     myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Pyramid] ) );
543     myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", QString::number( nbPrisms ) );
544     myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", QString::number( info[SMDSEntity_Penta] ) );
545     myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
546     myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", QString::number( info[SMDSEntity_Hexagonal_Prism] ) );
547     myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
548     long nbElemTotal       = info[SMDSEntity_0D] + info[SMDSEntity_Ball] + nbEdges + nb2DLinear + nb2DQuadratic + nb2DBiQuadratic + nb3DLinear + nb3DQuadratic + nb3DBiQuadratic;
549     long nbElemLinerial    = info[SMDSEntity_Edge] + nb2DLinear + nb3DLinear;
550     long nbElemQuadratic   = info[SMDSEntity_Quad_Edge] + nb2DQuadratic + nb3DQuadratic;
551     long nbElemBiQuadratic = nb2DBiQuadratic + nb3DBiQuadratic;
552     myWidgets[iNb][iTotal]      ->setProperty( "text", QString::number( nbElemTotal ) );
553     myWidgets[iNb][iLinear]     ->setProperty( "text", QString::number( nbElemLinerial ) );
554     myWidgets[iNb][iQuadratic]  ->setProperty( "text", QString::number( nbElemQuadratic ) );
555     myWidgets[iNb][iBiQuadratic]->setProperty( "text", QString::number( nbElemBiQuadratic ) );
556     // before full loading from study file, type of elements in a sub-mesh can't be defined
557     // in some cases
558     bool infoOK = obj->IsMeshInfoCorrect();
559     myLoadBtn->setVisible( !infoOK );
560     if ( !infoOK )
561     {
562       // two options:
563       // 1. Type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
564       // 2. No info at all (for a group on geom or filter)
565       bool hasAnyInfo = false;
566       for ( size_t i = 0; i < info->length() && !hasAnyInfo; ++i )
567         hasAnyInfo = info[i];
568       if ( hasAnyInfo ) // believe it is a sub-mesh
569       {
570         if ( nb2DLinear + nb2DQuadratic + nb2DBiQuadratic > 0 )
571         {
572           myWidgets[i2D][iLinear]                 ->setProperty( "text", "?" );
573           myWidgets[i2D][iQuadratic]              ->setProperty( "text", "?" );
574           myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", "?" );
575           myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", "?" );
576           myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", "?" );
577           myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", "?" );
578           myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", "?" );
579           myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", "?" );
580           myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", "?" );
581           myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", "?" );
582           myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", "?" );
583           myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", "?" );
584           myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
585           myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
586           myWidgets[iNb][iQuadratic]              ->setProperty( "text", "?" );
587           myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", "?" );
588         }
589         else if ( nb3DLinear + nb3DQuadratic + nb3DBiQuadratic > 0 )
590         {
591           myWidgets[i3D][iLinear]                 ->setProperty( "text", "?" );
592           myWidgets[i3D][iQuadratic]              ->setProperty( "text", "?" );
593           myWidgets[i3D][iBiQuadratic]            ->setProperty( "text", "?" );
594           myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", "?" );
595           myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", "?" );
596           myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", "?" );
597           myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", "?" );
598           myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", "?" );
599           myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", "?" );
600           myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", "?" );
601           myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", "?" );
602           myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", "?" );
603           myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", "?" );
604           myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", "?" );
605           myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", "?" );
606           myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", "?" );
607           myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", "?" );
608           myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", "?" );
609           myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
610           myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
611           myWidgets[iNb][iQuadratic]              ->setProperty( "text", "?" );
612           myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", "?" );
613         }
614       }
615       else
616       {
617         myWidgets[iNodes][iTotal]               ->setProperty( "text", "?" );
618         myWidgets[i0D][iTotal]                  ->setProperty( "text", "?" );
619         myWidgets[iBalls][iTotal]               ->setProperty( "text", "?" );
620         myWidgets[i1D][iTotal]                  ->setProperty( "text", "?" );
621         myWidgets[i1D][iLinear]                 ->setProperty( "text", "?" );
622         myWidgets[i1D][iQuadratic]              ->setProperty( "text", "?" );
623         myWidgets[i2D][iTotal]                  ->setProperty( "text", "?" );
624         myWidgets[i2D][iLinear]                 ->setProperty( "text", "?" );
625         myWidgets[i2D][iQuadratic]              ->setProperty( "text", "?" );
626         myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", "?" );
627         myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", "?" );
628         myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", "?" );
629         myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", "?" );
630         myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", "?" );
631         myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", "?" );
632         myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", "?" );
633         myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", "?" );
634         myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", "?" );
635         myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", "?" );
636         myWidgets[i3D][iTotal]                  ->setProperty( "text", "?" );
637         myWidgets[i3D][iLinear]                 ->setProperty( "text", "?" );
638         myWidgets[i3D][iQuadratic]              ->setProperty( "text", "?" );
639         myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", "?" );
640         myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", "?" );
641         myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", "?" );
642         myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", "?" );
643         myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", "?" );
644         myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", "?" );
645         myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", "?" );
646         myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", "?" );
647         myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", "?" );
648         myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", "?" );
649         myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", "?" );
650         myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", "?" );
651         myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", "?" );
652         myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", "?" );
653         myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", "?" );
654         myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
655         myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
656         myWidgets[iNb][iQuadratic]              ->setProperty( "text", "?" );
657         myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", "?" );
658       }
659     }
660   }
661 }
662
663 /*!
664   \brief Load mesh from a study file
665 */
666 void SMESHGUI_MeshInfo::loadMesh()
667 {
668   SUIT_OverrideCursor wc;
669
670   SALOME_ListIO selected;
671   SMESHGUI::selectionMgr()->selectedObjects( selected );
672
673   if ( selected.Extent() == 1 ) {
674     Handle(SALOME_InteractiveObject) IO = selected.First();
675     SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
676     if ( !CORBA::is_nil( obj ) ) {
677       SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
678       if ( !mesh->_is_nil() )
679       {
680         mesh->Load();
681         showInfo( obj );
682       }
683     }
684   }
685 }
686
687 /*!
688   \brief Reset the widget to the initial state (nullify all fields).
689 */
690 void SMESHGUI_MeshInfo::clear()
691 {
692   myWidgets[iName][iSingle]               ->setProperty( "text", QString() );
693   myWidgets[iObject][iSingle]             ->setProperty( "text", QString() );
694   myWidgets[iNodes][iTotal]               ->setProperty( "text", QString::number( 0 ) );
695   myWidgets[i0D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
696   myWidgets[iBalls][iTotal]               ->setProperty( "text", QString::number( 0 ) );
697   myWidgets[i1D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
698   myWidgets[i1D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
699   myWidgets[i1D][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
700   myWidgets[i2D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
701   myWidgets[i2D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
702   myWidgets[i2D][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
703   myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", QString::number( 0 ) );
704   myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", QString::number( 0 ) );
705   myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", QString::number( 0 ) );
706   myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", QString::number( 0 ) );
707   myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", QString::number( 0 ) );
708   myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", QString::number( 0 ) );
709   myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", QString::number( 0 ) );
710   myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", QString::number( 0 ) );
711   myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", QString::number( 0 ) );
712   myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( 0 ) );
713   myWidgets[i3D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
714   myWidgets[i3D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
715   myWidgets[i3D][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
716   myWidgets[i3D][iBiQuadratic]            ->setProperty( "text", QString::number( 0 ) );
717   myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", QString::number( 0 ) );
718   myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", QString::number( 0 ) );
719   myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", QString::number( 0 ) );
720   myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", QString::number( 0 ) );
721   myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", QString::number( 0 ) );
722   myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", QString::number( 0 ) );
723   myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", QString::number( 0 ) );
724   myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", QString::number( 0 ) );
725   myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", QString::number( 0 ) );
726   myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", QString::number( 0 ) );
727   myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", QString::number( 0 ) );
728   myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", QString::number( 0 ) );
729   myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", QString::number( 0 ) );
730   myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", QString::number( 0 ) );
731   myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", QString::number( 0 ) );
732   myWidgets[iNb][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
733   myWidgets[iNb][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
734   myWidgets[iNb][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
735   myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", QString::number( 0 ) );
736 }
737
738 /*!
739   \brief Create info field
740   \return new info field
741 */
742 QLabel* SMESHGUI_MeshInfo::createField()
743 {
744   QLabel* lab = new QLabel( this );
745   lab->setFrameStyle( StyledPanel | Sunken );
746   lab->setAlignment( Qt::AlignCenter );
747   lab->setAutoFillBackground( true );
748   QPalette pal = lab->palette();
749   pal.setColor( QPalette::Window, QApplication::palette().color( QPalette::Active, QPalette::Base ) );
750   lab->setPalette( pal );
751   lab->setMinimumWidth( 70 );
752   return lab;
753 }
754
755 /*!
756   \brief Create horizontal rule.
757   \return new line object
758 */
759 QWidget* SMESHGUI_MeshInfo::createLine()
760 {
761   QFrame* line = new QFrame( this );
762   line->setFrameStyle( HLine | Sunken );
763   return line;
764 }
765
766 /*!
767   \brief Change widget font attributes (bold, italic, ...).
768   \param w widget
769   \param attr font attributes (XORed flags)
770   \param val value to be set to attributes
771 */
772 void SMESHGUI_MeshInfo::setFontAttributes( QWidget* w, int attr, bool val )
773 {
774   if ( w && attr ) {
775     QFont f = w->font();
776     if ( attr & Bold   ) f.setBold( val );
777     if ( attr & Italic ) f.setItalic( val );
778     w->setFont( f );
779   }
780 }
781
782 /*!
783   \brief Show/hide group(s) of fields.
784   \param start beginning of the block
785   \param end end of the block
786   \param on visibility flag
787 */
788 void SMESHGUI_MeshInfo::setFieldsVisible( int start, int end, bool on )
789 {
790   start = qMax( 0, start );
791   end   = qMin( end, (int)iElementsEnd );
792   for ( int i = start; i < end; i++ ) {
793     wlist wl = myWidgets[i];
794     foreach ( QWidget* w, wl ) w->setVisible( on );
795   }
796 }
797
798 void SMESHGUI_MeshInfo::saveInfo( QTextStream &out )
799 {
800   out << QString( 9, '-' ) << "\n";
801   out << tr( "BASE_INFO" ) << "\n";
802   out << QString( 9, '-' ) << "\n";
803   out <<                                   tr( "NAME_LAB" )         << "  " << ( myWidgets[iName][iSingle]->property( "text" ) ).toString() << "\n";
804   out <<                                   tr( "OBJECT_LAB" )       << "  " << ( myWidgets[iObject][iSingle]->property( "text" ) ).toString() << "\n";
805   out <<                                   tr( "NODES_LAB" )        << "  " << ( myWidgets[iNodes][iTotal]->property( "text" ) ).toString() << "\n";
806   out <<                                   tr( "ELEMENTS_LAB" )     << "\n";
807   out << QString( SPACING_INFO,   ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[iNb][iTotal]->property( "text" ) ).toString() << "\n";
808   out << QString( SPACING_INFO,   ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[iNb][iLinear]->property( "text" ) ).toString() << "\n";
809   out << QString( SPACING_INFO,   ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[iNb][iQuadratic]->property( "text" ) ).toString() << "\n";
810   out << QString( SPACING_INFO,   ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[iNb][iBiQuadratic]->property( "text" ) ).toString() << "\n";
811   out << QString( SPACING_INFO,   ' ' ) << tr( "0D_LAB" )           << "\n";
812   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i0D][iTotal]->property( "text" ) ).toString() << "\n";
813   out << QString( SPACING_INFO,   ' ' ) << tr( "BALL_LAB" )         << "\n";
814   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[iBalls][iTotal]->property( "text" ) ).toString() << "\n";
815   out << QString( SPACING_INFO,   ' ' ) << tr( "1D_LAB" )           << "\n";
816   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i1D][iTotal]->property( "text" ) ).toString() << "\n";
817   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i1D][iLinear]->property( "text" ) ).toString() << "\n";
818   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i1D][iQuadratic]->property( "text" ) ).toString() << "\n";
819   out << QString( SPACING_INFO,   ' ' ) << tr( "2D_LAB" )           << "\n";
820   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2D][iTotal]->property( "text" ) ).toString() << "\n";
821   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2D][iLinear]->property( "text" ) ).toString() << "\n";
822   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2D][iQuadratic]->property( "text" ) ).toString() << "\n";
823   out << QString( SPACING_INFO*2, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2D][iBiQuadratic]->property( "text" ) ).toString() << "\n";
824   out << QString( SPACING_INFO*2, ' ' ) << tr( "TRIANGLES_LAB" )    << "\n";
825   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DTriangles][iTotal]->property( "text" ) ).toString() << "\n";
826   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2DTriangles][iLinear]->property( "text" ) ).toString() << "\n";
827   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2DTriangles][iQuadratic]->property( "text" ) ).toString() << "\n";
828   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2DTriangles][iBiQuadratic]->property( "text" ) ).toString() << "\n";
829   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRANGLES_LAB" )  << "\n";
830   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DQuadrangles][iTotal]->property( "text" ) ).toString() << "\n";
831   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2DQuadrangles][iLinear]->property( "text" ) ).toString() << "\n";
832   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2DQuadrangles][iQuadratic]->property( "text" ) ).toString() << "\n";
833   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2DQuadrangles][iBiQuadratic]->property( "text" ) ).toString() << "\n";
834   out << QString( SPACING_INFO*2, ' ' ) << tr( "POLYGONS_LAB" )     << "\n";
835   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DPolygons][iTotal]->property( "text" ) ).toString() << "\n";
836   out << QString( SPACING_INFO,   ' ' ) << tr( "3D_LAB" )           << "\n";
837   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3D][iTotal]->property( "text" ) ).toString() << "\n";
838   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3D][iLinear]->property( "text" ) ).toString() << "\n";
839   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3D][iQuadratic]->property( "text" ) ).toString() << "\n";
840   out << QString( SPACING_INFO*2, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i3D][iBiQuadratic]->property( "text" ) ).toString() << "\n";
841   out << QString( SPACING_INFO*2, ' ' ) << tr( "TETRAHEDRONS_LAB" ) << "\n";
842   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DTetrahedrons][iTotal]->property( "text" ) ).toString() << "\n";
843   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DTetrahedrons][iLinear]->property( "text" ) ).toString() << "\n";
844   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DTetrahedrons][iQuadratic]->property( "text" ) ).toString() << "\n";
845   out << QString( SPACING_INFO*2, ' ' ) << tr( "HEXAHEDONRS_LAB" )  << "\n";
846   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DHexahedrons][iTotal]->property( "text" ) ).toString() << "\n";
847   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DHexahedrons][iLinear]->property( "text" ) ).toString() << "\n";
848   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DHexahedrons][iQuadratic]->property( "text" ) ).toString() << "\n";
849   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i3DHexahedrons][iBiQuadratic]->property( "text" ) ).toString() << "\n";
850   out << QString( SPACING_INFO*2, ' ' ) << tr( "PYRAMIDS_LAB" )     << "\n";
851   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DPyramids][iTotal]->property( "text" ) ).toString() << "\n";
852   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DPyramids][iLinear]->property( "text" ) ).toString() << "\n";
853   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DPyramids][iQuadratic]->property( "text" ) ).toString() << "\n";
854   out << QString( SPACING_INFO*2, ' ' ) << tr( "PRISMS_LAB" )       << "\n";
855   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DPrisms][iTotal]->property( "text" ) ).toString() << "\n";
856   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DPrisms][iLinear]->property( "text" ) ).toString() << "\n";
857   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DPrisms][iQuadratic]->property( "text" ) ).toString() << "\n";
858   out << QString( SPACING_INFO*2, ' ' ) << tr( "HEX_PRISMS_LAB" )   << "\n";
859   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DHexaPrisms][iTotal]->property( "text" ) ).toString() << "\n";
860   out << QString( SPACING_INFO*2, ' ' ) << tr( "POLYHEDRONS_LAB" )  << "\n";
861   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DPolyhedrons][iTotal]->property( "text" ) ).toString() << "\n" << "\n";
862 }
863
864 /*!
865   \class SMESHGUI_ElemInfo
866   \brief Base class for the mesh element information widget.
867 */
868
869 /*!
870   \brief Constructor
871   \param parent parent widget
872 */
873 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent )
874 : QWidget( parent ), myActor( 0 ), myIsElement( -1 )
875 {
876   myFrame = new QWidget( this );
877   myExtra = new ExtraWidget( this );
878   QVBoxLayout* vbl = new QVBoxLayout( this );
879   vbl->setMargin( 0 );
880   vbl->setSpacing( 0 );
881   vbl->addWidget( myFrame );
882   vbl->addWidget( myExtra );
883   connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
884   connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
885   clear();
886 }
887
888 /*!
889   \brief Destructor
890 */
891 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
892 {
893 }
894
895 /*!
896   \brief Set mesh data source (actor)
897   \param actor mesh object actor
898 */
899 void SMESHGUI_ElemInfo::setSource( SMESH_Actor* actor )
900 {
901   if ( myActor != actor ) {
902     myActor = actor;
903     myIsElement = -1;
904     clear();
905   }
906 }
907
908 /*!
909   \brief Show mesh element information
910   \param id mesh node / element ID
911   \param isElem show mesh element information if \c true or mesh node information if \c false
912 */
913 void SMESHGUI_ElemInfo::showInfo( long id, bool isElem )
914 {
915   QSet<long> ids;
916   ids << id;
917   showInfo( ids, isElem );
918 }
919
920 /*!
921   \brief Show mesh element information
922   \param ids mesh nodes / elements identifiers
923   \param isElem show mesh element information if \c true or mesh node information if \c false
924 */
925 void SMESHGUI_ElemInfo::showInfo( QSet<long> ids, bool isElem )
926 {
927   QList<long> newIds = ids.toList();
928   qSort( newIds );
929   if ( myIDs == newIds && myIsElement == isElem ) return;
930
931   myIDs = newIds;
932   myIsElement = isElem;
933   myIndex = 0;
934   updateControls();
935   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
936 }
937
938 /*!
939   \brief Clear mesh element information widget
940 */
941 void SMESHGUI_ElemInfo::clear()
942 {
943   myIDs.clear();
944   myIndex = 0;
945   clearInternal();
946   updateControls();
947 }
948
949 /*!
950   \brief Get central area widget
951   \return central widget
952 */
953 QWidget* SMESHGUI_ElemInfo::frame() const
954 {
955   return myFrame;
956 }
957
958 /*!
959   \brief Get actor
960   \return actor being used
961 */
962 SMESH_Actor* SMESHGUI_ElemInfo::actor() const
963 {
964   return myActor;
965 }
966
967 /*!
968   \brief Get current info mode.
969   \return \c true if mesh element information is shown or \c false if node information is shown
970 */
971 bool SMESHGUI_ElemInfo::isElements() const
972 {
973   return myIsElement;
974 }
975
976 /*!
977   \fn void SMESHGUI_ElemInfo::information( const QList<long>& ids )
978   \brief Show information on the specified nodes / elements
979
980   This function is to be redefined in sub-classes.
981
982   \param ids nodes / elements identifiers information is to be shown on
983 */
984
985 /*!
986   \brief Internal clean-up (reset widget)
987 */
988 void SMESHGUI_ElemInfo::clearInternal()
989 {
990 }
991
992 /*!
993   \brief Get node connectivity
994   \param node mesh node
995   \return node connectivity map
996 */
997 SMESHGUI_ElemInfo::Connectivity SMESHGUI_ElemInfo::nodeConnectivity( const SMDS_MeshNode* node )
998 {
999   Connectivity elmap;
1000   if ( node ) {
1001     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
1002     while ( it && it->more() ) {
1003       const SMDS_MeshElement* ne = it->next();
1004       elmap[ ne->GetType() ] << ne->GetID();
1005     }
1006   }
1007   return elmap;
1008 }
1009
1010 /*!
1011   \brief Format connectivity data to string representation
1012   \param connectivity connetivity map
1013   \param type element type
1014   \return string representation of the connectivity
1015 */
1016 QString SMESHGUI_ElemInfo::formatConnectivity( Connectivity connectivity, int type )
1017 {
1018   QStringList str;
1019   if ( connectivity.contains( type ) ) {
1020     QList<int> elements = connectivity[ type ];
1021     qSort( elements );
1022     foreach( int id, elements )
1023       str << QString::number( id );
1024   }
1025   return str.join( " " );
1026 }
1027
1028 /*!
1029   \brief Calculate gravity center of the mesh element
1030   \param element mesh element
1031 */
1032 SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* element )
1033 {
1034   XYZ xyz;
1035   if ( element ) {
1036     SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
1037     while ( nodeIt->more() ) {
1038       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1039       xyz.add( node->X(), node->Y(), node->Z() );
1040     }
1041     xyz.divide( element->NbNodes() );
1042   }
1043   return xyz;
1044 }
1045
1046 /*!
1047   \brief This slot is called from "Show Previous" button click.
1048   Shows information on the previous group of the items.
1049 */
1050 void SMESHGUI_ElemInfo::showPrevious()
1051 {
1052   myIndex = qMax( 0, myIndex-1 );
1053   updateControls();
1054   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
1055 }
1056
1057 /*!
1058   \brief This slot is called from "Show Next" button click.
1059   Shows information on the next group of the items.
1060 */
1061 void SMESHGUI_ElemInfo::showNext()
1062 {
1063   myIndex = qMin( myIndex+1, myIDs.count() / MAXITEMS );
1064   updateControls();
1065   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
1066 }
1067
1068 /*!
1069   \brief Update widgets state
1070 */
1071 void SMESHGUI_ElemInfo::updateControls()
1072 {
1073   myExtra->updateControls( myIDs.count(), myIndex );
1074 }
1075
1076 /*!
1077   \class SMESHGUI_SimpleElemInfo
1078   \brief Represents mesh element information in the simple text area.
1079 */
1080
1081 /*!
1082   \brief Constructor
1083   \param parent parent widget
1084 */
1085 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
1086 : SMESHGUI_ElemInfo( parent )
1087 {
1088   myInfo = new QTextBrowser( frame() );
1089   QVBoxLayout* l = new QVBoxLayout( frame() );
1090   l->setMargin( 0 );
1091   l->addWidget( myInfo );
1092 }
1093
1094 /*!
1095   \brief Show mesh element information
1096   \param ids mesh nodes / elements identifiers
1097 */
1098 void SMESHGUI_SimpleElemInfo::information( const QList<long>& ids )
1099 {
1100   clearInternal();
1101   
1102   if ( actor() ) {
1103     int grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1104     int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1105     int cprecision = -1;
1106     if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ) 
1107       cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
1108     foreach ( long id, ids ) {
1109       if ( !isElements() ) {
1110         //
1111         // show node info
1112         //
1113         const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
1114         if ( !node ) return;
1115
1116         // node ID
1117         myInfo->append( QString( "<b>%1 #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "NODE" ) ).arg( id ) );
1118         // separator
1119         myInfo->append( "" );
1120         // coordinates
1121         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "COORDINATES" ) ).
1122                         arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1123                         arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1124                         arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1125         // separator
1126         myInfo->append( "" );
1127         // connectivity
1128         Connectivity connectivity = nodeConnectivity( node );
1129         if ( !connectivity.isEmpty() ) {
1130           myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) ) );
1131           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1132           if ( !con.isEmpty() )
1133             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) ).arg( con ) );
1134           con = formatConnectivity( connectivity, SMDSAbs_Edge );
1135           if ( !con.isEmpty() )
1136             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "EDGES" ) ).arg( con ) );
1137           con = formatConnectivity( connectivity, SMDSAbs_Ball );
1138           if ( !con.isEmpty() )
1139             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ) ).arg( con ) );
1140           con = formatConnectivity( connectivity, SMDSAbs_Face );
1141           if ( !con.isEmpty() )
1142             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "FACES" ) ).arg( con ) );
1143           con = formatConnectivity( connectivity, SMDSAbs_Volume );
1144           if ( !con.isEmpty() )
1145             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "VOLUMES" ) ).arg( con ) );
1146         }
1147         else {
1148           myInfo->append( QString( "<b>%1</b>" ).arg( SMESHGUI_ElemInfo::tr( "FREE_NODE" ) ).arg( id ) );
1149         }
1150         // node position
1151         SMESH::SMESH_Mesh_ptr aMeshPtr = actor()->GetObject()->GetMeshServer();   
1152         if ( !CORBA::is_nil( aMeshPtr ) ) {
1153           SMESH::NodePosition_var pos = aMeshPtr->GetNodePosition( id );
1154           int shapeID = pos->shapeID;
1155           if ( shapeID > 0 ) {
1156             QString shapeType;
1157             double u, v;
1158             switch ( pos->shapeType ) {
1159             case GEOM::EDGE:
1160               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );
1161               if ( pos->params.length() == 1 )
1162                 u = pos->params[0];
1163               break;
1164             case GEOM::FACE:
1165               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );
1166               if ( pos->params.length() == 2 ) {
1167                u = pos->params[0];
1168                v = pos->params[1];
1169               }
1170               break;
1171             case GEOM::VERTEX:
1172               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" );
1173               break;
1174             default:
1175               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );
1176               break;
1177             }
1178             // separator
1179             myInfo->append( "" );
1180             myInfo->append( QString( "<b>%1:" ).arg( SMESHGUI_ElemInfo::tr( "POSITION" ) ) );
1181             myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( shapeType ).arg( shapeID ) );
1182             if ( pos->shapeType == GEOM::EDGE || pos->shapeType == GEOM::FACE ) {
1183               myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "U_POSITION" ) ).
1184                               arg( QString::number( u, precision > 0 ? 'f' : 'g', qAbs( precision )) ) );
1185               if ( pos->shapeType == GEOM::FACE ) {
1186                 myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "V_POSITION" ) ).
1187                                 arg( QString::number( v, precision > 0 ? 'f' : 'g', qAbs( precision )) ) );
1188               }
1189             }
1190           }
1191         }
1192         // groups node belongs to
1193         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
1194         if ( !CORBA::is_nil( aMesh ) ) {
1195           SMESH::ListOfGroups_var groups = aMesh->GetGroups();
1196           myInfo->append( "" ); // separator
1197           bool top_created = false;
1198           for ( int i = 0; i < groups->length(); i++ ) {
1199             SMESH::SMESH_GroupBase_var aGrp = groups[i];
1200             if ( CORBA::is_nil( aGrp ) ) continue;
1201             QString aName = aGrp->GetName();
1202             if ( aGrp->GetType() == SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
1203               if ( !top_created ) {
1204                 myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_AddInfo::tr( "GROUPS" ) ) );
1205                 top_created = true;
1206               }
1207               myInfo->append( QString( "+ <b>%1:</b>" ).arg( aName.trimmed() ) );
1208               if ( grp_details ) {
1209                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
1210                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
1211                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
1212                 
1213                 // type : group on geometry, standalone group, group on filter
1214                 if ( !CORBA::is_nil( aStdGroup ) ) {
1215                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1216                                   arg( SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) ) );
1217                 }
1218                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
1219                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1220                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) ) );
1221                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1222                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1223                   if ( sobj ) {
1224                     myInfo->append( QString( "  - <b>%1:</b> %2: %3" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1225                                     arg( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) ).arg( sobj->GetName().c_str() ) );
1226                   }
1227                 }
1228                 else if ( !CORBA::is_nil( aFltGroup ) ) {
1229                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1230                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) ) );
1231                 }
1232                 
1233                 // size
1234                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "SIZE" ) ).
1235                                 arg( QString::number( aGrp->Size() ) ) );
1236                 
1237                 // color
1238                 SALOMEDS::Color color = aGrp->GetColor();
1239                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "COLOR" ) ).
1240                                 arg( QColor( color.R*255., color.G*255., color.B*255. ).name() ) );
1241               }
1242             }
1243           }
1244         }
1245       }
1246       else {
1247         //
1248         // show element info
1249         // 
1250         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id );
1251         SMESH::Controls::NumericalFunctorPtr afunctor;
1252         if ( !e ) return;
1253         
1254         // Element ID && Type
1255         QString stype;
1256         switch( e->GetType() ) {
1257         case SMDSAbs_0DElement:
1258           stype = SMESHGUI_ElemInfo::tr( "0D_ELEMENT" ); break;
1259         case SMDSAbs_Ball:
1260           stype = SMESHGUI_ElemInfo::tr( "BALL" ); break;
1261         case SMDSAbs_Edge:
1262           stype = SMESHGUI_ElemInfo::tr( "EDGE" ); break;
1263         case SMDSAbs_Face:
1264           stype = SMESHGUI_ElemInfo::tr( "FACE" ); break;
1265         case SMDSAbs_Volume:
1266           stype = SMESHGUI_ElemInfo::tr( "VOLUME" ); break;
1267         default: 
1268           break;
1269         }
1270         if ( stype.isEmpty() ) return;
1271         myInfo->append( QString( "<b>%1 #%2</b>" ).arg( stype ).arg( id ) );
1272         // separator
1273         myInfo->append( "" );
1274
1275         // Geometry type
1276         QString gtype;
1277         switch( e->GetEntityType() ) {
1278         case SMDSEntity_Triangle:
1279         case SMDSEntity_Quad_Triangle:
1280         case SMDSEntity_BiQuad_Triangle:
1281           gtype = SMESHGUI_ElemInfo::tr( "TRIANGLE" ); break;
1282         case SMDSEntity_Quadrangle:
1283         case SMDSEntity_Quad_Quadrangle:
1284         case SMDSEntity_BiQuad_Quadrangle:
1285           gtype = SMESHGUI_ElemInfo::tr( "QUADRANGLE" ); break;
1286         case SMDSEntity_Polygon:
1287         case SMDSEntity_Quad_Polygon:
1288           gtype = SMESHGUI_ElemInfo::tr( "POLYGON" ); break;
1289         case SMDSEntity_Tetra:
1290         case SMDSEntity_Quad_Tetra:
1291           gtype = SMESHGUI_ElemInfo::tr( "TETRAHEDRON" ); break;
1292         case SMDSEntity_Pyramid:
1293         case SMDSEntity_Quad_Pyramid:
1294           gtype = SMESHGUI_ElemInfo::tr( "PYRAMID" ); break;
1295         case SMDSEntity_Hexa:
1296         case SMDSEntity_Quad_Hexa:
1297         case SMDSEntity_TriQuad_Hexa:
1298           gtype = SMESHGUI_ElemInfo::tr( "HEXAHEDRON" ); break;
1299         case SMDSEntity_Penta:
1300         case SMDSEntity_Quad_Penta:
1301           gtype = SMESHGUI_ElemInfo::tr( "PRISM" ); break;
1302         case SMDSEntity_Hexagonal_Prism:
1303           gtype = SMESHGUI_ElemInfo::tr( "HEX_PRISM" ); break;
1304         case SMDSEntity_Polyhedra:
1305         case SMDSEntity_Quad_Polyhedra:
1306           gtype = SMESHGUI_ElemInfo::tr( "POLYHEDRON" ); break;
1307         default: 
1308           break;
1309         }
1310         if ( !gtype.isEmpty() )
1311           myInfo->append( QString( "<b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "TYPE" ) ).arg( gtype ) );
1312
1313         // Quadratic flag (any element except 0D)
1314         if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Ball ) {
1315           myInfo->append( QString( "<b>%1?</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "QUADRATIC" ) ).arg( e->IsQuadratic() ? SMESHGUI_ElemInfo::tr( "YES" ) : SMESHGUI_ElemInfo::tr( "NO" ) ) );
1316         }
1317         if ( const SMDS_BallElement* ball = dynamic_cast<const SMDS_BallElement*>( e )) {
1318           // Ball diameter
1319           myInfo->append( QString( "<b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "BALL_DIAMETER" ) ).arg( ball->GetDiameter() ));
1320         }
1321         // separator
1322         myInfo->append( "" );
1323
1324         // Connectivity
1325         SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
1326         for ( int idx = 1; nodeIt->more(); idx++ ) {
1327           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1328           // node number and ID
1329           myInfo->append( QString( "<b>%1 %2/%3</b> - #%4" ).arg( SMESHGUI_ElemInfo::tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ) );
1330           // node coordinates
1331           myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "COORDINATES" ) ).
1332                           arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1333                           arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1334                           arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1335           // node connectivity
1336           Connectivity connectivity = nodeConnectivity( node );
1337           if ( !connectivity.isEmpty() ) {
1338             myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) ) );
1339             QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1340             if ( !con.isEmpty() )
1341               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) ).arg( con ) );
1342             con = formatConnectivity( connectivity, SMDSAbs_Edge );
1343             if ( !con.isEmpty() )
1344               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "EDGES" ) ).arg( con ) );
1345             con = formatConnectivity( connectivity, SMDSAbs_Face );
1346             if ( !con.isEmpty() )
1347               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "FACES" ) ).arg( con ) );
1348             con = formatConnectivity( connectivity, SMDSAbs_Volume );
1349             if ( !con.isEmpty() )
1350               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "VOLUMES" ) ).arg( con ) );
1351           }
1352           else {
1353             myInfo->append( QString( "<b>%1</b>" ).arg( SMESHGUI_ElemInfo::tr( "FREE_NODE" ) ).arg( id ) );
1354           }
1355         }
1356         // separator
1357         myInfo->append( "" );
1358
1359         // Controls
1360         myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONTROLS" ) ) );
1361         //Length
1362         if ( e->GetType() == SMDSAbs_Edge ) {
1363           afunctor.reset( new SMESH::Controls::Length() );
1364           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1365           afunctor->SetPrecision( cprecision );
1366           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "LENGTH_EDGES" ) ).arg( afunctor->GetValue( id ) ) );  
1367         }
1368         if( e->GetType() == SMDSAbs_Face ) {
1369           //Area
1370           afunctor.reset(  new SMESH::Controls::Area() );
1371           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1372           afunctor->SetPrecision( cprecision );  
1373           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "AREA_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1374           //Taper
1375           afunctor.reset( new SMESH::Controls::Taper() );
1376           afunctor->SetMesh( actor()->GetObject()->GetMesh() );  
1377           afunctor->SetPrecision( cprecision );
1378           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "TAPER_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1379           //AspectRatio2D
1380           afunctor.reset( new SMESH::Controls::AspectRatio() );
1381           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1382           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "ASPECTRATIO_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1383           //Minimum angle         
1384           afunctor.reset( new SMESH::Controls::MinimumAngle() );
1385           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1386           afunctor->SetPrecision( cprecision );
1387           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MINIMUMANGLE_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1388           //Wraping angle        
1389           afunctor.reset( new SMESH::Controls::Warping() );
1390           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1391           afunctor->SetPrecision( cprecision );
1392           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "WARP_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1393           //Skew         
1394           afunctor.reset( new SMESH::Controls::Skew() );
1395           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1396           afunctor->SetPrecision( cprecision );
1397           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "SKEW_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1398           //ElemDiam2D   
1399           afunctor.reset( new SMESH::Controls::MaxElementLength2D() );
1400           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1401           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MAX_ELEMENT_LENGTH_2D" ) ).arg( afunctor->GetValue( id ) ) );
1402         }
1403         if( e->GetType() == SMDSAbs_Volume ) {
1404           //AspectRatio3D
1405           afunctor.reset(  new SMESH::Controls::AspectRatio3D() );
1406           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1407           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "ASPECTRATIO_3D_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1408           //Volume      
1409           afunctor.reset(  new SMESH::Controls::Volume() );
1410           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1411           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUME_3D_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1412           //ElementDiameter3D    
1413           afunctor.reset(  new SMESH::Controls::Volume() );
1414           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1415           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MAX_ELEMENT_LENGTH_3D" ) ).arg( afunctor->GetValue( id ) ) );
1416         }
1417         // separator
1418         myInfo->append( "" );
1419
1420         // Gravity center
1421         XYZ gc = gravityCenter( e );
1422         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "GRAVITY_CENTER" ) ).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ) );
1423
1424         // Element position
1425         if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
1426           SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();    
1427           if ( !CORBA::is_nil( aMesh ) ) {
1428             SMESH::ElementPosition pos = aMesh->GetElementPosition( id );
1429             int shapeID = pos.shapeID;
1430             if ( shapeID > 0 ) {
1431               myInfo->append( "" ); // separator
1432               QString shapeType;
1433               switch ( pos.shapeType ) {
1434               case GEOM::EDGE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );   break;
1435               case GEOM::FACE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );   break;
1436               case GEOM::VERTEX: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" ); break;
1437               case GEOM::SOLID:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );  break;
1438               case GEOM::SHELL:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHELL" );  break;
1439               default:           shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHAPE" );  break;
1440               }
1441               myInfo->append( QString( "<b>%1:</b> %2 #%3" ).arg( SMESHGUI_ElemInfo::tr( "POSITION" ) ).arg( shapeType ).arg( shapeID ) );
1442             }
1443           }
1444         }
1445
1446         // Groups the element belongs to
1447         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
1448         if ( !CORBA::is_nil( aMesh ) ) {
1449           SMESH::ListOfGroups_var  groups = aMesh->GetGroups();
1450           myInfo->append( "" ); // separator
1451           bool top_created = false;
1452           for ( int i = 0; i < groups->length(); i++ ) {
1453             SMESH::SMESH_GroupBase_var aGrp = groups[i];
1454             if ( CORBA::is_nil( aGrp ) ) continue;
1455             QString aName = aGrp->GetName();
1456             if ( aGrp->GetType() != SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
1457               if ( !top_created ) {
1458                 myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_AddInfo::tr( "GROUPS" ) ) );
1459                 top_created = true;
1460               }
1461               myInfo->append( QString( "+ <b>%1:</b>" ).arg( aName.trimmed() ) );
1462               if ( grp_details ) {
1463                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
1464                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
1465                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
1466                 
1467                 // type : group on geometry, standalone group, group on filter
1468                 if ( !CORBA::is_nil( aStdGroup ) ) {
1469                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1470                                   arg( SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) ) );
1471                 }
1472                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
1473                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1474                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) ) );
1475                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1476                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1477                   if ( sobj ) {
1478                     myInfo->append( QString( "  - <b>%1:</b> %2: %3" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1479                                     arg( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) ).arg( sobj->GetName().c_str() ) );
1480                   }
1481                 }
1482                 else if ( !CORBA::is_nil( aFltGroup ) ) {
1483                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1484                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) ) );
1485                 }
1486                 
1487                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "SIZE" ) ).
1488                                 arg( QString::number( aGrp->Size() ) ) );
1489                 
1490                 // color
1491                 SALOMEDS::Color color = aGrp->GetColor();
1492                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "COLOR" ) ).
1493                                 arg( QColor( color.R*255., color.G*255., color.B*255. ).name() ) );
1494               }
1495             }
1496           }
1497         }
1498       }
1499       // separator
1500       if ( ids.count() > 1 ) {
1501         myInfo->append( "" );
1502         myInfo->append( "------" );
1503         myInfo->append( "" );
1504       }
1505     }
1506   }
1507 }
1508
1509 /*!
1510   \brief Internal clean-up (reset widget)
1511 */
1512 void SMESHGUI_SimpleElemInfo::clearInternal()
1513 {
1514   myInfo->clear();
1515 }
1516
1517 void SMESHGUI_SimpleElemInfo::saveInfo( QTextStream &out )
1518 {
1519   out << QString( 12, '-' ) << "\n";
1520   out << SMESHGUI_ElemInfo::tr( "ELEM_INFO" ) << "\n";
1521   out << QString( 12, '-' ) << "\n";
1522   out << myInfo->toPlainText();
1523   out << "\n";
1524 }
1525
1526
1527 /*!
1528   \class SMESHGUI_TreeElemInfo::ItemDelegate
1529   \brief Item delegate for tree mesh info widget
1530   \internal
1531 */
1532 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
1533 {
1534 public:
1535   ItemDelegate( QObject* );
1536   QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
1537 };
1538
1539 /*!
1540   \brief Constructor
1541   \internal
1542 */
1543 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ) : QItemDelegate( parent )
1544 {
1545 }
1546
1547 /*!
1548   \brief Create item editor widget
1549   \internal
1550 */
1551 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
1552 {
1553   QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
1554   if ( qobject_cast<QLineEdit*>( w ) ) qobject_cast<QLineEdit*>( w )->setReadOnly(  true );
1555   return w;
1556 }
1557
1558 /*!
1559   \class SMESHGUI_TreeElemInfo
1560   \brief Represents mesh element information in the tree-like form.
1561 */
1562
1563 /*!
1564   \brief Constructor
1565   \param parent parent widget
1566 */
1567 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
1568 : SMESHGUI_ElemInfo( parent )
1569 {
1570   myInfo = new QTreeWidget( frame() );
1571   myInfo->setColumnCount( 2 );
1572   myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
1573   myInfo->header()->setStretchLastSection( true );
1574   myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
1575   myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
1576   QVBoxLayout* l = new QVBoxLayout( frame() );
1577   l->setMargin( 0 );
1578   l->addWidget( myInfo );
1579   connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
1580 }
1581
1582 /*!
1583   \brief Show mesh element information
1584   \param ids mesh nodes / elements identifiers
1585 */
1586 void SMESHGUI_TreeElemInfo::information( const QList<long>& ids )
1587 {
1588   clearInternal();
1589
1590   if ( actor() ) {
1591     int grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1592     int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1593     int cprecision = -1;
1594     if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ) 
1595       cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
1596     foreach ( long id, ids ) {
1597       if ( !isElements() ) {
1598         //
1599         // show node info
1600         //
1601         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindNode( id );
1602         if ( !e ) return;
1603         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
1604       
1605         // node ID
1606         QTreeWidgetItem* nodeItem = createItem( 0, Bold | All );
1607         nodeItem->setText( 0, SMESHGUI_ElemInfo::tr( "NODE" ) );
1608         nodeItem->setText( 1, QString( "#%1" ).arg( id ) );
1609         // coordinates
1610         QTreeWidgetItem* coordItem = createItem( nodeItem, Bold );
1611         coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ) );
1612         QTreeWidgetItem* xItem = createItem( coordItem );
1613         xItem->setText( 0, "X" );
1614         xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1615         QTreeWidgetItem* yItem = createItem( coordItem );
1616         yItem->setText( 0, "Y" );
1617         yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1618         QTreeWidgetItem* zItem = createItem( coordItem );
1619         zItem->setText( 0, "Z" );
1620         zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1621         // connectivity
1622         QTreeWidgetItem* conItem = createItem( nodeItem, Bold );
1623         conItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) );
1624         Connectivity connectivity = nodeConnectivity( node );
1625         if ( !connectivity.isEmpty() ) {
1626           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1627           if ( !con.isEmpty() ) {
1628             QTreeWidgetItem* i = createItem( conItem );
1629             i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) );
1630             i->setText( 1, con );
1631           }
1632           con = formatConnectivity( connectivity, SMDSAbs_Ball );
1633           if ( !con.isEmpty() ) {
1634             QTreeWidgetItem* i = createItem( conItem );
1635             i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ) );
1636             i->setText( 1, con );
1637             i->setData( 1, TypeRole, NodeConnectivity );
1638           }
1639           con = formatConnectivity( connectivity, SMDSAbs_Edge );
1640           if ( !con.isEmpty() ) {
1641             QTreeWidgetItem* i = createItem( conItem );
1642             i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ) );
1643             i->setText( 1, con );
1644             i->setData( 1, TypeRole, NodeConnectivity );
1645           }
1646           con = formatConnectivity( connectivity, SMDSAbs_Face );
1647           if ( !con.isEmpty() ) {
1648             QTreeWidgetItem* i = createItem( conItem );
1649             i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ) );
1650             i->setText( 1, con );
1651             i->setData( 1, TypeRole, NodeConnectivity );
1652           }
1653           con = formatConnectivity( connectivity, SMDSAbs_Volume );
1654           if ( !con.isEmpty() ) {
1655             QTreeWidgetItem* i = createItem( conItem );
1656             i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ) );
1657             i->setText( 1, con );
1658             i->setData( 1, TypeRole, NodeConnectivity );
1659           }
1660         }
1661         else {
1662           conItem->setText( 1, SMESHGUI_ElemInfo::tr( "FREE_NODE" ) );
1663         }
1664         // node position
1665         SMESH::SMESH_Mesh_ptr aMeshPtr = actor()->GetObject()->GetMeshServer();   
1666         if ( !CORBA::is_nil( aMeshPtr ) ) {
1667           SMESH::NodePosition_var pos = aMeshPtr->GetNodePosition( id );
1668           int shapeID = pos->shapeID;
1669           if ( shapeID > 0 ) {
1670             QString shapeType;
1671             double u, v;
1672             switch ( pos->shapeType ) {
1673             case GEOM::EDGE:
1674               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );
1675               if ( pos->params.length() == 1 )
1676                 u = pos->params[0];
1677               break;
1678             case GEOM::FACE:
1679               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );
1680               if ( pos->params.length() == 2 ) {
1681                 u = pos->params[0];
1682                 v = pos->params[1];
1683               }
1684               break;
1685             case GEOM::VERTEX:
1686               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" );
1687               break;
1688             default:
1689               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );
1690               break;
1691             }
1692             QTreeWidgetItem* posItem = createItem( nodeItem, Bold );
1693             posItem->setText( 0, SMESHGUI_ElemInfo::tr("POSITION") );
1694             posItem->setText( 1, (shapeType + " #%1").arg( shapeID ));
1695             if ( pos->shapeType == GEOM::EDGE || pos->shapeType == GEOM::FACE ) {
1696               QTreeWidgetItem* uItem = createItem( posItem );
1697               uItem->setText( 0, SMESHGUI_ElemInfo::tr("U_POSITION") );
1698               uItem->setText( 1, QString::number( u, precision > 0 ? 'f' : 'g', qAbs( precision )));
1699               if ( pos->shapeType == GEOM::FACE ) {
1700                 QTreeWidgetItem* vItem = createItem( posItem );
1701                 vItem->setText( 0, SMESHGUI_ElemInfo::tr("V_POSITION") );
1702                 vItem->setText( 1, QString::number( v, precision > 0 ? 'f' : 'g', qAbs( precision )));
1703               }
1704             }
1705           }
1706         }
1707         // groups node belongs to
1708         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
1709         if ( !CORBA::is_nil( aMesh ) ) {
1710           SMESH::ListOfGroups_var groups = aMesh->GetGroups();
1711           QTreeWidgetItem* groupsItem = 0;
1712           for ( int i = 0; i < groups->length(); i++ ) {
1713             SMESH::SMESH_GroupBase_var aGrp = groups[i];
1714             if ( CORBA::is_nil( aGrp ) ) continue;
1715             QString aName = aGrp->GetName();
1716             if ( aGrp->GetType() == SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
1717               if ( !groupsItem ) {
1718                 groupsItem = createItem( nodeItem, Bold );
1719                 groupsItem->setText( 0, SMESHGUI_AddInfo::tr( "GROUPS" ) );
1720               }
1721               QTreeWidgetItem* it = createItem( groupsItem, Bold );
1722               it->setText( 0, aName.trimmed() );
1723               if ( grp_details ) {
1724                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
1725                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
1726                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
1727                 
1728                 // type : group on geometry, standalone group, group on filter
1729                 QTreeWidgetItem* typeItem = createItem( it );
1730                 typeItem->setText( 0, SMESHGUI_AddInfo::tr( "TYPE" ) );
1731                 if ( !CORBA::is_nil( aStdGroup ) ) {
1732                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1733                 }
1734                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
1735                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1736                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1737                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1738                   if ( sobj ) {
1739                     QTreeWidgetItem* gobjItem = createItem( typeItem );
1740                     gobjItem->setText( 0, SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) );
1741                     gobjItem->setText( 1, sobj->GetName().c_str() );
1742                   }
1743                 }
1744                 else if ( !CORBA::is_nil( aFltGroup ) ) {
1745                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1746                 }
1747                 
1748                 // size
1749                 QTreeWidgetItem* sizeItem = createItem( it );
1750                 sizeItem->setText( 0, SMESHGUI_AddInfo::tr( "SIZE" ) );
1751                 sizeItem->setText( 1, QString::number( aGrp->Size() ) );
1752                 
1753                 // color
1754                 SALOMEDS::Color color = aGrp->GetColor();
1755                 QTreeWidgetItem* colorItem = createItem( it );
1756                 colorItem->setText( 0, SMESHGUI_AddInfo::tr( "COLOR" ) );
1757                 colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
1758               }
1759             }
1760           }
1761         }
1762       }
1763       else {
1764         //
1765         // show element info
1766         // 
1767         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id );
1768         SMESH::Controls::NumericalFunctorPtr afunctor;
1769         if ( !e ) return;
1770         
1771         // element ID && type
1772         QString stype;
1773         switch( e->GetType() ) {
1774         case SMDSAbs_0DElement: stype = SMESHGUI_ElemInfo::tr( "0D_ELEMENT" ); break;
1775         case SMDSAbs_Ball:      stype = SMESHGUI_ElemInfo::tr( "BALL" ); break;
1776         case SMDSAbs_Edge:      stype = SMESHGUI_ElemInfo::tr( "EDGE" ); break;
1777         case SMDSAbs_Face:      stype = SMESHGUI_ElemInfo::tr( "FACE" ); break;
1778         case SMDSAbs_Volume:    stype = SMESHGUI_ElemInfo::tr( "VOLUME" ); break;
1779         default:;
1780         }
1781         if ( stype.isEmpty() ) return;
1782         QTreeWidgetItem* elemItem = createItem( 0, Bold | All );
1783         elemItem->setText( 0, stype );
1784         elemItem->setText( 1, QString( "#%1" ).arg( id ) );
1785         // geometry type
1786         QString gtype;
1787         switch( e->GetEntityType() ) {
1788         case SMDSEntity_Triangle:
1789         case SMDSEntity_Quad_Triangle:
1790         case SMDSEntity_BiQuad_Triangle:
1791           gtype = SMESHGUI_ElemInfo::tr( "TRIANGLE" ); break;
1792         case SMDSEntity_Quadrangle:
1793         case SMDSEntity_Quad_Quadrangle:
1794         case SMDSEntity_BiQuad_Quadrangle:
1795           gtype = SMESHGUI_ElemInfo::tr( "QUADRANGLE" ); break;
1796         case SMDSEntity_Polygon:
1797         case SMDSEntity_Quad_Polygon:
1798           gtype = SMESHGUI_ElemInfo::tr( "POLYGON" ); break;
1799         case SMDSEntity_Tetra:
1800         case SMDSEntity_Quad_Tetra:
1801           gtype = SMESHGUI_ElemInfo::tr( "TETRAHEDRON" ); break;
1802         case SMDSEntity_Pyramid:
1803         case SMDSEntity_Quad_Pyramid:
1804           gtype = SMESHGUI_ElemInfo::tr( "PYRAMID" ); break;
1805         case SMDSEntity_Hexa:
1806         case SMDSEntity_Quad_Hexa:
1807         case SMDSEntity_TriQuad_Hexa:
1808           gtype = SMESHGUI_ElemInfo::tr( "HEXAHEDRON" ); break;
1809         case SMDSEntity_Penta:
1810         case SMDSEntity_Quad_Penta:
1811           gtype = SMESHGUI_ElemInfo::tr( "PRISM" ); break;
1812         case SMDSEntity_Hexagonal_Prism:
1813           gtype = SMESHGUI_ElemInfo::tr( "HEX_PRISM" ); break;
1814         case SMDSEntity_Polyhedra:
1815         case SMDSEntity_Quad_Polyhedra:
1816           gtype = SMESHGUI_ElemInfo::tr( "POLYHEDRON" ); break;
1817         default: 
1818           break;
1819         }
1820         if ( !gtype.isEmpty() ) {
1821           QTreeWidgetItem* typeItem = createItem( elemItem, Bold );
1822           typeItem->setText( 0, SMESHGUI_ElemInfo::tr( "TYPE" ) );
1823           typeItem->setText( 1, gtype );
1824         }
1825         // quadratic flag (for edges, faces and volumes)
1826         if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
1827           // quadratic flag
1828           QTreeWidgetItem* quadItem = createItem( elemItem, Bold );
1829           quadItem->setText( 0, SMESHGUI_ElemInfo::tr( "QUADRATIC" ) );
1830           quadItem->setText( 1, e->IsQuadratic() ? SMESHGUI_ElemInfo::tr( "YES" ) : SMESHGUI_ElemInfo::tr( "NO" ) );
1831         }
1832         if ( const SMDS_BallElement* ball = dynamic_cast<const SMDS_BallElement*>( e )) {
1833           // ball diameter
1834           QTreeWidgetItem* diamItem = createItem( elemItem, Bold );
1835           diamItem->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_DIAMETER" ) );
1836           diamItem->setText( 1, QString( "%1" ).arg( ball->GetDiameter() ));
1837         }
1838         // connectivity
1839         QTreeWidgetItem* conItem = createItem( elemItem, Bold );
1840         conItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) );
1841         SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
1842         for ( int idx = 1; nodeIt->more(); idx++ ) {
1843           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1844           // node number and ID
1845           QTreeWidgetItem* nodeItem = createItem( conItem, Bold );
1846           nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ) );
1847           nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ) );
1848           nodeItem->setData( 1, TypeRole, ElemConnectivity );
1849           nodeItem->setData( 1, IdRole, node->GetID() );
1850           nodeItem->setExpanded( false );
1851           // node coordinates
1852           QTreeWidgetItem* coordItem = createItem( nodeItem );
1853           coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ) );
1854           QTreeWidgetItem* xItem = createItem( coordItem );
1855           xItem->setText( 0, "X" );
1856           xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1857           QTreeWidgetItem* yItem = createItem( coordItem );
1858           yItem->setText( 0, "Y" );
1859           yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1860           QTreeWidgetItem* zItem = createItem( coordItem );
1861           zItem->setText( 0, "Z" );
1862           zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1863           // node connectivity
1864           QTreeWidgetItem* nconItem = createItem( nodeItem );
1865           nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) );
1866           Connectivity connectivity = nodeConnectivity( node );
1867           if ( !connectivity.isEmpty() ) {
1868             QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1869             if ( !con.isEmpty() ) {
1870               QTreeWidgetItem* i = createItem( nconItem );
1871               i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) );
1872               i->setText( 1, con );
1873             }
1874             con = formatConnectivity( connectivity, SMDSAbs_Edge );
1875             if ( !con.isEmpty() ) {
1876               QTreeWidgetItem* i = createItem( nconItem );
1877               i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ) );
1878               i->setText( 1, con );
1879               i->setData( 1, TypeRole, NodeConnectivity );
1880             }
1881             con = formatConnectivity( connectivity, SMDSAbs_Ball );
1882             if ( !con.isEmpty() ) {
1883               QTreeWidgetItem* i = createItem( nconItem );
1884               i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ) );
1885               i->setText( 1, con );
1886               i->setData( 1, TypeRole, NodeConnectivity );
1887             }
1888             con = formatConnectivity( connectivity, SMDSAbs_Face );
1889             if ( !con.isEmpty() ) {
1890               QTreeWidgetItem* i = createItem( nconItem );
1891               i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ) );
1892               i->setText( 1, con );
1893               i->setData( 1, TypeRole, NodeConnectivity );
1894             }
1895             con = formatConnectivity( connectivity, SMDSAbs_Volume );
1896             if ( !con.isEmpty() ) {
1897               QTreeWidgetItem* i = createItem( nconItem );
1898               i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ) );
1899               i->setText( 1, con );
1900               i->setData( 1, TypeRole, NodeConnectivity );
1901             }
1902           }
1903         }
1904         //Controls
1905         QTreeWidgetItem* cntrItem = createItem( elemItem, Bold );
1906         cntrItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONTROLS" ) );
1907         //Length
1908         if( e->GetType()==SMDSAbs_Edge){         
1909           afunctor.reset( new SMESH::Controls::Length() );
1910           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1911           afunctor->SetPrecision( cprecision );
1912           QTreeWidgetItem* lenItem = createItem( cntrItem, Bold );
1913           lenItem->setText( 0, tr( "LENGTH_EDGES" ) );
1914           lenItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );         
1915         }
1916         if( e->GetType() == SMDSAbs_Face ) {
1917           //Area         
1918           afunctor.reset( new SMESH::Controls::Area() );        
1919           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1920           afunctor->SetPrecision( cprecision );
1921           QTreeWidgetItem* areaItem = createItem( cntrItem, Bold );
1922           areaItem->setText( 0, tr( "AREA_ELEMENTS" ) );
1923           areaItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue(id) ) );         
1924           //Taper
1925           afunctor.reset( new SMESH::Controls::Taper() );
1926           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1927           afunctor->SetPrecision( cprecision );
1928           QTreeWidgetItem* taperlItem = createItem( cntrItem, Bold );
1929           taperlItem->setText( 0, tr( "TAPER_ELEMENTS" ) );
1930           taperlItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );    
1931           //AspectRatio2D
1932           afunctor.reset( new SMESH::Controls::AspectRatio() );
1933           afunctor->SetMesh( actor()->GetObject()->GetMesh() );  
1934           QTreeWidgetItem* ratlItem = createItem( cntrItem, Bold );
1935           ratlItem->setText( 0, tr( "ASPECTRATIO_ELEMENTS" ));
1936           ratlItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );      
1937           //Minimum angle
1938           afunctor.reset( new SMESH::Controls::MinimumAngle() );
1939           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1940           afunctor->SetPrecision( cprecision );
1941           QTreeWidgetItem* minanglItem = createItem( cntrItem, Bold );
1942           minanglItem->setText( 0, tr( "MINIMUMANGLE_ELEMENTS" ) );
1943           minanglItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );    
1944           //Wraping angle       
1945           afunctor.reset( new SMESH::Controls::Warping() );
1946           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1947           afunctor->SetPrecision( cprecision );
1948           QTreeWidgetItem* warpItem = createItem( cntrItem, Bold );
1949           warpItem->setText( 0, tr( "WARP_ELEMENTS" ));
1950           warpItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );        
1951           //Skew          
1952           afunctor.reset( new SMESH::Controls::Skew() );
1953           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1954           afunctor->SetPrecision( cprecision );
1955           QTreeWidgetItem* skewItem = createItem( cntrItem, Bold );
1956           skewItem->setText( 0, tr( "SKEW_ELEMENTS" ) );
1957           skewItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );       
1958           //ElemDiam2D    
1959           afunctor.reset( new SMESH::Controls::MaxElementLength2D() );
1960           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1961           QTreeWidgetItem* diamItem = createItem( cntrItem, Bold );
1962           diamItem->setText( 0, tr( "MAX_ELEMENT_LENGTH_2D" ));
1963           diamItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );       
1964         }
1965         if( e->GetType() == SMDSAbs_Volume ) {
1966           //AspectRatio3D
1967           afunctor.reset( new SMESH::Controls::AspectRatio3D() );
1968           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1969           QTreeWidgetItem* ratlItem3 = createItem( cntrItem, Bold );
1970           ratlItem3->setText( 0, tr( "ASPECTRATIO_3D_ELEMENTS" ) );
1971           ratlItem3->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );      
1972           //Volume
1973           afunctor.reset( new SMESH::Controls::Volume() );
1974           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1975           QTreeWidgetItem* volItem = createItem( cntrItem, Bold );
1976           volItem->setText( 0, tr( "VOLUME_3D_ELEMENTS" ) );
1977           volItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );
1978           //ElementDiameter3D
1979           afunctor.reset( new SMESH::Controls::MaxElementLength3D() );
1980           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1981           QTreeWidgetItem* diam3Item = createItem( cntrItem, Bold );
1982           diam3Item->setText( 0, tr( "MAX_ELEMENT_LENGTH_3D" ) );
1983           diam3Item->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );     
1984         }
1985
1986         // gravity center
1987         XYZ gc = gravityCenter( e );
1988         QTreeWidgetItem* gcItem = createItem( elemItem, Bold );
1989         gcItem->setText( 0, SMESHGUI_ElemInfo::tr( "GRAVITY_CENTER" ) );
1990         QTreeWidgetItem* xItem = createItem( gcItem );
1991         xItem->setText( 0, "X" );
1992         xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1993         QTreeWidgetItem* yItem = createItem( gcItem );
1994         yItem->setText( 0, "Y" );
1995         yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1996         QTreeWidgetItem* zItem = createItem( gcItem );
1997         zItem->setText( 0, "Z" );
1998         zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1999         // element position
2000         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
2001         if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
2002           if ( !CORBA::is_nil( aMesh ) ) {
2003             SMESH::ElementPosition pos = aMesh->GetElementPosition( id );
2004             int shapeID = pos.shapeID;
2005             if ( shapeID > 0 ) {
2006               QTreeWidgetItem* shItem = createItem( elemItem, Bold );
2007               QString shapeType;
2008               switch ( pos.shapeType ) {
2009               case GEOM::EDGE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );   break;
2010               case GEOM::FACE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );   break;
2011               case GEOM::VERTEX: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" ); break;
2012               case GEOM::SOLID:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );  break;
2013               case GEOM::SHELL:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHELL" );  break;
2014               default:           shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHAPE" );  break;
2015               }
2016               shItem->setText( 0, SMESHGUI_ElemInfo::tr( "POSITION" ) );
2017               shItem->setText( 1, QString( "%1 #%2" ).arg( shapeType ).arg( shapeID ) );
2018             }
2019           }
2020         }
2021         // groups element belongs to
2022         if ( !CORBA::is_nil( aMesh ) ) {
2023           SMESH::ListOfGroups_var  groups = aMesh->GetGroups();
2024           QTreeWidgetItem* groupsItem = 0;
2025           for ( int i = 0; i < groups->length(); i++ ) {
2026             SMESH::SMESH_GroupBase_var aGrp = groups[i];
2027             if ( CORBA::is_nil( aGrp ) ) continue;
2028             QString aName = aGrp->GetName();
2029             if ( aGrp->GetType() != SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
2030               if ( !groupsItem ) {
2031                 groupsItem = createItem( elemItem, Bold );
2032                 groupsItem->setText( 0, SMESHGUI_AddInfo::tr( "GROUPS" ) );
2033               }
2034               QTreeWidgetItem* it = createItem( groupsItem, Bold );
2035               it->setText( 0, aName.trimmed() );
2036               if ( grp_details ) {
2037                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
2038                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
2039                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
2040                 
2041                 // type : group on geometry, standalone group, group on filter
2042                 QTreeWidgetItem* typeItem = createItem( it );
2043                 typeItem->setText( 0, SMESHGUI_AddInfo::tr( "TYPE" ) );
2044                 if ( !CORBA::is_nil( aStdGroup ) ) {
2045                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
2046                 }
2047                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
2048                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
2049                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
2050                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
2051                   if ( sobj ) {
2052                     QTreeWidgetItem* gobjItem = createItem( typeItem );
2053                     gobjItem->setText( 0, SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) );
2054                     gobjItem->setText( 1, sobj->GetName().c_str() );
2055                   }
2056                 }
2057                 else if ( !CORBA::is_nil( aFltGroup ) ) {
2058                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
2059                 }
2060                 
2061                 // size
2062                 QTreeWidgetItem* sizeItem = createItem( it );
2063                 sizeItem->setText( 0, SMESHGUI_AddInfo::tr( "SIZE" ) );
2064                 sizeItem->setText( 1, QString::number( aGrp->Size() ) );
2065                 
2066                 // color
2067                 SALOMEDS::Color color = aGrp->GetColor();
2068                 QTreeWidgetItem* colorItem = createItem( it );
2069                 colorItem->setText( 0, SMESHGUI_AddInfo::tr( "COLOR" ) );
2070                 colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
2071               }
2072             }
2073           }
2074         }
2075       }
2076     }
2077   }
2078 }
2079
2080 /*!
2081   \brief Internal clean-up (reset widget)
2082 */
2083 void SMESHGUI_TreeElemInfo::clearInternal()
2084 {
2085   myInfo->clear();
2086   myInfo->repaint();
2087 }
2088
2089 /*!
2090   \brief Create new tree item.
2091   \param parent parent tree widget item
2092   \param flags item flag
2093   \return new tree widget item
2094 */
2095 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int flags )
2096 {
2097   QTreeWidgetItem* item;
2098   if ( parent )
2099     item = new QTreeWidgetItem( parent );
2100   else
2101     item = new QTreeWidgetItem( myInfo );
2102
2103   item->setFlags( item->flags() | Qt::ItemIsEditable );
2104
2105   QFont f = item->font( 0 );
2106   f.setBold( true );
2107   for ( int i = 0; i < myInfo->columnCount(); i++ ) {
2108     if ( ( flags & Bold ) && ( i == 0 || flags & All ) )
2109       item->setFont( i, f );
2110   }
2111
2112   item->setExpanded( true );
2113   return item;
2114 }
2115
2116 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2117 {
2118   QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2119   if ( widgets.isEmpty() ) return;
2120   QTreeWidgetItem* aTreeItem = widgets.first();
2121   int type = aTreeItem->data( 1, TypeRole ).toInt();
2122   int id   = aTreeItem->data( 1, IdRole ).toInt();
2123   QMenu menu;
2124   QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ) );
2125   if ( type == ElemConnectivity && id > 0 && menu.exec( e->globalPos() ) == a )
2126     emit( itemInfo( id ) );
2127   else if ( type == NodeConnectivity && menu.exec( e->globalPos() ) == a )
2128     emit( itemInfo( aTreeItem->text( 1 ) ) );
2129 }
2130
2131 void  SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
2132 {
2133   if ( theItem ) {
2134     int type = theItem->data( 1, TypeRole ).toInt();
2135     int id   = theItem->data( 1, IdRole ).toInt();
2136     if ( type == ElemConnectivity && id > 0 )
2137       emit( itemInfo( id ) );
2138     else if ( type == NodeConnectivity )
2139       emit( itemInfo( theItem->text( 1 ) ) );
2140   }
2141 }
2142
2143 void SMESHGUI_TreeElemInfo::saveInfo( QTextStream &out )
2144 {
2145   out << QString( 12, '-' ) << "\n";
2146   out << SMESHGUI_ElemInfo::tr( "ELEM_INFO" ) << "\n";
2147   out << QString( 12, '-' ) << "\n";
2148
2149   QTreeWidgetItemIterator it( myInfo );
2150   while ( *it ) {
2151     if ( !( *it )->text(0).isEmpty() ) {
2152       out << QString( SPACING_INFO * itemDepth( *it ), ' ' ) << ( *it )->text(0);
2153       if ( !( *it )->text(1).isEmpty() ) out << ": " << ( *it )->text(1);
2154       out << "\n";
2155     }
2156     ++it;
2157   }
2158   out << "\n";
2159 }
2160
2161 /*!
2162   \class GrpComputor
2163   \brief Mesh information computer
2164   \internal
2165   
2166   The class is created for different computation operation. Currently it is used
2167   to compute number of underlying nodes for the groups.
2168 */
2169
2170 /*!
2171   \brief Contructor
2172 */
2173 GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* item, QObject* parent )
2174   : QObject( parent ), myItem( item )
2175 {
2176   myGroup = SMESH::SMESH_GroupBase::_narrow( grp );
2177 }
2178
2179 /*!
2180   \brief Compute function
2181 */
2182 void GrpComputor::compute()
2183 {
2184   if ( !CORBA::is_nil( myGroup ) && myItem ) {
2185     QTreeWidgetItem* item = myItem;
2186     myItem = 0;
2187     int nbNodes = myGroup->GetNumberOfNodes();
2188     item->treeWidget()->removeItemWidget( item, 1 );
2189     item->setText( 1, QString::number( nbNodes ));
2190   }
2191 }
2192
2193 /*!
2194   \class SMESHGUI_AddInfo
2195   \brief The wigdet shows additional information on the mesh object.
2196 */
2197
2198 /*!
2199   \brief Constructor
2200   \param parent parent widget
2201 */
2202 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent )
2203 : QTreeWidget( parent )
2204 {
2205   setColumnCount( 2 );
2206   header()->setStretchLastSection( true );
2207   header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2208   header()->hide();
2209 }
2210
2211 /*!
2212   \brief Destructor
2213 */
2214 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2215 {
2216 }
2217
2218 /*!
2219   \brief Show additional information on the selected object
2220   \param obj object being processed (mesh, sub-mesh, group, ID source)
2221 */
2222 void SMESHGUI_AddInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
2223 {
2224   setProperty( "group_index", 0 );
2225   setProperty( "submesh_index",  0 );
2226   myComputors.clear();
2227   clear();
2228
2229   if ( CORBA::is_nil( obj ) ) return;
2230
2231   _PTR(SObject) sobj = SMESH::ObjectToSObject( obj );
2232   if ( !sobj ) return;
2233
2234   // name
2235   QTreeWidgetItem* nameItem = createItem( 0, Bold | All );
2236   nameItem->setText( 0, tr( "NAME" ) );
2237   nameItem->setText( 1, sobj->GetName().c_str() );
2238   
2239   SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
2240   SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
2241   SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
2242   
2243   if ( !aMesh->_is_nil() )
2244     meshInfo( aMesh, nameItem );
2245   else if ( !aSubMesh->_is_nil() )
2246     subMeshInfo( aSubMesh, nameItem );
2247   else if ( !aGroup->_is_nil() )
2248     groupInfo( aGroup.in(), nameItem );
2249 }
2250
2251 /*!
2252   \brief Create new tree item.
2253   \param parent parent tree widget item
2254   \param flags item flag
2255   \return new tree widget item
2256 */
2257 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int flags )
2258 {
2259   QTreeWidgetItem* item;
2260
2261   if ( parent )
2262     item = new QTreeWidgetItem( parent );
2263   else
2264     item = new QTreeWidgetItem( this );
2265
2266   //item->setFlags( item->flags() | Qt::ItemIsEditable );
2267
2268   QFont f = item->font( 0 );
2269   f.setBold( true );
2270   for ( int i = 0; i < columnCount(); i++ ) {
2271     if ( ( flags & Bold ) && ( i == 0 || flags & All ) )
2272       item->setFont( i, f );
2273   }
2274
2275   item->setExpanded( true );
2276   return item;
2277 }
2278
2279 /*!
2280   \brief Show mesh info
2281   \param mesh mesh object
2282   \param parent parent tree item
2283 */
2284 void SMESHGUI_AddInfo::meshInfo( SMESH::SMESH_Mesh_ptr mesh, QTreeWidgetItem* parent )
2285 {
2286   // type
2287   GEOM::GEOM_Object_var shape = mesh->GetShapeToMesh();
2288   SMESH::MedFileInfo_var inf = mesh->GetMEDFileInfo();
2289   QTreeWidgetItem* typeItem = createItem( parent, Bold );
2290   typeItem->setText( 0, tr( "TYPE" ) );
2291   if ( !CORBA::is_nil( shape ) ) {
2292     typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2293     _PTR(SObject) sobj = SMESH::ObjectToSObject( shape );
2294     if ( sobj ) {
2295       QTreeWidgetItem* gobjItem = createItem( typeItem );
2296       gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2297       gobjItem->setText( 1, sobj->GetName().c_str() );
2298     }
2299   }
2300   else if ( strlen( (char*)inf->fileName ) > 0 ) {
2301     typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2302     QTreeWidgetItem* fileItem = createItem( typeItem );
2303     fileItem->setText( 0, tr( "FILE_NAME" ) );
2304     fileItem->setText( 1, (char*)inf->fileName );
2305   }
2306   else {
2307     typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2308   }
2309   
2310   // groups
2311   myGroups = mesh->GetGroups();
2312   showGroups();
2313
2314   // sub-meshes
2315   mySubMeshes = mesh->GetSubMeshes();
2316   showSubMeshes();
2317 }
2318
2319 /*!
2320   \brief Show sub-mesh info
2321   \param subMesh sub-mesh object
2322   \param parent parent tree item
2323 */
2324 void SMESHGUI_AddInfo::subMeshInfo( SMESH::SMESH_subMesh_ptr subMesh, QTreeWidgetItem* parent )
2325 {
2326   bool isShort = parent->parent() != 0;
2327
2328   if ( !isShort ) {
2329     // parent mesh
2330     _PTR(SObject) sobj = SMESH::ObjectToSObject( subMesh->GetFather() );
2331     if ( sobj ) {
2332       QTreeWidgetItem* nameItem = createItem( parent, Bold );
2333       nameItem->setText( 0, tr( "PARENT_MESH" ) );
2334       nameItem->setText( 1, sobj->GetName().c_str() );
2335     }
2336   }
2337   
2338   // shape
2339   GEOM::GEOM_Object_var gobj = subMesh->GetSubShape();
2340   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
2341   if ( sobj ) {
2342     QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2343     gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2344     gobjItem->setText( 1, sobj->GetName().c_str() );
2345   }
2346 }
2347
2348 /*!
2349   \brief Show group info
2350   \param grp mesh group object
2351   \param parent parent tree item
2352 */
2353 void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* parent )
2354 {
2355   bool isShort = parent->parent() != 0;
2356
2357   SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( grp );
2358   SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( grp );
2359   SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( grp );
2360
2361   if ( !isShort ) {
2362     // parent mesh
2363     _PTR(SObject) sobj = SMESH::ObjectToSObject( grp->GetMesh() );
2364     if ( sobj ) {
2365       QTreeWidgetItem* nameItem = createItem( parent, Bold );
2366       nameItem->setText( 0, tr( "PARENT_MESH" ) );
2367       nameItem->setText( 1, sobj->GetName().c_str() );
2368     }
2369   }
2370
2371   // type : group on geometry, standalone group, group on filter
2372   QTreeWidgetItem* typeItem = createItem( parent, Bold );
2373   typeItem->setText( 0, tr( "TYPE" ) );
2374   if ( !CORBA::is_nil( aStdGroup ) ) {
2375     typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2376   }
2377   else if ( !CORBA::is_nil( aGeomGroup ) ) {
2378     typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2379     GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
2380     _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
2381     if ( sobj ) {
2382       QTreeWidgetItem* gobjItem = createItem( typeItem );
2383       gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2384       gobjItem->setText( 1, sobj->GetName().c_str() );
2385     }
2386   }
2387   else if ( !CORBA::is_nil( aFltGroup ) ) {
2388     typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2389   }
2390
2391   if ( !isShort ) {
2392     // entity type
2393     QString etype = tr( "UNKNOWN" );
2394     switch( grp->GetType() ) {
2395     case SMESH::NODE:
2396       etype = tr( "NODE" );
2397       break;
2398     case SMESH::EDGE:
2399       etype = tr( "EDGE" );
2400       break;
2401     case SMESH::FACE:
2402       etype = tr( "FACE" );
2403       break;
2404     case SMESH::VOLUME:
2405       etype = tr( "VOLUME" );
2406       break;
2407     case SMESH::ELEM0D:
2408       etype = tr( "0DELEM" );
2409       break;
2410     case SMESH::BALL:
2411       etype = tr( "BALL" );
2412       break;
2413     default:
2414       break;
2415     }
2416     QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2417     etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2418     etypeItem->setText( 1, etype );
2419   }
2420
2421   // size
2422   QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2423   sizeItem->setText( 0, tr( "SIZE" ) );
2424   sizeItem->setText( 1, QString::number( grp->Size() ) );
2425
2426   // color
2427   SALOMEDS::Color color = grp->GetColor();
2428   QTreeWidgetItem* colorItem = createItem( parent, Bold );
2429   colorItem->setText( 0, tr( "COLOR" ) );
2430   colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
2431
2432   // nb of underlying nodes
2433   if ( grp->GetType() != SMESH::NODE) {
2434     QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2435     nodesItem->setText( 0, tr( "NB_NODES" ) );
2436     int nbNodesLimit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
2437     SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
2438     bool meshLoaded = mesh->IsLoaded();
2439     bool toShowNodes = ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit );
2440     if ( toShowNodes && meshLoaded ) {
2441       // already calculated and up-to-date
2442       nodesItem->setText( 1, QString::number( grp->GetNumberOfNodes() ) );
2443     }
2444     else {
2445       QPushButton* btn = new QPushButton( tr( meshLoaded ? "COMPUTE" : "LOAD"), this );
2446       setItemWidget( nodesItem, 1, btn );
2447       GrpComputor* comp = new GrpComputor( grp, nodesItem, this ); 
2448       connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2449       myComputors.append( comp );
2450       if ( !meshLoaded )
2451         connect( btn, SIGNAL( clicked() ), this, SLOT( changeLoadToCompute() ) );
2452     }
2453   }
2454 }
2455
2456 void SMESHGUI_AddInfo::showGroups()
2457 {
2458   myComputors.clear();
2459
2460   QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
2461   if ( !parent ) return;
2462
2463   int idx = property( "group_index" ).toInt();
2464
2465   QTreeWidgetItem* itemGroups = 0;
2466   for ( int i = 0; i < parent->childCount() && !itemGroups; i++ ) {
2467     if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GROUPS_ID ) {
2468       itemGroups = parent->child( i );
2469       ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemGroups, 1 ) );
2470       if ( extra )
2471         extra->updateControls( myGroups->length(), idx );
2472       while ( itemGroups->childCount() ) delete itemGroups->child( 0 ); // clear child items
2473     }
2474   }
2475
2476   QMap<int, QTreeWidgetItem*> grpItems;
2477   for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)myGroups->length() ); i++ ) {
2478     SMESH::SMESH_GroupBase_var grp = myGroups[i];
2479     if ( CORBA::is_nil( grp ) ) continue;
2480     _PTR(SObject) grpSObj = SMESH::ObjectToSObject( grp );
2481     if ( !grpSObj ) continue;
2482
2483     int grpType = grp->GetType();
2484
2485     if ( !itemGroups ) {
2486       // create top-level groups container item
2487       itemGroups = createItem( parent, Bold | All );
2488       itemGroups->setText( 0, tr( "GROUPS" ) );
2489       itemGroups->setData( 0, Qt::UserRole, GROUPS_ID );
2490
2491       // total number of groups > 10, show extra widgets for info browsing
2492       if ( myGroups->length() > MAXITEMS ) {
2493         ExtraWidget* extra = new ExtraWidget( this, true );
2494         connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2495         connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2496         setItemWidget( itemGroups, 1, extra );
2497         extra->updateControls( myGroups->length(), idx );
2498       }
2499     }
2500
2501     if ( grpItems.find( grpType ) == grpItems.end() ) {
2502       grpItems[ grpType ] = createItem( itemGroups, Bold | All );
2503       grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2504       itemGroups->insertChild( grpType-1, grpItems[ grpType ] );
2505     }
2506   
2507     // group name
2508     QTreeWidgetItem* grpNameItem = createItem( grpItems[ grpType ] );
2509     grpNameItem->setText( 0, QString( grpSObj->GetName().c_str() ).trimmed() ); // name is trimmed
2510
2511     // group info
2512     groupInfo( grp.in(), grpNameItem );
2513   }
2514 }
2515
2516 void SMESHGUI_AddInfo::showSubMeshes()
2517 {
2518   QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
2519   if ( !parent ) return;
2520
2521   int idx = property( "submesh_index" ).toInt();
2522
2523   QTreeWidgetItem* itemSubMeshes = 0;
2524   for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ ) {
2525     if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SUBMESHES_ID ) {
2526       itemSubMeshes = parent->child( i );
2527       ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemSubMeshes, 1 ) );
2528       if ( extra )
2529         extra->updateControls( mySubMeshes->length(), idx );
2530       while ( itemSubMeshes->childCount() ) delete itemSubMeshes->child( 0 ); // clear child items
2531     }
2532   }
2533
2534   QMap<int, QTreeWidgetItem*> smItems;
2535   for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)mySubMeshes->length() ); i++ ) {
2536     SMESH::SMESH_subMesh_var sm = mySubMeshes[i];
2537     if ( CORBA::is_nil( sm ) ) continue;
2538     _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm );
2539     if ( !smSObj ) continue;
2540     
2541     GEOM::GEOM_Object_var gobj = sm->GetSubShape();
2542     if ( CORBA::is_nil(gobj ) ) continue;
2543     
2544     int smType = gobj->GetShapeType();
2545     if ( smType == GEOM::COMPSOLID ) smType = GEOM::COMPOUND;
2546
2547     if ( !itemSubMeshes ) {
2548       itemSubMeshes = createItem( parent, Bold | All );
2549       itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2550       itemSubMeshes->setData( 0, Qt::UserRole, SUBMESHES_ID );
2551
2552       // total number of sub-meshes > 10, show extra widgets for info browsing
2553       if ( mySubMeshes->length() > MAXITEMS ) {
2554         ExtraWidget* extra = new ExtraWidget( this, true );
2555         connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2556         connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2557         setItemWidget( itemSubMeshes, 1, extra );
2558         extra->updateControls( mySubMeshes->length(), idx );
2559       }
2560     }
2561          
2562     if ( smItems.find( smType ) == smItems.end() ) {
2563       smItems[ smType ] = createItem( itemSubMeshes, Bold | All );
2564       smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2565       itemSubMeshes->insertChild( smType, smItems[ smType ] );
2566     }
2567     
2568     // submesh name
2569     QTreeWidgetItem* smNameItem = createItem( smItems[ smType ] );
2570     smNameItem->setText( 0, QString( smSObj->GetName().c_str() ).trimmed() ); // name is trimmed
2571     
2572     // submesh info
2573     subMeshInfo( sm.in(), smNameItem );
2574   }
2575 }
2576
2577 /*!
2578  * \brief Change button label of "nb underlying node" group from "Load" to "Compute"
2579  */
2580 void SMESHGUI_AddInfo::changeLoadToCompute()
2581 {
2582   for ( int i = 0; i < myComputors.count(); ++i )
2583   {
2584     if ( QTreeWidgetItem* item = myComputors[i]->getItem() )
2585     {
2586       if ( QPushButton* btn = qobject_cast<QPushButton*>( itemWidget ( item, 1 ) ) )
2587         btn->setText( tr("COMPUTE") );
2588     }
2589   }
2590 }
2591
2592 void SMESHGUI_AddInfo::showPreviousGroups()
2593 {
2594   int idx = property( "group_index" ).toInt();
2595   setProperty( "group_index", idx-1 );
2596   showGroups();
2597 }
2598
2599 void SMESHGUI_AddInfo::showNextGroups()
2600 {
2601   int idx = property( "group_index" ).toInt();
2602   setProperty( "group_index", idx+1 );
2603   showGroups();
2604 }
2605
2606 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2607 {
2608   int idx = property( "submesh_index" ).toInt();
2609   setProperty( "submesh_index", idx-1 );
2610   showSubMeshes();
2611 }
2612
2613 void SMESHGUI_AddInfo::showNextSubMeshes()
2614 {
2615   int idx = property( "submesh_index" ).toInt();
2616   setProperty( "submesh_index", idx+1 );
2617   showSubMeshes();
2618 }
2619
2620 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2621 {
2622   out << QString( 15, '-')       << "\n";
2623   out << tr( "ADDITIONAL_INFO" ) << "\n";
2624   out << QString( 15, '-' )      << "\n";
2625   QTreeWidgetItemIterator it( this );
2626   while ( *it ) {
2627     if ( !( ( *it )->text(0) ).isEmpty() ) {
2628       out << QString( SPACING_INFO * itemDepth( *it ), ' ' ) << ( *it )->text(0);
2629       if ( ( *it )->text(0)  == tr( "COLOR" ) ) {
2630         out << ": " << ( ( ( *it )->background(1) ).color() ).name();
2631       }
2632       else if ( !( ( *it )->text(1) ).isEmpty() ) out << ": " << ( *it )->text(1);
2633       out << "\n";
2634     }
2635     ++it;
2636   }
2637   out << "\n";
2638 }
2639
2640 /*!
2641   \class SMESHGUI_MeshInfoDlg
2642   \brief Mesh information dialog box
2643 */
2644
2645 /*!
2646   \brief Constructor
2647   \param parent parent widget
2648   \param page specifies the dialog page to be shown at the start-up
2649 */
2650 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
2651 : QDialog( parent ), myActor( 0 )
2652 {
2653   setModal( false );
2654   setAttribute( Qt::WA_DeleteOnClose, true );
2655   setWindowTitle( tr( "MESH_INFO" ) );
2656   setSizeGripEnabled( true );
2657
2658   myTabWidget = new QTabWidget( this );
2659
2660   // base info 
2661
2662   myBaseInfo = new SMESHGUI_MeshInfo( myTabWidget );
2663   myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
2664
2665   // elem info 
2666   
2667   QWidget* w = new QWidget( myTabWidget );
2668
2669   myMode = new QButtonGroup( this );
2670   myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
2671   myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
2672   myMode->button( NodeMode )->setChecked( true );
2673   myID = new QLineEdit( w );
2674   myID->setValidator( new SMESHGUI_IdValidator( this ) );
2675
2676   int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
2677   mode = qMin( 1, qMax( 0, mode ) );
2678   
2679   if ( mode == 0 ) 
2680     myElemInfo = new SMESHGUI_SimpleElemInfo( w );
2681   else
2682     myElemInfo = new SMESHGUI_TreeElemInfo( w );
2683
2684   QGridLayout* elemLayout = new QGridLayout( w );
2685   elemLayout->setMargin( MARGIN );
2686   elemLayout->setSpacing( SPACING );
2687   elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
2688   elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
2689   elemLayout->addWidget( myID, 0, 2 );
2690   elemLayout->addWidget( myElemInfo, 1, 0, 1, 3 );
2691   
2692   myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
2693
2694   // additional info
2695
2696   myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
2697   myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
2698
2699   // controls info
2700
2701   myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
2702   myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
2703
2704   // buttons
2705
2706   QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
2707   okBtn->setAutoDefault( true );
2708   okBtn->setDefault( true );
2709   okBtn->setFocus();
2710   QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
2711   dumpBtn->setAutoDefault( true );
2712   QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
2713   helpBtn->setAutoDefault( true );
2714
2715   QHBoxLayout* btnLayout = new QHBoxLayout;
2716   btnLayout->setSpacing( SPACING );
2717   btnLayout->setMargin( 0 );
2718
2719   btnLayout->addWidget( okBtn );
2720   btnLayout->addWidget( dumpBtn );
2721   btnLayout->addStretch( 10 );
2722   btnLayout->addWidget( helpBtn );
2723
2724   QVBoxLayout* l = new QVBoxLayout ( this );
2725   l->setMargin( MARGIN );
2726   l->setSpacing( SPACING );
2727   l->addWidget( myTabWidget );
2728   l->addLayout( btnLayout );
2729
2730   myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
2731
2732   connect( okBtn,       SIGNAL( clicked() ),              this, SLOT( reject() ) );
2733   connect( dumpBtn,     SIGNAL( clicked() ),              this, SLOT( dump() ) );
2734   connect( helpBtn,     SIGNAL( clicked() ),              this, SLOT( help() ) );
2735   connect( myTabWidget, SIGNAL( currentChanged( int  ) ), this, SLOT( updateSelection() ) );
2736   connect( myMode,      SIGNAL( buttonClicked( int  ) ),  this, SLOT( modeChanged() ) );
2737   connect( myID,        SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
2738   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
2739   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalCloseAllDialogs() ),        this, SLOT( reject() ) );
2740   connect( myElemInfo,  SIGNAL( itemInfo( int ) ),     this, SLOT( showItemInfo( int ) ) );
2741   connect( myElemInfo,  SIGNAL( itemInfo( QString ) ), this, SLOT( showItemInfo( QString ) ) );
2742
2743   updateSelection();
2744 }
2745
2746 /*!
2747   \brief Destructor
2748 */
2749 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
2750 {
2751 }
2752
2753 /*!
2754   \brief Show mesh information
2755   \param IO interactive object
2756 */
2757 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO )
2758 {
2759   SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
2760   if ( !CORBA::is_nil( obj ) ) {
2761     myBaseInfo->showInfo( obj );
2762     myAddInfo->showInfo( obj );
2763     myCtrlInfo->showInfo( obj );
2764
2765     myActor = SMESH::FindActorByEntry( IO->getEntry() );
2766     SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
2767     QString ID;
2768     int nb = 0;
2769     if ( myActor && selector ) {
2770       nb = myMode->checkedId() == NodeMode ? 
2771         SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
2772         SMESH::GetNameOfSelectedNodes( selector, IO, ID );
2773     }
2774     myElemInfo->setSource( myActor ) ;
2775     if ( nb > 0 ) {
2776       myID->setText( ID.trimmed() );
2777       QSet<long> ids;
2778       QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
2779       foreach ( ID, idTxt )
2780         ids << ID.trimmed().toLong();
2781       myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode );
2782     }
2783     else {
2784       myID->clear();
2785       myElemInfo->clear();
2786     }
2787   }
2788 }
2789
2790 /*!
2791   \brief Perform clean-up actions on the dialog box closing.
2792 */
2793 void SMESHGUI_MeshInfoDlg::reject()
2794 {
2795   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
2796   selMgr->clearFilters();
2797   SMESH::SetPointRepresentation( false );
2798   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2799     aViewWindow->SetSelectionMode( ActorSelection );
2800   QDialog::reject();
2801 }
2802
2803 /*!
2804   \brief Process keyboard event
2805   \param e key press event
2806 */
2807 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
2808 {
2809   QDialog::keyPressEvent( e );
2810   if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
2811     e->accept();
2812     help();
2813   }
2814 }
2815
2816 /*!
2817   \brief Reactivate dialog box, when mouse pointer goes into it.
2818 */
2819 void SMESHGUI_MeshInfoDlg::enterEvent( QEvent* )
2820 {
2821   //activate();
2822 }
2823
2824 /*!
2825   \brief Setup selection mode depending on the current dialog box state.
2826 */
2827 void SMESHGUI_MeshInfoDlg::updateSelection()
2828 {
2829   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
2830
2831   disconnect( selMgr, 0, this, 0 );
2832   selMgr->clearFilters();
2833
2834   if ( myTabWidget->currentIndex() == BaseInfo || myTabWidget->currentIndex() == AddInfo || myTabWidget->currentIndex() == CtrlInfo ) {
2835     SMESH::SetPointRepresentation( false );
2836     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2837       aViewWindow->SetSelectionMode( ActorSelection );
2838   }
2839   else {
2840     if ( myMode->checkedId() == NodeMode ) {
2841       SMESH::SetPointRepresentation( true );
2842       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2843         aViewWindow->SetSelectionMode( NodeSelection );
2844     }
2845     else {
2846       SMESH::SetPointRepresentation( false );
2847       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2848         aViewWindow->SetSelectionMode( CellSelection );
2849     }
2850   }
2851
2852   QString oldID = myID->text().trimmed();
2853   SMESH_Actor* oldActor = myActor;
2854   myID->clear();
2855   
2856   connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
2857   updateInfo();
2858   
2859   if ( oldActor == myActor && myActor && !oldID.isEmpty() ) {
2860     myID->setText( oldID );
2861     idChanged();
2862   }
2863 }
2864
2865 /*!
2866   \brief Show help page
2867 */
2868 void SMESHGUI_MeshInfoDlg::help()
2869 {
2870   SMESH::ShowHelpFile( ( myTabWidget->currentIndex() == BaseInfo || myTabWidget->currentIndex() == AddInfo ) ?
2871                        "mesh_infos_page.html#advanced_mesh_infos_anchor" : 
2872                        "mesh_infos_page.html#mesh_element_info_anchor" );
2873 }
2874
2875 /*!
2876   \brief Show mesh information
2877 */
2878 void SMESHGUI_MeshInfoDlg::updateInfo()
2879 {
2880   SUIT_OverrideCursor wc;
2881
2882   SALOME_ListIO selected;
2883   SMESHGUI::selectionMgr()->selectedObjects( selected );
2884
2885   if ( selected.Extent() == 1 ) {
2886     Handle(SALOME_InteractiveObject) IO = selected.First();
2887     showInfo( IO );
2888   }
2889 //   else {
2890 //     myBaseInfo->clear();
2891 //     myElemInfo->clear();
2892 //     myAddInfo->clear();
2893 //   }
2894 }
2895
2896 /*!
2897   \brief Activate dialog box
2898 */
2899 void SMESHGUI_MeshInfoDlg::activate()
2900 {
2901   SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
2902   SMESHGUI::GetSMESHGUI()->SetActiveDialogBox( this );
2903   myTabWidget->setEnabled( true );
2904   updateSelection();
2905 }
2906
2907 /*!
2908   \brief Deactivate dialog box
2909 */
2910 void SMESHGUI_MeshInfoDlg::deactivate()
2911 {
2912   myTabWidget->setEnabled( false );
2913   disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
2914 }
2915
2916 /*!
2917   \brief Called when users switches between node / element modes.
2918 */
2919 void SMESHGUI_MeshInfoDlg::modeChanged()
2920 {
2921   myID->clear();
2922   updateSelection();
2923 }
2924
2925 /*!
2926   \brief Caled when users prints mesh element ID in the corresponding field.
2927 */
2928 void SMESHGUI_MeshInfoDlg::idChanged()
2929 {
2930   SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
2931   if ( myActor && selector ) {
2932     Handle(SALOME_InteractiveObject) IO = myActor->getIO();
2933     TColStd_MapOfInteger ID;
2934     QSet<long> ids;
2935     QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
2936     foreach ( QString tid, idTxt ) {
2937       long id = tid.trimmed().toLong();
2938       const SMDS_MeshElement* e = myMode->checkedId() == ElemMode ? 
2939         myActor->GetObject()->GetMesh()->FindElement( id ) :
2940         myActor->GetObject()->GetMesh()->FindNode( id );
2941       if ( e ) {
2942         ID.Add( id );
2943         ids << id;
2944       }
2945     }
2946     selector->AddOrRemoveIndex( IO, ID, false );
2947     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) {
2948       aViewWindow->highlight( IO, true, true );
2949       aViewWindow->Repaint();
2950     }
2951     myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode );
2952   }
2953 }
2954
2955 void SMESHGUI_MeshInfoDlg::showItemInfo( int id )
2956 {
2957   if ( id > 0 &&  myActor->GetObject()->GetMesh()->FindNode( id ) ) {
2958     myMode->button( NodeMode )->click();
2959     myID->setText( QString::number( id ) );
2960   }
2961 }
2962
2963 void SMESHGUI_MeshInfoDlg::showItemInfo( const QString& theStr )
2964 {
2965   if ( !theStr.isEmpty() ) {
2966     myMode->button( ElemMode )->click();
2967     myID->setText( theStr );
2968   }
2969 }
2970
2971 void SMESHGUI_MeshInfoDlg::dump()
2972 {
2973   SUIT_Application* app = SUIT_Session::session()->activeApplication();
2974   if ( !app ) return;
2975   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study *>( app->activeStudy() );
2976   if ( !appStudy ) return;
2977   _PTR( Study ) aStudy = appStudy->studyDS();
2978
2979   QStringList aFilters;
2980   aFilters.append( tr( "TEXT_FILES" ) );
2981
2982   bool anIsBase = true;
2983   bool anIsElem = true;
2984   bool anIsAdd  = true;
2985   bool anIsCtrl = true;
2986
2987   if ( SUIT_ResourceMgr* aResourceMgr = SMESHGUI::resourceMgr() ) {
2988     anIsBase = aResourceMgr->booleanValue( "SMESH", "info_dump_base", anIsBase );
2989     anIsElem = aResourceMgr->booleanValue( "SMESH", "info_dump_elem", anIsElem );
2990     anIsAdd  = aResourceMgr->booleanValue( "SMESH", "info_dump_add",  anIsAdd );
2991     anIsCtrl = aResourceMgr->booleanValue( "SMESH", "info_dump_ctrl", anIsCtrl );
2992   }
2993
2994   DumpFileDlg fd( this );
2995   fd.setWindowTitle( tr( "SAVE_INFO" ) );
2996   fd.setFilters( aFilters );
2997   fd.myBaseChk->setChecked( anIsBase );
2998   fd.myElemChk->setChecked( anIsElem );
2999   fd.myAddChk ->setChecked( anIsAdd );
3000   fd.myCtrlChk->setChecked( anIsCtrl );
3001   if ( fd.exec() == QDialog::Accepted )
3002   {
3003     QString aFileName = fd.selectedFile();
3004
3005     bool toBase = fd.myBaseChk->isChecked();
3006     bool toElem = fd.myElemChk->isChecked();
3007     bool toAdd  = fd.myAddChk->isChecked();
3008     bool toCtrl = fd.myCtrlChk->isChecked();
3009
3010     if ( !aFileName.isEmpty() ) {
3011       QFileInfo aFileInfo( aFileName );
3012       if ( aFileInfo.isDir() )
3013         return;
3014  
3015       QFile aFile( aFileName );
3016       if ( !aFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
3017         return;
3018       
3019       QTextStream out( &aFile );
3020       
3021       if ( toBase ) myBaseInfo->saveInfo( out );
3022       if ( toElem ) myElemInfo->saveInfo( out );
3023       if ( toAdd )  myAddInfo ->saveInfo( out );
3024       if ( toCtrl ) myCtrlInfo->saveInfo( out );
3025     }
3026   }
3027 }
3028
3029 /*!
3030   \class SMESHGUI_CtrlInfo
3031   \brief Class for the mesh controls information widget.
3032 */
3033
3034 /*!
3035   \brief Constructor
3036   \param parent parent widget
3037 */
3038 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent )
3039   : QFrame( parent ), myPlot( 0 ), myPlot3D( 0 )
3040 {
3041   setFrameStyle( StyledPanel | Sunken );
3042
3043   myMainLayout = new QGridLayout( this );
3044   myMainLayout->setMargin( MARGIN );
3045   myMainLayout->setSpacing( SPACING );
3046
3047   // name
3048   QLabel* aNameLab = new QLabel( tr( "NAME_LAB" ), this );
3049   QLabel* aName = createField();
3050   aName->setMinimumWidth( 150 );
3051   myWidgets << aName;
3052
3053   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
3054   QIcon aComputeIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3055
3056   SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3057
3058   // nodes info
3059   QLabel* aNodesLab = new QLabel( tr( "NODES_INFO" ), this );
3060   QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3061   QLabel* aNodesFree = createField();
3062   myWidgets << aNodesFree;
3063   myPredicates << aFilterMgr->CreateFreeNodes();
3064   //
3065   QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3066   QLabel* aNodesDouble = createField();
3067   myWidgets << aNodesDouble;
3068   myPredicates << aFilterMgr->CreateEqualNodes();
3069   QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3070   myToleranceWidget = new SMESHGUI_SpinBox( this );
3071   myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3072   myToleranceWidget->setAcceptNames( false );
3073   myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3074
3075   // edges info
3076   QLabel* anEdgesLab = new QLabel( tr( "EDGES_INFO" ),  this );
3077   QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ),     this );
3078   QLabel* anEdgesDouble = createField();
3079   myWidgets << anEdgesDouble;
3080   myPredicates << aFilterMgr->CreateEqualEdges();
3081
3082   // faces info
3083   QLabel* aFacesLab = new QLabel( tr( "FACES_INFO" ), this );
3084   QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3085   QLabel* aFacesDouble = createField();
3086   myWidgets << aFacesDouble;
3087   myPredicates << aFilterMgr->CreateEqualFaces();
3088   QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3089   QLabel* aFacesOver = createField();
3090   myWidgets << aFacesOver;
3091   myPredicates << aFilterMgr->CreateOverConstrainedFace();
3092   QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3093   myPlot = createPlot( this );
3094   myAspectRatio = aFilterMgr->CreateAspectRatio();
3095  
3096   // volumes info
3097   QLabel* aVolumesLab = new QLabel( tr( "VOLUMES_INFO" ), this );
3098   QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3099   QLabel* aVolumesDouble = createField();
3100   myWidgets << aVolumesDouble;
3101   myPredicates << aFilterMgr->CreateEqualVolumes();
3102   QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3103   QLabel* aVolumesOver = createField();
3104   myWidgets << aVolumesOver;
3105   myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3106   QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3107   myPlot3D = createPlot( this );
3108   myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3109
3110   QToolButton* aFreeNodesBtn = new QToolButton( this );
3111   aFreeNodesBtn->setIcon(aComputeIcon);
3112   myButtons << aFreeNodesBtn;       //0
3113
3114   QToolButton* aDoubleNodesBtn = new QToolButton( this );
3115   aDoubleNodesBtn->setIcon(aComputeIcon);
3116   myButtons << aDoubleNodesBtn;     //1
3117
3118   QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3119   aDoubleEdgesBtn->setIcon(aComputeIcon);
3120   myButtons << aDoubleEdgesBtn;     //2
3121
3122   QToolButton* aDoubleFacesBtn = new QToolButton( this );
3123   aDoubleFacesBtn->setIcon(aComputeIcon);
3124   myButtons << aDoubleFacesBtn;     //3
3125
3126   QToolButton* aOverContFacesBtn = new QToolButton( this );
3127   aOverContFacesBtn->setIcon(aComputeIcon);
3128   myButtons << aOverContFacesBtn;   //4
3129
3130   QToolButton* aComputeFaceBtn = new QToolButton( this );
3131   aComputeFaceBtn->setIcon(aComputeIcon);
3132   myButtons << aComputeFaceBtn;     //5
3133
3134   QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3135   aDoubleVolumesBtn->setIcon(aComputeIcon);
3136   myButtons << aDoubleVolumesBtn;   //6
3137
3138   QToolButton* aOverContVolumesBtn = new QToolButton( this );
3139   aOverContVolumesBtn->setIcon(aComputeIcon);
3140   myButtons << aOverContVolumesBtn; //7
3141
3142   QToolButton* aComputeVolumeBtn = new QToolButton( this );
3143   aComputeVolumeBtn->setIcon(aComputeIcon);
3144   myButtons << aComputeVolumeBtn;   //8
3145
3146   connect( aComputeFaceBtn,   SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3147   connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3148   connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3149   connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3150   connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3151   connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3152   connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3153   connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3154   connect( aOverContVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3155   connect( myToleranceWidget, SIGNAL(valueChanged(double)), this, SLOT( setTolerance( double )));
3156
3157   setFontAttributes( aNameLab );
3158   setFontAttributes( aNodesLab );
3159   setFontAttributes( anEdgesLab );
3160   setFontAttributes( aFacesLab );
3161   setFontAttributes( aVolumesLab );
3162
3163   myMainLayout->addWidget( aNameLab,           0, 0 );       //0
3164   myMainLayout->addWidget( aName,              0, 1, 1, 2 ); //1
3165   myMainLayout->addWidget( aNodesLab,          1, 0, 1, 3 ); //2
3166   myMainLayout->addWidget( aNodesFreeLab,      2, 0 );       //3
3167   myMainLayout->addWidget( aNodesFree,         2, 1 );       //4
3168   myMainLayout->addWidget( aFreeNodesBtn,      2, 2 );       //5
3169   myMainLayout->addWidget( aNodesDoubleLab,    3, 0 );       //6
3170   myMainLayout->addWidget( aNodesDouble,       3, 1 );       //7
3171   myMainLayout->addWidget( aDoubleNodesBtn,    3, 2 );       //8
3172   myMainLayout->addWidget( aToleranceLab,      4, 0 );       //9
3173   myMainLayout->addWidget( myToleranceWidget,  4, 1 );       //10
3174   myMainLayout->addWidget( anEdgesLab,         5, 0, 1, 3 ); //11
3175   myMainLayout->addWidget( anEdgesDoubleLab,   6, 0 );       //12
3176   myMainLayout->addWidget( anEdgesDouble,      6, 1 );       //13
3177   myMainLayout->addWidget( aDoubleEdgesBtn,    6, 2 );       //14
3178   myMainLayout->addWidget( aFacesLab,          7, 0, 1, 3 ); //15
3179   myMainLayout->addWidget( aFacesDoubleLab,    8, 0 );       //16
3180   myMainLayout->addWidget( aFacesDouble,       8, 1 );       //17
3181   myMainLayout->addWidget( aDoubleFacesBtn,    8, 2 );       //18
3182   myMainLayout->addWidget( aFacesOverLab,      9, 0 );       //19
3183   myMainLayout->addWidget( aFacesOver,         9, 1 );       //20
3184   myMainLayout->addWidget( aOverContFacesBtn,  9, 2 );       //21
3185   myMainLayout->addWidget( anAspectRatioLab,   10, 0 );      //22
3186   myMainLayout->addWidget( aComputeFaceBtn,    10, 2 );      //23
3187   myMainLayout->addWidget( myPlot,             11, 0, 1, 3 );//24
3188   myMainLayout->addWidget( aVolumesLab,        12, 0, 1, 3 );//25
3189   myMainLayout->addWidget( aVolumesDoubleLab,  13, 0 );      //26
3190   myMainLayout->addWidget( aVolumesDouble,     13, 1 );      //27
3191   myMainLayout->addWidget( aDoubleVolumesBtn,  13, 2 );      //28
3192   myMainLayout->addWidget( aVolumesOverLab,    14, 0 );      //28
3193   myMainLayout->addWidget( aVolumesOver,       14, 1 );      //30
3194   myMainLayout->addWidget( aOverContVolumesBtn,14, 2 );      //31
3195   myMainLayout->addWidget( anAspectRatio3DLab, 15, 0 );      //32
3196   myMainLayout->addWidget( aComputeVolumeBtn,  15, 2 );      //33
3197   myMainLayout->addWidget( myPlot3D,           16, 0, 1, 3 );//34
3198  
3199   myMainLayout->setColumnStretch(  0,  0 );
3200   myMainLayout->setColumnStretch(  1,  5 );
3201   myMainLayout->setRowStretch   ( 11,  5 );
3202   myMainLayout->setRowStretch   ( 16,  5 );
3203   myMainLayout->setRowStretch   ( 17,  1 );
3204
3205   clearInternal();
3206 }
3207
3208 /*!
3209   \brief Destructor
3210 */
3211 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3212 {}
3213
3214 /*!
3215   \brief Change widget font attributes (bold, ...).
3216   \param w widget
3217   \param attr font attributes (XORed flags)
3218 */
3219 void SMESHGUI_CtrlInfo::setFontAttributes( QWidget* w )
3220 {
3221   if ( w ) {
3222     QFont f = w->font();
3223     f.setBold( true );
3224     w->setFont( f );
3225   }
3226 }
3227
3228 /*!
3229   \brief Create info field
3230   \return new info field
3231 */
3232 QLabel* SMESHGUI_CtrlInfo::createField()
3233 {
3234   QLabel* lab = new QLabel( this );
3235   lab->setFrameStyle( StyledPanel | Sunken );
3236   lab->setAlignment( Qt::AlignCenter );
3237   lab->setAutoFillBackground( true );
3238   QPalette pal = lab->palette();
3239   pal.setColor( QPalette::Window, QApplication::palette().color( QPalette::Active, QPalette::Base ) );
3240   lab->setPalette( pal );
3241   lab->setMinimumWidth( 60 );
3242   return lab;
3243 }
3244
3245 /*!
3246   \brief Create QwtPlot
3247   \return new QwtPlot
3248 */
3249 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3250 {
3251   QwtPlot* aPlot = new QwtPlot( parent );
3252   aPlot->setMinimumSize( 100, 100 );
3253   QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3254   xFont.setPointSize( 5 );
3255   QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3256   yFont.setPointSize( 5 );
3257   aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3258   aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3259   aPlot->replot();
3260   return aPlot;
3261 }
3262
3263 /*!
3264   \brief Show controls information on the selected object
3265 */
3266 void SMESHGUI_CtrlInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
3267 {
3268   clearInternal();
3269
3270   myObject = SMESH::SMESH_IDSource::_duplicate( obj );
3271   if ( myObject->_is_nil() ) return;
3272
3273   if ( _PTR(SObject) aSO = SMESH::FindSObject( obj ))
3274     myWidgets[0]->setText( aSO->GetName().c_str() );
3275
3276   SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3277   if ( mesh->_is_nil() ) return;
3278
3279   const bool meshLoaded = mesh->IsLoaded();
3280   if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3281     // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3282     for ( int i = 0; i < myButtons.count(); ++i )
3283       myButtons[i]->setEnabled( true );
3284
3285   SMESH::long_array_var nbElemsByType = obj->GetNbElementsByType();
3286   if ( ! &nbElemsByType.in() ) return;
3287
3288   const CORBA::Long ctrlLimit =
3289     meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3290
3291   // nodes info
3292   const CORBA::Long nbNodes =   nbElemsByType[ SMESH::NODE ];
3293   const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3294                                 nbElemsByType[ SMESH::FACE ] +
3295                                 nbElemsByType[ SMESH::VOLUME ] );
3296   if ( nbNodes + nbElems > 0 ) {
3297     if ( Max( (int)nbNodes, (int)nbElems ) <= ctrlLimit ) {
3298       // free nodes
3299       computeFreeNodesInfo();
3300       // double nodes
3301       computeDoubleNodesInfo();
3302     }
3303     else {
3304       myButtons[0]->setEnabled( true );
3305       myButtons[1]->setEnabled( true );
3306     }
3307   }
3308   else {
3309     for( int i=2; i<=10; i++)
3310       myMainLayout->itemAt(i)->widget()->setVisible( false );
3311   }
3312
3313   // edges info
3314   if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3315     // double edges
3316     if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3317       computeDoubleEdgesInfo();
3318     else
3319       myButtons[2]->setEnabled( true );
3320   }
3321   else {
3322     for( int i=11; i<=14; i++)
3323       myMainLayout->itemAt(i)->widget()->setVisible( false );
3324   }
3325  
3326   // faces info
3327   if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3328     if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3329       // double faces
3330       computeDoubleFacesInfo();
3331       // over constrained faces
3332       computeOverConstrainedFacesInfo();
3333       // aspect Ratio histogram
3334       computeAspectRatio();
3335     }
3336     else {
3337       myButtons[3]->setEnabled( true );
3338       myButtons[4]->setEnabled( true );
3339       myButtons[5]->setEnabled( true );
3340     }
3341   }
3342   else {
3343     myMainLayout->setRowStretch(11,0);
3344     for( int i=15; i<=24; i++)
3345       myMainLayout->itemAt(i)->widget()->setVisible( false );
3346   }
3347
3348   // volumes info
3349   if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3350     if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3351       // double volumes
3352       computeDoubleVolumesInfo();
3353       // over constrained volumes
3354       computeOverConstrainedVolumesInfo();
3355       // aspect Ratio 3D histogram
3356       computeAspectRatio3D();
3357      }
3358      else {
3359        myButtons[6]->setEnabled( true );
3360        myButtons[7]->setEnabled( true );
3361        myButtons[8]->setEnabled( true );
3362      }
3363   }
3364   else {
3365     myMainLayout->setRowStretch(16,0);
3366     for( int i=25; i<=34; i++)
3367       myMainLayout->itemAt(i)->widget()->setVisible( false );
3368   }
3369 }
3370
3371 //================================================================================
3372 /*!
3373  * \brief Computes and shows nb of elements satisfying a given predicate
3374  *  \param [in] ft - a predicate type (SMESH::FunctorType)
3375  *  \param [in] iBut - index of one of myButtons to disable
3376  *  \param [in] iWdg - index of one of myWidgets to show the computed number
3377  */
3378 //================================================================================
3379
3380 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3381 {
3382   myButtons[ iBut ]->setEnabled( false );
3383   myWidgets[ iWdg ]->setText( "" );
3384   if ( myObject->_is_nil() ) return;
3385
3386   SUIT_OverrideCursor wc;
3387
3388   SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
3389   if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3390   {
3391     mesh->Load();
3392     this->showInfo( myObject ); // try to show all values
3393     if ( !myWidgets[ iWdg ]->text().isEmpty() )
3394       return; // <ft> predicate already computed
3395   }
3396   // look for a predicate of type <ft>
3397   for ( int i = 0; i < myPredicates.count(); ++i )
3398     if ( myPredicates[i]->GetFunctorType() == ft )
3399     {
3400       CORBA::Long nb = myPredicates[i]->NbSatisfying( myObject );
3401       myWidgets[ iWdg ]->setText( QString::number( nb ));
3402     }
3403 }
3404
3405 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3406 {
3407   computeNb( SMESH::FT_FreeNodes, 0, 1 );
3408 }
3409
3410 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3411 {
3412   computeNb( SMESH::FT_EqualNodes, 1, 2 );
3413 }
3414
3415 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3416 {
3417   computeNb( SMESH::FT_EqualEdges, 2, 3 );
3418 }
3419
3420 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3421 {
3422   computeNb( SMESH::FT_EqualFaces, 3, 4 );
3423 }
3424
3425 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3426 {
3427   computeNb( SMESH::FT_OverConstrainedFace, 4, 5 );
3428 }
3429
3430 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3431 {
3432   computeNb( SMESH::FT_EqualVolumes, 6, 6 );
3433 }
3434
3435 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3436 {
3437   computeNb( SMESH::FT_OverConstrainedVolume, 7, 7 );
3438 }
3439
3440 void SMESHGUI_CtrlInfo::computeAspectRatio()
3441 {
3442   myButtons[5]->setEnabled( false );
3443
3444   if ( myObject->_is_nil() ) return;
3445
3446   SUIT_OverrideCursor wc;
3447
3448   Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3449   if ( aHistogram && !aHistogram->isEmpty() ) {
3450     QwtPlotItem* anItem = aHistogram->createPlotItem();
3451     anItem->attach( myPlot );
3452     myPlot->replot();
3453   }
3454   delete aHistogram;
3455 }
3456
3457 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3458 {
3459   myButtons[8]->setEnabled( false );
3460
3461   if ( myObject->_is_nil() ) return;
3462
3463   SUIT_OverrideCursor wc;
3464
3465   Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3466   if ( aHistogram && !aHistogram->isEmpty() ) {
3467     QwtPlotItem* anItem = aHistogram->createPlotItem();
3468     anItem->attach( myPlot3D );
3469     myPlot3D->replot();
3470   }
3471   delete aHistogram;
3472 }
3473
3474 /*!
3475   \brief Internal clean-up (reset widget)
3476 */
3477 void SMESHGUI_CtrlInfo::clearInternal()
3478 {
3479   for( int i=0; i<=34; i++)
3480     myMainLayout->itemAt(i)->widget()->setVisible( true );
3481   for( int i=0; i<=8; i++)
3482     myButtons[i]->setEnabled( false );
3483   myPlot->detachItems();
3484   myPlot3D->detachItems();
3485   myPlot->replot();
3486   myPlot3D->replot();
3487   myWidgets[0]->setText( QString() );
3488   for ( int i = 1; i < myWidgets.count(); i++ )
3489     myWidgets[i]->setText( "" );
3490   myMainLayout->setRowStretch(11,5);
3491   myMainLayout->setRowStretch(16,5);
3492 }
3493
3494 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3495 {
3496   //SMESH::long_array_var anElems = getElementsByType( SMESH::NODE );
3497   myButtons[1]->setEnabled( true );
3498   myWidgets[2]->setText("");
3499 }
3500
3501 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3502 {
3503   SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
3504   if ( mesh->_is_nil() ) return 0;
3505   if ( !mesh->IsLoaded() )
3506     mesh->Load();
3507   aNumFun->SetMesh( mesh );
3508
3509   CORBA::Long cprecision = 6;
3510   if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ) 
3511     cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3512   aNumFun->SetPrecision( cprecision );
3513
3514   int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3515
3516   SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3517                                                                   /*isLogarithmic=*/false,
3518                                                                   myObject );
3519   Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3520   aHistogram->setColor( palette().color( QPalette::Highlight ) );
3521   if ( &histogramVar.in() )
3522   {
3523     for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3524       aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3525     if ( histogramVar->length() >= 2 )
3526       aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3527   }
3528   return aHistogram;
3529 }
3530
3531 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out ) {
3532   out << QString( 20, '-' ) << "\n";
3533   out << tr( "CTRL_INFO"  ) << "\n";
3534   out << QString( 20, '-' ) << "\n";
3535   out <<                                 tr( "NAME_LAB" )                       << "  " << myWidgets[0]->text() << "\n";
3536   out <<                                 tr( "NODES_INFO" )                     << "\n";
3537   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_FREE_NODES" )       << ": " << myWidgets[1]->text() << "\n";
3538   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_DOUBLE_NODES" )     << ": " << myWidgets[2]->text() << "\n";
3539   out <<                                 tr( "EDGES_INFO" )                     << "\n";
3540   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_DOUBLE_EDGES" )     << ": " << myWidgets[3]->text() << "\n";
3541   out <<                                 tr( "FACES_INFO" )                     << "\n";
3542   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_DOUBLE_FACES" )     << ": " << myWidgets[4]->text() << "\n";
3543   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[5]->text() << "\n";
3544   out <<                                 tr( "VOLUMES_INFO" )                   << "\n";
3545   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" )   << ": " << myWidgets[6]->text() << "\n";
3546   out << QString( SPACING_INFO, ' ' ) << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[7]->text() << "\n";
3547 }
3548
3549 /*!
3550   \class SMESHGUI_CtrlInfoDlg
3551   \brief Controls information dialog box
3552 */
3553
3554 /*!
3555   \brief Constructor
3556   \param parent parent widget
3557   \param page specifies the dialog page to be shown at the start-up
3558 */
3559 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
3560 : QDialog( parent )
3561 {
3562   setAttribute( Qt::WA_DeleteOnClose, true );
3563   setWindowTitle( tr( "CTRL_INFO" ) );
3564   setMinimumSize( 400, 600 );
3565
3566   myCtrlInfo = new SMESHGUI_CtrlInfo( this );
3567   
3568   // buttons
3569   QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3570   okBtn->setAutoDefault( true );
3571   okBtn->setDefault( true );
3572   okBtn->setFocus();
3573   QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3574   dumpBtn->setAutoDefault( true );
3575   QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3576   helpBtn->setAutoDefault( true );
3577
3578   QHBoxLayout* btnLayout = new QHBoxLayout;
3579   btnLayout->setSpacing( SPACING );
3580   btnLayout->setMargin( 0 );
3581
3582   btnLayout->addWidget( okBtn );
3583   btnLayout->addWidget( dumpBtn );
3584   btnLayout->addStretch( 10 );
3585   btnLayout->addWidget( helpBtn );
3586
3587   QVBoxLayout* l = new QVBoxLayout ( this );
3588   l->setMargin( MARGIN );
3589   l->setSpacing( SPACING );
3590   l->addWidget( myCtrlInfo );
3591   l->addLayout( btnLayout );
3592
3593   connect( okBtn,   SIGNAL( clicked() ), this, SLOT( reject() ) );
3594   connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3595   connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3596   connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3597   connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ),        this, SLOT( reject() ) );
3598
3599   updateSelection();
3600 }
3601
3602 /*!
3603   \brief Destructor
3604 */
3605 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
3606 {
3607 }
3608
3609 /*!
3610   \brief Show controls information
3611   \param IO interactive object
3612 */
3613 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO )
3614 {  
3615   if ( SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO ) )
3616     myCtrlInfo->showInfo( obj );
3617 }
3618
3619 /*!
3620   \brief Perform clean-up actions on the dialog box closing.
3621 */
3622 void SMESHGUI_CtrlInfoDlg::reject()
3623 {
3624   SMESH::SetPointRepresentation( false );
3625   QDialog::reject();
3626 }
3627
3628 /*!
3629   \brief Setup selection mode depending on the current dialog box state.
3630 */
3631 void SMESHGUI_CtrlInfoDlg::updateSelection()
3632 {
3633   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3634   disconnect( selMgr, 0, this, 0 );
3635   SMESH::SetPointRepresentation( false );  
3636   connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3637   updateInfo();  
3638 }
3639
3640 /*!
3641   \brief Show mesh information
3642 */
3643 void SMESHGUI_CtrlInfoDlg::updateInfo()
3644 {
3645   SUIT_OverrideCursor wc;
3646
3647   SALOME_ListIO selected;
3648   SMESHGUI::selectionMgr()->selectedObjects( selected );
3649
3650   if ( selected.Extent() == 1 ) {
3651     Handle(SALOME_InteractiveObject) IO = selected.First();
3652     showInfo( IO );
3653   }
3654 }
3655
3656 /*!
3657   \brief Activate dialog box
3658 */
3659 void SMESHGUI_CtrlInfoDlg::activate()
3660 {
3661   SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
3662   SMESHGUI::GetSMESHGUI()->SetActiveDialogBox( this );
3663   updateSelection();
3664 }
3665
3666 /*!
3667   \brief Deactivate dialog box
3668 */
3669 void SMESHGUI_CtrlInfoDlg::deactivate()
3670 {
3671   disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3672 }
3673
3674 /*!
3675  * \brief Dump contents into a file
3676  */
3677 void SMESHGUI_CtrlInfoDlg::dump()
3678 {
3679   SUIT_Application* app = SUIT_Session::session()->activeApplication();
3680   if ( !app ) return;
3681   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study *>( app->activeStudy() );
3682   if ( !appStudy ) return;
3683   _PTR( Study ) aStudy = appStudy->studyDS();
3684
3685   QStringList aFilters;
3686   aFilters.append( tr( "TEXT_FILES" ) );
3687
3688   DumpFileDlg fd( this );
3689   fd.setWindowTitle( tr( "SAVE_INFO" ) );
3690   fd.setFilters( aFilters );
3691   fd.myBaseChk->hide();
3692   fd.myElemChk->hide();
3693   fd.myAddChk ->hide();
3694   fd.myCtrlChk->hide();
3695   if ( fd.exec() == QDialog::Accepted )
3696   {
3697     QString aFileName = fd.selectedFile();
3698     if ( !aFileName.isEmpty() ) {
3699       QFileInfo aFileInfo( aFileName );
3700       if ( aFileInfo.isDir() )
3701         return;
3702  
3703       QFile aFile( aFileName );
3704       if ( !aFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
3705         return;
3706       
3707       QTextStream out( &aFile );
3708       myCtrlInfo->saveInfo( out );
3709     }
3710   }
3711 }
3712
3713 /*!
3714  * \brief Show help
3715  */
3716 void SMESHGUI_CtrlInfoDlg::help()
3717 {
3718   SMESH::ShowHelpFile("mesh_infos_page.html#mesh_quality_info_anchor");
3719 }