Salome HOME
Merge from V5_1_main branch 24/11/2010
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshInfo.cxx
1 //  Copyright (C) 2007-2010  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 <QTreeWidget>
56 #include <QVBoxLayout>
57
58 #include <SALOMEconfig.h>
59 #include CORBA_SERVER_HEADER(SMESH_Group)
60
61 const int SPACING = 6;
62 const int MARGIN  = 9;
63
64 /*!
65   \class SMESHGUI_MeshInfo
66   \brief Base mesh information widget
67   
68   Displays the base information about mesh object: mesh, sub-mesh, group or arbitrary ID source.
69 */
70
71 /*!
72   \brief Constructor.
73   \param parent parent widget
74 */
75 SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
76   : QFrame( parent ), myWidgets( iElementsEnd )
77 {
78   setFrameStyle( StyledPanel | Sunken );
79
80   QGridLayout* l = new QGridLayout( this );
81   l->setMargin( MARGIN );
82   l->setSpacing( SPACING );
83
84   // object
85   QLabel* aNameLab     = new QLabel( tr( "NAME_LAB" ), this );
86   QLabel* aName        = createField();
87   aName->setMinimumWidth( 150 );
88   QLabel* aObjLab      = new QLabel( tr( "OBJECT_LAB" ), this );
89   QLabel* aObj         = createField();
90   aObj->setMinimumWidth( 150 );
91   myWidgets[0] << aNameLab << aName;
92   myWidgets[1] << aObjLab  << aObj;
93
94   // nodes
95   QWidget* aNodesLine  = createLine();
96   QLabel*  aNodesLab   = new QLabel( tr( "NODES_LAB" ), this );
97   QLabel*  aNodes      = createField();
98   myWidgets[2] << aNodesLine;
99   myWidgets[3] << aNodesLab << aNodes;
100
101   // elements
102   QWidget* aElemLine   = createLine();
103   QLabel*  aElemLab    = new QLabel( tr( "ELEMENTS_LAB" ),  this );
104   QLabel*  aElemTotal  = new QLabel( tr( "TOTAL_LAB" ),     this );
105   QLabel*  aElemLin    = new QLabel( tr( "LINEAR_LAB" ),    this );
106   QLabel*  aElemQuad   = new QLabel( tr( "QUADRATIC_LAB" ), this );
107   myWidgets[4] << aElemLine;
108   myWidgets[5] << aElemLab << aElemTotal << aElemLin << aElemQuad;
109
110   // ... 0D elements
111   QWidget* a0DLine     = createLine();
112   QLabel*  a0DLab      = new QLabel( tr( "0D_LAB" ), this );
113   QLabel*  a0DTotal    = createField();
114   myWidgets[6] << a0DLine;
115   myWidgets[7] << a0DLab << a0DTotal;
116
117   // ... 1D elements
118   QWidget* a1DLine     = createLine();
119   QLabel*  a1DLab      = new QLabel( tr( "1D_LAB" ), this );
120   QLabel*  a1DTotal    = createField();
121   QLabel*  a1DLin      = createField();
122   QLabel*  a1DQuad     = createField();
123   myWidgets[8] << a1DLine;
124   myWidgets[9] << a1DLab << a1DTotal << a1DLin << a1DQuad;
125
126   // ... 2D elements
127   QWidget* a2DLine     = createLine();
128   QLabel*  a2DLab      = new QLabel( tr( "2D_LAB" ), this );
129   QLabel*  a2DTotal    = createField();
130   QLabel*  a2DLin      = createField();
131   QLabel*  a2DQuad     = createField();
132   QLabel*  a2DTriLab   = new QLabel( tr( "TRIANGLES_LAB" ), this );
133   QLabel*  a2DTriTotal = createField();
134   QLabel*  a2DTriLin   = createField();
135   QLabel*  a2DTriQuad  = createField();
136   QLabel*  a2DQuaLab   = new QLabel( tr( "QUADRANGLES_LAB" ), this );
137   QLabel*  a2DQuaTotal = createField();
138   QLabel*  a2DQuaLin   = createField();
139   QLabel*  a2DQuaQuad  = createField();
140   QLabel*  a2DPolLab   = new QLabel( tr( "POLYGONS_LAB" ), this );
141   QLabel*  a2DPolTotal = createField();
142   myWidgets[10] << a2DLine;
143   myWidgets[11] << a2DLab    << a2DTotal    << a2DLin    << a2DQuad;
144   myWidgets[12] << a2DTriLab << a2DTriTotal << a2DTriLin << a2DTriQuad;
145   myWidgets[13] << a2DQuaLab << a2DQuaTotal << a2DQuaLin << a2DQuaQuad;
146   myWidgets[14] << a2DPolLab << a2DPolTotal;
147
148   // ... 3D elements
149   QWidget* a3DLine     = createLine();
150   QLabel*  a3DLab      = new QLabel( tr( "3D_LAB" ), this );
151   QLabel*  a3DTotal    = createField();
152   QLabel*  a3DLin      = createField();
153   QLabel*  a3DQuad     = createField();
154   QLabel*  a3DTetLab   = new QLabel( tr( "TETRAHEDRONS_LAB" ), this );
155   QLabel*  a3DTetTotal = createField();
156   QLabel*  a3DTetLin   = createField();
157   QLabel*  a3DTetQuad  = createField();
158   QLabel*  a3DHexLab   = new QLabel( tr( "HEXAHEDONRS_LAB" ), this );
159   QLabel*  a3DHexTotal = createField();
160   QLabel*  a3DHexLin   = createField();
161   QLabel*  a3DHexQuad  = createField();
162   QLabel*  a3DPyrLab   = new QLabel( tr( "PYRAMIDS_LAB" ), this );
163   QLabel*  a3DPyrTotal = createField();
164   QLabel*  a3DPyrLin   = createField();
165   QLabel*  a3DPyrQuad  = createField();
166   QLabel*  a3DPriLab   = new QLabel( tr( "PRISMS_LAB" ), this );
167   QLabel*  a3DPriTotal = createField();
168   QLabel*  a3DPriLin   = createField();
169   QLabel*  a3DPriQuad  = createField();
170   QLabel*  a3DPolLab   = new QLabel( tr( "POLYHEDRONS_LAB" ), this );
171   QLabel*  a3DPolTotal = createField();
172   myWidgets[15] << a3DLine;
173   myWidgets[16] << a3DLab    << a3DTotal    << a3DLin    << a3DQuad;
174   myWidgets[17] << a3DTetLab << a3DTetTotal << a3DTetLin << a3DTetQuad;
175   myWidgets[18] << a3DHexLab << a3DHexTotal << a3DHexLin << a3DHexQuad;
176   myWidgets[19] << a3DPyrLab << a3DPyrTotal << a3DPyrLin << a3DPyrQuad;
177   myWidgets[20] << a3DPriLab << a3DPriTotal << a3DPriLin << a3DPriQuad;
178   myWidgets[21] << a3DPolLab << a3DPolTotal;
179
180   setFontAttributes( aNameLab,   Bold );
181   setFontAttributes( aObjLab,    Bold );
182   setFontAttributes( aNodesLab,  Bold );
183   setFontAttributes( aElemLab,   Bold );
184   setFontAttributes( aElemTotal, Italic );
185   setFontAttributes( aElemLin,   Italic );
186   setFontAttributes( aElemQuad,  Italic );
187   setFontAttributes( a0DLab,     Bold );
188   setFontAttributes( a1DLab,     Bold );
189   setFontAttributes( a2DLab,     Bold );
190   setFontAttributes( a3DLab,     Bold );
191
192   l->addWidget( aNameLab,     0, 0 );
193   l->addWidget( aName,        0, 1, 1, 3 );
194   l->addWidget( aObjLab,      1, 0 );
195   l->addWidget( aObj,         1, 1, 1, 3 );
196   l->addWidget( aNodesLine,   2, 0, 1, 4 );
197   l->addWidget( aNodesLab,    3, 0 );
198   l->addWidget( aNodes,       3, 1 );
199   l->addWidget( aElemLine,    4, 0, 1, 4 );
200   l->addWidget( aElemLab,     5, 0 );
201   l->addWidget( aElemTotal,   5, 1 );
202   l->addWidget( aElemLin,     5, 2 );
203   l->addWidget( aElemQuad,    5, 3 );
204   l->addWidget( a0DLine,      6, 1, 1, 3 );
205   l->addWidget( a0DLab,       7, 0 );
206   l->addWidget( a0DTotal,     7, 1 );
207   l->addWidget( a1DLine,      8, 1, 1, 3 );
208   l->addWidget( a1DLab,       9, 0 );
209   l->addWidget( a1DTotal,     9, 1 );
210   l->addWidget( a1DLin,       9, 2 );
211   l->addWidget( a1DQuad,      9, 3 );
212   l->addWidget( a2DLine,     10, 1, 1, 3 );
213   l->addWidget( a2DLab,      11, 0 );
214   l->addWidget( a2DTotal,    11, 1 );
215   l->addWidget( a2DLin,      11, 2 );
216   l->addWidget( a2DQuad,     11, 3 );
217   l->addWidget( a2DTriLab,   12, 0 );
218   l->addWidget( a2DTriTotal, 12, 1 );
219   l->addWidget( a2DTriLin,   12, 2 );
220   l->addWidget( a2DTriQuad,  12, 3 );
221   l->addWidget( a2DQuaLab,   13, 0 );
222   l->addWidget( a2DQuaTotal, 13, 1 );
223   l->addWidget( a2DQuaLin,   13, 2 );
224   l->addWidget( a2DQuaQuad,  13, 3 );
225   l->addWidget( a2DPolLab,   14, 0 );
226   l->addWidget( a2DPolTotal, 14, 1 );
227   l->addWidget( a3DLine,     15, 1, 1, 3 );
228   l->addWidget( a3DLab,      16, 0 );
229   l->addWidget( a3DTotal,    16, 1 );
230   l->addWidget( a3DLin,      16, 2 );
231   l->addWidget( a3DQuad,     16, 3 );
232   l->addWidget( a3DTetLab,   17, 0 );
233   l->addWidget( a3DTetTotal, 17, 1 );
234   l->addWidget( a3DTetLin,   17, 2 );
235   l->addWidget( a3DTetQuad,  17, 3 );
236   l->addWidget( a3DHexLab,   18, 0 );
237   l->addWidget( a3DHexTotal, 18, 1 );
238   l->addWidget( a3DHexLin,   18, 2 );
239   l->addWidget( a3DHexQuad,  18, 3 );
240   l->addWidget( a3DPyrLab,   19, 0 );
241   l->addWidget( a3DPyrTotal, 19, 1 );
242   l->addWidget( a3DPyrLin,   19, 2 );
243   l->addWidget( a3DPyrQuad,  19, 3 );
244   l->addWidget( a3DPriLab,   20, 0 );
245   l->addWidget( a3DPriTotal, 20, 1 );
246   l->addWidget( a3DPriLin,   20, 2 );
247   l->addWidget( a3DPriQuad,  20, 3 );
248   l->addWidget( a3DPolLab,   21, 0 );
249   l->addWidget( a3DPolTotal, 21, 1 );
250   l->setColumnStretch( 0, 0 );
251   l->setColumnStretch( 1, 5 );
252   l->setColumnStretch( 2, 5 );
253   l->setColumnStretch( 3, 5 );
254   l->setRowStretch( 22, 5 );
255
256   clear();
257 }
258
259 /*!
260   \brief Destructor
261 */
262 SMESHGUI_MeshInfo::~SMESHGUI_MeshInfo()
263 {
264 }
265
266 /*!
267   \brief Show information on the mesh object.
268   \param obj object being processed (mesh, sub-mesh, group, ID source)
269 */
270 void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
271 {
272   clear();
273   if ( !CORBA::is_nil( obj ) ) {
274     _PTR(SObject) sobj = ObjectToSObject( obj );
275     if ( sobj ) 
276       myWidgets[iName][iSingle]->setProperty( "text", sobj->GetName().c_str() );
277     SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
278     SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
279     SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
280     if ( !aMesh->_is_nil() ) {
281       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_MESH" ) );
282     }
283     else if ( !aSubMesh->_is_nil() ) {
284       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_SUBMESH" ) );
285     }
286     else if ( !aGroup->_is_nil() ) {
287       QString objType;
288       switch( aGroup->GetType() ) {
289       case SMESH::NODE:
290         objType = tr( "OBJECT_GROUP_NODES" );
291         break;
292       case SMESH::EDGE:
293         objType = tr( "OBJECT_GROUP_EDGES" );
294         break;
295       case SMESH::FACE:
296         objType = tr( "OBJECT_GROUP_FACES" );
297         break;
298       case SMESH::VOLUME:
299         objType = tr( "OBJECT_GROUP_VOLUMES" );
300         break;
301       case SMESH::ELEM0D:
302         objType = tr( "OBJECT_GROUP_0DELEMS" );
303         break;
304       default:
305         objType = tr( "OBJECT_GROUP" );
306         break;
307       }
308       myWidgets[iObject][iSingle]->setProperty( "text", objType );
309     }
310     SMESH::long_array_var info = obj->GetMeshInfo();
311     myWidgets[iNodes][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Node] ) );
312     myWidgets[i0D][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_0D] ) );
313     long nbEdges = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
314     myWidgets[i1D][iTotal]->setProperty( "text", QString::number( nbEdges ) );
315     myWidgets[i1D][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Edge] ) );
316     myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Edge] ) );
317     long nbTriangles   = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle];
318     long nbQuadrangles = info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle];
319     long nb2DLinear    = info[SMDSEntity_Triangle] + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
320     long nb2DQuadratic = info[SMDSEntity_Quad_Triangle] + info[SMDSEntity_Quad_Quadrangle];
321     myWidgets[i2D][iTotal]->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ) );
322     myWidgets[i2D][iLinear]->setProperty( "text", QString::number( nb2DLinear ) );
323     myWidgets[i2D][iQuadratic]->setProperty( "text", QString::number( nb2DQuadratic ) );
324     myWidgets[i2DTriangles][iTotal]->setProperty( "text", QString::number( nbTriangles ) );
325     myWidgets[i2DTriangles][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Triangle] ) );
326     myWidgets[i2DTriangles][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Triangle] ) );
327     myWidgets[i2DQuadrangles][iTotal]->setProperty( "text", QString::number( nbQuadrangles ) );
328     myWidgets[i2DQuadrangles][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
329     myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Quadrangle] ) );
330     myWidgets[i2DPolygons][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
331     long nbTetrahedrons = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra];
332     long nbHexahedrons  = info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa];
333     long nbPyramids     = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
334     long nbPrisms       = info[SMDSEntity_Penta]   + info[SMDSEntity_Quad_Penta];
335     long nb3DLinear     = info[SMDSEntity_Tetra] + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra];
336     long nb3DQuadratic  = info[SMDSEntity_Quad_Tetra] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_Quad_Pyramid] + info[SMDSEntity_Quad_Penta];
337     myWidgets[i3D][iTotal]->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
338     myWidgets[i3D][iLinear]->setProperty( "text", QString::number( nb3DLinear ) );
339     myWidgets[i3D][iQuadratic]->setProperty( "text", QString::number( nb3DQuadratic ) );
340     myWidgets[i3DTetrahedrons][iTotal]->setProperty( "text", QString::number( nbTetrahedrons ) );
341     myWidgets[i3DTetrahedrons][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Tetra] ) );
342     myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Tetra] ) );
343     myWidgets[i3DHexahedrons][iTotal]->setProperty( "text", QString::number( nbHexahedrons ) );
344     myWidgets[i3DHexahedrons][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Hexa] ) );
345     myWidgets[i3DHexahedrons][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Hexa] ) );
346     myWidgets[i3DPyramids][iTotal]->setProperty( "text", QString::number( nbPyramids ) );
347     myWidgets[i3DPyramids][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Pyramid] ) );
348     myWidgets[i3DPyramids][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Pyramid] ) );
349     myWidgets[i3DPrisms][iTotal]->setProperty( "text", QString::number( nbPrisms ) );
350     myWidgets[i3DPrisms][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Penta] ) );
351     myWidgets[i3DPrisms][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
352     myWidgets[i3DPolyhedrons][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
353   }
354 }
355
356 /*!
357   \brief Reset the widget to the initial state (nullify all fields).
358 */
359 void SMESHGUI_MeshInfo::clear()
360 {
361   myWidgets[iName][iSingle]->setProperty( "text", QString() );
362   myWidgets[iObject][iSingle]->setProperty( "text", QString() );
363   myWidgets[iNodes][iTotal]->setProperty( "text", QString::number( 0 ) );
364   myWidgets[i0D][iTotal]->setProperty( "text", QString::number( 0 ) );
365   myWidgets[i1D][iTotal]->setProperty( "text", QString::number( 0 ) );
366   myWidgets[i1D][iLinear]->setProperty( "text", QString::number( 0 ) );
367   myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( 0 ) );
368   myWidgets[i2D][iTotal]->setProperty( "text", QString::number( 0 ) );
369   myWidgets[i2D][iLinear]->setProperty( "text", QString::number( 0 ) );
370   myWidgets[i2D][iQuadratic]->setProperty( "text", QString::number( 0 ) );
371   myWidgets[i2DTriangles][iTotal]->setProperty( "text", QString::number( 0 ) );
372   myWidgets[i2DTriangles][iLinear]->setProperty( "text", QString::number( 0 ) );
373   myWidgets[i2DTriangles][iQuadratic]->setProperty( "text", QString::number( 0 ) );
374   myWidgets[i2DQuadrangles][iTotal]->setProperty( "text", QString::number( 0 ) );
375   myWidgets[i2DQuadrangles][iLinear]->setProperty( "text", QString::number( 0 ) );
376   myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", QString::number( 0 ) );
377   myWidgets[i2DPolygons][iTotal]->setProperty( "text", QString::number( 0 ) );
378   myWidgets[i3D][iTotal]->setProperty( "text", QString::number( 0 ) );
379   myWidgets[i3D][iLinear]->setProperty( "text", QString::number( 0 ) );
380   myWidgets[i3D][iQuadratic]->setProperty( "text", QString::number( 0 ) );
381   myWidgets[i3DTetrahedrons][iTotal]->setProperty( "text", QString::number( 0 ) );
382   myWidgets[i3DTetrahedrons][iLinear]->setProperty( "text", QString::number( 0 ) );
383   myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", QString::number( 0 ) );
384   myWidgets[i3DHexahedrons][iTotal]->setProperty( "text", QString::number( 0 ) );
385   myWidgets[i3DHexahedrons][iLinear]->setProperty( "text", QString::number( 0 ) );
386   myWidgets[i3DHexahedrons][iQuadratic]->setProperty( "text", QString::number( 0 ) );
387   myWidgets[i3DPyramids][iTotal]->setProperty( "text", QString::number( 0 ) );
388   myWidgets[i3DPyramids][iLinear]->setProperty( "text", QString::number( 0 ) );
389   myWidgets[i3DPyramids][iQuadratic]->setProperty( "text", QString::number( 0 ) );
390   myWidgets[i3DPrisms][iTotal]->setProperty( "text", QString::number( 0 ) );
391   myWidgets[i3DPrisms][iLinear]->setProperty( "text", QString::number( 0 ) );
392   myWidgets[i3DPrisms][iQuadratic]->setProperty( "text", QString::number( 0 ) );
393   myWidgets[i3DPolyhedrons][iTotal]->setProperty( "text", QString::number( 0 ) );
394 }
395
396 /*!
397   \brief Create info field
398   \return new info field
399 */
400 QLabel* SMESHGUI_MeshInfo::createField()
401 {
402   QLabel* lab = new QLabel( this );
403   lab->setFrameStyle( StyledPanel | Sunken );
404   lab->setAlignment( Qt::AlignCenter );
405   lab->setAutoFillBackground( true );
406   QPalette pal = lab->palette();
407   pal.setColor( QPalette::Window, QApplication::palette().color( QPalette::Active, QPalette::Base ) );
408   lab->setPalette( pal );
409   lab->setMinimumWidth( 70 );
410   return lab;
411 }
412
413 /*!
414   \brief Create horizontal rule.
415   \return new line object
416 */
417 QWidget* SMESHGUI_MeshInfo::createLine()
418 {
419   QFrame* line = new QFrame( this );
420   line->setFrameStyle( HLine | Sunken );
421   return line;
422 }
423
424 /*!
425   \brief Change widget font attributes (bold, italic, ...).
426   \param w widget
427   \param attr font attributes (XORed flags)
428   \param val value to be set to attributes
429 */
430 void SMESHGUI_MeshInfo::setFontAttributes( QWidget* w, int attr, bool val )
431 {
432   if ( w && attr ) {
433     QFont f = w->font();
434     if ( attr & Bold   ) f.setBold( val );
435     if ( attr & Italic ) f.setItalic( val );
436     w->setFont( f );
437   }
438 }
439
440 /*!
441   \brief Show/hide group(s) of fields.
442   \param start beginning of the block
443   \param end end of the block
444   \param on visibility flag
445 */
446 void SMESHGUI_MeshInfo::setFieldsVisible( int start, int end, bool on )
447 {
448   start = qMax( 0, start );
449   end   = qMin( end, (int)iElementsEnd );
450   for ( int i = start; i < end; i++ ) {
451     wlist wl = myWidgets[i];
452     foreach ( QWidget* w, wl ) w->setVisible( on );
453   }
454 }
455
456 /*!
457   \class SMESHGUI_ElemInfo
458   \brief Base class for the mesh element information widget.
459 */
460
461 /*!
462   \brief Constructor
463   \param parent parent widget
464 */
465 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent )
466 : QWidget( parent ), myActor( 0 ), myID( 0 ), myIsElement( -1 )
467 {
468 }
469
470 /*!
471   \brief Destructor
472 */
473 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
474 {
475 }
476
477 /*!
478   \brief Set mesh data source (actor)
479   \param actor mesh object actor
480 */
481 void SMESHGUI_ElemInfo::setSource( SMESH_Actor* actor )
482 {
483   if ( myActor != actor ) {
484     myActor = actor;
485     myID = 0;
486     myIsElement = -1;
487     clear();
488   }
489 }
490
491 /*!
492   \brief Show mesh element information
493   \param long id mesh node / element ID
494   \param isElem show mesh element information if \c true or mesh node information if \c false
495 */
496 void SMESHGUI_ElemInfo::showInfo( long id, bool isElem )
497 {
498   myID = id;
499   myIsElement = isElem;
500 }
501
502 /*!
503   \fn void SMESHGUI_ElemInfo::clear()
504   \brief Clear mesh element information widget
505 */
506
507 /*!
508   \brief Get node connectivity
509   \param node mesh node
510   \return node connectivity map
511 */
512 SMESHGUI_ElemInfo::Connectivity SMESHGUI_ElemInfo::nodeConnectivity( const SMDS_MeshNode* node )
513 {
514   Connectivity elmap;
515   if ( node ) {
516     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
517     while ( it && it->more() ) {
518       const SMDS_MeshElement* ne = it->next();
519       elmap[ ne->GetType() ] << ne->GetID();
520     }
521   }
522   return elmap;
523 }
524
525 /*!
526   \brief Format connectivity data to string representation
527   \param connectivity connetivity map
528   \param type element type
529   \return string representation of the connectivity
530 */
531 QString SMESHGUI_ElemInfo::formatConnectivity( Connectivity connectivity, int type )
532 {
533   QStringList str;
534   if ( connectivity.contains( type ) ) {
535     QList<int> elements = connectivity[ type ];
536     qSort( elements );
537     foreach( int id, elements )
538       str << QString::number( id );
539   }
540   return str.join( " " );
541 }
542
543 /*!
544   \brief Calculate gravity center of the mesh element
545   \param element mesh element
546 */
547 SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* element )
548 {
549   XYZ xyz;
550   if ( element ) {
551     SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
552     while ( nodeIt->more() ) {
553       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
554       xyz.add( node->X(), node->Y(), node->Z() );
555     }
556     xyz.divide( element->NbNodes() );
557   }
558   return xyz;
559 }
560
561 /*!
562   \class SMESHGUI_SimpleElemInfo
563   \brief Represents mesh element information in the simple text area.
564 */
565
566 /*!
567   \brief Constructor
568   \param parent parent widget
569 */
570 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
571 : SMESHGUI_ElemInfo( parent )
572 {
573   myInfo = new QTextBrowser( this );
574   QVBoxLayout* l = new QVBoxLayout( this );
575   l->setMargin( 0 );
576   l->addWidget( myInfo );
577 }
578
579 /*!
580   \brief Show mesh element information
581   \param long id mesh node / element ID
582   \param isElem show mesh element information if \c true or mesh node information if \c false
583 */
584 void SMESHGUI_SimpleElemInfo::showInfo( long id, bool isElem )
585 {
586   if ( myID == id && myIsElement == isElem ) return;
587
588   SMESHGUI_ElemInfo::showInfo( id, isElem );
589
590   clear();
591   
592   if ( myActor ) {
593     int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
594     if ( !isElem ) {
595       //
596       // show node info
597       //
598       const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindNode( id );
599       if ( !e ) return;
600       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
601       
602       // node ID
603       myInfo->append( QString( "<b>%1 #%2</b>" ).arg( tr( "NODE" ) ).arg( id ) );
604       // separator
605       myInfo->append( "" );
606       // coordinates
607       myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ).
608                       arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
609                       arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
610                       arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
611       // separator
612       myInfo->append( "" );
613       // connectivity
614       Connectivity connectivity = nodeConnectivity( node );
615       if ( !connectivity.isEmpty() ) {
616         myInfo->append( QString( "<b>%1:</b>" ).arg( tr( "CONNECTIVITY" ) ) );
617         QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
618         if ( !con.isEmpty() )
619           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "0D_ELEMENTS" ) ).arg( con ) );
620         con = formatConnectivity( connectivity, SMDSAbs_Edge );
621         if ( !con.isEmpty() )
622           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "EDGES" ) ).arg( con ) );
623         con = formatConnectivity( connectivity, SMDSAbs_Face );
624         if ( !con.isEmpty() )
625           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "FACES" ) ).arg( con ) );
626         con = formatConnectivity( connectivity, SMDSAbs_Volume );
627         if ( !con.isEmpty() )
628           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUMES" ) ).arg( con ) );
629       }
630       else {
631         myInfo->append( QString( "<b>%1</b>" ).arg( tr( "FREE_NODE" ) ).arg( id ) );
632       }
633     }
634     else {
635       //
636       // show element info
637       // 
638       const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindElement( id );
639       if ( !e ) return;
640
641       // element ID && type
642       QString stype;
643       switch( e->GetType() ) {
644       case SMDSAbs_0DElement:
645         stype = tr( "0D ELEMENT" ); break;
646       case SMDSAbs_Edge:
647         stype = tr( "EDGE" ); break;
648       case SMDSAbs_Face:
649         stype = tr( "FACE" ); break;
650       case SMDSAbs_Volume:
651         stype = tr( "VOLUME" ); break;
652       default: 
653         break;
654       }
655       if ( stype.isEmpty() ) return;
656       myInfo->append( QString( "<b>%1 #%2</b>" ).arg( stype ).arg( id ) );
657       // separator
658       myInfo->append( "" );
659       // geometry type
660       QString gtype;
661       switch( e->GetEntityType() ) {
662       case SMDSEntity_Triangle:
663       case SMDSEntity_Quad_Triangle:
664         gtype = tr( "TRIANGLE" ); break;
665       case SMDSEntity_Quadrangle:
666       case SMDSEntity_Quad_Quadrangle:
667         gtype = tr( "QUADRANGLE" ); break;
668       case SMDSEntity_Polygon:
669       case SMDSEntity_Quad_Polygon:
670         gtype = tr( "QUADRANGLE" ); break;
671       case SMDSEntity_Tetra:
672       case SMDSEntity_Quad_Tetra:
673         gtype = tr( "TETRAHEDRON" ); break;
674       case SMDSEntity_Pyramid:
675       case SMDSEntity_Quad_Pyramid:
676         gtype = tr( "PYRAMID" ); break;
677       case SMDSEntity_Hexa:
678       case SMDSEntity_Quad_Hexa:
679         gtype = tr( "HEXAHEDRON" ); break;
680       case SMDSEntity_Penta:
681       case SMDSEntity_Quad_Penta:
682         gtype = tr( "PRISM" ); break;
683       case SMDSEntity_Polyhedra:
684       case SMDSEntity_Quad_Polyhedra:
685         gtype = tr( "POLYHEDRON" ); break;
686       default: 
687         break;
688       }
689       if ( !gtype.isEmpty() )
690         myInfo->append( QString( "<b>%1:</b> %2" ).arg( tr( "TYPE" ) ).arg( gtype ) );
691       // quadratic flag and gravity center (any element except 0D)
692       if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) {
693         // quadratic flag
694         myInfo->append( QString( "<b>%1?</b> %2" ).arg( tr( "QUADRATIC" ) ).arg( e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) ) );
695         // separator
696         myInfo->append( "" );
697         // gravity center
698         XYZ gc = gravityCenter( e );
699         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( tr( "GRAVITY_CENTER" ) ).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ) );
700       }
701       // separator
702       myInfo->append( "" );
703       // connectivity
704       SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
705       for ( int idx = 1; nodeIt->more(); idx++ ) {
706         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
707         // node number and ID
708         myInfo->append( QString( "<b>%1 %2/%3</b> - #%4" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ) );
709         // node coordinates
710         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ).
711                         arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
712                         arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
713                         arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
714         // node connectivity
715         Connectivity connectivity = nodeConnectivity( node );
716         if ( !connectivity.isEmpty() ) {
717           myInfo->append( QString( "<b>%1:</b>" ).arg( tr( "CONNECTIVITY" ) ) );
718           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
719           if ( !con.isEmpty() )
720             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "0D_ELEMENTS" ) ).arg( con ) );
721           con = formatConnectivity( connectivity, SMDSAbs_Edge );
722           if ( !con.isEmpty() )
723             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "EDGES" ) ).arg( con ) );
724           con = formatConnectivity( connectivity, SMDSAbs_Face );
725           if ( !con.isEmpty() )
726             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "FACES" ) ).arg( con ) );
727           con = formatConnectivity( connectivity, SMDSAbs_Volume );
728           if ( !con.isEmpty() )
729             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUMES" ) ).arg( con ) );
730         }
731         else {
732           myInfo->append( QString( "<b>%1</b>" ).arg( tr( "FREE_NODE" ) ).arg( id ) );
733         }
734         // separator
735         myInfo->append( "" );
736       }
737     }
738   }
739 }
740
741 /*!
742   \brief Clear mesh element information widget
743 */
744 void SMESHGUI_SimpleElemInfo::clear()
745 {
746   myInfo->clear();
747 }
748
749 /*!
750   \class SMESHGUI_TreeElemInfo::ItemDelegate
751   \brief Item delegate for tree mesh info widget
752   \internal
753 */
754 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
755 {
756 public:
757   ItemDelegate( QObject* );
758   QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
759 };
760
761 /*!
762   \brief Constructor
763   \internal
764 */
765 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ) : QItemDelegate( parent )
766 {
767 }
768
769 /*!
770   \brief Create item editor widget
771   \internal
772 */
773 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
774 {
775   QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
776   if ( qobject_cast<QLineEdit*>( w ) ) qobject_cast<QLineEdit*>( w )->setReadOnly(  true );
777   return w;
778 }
779
780 /*!
781   \class SMESHGUI_TreeElemInfo
782   \brief Represents mesh element information in the tree-like form.
783 */
784
785 /*!
786   \brief Constructor
787   \param parent parent widget
788 */
789 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
790 : SMESHGUI_ElemInfo( parent )
791 {
792   myInfo = new QTreeWidget( this );
793   myInfo->setColumnCount( 2 );
794   myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
795   myInfo->header()->setStretchLastSection( true );
796   myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
797   myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
798   QVBoxLayout* l = new QVBoxLayout( this );
799   l->setMargin( 0 );
800   l->addWidget( myInfo );
801 }
802
803 /*!
804   \brief Show mesh element information
805   \param long id mesh node / element ID
806   \param isElem show mesh element information if \c true or mesh node information if \c false
807 */
808 void SMESHGUI_TreeElemInfo::showInfo( long id, bool isElem )
809 {
810   if ( myID == id && myIsElement == isElem ) return;
811
812   SMESHGUI_ElemInfo::showInfo( id, isElem );
813
814   clear();
815   
816   if ( myActor ) {
817     int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
818     if ( !isElem ) {
819       //
820       // show node info
821       //
822       const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindNode( id );
823       if ( !e ) return;
824       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
825       
826       // node ID
827       QTreeWidgetItem* nodeItem = createItem( 0, -1 );
828       nodeItem->setText( 0, tr( "NODE" ) );
829       nodeItem->setText( 1, QString( "#%1" ).arg( id ) );
830       nodeItem->setExpanded( true );
831       // coordinates
832       QTreeWidgetItem* coordItem = createItem( nodeItem, 0 );
833       coordItem->setText( 0, tr( "COORDINATES" ) );
834       coordItem->setExpanded( true );
835       QTreeWidgetItem* xItem = createItem( coordItem );
836       xItem->setText( 0, "X" );
837       xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
838       QTreeWidgetItem* yItem = createItem( coordItem );
839       yItem->setText( 0, "Y" );
840       yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
841       QTreeWidgetItem* zItem = createItem( coordItem );
842       zItem->setText( 0, "Z" );
843       zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
844       // connectivity
845       QTreeWidgetItem* conItem = createItem( nodeItem, 0 );
846       conItem->setText( 0, tr( "CONNECTIVITY" ) );
847       conItem->setExpanded( true );
848       Connectivity connectivity = nodeConnectivity( node );
849       if ( !connectivity.isEmpty() ) {
850         QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
851         if ( !con.isEmpty() ) {
852           QTreeWidgetItem* i = createItem( conItem );
853           i->setText( 0, tr( "0D_ELEMENTS" ) );
854           i->setText( 1, con );
855         }
856         con = formatConnectivity( connectivity, SMDSAbs_Edge );
857         if ( !con.isEmpty() ) {
858           QTreeWidgetItem* i = createItem( conItem );
859           i->setText( 0, tr( "EDGES" ) );
860           i->setText( 1, con );
861         }
862         con = formatConnectivity( connectivity, SMDSAbs_Face );
863         if ( !con.isEmpty() ) {
864           QTreeWidgetItem* i = createItem( conItem );
865           i->setText( 0, tr( "FACES" ) );
866           i->setText( 1, con );
867         }
868         con = formatConnectivity( connectivity, SMDSAbs_Volume );
869         if ( !con.isEmpty() ) {
870           QTreeWidgetItem* i = createItem( conItem );
871           i->setText( 0, tr( "VOLUMES" ) );
872           i->setText( 1, con );
873         }
874       }
875       else {
876         conItem->setText( 1, tr( "FREE_NODE" ) );
877       }
878     }
879     else {
880       //
881       // show element info
882       // 
883       const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindElement( id );
884       if ( !e ) return;
885
886       // element ID && type
887       QString stype;
888       switch( e->GetType() ) {
889       case SMDSAbs_0DElement:
890         stype = tr( "0D ELEMENT" ); break;
891       case SMDSAbs_Edge:
892         stype = tr( "EDGE" ); break;
893       case SMDSAbs_Face:
894         stype = tr( "FACE" ); break;
895       case SMDSAbs_Volume:
896         stype = tr( "VOLUME" ); break;
897       default: 
898         break;
899       }
900       if ( stype.isEmpty() ) return;
901       QTreeWidgetItem* elemItem = createItem( 0, -1 );
902       elemItem->setText( 0, stype );
903       elemItem->setText( 1, QString( "#%1" ).arg( id ) );
904       elemItem->setExpanded( true );
905       // geometry type
906       QString gtype;
907       switch( e->GetEntityType() ) {
908       case SMDSEntity_Triangle:
909       case SMDSEntity_Quad_Triangle:
910         gtype = tr( "TRIANGLE" ); break;
911       case SMDSEntity_Quadrangle:
912       case SMDSEntity_Quad_Quadrangle:
913         gtype = tr( "QUADRANGLE" ); break;
914       case SMDSEntity_Polygon:
915       case SMDSEntity_Quad_Polygon:
916         gtype = tr( "QUADRANGLE" ); break;
917       case SMDSEntity_Tetra:
918       case SMDSEntity_Quad_Tetra:
919         gtype = tr( "TETRAHEDRON" ); break;
920       case SMDSEntity_Pyramid:
921       case SMDSEntity_Quad_Pyramid:
922         gtype = tr( "PYRAMID" ); break;
923       case SMDSEntity_Hexa:
924       case SMDSEntity_Quad_Hexa:
925         gtype = tr( "HEXAHEDRON" ); break;
926       case SMDSEntity_Penta:
927       case SMDSEntity_Quad_Penta:
928         gtype = tr( "PRISM" ); break;
929       case SMDSEntity_Polyhedra:
930       case SMDSEntity_Quad_Polyhedra:
931         gtype = tr( "POLYHEDRON" ); break;
932       default: 
933         break;
934       }
935       if ( !gtype.isEmpty() ) {
936         QTreeWidgetItem* typeItem = createItem( elemItem, 0 );
937         typeItem->setText( 0, tr( "TYPE" ) );
938         typeItem->setText( 1, gtype );
939       }
940       // quadratic flag and gravity center (any element except 0D)
941       if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) {
942         // quadratic flag
943         QTreeWidgetItem* quadItem = createItem( elemItem, 0 );
944         quadItem->setText( 0, tr( "QUADRATIC" ) );
945         quadItem->setText( 1, e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) );
946         // gravity center
947         XYZ gc = gravityCenter( e );
948         QTreeWidgetItem* gcItem = createItem( elemItem, 0 );
949         gcItem->setText( 0, tr( "GRAVITY_CENTER" ) );
950         gcItem->setExpanded( true );
951         QTreeWidgetItem* xItem = createItem( gcItem );
952         xItem->setText( 0, "X" );
953         xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
954         QTreeWidgetItem* yItem = createItem( gcItem );
955         yItem->setText( 0, "Y" );
956         yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
957         QTreeWidgetItem* zItem = createItem( gcItem );
958         zItem->setText( 0, "Z" );
959         zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
960       }
961       // connectivity
962       QTreeWidgetItem* conItem = createItem( elemItem, 0 );
963       conItem->setText( 0, tr( "CONNECTIVITY" ) );
964       conItem->setExpanded( true );
965       SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
966       for ( int idx = 1; nodeIt->more(); idx++ ) {
967         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
968         // node number and ID
969         QTreeWidgetItem* nodeItem = createItem( conItem, 0 );
970         nodeItem->setText( 0, QString( "%1 %2/%3" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ) );
971         nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ) );
972         //nodeItem->setExpanded( true );
973         // node coordinates
974         QTreeWidgetItem* coordItem = createItem( nodeItem );
975         coordItem->setText( 0, tr( "COORDINATES" ) );
976         coordItem->setExpanded( true );
977         QTreeWidgetItem* xItem = createItem( coordItem );
978         xItem->setText( 0, "X" );
979         xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
980         QTreeWidgetItem* yItem = createItem( coordItem );
981         yItem->setText( 0, "Y" );
982         yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
983         QTreeWidgetItem* zItem = createItem( coordItem );
984         zItem->setText( 0, "Z" );
985         zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
986         // node connectivity
987         QTreeWidgetItem* nconItem = createItem( nodeItem );
988         nconItem->setText( 0, tr( "CONNECTIVITY" ) );
989         nconItem->setExpanded( true );
990         Connectivity connectivity = nodeConnectivity( node );
991         if ( !connectivity.isEmpty() ) {
992           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
993           if ( !con.isEmpty() ) {
994             QTreeWidgetItem* i = createItem( nconItem );
995             i->setText( 0, tr( "0D_ELEMENTS" ) );
996             i->setText( 1, con );
997           }
998           con = formatConnectivity( connectivity, SMDSAbs_Edge );
999           if ( !con.isEmpty() ) {
1000             QTreeWidgetItem* i = createItem( nconItem );
1001             i->setText( 0, tr( "EDGES" ) );
1002             i->setText( 1, con );
1003           }
1004           con = formatConnectivity( connectivity, SMDSAbs_Face );
1005           if ( !con.isEmpty() ) {
1006             QTreeWidgetItem* i = createItem( nconItem );
1007             i->setText( 0, tr( "FACES" ) );
1008             i->setText( 1, con );
1009           }
1010           con = formatConnectivity( connectivity, SMDSAbs_Volume );
1011           if ( !con.isEmpty() ) {
1012             QTreeWidgetItem* i = createItem( nconItem );
1013             i->setText( 0, tr( "VOLUMES" ) );
1014             i->setText( 1, con );
1015           }
1016         }
1017       }
1018     }
1019   }
1020 }
1021
1022 /*!
1023   \brief Clear mesh element information widget
1024 */
1025 void SMESHGUI_TreeElemInfo::clear()
1026 {
1027   myInfo->clear();
1028   myInfo->repaint();
1029 }
1030
1031 /*!
1032   \brief Create new tree item.
1033   \param parnt parent tree widget item
1034   \param column item column to be set bold, if it is -1, bold font will be set for all columns
1035   \return new tree widget item
1036 */
1037 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int column )
1038 {
1039   QTreeWidgetItem* item;
1040   if ( parent )
1041     item = new QTreeWidgetItem( parent );
1042   else
1043     item = new QTreeWidgetItem( myInfo );
1044
1045   item->setFlags( item->flags() | Qt::ItemIsEditable );
1046
1047   QFont f = item->font( 0 );
1048   f.setBold( true );
1049   if ( column >= 0 && column < myInfo->columnCount() ) {
1050     item->setFont( column, f );
1051   }
1052   else if ( column == -1 ) {
1053     for ( int i = 0; i < myInfo->columnCount(); i++ )
1054       item->setFont( i, f );
1055   }
1056   return item;
1057 }
1058
1059 /*!
1060   \class SMESHGUI_MeshInfoDlg
1061   \brief Mesh information dialog box
1062 */
1063
1064 /*!
1065   \brief Constructor
1066   \param parent parent widget
1067   \param page specifies the dialog page to be shown at the start-up
1068 */
1069 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
1070 : QDialog( parent ), myActor( 0 )
1071 {
1072   setModal( false );
1073   setAttribute( Qt::WA_DeleteOnClose, true );
1074   setWindowTitle( tr( "MESH_INFO" ) );
1075   setSizeGripEnabled( true );
1076
1077   myTabWidget = new QTabWidget( this );
1078
1079   // base info 
1080
1081   myBaseInfo = new SMESHGUI_MeshInfo( myTabWidget );
1082   myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
1083
1084   // elem info 
1085   
1086   QWidget* w = new QWidget( myTabWidget );
1087
1088   myMode = new QButtonGroup( this );
1089   myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
1090   myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
1091   myMode->button( NodeMode )->setChecked( true );
1092   myID = new QLineEdit( w );
1093   myID->setValidator( new SMESHGUI_IdValidator( this, 1 ) );
1094
1095   int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
1096   mode = qMin( 1, qMax( 0, mode ) );
1097   
1098   if ( mode == 0 ) 
1099     myElemInfo = new SMESHGUI_SimpleElemInfo( w );
1100   else
1101     myElemInfo = new SMESHGUI_TreeElemInfo( w );
1102
1103   QGridLayout* elemLayout = new QGridLayout( w );
1104   elemLayout->setMargin( MARGIN );
1105   elemLayout->setSpacing( SPACING );
1106   elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
1107   elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
1108   elemLayout->addWidget( myID, 0, 2 );
1109   elemLayout->addWidget( myElemInfo, 1, 0, 1, 3 );
1110   
1111   myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
1112
1113   QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
1114   okBtn->setAutoDefault( true );
1115   okBtn->setDefault( true );
1116   okBtn->setFocus();
1117   QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
1118   helpBtn->setAutoDefault( true );
1119
1120   QHBoxLayout* btnLayout = new QHBoxLayout;
1121   btnLayout->setSpacing( SPACING );
1122   btnLayout->setMargin( 0 );
1123
1124   btnLayout->addWidget( okBtn );
1125   btnLayout->addStretch( 10 );
1126   btnLayout->addWidget( helpBtn );
1127
1128   QVBoxLayout* l = new QVBoxLayout ( this );
1129   l->setMargin( MARGIN );
1130   l->setSpacing( SPACING );
1131   l->addWidget( myTabWidget );
1132   l->addStretch();
1133   l->addLayout( btnLayout );
1134
1135   myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
1136
1137   connect( okBtn,       SIGNAL( clicked() ),              this, SLOT( reject() ) );
1138   connect( helpBtn,     SIGNAL( clicked() ),              this, SLOT( help() ) );
1139   connect( myTabWidget, SIGNAL( currentChanged( int  ) ), this, SLOT( updateSelection() ) );
1140   connect( myMode,      SIGNAL( buttonClicked( int  ) ),  this, SLOT( modeChanged() ) );
1141   connect( myID,        SIGNAL( textEdited( QString  ) ), this, SLOT( idChanged() ) );
1142   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
1143   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalCloseAllDialogs() ),        this, SLOT( reject() ) );
1144
1145   updateSelection();
1146 }
1147
1148 /*!
1149   \brief Destructor
1150 */
1151 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
1152 {
1153 }
1154
1155 /*!
1156   \brief Show mesh information
1157   \param IO interactive object
1158 */
1159 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO )
1160 {
1161   SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
1162   if ( !CORBA::is_nil( obj ) ) {
1163     myBaseInfo->showInfo( obj );
1164     
1165     myActor = SMESH::FindActorByEntry( IO->getEntry() );
1166     SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
1167     QString ID;
1168     int nb = 0;
1169     if ( myActor && selector ) {
1170       nb = myMode->checkedId() == NodeMode ? 
1171         SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
1172         SMESH::GetNameOfSelectedNodes( selector, IO, ID );
1173     }
1174     if ( nb == 1 ) {
1175       myID->setText( ID.trimmed() );
1176       myElemInfo->setSource( myActor ) ;
1177       myElemInfo->showInfo( ID.toLong(), myMode->checkedId() == ElemMode );
1178     }
1179     else {
1180       myID->clear();
1181       myElemInfo->clear();
1182     }
1183   }
1184 }
1185
1186 /*!
1187   \brief Perform clean-up actions on the dialog box closing.
1188 */
1189 void SMESHGUI_MeshInfoDlg::reject()
1190 {
1191   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
1192   selMgr->clearFilters();
1193   SMESH::SetPointRepresentation( false );
1194   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1195     aViewWindow->SetSelectionMode( ActorSelection );
1196   QDialog::reject();
1197 }
1198
1199 /*!
1200   \brief Process keyboard event
1201   \param e key press event
1202 */
1203 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
1204 {
1205   QDialog::keyPressEvent( e );
1206   if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
1207     e->accept();
1208     help();
1209   }
1210 }
1211
1212 /*!
1213   \brief Reactivate dialog box, when mouse pointer goes into it.
1214 */
1215 void SMESHGUI_MeshInfoDlg::enterEvent( QEvent* )
1216 {
1217   activate();
1218 }
1219
1220 /*!
1221   \brief Setup selection mode depending on the current dialog box state.
1222 */
1223 void SMESHGUI_MeshInfoDlg::updateSelection()
1224 {
1225   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
1226
1227   disconnect( selMgr, 0, this, 0 );
1228   selMgr->clearFilters();
1229
1230   if ( myTabWidget->currentIndex() == BaseInfo ) {
1231     SMESH::SetPointRepresentation( false );
1232     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1233       aViewWindow->SetSelectionMode( ActorSelection );
1234   }
1235   else {
1236     if ( myMode->checkedId() == NodeMode ) {
1237       SMESH::SetPointRepresentation( true );
1238       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1239         aViewWindow->SetSelectionMode( NodeSelection );
1240     }
1241     else {
1242       SMESH::SetPointRepresentation( false );
1243       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1244         aViewWindow->SetSelectionMode( CellSelection );
1245     }
1246   }
1247
1248   int oldID = myID->text().toLong();
1249   SMESH_Actor* oldActor = myActor;
1250   myID->clear();
1251   
1252   connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
1253   updateInfo();
1254   
1255   if ( oldActor == myActor && myActor && oldID ) {
1256     myID->setText( QString::number( oldID ) );
1257     idChanged();
1258   }
1259 }
1260
1261 /*!
1262   \brief Show help page
1263 */
1264 void SMESHGUI_MeshInfoDlg::help()
1265 {
1266   SMESH::ShowHelpFile( myTabWidget->currentIndex() == BaseInfo ?
1267                        "mesh_infos_page.html#advanced_mesh_infos_anchor" : 
1268                        "mesh_infos_page.html#mesh_element_info_anchor" );
1269 }
1270
1271 /*!
1272   \brief Show mesh information
1273 */
1274 void SMESHGUI_MeshInfoDlg::updateInfo()
1275 {
1276   SUIT_OverrideCursor wc;
1277
1278   SALOME_ListIO selected;
1279   SMESHGUI::selectionMgr()->selectedObjects( selected );
1280
1281   if ( selected.Extent() == 1 ) {
1282     Handle(SALOME_InteractiveObject) IO = selected.First();
1283     showInfo( IO );
1284   }
1285 //   else {
1286 //     myBaseInfo->clear();
1287 //     myElemInfo->clear();
1288 //   }
1289 }
1290
1291 /*!
1292   \brief Activate dialog box
1293 */
1294 void SMESHGUI_MeshInfoDlg::activate()
1295 {
1296   SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
1297   SMESHGUI::GetSMESHGUI()->SetActiveDialogBox( this );
1298   myTabWidget->setEnabled( true );
1299   updateSelection();
1300 }
1301
1302 /*!
1303   \brief Deactivate dialog box
1304 */
1305 void SMESHGUI_MeshInfoDlg::deactivate()
1306 {
1307   myTabWidget->setEnabled( false );
1308   disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
1309 }
1310
1311 /*!
1312   \brief Called when users switches between node / element modes.
1313 */
1314 void SMESHGUI_MeshInfoDlg::modeChanged()
1315 {
1316   myID->clear();
1317   updateSelection();
1318 }
1319
1320 /*!
1321   \brief Caled when users prints mesh element ID in the corresponding field.
1322 */
1323 void SMESHGUI_MeshInfoDlg::idChanged()
1324 {
1325   SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
1326   if ( myActor && selector ) {
1327     Handle(SALOME_InteractiveObject) IO = myActor->getIO();
1328     TColStd_MapOfInteger ID;
1329     ID.Add( myID->text().toLong() );
1330     selector->AddOrRemoveIndex( IO, ID, false );
1331     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
1332       aViewWindow->highlight( IO, true, true );
1333     myElemInfo->showInfo( myID->text().toLong(), myMode->checkedId() == ElemMode );
1334   }
1335 }