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