Salome HOME
0021542: EDF 1699 SMESH: Reorient a group of faces
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshInfo.cxx
index 59a422ec8b7e5001299941e9a7fd8e56c63b3df8..c0dd77c103038f00a1e40d2f1f6eca97cb8260e5 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(GEOM_Gen)
 
-const int SPACING  = 6;
-const int MARGIN   = 9;
-const int MAXITEMS = 10;
+const int SPACING      = 6;
+const int MARGIN       = 9;
+const int MAXITEMS     = 10;
+const int GROUPS_ID    = 100;
+const int SUBMESHES_ID = 200;
+
+/*!
+  \class ExtraWidget
+  \internal
+*/
+
+class ExtraWidget : public QWidget
+{
+public:
+  ExtraWidget( QWidget*, bool = false );
+  ~ExtraWidget();
+
+  void updateControls( int, int, int = MAXITEMS );
+
+public:
+  QLabel*      current;
+  QPushButton* prev;
+  QPushButton* next;
+  bool         brief;
+};
+
+ExtraWidget::ExtraWidget( QWidget* parent, bool b ) : QWidget( parent ), brief( b )
+{
+  current = new QLabel( this );
+  current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
+  prev = new QPushButton( tr( "<<" ), this );
+  next = new QPushButton( tr( ">>" ), this );
+  QHBoxLayout* hbl = new QHBoxLayout( this );
+  hbl->setContentsMargins( 0, SPACING, 0, 0 );
+  hbl->setSpacing( SPACING );
+  hbl->addStretch();
+  hbl->addWidget( current );
+  hbl->addWidget( prev );
+  hbl->addWidget( next );
+}
+
+ExtraWidget::~ExtraWidget()
+{
+}
+
+void ExtraWidget::updateControls( int total, int index, int blockSize )
+{
+  setVisible( total > blockSize );
+  QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
+  current->setText( format.arg( index*blockSize+1 ).arg( qMin( index*blockSize+blockSize, total ) ).arg( total ) );
+  prev->setEnabled( index > 0 );
+  next->setEnabled( (index+1)*blockSize < total );
+}
 
 /*!
   \class SMESHGUI_MeshInfo
@@ -182,6 +232,10 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   myWidgets[21] << a3DHexPriLab << a3DHexPriTotal;
   myWidgets[22] << a3DPolLab << a3DPolTotal;
 
+  myLoadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
+  myLoadBtn->setAutoDefault( true );
+  connect( myLoadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
+  
   setFontAttributes( aNameLab,   Bold );
   setFontAttributes( aObjLab,    Bold );
   setFontAttributes( aNodesLab,  Bold );
@@ -254,11 +308,12 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   l->addWidget( a3DHexPriTotal, 21, 1 );
   l->addWidget( a3DPolLab,   22, 0 );
   l->addWidget( a3DPolTotal, 22, 1 );
+  l->addWidget( myLoadBtn,   23, 1, 1, 3 );
   l->setColumnStretch( 0, 0 );
   l->setColumnStretch( 1, 5 );
   l->setColumnStretch( 2, 5 );
   l->setColumnStretch( 3, 5 );
-  l->setRowStretch( 22, 5 );
+  l->setRowStretch( 23, 5 );
 
   clear();
 }
@@ -315,49 +370,156 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
       myWidgets[iObject][iSingle]->setProperty( "text", objType );
     }
     SMESH::long_array_var info = obj->GetMeshInfo();
-    myWidgets[iNodes][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Node] ) );
-    myWidgets[i0D][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_0D] ) );
+    myWidgets[iNodes][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Node] ) );
+    myWidgets[i0D][iTotal]    ->setProperty( "text", QString::number( info[SMDSEntity_0D] ) );
     long nbEdges = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
-    myWidgets[i1D][iTotal]->setProperty( "text", QString::number( nbEdges ) );
-    myWidgets[i1D][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Edge] ) );
+    myWidgets[i1D][iTotal]    ->setProperty( "text", QString::number( nbEdges ) );
+    myWidgets[i1D][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Edge] ) );
     myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Edge] ) );
     long nbTriangles   = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle];
     long nbQuadrangles = info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
     long nb2DLinear    = info[SMDSEntity_Triangle] + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
     long nb2DQuadratic = info[SMDSEntity_Quad_Triangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
-    myWidgets[i2D][iTotal]->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ) );
-    myWidgets[i2D][iLinear]->setProperty( "text", QString::number( nb2DLinear ) );
-    myWidgets[i2D][iQuadratic]->setProperty( "text", QString::number( nb2DQuadratic ) );
-    myWidgets[i2DTriangles][iTotal]->setProperty( "text", QString::number( nbTriangles ) );
-    myWidgets[i2DTriangles][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Triangle] ) );
-    myWidgets[i2DTriangles][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Triangle] ) );
-    myWidgets[i2DQuadrangles][iTotal]->setProperty( "text", QString::number( nbQuadrangles ) );
-    myWidgets[i2DQuadrangles][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
+    myWidgets[i2D][iTotal]               ->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ) );
+    myWidgets[i2D][iLinear]              ->setProperty( "text", QString::number( nb2DLinear ) );
+    myWidgets[i2D][iQuadratic]           ->setProperty( "text", QString::number( nb2DQuadratic ) );
+    myWidgets[i2DTriangles][iTotal]      ->setProperty( "text", QString::number( nbTriangles ) );
+    myWidgets[i2DTriangles][iLinear]     ->setProperty( "text", QString::number( info[SMDSEntity_Triangle] ) );
+    myWidgets[i2DTriangles][iQuadratic]  ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Triangle] ) );
+    myWidgets[i2DQuadrangles][iTotal]    ->setProperty( "text", QString::number( nbQuadrangles ) );
+    myWidgets[i2DQuadrangles][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
     myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle] ));
-    myWidgets[i2DPolygons][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
+    myWidgets[i2DPolygons][iTotal]       ->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
     long nbTetrahedrons = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra];
     long nbHexahedrons  = info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa];
     long nbPyramids     = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
     long nbPrisms       = info[SMDSEntity_Penta]   + info[SMDSEntity_Quad_Penta];
     long nb3DLinear     = info[SMDSEntity_Tetra] + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra] + info[SMDSEntity_Hexagonal_Prism];
     long nb3DQuadratic  = info[SMDSEntity_Quad_Tetra] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] + info[SMDSEntity_Quad_Pyramid] + info[SMDSEntity_Quad_Penta];
-    myWidgets[i3D][iTotal]->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
-    myWidgets[i3D][iLinear]->setProperty( "text", QString::number( nb3DLinear ) );
-    myWidgets[i3D][iQuadratic]->setProperty( "text", QString::number( nb3DQuadratic ) );
-    myWidgets[i3DTetrahedrons][iTotal]->setProperty( "text", QString::number( nbTetrahedrons ) );
-    myWidgets[i3DTetrahedrons][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Tetra] ) );
+    myWidgets[i3D][iTotal]                ->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
+    myWidgets[i3D][iLinear]               ->setProperty( "text", QString::number( nb3DLinear ) );
+    myWidgets[i3D][iQuadratic]            ->setProperty( "text", QString::number( nb3DQuadratic ) );
+    myWidgets[i3DTetrahedrons][iTotal]    ->setProperty( "text", QString::number( nbTetrahedrons ) );
+    myWidgets[i3DTetrahedrons][iLinear]   ->setProperty( "text", QString::number( info[SMDSEntity_Tetra] ) );
     myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Tetra] ) );
-    myWidgets[i3DHexahedrons][iTotal]->setProperty( "text", QString::number( nbHexahedrons ) );
-    myWidgets[i3DHexahedrons][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Hexa] ) );
-    myWidgets[i3DHexahedrons][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] ) );
-    myWidgets[i3DPyramids][iTotal]->setProperty( "text", QString::number( nbPyramids ) );
-    myWidgets[i3DPyramids][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Pyramid] ) );
-    myWidgets[i3DPyramids][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Pyramid] ) );
-    myWidgets[i3DPrisms][iTotal]->setProperty( "text", QString::number( nbPrisms ) );
-    myWidgets[i3DPrisms][iLinear]->setProperty( "text", QString::number( info[SMDSEntity_Penta] ) );
-    myWidgets[i3DPrisms][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
-    myWidgets[i3DHexaPrisms][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Hexagonal_Prism] ) );
-    myWidgets[i3DPolyhedrons][iTotal]->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
+    myWidgets[i3DHexahedrons][iTotal]     ->setProperty( "text", QString::number( nbHexahedrons ) );
+    myWidgets[i3DHexahedrons][iLinear]    ->setProperty( "text", QString::number( info[SMDSEntity_Hexa] ) );
+    myWidgets[i3DHexahedrons][iQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] ) );
+    myWidgets[i3DPyramids][iTotal]        ->setProperty( "text", QString::number( nbPyramids ) );
+    myWidgets[i3DPyramids][iLinear]       ->setProperty( "text", QString::number( info[SMDSEntity_Pyramid] ) );
+    myWidgets[i3DPyramids][iQuadratic]    ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Pyramid] ) );
+    myWidgets[i3DPrisms][iTotal]          ->setProperty( "text", QString::number( nbPrisms ) );
+    myWidgets[i3DPrisms][iLinear]         ->setProperty( "text", QString::number( info[SMDSEntity_Penta] ) );
+    myWidgets[i3DPrisms][iQuadratic]      ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
+    myWidgets[i3DHexaPrisms][iTotal]      ->setProperty( "text", QString::number( info[SMDSEntity_Hexagonal_Prism] ) );
+    myWidgets[i3DPolyhedrons][iTotal]     ->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
+
+    // before full loading from study file, type of elements in a sub-mesh can't be defined
+    // in some cases
+    bool infoOK = obj->IsMeshInfoCorrect();
+    myLoadBtn->setVisible( !infoOK );
+    if ( !infoOK )
+    {
+      // two options:
+      // 1. Type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
+      // 2. No info at all (for a group on geom or filter)
+      bool hasAnyInfo = false;
+      for ( size_t i = 0; i < info->length() && !hasAnyInfo; ++i )
+        hasAnyInfo = info[i];
+      if ( hasAnyInfo ) // believe it is a sub-mesh
+      {
+        if ( nb2DLinear + nb2DQuadratic > 0 )
+        {
+          myWidgets[i2D][iLinear]              ->setProperty( "text", "?" );
+          myWidgets[i2D][iQuadratic]           ->setProperty( "text", "?" );
+          myWidgets[i2DTriangles][iTotal]      ->setProperty( "text", "?" );
+          myWidgets[i2DTriangles][iLinear]     ->setProperty( "text", "?" );
+          myWidgets[i2DTriangles][iQuadratic]  ->setProperty( "text", "?" );
+          myWidgets[i2DQuadrangles][iTotal]    ->setProperty( "text", "?" );
+          myWidgets[i2DQuadrangles][iLinear]   ->setProperty( "text", "?" );
+          myWidgets[i2DQuadrangles][iQuadratic]->setProperty( "text", "?" );
+          myWidgets[i2DPolygons][iTotal]       ->setProperty( "text", "?" );
+        }
+        else if ( nb3DLinear + nb3DQuadratic > 0 )
+        {
+          myWidgets[i3D][iLinear]               ->setProperty( "text", "?" );
+          myWidgets[i3D][iQuadratic]            ->setProperty( "text", "?" );
+          myWidgets[i3DTetrahedrons][iTotal]    ->setProperty( "text", "?" );
+          myWidgets[i3DTetrahedrons][iLinear]   ->setProperty( "text", "?" );
+          myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", "?" );
+          myWidgets[i3DHexahedrons][iTotal]     ->setProperty( "text", "?" );
+          myWidgets[i3DHexahedrons][iLinear]    ->setProperty( "text", "?" );
+          myWidgets[i3DHexahedrons][iQuadratic] ->setProperty( "text", "?" );
+          myWidgets[i3DPyramids][iTotal]        ->setProperty( "text", "?" );
+          myWidgets[i3DPyramids][iLinear]       ->setProperty( "text", "?" );
+          myWidgets[i3DPyramids][iQuadratic]    ->setProperty( "text", "?" );
+          myWidgets[i3DPrisms][iTotal]          ->setProperty( "text", "?" );
+          myWidgets[i3DPrisms][iLinear]         ->setProperty( "text", "?" );
+          myWidgets[i3DPrisms][iQuadratic]      ->setProperty( "text", "?" );
+          myWidgets[i3DHexaPrisms][iTotal]      ->setProperty( "text", "?" );
+          myWidgets[i3DPolyhedrons][iTotal]     ->setProperty( "text", "?" );
+        }
+      }
+      else
+      {
+        myWidgets[iNodes][iTotal]             ->setProperty( "text", "?" );
+        myWidgets[i0D][iTotal]                ->setProperty( "text", "?" );
+        myWidgets[i1D][iTotal]                ->setProperty( "text", "?" );
+        myWidgets[i1D][iLinear]               ->setProperty( "text", "?" );
+        myWidgets[i1D][iQuadratic]            ->setProperty( "text", "?" );
+        myWidgets[i2D][iTotal]                ->setProperty( "text", "?" );
+        myWidgets[i2D][iLinear]               ->setProperty( "text", "?" );
+        myWidgets[i2D][iQuadratic]            ->setProperty( "text", "?" );
+        myWidgets[i2DTriangles][iTotal]       ->setProperty( "text", "?" );
+        myWidgets[i2DTriangles][iLinear]      ->setProperty( "text", "?" );
+        myWidgets[i2DTriangles][iQuadratic]   ->setProperty( "text", "?" );
+        myWidgets[i2DQuadrangles][iTotal]     ->setProperty( "text", "?" );
+        myWidgets[i2DQuadrangles][iLinear]    ->setProperty( "text", "?" );
+        myWidgets[i2DQuadrangles][iQuadratic] ->setProperty( "text", "?" );
+        myWidgets[i2DPolygons][iTotal]        ->setProperty( "text", "?" );
+        myWidgets[i3D][iTotal]                ->setProperty( "text", "?" );
+        myWidgets[i3D][iLinear]               ->setProperty( "text", "?" );
+        myWidgets[i3D][iQuadratic]            ->setProperty( "text", "?" );
+        myWidgets[i3DTetrahedrons][iTotal]    ->setProperty( "text", "?" );
+        myWidgets[i3DTetrahedrons][iLinear]   ->setProperty( "text", "?" );
+        myWidgets[i3DTetrahedrons][iQuadratic]->setProperty( "text", "?" );
+        myWidgets[i3DHexahedrons][iTotal]     ->setProperty( "text", "?" );
+        myWidgets[i3DHexahedrons][iLinear]    ->setProperty( "text", "?" );
+        myWidgets[i3DHexahedrons][iQuadratic] ->setProperty( "text", "?" );
+        myWidgets[i3DPyramids][iTotal]        ->setProperty( "text", "?" );
+        myWidgets[i3DPyramids][iLinear]       ->setProperty( "text", "?" );
+        myWidgets[i3DPyramids][iQuadratic]    ->setProperty( "text", "?" );
+        myWidgets[i3DPrisms][iTotal]          ->setProperty( "text", "?" );
+        myWidgets[i3DPrisms][iLinear]         ->setProperty( "text", "?" );
+        myWidgets[i3DPrisms][iQuadratic]      ->setProperty( "text", "?" );
+        myWidgets[i3DHexaPrisms][iTotal]      ->setProperty( "text", "?" );
+        myWidgets[i3DPolyhedrons][iTotal]     ->setProperty( "text", "?" );
+      }
+    }
+  }
+}
+
+/*!
+  \brief Load mesh from a study file
+*/
+void SMESHGUI_MeshInfo::loadMesh()
+{
+  SUIT_OverrideCursor wc;
+
+  SALOME_ListIO selected;
+  SMESHGUI::selectionMgr()->selectedObjects( selected );
+
+  if ( selected.Extent() == 1 ) {
+    Handle(SALOME_InteractiveObject) IO = selected.First();
+    SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
+    if ( !CORBA::is_nil( obj ) ) {
+      SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
+      if ( !mesh->_is_nil() )
+      {
+        mesh->Load();
+        showInfo( obj );
+      }
+    }
   }
 }
 
@@ -475,25 +637,14 @@ SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent )
 : QWidget( parent ), myActor( 0 ), myIsElement( -1 )
 {
   myFrame = new QWidget( this );
-  myExtra = new QWidget( this );
-  myCurrent = new QLabel( "10/43 items shown", myExtra );
-  myCurrent->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
-  myPrev = new QPushButton( tr( "<<" ), myExtra );
-  myNext = new QPushButton( tr( ">>" ), myExtra );
-  QHBoxLayout* hbl = new QHBoxLayout( myExtra );
-  hbl->setContentsMargins( 0, SPACING, 0, 0 );
-  hbl->setSpacing( SPACING );
-  hbl->addStretch();
-  hbl->addWidget( myCurrent );
-  hbl->addWidget( myPrev );
-  hbl->addWidget( myNext );
+  myExtra = new ExtraWidget( this );
   QVBoxLayout* vbl = new QVBoxLayout( this );
   vbl->setMargin( 0 );
   vbl->setSpacing( 0 );
   vbl->addWidget( myFrame );
   vbl->addWidget( myExtra );
-  connect( myPrev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
-  connect( myNext, SIGNAL( clicked() ), this, SLOT( showNext() ) );
+  connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
+  connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
   clear();
 }
 
@@ -682,10 +833,7 @@ void SMESHGUI_ElemInfo::showNext()
 */
 void SMESHGUI_ElemInfo::updateControls()
 {
-  myExtra->setVisible( myIDs.count() > MAXITEMS );
-  myCurrent->setText( tr( "X_FROM_Y_ITEMS_SHOWN" ).arg( myIndex*MAXITEMS+1 ).arg(qMin(myIndex*MAXITEMS+MAXITEMS, myIDs.count())).arg( myIDs.count() ) );
-  myPrev->setEnabled( myIndex > 0 );
-  myNext->setEnabled( (myIndex+1)*MAXITEMS < myIDs.count() );
+  myExtra->updateControls( myIDs.count(), myIndex );
 }
 
 /*!
@@ -1207,9 +1355,11 @@ GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* item,
 void GrpComputor::compute()
 {
   if ( !CORBA::is_nil( myGroup ) && myItem ) {
+    QTreeWidgetItem* item = myItem;
+    myItem = 0;
     int nbNodes = myGroup->GetNumberOfNodes();
-    myItem->treeWidget()->removeItemWidget( myItem, 1 );
-    myItem->setText( 1, QString::number( nbNodes ) );
+    item->treeWidget()->removeItemWidget( item, 1 );
+    item->setText( 1, QString::number( nbNodes ));
   }
 }
 
@@ -1244,8 +1394,9 @@ SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
 */
 void SMESHGUI_AddInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
 {
+  setProperty( "group_index", 0 );
+  setProperty( "submesh_index",  0 );
   myComputors.clear();
-
   clear();
 
   if ( CORBA::is_nil( obj ) ) return;
@@ -1330,70 +1481,12 @@ void SMESHGUI_AddInfo::meshInfo( SMESH::SMESH_Mesh_ptr mesh, QTreeWidgetItem* pa
   }
   
   // groups
-  SMESH::ListOfGroups_var groups = mesh->GetGroups();
-  QTreeWidgetItem* itemGroups  = 0;
-  QMap<int, QTreeWidgetItem*> grpItems;
-  for ( int i = 0; i < groups->length(); i++ ) {
-    SMESH::SMESH_GroupBase_var grp = groups[i];
-    if ( CORBA::is_nil( grp ) ) continue;
-    _PTR(SObject) grpSObj = SMESH::ObjectToSObject( grp );
-    if ( !grpSObj ) continue;
-
-    int grpType = grp->GetType();
-
-    if ( !itemGroups ) {
-      itemGroups = createItem( parent, Bold | All );
-      itemGroups->setText( 0, tr( "GROUPS" ) );
-    }
-
-    if ( grpItems.find( grpType ) == grpItems.end() ) {
-      grpItems[ grpType ] = createItem( itemGroups, Bold | All );
-      grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
-      itemGroups->insertChild( grpType-1, grpItems[ grpType ] );
-    }
-  
-    // group name
-    QTreeWidgetItem* grpNameItem = createItem( grpItems[ grpType ] );
-    grpNameItem->setText( 0, grpSObj->GetName().c_str() );
-
-    // group info
-    groupInfo( grp.in(), grpNameItem );
-  }
+  myGroups = mesh->GetGroups();
+  showGroups();
 
   // sub-meshes
-  SMESH::submesh_array_var subMeshes = mesh->GetSubMeshes();
-  QTreeWidgetItem* itemSubMeshes = 0;
-  QMap<int, QTreeWidgetItem*> smItems;
-  for ( int i = 0; i < subMeshes->length(); i++ ) {
-    SMESH::SMESH_subMesh_var sm = subMeshes[i];
-    if ( CORBA::is_nil( sm ) ) continue;
-    _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm );
-    if ( !smSObj ) continue;
-    
-    GEOM::GEOM_Object_var gobj = sm->GetSubShape();
-    if ( CORBA::is_nil(gobj ) ) continue;
-    
-    int smType = gobj->GetShapeType();
-    if ( smType == GEOM::COMPSOLID ) smType = GEOM::COMPOUND;
-
-    if ( !itemSubMeshes ) {
-      itemSubMeshes = createItem( parent, Bold | All );
-      itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
-    }
-         
-    if ( smItems.find( smType ) == smItems.end() ) {
-      smItems[ smType ] = createItem( itemSubMeshes, Bold | All );
-      smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
-      itemSubMeshes->insertChild( smType, smItems[ smType ] );
-    }
-    
-    // submesh name
-    QTreeWidgetItem* smNameItem = createItem( smItems[ smType ] );
-    smNameItem->setText( 0, smSObj->GetName().c_str() );
-    
-    // submesh info
-    subMeshInfo( sm.in(), smNameItem );
-  }
+  mySubMeshes = mesh->GetSubMeshes();
+  showSubMeshes();
 }
 
 /*!
@@ -1511,21 +1604,189 @@ void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetIte
     QTreeWidgetItem* nodesItem = createItem( parent, Bold );
     nodesItem->setText( 0, tr( "NB_NODES" ) );
     int nbNodesLimit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
-    bool hasNodes = grp->IsNodeInfoAvailable();
-    if ( hasNodes || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit ) {
+    SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
+    bool meshLoaded = mesh->IsLoaded();
+    bool toShowNodes = ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit );
+    if ( toShowNodes && meshLoaded ) {
       // already calculated and up-to-date
       nodesItem->setText( 1, QString::number( grp->GetNumberOfNodes() ) );
     }
     else {
-      QPushButton* btn = new QPushButton( tr( "COMPUTE" ), this );
+      QPushButton* btn = new QPushButton( tr( meshLoaded ? "COMPUTE" : "LOAD"), this );
       setItemWidget( nodesItem, 1, btn );
       GrpComputor* comp = new GrpComputor( grp, nodesItem, this ); 
       connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
       myComputors.append( comp );
+      if ( !meshLoaded )
+        connect( btn, SIGNAL( clicked() ), this, SLOT( changeLoadToCompute() ) );
     }
   }
 }
 
+void SMESHGUI_AddInfo::showGroups()
+{
+  myComputors.clear();
+
+  QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
+  if ( !parent ) return;
+
+  int idx = property( "group_index" ).toInt();
+
+  QTreeWidgetItem* itemGroups = 0;
+  for ( int i = 0; i < parent->childCount() && !itemGroups; i++ ) {
+    if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GROUPS_ID ) {
+      itemGroups = parent->child( i );
+      ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemGroups, 1 ) );
+      if ( extra )
+       extra->updateControls( myGroups->length(), idx );
+      while ( itemGroups->childCount() ) delete itemGroups->child( 0 ); // clear child items
+    }
+  }
+
+  QMap<int, QTreeWidgetItem*> grpItems;
+  for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)myGroups->length() ); i++ ) {
+    SMESH::SMESH_GroupBase_var grp = myGroups[i];
+    if ( CORBA::is_nil( grp ) ) continue;
+    _PTR(SObject) grpSObj = SMESH::ObjectToSObject( grp );
+    if ( !grpSObj ) continue;
+
+    int grpType = grp->GetType();
+
+    if ( !itemGroups ) {
+      // create top-level groups container item
+      itemGroups = createItem( parent, Bold | All );
+      itemGroups->setText( 0, tr( "GROUPS" ) );
+      itemGroups->setData( 0, Qt::UserRole, GROUPS_ID );
+
+      // total number of groups > 10, show extra widgets for info browsing
+      if ( myGroups->length() > MAXITEMS ) {
+       ExtraWidget* extra = new ExtraWidget( this, true );
+       connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
+       connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
+       setItemWidget( itemGroups, 1, extra );
+       extra->updateControls( myGroups->length(), idx );
+      }
+    }
+
+    if ( grpItems.find( grpType ) == grpItems.end() ) {
+      grpItems[ grpType ] = createItem( itemGroups, Bold | All );
+      grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
+      itemGroups->insertChild( grpType-1, grpItems[ grpType ] );
+    }
+  
+    // group name
+    QTreeWidgetItem* grpNameItem = createItem( grpItems[ grpType ] );
+    grpNameItem->setText( 0, QString( grpSObj->GetName().c_str() ).trimmed() ); // name is trimmed
+
+    // group info
+    groupInfo( grp.in(), grpNameItem );
+  }
+}
+
+void SMESHGUI_AddInfo::showSubMeshes()
+{
+  QTreeWidgetItem* parent = topLevelItemCount() > 0 ? topLevelItem( 0 ) : 0; // parent should be first top level item
+  if ( !parent ) return;
+
+  int idx = property( "submesh_index" ).toInt();
+
+  QTreeWidgetItem* itemSubMeshes = 0;
+  for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ ) {
+    if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SUBMESHES_ID ) {
+      itemSubMeshes = parent->child( i );
+      ExtraWidget* extra = dynamic_cast<ExtraWidget*>( itemWidget( itemSubMeshes, 1 ) );
+      if ( extra )
+       extra->updateControls( mySubMeshes->length(), idx );
+      while ( itemSubMeshes->childCount() ) delete itemSubMeshes->child( 0 ); // clear child items
+    }
+  }
+
+  QMap<int, QTreeWidgetItem*> smItems;
+  for ( int i = idx*MAXITEMS ; i < qMin( (idx+1)*MAXITEMS, (int)mySubMeshes->length() ); i++ ) {
+    SMESH::SMESH_subMesh_var sm = mySubMeshes[i];
+    if ( CORBA::is_nil( sm ) ) continue;
+    _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm );
+    if ( !smSObj ) continue;
+    
+    GEOM::GEOM_Object_var gobj = sm->GetSubShape();
+    if ( CORBA::is_nil(gobj ) ) continue;
+    
+    int smType = gobj->GetShapeType();
+    if ( smType == GEOM::COMPSOLID ) smType = GEOM::COMPOUND;
+
+    if ( !itemSubMeshes ) {
+      itemSubMeshes = createItem( parent, Bold | All );
+      itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
+      itemSubMeshes->setData( 0, Qt::UserRole, SUBMESHES_ID );
+
+      // total number of sub-meshes > 10, show extra widgets for info browsing
+      if ( mySubMeshes->length() > MAXITEMS ) {
+       ExtraWidget* extra = new ExtraWidget( this, true );
+       connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
+       connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
+       setItemWidget( itemSubMeshes, 1, extra );
+       extra->updateControls( mySubMeshes->length(), idx );
+      }
+    }
+         
+    if ( smItems.find( smType ) == smItems.end() ) {
+      smItems[ smType ] = createItem( itemSubMeshes, Bold | All );
+      smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
+      itemSubMeshes->insertChild( smType, smItems[ smType ] );
+    }
+    
+    // submesh name
+    QTreeWidgetItem* smNameItem = createItem( smItems[ smType ] );
+    smNameItem->setText( 0, QString( smSObj->GetName().c_str() ).trimmed() ); // name is trimmed
+    
+    // submesh info
+    subMeshInfo( sm.in(), smNameItem );
+  }
+}
+
+/*!
+ * \brief Change button label of "nb underlying node" group from "Load" to "Compute"
+ */
+void SMESHGUI_AddInfo::changeLoadToCompute()
+{
+  for ( int i = 0; i < myComputors.count(); ++i )
+  {
+    if ( QTreeWidgetItem* item = myComputors[i]->getItem() )
+    {
+      if ( QPushButton* btn = qobject_cast<QPushButton*>( itemWidget ( item, 1 ) ) )
+        btn->setText( tr("COMPUTE") );
+    }
+  }
+}
+
+void SMESHGUI_AddInfo::showPreviousGroups()
+{
+  int idx = property( "group_index" ).toInt();
+  setProperty( "group_index", idx-1 );
+  showGroups();
+}
+
+void SMESHGUI_AddInfo::showNextGroups()
+{
+  int idx = property( "group_index" ).toInt();
+  setProperty( "group_index", idx+1 );
+  showGroups();
+}
+
+void SMESHGUI_AddInfo::showPreviousSubMeshes()
+{
+  int idx = property( "submesh_index" ).toInt();
+  setProperty( "submesh_index", idx-1 );
+  showSubMeshes();
+}
+
+void SMESHGUI_AddInfo::showNextSubMeshes()
+{
+  int idx = property( "submesh_index" ).toInt();
+  setProperty( "submesh_index", idx+1 );
+  showSubMeshes();
+}
+
 /*!
   \class SMESHGUI_MeshInfoDlg
   \brief Mesh information dialog box
@@ -1638,7 +1899,7 @@ void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO
   if ( !CORBA::is_nil( obj ) ) {
     myBaseInfo->showInfo( obj );
     myAddInfo->showInfo( obj );
-    
+
     myActor = SMESH::FindActorByEntry( IO->getEntry() );
     SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
     QString ID;
@@ -1695,7 +1956,7 @@ void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
 */
 void SMESHGUI_MeshInfoDlg::enterEvent( QEvent* )
 {
-  activate();
+  //activate();
 }
 
 /*!