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