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