Salome HOME
0021669: EDF 2262 SMESH: "Mesh information" takes a long time on small mesh with...
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshInfo.cxx
1 // Copyright (C) 2007-2012  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.
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 "SMESH_Actor.h"
28 #include "SMESHGUI.h"
29 #include "SMESHGUI_IdValidator.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMDSAbs_ElementType.hxx"
33 #include "SMDS_Mesh.hxx"
34
35 #include <LightApp_SelectionMgr.h>
36 #include <SUIT_OverrideCursor.h>
37 #include <SUIT_ResourceMgr.h>
38 #include <SVTK_ViewWindow.h>
39
40 #include <SALOMEDSClient_Study.hxx>
41
42 #include <QApplication>
43 #include <QButtonGroup>
44 #include <QGridLayout>
45 #include <QHBoxLayout>
46 #include <QHeaderView>
47 #include <QItemDelegate>
48 #include <QKeyEvent>
49 #include <QLabel>
50 #include <QLineEdit>
51 #include <QPushButton>
52 #include <QRadioButton>
53 #include <QTabWidget>
54 #include <QTextBrowser>
55 #include <QVBoxLayout>
56
57 #include "utilities.h"
58
59 #include <SALOMEconfig.h>
60 #include CORBA_SERVER_HEADER(GEOM_Gen)
61
62 const int SPACING      = 6;
63 const int MARGIN       = 9;
64 const int MAXITEMS     = 10;
65 const int GROUPS_ID    = 100;
66 const int SUBMESHES_ID = 200;
67
68 /*!
69   \class ExtraWidget
70   \internal
71 */
72
73 class ExtraWidget : public QWidget
74 {
75 public:
76   ExtraWidget( QWidget*, bool = false );
77   ~ExtraWidget();
78
79   void updateControls( int, int, int = MAXITEMS );
80
81 public:
82   QLabel*      current;
83   QPushButton* prev;
84   QPushButton* next;
85   bool         brief;
86 };
87
88 ExtraWidget::ExtraWidget( QWidget* parent, bool b ) : QWidget( parent ), brief( b )
89 {
90   current = new QLabel( this );
91   current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
92   prev = new QPushButton( tr( "<<" ), this );
93   next = new QPushButton( tr( ">>" ), this );
94   QHBoxLayout* hbl = new QHBoxLayout( this );
95   hbl->setContentsMargins( 0, SPACING, 0, 0 );
96   hbl->setSpacing( SPACING );
97   hbl->addStretch();
98   hbl->addWidget( current );
99   hbl->addWidget( prev );
100   hbl->addWidget( next );
101 }
102
103 ExtraWidget::~ExtraWidget()
104 {
105 }
106
107 void ExtraWidget::updateControls( int total, int index, int blockSize )
108 {
109   setVisible( total > blockSize );
110   QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
111   current->setText( format.arg( index*blockSize+1 ).arg( qMin( index*blockSize+blockSize, total ) ).arg( total ) );
112   prev->setEnabled( index > 0 );
113   next->setEnabled( (index+1)*blockSize < total );
114 }
115
116 /*!
117   \class SMESHGUI_MeshInfo
118   \brief Base mesh information widget
119   
120   Displays the base information about mesh object: mesh, sub-mesh, group or arbitrary ID source.
121 */
122
123 /*!
124   \brief Constructor.
125   \param parent parent widget
126 */
127 SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
128   : QFrame( parent ), myWidgets( iElementsEnd )
129 {
130   setFrameStyle( StyledPanel | Sunken );
131
132   QGridLayout* l = new QGridLayout( this );
133   l->setMargin( MARGIN );
134   l->setSpacing( SPACING );
135
136   // object
137   QLabel* aNameLab     = new QLabel( tr( "NAME_LAB" ), this );
138   QLabel* aName        = createField();
139   aName->setMinimumWidth( 150 );
140   QLabel* aObjLab      = new QLabel( tr( "OBJECT_LAB" ), this );
141   QLabel* aObj         = createField();
142   aObj->setMinimumWidth( 150 );
143   myWidgets[0] << aNameLab << aName;
144   myWidgets[1] << aObjLab  << aObj;
145
146   // nodes
147   QWidget* aNodesLine  = createLine();
148   QLabel*  aNodesLab   = new QLabel( tr( "NODES_LAB" ), this );
149   QLabel*  aNodes      = createField();
150   myWidgets[2] << aNodesLine;
151   myWidgets[3] << aNodesLab << aNodes;
152
153   // elements
154   QWidget* aElemLine   = createLine();
155   QLabel*  aElemLab    = new QLabel( tr( "ELEMENTS_LAB" ),  this );
156   QLabel*  aElemTotal  = new QLabel( tr( "TOTAL_LAB" ),     this );
157   QLabel*  aElemLin    = new QLabel( tr( "LINEAR_LAB" ),    this );
158   QLabel*  aElemQuad   = new QLabel( tr( "QUADRATIC_LAB" ), this );
159   myWidgets[4] << aElemLine;
160   myWidgets[5] << aElemLab << aElemTotal << aElemLin << aElemQuad;
161
162   // ... 0D elements
163   QWidget* a0DLine     = createLine();
164   QLabel*  a0DLab      = new QLabel( tr( "0D_LAB" ), this );
165   QLabel*  a0DTotal    = createField();
166   myWidgets[6] << a0DLine;
167   myWidgets[7] << a0DLab << a0DTotal;
168
169   // ... 1D elements
170   QWidget* a1DLine     = createLine();
171   QLabel*  a1DLab      = new QLabel( tr( "1D_LAB" ), this );
172   QLabel*  a1DTotal    = createField();
173   QLabel*  a1DLin      = createField();
174   QLabel*  a1DQuad     = createField();
175   myWidgets[8] << a1DLine;
176   myWidgets[9] << a1DLab << a1DTotal << a1DLin << a1DQuad;
177
178   // ... 2D elements
179   QWidget* a2DLine     = createLine();
180   QLabel*  a2DLab      = new QLabel( tr( "2D_LAB" ), this );
181   QLabel*  a2DTotal    = createField();
182   QLabel*  a2DLin      = createField();
183   QLabel*  a2DQuad     = createField();
184   QLabel*  a2DTriLab   = new QLabel( tr( "TRIANGLES_LAB" ), this );
185   QLabel*  a2DTriTotal = createField();
186   QLabel*  a2DTriLin   = createField();
187   QLabel*  a2DTriQuad  = createField();
188   QLabel*  a2DQuaLab   = new QLabel( tr( "QUADRANGLES_LAB" ), this );
189   QLabel*  a2DQuaTotal = createField();
190   QLabel*  a2DQuaLin   = createField();
191   QLabel*  a2DQuaQuad  = createField();
192   QLabel*  a2DPolLab   = new QLabel( tr( "POLYGONS_LAB" ), this );
193   QLabel*  a2DPolTotal = createField();
194   myWidgets[10] << a2DLine;
195   myWidgets[11] << a2DLab    << a2DTotal    << a2DLin    << a2DQuad;
196   myWidgets[12] << a2DTriLab << a2DTriTotal << a2DTriLin << a2DTriQuad;
197   myWidgets[13] << a2DQuaLab << a2DQuaTotal << a2DQuaLin << a2DQuaQuad;
198   myWidgets[14] << a2DPolLab << a2DPolTotal;
199
200   // ... 3D elements
201   QWidget* a3DLine     = createLine();
202   QLabel*  a3DLab      = new QLabel( tr( "3D_LAB" ), this );
203   QLabel*  a3DTotal    = createField();
204   QLabel*  a3DLin      = createField();
205   QLabel*  a3DQuad     = createField();
206   QLabel*  a3DTetLab   = new QLabel( tr( "TETRAHEDRONS_LAB" ), this );
207   QLabel*  a3DTetTotal = createField();
208   QLabel*  a3DTetLin   = createField();
209   QLabel*  a3DTetQuad  = createField();
210   QLabel*  a3DHexLab   = new QLabel( tr( "HEXAHEDONRS_LAB" ), this );
211   QLabel*  a3DHexTotal = createField();
212   QLabel*  a3DHexLin   = createField();
213   QLabel*  a3DHexQuad  = createField();
214   QLabel*  a3DPyrLab   = new QLabel( tr( "PYRAMIDS_LAB" ), this );
215   QLabel*  a3DPyrTotal = createField();
216   QLabel*  a3DPyrLin   = createField();
217   QLabel*  a3DPyrQuad  = createField();
218   QLabel*  a3DPriLab   = new QLabel( tr( "PRISMS_LAB" ), this );
219   QLabel*  a3DPriTotal = createField();
220   QLabel*  a3DPriLin   = createField();
221   QLabel*  a3DPriQuad  = createField();
222   QLabel*  a3DHexPriLab   = new QLabel( tr( "HEX_PRISMS_LAB" ), this );
223   QLabel*  a3DHexPriTotal = createField();
224   QLabel*  a3DPolLab   = new QLabel( tr( "POLYHEDRONS_LAB" ), this );
225   QLabel*  a3DPolTotal = createField();
226   myWidgets[15] << a3DLine;
227   myWidgets[16] << a3DLab    << a3DTotal    << a3DLin    << a3DQuad;
228   myWidgets[17] << a3DTetLab << a3DTetTotal << a3DTetLin << a3DTetQuad;
229   myWidgets[18] << a3DHexLab << a3DHexTotal << a3DHexLin << a3DHexQuad;
230   myWidgets[19] << a3DPyrLab << a3DPyrTotal << a3DPyrLin << a3DPyrQuad;
231   myWidgets[20] << a3DPriLab << a3DPriTotal << a3DPriLin << a3DPriQuad;
232   myWidgets[21] << a3DHexPriLab << a3DHexPriTotal;
233   myWidgets[22] << a3DPolLab << a3DPolTotal;
234
235   myLoadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
236   myLoadBtn->setAutoDefault( true );
237   connect( myLoadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
238   
239   setFontAttributes( aNameLab,   Bold );
240   setFontAttributes( aObjLab,    Bold );
241   setFontAttributes( aNodesLab,  Bold );
242   setFontAttributes( aElemLab,   Bold );
243   setFontAttributes( aElemTotal, Italic );
244   setFontAttributes( aElemLin,   Italic );
245   setFontAttributes( aElemQuad,  Italic );
246   setFontAttributes( a0DLab,     Bold );
247   setFontAttributes( a1DLab,     Bold );
248   setFontAttributes( a2DLab,     Bold );
249   setFontAttributes( a3DLab,     Bold );
250
251   l->addWidget( aNameLab,     0, 0 );
252   l->addWidget( aName,        0, 1, 1, 3 );
253   l->addWidget( aObjLab,      1, 0 );
254   l->addWidget( aObj,         1, 1, 1, 3 );
255   l->addWidget( aNodesLine,   2, 0, 1, 4 );
256   l->addWidget( aNodesLab,    3, 0 );
257   l->addWidget( aNodes,       3, 1 );
258   l->addWidget( aElemLine,    4, 0, 1, 4 );
259   l->addWidget( aElemLab,     5, 0 );
260   l->addWidget( aElemTotal,   5, 1 );
261   l->addWidget( aElemLin,     5, 2 );
262   l->addWidget( aElemQuad,    5, 3 );
263   l->addWidget( a0DLine,      6, 1, 1, 3 );
264   l->addWidget( a0DLab,       7, 0 );
265   l->addWidget( a0DTotal,     7, 1 );
266   l->addWidget( a1DLine,      8, 1, 1, 3 );
267   l->addWidget( a1DLab,       9, 0 );
268   l->addWidget( a1DTotal,     9, 1 );
269   l->addWidget( a1DLin,       9, 2 );
270   l->addWidget( a1DQuad,      9, 3 );
271   l->addWidget( a2DLine,     10, 1, 1, 3 );
272   l->addWidget( a2DLab,      11, 0 );
273   l->addWidget( a2DTotal,    11, 1 );
274   l->addWidget( a2DLin,      11, 2 );
275   l->addWidget( a2DQuad,     11, 3 );
276   l->addWidget( a2DTriLab,   12, 0 );
277   l->addWidget( a2DTriTotal, 12, 1 );
278   l->addWidget( a2DTriLin,   12, 2 );
279   l->addWidget( a2DTriQuad,  12, 3 );
280   l->addWidget( a2DQuaLab,   13, 0 );
281   l->addWidget( a2DQuaTotal, 13, 1 );
282   l->addWidget( a2DQuaLin,   13, 2 );
283   l->addWidget( a2DQuaQuad,  13, 3 );
284   l->addWidget( a2DPolLab,   14, 0 );
285   l->addWidget( a2DPolTotal, 14, 1 );
286   l->addWidget( a3DLine,     15, 1, 1, 3 );
287   l->addWidget( a3DLab,      16, 0 );
288   l->addWidget( a3DTotal,    16, 1 );
289   l->addWidget( a3DLin,      16, 2 );
290   l->addWidget( a3DQuad,     16, 3 );
291   l->addWidget( a3DTetLab,   17, 0 );
292   l->addWidget( a3DTetTotal, 17, 1 );
293   l->addWidget( a3DTetLin,   17, 2 );
294   l->addWidget( a3DTetQuad,  17, 3 );
295   l->addWidget( a3DHexLab,   18, 0 );
296   l->addWidget( a3DHexTotal, 18, 1 );
297   l->addWidget( a3DHexLin,   18, 2 );
298   l->addWidget( a3DHexQuad,  18, 3 );
299   l->addWidget( a3DPyrLab,   19, 0 );
300   l->addWidget( a3DPyrTotal, 19, 1 );
301   l->addWidget( a3DPyrLin,   19, 2 );
302   l->addWidget( a3DPyrQuad,  19, 3 );
303   l->addWidget( a3DPriLab,   20, 0 );
304   l->addWidget( a3DPriTotal, 20, 1 );
305   l->addWidget( a3DPriLin,   20, 2 );
306   l->addWidget( a3DPriQuad,  20, 3 );
307   l->addWidget( a3DHexPriLab,   21, 0 );
308   l->addWidget( a3DHexPriTotal, 21, 1 );
309   l->addWidget( a3DPolLab,   22, 0 );
310   l->addWidget( a3DPolTotal, 22, 1 );
311   l->addWidget( myLoadBtn,   23, 1, 1, 3 );
312   l->setColumnStretch( 0, 0 );
313   l->setColumnStretch( 1, 5 );
314   l->setColumnStretch( 2, 5 );
315   l->setColumnStretch( 3, 5 );
316   l->setRowStretch( 23, 5 );
317
318   clear();
319 }
320
321 /*!
322   \brief Destructor
323 */
324 SMESHGUI_MeshInfo::~SMESHGUI_MeshInfo()
325 {
326 }
327
328 /*!
329   \brief Show information on the mesh object.
330   \param obj object being processed (mesh, sub-mesh, group, ID source)
331 */
332 void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
333 {
334   clear();
335   if ( !CORBA::is_nil( obj ) ) {
336     _PTR(SObject) sobj = SMESH::ObjectToSObject( obj );
337     if ( sobj ) 
338       myWidgets[iName][iSingle]->setProperty( "text", sobj->GetName().c_str() );
339     SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
340     SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
341     SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
342     if ( !aMesh->_is_nil() ) {
343       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_MESH" ) );
344     }
345     else if ( !aSubMesh->_is_nil() ) {
346       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_SUBMESH" ) );
347     }
348     else if ( !aGroup->_is_nil() ) {
349       QString objType;
350       switch( aGroup->GetType() ) {
351       case SMESH::NODE:
352         objType = tr( "OBJECT_GROUP_NODES" );
353         break;
354       case SMESH::EDGE:
355         objType = tr( "OBJECT_GROUP_EDGES" );
356         break;
357       case SMESH::FACE:
358         objType = tr( "OBJECT_GROUP_FACES" );
359         break;
360       case SMESH::VOLUME:
361         objType = tr( "OBJECT_GROUP_VOLUMES" );
362         break;
363       case SMESH::ELEM0D:
364         objType = tr( "OBJECT_GROUP_0DELEMS" );
365         break;
366       default:
367         objType = tr( "OBJECT_GROUP" );
368         break;
369       }
370       myWidgets[iObject][iSingle]->setProperty( "text", objType );
371     }
372     SMESH::long_array_var info = obj->GetMeshInfo();
373     myWidgets[iNodes][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Node] ) );
374     myWidgets[i0D][iTotal]    ->setProperty( "text", QString::number( info[SMDSEntity_0D] ) );
375     long nbEdges = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
376     myWidgets[i1D][iTotal]    ->setProperty( "text", QString::number( nbEdges ) );
377     myWidgets[i1D][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Edge] ) );
378     myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Edge] ) );
379     long nbTriangles   = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle];
380     long nbQuadrangles = info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
381     long nb2DLinear    = info[SMDSEntity_Triangle] + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
382     long nb2DQuadratic = info[SMDSEntity_Quad_Triangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
383     myWidgets[i2D][iTotal]               ->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ) );
384     myWidgets[i2D][iLinear]              ->setProperty( "text", QString::number( nb2DLinear ) );
385     myWidgets[i2D][iQuadratic]           ->setProperty( "text", QString::number( nb2DQuadratic ) );
386     myWidgets[i2DTriangles][iTotal]      ->setProperty( "text", QString::number( nbTriangles ) );
387     myWidgets[i2DTriangles][iLinear]     ->setProperty( "text", QString::number( info[SMDSEntity_Triangle] ) );
388     myWidgets[i2DTriangles][iQuadratic]  ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Triangle] ) );
389     myWidgets[i2DQuadrangles][iTotal]    ->setProperty( "text", QString::number( nbQuadrangles ) );
390     myWidgets[i2DQuadrangles][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
391     myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle] ));
392     myWidgets[i2DPolygons][iTotal]       ->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
393     long nbTetrahedrons = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra];
394     long nbHexahedrons  = info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa];
395     long nbPyramids     = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
396     long nbPrisms       = info[SMDSEntity_Penta]   + info[SMDSEntity_Quad_Penta];
397     long nb3DLinear     = info[SMDSEntity_Tetra] + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra] + info[SMDSEntity_Hexagonal_Prism];
398     long nb3DQuadratic  = info[SMDSEntity_Quad_Tetra] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] + info[SMDSEntity_Quad_Pyramid] + info[SMDSEntity_Quad_Penta];
399     myWidgets[i3D][iTotal]                ->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
400     myWidgets[i3D][iLinear]               ->setProperty( "text", QString::number( nb3DLinear ) );
401     myWidgets[i3D][iQuadratic]            ->setProperty( "text", QString::number( nb3DQuadratic ) );
402     myWidgets[i3DTetrahedrons][iTotal]    ->setProperty( "text", QString::number( nbTetrahedrons ) );
403     myWidgets[i3DTetrahedrons][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Tetra] ) );
404     myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Tetra] ) );
405     myWidgets[i3DHexahedrons][iTotal]     ->setProperty( "text", QString::number( nbHexahedrons ) );
406     myWidgets[i3DHexahedrons][iLinear]    ->setProperty( "text", QString::number( info[SMDSEntity_Hexa] ) );
407     myWidgets[i3DHexahedrons][iQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] ) );
408     myWidgets[i3DPyramids][iTotal]        ->setProperty( "text", QString::number( nbPyramids ) );
409     myWidgets[i3DPyramids][iLinear]       ->setProperty( "text", QString::number( info[SMDSEntity_Pyramid] ) );
410     myWidgets[i3DPyramids][iQuadratic]    ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Pyramid] ) );
411     myWidgets[i3DPrisms][iTotal]          ->setProperty( "text", QString::number( nbPrisms ) );
412     myWidgets[i3DPrisms][iLinear]         ->setProperty( "text", QString::number( info[SMDSEntity_Penta] ) );
413     myWidgets[i3DPrisms][iQuadratic]      ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
414     myWidgets[i3DHexaPrisms][iTotal]      ->setProperty( "text", QString::number( info[SMDSEntity_Hexagonal_Prism] ) );
415     myWidgets[i3DPolyhedrons][iTotal]     ->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
416
417     // before full loading from study file, type of elements in a sub-mesh can't be defined
418     // in some cases
419     bool infoOK = obj->IsMeshInfoCorrect();
420     myLoadBtn->setVisible( !infoOK );
421     if ( !infoOK )
422     {
423       // two options:
424       // 1. Type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
425       // 2. No info at all (for a group on geom or filter)
426       bool hasAnyInfo = false;
427       for ( size_t i = 0; i < info->length() && !hasAnyInfo; ++i )
428         hasAnyInfo = info[i];
429       if ( hasAnyInfo ) // believe it is a sub-mesh
430       {
431         if ( nb2DLinear + nb2DQuadratic > 0 )
432         {
433           myWidgets[i2D][iLinear]              ->setProperty( "text", "?" );
434           myWidgets[i2D][iQuadratic]           ->setProperty( "text", "?" );
435           myWidgets[i2DTriangles][iTotal]      ->setProperty( "text", "?" );
436           myWidgets[i2DTriangles][iLinear]     ->setProperty( "text", "?" );
437           myWidgets[i2DTriangles][iQuadratic]  ->setProperty( "text", "?" );
438           myWidgets[i2DQuadrangles][iTotal]    ->setProperty( "text", "?" );
439           myWidgets[i2DQuadrangles][iLinear]   ->setProperty( "text", "?" );
440           myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", "?" );
441           myWidgets[i2DPolygons][iTotal]       ->setProperty( "text", "?" );
442         }
443         else if ( nb3DLinear + nb3DQuadratic > 0 )
444         {
445           myWidgets[i3D][iLinear]               ->setProperty( "text", "?" );
446           myWidgets[i3D][iQuadratic]            ->setProperty( "text", "?" );
447           myWidgets[i3DTetrahedrons][iTotal]    ->setProperty( "text", "?" );
448           myWidgets[i3DTetrahedrons][iLinear]   ->setProperty( "text", "?" );
449           myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", "?" );
450           myWidgets[i3DHexahedrons][iTotal]     ->setProperty( "text", "?" );
451           myWidgets[i3DHexahedrons][iLinear]    ->setProperty( "text", "?" );
452           myWidgets[i3DHexahedrons][iQuadratic] ->setProperty( "text", "?" );
453           myWidgets[i3DPyramids][iTotal]        ->setProperty( "text", "?" );
454           myWidgets[i3DPyramids][iLinear]       ->setProperty( "text", "?" );
455           myWidgets[i3DPyramids][iQuadratic]    ->setProperty( "text", "?" );
456           myWidgets[i3DPrisms][iTotal]          ->setProperty( "text", "?" );
457           myWidgets[i3DPrisms][iLinear]         ->setProperty( "text", "?" );
458           myWidgets[i3DPrisms][iQuadratic]      ->setProperty( "text", "?" );
459           myWidgets[i3DHexaPrisms][iTotal]      ->setProperty( "text", "?" );
460           myWidgets[i3DPolyhedrons][iTotal]     ->setProperty( "text", "?" );
461         }
462       }
463       else
464       {
465         myWidgets[iNodes][iTotal]             ->setProperty( "text", "?" );
466         myWidgets[i0D][iTotal]                ->setProperty( "text", "?" );
467         myWidgets[i1D][iTotal]                ->setProperty( "text", "?" );
468         myWidgets[i1D][iLinear]               ->setProperty( "text", "?" );
469         myWidgets[i1D][iQuadratic]            ->setProperty( "text", "?" );
470         myWidgets[i2D][iTotal]                ->setProperty( "text", "?" );
471         myWidgets[i2D][iLinear]               ->setProperty( "text", "?" );
472         myWidgets[i2D][iQuadratic]            ->setProperty( "text", "?" );
473         myWidgets[i2DTriangles][iTotal]       ->setProperty( "text", "?" );
474         myWidgets[i2DTriangles][iLinear]      ->setProperty( "text", "?" );
475         myWidgets[i2DTriangles][iQuadratic]   ->setProperty( "text", "?" );
476         myWidgets[i2DQuadrangles][iTotal]     ->setProperty( "text", "?" );
477         myWidgets[i2DQuadrangles][iLinear]    ->setProperty( "text", "?" );
478         myWidgets[i2DQuadrangles][iQuadratic] ->setProperty( "text", "?" );
479         myWidgets[i2DPolygons][iTotal]        ->setProperty( "text", "?" );
480         myWidgets[i3D][iTotal]                ->setProperty( "text", "?" );
481         myWidgets[i3D][iLinear]               ->setProperty( "text", "?" );
482         myWidgets[i3D][iQuadratic]            ->setProperty( "text", "?" );
483         myWidgets[i3DTetrahedrons][iTotal]    ->setProperty( "text", "?" );
484         myWidgets[i3DTetrahedrons][iLinear]   ->setProperty( "text", "?" );
485         myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", "?" );
486         myWidgets[i3DHexahedrons][iTotal]     ->setProperty( "text", "?" );
487         myWidgets[i3DHexahedrons][iLinear]    ->setProperty( "text", "?" );
488         myWidgets[i3DHexahedrons][iQuadratic] ->setProperty( "text", "?" );
489         myWidgets[i3DPyramids][iTotal]        ->setProperty( "text", "?" );
490         myWidgets[i3DPyramids][iLinear]       ->setProperty( "text", "?" );
491         myWidgets[i3DPyramids][iQuadratic]    ->setProperty( "text", "?" );
492         myWidgets[i3DPrisms][iTotal]          ->setProperty( "text", "?" );
493         myWidgets[i3DPrisms][iLinear]         ->setProperty( "text", "?" );
494         myWidgets[i3DPrisms][iQuadratic]      ->setProperty( "text", "?" );
495         myWidgets[i3DHexaPrisms][iTotal]      ->setProperty( "text", "?" );
496         myWidgets[i3DPolyhedrons][iTotal]     ->setProperty( "text", "?" );
497       }
498     }
499   }
500 }
501
502 /*!
503   \brief Load mesh from a study file
504 */
505 void SMESHGUI_MeshInfo::loadMesh()
506 {
507   SUIT_OverrideCursor wc;
508
509   SALOME_ListIO selected;
510   SMESHGUI::selectionMgr()->selectedObjects( selected );
511
512   if ( selected.Extent() == 1 ) {
513     Handle(SALOME_InteractiveObject) IO = selected.First();
514     SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
515     if ( !CORBA::is_nil( obj ) ) {
516       SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
517       if ( !mesh->_is_nil() )
518       {
519         mesh->Load();
520         showInfo( obj );
521       }
522     }
523   }
524 }
525
526 /*!
527   \brief Reset the widget to the initial state (nullify all fields).
528 */
529 void SMESHGUI_MeshInfo::clear()
530 {
531   myWidgets[iName][iSingle]->setProperty( "text", QString() );
532   myWidgets[iObject][iSingle]->setProperty( "text", QString() );
533   myWidgets[iNodes][iTotal]->setProperty( "text", QString::number( 0 ) );
534   myWidgets[i0D][iTotal]->setProperty( "text", QString::number( 0 ) );
535   myWidgets[i1D][iTotal]->setProperty( "text", QString::number( 0 ) );
536   myWidgets[i1D][iLinear]->setProperty( "text", QString::number( 0 ) );
537   myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( 0 ) );
538   myWidgets[i2D][iTotal]->setProperty( "text", QString::number( 0 ) );
539   myWidgets[i2D][iLinear]->setProperty( "text", QString::number( 0 ) );
540   myWidgets[i2D][iQuadratic]->setProperty( "text", QString::number( 0 ) );
541   myWidgets[i2DTriangles][iTotal]->setProperty( "text", QString::number( 0 ) );
542   myWidgets[i2DTriangles][iLinear]->setProperty( "text", QString::number( 0 ) );
543   myWidgets[i2DTriangles][iQuadratic]->setProperty( "text", QString::number( 0 ) );
544   myWidgets[i2DQuadrangles][iTotal]->setProperty( "text", QString::number( 0 ) );
545   myWidgets[i2DQuadrangles][iLinear]->setProperty( "text", QString::number( 0 ) );
546   myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", QString::number( 0 ) );
547   myWidgets[i2DPolygons][iTotal]->setProperty( "text", QString::number( 0 ) );
548   myWidgets[i3D][iTotal]->setProperty( "text", QString::number( 0 ) );
549   myWidgets[i3D][iLinear]->setProperty( "text", QString::number( 0 ) );
550   myWidgets[i3D][iQuadratic]->setProperty( "text", QString::number( 0 ) );
551   myWidgets[i3DTetrahedrons][iTotal]->setProperty( "text", QString::number( 0 ) );
552   myWidgets[i3DTetrahedrons][iLinear]->setProperty( "text", QString::number( 0 ) );
553   myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", QString::number( 0 ) );
554   myWidgets[i3DHexahedrons][iTotal]->setProperty( "text", QString::number( 0 ) );
555   myWidgets[i3DHexahedrons][iLinear]->setProperty( "text", QString::number( 0 ) );
556   myWidgets[i3DHexahedrons][iQuadratic]->setProperty( "text", QString::number( 0 ) );
557   myWidgets[i3DPyramids][iTotal]->setProperty( "text", QString::number( 0 ) );
558   myWidgets[i3DPyramids][iLinear]->setProperty( "text", QString::number( 0 ) );
559   myWidgets[i3DPyramids][iQuadratic]->setProperty( "text", QString::number( 0 ) );
560   myWidgets[i3DPrisms][iTotal]->setProperty( "text", QString::number( 0 ) );
561   myWidgets[i3DPrisms][iLinear]->setProperty( "text", QString::number( 0 ) );
562   myWidgets[i3DPrisms][iQuadratic]->setProperty( "text", QString::number( 0 ) );
563   myWidgets[i3DHexaPrisms][iTotal]->setProperty( "text", QString::number( 0 ) );
564   myWidgets[i3DPolyhedrons][iTotal]->setProperty( "text", QString::number( 0 ) );
565 }
566
567 /*!
568   \brief Create info field
569   \return new info field
570 */
571 QLabel* SMESHGUI_MeshInfo::createField()
572 {
573   QLabel* lab = new QLabel( this );
574   lab->setFrameStyle( StyledPanel | Sunken );
575   lab->setAlignment( Qt::AlignCenter );
576   lab->setAutoFillBackground( true );
577   QPalette pal = lab->palette();
578   pal.setColor( QPalette::Window, QApplication::palette().color( QPalette::Active, QPalette::Base ) );
579   lab->setPalette( pal );
580   lab->setMinimumWidth( 70 );
581   return lab;
582 }
583
584 /*!
585   \brief Create horizontal rule.
586   \return new line object
587 */
588 QWidget* SMESHGUI_MeshInfo::createLine()
589 {
590   QFrame* line = new QFrame( this );
591   line->setFrameStyle( HLine | Sunken );
592   return line;
593 }
594
595 /*!
596   \brief Change widget font attributes (bold, italic, ...).
597   \param w widget
598   \param attr font attributes (XORed flags)
599   \param val value to be set to attributes
600 */
601 void SMESHGUI_MeshInfo::setFontAttributes( QWidget* w, int attr, bool val )
602 {
603   if ( w && attr ) {
604     QFont f = w->font();
605     if ( attr & Bold   ) f.setBold( val );
606     if ( attr & Italic ) f.setItalic( val );
607     w->setFont( f );
608   }
609 }
610
611 /*!
612   \brief Show/hide group(s) of fields.
613   \param start beginning of the block
614   \param end end of the block
615   \param on visibility flag
616 */
617 void SMESHGUI_MeshInfo::setFieldsVisible( int start, int end, bool on )
618 {
619   start = qMax( 0, start );
620   end   = qMin( end, (int)iElementsEnd );
621   for ( int i = start; i < end; i++ ) {
622     wlist wl = myWidgets[i];
623     foreach ( QWidget* w, wl ) w->setVisible( on );
624   }
625 }
626
627 /*!
628   \class SMESHGUI_ElemInfo
629   \brief Base class for the mesh element information widget.
630 */
631
632 /*!
633   \brief Constructor
634   \param parent parent widget
635 */
636 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent )
637 : QWidget( parent ), myActor( 0 ), myIsElement( -1 )
638 {
639   myFrame = new QWidget( this );
640   myExtra = new ExtraWidget( this );
641   QVBoxLayout* vbl = new QVBoxLayout( this );
642   vbl->setMargin( 0 );
643   vbl->setSpacing( 0 );
644   vbl->addWidget( myFrame );
645   vbl->addWidget( myExtra );
646   connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
647   connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
648   clear();
649 }
650
651 /*!
652   \brief Destructor
653 */
654 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
655 {
656 }
657
658 /*!
659   \brief Set mesh data source (actor)
660   \param actor mesh object actor
661 */
662 void SMESHGUI_ElemInfo::setSource( SMESH_Actor* actor )
663 {
664   if ( myActor != actor ) {
665     myActor = actor;
666     myIsElement = -1;
667     clear();
668   }
669 }
670
671 /*!
672   \brief Show mesh element information
673   \param id mesh node / element ID
674   \param isElem show mesh element information if \c true or mesh node information if \c false
675 */
676 void SMESHGUI_ElemInfo::showInfo( long id, bool isElem )
677 {
678   QSet<long> ids;
679   ids << id;
680   showInfo( ids, isElem );
681 }
682
683 /*!
684   \brief Show mesh element information
685   \param ids mesh nodes / elements identifiers
686   \param isElem show mesh element information if \c true or mesh node information if \c false
687 */
688 void SMESHGUI_ElemInfo::showInfo( QSet<long> ids, bool isElem )
689 {
690   QList<long> newIds = ids.toList();
691   qSort( newIds );
692   if ( myIDs == newIds && myIsElement == isElem ) return;
693
694   myIDs = newIds;
695   myIsElement = isElem;
696   myIndex = 0;
697   updateControls();
698   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
699 }
700
701 /*!
702   \brief Clear mesh element information widget
703 */
704 void SMESHGUI_ElemInfo::clear()
705 {
706   myIDs.clear();
707   myIndex = 0;
708   clearInternal();
709   updateControls();
710 }
711
712 /*!
713   \brief Get central area widget
714   \return central widget
715 */
716 QWidget* SMESHGUI_ElemInfo::frame() const
717 {
718   return myFrame;
719 }
720
721 /*!
722   \brief Get actor
723   \return actor being used
724 */
725 SMESH_Actor* SMESHGUI_ElemInfo::actor() const
726 {
727   return myActor;
728 }
729
730 /*!
731   \brief Get current info mode.
732   \return \c true if mesh element information is shown or \c false if node information is shown
733 */
734 bool SMESHGUI_ElemInfo::isElements() const
735 {
736   return myIsElement;
737 }
738
739 /*!
740   \fn void SMESHGUI_ElemInfo::information( const QList<long>& ids )
741   \brief Show information on the specified nodes / elements
742
743   This function is to be redefined in sub-classes.
744
745   \param ids nodes / elements identifiers information is to be shown on
746 */
747
748 /*!
749   \brief Internal clean-up (reset widget)
750 */
751 void SMESHGUI_ElemInfo::clearInternal()
752 {
753 }
754
755 /*!
756   \brief Get node connectivity
757   \param node mesh node
758   \return node connectivity map
759 */
760 SMESHGUI_ElemInfo::Connectivity SMESHGUI_ElemInfo::nodeConnectivity( const SMDS_MeshNode* node )
761 {
762   Connectivity elmap;
763   if ( node ) {
764     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
765     while ( it && it->more() ) {
766       const SMDS_MeshElement* ne = it->next();
767       elmap[ ne->GetType() ] << ne->GetID();
768     }
769   }
770   return elmap;
771 }
772
773 /*!
774   \brief Format connectivity data to string representation
775   \param connectivity connetivity map
776   \param type element type
777   \return string representation of the connectivity
778 */
779 QString SMESHGUI_ElemInfo::formatConnectivity( Connectivity connectivity, int type )
780 {
781   QStringList str;
782   if ( connectivity.contains( type ) ) {
783     QList<int> elements = connectivity[ type ];
784     qSort( elements );
785     foreach( int id, elements )
786       str << QString::number( id );
787   }
788   return str.join( " " );
789 }
790
791 /*!
792   \brief Calculate gravity center of the mesh element
793   \param element mesh element
794 */
795 SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* element )
796 {
797   XYZ xyz;
798   if ( element ) {
799     SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
800     while ( nodeIt->more() ) {
801       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
802       xyz.add( node->X(), node->Y(), node->Z() );
803     }
804     xyz.divide( element->NbNodes() );
805   }
806   return xyz;
807 }
808
809 /*!
810   \brief This slot is called from "Show Previous" button click.
811   Shows information on the previous group of the items.
812 */
813 void SMESHGUI_ElemInfo::showPrevious()
814 {
815   myIndex = qMax( 0, myIndex-1 );
816   updateControls();
817   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
818 }
819
820 /*!
821   \brief This slot is called from "Show Next" button click.
822   Shows information on the next group of the items.
823 */
824 void SMESHGUI_ElemInfo::showNext()
825 {
826   myIndex = qMin( myIndex+1, myIDs.count() / MAXITEMS );
827   updateControls();
828   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
829 }
830
831 /*!
832   \brief Update widgets state
833 */
834 void SMESHGUI_ElemInfo::updateControls()
835 {
836   myExtra->updateControls( myIDs.count(), myIndex );
837 }
838
839 /*!
840   \class SMESHGUI_SimpleElemInfo
841   \brief Represents mesh element information in the simple text area.
842 */
843
844 /*!
845   \brief Constructor
846   \param parent parent widget
847 */
848 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
849 : SMESHGUI_ElemInfo( parent )
850 {
851   myInfo = new QTextBrowser( frame() );
852   QVBoxLayout* l = new QVBoxLayout( frame() );
853   l->setMargin( 0 );
854   l->addWidget( myInfo );
855 }
856
857 /*!
858   \brief Show mesh element information
859   \param ids mesh nodes / elements identifiers
860 */
861 void SMESHGUI_SimpleElemInfo::information( const QList<long>& ids )
862 {
863   clearInternal();
864   
865   if ( actor() ) {
866     int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
867     foreach ( long id, ids ) {
868       if ( !isElements() ) {
869         //
870         // show node info
871         //
872         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindNode( id );
873         if ( !e ) return;
874         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
875         
876         // node ID
877         myInfo->append( QString( "<b>%1 #%2</b>" ).arg( tr( "NODE" ) ).arg( id ) );
878         // separator
879         myInfo->append( "" );
880         // coordinates
881         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ).
882                         arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
883                         arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
884                         arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
885         // separator
886         myInfo->append( "" );
887         // connectivity
888         Connectivity connectivity = nodeConnectivity( node );
889         if ( !connectivity.isEmpty() ) {
890           myInfo->append( QString( "<b>%1:</b>" ).arg( tr( "CONNECTIVITY" ) ) );
891           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
892           if ( !con.isEmpty() )
893             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "0D_ELEMENTS" ) ).arg( con ) );
894           con = formatConnectivity( connectivity, SMDSAbs_Edge );
895           if ( !con.isEmpty() )
896             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "EDGES" ) ).arg( con ) );
897           con = formatConnectivity( connectivity, SMDSAbs_Face );
898           if ( !con.isEmpty() )
899             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "FACES" ) ).arg( con ) );
900           con = formatConnectivity( connectivity, SMDSAbs_Volume );
901           if ( !con.isEmpty() )
902             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUMES" ) ).arg( con ) );
903         }
904         else {
905           myInfo->append( QString( "<b>%1</b>" ).arg( tr( "FREE_NODE" ) ).arg( id ) );
906         }
907       }
908       else {
909         //
910         // show element info
911         // 
912         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id );
913         if ( !e ) return;
914         
915         // element ID && type
916         QString stype;
917         switch( e->GetType() ) {
918         case SMDSAbs_0DElement:
919           stype = tr( "0D ELEMENT" ); break;
920         case SMDSAbs_Edge:
921           stype = tr( "EDGE" ); break;
922         case SMDSAbs_Face:
923           stype = tr( "FACE" ); break;
924         case SMDSAbs_Volume:
925           stype = tr( "VOLUME" ); break;
926         default: 
927           break;
928         }
929         if ( stype.isEmpty() ) return;
930         myInfo->append( QString( "<b>%1 #%2</b>" ).arg( stype ).arg( id ) );
931         // separator
932         myInfo->append( "" );
933         // geometry type
934         QString gtype;
935         switch( e->GetEntityType() ) {
936         case SMDSEntity_Triangle:
937         case SMDSEntity_Quad_Triangle:
938           gtype = tr( "TRIANGLE" ); break;
939         case SMDSEntity_Quadrangle:
940         case SMDSEntity_Quad_Quadrangle:
941         case SMDSEntity_BiQuad_Quadrangle:
942           gtype = tr( "QUADRANGLE" ); break;
943         case SMDSEntity_Polygon:
944         case SMDSEntity_Quad_Polygon:
945           gtype = tr( "POLYGON" ); break;
946         case SMDSEntity_Tetra:
947         case SMDSEntity_Quad_Tetra:
948           gtype = tr( "TETRAHEDRON" ); break;
949         case SMDSEntity_Pyramid:
950         case SMDSEntity_Quad_Pyramid:
951           gtype = tr( "PYRAMID" ); break;
952         case SMDSEntity_Hexa:
953         case SMDSEntity_Quad_Hexa:
954         case SMDSEntity_TriQuad_Hexa:
955           gtype = tr( "HEXAHEDRON" ); break;
956         case SMDSEntity_Penta:
957         case SMDSEntity_Quad_Penta:
958           gtype = tr( "PRISM" ); break;
959         case SMDSEntity_Hexagonal_Prism:
960           gtype = tr( "HEX_PRISM" ); break;
961         case SMDSEntity_Polyhedra:
962         case SMDSEntity_Quad_Polyhedra:
963           gtype = tr( "POLYHEDRON" ); break;
964         default: 
965           break;
966         }
967         if ( !gtype.isEmpty() )
968           myInfo->append( QString( "<b>%1:</b> %2" ).arg( tr( "TYPE" ) ).arg( gtype ) );
969         // quadratic flag and gravity center (any element except 0D)
970         if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) {
971           // quadratic flag
972           myInfo->append( QString( "<b>%1?</b> %2" ).arg( tr( "QUADRATIC" ) ).arg( e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) ) );
973           // separator
974           myInfo->append( "" );
975           // gravity center
976           XYZ gc = gravityCenter( e );
977           myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( tr( "GRAVITY_CENTER" ) ).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ) );
978         }
979         // separator
980         myInfo->append( "" );
981         // connectivity
982         SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
983         for ( int idx = 1; nodeIt->more(); idx++ ) {
984           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
985           // node number and ID
986           myInfo->append( QString( "<b>%1 %2/%3</b> - #%4" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ) );
987           // node coordinates
988           myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ).
989                           arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
990                           arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
991                           arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
992           // node connectivity
993           Connectivity connectivity = nodeConnectivity( node );
994           if ( !connectivity.isEmpty() ) {
995             myInfo->append( QString( "<b>%1:</b>" ).arg( tr( "CONNECTIVITY" ) ) );
996             QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
997             if ( !con.isEmpty() )
998               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "0D_ELEMENTS" ) ).arg( con ) );
999             con = formatConnectivity( connectivity, SMDSAbs_Edge );
1000             if ( !con.isEmpty() )
1001               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "EDGES" ) ).arg( con ) );
1002             con = formatConnectivity( connectivity, SMDSAbs_Face );
1003             if ( !con.isEmpty() )
1004               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "FACES" ) ).arg( con ) );
1005             con = formatConnectivity( connectivity, SMDSAbs_Volume );
1006             if ( !con.isEmpty() )
1007               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUMES" ) ).arg( con ) );
1008           }
1009           else {
1010             myInfo->append( QString( "<b>%1</b>" ).arg( tr( "FREE_NODE" ) ).arg( id ) );
1011           }
1012         }
1013       }
1014       // separator
1015       if ( ids.count() > 1 ) {
1016         myInfo->append( "" );
1017         myInfo->append( "------" );
1018         myInfo->append( "" );
1019       }
1020     }
1021   }
1022 }
1023
1024 /*!
1025   \brief Internal clean-up (reset widget)
1026 */
1027 void SMESHGUI_SimpleElemInfo::clearInternal()
1028 {
1029   myInfo->clear();
1030 }
1031
1032 /*!
1033   \class SMESHGUI_TreeElemInfo::ItemDelegate
1034   \brief Item delegate for tree mesh info widget
1035   \internal
1036 */
1037 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
1038 {
1039 public:
1040   ItemDelegate( QObject* );
1041   QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
1042 };
1043
1044 /*!
1045   \brief Constructor
1046   \internal
1047 */
1048 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ) : QItemDelegate( parent )
1049 {
1050 }
1051
1052 /*!
1053   \brief Create item editor widget
1054   \internal
1055 */
1056 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
1057 {
1058   QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
1059   if ( qobject_cast<QLineEdit*>( w ) ) qobject_cast<QLineEdit*>( w )->setReadOnly(  true );
1060   return w;
1061 }
1062
1063 /*!
1064   \class SMESHGUI_TreeElemInfo
1065   \brief Represents mesh element information in the tree-like form.
1066 */
1067
1068 /*!
1069   \brief Constructor
1070   \param parent parent widget
1071 */
1072 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
1073 : SMESHGUI_ElemInfo( parent )
1074 {
1075   myInfo = new QTreeWidget( frame() );
1076   myInfo->setColumnCount( 2 );
1077   myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
1078   myInfo->header()->setStretchLastSection( true );
1079   myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
1080   myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
1081   QVBoxLayout* l = new QVBoxLayout( frame() );
1082   l->setMargin( 0 );
1083   l->addWidget( myInfo );
1084 }
1085
1086 /*!
1087   \brief Show mesh element information
1088   \param ids mesh nodes / elements identifiers
1089 */
1090 void SMESHGUI_TreeElemInfo::information( const QList<long>& ids )
1091 {
1092   clearInternal();
1093
1094   if ( actor() ) {
1095     int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1096     foreach ( long id, ids ) {
1097       if ( !isElements() ) {
1098         //
1099         // show node info
1100         //
1101         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindNode( id );
1102         if ( !e ) return;
1103         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
1104       
1105         // node ID
1106         QTreeWidgetItem* nodeItem = createItem( 0, Bold | All );
1107         nodeItem->setText( 0, tr( "NODE" ) );
1108         nodeItem->setText( 1, QString( "#%1" ).arg( id ) );
1109         // coordinates
1110         QTreeWidgetItem* coordItem = createItem( nodeItem, Bold );
1111         coordItem->setText( 0, tr( "COORDINATES" ) );
1112         QTreeWidgetItem* xItem = createItem( coordItem );
1113         xItem->setText( 0, "X" );
1114         xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1115         QTreeWidgetItem* yItem = createItem( coordItem );
1116         yItem->setText( 0, "Y" );
1117         yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1118         QTreeWidgetItem* zItem = createItem( coordItem );
1119         zItem->setText( 0, "Z" );
1120         zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1121         // connectivity
1122         QTreeWidgetItem* conItem = createItem( nodeItem, Bold );
1123         conItem->setText( 0, tr( "CONNECTIVITY" ) );
1124         Connectivity connectivity = nodeConnectivity( node );
1125         if ( !connectivity.isEmpty() ) {
1126           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1127           if ( !con.isEmpty() ) {
1128             QTreeWidgetItem* i = createItem( conItem );
1129             i->setText( 0, tr( "0D_ELEMENTS" ) );
1130             i->setText( 1, con );
1131           }
1132           con = formatConnectivity( connectivity, SMDSAbs_Edge );
1133           if ( !con.isEmpty() ) {
1134             QTreeWidgetItem* i = createItem( conItem );
1135             i->setText( 0, tr( "EDGES" ) );
1136             i->setText( 1, con );
1137           }
1138           con = formatConnectivity( connectivity, SMDSAbs_Face );
1139           if ( !con.isEmpty() ) {
1140             QTreeWidgetItem* i = createItem( conItem );
1141             i->setText( 0, tr( "FACES" ) );
1142             i->setText( 1, con );
1143           }
1144           con = formatConnectivity( connectivity, SMDSAbs_Volume );
1145           if ( !con.isEmpty() ) {
1146             QTreeWidgetItem* i = createItem( conItem );
1147             i->setText( 0, tr( "VOLUMES" ) );
1148             i->setText( 1, con );
1149           }
1150         }
1151         else {
1152           conItem->setText( 1, tr( "FREE_NODE" ) );
1153         }
1154       }
1155       else {
1156         //
1157         // show element info
1158         // 
1159         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id );
1160         if ( !e ) return;
1161         
1162         // element ID && type
1163         QString stype;
1164         switch( e->GetType() ) {
1165         case SMDSAbs_0DElement:
1166           stype = tr( "0D ELEMENT" ); break;
1167         case SMDSAbs_Edge:
1168           stype = tr( "EDGE" ); break;
1169         case SMDSAbs_Face:
1170           stype = tr( "FACE" ); break;
1171         case SMDSAbs_Volume:
1172           stype = tr( "VOLUME" ); break;
1173         default: 
1174           break;
1175         }
1176         if ( stype.isEmpty() ) return;
1177         QTreeWidgetItem* elemItem = createItem( 0, Bold | All );
1178         elemItem->setText( 0, stype );
1179         elemItem->setText( 1, QString( "#%1" ).arg( id ) );
1180         // geometry type
1181         QString gtype;
1182         switch( e->GetEntityType() ) {
1183         case SMDSEntity_Triangle:
1184         case SMDSEntity_Quad_Triangle:
1185           gtype = tr( "TRIANGLE" ); break;
1186         case SMDSEntity_Quadrangle:
1187         case SMDSEntity_Quad_Quadrangle:
1188         case SMDSEntity_BiQuad_Quadrangle:
1189           gtype = tr( "QUADRANGLE" ); break;
1190         case SMDSEntity_Polygon:
1191         case SMDSEntity_Quad_Polygon:
1192           gtype = tr( "POLYGON" ); break;
1193         case SMDSEntity_Tetra:
1194         case SMDSEntity_Quad_Tetra:
1195           gtype = tr( "TETRAHEDRON" ); break;
1196         case SMDSEntity_Pyramid:
1197         case SMDSEntity_Quad_Pyramid:
1198           gtype = tr( "PYRAMID" ); break;
1199         case SMDSEntity_Hexa:
1200         case SMDSEntity_Quad_Hexa:
1201         case SMDSEntity_TriQuad_Hexa:
1202           gtype = tr( "HEXAHEDRON" ); break;
1203         case SMDSEntity_Penta:
1204         case SMDSEntity_Quad_Penta:
1205           gtype = tr( "PRISM" ); break;
1206         case SMDSEntity_Hexagonal_Prism:
1207           gtype = tr( "HEX_PRISM" ); break;
1208         case SMDSEntity_Polyhedra:
1209         case SMDSEntity_Quad_Polyhedra:
1210           gtype = tr( "POLYHEDRON" ); break;
1211         default: 
1212           break;
1213         }
1214         if ( !gtype.isEmpty() ) {
1215           QTreeWidgetItem* typeItem = createItem( elemItem, Bold );
1216           typeItem->setText( 0, tr( "TYPE" ) );
1217           typeItem->setText( 1, gtype );
1218         }
1219         // quadratic flag and gravity center (any element except 0D)
1220         if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) {
1221           // quadratic flag
1222           QTreeWidgetItem* quadItem = createItem( elemItem, Bold );
1223           quadItem->setText( 0, tr( "QUADRATIC" ) );
1224           quadItem->setText( 1, e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) );
1225           // gravity center
1226           XYZ gc = gravityCenter( e );
1227           QTreeWidgetItem* gcItem = createItem( elemItem, Bold );
1228           gcItem->setText( 0, tr( "GRAVITY_CENTER" ) );
1229           QTreeWidgetItem* xItem = createItem( gcItem );
1230           xItem->setText( 0, "X" );
1231           xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1232           QTreeWidgetItem* yItem = createItem( gcItem );
1233           yItem->setText( 0, "Y" );
1234           yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1235           QTreeWidgetItem* zItem = createItem( gcItem );
1236           zItem->setText( 0, "Z" );
1237           zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1238         }
1239         // connectivity
1240         QTreeWidgetItem* conItem = createItem( elemItem, Bold );
1241         conItem->setText( 0, tr( "CONNECTIVITY" ) );
1242         SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
1243         for ( int idx = 1; nodeIt->more(); idx++ ) {
1244           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1245           // node number and ID
1246           QTreeWidgetItem* nodeItem = createItem( conItem, Bold );
1247           nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ) );
1248           nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ) );
1249           nodeItem->setExpanded( false );
1250           // node coordinates
1251           QTreeWidgetItem* coordItem = createItem( nodeItem );
1252           coordItem->setText( 0, tr( "COORDINATES" ) );
1253           QTreeWidgetItem* xItem = createItem( coordItem );
1254           xItem->setText( 0, "X" );
1255           xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1256           QTreeWidgetItem* yItem = createItem( coordItem );
1257           yItem->setText( 0, "Y" );
1258           yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1259           QTreeWidgetItem* zItem = createItem( coordItem );
1260           zItem->setText( 0, "Z" );
1261           zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1262           // node connectivity
1263           QTreeWidgetItem* nconItem = createItem( nodeItem );
1264           nconItem->setText( 0, tr( "CONNECTIVITY" ) );
1265           Connectivity connectivity = nodeConnectivity( node );
1266           if ( !connectivity.isEmpty() ) {
1267             QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1268             if ( !con.isEmpty() ) {
1269               QTreeWidgetItem* i = createItem( nconItem );
1270               i->setText( 0, tr( "0D_ELEMENTS" ) );
1271               i->setText( 1, con );
1272             }
1273             con = formatConnectivity( connectivity, SMDSAbs_Edge );
1274             if ( !con.isEmpty() ) {
1275               QTreeWidgetItem* i = createItem( nconItem );
1276               i->setText( 0, tr( "EDGES" ) );
1277               i->setText( 1, con );
1278             }
1279             con = formatConnectivity( connectivity, SMDSAbs_Face );
1280             if ( !con.isEmpty() ) {
1281               QTreeWidgetItem* i = createItem( nconItem );
1282               i->setText( 0, tr( "FACES" ) );
1283               i->setText( 1, con );
1284             }
1285             con = formatConnectivity( connectivity, SMDSAbs_Volume );
1286             if ( !con.isEmpty() ) {
1287               QTreeWidgetItem* i = createItem( nconItem );
1288               i->setText( 0, tr( "VOLUMES" ) );
1289               i->setText( 1, con );
1290             }
1291           }
1292         }
1293       }
1294     }
1295   }
1296 }
1297
1298 /*!
1299   \brief Internal clean-up (reset widget)
1300 */
1301 void SMESHGUI_TreeElemInfo::clearInternal()
1302 {
1303   myInfo->clear();
1304   myInfo->repaint();
1305 }
1306
1307 /*!
1308   \brief Create new tree item.
1309   \param parent parent tree widget item
1310   \param flags item flag
1311   \return new tree widget item
1312 */
1313 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int flags )
1314 {
1315   QTreeWidgetItem* item;
1316   if ( parent )
1317     item = new QTreeWidgetItem( parent );
1318   else
1319     item = new QTreeWidgetItem( myInfo );
1320
1321   item->setFlags( item->flags() | Qt::ItemIsEditable );
1322
1323   QFont f = item->font( 0 );
1324   f.setBold( true );
1325   for ( int i = 0; i < myInfo->columnCount(); i++ ) {
1326     if ( ( flags & Bold ) && ( i == 0 || flags & All ) )
1327       item->setFont( i, f );
1328   }
1329
1330   item->setExpanded( true );
1331   return item;
1332 }
1333
1334 /*!
1335   \class GrpComputor
1336   \brief Mesh information computer
1337   \internal
1338   
1339   The class is created for different computation operation. Currently it is used
1340   to compute number of underlying nodes for the groups.
1341 */
1342
1343 /*!
1344   \brief Contructor
1345 */
1346 GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* item, QObject* parent )
1347   : QObject( parent ), myItem( item )
1348 {
1349   myGroup = SMESH::SMESH_GroupBase::_narrow( grp );
1350 }
1351
1352 /*!
1353   \brief Compute function
1354 */
1355 void GrpComputor::compute()
1356 {
1357   if ( !CORBA::is_nil( myGroup ) && myItem ) {
1358     QTreeWidgetItem* item = myItem;
1359     myItem = 0;
1360     int nbNodes = myGroup->GetNumberOfNodes();
1361     item->treeWidget()->removeItemWidget( item, 1 );
1362     item->setText( 1, QString::number( nbNodes ));
1363   }
1364 }
1365
1366 /*!
1367   \class SMESHGUI_AddInfo
1368   \brief The wigdet shows additional information on the mesh object.
1369 */
1370
1371 /*!
1372   \brief Constructor
1373   \param parent parent widget
1374 */
1375 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent )
1376 : QTreeWidget( parent )
1377 {
1378   setColumnCount( 2 );
1379   header()->setStretchLastSection( true );
1380   header()->setResizeMode( 0, QHeaderView::ResizeToContents );
1381   header()->hide();
1382 }
1383
1384 /*!
1385   \brief Destructor
1386 */
1387 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
1388 {
1389 }
1390
1391 /*!
1392   \brief Show additional information on the selected object
1393   \param obj object being processed (mesh, sub-mesh, group, ID source)
1394 */
1395 void SMESHGUI_AddInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
1396 {
1397   setProperty( "group_index", 0 );
1398   setProperty( "submesh_index",  0 );
1399   myComputors.clear();
1400   clear();
1401
1402   if ( CORBA::is_nil( obj ) ) return;
1403
1404   _PTR(SObject) sobj = SMESH::ObjectToSObject( obj );
1405   if ( !sobj ) return;
1406
1407   // name
1408   QTreeWidgetItem* nameItem = createItem( 0, Bold | All );
1409   nameItem->setText( 0, tr( "NAME" ) );
1410   nameItem->setText( 1, sobj->GetName().c_str() );
1411   
1412   SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
1413   SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
1414   SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
1415   
1416   if ( !aMesh->_is_nil() )
1417     meshInfo( aMesh, nameItem );
1418   else if ( !aSubMesh->_is_nil() )
1419     subMeshInfo( aSubMesh, nameItem );
1420   else if ( !aGroup->_is_nil() )
1421     groupInfo( aGroup.in(), nameItem );
1422 }
1423
1424 /*!
1425   \brief Create new tree item.
1426   \param parent parent tree widget item
1427   \param flags item flag
1428   \return new tree widget item
1429 */
1430 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int flags )
1431 {
1432   QTreeWidgetItem* item;
1433
1434   if ( parent )
1435     item = new QTreeWidgetItem( parent );
1436   else
1437     item = new QTreeWidgetItem( this );
1438
1439   //item->setFlags( item->flags() | Qt::ItemIsEditable );
1440
1441   QFont f = item->font( 0 );
1442   f.setBold( true );
1443   for ( int i = 0; i < columnCount(); i++ ) {
1444     if ( ( flags & Bold ) && ( i == 0 || flags & All ) )
1445       item->setFont( i, f );
1446   }
1447
1448   item->setExpanded( true );
1449   return item;
1450 }
1451
1452 /*!
1453   \brief Show mesh info
1454   \param mesh mesh object
1455   \param parent parent tree item
1456 */
1457 void SMESHGUI_AddInfo::meshInfo( SMESH::SMESH_Mesh_ptr mesh, QTreeWidgetItem* parent )
1458 {
1459   // type
1460   GEOM::GEOM_Object_var shape = mesh->GetShapeToMesh();
1461   SALOME_MED::MedFileInfo* inf = mesh->GetMEDFileInfo();
1462   QTreeWidgetItem* typeItem = createItem( parent, Bold );
1463   typeItem->setText( 0, tr( "TYPE" ) );
1464   if ( !CORBA::is_nil( shape ) ) {
1465     typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
1466     _PTR(SObject) sobj = SMESH::ObjectToSObject( shape );
1467     if ( sobj ) {
1468       QTreeWidgetItem* gobjItem = createItem( typeItem );
1469       gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
1470       gobjItem->setText( 1, sobj->GetName().c_str() );
1471     }
1472   }
1473   else if ( strlen( (char*)inf->fileName ) > 0 ) {
1474     typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
1475     QTreeWidgetItem* fileItem = createItem( typeItem );
1476     fileItem->setText( 0, tr( "FILE_NAME" ) );
1477     fileItem->setText( 1, (char*)inf->fileName );
1478   }
1479   else {
1480     typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
1481   }
1482   
1483   // groups
1484   myGroups = mesh->GetGroups();
1485   showGroups();
1486
1487   // sub-meshes
1488   mySubMeshes = mesh->GetSubMeshes();
1489   showSubMeshes();
1490 }
1491
1492 /*!
1493   \brief Show sub-mesh info
1494   \param subMesh sub-mesh object
1495   \param parent parent tree item
1496 */
1497 void SMESHGUI_AddInfo::subMeshInfo( SMESH::SMESH_subMesh_ptr subMesh, QTreeWidgetItem* parent )
1498 {
1499   bool isShort = parent->parent() != 0;
1500
1501   if ( !isShort ) {
1502     // parent mesh
1503     _PTR(SObject) sobj = SMESH::ObjectToSObject( subMesh->GetFather() );
1504     if ( sobj ) {
1505       QTreeWidgetItem* nameItem = createItem( parent, Bold );
1506       nameItem->setText( 0, tr( "PARENT_MESH" ) );
1507       nameItem->setText( 1, sobj->GetName().c_str() );
1508     }
1509   }
1510   
1511   // shape
1512   GEOM::GEOM_Object_var gobj = subMesh->GetSubShape();
1513   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1514   if ( sobj ) {
1515     QTreeWidgetItem* gobjItem = createItem( parent, Bold );
1516     gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
1517     gobjItem->setText( 1, sobj->GetName().c_str() );
1518   }
1519 }
1520
1521 /*!
1522   \brief Show group info
1523   \param grp mesh group object
1524   \param parent parent tree item
1525 */
1526 void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* parent )
1527 {
1528   bool isShort = parent->parent() != 0;
1529
1530   SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( grp );
1531   SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( grp );
1532   SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( grp );
1533
1534   if ( !isShort ) {
1535     // parent mesh
1536     _PTR(SObject) sobj = SMESH::ObjectToSObject( grp->GetMesh() );
1537     if ( sobj ) {
1538       QTreeWidgetItem* nameItem = createItem( parent, Bold );
1539       nameItem->setText( 0, tr( "PARENT_MESH" ) );
1540       nameItem->setText( 1, sobj->GetName().c_str() );
1541     }
1542   }
1543
1544   // type : group on geometry, standalone group, group on filter
1545   QTreeWidgetItem* typeItem = createItem( parent, Bold );
1546   typeItem->setText( 0, tr( "TYPE" ) );
1547   if ( !CORBA::is_nil( aStdGroup ) ) {
1548     typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
1549   }
1550   else if ( !CORBA::is_nil( aGeomGroup ) ) {
1551     typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
1552     GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1553     _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1554     if ( sobj ) {
1555       QTreeWidgetItem* gobjItem = createItem( typeItem );
1556       gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
1557       gobjItem->setText( 1, sobj->GetName().c_str() );
1558     }
1559   }
1560   else if ( !CORBA::is_nil( aFltGroup ) ) {
1561     typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
1562   }
1563
1564   if ( !isShort ) {
1565     // entity type
1566     QString etype = tr( "UNKNOWN" );
1567     switch( grp->GetType() ) {
1568     case SMESH::NODE:
1569       etype = tr( "NODE" );
1570       break;
1571     case SMESH::EDGE:
1572       etype = tr( "EDGE" );
1573       break;
1574     case SMESH::FACE:
1575       etype = tr( "FACE" );
1576       break;
1577     case SMESH::VOLUME:
1578       etype = tr( "VOLUME" );
1579       break;
1580     case SMESH::ELEM0D:
1581       etype = tr( "0DELEM" );
1582       break;
1583     default:
1584       break;
1585     }
1586     QTreeWidgetItem* etypeItem = createItem( parent, Bold );
1587     etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
1588     etypeItem->setText( 1, etype );
1589   }
1590
1591   // size
1592   QTreeWidgetItem* sizeItem = createItem( parent, Bold );
1593   sizeItem->setText( 0, tr( "SIZE" ) );
1594   sizeItem->setText( 1, QString::number( grp->Size() ) );
1595
1596   // color
1597   SALOMEDS::Color color = grp->GetColor();
1598   QTreeWidgetItem* colorItem = createItem( parent, Bold );
1599   colorItem->setText( 0, tr( "COLOR" ) );
1600   colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
1601
1602   // nb of underlying nodes
1603   if ( grp->GetType() != SMESH::NODE) {
1604     QTreeWidgetItem* nodesItem = createItem( parent, Bold );
1605     nodesItem->setText( 0, tr( "NB_NODES" ) );
1606     int nbNodesLimit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
1607     SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
1608     bool meshLoaded = mesh->IsLoaded();
1609     bool toShowNodes = ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit );
1610     if ( toShowNodes && meshLoaded ) {
1611       // already calculated and up-to-date
1612       nodesItem->setText( 1, QString::number( grp->GetNumberOfNodes() ) );
1613     }
1614     else {
1615       QPushButton* btn = new QPushButton( tr( meshLoaded ? "COMPUTE" : "LOAD"), this );
1616       setItemWidget( nodesItem, 1, btn );
1617       GrpComputor* comp = new GrpComputor( grp, nodesItem, this ); 
1618       connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
1619       myComputors.append( comp );
1620       if ( !meshLoaded )
1621         connect( btn, SIGNAL( clicked() ), this, SLOT( changeLoadToCompute() ) );
1622     }
1623   }
1624 }
1625
1626 void SMESHGUI_AddInfo::showGroups()
1627 {
1628   myComputors.clear();
1629
1630   QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
1631   if ( !parent ) return;
1632
1633   int idx = property( "group_index" ).toInt();
1634
1635   QTreeWidgetItem* itemGroups = 0;
1636   for ( int i = 0; i < parent->childCount() && !itemGroups; i++ ) {
1637     if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GROUPS_ID ) {
1638       itemGroups = parent->child( i );
1639       ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemGroups, 1 ) );
1640       if ( extra )
1641         extra->updateControls( myGroups->length(), idx );
1642       while ( itemGroups->childCount() ) delete itemGroups->child( 0 ); // clear child items
1643     }
1644   }
1645
1646   QMap<int, QTreeWidgetItem*> grpItems;
1647   for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)myGroups->length() ); i++ ) {
1648     SMESH::SMESH_GroupBase_var grp = myGroups[i];
1649     if ( CORBA::is_nil( grp ) ) continue;
1650     _PTR(SObject) grpSObj = SMESH::ObjectToSObject( grp );
1651     if ( !grpSObj ) continue;
1652
1653     int grpType = grp->GetType();
1654
1655     if ( !itemGroups ) {
1656       // create top-level groups container item
1657       itemGroups = createItem( parent, Bold | All );
1658       itemGroups->setText( 0, tr( "GROUPS" ) );
1659       itemGroups->setData( 0, Qt::UserRole, GROUPS_ID );
1660
1661       // total number of groups > 10, show extra widgets for info browsing
1662       if ( myGroups->length() > MAXITEMS ) {
1663         ExtraWidget* extra = new ExtraWidget( this, true );
1664         connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
1665         connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
1666         setItemWidget( itemGroups, 1, extra );
1667         extra->updateControls( myGroups->length(), idx );
1668       }
1669     }
1670
1671     if ( grpItems.find( grpType ) == grpItems.end() ) {
1672       grpItems[ grpType ] = createItem( itemGroups, Bold | All );
1673       grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
1674       itemGroups->insertChild( grpType-1, grpItems[ grpType ] );
1675     }
1676   
1677     // group name
1678     QTreeWidgetItem* grpNameItem = createItem( grpItems[ grpType ] );
1679     grpNameItem->setText( 0, QString( grpSObj->GetName().c_str() ).trimmed() ); // name is trimmed
1680
1681     // group info
1682     groupInfo( grp.in(), grpNameItem );
1683   }
1684 }
1685
1686 void SMESHGUI_AddInfo::showSubMeshes()
1687 {
1688   QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
1689   if ( !parent ) return;
1690
1691   int idx = property( "submesh_index" ).toInt();
1692
1693   QTreeWidgetItem* itemSubMeshes = 0;
1694   for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ ) {
1695     if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SUBMESHES_ID ) {
1696       itemSubMeshes = parent->child( i );
1697       ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemSubMeshes, 1 ) );
1698       if ( extra )
1699         extra->updateControls( mySubMeshes->length(), idx );
1700       while ( itemSubMeshes->childCount() ) delete itemSubMeshes->child( 0 ); // clear child items
1701     }
1702   }
1703
1704   QMap<int, QTreeWidgetItem*> smItems;
1705   for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)mySubMeshes->length() ); i++ ) {
1706     SMESH::SMESH_subMesh_var sm = mySubMeshes[i];
1707     if ( CORBA::is_nil( sm ) ) continue;
1708     _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm );
1709     if ( !smSObj ) continue;
1710     
1711     GEOM::GEOM_Object_var gobj = sm->GetSubShape();
1712     if ( CORBA::is_nil(gobj ) ) continue;
1713     
1714     int smType = gobj->GetShapeType();
1715     if ( smType == GEOM::COMPSOLID ) smType = GEOM::COMPOUND;
1716
1717     if ( !itemSubMeshes ) {
1718       itemSubMeshes = createItem( parent, Bold | All );
1719       itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
1720       itemSubMeshes->setData( 0, Qt::UserRole, SUBMESHES_ID );
1721
1722       // total number of sub-meshes > 10, show extra widgets for info browsing
1723       if ( mySubMeshes->length() > MAXITEMS ) {
1724         ExtraWidget* extra = new ExtraWidget( this, true );
1725         connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
1726         connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
1727         setItemWidget( itemSubMeshes, 1, extra );
1728         extra->updateControls( mySubMeshes->length(), idx );
1729       }
1730     }
1731          
1732     if ( smItems.find( smType ) == smItems.end() ) {
1733       smItems[ smType ] = createItem( itemSubMeshes, Bold | All );
1734       smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
1735       itemSubMeshes->insertChild( smType, smItems[ smType ] );
1736     }
1737     
1738     // submesh name
1739     QTreeWidgetItem* smNameItem = createItem( smItems[ smType ] );
1740     smNameItem->setText( 0, QString( smSObj->GetName().c_str() ).trimmed() ); // name is trimmed
1741     
1742     // submesh info
1743     subMeshInfo( sm.in(), smNameItem );
1744   }
1745 }
1746
1747 /*!
1748  * \brief Change button label of "nb underlying node" group from "Load" to "Compute"
1749  */
1750 void SMESHGUI_AddInfo::changeLoadToCompute()
1751 {
1752   for ( int i = 0; i < myComputors.count(); ++i )
1753   {
1754     if ( QTreeWidgetItem* item = myComputors[i]->getItem() )
1755     {
1756       if ( QPushButton* btn = qobject_cast<QPushButton*>( itemWidget ( item, 1 ) ) )
1757         btn->setText( tr("COMPUTE") );
1758     }
1759   }
1760 }
1761
1762 void SMESHGUI_AddInfo::showPreviousGroups()
1763 {
1764   int idx = property( "group_index" ).toInt();
1765   setProperty( "group_index", idx-1 );
1766   showGroups();
1767 }
1768
1769 void SMESHGUI_AddInfo::showNextGroups()
1770 {
1771   int idx = property( "group_index" ).toInt();
1772   setProperty( "group_index", idx+1 );
1773   showGroups();
1774 }
1775
1776 void SMESHGUI_AddInfo::showPreviousSubMeshes()
1777 {
1778   int idx = property( "submesh_index" ).toInt();
1779   setProperty( "submesh_index", idx-1 );
1780   showSubMeshes();
1781 }
1782
1783 void SMESHGUI_AddInfo::showNextSubMeshes()
1784 {
1785   int idx = property( "submesh_index" ).toInt();
1786   setProperty( "submesh_index", idx+1 );
1787   showSubMeshes();
1788 }
1789
1790 /*!
1791   \class SMESHGUI_MeshInfoDlg
1792   \brief Mesh information dialog box
1793 */
1794
1795 /*!
1796   \brief Constructor
1797   \param parent parent widget
1798   \param page specifies the dialog page to be shown at the start-up
1799 */
1800 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
1801 : QDialog( parent ), myActor( 0 )
1802 {
1803   setModal( false );
1804   setAttribute( Qt::WA_DeleteOnClose, true );
1805   setWindowTitle( tr( "MESH_INFO" ) );
1806   setSizeGripEnabled( true );
1807
1808   myTabWidget = new QTabWidget( this );
1809
1810   // base info 
1811
1812   myBaseInfo = new SMESHGUI_MeshInfo( myTabWidget );
1813   myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
1814
1815   // elem info 
1816   
1817   QWidget* w = new QWidget( myTabWidget );
1818
1819   myMode = new QButtonGroup( this );
1820   myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
1821   myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
1822   myMode->button( NodeMode )->setChecked( true );
1823   myID = new QLineEdit( w );
1824   myID->setValidator( new SMESHGUI_IdValidator( this ) );
1825
1826   int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
1827   mode = qMin( 1, qMax( 0, mode ) );
1828   
1829   if ( mode == 0 ) 
1830     myElemInfo = new SMESHGUI_SimpleElemInfo( w );
1831   else
1832     myElemInfo = new SMESHGUI_TreeElemInfo( w );
1833
1834   QGridLayout* elemLayout = new QGridLayout( w );
1835   elemLayout->setMargin( MARGIN );
1836   elemLayout->setSpacing( SPACING );
1837   elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
1838   elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
1839   elemLayout->addWidget( myID, 0, 2 );
1840   elemLayout->addWidget( myElemInfo, 1, 0, 1, 3 );
1841   
1842   myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
1843
1844   // additional info
1845
1846   myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
1847   myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
1848
1849   // buttons
1850
1851   QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
1852   okBtn->setAutoDefault( true );
1853   okBtn->setDefault( true );
1854   okBtn->setFocus();
1855   QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
1856   helpBtn->setAutoDefault( true );
1857
1858   QHBoxLayout* btnLayout = new QHBoxLayout;
1859   btnLayout->setSpacing( SPACING );
1860   btnLayout->setMargin( 0 );
1861
1862   btnLayout->addWidget( okBtn );
1863   btnLayout->addStretch( 10 );
1864   btnLayout->addWidget( helpBtn );
1865
1866   QVBoxLayout* l = new QVBoxLayout ( this );
1867   l->setMargin( MARGIN );
1868   l->setSpacing( SPACING );
1869   l->addWidget( myTabWidget );
1870   l->addLayout( btnLayout );
1871
1872   myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
1873
1874   connect( okBtn,       SIGNAL( clicked() ),              this, SLOT( reject() ) );
1875   connect( helpBtn,     SIGNAL( clicked() ),              this, SLOT( help() ) );
1876   connect( myTabWidget, SIGNAL( currentChanged( int  ) ), this, SLOT( updateSelection() ) );
1877   connect( myMode,      SIGNAL( buttonClicked( int  ) ),  this, SLOT( modeChanged() ) );
1878   connect( myID,        SIGNAL( textEdited( QString  ) ), this, SLOT( idChanged() ) );
1879   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
1880   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalCloseAllDialogs() ),        this, SLOT( reject() ) );
1881
1882   updateSelection();
1883 }
1884
1885 /*!
1886   \brief Destructor
1887 */
1888 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
1889 {
1890 }
1891
1892 /*!
1893   \brief Show mesh information
1894   \param IO interactive object
1895 */
1896 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO )
1897 {
1898   SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
1899   if ( !CORBA::is_nil( obj ) ) {
1900     myBaseInfo->showInfo( obj );
1901     myAddInfo->showInfo( obj );
1902
1903     myActor = SMESH::FindActorByEntry( IO->getEntry() );
1904     SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
1905     QString ID;
1906     int nb = 0;
1907     if ( myActor && selector ) {
1908       nb = myMode->checkedId() == NodeMode ? 
1909         SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
1910         SMESH::GetNameOfSelectedNodes( selector, IO, ID );
1911     }
1912     myElemInfo->setSource( myActor ) ;
1913     if ( nb > 0 ) {
1914       myID->setText( ID.trimmed() );
1915       QSet<long> ids;
1916       QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
1917       foreach ( ID, idTxt )
1918         ids << ID.trimmed().toLong();
1919       myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode );
1920     }
1921     else {
1922       myID->clear();
1923       myElemInfo->clear();
1924     }
1925   }
1926 }
1927
1928 /*!
1929   \brief Perform clean-up actions on the dialog box closing.
1930 */
1931 void SMESHGUI_MeshInfoDlg::reject()
1932 {
1933   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
1934   selMgr->clearFilters();
1935   SMESH::SetPointRepresentation( false );
1936   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1937     aViewWindow->SetSelectionMode( ActorSelection );
1938   QDialog::reject();
1939 }
1940
1941 /*!
1942   \brief Process keyboard event
1943   \param e key press event
1944 */
1945 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
1946 {
1947   QDialog::keyPressEvent( e );
1948   if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
1949     e->accept();
1950     help();
1951   }
1952 }
1953
1954 /*!
1955   \brief Reactivate dialog box, when mouse pointer goes into it.
1956 */
1957 void SMESHGUI_MeshInfoDlg::enterEvent( QEvent* )
1958 {
1959   //activate();
1960 }
1961
1962 /*!
1963   \brief Setup selection mode depending on the current dialog box state.
1964 */
1965 void SMESHGUI_MeshInfoDlg::updateSelection()
1966 {
1967   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
1968
1969   disconnect( selMgr, 0, this, 0 );
1970   selMgr->clearFilters();
1971
1972   if ( myTabWidget->currentIndex() == BaseInfo || myTabWidget->currentIndex() == AddInfo ) {
1973     SMESH::SetPointRepresentation( false );
1974     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1975       aViewWindow->SetSelectionMode( ActorSelection );
1976   }
1977   else {
1978     if ( myMode->checkedId() == NodeMode ) {
1979       SMESH::SetPointRepresentation( true );
1980       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1981         aViewWindow->SetSelectionMode( NodeSelection );
1982     }
1983     else {
1984       SMESH::SetPointRepresentation( false );
1985       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1986         aViewWindow->SetSelectionMode( CellSelection );
1987     }
1988   }
1989
1990   QString oldID = myID->text().trimmed();
1991   SMESH_Actor* oldActor = myActor;
1992   myID->clear();
1993   
1994   connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
1995   updateInfo();
1996   
1997   if ( oldActor == myActor && myActor && !oldID.isEmpty() ) {
1998     myID->setText( oldID );
1999     idChanged();
2000   }
2001 }
2002
2003 /*!
2004   \brief Show help page
2005 */
2006 void SMESHGUI_MeshInfoDlg::help()
2007 {
2008   SMESH::ShowHelpFile( ( myTabWidget->currentIndex() == BaseInfo || myTabWidget->currentIndex() == AddInfo ) ?
2009                        "mesh_infos_page.html#advanced_mesh_infos_anchor" : 
2010                        "mesh_infos_page.html#mesh_element_info_anchor" );
2011 }
2012
2013 /*!
2014   \brief Show mesh information
2015 */
2016 void SMESHGUI_MeshInfoDlg::updateInfo()
2017 {
2018   SUIT_OverrideCursor wc;
2019
2020   SALOME_ListIO selected;
2021   SMESHGUI::selectionMgr()->selectedObjects( selected );
2022
2023   if ( selected.Extent() == 1 ) {
2024     Handle(SALOME_InteractiveObject) IO = selected.First();
2025     showInfo( IO );
2026   }
2027 //   else {
2028 //     myBaseInfo->clear();
2029 //     myElemInfo->clear();
2030 //     myAddInfo->clear();
2031 //   }
2032 }
2033
2034 /*!
2035   \brief Activate dialog box
2036 */
2037 void SMESHGUI_MeshInfoDlg::activate()
2038 {
2039   SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
2040   SMESHGUI::GetSMESHGUI()->SetActiveDialogBox( this );
2041   myTabWidget->setEnabled( true );
2042   updateSelection();
2043 }
2044
2045 /*!
2046   \brief Deactivate dialog box
2047 */
2048 void SMESHGUI_MeshInfoDlg::deactivate()
2049 {
2050   myTabWidget->setEnabled( false );
2051   disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
2052 }
2053
2054 /*!
2055   \brief Called when users switches between node / element modes.
2056 */
2057 void SMESHGUI_MeshInfoDlg::modeChanged()
2058 {
2059   myID->clear();
2060   updateSelection();
2061 }
2062
2063 /*!
2064   \brief Caled when users prints mesh element ID in the corresponding field.
2065 */
2066 void SMESHGUI_MeshInfoDlg::idChanged()
2067 {
2068   SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
2069   if ( myActor && selector ) {
2070     Handle(SALOME_InteractiveObject) IO = myActor->getIO();
2071     TColStd_MapOfInteger ID;
2072     QSet<long> ids;
2073     QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
2074     foreach ( QString tid, idTxt ) {
2075       long id = tid.trimmed().toLong();
2076       const SMDS_MeshElement* e = myMode->checkedId() == ElemMode ? 
2077         myActor->GetObject()->GetMesh()->FindElement( id ) :
2078         myActor->GetObject()->GetMesh()->FindNode( id );
2079       if ( e ) {
2080         ID.Add( id );
2081         ids << id;
2082       }
2083     }
2084     selector->AddOrRemoveIndex( IO, ID, false );
2085     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2086       aViewWindow->highlight( IO, true, true );
2087     myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode );
2088   }
2089 }