Salome HOME
0022523: [CEA 1096] Add a colomn "biquadratic" in "Mesh Information"
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshInfo.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 "SMDSAbs_ElementType.hxx"
28 #include "SMDS_BallElement.hxx"
29 #include "SMDS_EdgePosition.hxx"
30 #include "SMDS_FacePosition.hxx"
31 #include "SMDS_Mesh.hxx"
32 #include "SMESHDS_Mesh.hxx"
33 #include "SMESHGUI.h"
34 #include "SMESHGUI_FilterUtils.h"
35 #include "SMESHGUI_IdValidator.h"
36 #include "SMESHGUI_SpinBox.h"
37 #include "SMESHGUI_Utils.h"
38 #include "SMESHGUI_VTKUtils.h"
39 #include "SMESH_Actor.h"
40
41 #include <LightApp_SelectionMgr.h>
42 #include <SUIT_FileDlg.h>
43 #include <SUIT_OverrideCursor.h>
44 #include <SUIT_ResourceMgr.h>
45 #include <SUIT_Session.h>
46 #include <SVTK_ViewWindow.h>
47
48 #include <SALOMEDSClient_Study.hxx>
49 #include <SalomeApp_Study.h>
50
51 #include <QApplication>
52 #include <QButtonGroup>
53 #include <QCheckBox>
54 #include <QContextMenuEvent>
55 #include <QGridLayout>
56 #include <QHBoxLayout>
57 #include <QHeaderView>
58 #include <QItemDelegate>
59 #include <QKeyEvent>
60 #include <QLabel>
61 #include <QLineEdit>
62 #include <QMenu>
63 #include <QPushButton>
64 #include <QToolButton>
65 #include <QRadioButton>
66 #include <QTextStream>
67 #include <QTabWidget>
68 #include <QTextBrowser>
69 #include <QVBoxLayout>
70
71 #include "utilities.h"
72
73 #include <SALOMEconfig.h>
74 #include CORBA_SERVER_HEADER(GEOM_Gen)
75
76 namespace {
77
78 const int SPACING      = 6;
79 const int MARGIN       = 9;
80 const int MAXITEMS     = 10;
81 const int GROUPS_ID    = 100;
82 const int SUBMESHES_ID = 200;
83 const int SPACING_INFO = 2;
84
85 enum InfoRole {
86   TypeRole = Qt::UserRole + 10,
87   IdRole,
88 };
89
90 enum InfoType {
91   NodeConnectivity = 100,
92   ElemConnectivity,
93 };
94 } // namesapce
95
96 /*!
97   \class ExtraWidget
98   \internal
99 */
100 class ExtraWidget : public QWidget
101 {
102 public:
103   ExtraWidget( QWidget*, bool = false );
104   ~ExtraWidget();
105
106   void updateControls( int, int, int = MAXITEMS );
107
108 public:
109   QLabel*      current;
110   QPushButton* prev;
111   QPushButton* next;
112   bool         brief;
113 };
114
115 ExtraWidget::ExtraWidget( QWidget* parent, bool b ) : QWidget( parent ), brief( b )
116 {
117   current = new QLabel( this );
118   current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
119   prev = new QPushButton( tr( "<<" ), this );
120   next = new QPushButton( tr( ">>" ), this );
121   QHBoxLayout* hbl = new QHBoxLayout( this );
122   hbl->setContentsMargins( 0, SPACING, 0, 0 );
123   hbl->setSpacing( SPACING );
124   hbl->addStretch();
125   hbl->addWidget( current );
126   hbl->addWidget( prev );
127   hbl->addWidget( next );
128 }
129
130 ExtraWidget::~ExtraWidget()
131 {
132 }
133
134 void ExtraWidget::updateControls( int total, int index, int blockSize )
135 {
136   setVisible( total > blockSize );
137   QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
138   current->setText( format.arg( index*blockSize+1 ).arg( qMin( index*blockSize+blockSize, total ) ).arg( total ) );
139   prev->setEnabled( index > 0 );
140   next->setEnabled( (index+1)*blockSize < total );
141 }
142
143 /*!
144   \class DumpFileDlg
145   \brief Customization of standard "Save file" dialog box for dump info operation
146   \internal
147 */
148
149 class DumpFileDlg : public SUIT_FileDlg
150 {
151 public:
152   DumpFileDlg( QWidget* parent );
153
154   QCheckBox* myBaseChk;
155   QCheckBox* myElemChk;
156   QCheckBox* myAddChk;
157   QCheckBox* myCtrlChk;
158 };
159
160 /*!
161   \brief Constructor
162   \internal
163 */
164 DumpFileDlg::DumpFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
165 {
166   QGridLayout* grid = ::qobject_cast<QGridLayout *>( layout() );
167   if ( grid ) {
168     QWidget* hB = new QWidget( this );
169     myBaseChk = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_BASE_INFO" ), hB );
170     myElemChk = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ELEM_INFO" ), hB );
171     myAddChk  = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ADD_INFO" ),  hB );
172     myCtrlChk = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_CTRL_INFO" ), hB );
173
174     QGridLayout* layout = new QGridLayout( hB );
175     layout->addWidget( myBaseChk, 0, 0 );
176     layout->addWidget( myElemChk, 0, 1 );
177     layout->addWidget( myAddChk, 1, 0 );
178     layout->addWidget( myCtrlChk, 1, 1 );
179
180     QPushButton* pb = new QPushButton( this );
181
182     int row = grid->rowCount();
183     grid->addWidget( new QLabel( "", this ), row, 0 );
184     grid->addWidget( hB, row, 1, 1, 3 );
185     grid->addWidget( pb, row, 5 );
186
187     pb->hide();
188   }
189 }
190
191 /*!
192   \brief Get depth of the tree item
193   \internal
194   \param theItem tree widget item
195   \return item's depth in tree widget (where top-level items have zero depth)
196 */
197 static int itemDepth( QTreeWidgetItem* item )
198 {
199   int d = 0;
200   QTreeWidgetItem* p = item->parent();
201   while ( p ) {
202     d++;
203     p = p->parent();
204   }
205   return d;
206 }
207
208 /*!
209   \class SMESHGUI_MeshInfo
210   \brief Base mesh information widget
211   
212   Displays the base information about mesh object: mesh, sub-mesh, group or arbitrary ID source.
213 */
214
215 /*!
216   \brief Constructor.
217   \param parent parent widget
218 */
219 SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
220   : QFrame( parent ), myWidgets( iElementsEnd )
221 {
222   setFrameStyle( StyledPanel | Sunken );
223
224   QGridLayout* l = new QGridLayout( this );
225   l->setMargin( MARGIN );
226   l->setSpacing( SPACING );
227
228   int index = 0;
229
230   // object
231   QLabel* aNameLab     = new QLabel( tr( "NAME_LAB" ), this );
232   QLabel* aName        = createField();
233   aName->setMinimumWidth( 150 );
234   QLabel* aObjLab      = new QLabel( tr( "OBJECT_LAB" ), this );
235   QLabel* aObj         = createField();
236   aObj->setMinimumWidth( 150 );
237   myWidgets[ index++ ] << aNameLab << aName;
238   myWidgets[ index++ ] << aObjLab  << aObj;
239
240   // nodes
241   QWidget* aNodesLine  = createLine();
242   QLabel*  aNodesLab   = new QLabel( tr( "NODES_LAB" ), this );
243   QLabel*  aNodes      = createField();
244   myWidgets[ index++ ] << aNodesLine;
245   myWidgets[ index++ ] << aNodesLab << aNodes;
246
247   // elements
248   QWidget* aElemLine   = createLine();
249   QLabel*  aElemLab    = new QLabel( tr( "ELEMENTS_LAB" ),     this );
250   QLabel*  aElemTotal  = new QLabel( tr( "TOTAL_LAB" ),        this );
251   QLabel*  aElemLin    = new QLabel( tr( "LINEAR_LAB" ),       this );
252   QLabel*  aElemQuad   = new QLabel( tr( "QUADRATIC_LAB" ),    this );
253   QLabel*  aElemBiQuad = new QLabel( tr( "BI_QUADRATIC_LAB" ), this );
254   myWidgets[ index++ ] << aElemLine;
255   myWidgets[ index++ ] << aElemLab << aElemTotal << aElemLin << aElemQuad << aElemBiQuad;
256
257   // ... Number elements
258   QWidget* aNbLine     = createLine(); 
259   QLabel*  aNbTotal    = createField();
260   QLabel*  aNbLin      = createField();
261   QLabel*  aNbQuad     = createField();
262   QLabel*  aNbBiQuad   = createField();
263   myWidgets[ index++ ] << aNbLine;
264   myWidgets[ index++ ] << new QLabel( "", this ) << aNbTotal << aNbLin << aNbQuad << aNbBiQuad;
265
266   // ... 0D elements
267   QWidget* a0DLine     = createLine();
268   QLabel*  a0DLab      = new QLabel( tr( "0D_LAB" ), this );
269   QLabel*  a0DTotal    = createField();
270   myWidgets[ index++ ] << a0DLine;
271   myWidgets[ index++ ] << a0DLab << a0DTotal;
272
273   // ... Ball elements
274   QWidget* aBallLine     = createLine();
275   QLabel*  aBallLab      = new QLabel( tr( "BALL_LAB" ), this );
276   QLabel*  aBallTotal    = createField();
277   myWidgets[ index++ ] << aBallLine;
278   myWidgets[ index++ ] << aBallLab << aBallTotal;
279
280   // ... 1D elements
281   QWidget* a1DLine     = createLine();
282   QLabel*  a1DLab      = new QLabel( tr( "1D_LAB" ), this );
283   QLabel*  a1DTotal    = createField();
284   QLabel*  a1DLin      = createField();
285   QLabel*  a1DQuad     = createField();
286   myWidgets[ index++ ] << a1DLine;
287   myWidgets[ index++ ] << a1DLab << a1DTotal << a1DLin << a1DQuad;
288
289   // ... 2D elements
290   QWidget* a2DLine      = createLine();
291   QLabel*  a2DLab       = new QLabel( tr( "2D_LAB" ), this );
292   QLabel*  a2DTotal     = createField();
293   QLabel*  a2DLin       = createField();
294   QLabel*  a2DQuad      = createField();
295   QLabel*  a2DBiQuad    = createField();
296   QLabel*  a2DTriLab    = new QLabel( tr( "TRIANGLES_LAB" ), this );
297   QLabel*  a2DTriTotal  = createField();
298   QLabel*  a2DTriLin    = createField();
299   QLabel*  a2DTriQuad   = createField();
300   QLabel*  a2DTriBiQuad = createField();
301   QLabel*  a2DQuaLab    = new QLabel( tr( "QUADRANGLES_LAB" ), this );
302   QLabel*  a2DQuaTotal  = createField();
303   QLabel*  a2DQuaLin    = createField();
304   QLabel*  a2DQuaQuad   = createField();
305   QLabel*  a2DQuaBiQuad = createField();
306   QLabel*  a2DPolLab    = new QLabel( tr( "POLYGONS_LAB" ), this );
307   QLabel*  a2DPolTotal  = createField();
308   myWidgets[ index++ ] << a2DLine;
309   myWidgets[ index++ ] << a2DLab    << a2DTotal    << a2DLin    << a2DQuad    << a2DBiQuad;
310   myWidgets[ index++ ] << a2DTriLab << a2DTriTotal << a2DTriLin << a2DTriQuad << a2DTriBiQuad;
311   myWidgets[ index++ ] << a2DQuaLab << a2DQuaTotal << a2DQuaLin << a2DQuaQuad << a2DQuaBiQuad;
312   myWidgets[ index++ ] << a2DPolLab << a2DPolTotal;
313
314   // ... 3D elements
315   QWidget* a3DLine      = createLine();
316   QLabel*  a3DLab       = new QLabel( tr( "3D_LAB" ), this );
317   QLabel*  a3DTotal     = createField();
318   QLabel*  a3DLin       = createField();
319   QLabel*  a3DQuad      = createField();
320   QLabel*  a3DBiQuad    = createField();
321   QLabel*  a3DTetLab    = new QLabel( tr( "TETRAHEDRONS_LAB" ), this );
322   QLabel*  a3DTetTotal  = createField();
323   QLabel*  a3DTetLin    = createField();
324   QLabel*  a3DTetQuad   = createField();
325   QLabel*  a3DHexLab    = new QLabel( tr( "HEXAHEDONRS_LAB" ), this );
326   QLabel*  a3DHexTotal  = createField();
327   QLabel*  a3DHexLin    = createField();
328   QLabel*  a3DHexQuad   = createField();
329   QLabel*  a3DHexBiQuad = createField();
330   QLabel*  a3DPyrLab    = new QLabel( tr( "PYRAMIDS_LAB" ), this );
331   QLabel*  a3DPyrTotal  = createField();
332   QLabel*  a3DPyrLin    = createField();
333   QLabel*  a3DPyrQuad   = createField();
334   QLabel*  a3DPriLab    = new QLabel( tr( "PRISMS_LAB" ), this );
335   QLabel*  a3DPriTotal  = createField();
336   QLabel*  a3DPriLin    = createField();
337   QLabel*  a3DPriQuad   = createField();
338   QLabel*  a3DHexPriLab   = new QLabel( tr( "HEX_PRISMS_LAB" ), this );
339   QLabel*  a3DHexPriTotal = createField();
340   QLabel*  a3DPolLab    = new QLabel( tr( "POLYHEDRONS_LAB" ), this );
341   QLabel*  a3DPolTotal  = createField();
342   myWidgets[ index++ ] << a3DLine;
343   myWidgets[ index++ ] << a3DLab    << a3DTotal    << a3DLin    << a3DQuad    << a3DBiQuad;
344   myWidgets[ index++ ] << a3DTetLab << a3DTetTotal << a3DTetLin << a3DTetQuad;
345   myWidgets[ index++ ] << a3DHexLab << a3DHexTotal << a3DHexLin << a3DHexQuad << a3DHexBiQuad;
346   myWidgets[ index++ ] << a3DPyrLab << a3DPyrTotal << a3DPyrLin << a3DPyrQuad;
347   myWidgets[ index++ ] << a3DPriLab << a3DPriTotal << a3DPriLin << a3DPriQuad;
348   myWidgets[ index++ ] << a3DHexPriLab << a3DHexPriTotal;
349   myWidgets[ index++ ] << a3DPolLab << a3DPolTotal;
350
351   myLoadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
352   myLoadBtn->setAutoDefault( true );
353   connect( myLoadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
354   
355   setFontAttributes( aNameLab,    Bold );
356   setFontAttributes( aObjLab,     Bold );
357   setFontAttributes( aNodesLab,   Bold );
358   setFontAttributes( aElemLab,    Bold );
359   setFontAttributes( aElemTotal,  Italic );
360   setFontAttributes( aElemLin,    Italic );
361   setFontAttributes( aElemQuad,   Italic );
362   setFontAttributes( aElemBiQuad, Italic );
363   setFontAttributes( a0DLab,      Bold );
364   setFontAttributes( aBallLab,    Bold );
365   setFontAttributes( a1DLab,      Bold );
366   setFontAttributes( a2DLab,      Bold );
367   setFontAttributes( a3DLab,      Bold );
368
369   l->addWidget( aNameLab,     0, 0 );
370   l->addWidget( aName,        0, 1, 1, 4 );
371   l->addWidget( aObjLab,      1, 0 );
372   l->addWidget( aObj,         1, 1, 1, 4 );
373   l->addWidget( aNodesLine,   2, 0, 1, 5 );
374   l->addWidget( aNodesLab,    3, 0 );
375   l->addWidget( aNodes,       3, 1 );
376   l->addWidget( aElemLine,    4, 0, 1, 5 );
377   l->addWidget( aElemLab,     5, 0 );
378   l->addWidget( aElemTotal,   5, 1 );
379   l->addWidget( aElemLin,     5, 2 );
380   l->addWidget( aElemQuad,    5, 3 );
381   l->addWidget( aElemBiQuad,  5, 4 );
382   l->addWidget( aNbLine,      6, 1, 1, 4 );
383   l->addWidget( aNbTotal,     7, 1 );
384   l->addWidget( aNbLin,       7, 2 );
385   l->addWidget( aNbQuad,      7, 3 );
386   l->addWidget( aNbBiQuad,    7, 4 );
387   l->addWidget( a0DLine,      8, 1, 1, 4 );
388   l->addWidget( a0DLab,       9, 0 );
389   l->addWidget( a0DTotal,     9, 1 );
390   l->addWidget( aBallLine,    10, 1, 1, 4 );
391   l->addWidget( aBallLab,     11, 0 );
392   l->addWidget( aBallTotal,   11, 1 );
393   l->addWidget( a1DLine,      12, 1, 1, 4 );
394   l->addWidget( a1DLab,       13, 0 );
395   l->addWidget( a1DTotal,     13, 1 );
396   l->addWidget( a1DLin,       13, 2 );
397   l->addWidget( a1DQuad,      13, 3 );
398   l->addWidget( a2DLine,      14, 1, 1, 4 );
399   l->addWidget( a2DLab,       15, 0 );
400   l->addWidget( a2DTotal,     15, 1 );
401   l->addWidget( a2DLin,       15, 2 );
402   l->addWidget( a2DQuad,      15, 3 );
403   l->addWidget( a2DBiQuad,    15, 4 );
404   l->addWidget( a2DTriLab,    16, 0 );
405   l->addWidget( a2DTriTotal,  16, 1 );
406   l->addWidget( a2DTriLin,    16, 2 );
407   l->addWidget( a2DTriQuad,   16, 3 );
408   l->addWidget( a2DTriBiQuad, 16, 4 );
409   l->addWidget( a2DQuaLab,    17, 0 );
410   l->addWidget( a2DQuaTotal,  17, 1 );
411   l->addWidget( a2DQuaLin,    17, 2 );
412   l->addWidget( a2DQuaQuad,   17, 3 );
413   l->addWidget( a2DQuaBiQuad, 17, 4 );
414   l->addWidget( a2DPolLab,    18, 0 );
415   l->addWidget( a2DPolTotal,  18, 1 );
416   l->addWidget( a3DLine,      19, 1, 1, 4 );
417   l->addWidget( a3DLab,       20, 0 );
418   l->addWidget( a3DTotal,     20, 1 );
419   l->addWidget( a3DLin,       20, 2 );
420   l->addWidget( a3DQuad,      20, 3 );
421   l->addWidget( a3DBiQuad,    20, 4 );
422   l->addWidget( a3DTetLab,    21, 0 );
423   l->addWidget( a3DTetTotal,  21, 1 );
424   l->addWidget( a3DTetLin,    21, 2 );
425   l->addWidget( a3DTetQuad,   21, 3 );
426   l->addWidget( a3DHexLab,    22, 0 );
427   l->addWidget( a3DHexTotal,  22, 1 );
428   l->addWidget( a3DHexLin,    22, 2 );
429   l->addWidget( a3DHexQuad,   22, 3 );
430   l->addWidget( a3DHexBiQuad, 22, 4 );
431   l->addWidget( a3DPyrLab,    23, 0 );
432   l->addWidget( a3DPyrTotal,  23, 1 );
433   l->addWidget( a3DPyrLin,    23, 2 );
434   l->addWidget( a3DPyrQuad,   23, 3 );
435   l->addWidget( a3DPriLab,    24, 0 );
436   l->addWidget( a3DPriTotal,  24, 1 );
437   l->addWidget( a3DPriLin,    24, 2 );
438   l->addWidget( a3DPriQuad,   24, 3 );
439   l->addWidget( a3DHexPriLab,   25, 0 );
440   l->addWidget( a3DHexPriTotal, 25, 1 );
441   l->addWidget( a3DPolLab,    26, 0 );
442   l->addWidget( a3DPolTotal,  26, 1 );
443   l->addWidget( myLoadBtn,    28, 1, 1, 4 );
444
445   l->setColumnStretch( 0, 0 );
446   l->setColumnStretch( 1, 5 );
447   l->setColumnStretch( 2, 5 );
448   l->setColumnStretch( 3, 5 );
449   l->setColumnStretch( 4, 5 );
450   l->setRowStretch( 27, 5 );
451
452   clear();
453 }
454
455 /*!
456   \brief Destructor
457 */
458 SMESHGUI_MeshInfo::~SMESHGUI_MeshInfo()
459 {
460 }
461
462 /*!
463   \brief Show information on the mesh object.
464   \param obj object being processed (mesh, sub-mesh, group, ID source)
465 */
466 void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
467 {
468   clear();
469   if ( !CORBA::is_nil( obj ) ) {
470     _PTR(SObject) sobj = SMESH::ObjectToSObject( obj );
471     if ( sobj ) 
472       myWidgets[iName][iSingle]->setProperty( "text", sobj->GetName().c_str() );
473     SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
474     SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
475     SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
476     if ( !aMesh->_is_nil() ) {
477       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_MESH" ) );
478     }
479     else if ( !aSubMesh->_is_nil() ) {
480       myWidgets[iObject][iSingle]->setProperty( "text", tr( "OBJECT_SUBMESH" ) );
481     }
482     else if ( !aGroup->_is_nil() ) {
483       QString objType;
484       switch( aGroup->GetType() ) {
485       case SMESH::NODE:  objType = tr( "OBJECT_GROUP_NODES"   );break;
486       case SMESH::EDGE:  objType = tr( "OBJECT_GROUP_EDGES"   );break;
487       case SMESH::FACE:  objType = tr( "OBJECT_GROUP_FACES"   );break;
488       case SMESH::VOLUME:objType = tr( "OBJECT_GROUP_VOLUMES" );break;
489       case SMESH::ELEM0D:objType = tr( "OBJECT_GROUP_0DELEMS" );break;
490       case SMESH::BALL:  objType = tr( "OBJECT_GROUP_BALLS"   );break;
491       default:           objType = tr( "OBJECT_GROUP"         );break;
492       }
493       myWidgets[iObject][iSingle]->setProperty( "text", objType );
494     }
495     SMESH::long_array_var info = obj->GetMeshInfo();
496     myWidgets[iNodes][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Node] ) );
497     myWidgets[i0D][iTotal]    ->setProperty( "text", QString::number( info[SMDSEntity_0D] ) );
498     myWidgets[iBalls][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Ball] ) );
499     long nbEdges = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
500     myWidgets[i1D][iTotal]    ->setProperty( "text", QString::number( nbEdges ) );
501     myWidgets[i1D][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Edge] ) );
502     myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Edge] ) );
503     long nbTriangles     = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_BiQuad_Triangle];
504     long nbQuadrangles   = info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
505     long nb2DLinear      = info[SMDSEntity_Triangle]        + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
506     long nb2DQuadratic   = info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_Quad_Quadrangle];
507     long nb2DBiQuadratic = info[SMDSEntity_BiQuad_Triangle] + info[SMDSEntity_BiQuad_Quadrangle];
508
509     myWidgets[i2D][iTotal]                  ->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ));
510     myWidgets[i2D][iLinear]                 ->setProperty( "text", QString::number( nb2DLinear ) );
511     myWidgets[i2D][iQuadratic]              ->setProperty( "text", QString::number( nb2DQuadratic ) );
512     myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", QString::number( nb2DBiQuadratic ) );
513     myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", QString::number( nbTriangles ) );
514     myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", QString::number( info[SMDSEntity_Triangle] ) );
515     myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Triangle] ) );
516     myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_BiQuad_Triangle] ) );
517     myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", QString::number( nbQuadrangles ) );
518     myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
519     myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Quadrangle] ) );
520     myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_BiQuad_Quadrangle] ) );
521     myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
522     long nbTetrahedrons  = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra];
523     long nbHexahedrons   = info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa];
524     long nbPyramids      = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
525     long nbPrisms        = info[SMDSEntity_Penta]   + info[SMDSEntity_Quad_Penta];
526     long nb3DLinear      = info[SMDSEntity_Tetra]      + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra] + info[SMDSEntity_Hexagonal_Prism];
527     long nb3DQuadratic   = info[SMDSEntity_Quad_Tetra] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_Quad_Pyramid] + info[SMDSEntity_Quad_Penta];
528     long nb3DBiQuadratic = info[SMDSEntity_TriQuad_Hexa];
529     myWidgets[i3D][iTotal]                  ->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
530     myWidgets[i3D][iLinear]                 ->setProperty( "text", QString::number( nb3DLinear ) );
531     myWidgets[i3D][iQuadratic]              ->setProperty( "text", QString::number( nb3DQuadratic ) );
532     myWidgets[i3D][iBiQuadratic]            ->setProperty( "text", QString::number( nb3DBiQuadratic ) );
533     myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", QString::number( nbTetrahedrons ) );
534     myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", QString::number( info[SMDSEntity_Tetra] ) );
535     myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Tetra] ) );
536     myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", QString::number( nbHexahedrons ) );
537     myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", QString::number( info[SMDSEntity_Hexa] ) );
538     myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Hexa] ) );
539     myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_TriQuad_Hexa] ) );
540     myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", QString::number( nbPyramids ) );
541     myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", QString::number( info[SMDSEntity_Pyramid] ) );
542     myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Pyramid] ) );
543     myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", QString::number( nbPrisms ) );
544     myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", QString::number( info[SMDSEntity_Penta] ) );
545     myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
546     myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", QString::number( info[SMDSEntity_Hexagonal_Prism] ) );
547     myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
548     long nbElemTotal       = info[SMDSEntity_0D] + info[SMDSEntity_Ball] + nbEdges + nb2DLinear + nb2DQuadratic + nb2DBiQuadratic + nb3DLinear + nb3DQuadratic + nb3DBiQuadratic;
549     long nbElemLinerial    = info[SMDSEntity_Edge] + nb2DLinear + nb3DLinear;
550     long nbElemQuadratic   = info[SMDSEntity_Quad_Edge] + nb2DQuadratic + nb3DQuadratic;
551     long nbElemBiQuadratic = nb2DBiQuadratic + nb3DBiQuadratic;
552     myWidgets[iNb][iTotal]      ->setProperty( "text", QString::number( nbElemTotal ) );
553     myWidgets[iNb][iLinear]     ->setProperty( "text", QString::number( nbElemLinerial ) );
554     myWidgets[iNb][iQuadratic]  ->setProperty( "text", QString::number( nbElemQuadratic ) );
555     myWidgets[iNb][iBiQuadratic]->setProperty( "text", QString::number( nbElemBiQuadratic ) );
556     // before full loading from study file, type of elements in a sub-mesh can't be defined
557     // in some cases
558     bool infoOK = obj->IsMeshInfoCorrect();
559     myLoadBtn->setVisible( !infoOK );
560     if ( !infoOK )
561     {
562       // two options:
563       // 1. Type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
564       // 2. No info at all (for a group on geom or filter)
565       bool hasAnyInfo = false;
566       for ( size_t i = 0; i < info->length() && !hasAnyInfo; ++i )
567         hasAnyInfo = info[i];
568       if ( hasAnyInfo ) // believe it is a sub-mesh
569       {
570         if ( nb2DLinear + nb2DQuadratic + nb2DBiQuadratic > 0 )
571         {
572           myWidgets[i2D][iLinear]                 ->setProperty( "text", "?" );
573           myWidgets[i2D][iQuadratic]              ->setProperty( "text", "?" );
574           myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", "?" );
575           myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", "?" );
576           myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", "?" );
577           myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", "?" );
578           myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", "?" );
579           myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", "?" );
580           myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", "?" );
581           myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", "?" );
582           myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", "?" );
583           myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", "?" );
584           myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
585           myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
586           myWidgets[iNb][iQuadratic]              ->setProperty( "text", "?" );
587           myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", "?" );
588         }
589         else if ( nb3DLinear + nb3DQuadratic + nb3DBiQuadratic > 0 )
590         {
591           myWidgets[i3D][iLinear]                 ->setProperty( "text", "?" );
592           myWidgets[i3D][iQuadratic]              ->setProperty( "text", "?" );
593           myWidgets[i3D][iBiQuadratic]            ->setProperty( "text", "?" );
594           myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", "?" );
595           myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", "?" );
596           myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", "?" );
597           myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", "?" );
598           myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", "?" );
599           myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", "?" );
600           myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", "?" );
601           myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", "?" );
602           myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", "?" );
603           myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", "?" );
604           myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", "?" );
605           myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", "?" );
606           myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", "?" );
607           myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", "?" );
608           myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", "?" );
609           myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
610           myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
611           myWidgets[iNb][iQuadratic]              ->setProperty( "text", "?" );
612           myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", "?" );
613         }
614       }
615       else
616       {
617         myWidgets[iNodes][iTotal]               ->setProperty( "text", "?" );
618         myWidgets[i0D][iTotal]                  ->setProperty( "text", "?" );
619         myWidgets[iBalls][iTotal]               ->setProperty( "text", "?" );
620         myWidgets[i1D][iTotal]                  ->setProperty( "text", "?" );
621         myWidgets[i1D][iLinear]                 ->setProperty( "text", "?" );
622         myWidgets[i1D][iQuadratic]              ->setProperty( "text", "?" );
623         myWidgets[i2D][iTotal]                  ->setProperty( "text", "?" );
624         myWidgets[i2D][iLinear]                 ->setProperty( "text", "?" );
625         myWidgets[i2D][iQuadratic]              ->setProperty( "text", "?" );
626         myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", "?" );
627         myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", "?" );
628         myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", "?" );
629         myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", "?" );
630         myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", "?" );
631         myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", "?" );
632         myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", "?" );
633         myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", "?" );
634         myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", "?" );
635         myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", "?" );
636         myWidgets[i3D][iTotal]                  ->setProperty( "text", "?" );
637         myWidgets[i3D][iLinear]                 ->setProperty( "text", "?" );
638         myWidgets[i3D][iQuadratic]              ->setProperty( "text", "?" );
639         myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", "?" );
640         myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", "?" );
641         myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", "?" );
642         myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", "?" );
643         myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", "?" );
644         myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", "?" );
645         myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", "?" );
646         myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", "?" );
647         myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", "?" );
648         myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", "?" );
649         myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", "?" );
650         myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", "?" );
651         myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", "?" );
652         myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", "?" );
653         myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", "?" );
654         myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
655         myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
656         myWidgets[iNb][iQuadratic]              ->setProperty( "text", "?" );
657         myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", "?" );
658       }
659     }
660   }
661 }
662
663 /*!
664   \brief Load mesh from a study file
665 */
666 void SMESHGUI_MeshInfo::loadMesh()
667 {
668   SUIT_OverrideCursor wc;
669
670   SALOME_ListIO selected;
671   SMESHGUI::selectionMgr()->selectedObjects( selected );
672
673   if ( selected.Extent() == 1 ) {
674     Handle(SALOME_InteractiveObject) IO = selected.First();
675     SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
676     if ( !CORBA::is_nil( obj ) ) {
677       SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
678       if ( !mesh->_is_nil() )
679       {
680         mesh->Load();
681         showInfo( obj );
682       }
683     }
684   }
685 }
686
687 /*!
688   \brief Reset the widget to the initial state (nullify all fields).
689 */
690 void SMESHGUI_MeshInfo::clear()
691 {
692   myWidgets[iName][iSingle]               ->setProperty( "text", QString() );
693   myWidgets[iObject][iSingle]             ->setProperty( "text", QString() );
694   myWidgets[iNodes][iTotal]               ->setProperty( "text", QString::number( 0 ) );
695   myWidgets[i0D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
696   myWidgets[iBalls][iTotal]               ->setProperty( "text", QString::number( 0 ) );
697   myWidgets[i1D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
698   myWidgets[i1D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
699   myWidgets[i1D][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
700   myWidgets[i2D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
701   myWidgets[i2D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
702   myWidgets[i2D][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
703   myWidgets[i2D][iBiQuadratic]            ->setProperty( "text", QString::number( 0 ) );
704   myWidgets[i2DTriangles][iTotal]         ->setProperty( "text", QString::number( 0 ) );
705   myWidgets[i2DTriangles][iLinear]        ->setProperty( "text", QString::number( 0 ) );
706   myWidgets[i2DTriangles][iQuadratic]     ->setProperty( "text", QString::number( 0 ) );
707   myWidgets[i2DTriangles][iBiQuadratic]   ->setProperty( "text", QString::number( 0 ) );
708   myWidgets[i2DQuadrangles][iTotal]       ->setProperty( "text", QString::number( 0 ) );
709   myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", QString::number( 0 ) );
710   myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", QString::number( 0 ) );
711   myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", QString::number( 0 ) );
712   myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( 0 ) );
713   myWidgets[i3D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
714   myWidgets[i3D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
715   myWidgets[i3D][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
716   myWidgets[i3D][iBiQuadratic]            ->setProperty( "text", QString::number( 0 ) );
717   myWidgets[i3DTetrahedrons][iTotal]      ->setProperty( "text", QString::number( 0 ) );
718   myWidgets[i3DTetrahedrons][iLinear]     ->setProperty( "text", QString::number( 0 ) );
719   myWidgets[i3DTetrahedrons][iQuadratic]  ->setProperty( "text", QString::number( 0 ) );
720   myWidgets[i3DHexahedrons][iTotal]       ->setProperty( "text", QString::number( 0 ) );
721   myWidgets[i3DHexahedrons][iLinear]      ->setProperty( "text", QString::number( 0 ) );
722   myWidgets[i3DHexahedrons][iQuadratic]   ->setProperty( "text", QString::number( 0 ) );
723   myWidgets[i3DHexahedrons][iBiQuadratic] ->setProperty( "text", QString::number( 0 ) );
724   myWidgets[i3DPyramids][iTotal]          ->setProperty( "text", QString::number( 0 ) );
725   myWidgets[i3DPyramids][iLinear]         ->setProperty( "text", QString::number( 0 ) );
726   myWidgets[i3DPyramids][iQuadratic]      ->setProperty( "text", QString::number( 0 ) );
727   myWidgets[i3DPrisms][iTotal]            ->setProperty( "text", QString::number( 0 ) );
728   myWidgets[i3DPrisms][iLinear]           ->setProperty( "text", QString::number( 0 ) );
729   myWidgets[i3DPrisms][iQuadratic]        ->setProperty( "text", QString::number( 0 ) );
730   myWidgets[i3DHexaPrisms][iTotal]        ->setProperty( "text", QString::number( 0 ) );
731   myWidgets[i3DPolyhedrons][iTotal]       ->setProperty( "text", QString::number( 0 ) );
732   myWidgets[iNb][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
733   myWidgets[iNb][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
734   myWidgets[iNb][iQuadratic]              ->setProperty( "text", QString::number( 0 ) );
735   myWidgets[iNb][iBiQuadratic]            ->setProperty( "text", QString::number( 0 ) );
736 }
737
738 /*!
739   \brief Create info field
740   \return new info field
741 */
742 QLabel* SMESHGUI_MeshInfo::createField()
743 {
744   QLabel* lab = new QLabel( this );
745   lab->setFrameStyle( StyledPanel | Sunken );
746   lab->setAlignment( Qt::AlignCenter );
747   lab->setAutoFillBackground( true );
748   QPalette pal = lab->palette();
749   pal.setColor( QPalette::Window, QApplication::palette().color( QPalette::Active, QPalette::Base ) );
750   lab->setPalette( pal );
751   lab->setMinimumWidth( 70 );
752   return lab;
753 }
754
755 /*!
756   \brief Create horizontal rule.
757   \return new line object
758 */
759 QWidget* SMESHGUI_MeshInfo::createLine()
760 {
761   QFrame* line = new QFrame( this );
762   line->setFrameStyle( HLine | Sunken );
763   return line;
764 }
765
766 /*!
767   \brief Change widget font attributes (bold, italic, ...).
768   \param w widget
769   \param attr font attributes (XORed flags)
770   \param val value to be set to attributes
771 */
772 void SMESHGUI_MeshInfo::setFontAttributes( QWidget* w, int attr, bool val )
773 {
774   if ( w && attr ) {
775     QFont f = w->font();
776     if ( attr & Bold   ) f.setBold( val );
777     if ( attr & Italic ) f.setItalic( val );
778     w->setFont( f );
779   }
780 }
781
782 /*!
783   \brief Show/hide group(s) of fields.
784   \param start beginning of the block
785   \param end end of the block
786   \param on visibility flag
787 */
788 void SMESHGUI_MeshInfo::setFieldsVisible( int start, int end, bool on )
789 {
790   start = qMax( 0, start );
791   end   = qMin( end, (int)iElementsEnd );
792   for ( int i = start; i < end; i++ ) {
793     wlist wl = myWidgets[i];
794     foreach ( QWidget* w, wl ) w->setVisible( on );
795   }
796 }
797
798 void SMESHGUI_MeshInfo::saveInfo( QTextStream &out )
799 {
800   out << QString( 9, '-' ) << "\n";
801   out << tr( "BASE_INFO" ) << "\n";
802   out << QString( 9, '-' ) << "\n";
803   out <<                                   tr( "NAME_LAB" )         << "  " << ( myWidgets[iName][iSingle]->property( "text" ) ).toString() << "\n";
804   out <<                                   tr( "OBJECT_LAB" )       << "  " << ( myWidgets[iObject][iSingle]->property( "text" ) ).toString() << "\n";
805   out <<                                   tr( "NODES_LAB" )        << "  " << ( myWidgets[iNodes][iTotal]->property( "text" ) ).toString() << "\n";
806   out <<                                   tr( "ELEMENTS_LAB" )     << "\n";
807   out << QString( SPACING_INFO,   ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[iNb][iTotal]->property( "text" ) ).toString() << "\n";
808   out << QString( SPACING_INFO,   ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[iNb][iLinear]->property( "text" ) ).toString() << "\n";
809   out << QString( SPACING_INFO,   ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[iNb][iQuadratic]->property( "text" ) ).toString() << "\n";
810   out << QString( SPACING_INFO,   ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[iNb][iBiQuadratic]->property( "text" ) ).toString() << "\n";
811   out << QString( SPACING_INFO,   ' ' ) << tr( "0D_LAB" )           << "\n";
812   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i0D][iTotal]->property( "text" ) ).toString() << "\n";
813   out << QString( SPACING_INFO,   ' ' ) << tr( "BALL_LAB" )         << "\n";
814   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[iBalls][iTotal]->property( "text" ) ).toString() << "\n";
815   out << QString( SPACING_INFO,   ' ' ) << tr( "1D_LAB" )           << "\n";
816   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i1D][iTotal]->property( "text" ) ).toString() << "\n";
817   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i1D][iLinear]->property( "text" ) ).toString() << "\n";
818   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i1D][iQuadratic]->property( "text" ) ).toString() << "\n";
819   out << QString( SPACING_INFO,   ' ' ) << tr( "2D_LAB" )           << "\n";
820   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2D][iTotal]->property( "text" ) ).toString() << "\n";
821   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2D][iLinear]->property( "text" ) ).toString() << "\n";
822   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2D][iQuadratic]->property( "text" ) ).toString() << "\n";
823   out << QString( SPACING_INFO*2, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2D][iBiQuadratic]->property( "text" ) ).toString() << "\n";
824   out << QString( SPACING_INFO*2, ' ' ) << tr( "TRIANGLES_LAB" )    << "\n";
825   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DTriangles][iTotal]->property( "text" ) ).toString() << "\n";
826   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2DTriangles][iLinear]->property( "text" ) ).toString() << "\n";
827   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2DTriangles][iQuadratic]->property( "text" ) ).toString() << "\n";
828   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2DTriangles][iBiQuadratic]->property( "text" ) ).toString() << "\n";
829   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRANGLES_LAB" )  << "\n";
830   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DQuadrangles][iTotal]->property( "text" ) ).toString() << "\n";
831   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2DQuadrangles][iLinear]->property( "text" ) ).toString() << "\n";
832   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2DQuadrangles][iQuadratic]->property( "text" ) ).toString() << "\n";
833   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2DQuadrangles][iBiQuadratic]->property( "text" ) ).toString() << "\n";
834   out << QString( SPACING_INFO*2, ' ' ) << tr( "POLYGONS_LAB" )     << "\n";
835   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DPolygons][iTotal]->property( "text" ) ).toString() << "\n";
836   out << QString( SPACING_INFO,   ' ' ) << tr( "3D_LAB" )           << "\n";
837   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3D][iTotal]->property( "text" ) ).toString() << "\n";
838   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3D][iLinear]->property( "text" ) ).toString() << "\n";
839   out << QString( SPACING_INFO*2, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3D][iQuadratic]->property( "text" ) ).toString() << "\n";
840   out << QString( SPACING_INFO*2, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i3D][iBiQuadratic]->property( "text" ) ).toString() << "\n";
841   out << QString( SPACING_INFO*2, ' ' ) << tr( "TETRAHEDRONS_LAB" ) << "\n";
842   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DTetrahedrons][iTotal]->property( "text" ) ).toString() << "\n";
843   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DTetrahedrons][iLinear]->property( "text" ) ).toString() << "\n";
844   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DTetrahedrons][iQuadratic]->property( "text" ) ).toString() << "\n";
845   out << QString( SPACING_INFO*2, ' ' ) << tr( "HEXAHEDONRS_LAB" )  << "\n";
846   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DHexahedrons][iTotal]->property( "text" ) ).toString() << "\n";
847   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DHexahedrons][iLinear]->property( "text" ) ).toString() << "\n";
848   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DHexahedrons][iQuadratic]->property( "text" ) ).toString() << "\n";
849   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i3DHexahedrons][iBiQuadratic]->property( "text" ) ).toString() << "\n";
850   out << QString( SPACING_INFO*2, ' ' ) << tr( "PYRAMIDS_LAB" )     << "\n";
851   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DPyramids][iTotal]->property( "text" ) ).toString() << "\n";
852   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DPyramids][iLinear]->property( "text" ) ).toString() << "\n";
853   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DPyramids][iQuadratic]->property( "text" ) ).toString() << "\n";
854   out << QString( SPACING_INFO*2, ' ' ) << tr( "PRISMS_LAB" )       << "\n";
855   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DPrisms][iTotal]->property( "text" ) ).toString() << "\n";
856   out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3DPrisms][iLinear]->property( "text" ) ).toString() << "\n";
857   out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i3DPrisms][iQuadratic]->property( "text" ) ).toString() << "\n";
858   out << QString( SPACING_INFO*2, ' ' ) << tr( "HEX_PRISMS_LAB" )   << "\n";
859   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DHexaPrisms][iTotal]->property( "text" ) ).toString() << "\n";
860   out << QString( SPACING_INFO*2, ' ' ) << tr( "POLYHEDRONS_LAB" )  << "\n";
861   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3DPolyhedrons][iTotal]->property( "text" ) ).toString() << "\n" << "\n";
862 }
863
864 /*!
865   \class SMESHGUI_ElemInfo
866   \brief Base class for the mesh element information widget.
867 */
868
869 /*!
870   \brief Constructor
871   \param parent parent widget
872 */
873 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent )
874 : QWidget( parent ), myActor( 0 ), myIsElement( -1 )
875 {
876   myFrame = new QWidget( this );
877   myExtra = new ExtraWidget( this );
878   QVBoxLayout* vbl = new QVBoxLayout( this );
879   vbl->setMargin( 0 );
880   vbl->setSpacing( 0 );
881   vbl->addWidget( myFrame );
882   vbl->addWidget( myExtra );
883   connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
884   connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
885   clear();
886 }
887
888 /*!
889   \brief Destructor
890 */
891 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
892 {
893 }
894
895 /*!
896   \brief Set mesh data source (actor)
897   \param actor mesh object actor
898 */
899 void SMESHGUI_ElemInfo::setSource( SMESH_Actor* actor )
900 {
901   if ( myActor != actor ) {
902     myActor = actor;
903     myIsElement = -1;
904     clear();
905   }
906 }
907
908 /*!
909   \brief Show mesh element information
910   \param id mesh node / element ID
911   \param isElem show mesh element information if \c true or mesh node information if \c false
912 */
913 void SMESHGUI_ElemInfo::showInfo( long id, bool isElem )
914 {
915   QSet<long> ids;
916   ids << id;
917   showInfo( ids, isElem );
918 }
919
920 /*!
921   \brief Show mesh element information
922   \param ids mesh nodes / elements identifiers
923   \param isElem show mesh element information if \c true or mesh node information if \c false
924 */
925 void SMESHGUI_ElemInfo::showInfo( QSet<long> ids, bool isElem )
926 {
927   QList<long> newIds = ids.toList();
928   qSort( newIds );
929   if ( myIDs == newIds && myIsElement == isElem ) return;
930
931   myIDs = newIds;
932   myIsElement = isElem;
933   myIndex = 0;
934   updateControls();
935   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
936 }
937
938 /*!
939   \brief Clear mesh element information widget
940 */
941 void SMESHGUI_ElemInfo::clear()
942 {
943   myIDs.clear();
944   myIndex = 0;
945   clearInternal();
946   updateControls();
947 }
948
949 /*!
950   \brief Get central area widget
951   \return central widget
952 */
953 QWidget* SMESHGUI_ElemInfo::frame() const
954 {
955   return myFrame;
956 }
957
958 /*!
959   \brief Get actor
960   \return actor being used
961 */
962 SMESH_Actor* SMESHGUI_ElemInfo::actor() const
963 {
964   return myActor;
965 }
966
967 /*!
968   \brief Get current info mode.
969   \return \c true if mesh element information is shown or \c false if node information is shown
970 */
971 bool SMESHGUI_ElemInfo::isElements() const
972 {
973   return myIsElement;
974 }
975
976 /*!
977   \fn void SMESHGUI_ElemInfo::information( const QList<long>& ids )
978   \brief Show information on the specified nodes / elements
979
980   This function is to be redefined in sub-classes.
981
982   \param ids nodes / elements identifiers information is to be shown on
983 */
984
985 /*!
986   \brief Internal clean-up (reset widget)
987 */
988 void SMESHGUI_ElemInfo::clearInternal()
989 {
990 }
991
992 /*!
993   \brief Get node connectivity
994   \param node mesh node
995   \return node connectivity map
996 */
997 SMESHGUI_ElemInfo::Connectivity SMESHGUI_ElemInfo::nodeConnectivity( const SMDS_MeshNode* node )
998 {
999   Connectivity elmap;
1000   if ( node ) {
1001     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
1002     while ( it && it->more() ) {
1003       const SMDS_MeshElement* ne = it->next();
1004       elmap[ ne->GetType() ] << ne->GetID();
1005     }
1006   }
1007   return elmap;
1008 }
1009
1010 /*!
1011   \brief Format connectivity data to string representation
1012   \param connectivity connetivity map
1013   \param type element type
1014   \return string representation of the connectivity
1015 */
1016 QString SMESHGUI_ElemInfo::formatConnectivity( Connectivity connectivity, int type )
1017 {
1018   QStringList str;
1019   if ( connectivity.contains( type ) ) {
1020     QList<int> elements = connectivity[ type ];
1021     qSort( elements );
1022     foreach( int id, elements )
1023       str << QString::number( id );
1024   }
1025   return str.join( " " );
1026 }
1027
1028 /*!
1029   \brief Calculate gravity center of the mesh element
1030   \param element mesh element
1031 */
1032 SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* element )
1033 {
1034   XYZ xyz;
1035   if ( element ) {
1036     SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
1037     while ( nodeIt->more() ) {
1038       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1039       xyz.add( node->X(), node->Y(), node->Z() );
1040     }
1041     xyz.divide( element->NbNodes() );
1042   }
1043   return xyz;
1044 }
1045
1046 /*!
1047   \brief This slot is called from "Show Previous" button click.
1048   Shows information on the previous group of the items.
1049 */
1050 void SMESHGUI_ElemInfo::showPrevious()
1051 {
1052   myIndex = qMax( 0, myIndex-1 );
1053   updateControls();
1054   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
1055 }
1056
1057 /*!
1058   \brief This slot is called from "Show Next" button click.
1059   Shows information on the next group of the items.
1060 */
1061 void SMESHGUI_ElemInfo::showNext()
1062 {
1063   myIndex = qMin( myIndex+1, myIDs.count() / MAXITEMS );
1064   updateControls();
1065   information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) );
1066 }
1067
1068 /*!
1069   \brief Update widgets state
1070 */
1071 void SMESHGUI_ElemInfo::updateControls()
1072 {
1073   myExtra->updateControls( myIDs.count(), myIndex );
1074 }
1075
1076 /*!
1077   \class SMESHGUI_SimpleElemInfo
1078   \brief Represents mesh element information in the simple text area.
1079 */
1080
1081 /*!
1082   \brief Constructor
1083   \param parent parent widget
1084 */
1085 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
1086 : SMESHGUI_ElemInfo( parent )
1087 {
1088   myInfo = new QTextBrowser( frame() );
1089   QVBoxLayout* l = new QVBoxLayout( frame() );
1090   l->setMargin( 0 );
1091   l->addWidget( myInfo );
1092 }
1093
1094 /*!
1095   \brief Show mesh element information
1096   \param ids mesh nodes / elements identifiers
1097 */
1098 void SMESHGUI_SimpleElemInfo::information( const QList<long>& ids )
1099 {
1100   clearInternal();
1101   
1102   if ( actor() ) {
1103     int grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1104     int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1105     int cprecision = -1;
1106     if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ) 
1107       cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
1108     foreach ( long id, ids ) {
1109       if ( !isElements() ) {
1110         //
1111         // show node info
1112         //
1113         const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
1114         if ( !node ) return;
1115
1116         // node ID
1117         myInfo->append( QString( "<b>%1 #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "NODE" ) ).arg( id ) );
1118         // separator
1119         myInfo->append( "" );
1120         // coordinates
1121         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "COORDINATES" ) ).
1122                         arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1123                         arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1124                         arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1125         // separator
1126         myInfo->append( "" );
1127         // connectivity
1128         Connectivity connectivity = nodeConnectivity( node );
1129         if ( !connectivity.isEmpty() ) {
1130           myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) ) );
1131           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1132           if ( !con.isEmpty() )
1133             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) ).arg( con ) );
1134           con = formatConnectivity( connectivity, SMDSAbs_Edge );
1135           if ( !con.isEmpty() )
1136             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "EDGES" ) ).arg( con ) );
1137           con = formatConnectivity( connectivity, SMDSAbs_Ball );
1138           if ( !con.isEmpty() )
1139             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ) ).arg( con ) );
1140           con = formatConnectivity( connectivity, SMDSAbs_Face );
1141           if ( !con.isEmpty() )
1142             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "FACES" ) ).arg( con ) );
1143           con = formatConnectivity( connectivity, SMDSAbs_Volume );
1144           if ( !con.isEmpty() )
1145             myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "VOLUMES" ) ).arg( con ) );
1146         }
1147         else {
1148           myInfo->append( QString( "<b>%1</b>" ).arg( SMESHGUI_ElemInfo::tr( "FREE_NODE" ) ).arg( id ) );
1149         }
1150         // node position
1151         SMESH::SMESH_Mesh_ptr aMeshPtr = actor()->GetObject()->GetMeshServer();   
1152         if ( !CORBA::is_nil( aMeshPtr ) ) {
1153           SMESH::NodePosition_var pos = aMeshPtr->GetNodePosition( id );
1154           int shapeID = pos->shapeID;
1155           if ( shapeID > 0 ) {
1156             QString shapeType;
1157             double u, v;
1158             switch ( pos->shapeType ) {
1159             case GEOM::EDGE:
1160               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );
1161               if ( pos->params.length() == 1 )
1162                 u = pos->params[0];
1163               break;
1164             case GEOM::FACE:
1165               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );
1166               if ( pos->params.length() == 2 ) {
1167                u = pos->params[0];
1168                v = pos->params[1];
1169               }
1170               break;
1171             case GEOM::VERTEX:
1172               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" );
1173               break;
1174             default:
1175               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );
1176               break;
1177             }
1178             // separator
1179             myInfo->append( "" );
1180             myInfo->append( QString( "<b>%1:" ).arg( SMESHGUI_ElemInfo::tr( "POSITION" ) ) );
1181             myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( shapeType ).arg( shapeID ) );
1182             if ( pos->shapeType == GEOM::EDGE || pos->shapeType == GEOM::FACE ) {
1183               myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "U_POSITION" ) ).
1184                               arg( QString::number( u, precision > 0 ? 'f' : 'g', qAbs( precision )) ) );
1185               if ( pos->shapeType == GEOM::FACE ) {
1186                 myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "V_POSITION" ) ).
1187                                 arg( QString::number( v, precision > 0 ? 'f' : 'g', qAbs( precision )) ) );
1188               }
1189             }
1190           }
1191         }
1192         // groups node belongs to
1193         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
1194         if ( !CORBA::is_nil( aMesh ) ) {
1195           SMESH::ListOfGroups_var groups = aMesh->GetGroups();
1196           myInfo->append( "" ); // separator
1197           bool top_created = false;
1198           for ( int i = 0; i < groups->length(); i++ ) {
1199             SMESH::SMESH_GroupBase_var aGrp = groups[i];
1200             if ( CORBA::is_nil( aGrp ) ) continue;
1201             QString aName = aGrp->GetName();
1202             if ( aGrp->GetType() == SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
1203               if ( !top_created ) {
1204                 myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_AddInfo::tr( "GROUPS" ) ) );
1205                 top_created = true;
1206               }
1207               myInfo->append( QString( "+ <b>%1:</b>" ).arg( aName.trimmed() ) );
1208               if ( grp_details ) {
1209                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
1210                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
1211                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
1212                 
1213                 // type : group on geometry, standalone group, group on filter
1214                 if ( !CORBA::is_nil( aStdGroup ) ) {
1215                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1216                                   arg( SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) ) );
1217                 }
1218                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
1219                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1220                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) ) );
1221                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1222                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1223                   if ( sobj ) {
1224                     myInfo->append( QString( "  - <b>%1:</b> %2: %3" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1225                                     arg( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) ).arg( sobj->GetName().c_str() ) );
1226                   }
1227                 }
1228                 else if ( !CORBA::is_nil( aFltGroup ) ) {
1229                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1230                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) ) );
1231                 }
1232                 
1233                 // size
1234                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "SIZE" ) ).
1235                                 arg( QString::number( aGrp->Size() ) ) );
1236                 
1237                 // color
1238                 SALOMEDS::Color color = aGrp->GetColor();
1239                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "COLOR" ) ).
1240                                 arg( QColor( color.R*255., color.G*255., color.B*255. ).name() ) );
1241               }
1242             }
1243           }
1244         }
1245       }
1246       else {
1247         //
1248         // show element info
1249         // 
1250         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id );
1251         SMESH::Controls::NumericalFunctorPtr afunctor;
1252         if ( !e ) return;
1253         
1254         // Element ID && Type
1255         QString stype;
1256         switch( e->GetType() ) {
1257         case SMDSAbs_0DElement:
1258           stype = SMESHGUI_ElemInfo::tr( "0D_ELEMENT" ); break;
1259         case SMDSAbs_Ball:
1260           stype = SMESHGUI_ElemInfo::tr( "BALL" ); break;
1261         case SMDSAbs_Edge:
1262           stype = SMESHGUI_ElemInfo::tr( "EDGE" ); break;
1263         case SMDSAbs_Face:
1264           stype = SMESHGUI_ElemInfo::tr( "FACE" ); break;
1265         case SMDSAbs_Volume:
1266           stype = SMESHGUI_ElemInfo::tr( "VOLUME" ); break;
1267         default: 
1268           break;
1269         }
1270         if ( stype.isEmpty() ) return;
1271         myInfo->append( QString( "<b>%1 #%2</b>" ).arg( stype ).arg( id ) );
1272         // separator
1273         myInfo->append( "" );
1274
1275         // Geometry type
1276         QString gtype;
1277         switch( e->GetEntityType() ) {
1278         case SMDSEntity_Triangle:
1279         case SMDSEntity_Quad_Triangle:
1280         case SMDSEntity_BiQuad_Triangle:
1281           gtype = SMESHGUI_ElemInfo::tr( "TRIANGLE" ); break;
1282         case SMDSEntity_Quadrangle:
1283         case SMDSEntity_Quad_Quadrangle:
1284         case SMDSEntity_BiQuad_Quadrangle:
1285           gtype = SMESHGUI_ElemInfo::tr( "QUADRANGLE" ); break;
1286         case SMDSEntity_Polygon:
1287         case SMDSEntity_Quad_Polygon:
1288           gtype = SMESHGUI_ElemInfo::tr( "POLYGON" ); break;
1289         case SMDSEntity_Tetra:
1290         case SMDSEntity_Quad_Tetra:
1291           gtype = SMESHGUI_ElemInfo::tr( "TETRAHEDRON" ); break;
1292         case SMDSEntity_Pyramid:
1293         case SMDSEntity_Quad_Pyramid:
1294           gtype = SMESHGUI_ElemInfo::tr( "PYRAMID" ); break;
1295         case SMDSEntity_Hexa:
1296         case SMDSEntity_Quad_Hexa:
1297         case SMDSEntity_TriQuad_Hexa:
1298           gtype = SMESHGUI_ElemInfo::tr( "HEXAHEDRON" ); break;
1299         case SMDSEntity_Penta:
1300         case SMDSEntity_Quad_Penta:
1301           gtype = SMESHGUI_ElemInfo::tr( "PRISM" ); break;
1302         case SMDSEntity_Hexagonal_Prism:
1303           gtype = SMESHGUI_ElemInfo::tr( "HEX_PRISM" ); break;
1304         case SMDSEntity_Polyhedra:
1305         case SMDSEntity_Quad_Polyhedra:
1306           gtype = SMESHGUI_ElemInfo::tr( "POLYHEDRON" ); break;
1307         default: 
1308           break;
1309         }
1310         if ( !gtype.isEmpty() )
1311           myInfo->append( QString( "<b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "TYPE" ) ).arg( gtype ) );
1312
1313         // Quadratic flag (any element except 0D)
1314         if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Ball ) {
1315           myInfo->append( QString( "<b>%1?</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "QUADRATIC" ) ).arg( e->IsQuadratic() ? SMESHGUI_ElemInfo::tr( "YES" ) : SMESHGUI_ElemInfo::tr( "NO" ) ) );
1316         }
1317         if ( const SMDS_BallElement* ball = dynamic_cast<const SMDS_BallElement*>( e )) {
1318           // Ball diameter
1319           myInfo->append( QString( "<b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "BALL_DIAMETER" ) ).arg( ball->GetDiameter() ));
1320         }
1321         // separator
1322         myInfo->append( "" );
1323
1324         // Connectivity
1325         SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
1326         for ( int idx = 1; nodeIt->more(); idx++ ) {
1327           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1328           // node number and ID
1329           myInfo->append( QString( "<b>%1 %2/%3</b> - #%4" ).arg( SMESHGUI_ElemInfo::tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ) );
1330           // node coordinates
1331           myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "COORDINATES" ) ).
1332                           arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1333                           arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ).
1334                           arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1335           // node connectivity
1336           Connectivity connectivity = nodeConnectivity( node );
1337           if ( !connectivity.isEmpty() ) {
1338             myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) ) );
1339             QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1340             if ( !con.isEmpty() )
1341               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) ).arg( con ) );
1342             con = formatConnectivity( connectivity, SMDSAbs_Edge );
1343             if ( !con.isEmpty() )
1344               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "EDGES" ) ).arg( con ) );
1345             con = formatConnectivity( connectivity, SMDSAbs_Face );
1346             if ( !con.isEmpty() )
1347               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "FACES" ) ).arg( con ) );
1348             con = formatConnectivity( connectivity, SMDSAbs_Volume );
1349             if ( !con.isEmpty() )
1350               myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "VOLUMES" ) ).arg( con ) );
1351           }
1352           else {
1353             myInfo->append( QString( "<b>%1</b>" ).arg( SMESHGUI_ElemInfo::tr( "FREE_NODE" ) ).arg( id ) );
1354           }
1355         }
1356         // separator
1357         myInfo->append( "" );
1358
1359         // Controls
1360         myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONTROLS" ) ) );
1361         //Length
1362         if ( e->GetType() == SMDSAbs_Edge ) {
1363           afunctor.reset( new SMESH::Controls::Length() );
1364           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1365           afunctor->SetPrecision( cprecision );
1366           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "LENGTH_EDGES" ) ).arg( afunctor->GetValue( id ) ) );  
1367         }
1368         if( e->GetType() == SMDSAbs_Face ) {
1369           //Area
1370           afunctor.reset(  new SMESH::Controls::Area() );
1371           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1372           afunctor->SetPrecision( cprecision );  
1373           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "AREA_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1374           //Taper
1375           afunctor.reset( new SMESH::Controls::Taper() );
1376           afunctor->SetMesh( actor()->GetObject()->GetMesh() );  
1377           afunctor->SetPrecision( cprecision );
1378           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "TAPER_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1379           //AspectRatio2D
1380           afunctor.reset( new SMESH::Controls::AspectRatio() );
1381           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1382           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "ASPECTRATIO_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1383           //Minimum angle         
1384           afunctor.reset( new SMESH::Controls::MinimumAngle() );
1385           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1386           afunctor->SetPrecision( cprecision );
1387           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MINIMUMANGLE_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1388           //Wraping angle        
1389           afunctor.reset( new SMESH::Controls::Warping() );
1390           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1391           afunctor->SetPrecision( cprecision );
1392           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "WARP_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1393           //Skew         
1394           afunctor.reset( new SMESH::Controls::Skew() );
1395           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1396           afunctor->SetPrecision( cprecision );
1397           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "SKEW_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1398           //ElemDiam2D   
1399           afunctor.reset( new SMESH::Controls::MaxElementLength2D() );
1400           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1401           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MAX_ELEMENT_LENGTH_2D" ) ).arg( afunctor->GetValue( id ) ) );
1402         }
1403         if( e->GetType() == SMDSAbs_Volume ) {
1404           //AspectRatio3D
1405           afunctor.reset(  new SMESH::Controls::AspectRatio3D() );
1406           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1407           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "ASPECTRATIO_3D_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1408           //Volume      
1409           afunctor.reset(  new SMESH::Controls::Volume() );
1410           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1411           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUME_3D_ELEMENTS" ) ).arg( afunctor->GetValue( id ) ) );
1412           //ElementDiameter3D    
1413           afunctor.reset(  new SMESH::Controls::Volume() );
1414           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1415           myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MAX_ELEMENT_LENGTH_3D" ) ).arg( afunctor->GetValue( id ) ) );
1416         }
1417         // separator
1418         myInfo->append( "" );
1419
1420         // Gravity center
1421         XYZ gc = gravityCenter( e );
1422         myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "GRAVITY_CENTER" ) ).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ) );
1423
1424         // Element position
1425         if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
1426           SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();    
1427           if ( !CORBA::is_nil( aMesh ) ) {
1428             SMESH::ElementPosition pos = aMesh->GetElementPosition( id );
1429             int shapeID = pos.shapeID;
1430             if ( shapeID > 0 ) {
1431               myInfo->append( "" ); // separator
1432               QString shapeType;
1433               switch ( pos.shapeType ) {
1434               case GEOM::EDGE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );   break;
1435               case GEOM::FACE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );   break;
1436               case GEOM::VERTEX: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" ); break;
1437               case GEOM::SOLID:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );  break;
1438               case GEOM::SHELL:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHELL" );  break;
1439               default:           shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHAPE" );  break;
1440               }
1441               myInfo->append( QString( "<b>%1:</b> %2 #%3" ).arg( SMESHGUI_ElemInfo::tr( "POSITION" ) ).arg( shapeType ).arg( shapeID ) );
1442             }
1443           }
1444         }
1445
1446         // Groups the element belongs to
1447         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
1448         if ( !CORBA::is_nil( aMesh ) ) {
1449           SMESH::ListOfGroups_var  groups = aMesh->GetGroups();
1450           myInfo->append( "" ); // separator
1451           bool top_created = false;
1452           for ( int i = 0; i < groups->length(); i++ ) {
1453             SMESH::SMESH_GroupBase_var aGrp = groups[i];
1454             if ( CORBA::is_nil( aGrp ) ) continue;
1455             QString aName = aGrp->GetName();
1456             if ( aGrp->GetType() != SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
1457               if ( !top_created ) {
1458                 myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_AddInfo::tr( "GROUPS" ) ) );
1459                 top_created = true;
1460               }
1461               myInfo->append( QString( "+ <b>%1:</b>" ).arg( aName.trimmed() ) );
1462               if ( grp_details ) {
1463                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
1464                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
1465                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
1466                 
1467                 // type : group on geometry, standalone group, group on filter
1468                 if ( !CORBA::is_nil( aStdGroup ) ) {
1469                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1470                                   arg( SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) ) );
1471                 }
1472                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
1473                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1474                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) ) );
1475                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1476                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1477                   if ( sobj ) {
1478                     myInfo->append( QString( "  - <b>%1:</b> %2: %3" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1479                                     arg( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) ).arg( sobj->GetName().c_str() ) );
1480                   }
1481                 }
1482                 else if ( !CORBA::is_nil( aFltGroup ) ) {
1483                   myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" ) ).
1484                                   arg( SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) ) );
1485                 }
1486                 
1487                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "SIZE" ) ).
1488                                 arg( QString::number( aGrp->Size() ) ) );
1489                 
1490                 // color
1491                 SALOMEDS::Color color = aGrp->GetColor();
1492                 myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "COLOR" ) ).
1493                                 arg( QColor( color.R*255., color.G*255., color.B*255. ).name() ) );
1494               }
1495             }
1496           }
1497         }
1498       }
1499       // separator
1500       if ( ids.count() > 1 ) {
1501         myInfo->append( "" );
1502         myInfo->append( "------" );
1503         myInfo->append( "" );
1504       }
1505     }
1506   }
1507 }
1508
1509 /*!
1510   \brief Internal clean-up (reset widget)
1511 */
1512 void SMESHGUI_SimpleElemInfo::clearInternal()
1513 {
1514   myInfo->clear();
1515 }
1516
1517 void SMESHGUI_SimpleElemInfo::saveInfo( QTextStream &out )
1518 {
1519   out << QString( 12, '-' ) << "\n";
1520   out << SMESHGUI_ElemInfo::tr( "ELEM_INFO" ) << "\n";
1521   out << QString( 12, '-' ) << "\n";
1522   out << myInfo->toPlainText();
1523   out << "\n";
1524 }
1525
1526
1527 /*!
1528   \class SMESHGUI_TreeElemInfo::ItemDelegate
1529   \brief Item delegate for tree mesh info widget
1530   \internal
1531 */
1532 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
1533 {
1534 public:
1535   ItemDelegate( QObject* );
1536   QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
1537 };
1538
1539 /*!
1540   \brief Constructor
1541   \internal
1542 */
1543 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ) : QItemDelegate( parent )
1544 {
1545 }
1546
1547 /*!
1548   \brief Create item editor widget
1549   \internal
1550 */
1551 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
1552 {
1553   QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
1554   if ( qobject_cast<QLineEdit*>( w ) ) qobject_cast<QLineEdit*>( w )->setReadOnly(  true );
1555   return w;
1556 }
1557
1558 /*!
1559   \class SMESHGUI_TreeElemInfo
1560   \brief Represents mesh element information in the tree-like form.
1561 */
1562
1563 /*!
1564   \brief Constructor
1565   \param parent parent widget
1566 */
1567 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
1568 : SMESHGUI_ElemInfo( parent )
1569 {
1570   myInfo = new QTreeWidget( frame() );
1571   myInfo->setColumnCount( 2 );
1572   myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
1573   myInfo->header()->setStretchLastSection( true );
1574   myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
1575   myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
1576   QVBoxLayout* l = new QVBoxLayout( frame() );
1577   l->setMargin( 0 );
1578   l->addWidget( myInfo );
1579   connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
1580 }
1581
1582 /*!
1583   \brief Show mesh element information
1584   \param ids mesh nodes / elements identifiers
1585 */
1586 void SMESHGUI_TreeElemInfo::information( const QList<long>& ids )
1587 {
1588   clearInternal();
1589
1590   if ( actor() ) {
1591     int grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1592     int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1593     int cprecision = -1;
1594     if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ) 
1595       cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
1596     foreach ( long id, ids ) {
1597       if ( !isElements() ) {
1598         //
1599         // show node info
1600         //
1601         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindNode( id );
1602         if ( !e ) return;
1603         const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
1604       
1605         // node ID
1606         QTreeWidgetItem* nodeItem = createItem( 0, Bold | All );
1607         nodeItem->setText( 0, SMESHGUI_ElemInfo::tr( "NODE" ) );
1608         nodeItem->setText( 1, QString( "#%1" ).arg( id ) );
1609         // coordinates
1610         QTreeWidgetItem* coordItem = createItem( nodeItem, Bold );
1611         coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ) );
1612         QTreeWidgetItem* xItem = createItem( coordItem );
1613         xItem->setText( 0, "X" );
1614         xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1615         QTreeWidgetItem* yItem = createItem( coordItem );
1616         yItem->setText( 0, "Y" );
1617         yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1618         QTreeWidgetItem* zItem = createItem( coordItem );
1619         zItem->setText( 0, "Z" );
1620         zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1621         // connectivity
1622         QTreeWidgetItem* conItem = createItem( nodeItem, Bold );
1623         conItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) );
1624         Connectivity connectivity = nodeConnectivity( node );
1625         if ( !connectivity.isEmpty() ) {
1626           QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1627           if ( !con.isEmpty() ) {
1628             QTreeWidgetItem* i = createItem( conItem );
1629             i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) );
1630             i->setText( 1, con );
1631           }
1632           con = formatConnectivity( connectivity, SMDSAbs_Ball );
1633           if ( !con.isEmpty() ) {
1634             QTreeWidgetItem* i = createItem( conItem );
1635             i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ) );
1636             i->setText( 1, con );
1637             i->setData( 1, TypeRole, NodeConnectivity );
1638           }
1639           con = formatConnectivity( connectivity, SMDSAbs_Edge );
1640           if ( !con.isEmpty() ) {
1641             QTreeWidgetItem* i = createItem( conItem );
1642             i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ) );
1643             i->setText( 1, con );
1644             i->setData( 1, TypeRole, NodeConnectivity );
1645           }
1646           con = formatConnectivity( connectivity, SMDSAbs_Face );
1647           if ( !con.isEmpty() ) {
1648             QTreeWidgetItem* i = createItem( conItem );
1649             i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ) );
1650             i->setText( 1, con );
1651             i->setData( 1, TypeRole, NodeConnectivity );
1652           }
1653           con = formatConnectivity( connectivity, SMDSAbs_Volume );
1654           if ( !con.isEmpty() ) {
1655             QTreeWidgetItem* i = createItem( conItem );
1656             i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ) );
1657             i->setText( 1, con );
1658             i->setData( 1, TypeRole, NodeConnectivity );
1659           }
1660         }
1661         else {
1662           conItem->setText( 1, SMESHGUI_ElemInfo::tr( "FREE_NODE" ) );
1663         }
1664         // node position
1665         SMESH::SMESH_Mesh_ptr aMeshPtr = actor()->GetObject()->GetMeshServer();   
1666         if ( !CORBA::is_nil( aMeshPtr ) ) {
1667           SMESH::NodePosition_var pos = aMeshPtr->GetNodePosition( id );
1668           int shapeID = pos->shapeID;
1669           if ( shapeID > 0 ) {
1670             QString shapeType;
1671             double u, v;
1672             switch ( pos->shapeType ) {
1673             case GEOM::EDGE:
1674               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );
1675               if ( pos->params.length() == 1 )
1676                 u = pos->params[0];
1677               break;
1678             case GEOM::FACE:
1679               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );
1680               if ( pos->params.length() == 2 ) {
1681                 u = pos->params[0];
1682                 v = pos->params[1];
1683               }
1684               break;
1685             case GEOM::VERTEX:
1686               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" );
1687               break;
1688             default:
1689               shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );
1690               break;
1691             }
1692             QTreeWidgetItem* posItem = createItem( nodeItem, Bold );
1693             posItem->setText( 0, SMESHGUI_ElemInfo::tr("POSITION") );
1694             posItem->setText( 1, (shapeType + " #%1").arg( shapeID ));
1695             if ( pos->shapeType == GEOM::EDGE || pos->shapeType == GEOM::FACE ) {
1696               QTreeWidgetItem* uItem = createItem( posItem );
1697               uItem->setText( 0, SMESHGUI_ElemInfo::tr("U_POSITION") );
1698               uItem->setText( 1, QString::number( u, precision > 0 ? 'f' : 'g', qAbs( precision )));
1699               if ( pos->shapeType == GEOM::FACE ) {
1700                 QTreeWidgetItem* vItem = createItem( posItem );
1701                 vItem->setText( 0, SMESHGUI_ElemInfo::tr("V_POSITION") );
1702                 vItem->setText( 1, QString::number( v, precision > 0 ? 'f' : 'g', qAbs( precision )));
1703               }
1704             }
1705           }
1706         }
1707         // groups node belongs to
1708         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
1709         if ( !CORBA::is_nil( aMesh ) ) {
1710           SMESH::ListOfGroups_var groups = aMesh->GetGroups();
1711           QTreeWidgetItem* groupsItem = 0;
1712           for ( int i = 0; i < groups->length(); i++ ) {
1713             SMESH::SMESH_GroupBase_var aGrp = groups[i];
1714             if ( CORBA::is_nil( aGrp ) ) continue;
1715             QString aName = aGrp->GetName();
1716             if ( aGrp->GetType() == SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
1717               if ( !groupsItem ) {
1718                 groupsItem = createItem( nodeItem, Bold );
1719                 groupsItem->setText( 0, SMESHGUI_AddInfo::tr( "GROUPS" ) );
1720               }
1721               QTreeWidgetItem* it = createItem( groupsItem, Bold );
1722               it->setText( 0, aName.trimmed() );
1723               if ( grp_details ) {
1724                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
1725                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
1726                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
1727                 
1728                 // type : group on geometry, standalone group, group on filter
1729                 QTreeWidgetItem* typeItem = createItem( it );
1730                 typeItem->setText( 0, SMESHGUI_AddInfo::tr( "TYPE" ) );
1731                 if ( !CORBA::is_nil( aStdGroup ) ) {
1732                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1733                 }
1734                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
1735                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1736                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
1737                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
1738                   if ( sobj ) {
1739                     QTreeWidgetItem* gobjItem = createItem( typeItem );
1740                     gobjItem->setText( 0, SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) );
1741                     gobjItem->setText( 1, sobj->GetName().c_str() );
1742                   }
1743                 }
1744                 else if ( !CORBA::is_nil( aFltGroup ) ) {
1745                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1746                 }
1747                 
1748                 // size
1749                 QTreeWidgetItem* sizeItem = createItem( it );
1750                 sizeItem->setText( 0, SMESHGUI_AddInfo::tr( "SIZE" ) );
1751                 sizeItem->setText( 1, QString::number( aGrp->Size() ) );
1752                 
1753                 // color
1754                 SALOMEDS::Color color = aGrp->GetColor();
1755                 QTreeWidgetItem* colorItem = createItem( it );
1756                 colorItem->setText( 0, SMESHGUI_AddInfo::tr( "COLOR" ) );
1757                 colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
1758               }
1759             }
1760           }
1761         }
1762       }
1763       else {
1764         //
1765         // show element info
1766         // 
1767         const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id );
1768         SMESH::Controls::NumericalFunctorPtr afunctor;
1769         if ( !e ) return;
1770         
1771         // element ID && type
1772         QString stype;
1773         switch( e->GetType() ) {
1774         case SMDSAbs_0DElement: stype = SMESHGUI_ElemInfo::tr( "0D_ELEMENT" ); break;
1775         case SMDSAbs_Ball:      stype = SMESHGUI_ElemInfo::tr( "BALL" ); break;
1776         case SMDSAbs_Edge:      stype = SMESHGUI_ElemInfo::tr( "EDGE" ); break;
1777         case SMDSAbs_Face:      stype = SMESHGUI_ElemInfo::tr( "FACE" ); break;
1778         case SMDSAbs_Volume:    stype = SMESHGUI_ElemInfo::tr( "VOLUME" ); break;
1779         default:;
1780         }
1781         if ( stype.isEmpty() ) return;
1782         QTreeWidgetItem* elemItem = createItem( 0, Bold | All );
1783         elemItem->setText( 0, stype );
1784         elemItem->setText( 1, QString( "#%1" ).arg( id ) );
1785         // geometry type
1786         QString gtype;
1787         switch( e->GetEntityType() ) {
1788         case SMDSEntity_Triangle:
1789         case SMDSEntity_Quad_Triangle:
1790         case SMDSEntity_BiQuad_Triangle:
1791           gtype = SMESHGUI_ElemInfo::tr( "TRIANGLE" ); break;
1792         case SMDSEntity_Quadrangle:
1793         case SMDSEntity_Quad_Quadrangle:
1794         case SMDSEntity_BiQuad_Quadrangle:
1795           gtype = SMESHGUI_ElemInfo::tr( "QUADRANGLE" ); break;
1796         case SMDSEntity_Polygon:
1797         case SMDSEntity_Quad_Polygon:
1798           gtype = SMESHGUI_ElemInfo::tr( "POLYGON" ); break;
1799         case SMDSEntity_Tetra:
1800         case SMDSEntity_Quad_Tetra:
1801           gtype = SMESHGUI_ElemInfo::tr( "TETRAHEDRON" ); break;
1802         case SMDSEntity_Pyramid:
1803         case SMDSEntity_Quad_Pyramid:
1804           gtype = SMESHGUI_ElemInfo::tr( "PYRAMID" ); break;
1805         case SMDSEntity_Hexa:
1806         case SMDSEntity_Quad_Hexa:
1807         case SMDSEntity_TriQuad_Hexa:
1808           gtype = SMESHGUI_ElemInfo::tr( "HEXAHEDRON" ); break;
1809         case SMDSEntity_Penta:
1810         case SMDSEntity_Quad_Penta:
1811           gtype = SMESHGUI_ElemInfo::tr( "PRISM" ); break;
1812         case SMDSEntity_Hexagonal_Prism:
1813           gtype = SMESHGUI_ElemInfo::tr( "HEX_PRISM" ); break;
1814         case SMDSEntity_Polyhedra:
1815         case SMDSEntity_Quad_Polyhedra:
1816           gtype = SMESHGUI_ElemInfo::tr( "POLYHEDRON" ); break;
1817         default: 
1818           break;
1819         }
1820         if ( !gtype.isEmpty() ) {
1821           QTreeWidgetItem* typeItem = createItem( elemItem, Bold );
1822           typeItem->setText( 0, SMESHGUI_ElemInfo::tr( "TYPE" ) );
1823           typeItem->setText( 1, gtype );
1824         }
1825         // quadratic flag (for edges, faces and volumes)
1826         if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
1827           // quadratic flag
1828           QTreeWidgetItem* quadItem = createItem( elemItem, Bold );
1829           quadItem->setText( 0, SMESHGUI_ElemInfo::tr( "QUADRATIC" ) );
1830           quadItem->setText( 1, e->IsQuadratic() ? SMESHGUI_ElemInfo::tr( "YES" ) : SMESHGUI_ElemInfo::tr( "NO" ) );
1831         }
1832         if ( const SMDS_BallElement* ball = dynamic_cast<const SMDS_BallElement*>( e )) {
1833           // ball diameter
1834           QTreeWidgetItem* diamItem = createItem( elemItem, Bold );
1835           diamItem->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_DIAMETER" ) );
1836           diamItem->setText( 1, QString( "%1" ).arg( ball->GetDiameter() ));
1837         }
1838         // connectivity
1839         QTreeWidgetItem* conItem = createItem( elemItem, Bold );
1840         conItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) );
1841         SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
1842         for ( int idx = 1; nodeIt->more(); idx++ ) {
1843           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
1844           // node number and ID
1845           QTreeWidgetItem* nodeItem = createItem( conItem, Bold );
1846           nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ) );
1847           nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ) );
1848           nodeItem->setData( 1, TypeRole, ElemConnectivity );
1849           nodeItem->setData( 1, IdRole, node->GetID() );
1850           nodeItem->setExpanded( false );
1851           // node coordinates
1852           QTreeWidgetItem* coordItem = createItem( nodeItem );
1853           coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ) );
1854           QTreeWidgetItem* xItem = createItem( coordItem );
1855           xItem->setText( 0, "X" );
1856           xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1857           QTreeWidgetItem* yItem = createItem( coordItem );
1858           yItem->setText( 0, "Y" );
1859           yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1860           QTreeWidgetItem* zItem = createItem( coordItem );
1861           zItem->setText( 0, "Z" );
1862           zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1863           // node connectivity
1864           QTreeWidgetItem* nconItem = createItem( nodeItem );
1865           nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ) );
1866           Connectivity connectivity = nodeConnectivity( node );
1867           if ( !connectivity.isEmpty() ) {
1868             QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
1869             if ( !con.isEmpty() ) {
1870               QTreeWidgetItem* i = createItem( nconItem );
1871               i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ) );
1872               i->setText( 1, con );
1873             }
1874             con = formatConnectivity( connectivity, SMDSAbs_Edge );
1875             if ( !con.isEmpty() ) {
1876               QTreeWidgetItem* i = createItem( nconItem );
1877               i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ) );
1878               i->setText( 1, con );
1879               i->setData( 1, TypeRole, NodeConnectivity );
1880             }
1881             con = formatConnectivity( connectivity, SMDSAbs_Ball );
1882             if ( !con.isEmpty() ) {
1883               QTreeWidgetItem* i = createItem( nconItem );
1884               i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ) );
1885               i->setText( 1, con );
1886               i->setData( 1, TypeRole, NodeConnectivity );
1887             }
1888             con = formatConnectivity( connectivity, SMDSAbs_Face );
1889             if ( !con.isEmpty() ) {
1890               QTreeWidgetItem* i = createItem( nconItem );
1891               i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ) );
1892               i->setText( 1, con );
1893               i->setData( 1, TypeRole, NodeConnectivity );
1894             }
1895             con = formatConnectivity( connectivity, SMDSAbs_Volume );
1896             if ( !con.isEmpty() ) {
1897               QTreeWidgetItem* i = createItem( nconItem );
1898               i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ) );
1899               i->setText( 1, con );
1900               i->setData( 1, TypeRole, NodeConnectivity );
1901             }
1902           }
1903         }
1904         //Controls
1905         QTreeWidgetItem* cntrItem = createItem( elemItem, Bold );
1906         cntrItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONTROLS" ) );
1907         //Length
1908         if( e->GetType()==SMDSAbs_Edge){         
1909           afunctor.reset( new SMESH::Controls::Length() );
1910           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1911           afunctor->SetPrecision( cprecision );
1912           QTreeWidgetItem* lenItem = createItem( cntrItem, Bold );
1913           lenItem->setText( 0, tr( "LENGTH_EDGES" ) );
1914           lenItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );         
1915         }
1916         if( e->GetType() == SMDSAbs_Face ) {
1917           //Area         
1918           afunctor.reset( new SMESH::Controls::Area() );        
1919           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1920           afunctor->SetPrecision( cprecision );
1921           QTreeWidgetItem* areaItem = createItem( cntrItem, Bold );
1922           areaItem->setText( 0, tr( "AREA_ELEMENTS" ) );
1923           areaItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue(id) ) );         
1924           //Taper
1925           afunctor.reset( new SMESH::Controls::Taper() );
1926           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1927           afunctor->SetPrecision( cprecision );
1928           QTreeWidgetItem* taperlItem = createItem( cntrItem, Bold );
1929           taperlItem->setText( 0, tr( "TAPER_ELEMENTS" ) );
1930           taperlItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );    
1931           //AspectRatio2D
1932           afunctor.reset( new SMESH::Controls::AspectRatio() );
1933           afunctor->SetMesh( actor()->GetObject()->GetMesh() );  
1934           QTreeWidgetItem* ratlItem = createItem( cntrItem, Bold );
1935           ratlItem->setText( 0, tr( "ASPECTRATIO_ELEMENTS" ));
1936           ratlItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );      
1937           //Minimum angle
1938           afunctor.reset( new SMESH::Controls::MinimumAngle() );
1939           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1940           afunctor->SetPrecision( cprecision );
1941           QTreeWidgetItem* minanglItem = createItem( cntrItem, Bold );
1942           minanglItem->setText( 0, tr( "MINIMUMANGLE_ELEMENTS" ) );
1943           minanglItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );    
1944           //Wraping angle       
1945           afunctor.reset( new SMESH::Controls::Warping() );
1946           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1947           afunctor->SetPrecision( cprecision );
1948           QTreeWidgetItem* warpItem = createItem( cntrItem, Bold );
1949           warpItem->setText( 0, tr( "WARP_ELEMENTS" ));
1950           warpItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );        
1951           //Skew          
1952           afunctor.reset( new SMESH::Controls::Skew() );
1953           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1954           afunctor->SetPrecision( cprecision );
1955           QTreeWidgetItem* skewItem = createItem( cntrItem, Bold );
1956           skewItem->setText( 0, tr( "SKEW_ELEMENTS" ) );
1957           skewItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );       
1958           //ElemDiam2D    
1959           afunctor.reset( new SMESH::Controls::MaxElementLength2D() );
1960           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1961           QTreeWidgetItem* diamItem = createItem( cntrItem, Bold );
1962           diamItem->setText( 0, tr( "MAX_ELEMENT_LENGTH_2D" ));
1963           diamItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );       
1964         }
1965         if( e->GetType() == SMDSAbs_Volume ) {
1966           //AspectRatio3D
1967           afunctor.reset( new SMESH::Controls::AspectRatio3D() );
1968           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1969           QTreeWidgetItem* ratlItem3 = createItem( cntrItem, Bold );
1970           ratlItem3->setText( 0, tr( "ASPECTRATIO_3D_ELEMENTS" ) );
1971           ratlItem3->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );      
1972           //Volume
1973           afunctor.reset( new SMESH::Controls::Volume() );
1974           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1975           QTreeWidgetItem* volItem = createItem( cntrItem, Bold );
1976           volItem->setText( 0, tr( "VOLUME_3D_ELEMENTS" ) );
1977           volItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );
1978           //ElementDiameter3D
1979           afunctor.reset( new SMESH::Controls::MaxElementLength3D() );
1980           afunctor->SetMesh( actor()->GetObject()->GetMesh() );
1981           QTreeWidgetItem* diam3Item = createItem( cntrItem, Bold );
1982           diam3Item->setText( 0, tr( "MAX_ELEMENT_LENGTH_3D" ) );
1983           diam3Item->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id ) ) );     
1984         }
1985
1986         // gravity center
1987         XYZ gc = gravityCenter( e );
1988         QTreeWidgetItem* gcItem = createItem( elemItem, Bold );
1989         gcItem->setText( 0, SMESHGUI_ElemInfo::tr( "GRAVITY_CENTER" ) );
1990         QTreeWidgetItem* xItem = createItem( gcItem );
1991         xItem->setText( 0, "X" );
1992         xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1993         QTreeWidgetItem* yItem = createItem( gcItem );
1994         yItem->setText( 0, "Y" );
1995         yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1996         QTreeWidgetItem* zItem = createItem( gcItem );
1997         zItem->setText( 0, "Z" );
1998         zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
1999         // element position
2000         SMESH::SMESH_Mesh_ptr aMesh = actor()->GetObject()->GetMeshServer();
2001         if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
2002           if ( !CORBA::is_nil( aMesh ) ) {
2003             SMESH::ElementPosition pos = aMesh->GetElementPosition( id );
2004             int shapeID = pos.shapeID;
2005             if ( shapeID > 0 ) {
2006               QTreeWidgetItem* shItem = createItem( elemItem, Bold );
2007               QString shapeType;
2008               switch ( pos.shapeType ) {
2009               case GEOM::EDGE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );   break;
2010               case GEOM::FACE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );   break;
2011               case GEOM::VERTEX: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" ); break;
2012               case GEOM::SOLID:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );  break;
2013               case GEOM::SHELL:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHELL" );  break;
2014               default:           shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHAPE" );  break;
2015               }
2016               shItem->setText( 0, SMESHGUI_ElemInfo::tr( "POSITION" ) );
2017               shItem->setText( 1, QString( "%1 #%2" ).arg( shapeType ).arg( shapeID ) );
2018             }
2019           }
2020         }
2021         // groups element belongs to
2022         if ( !CORBA::is_nil( aMesh ) ) {
2023           SMESH::ListOfGroups_var  groups = aMesh->GetGroups();
2024           QTreeWidgetItem* groupsItem = 0;
2025           for ( int i = 0; i < groups->length(); i++ ) {
2026             SMESH::SMESH_GroupBase_var aGrp = groups[i];
2027             if ( CORBA::is_nil( aGrp ) ) continue;
2028             QString aName = aGrp->GetName();
2029             if ( aGrp->GetType() != SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id ) ) {
2030               if ( !groupsItem ) {
2031                 groupsItem = createItem( elemItem, Bold );
2032                 groupsItem->setText( 0, SMESHGUI_AddInfo::tr( "GROUPS" ) );
2033               }
2034               QTreeWidgetItem* it = createItem( groupsItem, Bold );
2035               it->setText( 0, aName.trimmed() );
2036               if ( grp_details ) {
2037                 SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
2038                 SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
2039                 SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
2040                 
2041                 // type : group on geometry, standalone group, group on filter
2042                 QTreeWidgetItem* typeItem = createItem( it );
2043                 typeItem->setText( 0, SMESHGUI_AddInfo::tr( "TYPE" ) );
2044                 if ( !CORBA::is_nil( aStdGroup ) ) {
2045                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
2046                 }
2047                 else if ( !CORBA::is_nil( aGeomGroup ) ) {
2048                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
2049                   GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
2050                   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
2051                   if ( sobj ) {
2052                     QTreeWidgetItem* gobjItem = createItem( typeItem );
2053                     gobjItem->setText( 0, SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ) );
2054                     gobjItem->setText( 1, sobj->GetName().c_str() );
2055                   }
2056                 }
2057                 else if ( !CORBA::is_nil( aFltGroup ) ) {
2058                   typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
2059                 }
2060                 
2061                 // size
2062                 QTreeWidgetItem* sizeItem = createItem( it );
2063                 sizeItem->setText( 0, SMESHGUI_AddInfo::tr( "SIZE" ) );
2064                 sizeItem->setText( 1, QString::number( aGrp->Size() ) );
2065                 
2066                 // color
2067                 SALOMEDS::Color color = aGrp->GetColor();
2068                 QTreeWidgetItem* colorItem = createItem( it );
2069                 colorItem->setText( 0, SMESHGUI_AddInfo::tr( "COLOR" ) );
2070                 colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
2071               }
2072             }
2073           }
2074         }
2075       }
2076     }
2077   }
2078 }
2079
2080 /*!
2081   \brief Internal clean-up (reset widget)
2082 */
2083 void SMESHGUI_TreeElemInfo::clearInternal()
2084 {
2085   myInfo->clear();
2086   myInfo->repaint();
2087 }
2088
2089 /*!
2090   \brief Create new tree item.
2091   \param parent parent tree widget item
2092   \param flags item flag
2093   \return new tree widget item
2094 */
2095 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int flags )
2096 {
2097   QTreeWidgetItem* item;
2098   if ( parent )
2099     item = new QTreeWidgetItem( parent );
2100   else
2101     item = new QTreeWidgetItem( myInfo );
2102
2103   item->setFlags( item->flags() | Qt::ItemIsEditable );
2104
2105   QFont f = item->font( 0 );
2106   f.setBold( true );
2107   for ( int i = 0; i < myInfo->columnCount(); i++ ) {
2108     if ( ( flags & Bold ) && ( i == 0 || flags & All ) )
2109       item->setFont( i, f );
2110   }
2111
2112   item->setExpanded( true );
2113   return item;
2114 }
2115
2116 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2117 {
2118   QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2119   if ( widgets.isEmpty() ) return;
2120   QTreeWidgetItem* aTreeItem = widgets.first();
2121   int type = aTreeItem->data( 1, TypeRole ).toInt();
2122   int id   = aTreeItem->data( 1, IdRole ).toInt();
2123   QMenu menu;
2124   QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ) );
2125   if ( type == ElemConnectivity && id > 0 && menu.exec( e->globalPos() ) == a )
2126     emit( itemInfo( id ) );
2127   else if ( type == NodeConnectivity && menu.exec( e->globalPos() ) == a )
2128     emit( itemInfo( aTreeItem->text( 1 ) ) );
2129 }
2130
2131 void  SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
2132 {
2133   if ( theItem ) {
2134     int type = theItem->data( 1, TypeRole ).toInt();
2135     int id   = theItem->data( 1, IdRole ).toInt();
2136     if ( type == ElemConnectivity && id > 0 )
2137       emit( itemInfo( id ) );
2138     else if ( type == NodeConnectivity )
2139       emit( itemInfo( theItem->text( 1 ) ) );
2140   }
2141 }
2142
2143 void SMESHGUI_TreeElemInfo::saveInfo( QTextStream &out )
2144 {
2145   out << QString( 12, '-' ) << "\n";
2146   out << SMESHGUI_ElemInfo::tr( "ELEM_INFO" ) << "\n";
2147   out << QString( 12, '-' ) << "\n";
2148
2149   QTreeWidgetItemIterator it( myInfo );
2150   while ( *it ) {
2151     if ( !( *it )->text(0).isEmpty() ) {
2152       out << QString( SPACING_INFO * itemDepth( *it ), ' ' ) << ( *it )->text(0);
2153       if ( !( *it )->text(1).isEmpty() ) out << ": " << ( *it )->text(1);
2154       out << "\n";
2155     }
2156     ++it;
2157   }
2158   out << "\n";
2159 }
2160
2161 /*!
2162   \class GrpComputor
2163   \brief Mesh information computer
2164   \internal
2165   
2166   The class is created for different computation operation. Currently it is used
2167   to compute number of underlying nodes for the groups.
2168 */
2169
2170 /*!
2171   \brief Contructor
2172 */
2173 GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* item, QObject* parent )
2174   : QObject( parent ), myItem( item )
2175 {
2176   myGroup = SMESH::SMESH_GroupBase::_narrow( grp );
2177 }
2178
2179 /*!
2180   \brief Compute function
2181 */
2182 void GrpComputor::compute()
2183 {
2184   if ( !CORBA::is_nil( myGroup ) && myItem ) {
2185     QTreeWidgetItem* item = myItem;
2186     myItem = 0;
2187     int nbNodes = myGroup->GetNumberOfNodes();
2188     item->treeWidget()->removeItemWidget( item, 1 );
2189     item->setText( 1, QString::number( nbNodes ));
2190   }
2191 }
2192
2193 /*!
2194   \class SMESHGUI_AddInfo
2195   \brief The wigdet shows additional information on the mesh object.
2196 */
2197
2198 /*!
2199   \brief Constructor
2200   \param parent parent widget
2201 */
2202 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent )
2203 : QTreeWidget( parent )
2204 {
2205   setColumnCount( 2 );
2206   header()->setStretchLastSection( true );
2207   header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2208   header()->hide();
2209 }
2210
2211 /*!
2212   \brief Destructor
2213 */
2214 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2215 {
2216 }
2217
2218 /*!
2219   \brief Show additional information on the selected object
2220   \param obj object being processed (mesh, sub-mesh, group, ID source)
2221 */
2222 void SMESHGUI_AddInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
2223 {
2224   setProperty( "group_index", 0 );
2225   setProperty( "submesh_index",  0 );
2226   myComputors.clear();
2227   clear();
2228
2229   if ( CORBA::is_nil( obj ) ) return;
2230
2231   _PTR(SObject) sobj = SMESH::ObjectToSObject( obj );
2232   if ( !sobj ) return;
2233
2234   // name
2235   QTreeWidgetItem* nameItem = createItem( 0, Bold | All );
2236   nameItem->setText( 0, tr( "NAME" ) );
2237   nameItem->setText( 1, sobj->GetName().c_str() );
2238   
2239   SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( obj );
2240   SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( obj );
2241   SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( obj );
2242   
2243   if ( !aMesh->_is_nil() )
2244     meshInfo( aMesh, nameItem );
2245   else if ( !aSubMesh->_is_nil() )
2246     subMeshInfo( aSubMesh, nameItem );
2247   else if ( !aGroup->_is_nil() )
2248     groupInfo( aGroup.in(), nameItem );
2249 }
2250
2251 /*!
2252   \brief Create new tree item.
2253   \param parent parent tree widget item
2254   \param flags item flag
2255   \return new tree widget item
2256 */
2257 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int flags )
2258 {
2259   QTreeWidgetItem* item;
2260
2261   if ( parent )
2262     item = new QTreeWidgetItem( parent );
2263   else
2264     item = new QTreeWidgetItem( this );
2265
2266   //item->setFlags( item->flags() | Qt::ItemIsEditable );
2267
2268   QFont f = item->font( 0 );
2269   f.setBold( true );
2270   for ( int i = 0; i < columnCount(); i++ ) {
2271     if ( ( flags & Bold ) && ( i == 0 || flags & All ) )
2272       item->setFont( i, f );
2273   }
2274
2275   item->setExpanded( true );
2276   return item;
2277 }
2278
2279 /*!
2280   \brief Show mesh info
2281   \param mesh mesh object
2282   \param parent parent tree item
2283 */
2284 void SMESHGUI_AddInfo::meshInfo( SMESH::SMESH_Mesh_ptr mesh, QTreeWidgetItem* parent )
2285 {
2286   // type
2287   GEOM::GEOM_Object_var shape = mesh->GetShapeToMesh();
2288   SMESH::MedFileInfo_var inf = mesh->GetMEDFileInfo();
2289   QTreeWidgetItem* typeItem = createItem( parent, Bold );
2290   typeItem->setText( 0, tr( "TYPE" ) );
2291   if ( !CORBA::is_nil( shape ) ) {
2292     typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2293     _PTR(SObject) sobj = SMESH::ObjectToSObject( shape );
2294     if ( sobj ) {
2295       QTreeWidgetItem* gobjItem = createItem( typeItem );
2296       gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2297       gobjItem->setText( 1, sobj->GetName().c_str() );
2298     }
2299   }
2300   else if ( strlen( (char*)inf->fileName ) > 0 ) {
2301     typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2302     QTreeWidgetItem* fileItem = createItem( typeItem );
2303     fileItem->setText( 0, tr( "FILE_NAME" ) );
2304     fileItem->setText( 1, (char*)inf->fileName );
2305   }
2306   else {
2307     typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2308   }
2309   
2310   // groups
2311   myGroups = mesh->GetGroups();
2312   showGroups();
2313
2314   // sub-meshes
2315   mySubMeshes = mesh->GetSubMeshes();
2316   showSubMeshes();
2317 }
2318
2319 /*!
2320   \brief Show sub-mesh info
2321   \param subMesh sub-mesh object
2322   \param parent parent tree item
2323 */
2324 void SMESHGUI_AddInfo::subMeshInfo( SMESH::SMESH_subMesh_ptr subMesh, QTreeWidgetItem* parent )
2325 {
2326   bool isShort = parent->parent() != 0;
2327
2328   if ( !isShort ) {
2329     // parent mesh
2330     _PTR(SObject) sobj = SMESH::ObjectToSObject( subMesh->GetFather() );
2331     if ( sobj ) {
2332       QTreeWidgetItem* nameItem = createItem( parent, Bold );
2333       nameItem->setText( 0, tr( "PARENT_MESH" ) );
2334       nameItem->setText( 1, sobj->GetName().c_str() );
2335     }
2336   }
2337   
2338   // shape
2339   GEOM::GEOM_Object_var gobj = subMesh->GetSubShape();
2340   _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
2341   if ( sobj ) {
2342     QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2343     gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2344     gobjItem->setText( 1, sobj->GetName().c_str() );
2345   }
2346 }
2347
2348 /*!
2349   \brief Show group info
2350   \param grp mesh group object
2351   \param parent parent tree item
2352 */
2353 void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* parent )
2354 {
2355   bool isShort = parent->parent() != 0;
2356
2357   SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( grp );
2358   SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( grp );
2359   SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( grp );
2360
2361   if ( !isShort ) {
2362     // parent mesh
2363     _PTR(SObject) sobj = SMESH::ObjectToSObject( grp->GetMesh() );
2364     if ( sobj ) {
2365       QTreeWidgetItem* nameItem = createItem( parent, Bold );
2366       nameItem->setText( 0, tr( "PARENT_MESH" ) );
2367       nameItem->setText( 1, sobj->GetName().c_str() );
2368     }
2369   }
2370
2371   // type : group on geometry, standalone group, group on filter
2372   QTreeWidgetItem* typeItem = createItem( parent, Bold );
2373   typeItem->setText( 0, tr( "TYPE" ) );
2374   if ( !CORBA::is_nil( aStdGroup ) ) {
2375     typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2376   }
2377   else if ( !CORBA::is_nil( aGeomGroup ) ) {
2378     typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2379     GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
2380     _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
2381     if ( sobj ) {
2382       QTreeWidgetItem* gobjItem = createItem( typeItem );
2383       gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2384       gobjItem->setText( 1, sobj->GetName().c_str() );
2385     }
2386   }
2387   else if ( !CORBA::is_nil( aFltGroup ) ) {
2388     typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2389   }
2390
2391   if ( !isShort ) {
2392     // entity type
2393     QString etype = tr( "UNKNOWN" );
2394     switch( grp->GetType() ) {
2395     case SMESH::NODE:
2396       etype = tr( "NODE" );
2397       break;
2398     case SMESH::EDGE:
2399       etype = tr( "EDGE" );
2400       break;
2401     case SMESH::FACE:
2402       etype = tr( "FACE" );
2403       break;
2404     case SMESH::VOLUME:
2405       etype = tr( "VOLUME" );
2406       break;
2407     case SMESH::ELEM0D:
2408       etype = tr( "0DELEM" );
2409       break;
2410     case SMESH::BALL:
2411       etype = tr( "BALL" );
2412       break;
2413     default:
2414       break;
2415     }
2416     QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2417     etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2418     etypeItem->setText( 1, etype );
2419   }
2420
2421   // size
2422   QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2423   sizeItem->setText( 0, tr( "SIZE" ) );
2424   sizeItem->setText( 1, QString::number( grp->Size() ) );
2425
2426   // color
2427   SALOMEDS::Color color = grp->GetColor();
2428   QTreeWidgetItem* colorItem = createItem( parent, Bold );
2429   colorItem->setText( 0, tr( "COLOR" ) );
2430   colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ) );
2431
2432   // nb of underlying nodes
2433   if ( grp->GetType() != SMESH::NODE) {
2434     QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2435     nodesItem->setText( 0, tr( "NB_NODES" ) );
2436     int nbNodesLimit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
2437     SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
2438     bool meshLoaded = mesh->IsLoaded();
2439     bool toShowNodes = ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit );
2440     if ( toShowNodes && meshLoaded ) {
2441       // already calculated and up-to-date
2442       nodesItem->setText( 1, QString::number( grp->GetNumberOfNodes() ) );
2443     }
2444     else {
2445       QPushButton* btn = new QPushButton( tr( meshLoaded ? "COMPUTE" : "LOAD"), this );
2446       setItemWidget( nodesItem, 1, btn );
2447       GrpComputor* comp = new GrpComputor( grp, nodesItem, this ); 
2448       connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2449       myComputors.append( comp );
2450       if ( !meshLoaded )
2451         connect( btn, SIGNAL( clicked() ), this, SLOT( changeLoadToCompute() ) );
2452     }
2453   }
2454 }
2455
2456 void SMESHGUI_AddInfo::showGroups()
2457 {
2458   myComputors.clear();
2459
2460   QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
2461   if ( !parent ) return;
2462
2463   int idx = property( "group_index" ).toInt();
2464
2465   QTreeWidgetItem* itemGroups = 0;
2466   for ( int i = 0; i < parent->childCount() && !itemGroups; i++ ) {
2467     if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GROUPS_ID ) {
2468       itemGroups = parent->child( i );
2469       ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemGroups, 1 ) );
2470       if ( extra )
2471         extra->updateControls( myGroups->length(), idx );
2472       while ( itemGroups->childCount() ) delete itemGroups->child( 0 ); // clear child items
2473     }
2474   }
2475
2476   QMap<int, QTreeWidgetItem*> grpItems;
2477   for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)myGroups->length() ); i++ ) {
2478     SMESH::SMESH_GroupBase_var grp = myGroups[i];
2479     if ( CORBA::is_nil( grp ) ) continue;
2480     _PTR(SObject) grpSObj = SMESH::ObjectToSObject( grp );
2481     if ( !grpSObj ) continue;
2482
2483     int grpType = grp->GetType();
2484
2485     if ( !itemGroups ) {
2486       // create top-level groups container item
2487       itemGroups = createItem( parent, Bold | All );
2488       itemGroups->setText( 0, tr( "GROUPS" ) );
2489       itemGroups->setData( 0, Qt::UserRole, GROUPS_ID );
2490
2491       // total number of groups > 10, show extra widgets for info browsing
2492       if ( myGroups->length() > MAXITEMS ) {
2493         ExtraWidget* extra = new ExtraWidget( this, true );
2494         connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2495         connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2496         setItemWidget( itemGroups, 1, extra );
2497         extra->updateControls( myGroups->length(), idx );
2498       }
2499     }
2500
2501     if ( grpItems.find( grpType ) == grpItems.end() ) {
2502       grpItems[ grpType ] = createItem( itemGroups, Bold | All );
2503       grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2504       itemGroups->insertChild( grpType-1, grpItems[ grpType ] );
2505     }
2506   
2507     // group name
2508     QTreeWidgetItem* grpNameItem = createItem( grpItems[ grpType ] );
2509     grpNameItem->setText( 0, QString( grpSObj->GetName().c_str() ).trimmed() ); // name is trimmed
2510
2511     // group info
2512     groupInfo( grp.in(), grpNameItem );
2513   }
2514 }
2515
2516 void SMESHGUI_AddInfo::showSubMeshes()
2517 {
2518   QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
2519   if ( !parent ) return;
2520
2521   int idx = property( "submesh_index" ).toInt();
2522
2523   QTreeWidgetItem* itemSubMeshes = 0;
2524   for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ ) {
2525     if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SUBMESHES_ID ) {
2526       itemSubMeshes = parent->child( i );
2527       ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemSubMeshes, 1 ) );
2528       if ( extra )
2529         extra->updateControls( mySubMeshes->length(), idx );
2530       while ( itemSubMeshes->childCount() ) delete itemSubMeshes->child( 0 ); // clear child items
2531     }
2532   }
2533
2534   QMap<int, QTreeWidgetItem*> smItems;
2535   for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)mySubMeshes->length() ); i++ ) {
2536     SMESH::SMESH_subMesh_var sm = mySubMeshes[i];
2537     if ( CORBA::is_nil( sm ) ) continue;
2538     _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm );
2539     if ( !smSObj ) continue;
2540     
2541     GEOM::GEOM_Object_var gobj = sm->GetSubShape();
2542     if ( CORBA::is_nil(gobj ) ) continue;
2543     
2544     int smType = gobj->GetShapeType();
2545     if ( smType == GEOM::COMPSOLID ) smType = GEOM::COMPOUND;
2546
2547     if ( !itemSubMeshes ) {
2548       itemSubMeshes = createItem( parent, Bold | All );
2549       itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2550       itemSubMeshes->setData( 0, Qt::UserRole, SUBMESHES_ID );
2551
2552       // total number of sub-meshes > 10, show extra widgets for info browsing
2553       if ( mySubMeshes->length() > MAXITEMS ) {
2554         ExtraWidget* extra = new ExtraWidget( this, true );
2555         connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2556         connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2557         setItemWidget( itemSubMeshes, 1, extra );
2558         extra->updateControls( mySubMeshes->length(), idx );
2559       }
2560     }
2561          
2562     if ( smItems.find( smType ) == smItems.end() ) {
2563       smItems[ smType ] = createItem( itemSubMeshes, Bold | All );
2564       smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2565       itemSubMeshes->insertChild( smType, smItems[ smType ] );
2566     }
2567     
2568     // submesh name
2569     QTreeWidgetItem* smNameItem = createItem( smItems[ smType ] );
2570     smNameItem->setText( 0, QString( smSObj->GetName().c_str() ).trimmed() ); // name is trimmed
2571     
2572     // submesh info
2573     subMeshInfo( sm.in(), smNameItem );
2574   }
2575 }
2576
2577 /*!
2578  * \brief Change button label of "nb underlying node" group from "Load" to "Compute"
2579  */
2580 void SMESHGUI_AddInfo::changeLoadToCompute()
2581 {
2582   for ( int i = 0; i < myComputors.count(); ++i )
2583   {
2584     if ( QTreeWidgetItem* item = myComputors[i]->getItem() )
2585     {
2586       if ( QPushButton* btn = qobject_cast<QPushButton*>( itemWidget ( item, 1 ) ) )
2587         btn->setText( tr("COMPUTE") );
2588     }
2589   }
2590 }
2591
2592 void SMESHGUI_AddInfo::showPreviousGroups()
2593 {
2594   int idx = property( "group_index" ).toInt();
2595   setProperty( "group_index", idx-1 );
2596   showGroups();
2597 }
2598
2599 void SMESHGUI_AddInfo::showNextGroups()
2600 {
2601   int idx = property( "group_index" ).toInt();
2602   setProperty( "group_index", idx+1 );
2603   showGroups();
2604 }
2605
2606 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2607 {
2608   int idx = property( "submesh_index" ).toInt();
2609   setProperty( "submesh_index", idx-1 );
2610   showSubMeshes();
2611 }
2612
2613 void SMESHGUI_AddInfo::showNextSubMeshes()
2614 {
2615   int idx = property( "submesh_index" ).toInt();
2616   setProperty( "submesh_index", idx+1 );
2617   showSubMeshes();
2618 }
2619
2620 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2621 {
2622   out << QString( 15, '-')       << "\n";
2623   out << tr( "ADDITIONAL_INFO" ) << "\n";
2624   out << QString( 15, '-' )      << "\n";
2625   QTreeWidgetItemIterator it( this );
2626   while ( *it ) {
2627     if ( !( ( *it )->text(0) ).isEmpty() ) {
2628       out << QString( SPACING_INFO * itemDepth( *it ), ' ' ) << ( *it )->text(0);
2629       if ( ( *it )->text(0)  == tr( "COLOR" ) ) {
2630         out << ": " << ( ( ( *it )->background(1) ).color() ).name();
2631       }
2632       else if ( !( ( *it )->text(1) ).isEmpty() ) out << ": " << ( *it )->text(1);
2633       out << "\n";
2634     }
2635     ++it;
2636   }
2637   out << "\n";
2638 }
2639
2640 /*!
2641   \class SMESHGUI_MeshInfoDlg
2642   \brief Mesh information dialog box
2643 */
2644
2645 /*!
2646   \brief Constructor
2647   \param parent parent widget
2648   \param page specifies the dialog page to be shown at the start-up
2649 */
2650 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
2651 : QDialog( parent ), myActor( 0 )
2652 {
2653   setModal( false );
2654   setAttribute( Qt::WA_DeleteOnClose, true );
2655   setWindowTitle( tr( "MESH_INFO" ) );
2656   setSizeGripEnabled( true );
2657
2658   myTabWidget = new QTabWidget( this );
2659
2660   // base info 
2661
2662   myBaseInfo = new SMESHGUI_MeshInfo( myTabWidget );
2663   myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
2664
2665   // elem info 
2666   
2667   QWidget* w = new QWidget( myTabWidget );
2668
2669   myMode = new QButtonGroup( this );
2670   myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
2671   myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
2672   myMode->button( NodeMode )->setChecked( true );
2673   myID = new QLineEdit( w );
2674   myID->setValidator( new SMESHGUI_IdValidator( this ) );
2675
2676   int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
2677   mode = qMin( 1, qMax( 0, mode ) );
2678   
2679   if ( mode == 0 ) 
2680     myElemInfo = new SMESHGUI_SimpleElemInfo( w );
2681   else
2682     myElemInfo = new SMESHGUI_TreeElemInfo( w );
2683
2684   QGridLayout* elemLayout = new QGridLayout( w );
2685   elemLayout->setMargin( MARGIN );
2686   elemLayout->setSpacing( SPACING );
2687   elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
2688   elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
2689   elemLayout->addWidget( myID, 0, 2 );
2690   elemLayout->addWidget( myElemInfo, 1, 0, 1, 3 );
2691   
2692   myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
2693
2694   // additional info
2695
2696   myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
2697   myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
2698
2699   // controls info
2700
2701   myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
2702   myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
2703
2704   // buttons
2705
2706   QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
2707   okBtn->setAutoDefault( true );
2708   okBtn->setDefault( true );
2709   okBtn->setFocus();
2710   QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
2711   dumpBtn->setAutoDefault( true );
2712   QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
2713   helpBtn->setAutoDefault( true );
2714
2715   QHBoxLayout* btnLayout = new QHBoxLayout;
2716   btnLayout->setSpacing( SPACING );
2717   btnLayout->setMargin( 0 );
2718
2719   btnLayout->addWidget( okBtn );
2720   btnLayout->addWidget( dumpBtn );
2721   btnLayout->addStretch( 10 );
2722   btnLayout->addWidget( helpBtn );
2723
2724   QVBoxLayout* l = new QVBoxLayout ( this );
2725   l->setMargin( MARGIN );
2726   l->setSpacing( SPACING );
2727   l->addWidget( myTabWidget );
2728   l->addLayout( btnLayout );
2729
2730   myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
2731
2732   connect( okBtn,       SIGNAL( clicked() ),              this, SLOT( reject() ) );
2733   connect( dumpBtn,     SIGNAL( clicked() ),              this, SLOT( dump() ) );
2734   connect( helpBtn,     SIGNAL( clicked() ),              this, SLOT( help() ) );
2735   connect( myTabWidget, SIGNAL( currentChanged( int  ) ), this, SLOT( updateSelection() ) );
2736   connect( myMode,      SIGNAL( buttonClicked( int  ) ),  this, SLOT( modeChanged() ) );
2737   connect( myID,        SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
2738   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
2739   connect( SMESHGUI::GetSMESHGUI(),  SIGNAL( SignalCloseAllDialogs() ),        this, SLOT( reject() ) );
2740   connect( myElemInfo,  SIGNAL( itemInfo( int ) ),     this, SLOT( showItemInfo( int ) ) );
2741   connect( myElemInfo,  SIGNAL( itemInfo( QString ) ), this, SLOT( showItemInfo( QString ) ) );
2742
2743   updateSelection();
2744 }
2745
2746 /*!
2747   \brief Destructor
2748 */
2749 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
2750 {
2751 }
2752
2753 /*!
2754   \brief Show mesh information
2755   \param IO interactive object
2756 */
2757 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO )
2758 {
2759   SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
2760   if ( !CORBA::is_nil( obj ) ) {
2761     myBaseInfo->showInfo( obj );
2762     myAddInfo->showInfo( obj );
2763     myCtrlInfo->showInfo( obj );
2764
2765     myActor = SMESH::FindActorByEntry( IO->getEntry() );
2766     SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
2767     QString ID;
2768     int nb = 0;
2769     if ( myActor && selector ) {
2770       nb = myMode->checkedId() == NodeMode ? 
2771         SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
2772         SMESH::GetNameOfSelectedNodes( selector, IO, ID );
2773     }
2774     myElemInfo->setSource( myActor ) ;
2775     if ( nb > 0 ) {
2776       myID->setText( ID.trimmed() );
2777       QSet<long> ids;
2778       QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
2779       foreach ( ID, idTxt )
2780         ids << ID.trimmed().toLong();
2781       myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode );
2782     }
2783     else {
2784       myID->clear();
2785       myElemInfo->clear();
2786     }
2787   }
2788 }
2789
2790 /*!
2791   \brief Perform clean-up actions on the dialog box closing.
2792 */
2793 void SMESHGUI_MeshInfoDlg::reject()
2794 {
2795   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
2796   selMgr->clearFilters();
2797   SMESH::SetPointRepresentation( false );
2798   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2799     aViewWindow->SetSelectionMode( ActorSelection );
2800   QDialog::reject();
2801 }
2802
2803 /*!
2804   \brief Process keyboard event
2805   \param e key press event
2806 */
2807 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
2808 {
2809   QDialog::keyPressEvent( e );
2810   if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
2811     e->accept();
2812     help();
2813   }
2814 }
2815
2816 /*!
2817   \brief Reactivate dialog box, when mouse pointer goes into it.
2818 */
2819 void SMESHGUI_MeshInfoDlg::enterEvent( QEvent* )
2820 {
2821   //activate();
2822 }
2823
2824 /*!
2825   \brief Setup selection mode depending on the current dialog box state.
2826 */
2827 void SMESHGUI_MeshInfoDlg::updateSelection()
2828 {
2829   LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
2830
2831   disconnect( selMgr, 0, this, 0 );
2832   selMgr->clearFilters();
2833
2834   if ( myTabWidget->currentIndex() == BaseInfo || myTabWidget->currentIndex() == AddInfo || myTabWidget->currentIndex() == CtrlInfo ) {
2835     SMESH::SetPointRepresentation( false );
2836     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2837       aViewWindow->SetSelectionMode( ActorSelection );
2838   }
2839   else {
2840     if ( myMode->checkedId() == NodeMode ) {
2841       SMESH::SetPointRepresentation( true );
2842       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2843         aViewWindow->SetSelectionMode( NodeSelection );
2844     }
2845     else {
2846       SMESH::SetPointRepresentation( false );
2847       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
2848         aViewWindow->SetSelectionMode( CellSelection );
2849     }
2850   }
2851
2852   QString oldID = myID->text().trimmed();
2853   SMESH_Actor* oldActor = myActor;
2854   myID->clear();
2855   
2856   connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
2857   updateInfo();
2858   
2859   if ( oldActor == myActor && myActor && !oldID.isEmpty() ) {
2860     myID->setText( oldID );
2861     idChanged();
2862   }
2863 }
2864
2865 /*!
2866   \brief Show help page
2867 */
2868 void SMESHGUI_MeshInfoDlg::help()
2869 {
2870   SMESH::ShowHelpFile( ( myTabWidget->currentIndex() == BaseInfo || myTabWidget->currentIndex() == AddInfo ) ?
2871                        "mesh_infos_page.html#advanced_mesh_infos_anchor" : 
2872                        "mesh_infos_page.html#mesh_element_info_anchor" );
2873 }
2874
2875 /*!
2876   \brief Show mesh information