+ QString title;
+ switch ( control )
+ {
+ case SMESH::FT_AspectRatio:
+ title = tr( "ASPECTRATIO_ELEMENTS" ); break;
+ case SMESH::FT_AspectRatio3D:
+ title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
+ case SMESH::FT_Warping:
+ title = tr( "WARP_ELEMENTS" ); break;
+ case SMESH::FT_MinimumAngle:
+ title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
+ case SMESH::FT_Taper:
+ title = tr( "TAPER_ELEMENTS" ); break;
+ case SMESH::FT_Skew:
+ title = tr( "SKEW_ELEMENTS" ); break;
+ case SMESH::FT_Area:
+ title = tr( "AREA_ELEMENTS" ); break;
+ case SMESH::FT_Volume3D:
+ title = tr( "VOLUME_3D_ELEMENTS" ); break;
+ case SMESH::FT_MaxElementLength2D:
+ title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
+ case SMESH::FT_MaxElementLength3D:
+ title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
+ case SMESH::FT_Length:
+ title = tr( "LENGTH_EDGES" ); break;
+ case SMESH::FT_Length2D:
+ case SMESH::FT_Length3D:
+ title = tr( "MIN_ELEM_EDGE" ); break;
+ case SMESH::FT_BallDiameter:
+ title = tr( "BALL_DIAMETER" ); break;
+ default:
+ break;
+ }
+ return title;
+}
+
+/*!
+ \brief Write information on given mesh nodes / elements.
+ \param writer Information writer.
+ \param ids Nodes / elements IDs.
+*/
+void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
+{
+ if ( !proxy() )
+ return;
+
+ bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
+ int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ?
+ SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
+
+ SMESH::XYZ xyz;
+ SMESH::Connectivity connectivity;
+ SMESH::Position position;
+ bool ok;
+
+ foreach ( uint id, ids )
+ {
+ writer->separator();
+
+ if ( what() == ShowNodes )
+ {
+ // show node info
+ // - check that node exists
+ if ( !proxy().hasNode( id ) )
+ continue;
+ // - id
+ writer->write( tr( "NODE" ), (int)id, true );
+ writer->indent();
+ // - coordinates
+ ok = proxy().nodeCoordinates( id, xyz );
+ if ( ok )
+ {
+ writer->write( tr( "COORDINATES" ), xyz );
+ }
+ // - connectivity
+ ok = proxy().nodeConnectivity( id, connectivity );
+ if ( ok )
+ {
+ if ( !connectivity.isEmpty() )
+ {
+ writer->write( tr( "CONNECTIVITY" ) );
+ writer->indent();
+ for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
+ {
+ QString formatted = formatConnectivity( connectivity, i );
+ if ( !formatted.isEmpty() )
+ writer->write( type2str( i, true ), formatted );
+ }
+ writer->unindent();
+ }
+ else
+ {
+ writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
+ }
+ }
+ // - position
+ ok = proxy().nodePosition( id, position );
+ if ( ok && position.isValid() )
+ {
+ writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
+ writer->indent();
+ if ( position.hasU() )
+ writer->write( tr("U_POSITION"), position.u() );
+ if ( position.hasV() )
+ writer->write( tr("V_POSITION"), position.v() );
+ writer->unindent();
+ }
+ // - groups node belongs to
+ QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
+ bool topCreated = false;
+ foreach( SMESH::SelectionProxy group, groups )
+ {
+ if ( group && !group.name().isEmpty() )
+ {
+ if ( !topCreated )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
+ writer->indent();
+ topCreated = true;
+ }
+ writer->write( group.name().trimmed() ); // trim name
+ if ( grp_details )
+ {
+ writer->indent();
+ int type = group.type();
+ if ( type == SMESH::SelectionProxy::GroupStd )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
+ }
+ else if ( type == SMESH::SelectionProxy::GroupGeom )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
+ writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
+ }
+ else if ( type == SMESH::SelectionProxy::GroupFilter )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
+ }
+ int size = group.size();
+ if ( size != -1 );
+ writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
+ QColor color = group.color();
+ if ( color.isValid() )
+ writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
+ writer->unindent();
+ }
+ }
+ }
+ if ( topCreated )
+ writer->unindent();
+ writer->unindent();
+ }
+ else if ( what() == ShowElements )
+ {
+ // show element info
+ // - check that element exists
+ if ( !proxy().hasElement( id ) )
+ continue;
+ // - id & type
+ int type = proxy().elementType( id );
+ if ( type == SMESH::ALL )
+ continue;
+ writer->write( type2str( type ), (int)id, true );
+ writer->indent();
+ // - geometry type
+ type = proxy().elementEntityType( id );
+ writer->write( tr( "TYPE" ), etype2str( type ) );
+ // - connectivity
+ if ( type == SMESH::Entity_Polyhedra ||
+ type == SMESH::Entity_Quad_Polyhedra )
+ {
+ int nbNodes;
+ ok = proxy().perFaceConnectivity( id, connectivity, nbNodes );
+ if ( ok && !connectivity.isEmpty() )
+ {
+ writer->write( tr( "NB_NODES" ), nbNodes );
+ writer->write( tr( "CONNECTIVITY" ) );
+ writer->indent();
+ int nbFaces = connectivity.size();
+ for ( int iF = 1; iF <= nbFaces; ++iF )
+ {
+ QString formatted = formatConnectivity( connectivity, -iF );
+ writer->write(( type2str( SMDSAbs_Face, 0 ) + " %1 / %2" ).arg( iF ).arg( nbFaces ),
+ formatted );
+ }
+ writer->unindent();
+ }
+ }
+ else
+ {
+ ok = proxy().elementConnectivity( id, connectivity );
+ if ( ok && !connectivity.isEmpty() )
+ {
+ QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
+ if ( !formatted.isEmpty() )
+ {
+ writer->write( tr( "NB_NODES" ), connectivity[ SMDSAbs_Node ].size() );
+ writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
+ }
+ }
+ }
+ // - position
+ ok = proxy().elementPosition( id, position );
+ if ( ok && position.isValid() )
+ {
+ writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
+ }
+ // - gravity center
+ ok = proxy().elementGravityCenter( id, xyz );
+ if ( ok )
+ {
+ writer->write( tr( "GRAVITY_CENTER" ), xyz );
+ }
+ // - normal vector
+ ok = proxy().elementNormal( id, xyz );
+ if ( ok )
+ {
+ writer->write( tr( "NORMAL_VECTOR" ), xyz );
+ }
+ // - controls
+ bool topCreated = false;
+ for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
+ {
+ QString ctrlTitle = ctrl2str( i );
+ if ( ctrlTitle.isEmpty() )
+ continue;
+ if ( !topCreated )
+ {
+ writer->write( tr( "CONTROLS" ) );
+ writer->indent();
+ topCreated = true;
+ }
+ double value;
+ if ( proxy().elementControl( id, i, cprecision, value ) )
+ writer->write( ctrlTitle, value );
+ }
+ if ( topCreated )
+ writer->unindent();
+ // - groups element belongs to
+ QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
+ topCreated = false;
+ foreach( SMESH::SelectionProxy group, groups )
+ {
+ if ( group && !group.name().isEmpty() )
+ {
+ if ( !topCreated )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
+ writer->indent();
+ topCreated = true;
+ }
+ writer->write( group.name().trimmed() ); // trim name
+ if ( grp_details )
+ {
+ writer->indent();
+ int type = group.type();
+ if ( type == SMESH::SelectionProxy::GroupStd )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
+ }
+ else if ( type == SMESH::SelectionProxy::GroupGeom )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
+ writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
+ }
+ else if ( type == SMESH::SelectionProxy::GroupFilter )
+ {
+ writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
+ }
+ int size = group.size();
+ if ( size != -1 );
+ writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
+ QColor color = group.color();
+ if ( color.isValid() )
+ writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
+ writer->unindent();
+ }
+ }
+ }
+ if ( topCreated )
+ writer->unindent();
+ writer->unindent();
+ }
+ }
+}
+
+/*!
+ \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
+ \brief Show information on given mesh nodes / elements.
+
+ This function has to be redefined in sub-classes.
+
+ \param ids Nodes / elements IDs.
+*/
+
+/*!
+ \brief Internal clean-up (reset panel).
+
+ Default implementation does nothing; the method has to be redefined
+ in sub-classes to perform internal clean-up.
+*/
+void SMESHGUI_ElemInfo::clearInternal()
+{
+}
+
+/*!
+ \brief Show previous chunk of information.
+*/
+void SMESHGUI_ElemInfo::showPrevious()
+{
+ myIndex = qMax( 0, myIndex-1 );
+ updateControls();
+ information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
+}
+
+/*!
+ \brief Show next chunk of information.
+*/
+void SMESHGUI_ElemInfo::showNext()
+{
+ myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
+ updateControls();
+ information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
+}
+
+/*!
+ \brief Update control widget state.
+*/
+void SMESHGUI_ElemInfo::updateControls()
+{
+ myExtra->updateControls( myIDs.count(), myIndex );
+}
+
+/*!
+ \brief Write information from panel to ouput stream.
+ \param out Text stream output.
+*/
+void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
+{
+ // title
+ QString title = tr( "ELEM_INFO" );
+ out << ruler( title.size() ) << endl;
+ out << title << endl;
+ out << ruler( title.size() ) << endl;
+ // out << endl;
+
+ // info
+ StreamWriter writer( out );
+ writeInfo( &writer, myIDs );
+ out << endl;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_SimpleElemInfo
+/// \brief Show mesh element information in the simple text area.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \brief Constructor.
+ \param parent Parent widget. Defaults to 0.
+*/
+SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
+ : SMESHGUI_ElemInfo( parent )
+{
+ myInfo = new QTextBrowser( centralWidget() );
+ QVBoxLayout* l = new QVBoxLayout( centralWidget() );
+ l->setMargin( 0 );
+ l->addWidget( myInfo );
+
+ connect( myInfo, SIGNAL( anchorClicked(QUrl)), this, SLOT( connectivityClicked( QUrl )));
+}
+
+/*!
+ \brief Show mesh element information.
+ \param ids Nodes / elements IDs.
+*/
+void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
+{
+ clearInternal();
+ TextWriter writer( myInfo );
+ writeInfo( &writer, ids );
+}
+
+/*!
+ \brief Internal clean-up (reset widget)
+*/
+void SMESHGUI_SimpleElemInfo::clearInternal()
+{
+ myInfo->clear();
+}
+
+void SMESHGUI_SimpleElemInfo::connectivityClicked(const QUrl & url)
+{
+ int type = ( url.scheme()[0] == 'n' ) ? NodeConnectivity : ElemConnectivity;
+ QString ids = url.path(); // excess chars will be filtered off by SMESHGUI_IdValidator
+ emit( itemInfo( type, ids ));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_TreeElemInfo::ItemDelegate
+/// \brief Item delegate for tree mesh info widget.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
+{
+public:
+ ItemDelegate( QObject* );
+ QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
+};
+
+/*!
+ \brief Constructor.
+ \internal
+*/
+SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
+{
+}
+
+/*!
+ \brief Redefined from QItemDelegate.
+ \internal
+*/
+QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
+{
+ QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
+ if ( qobject_cast<QLineEdit*>( w ) )
+ qobject_cast<QLineEdit*>( w )->setReadOnly( true );
+ return w;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_TreeElemInfo::ItemCreator
+/// \brief Item creator for tree mesh info widget.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
+{
+ SMESHGUI_TreeElemInfo* myView;
+public:
+ ItemCreator( SMESHGUI_TreeElemInfo* );
+ QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
+};
+
+/*!
+ \brief Constructor.
+ \param view Parent view.
+ \internal
+*/
+SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
+{
+}
+
+/*!
+ \brief Create new tree item.
+ \param parent Parent tree item.
+ \param options Item options.
+ \return New tree widget item.
+ \internal
+*/
+QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
+{
+ return myView->createItem( parent, options );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_TreeElemInfo
+/// \brief Show mesh element information as the tree.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \brief Constructor.
+ \param parent Parent widget. Defaults to 0.
+*/
+SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
+ : SMESHGUI_ElemInfo( parent )
+{
+ myInfo = new QTreeWidget( centralWidget() );
+ myInfo->setColumnCount( 2 );
+ myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
+ myInfo->header()->setStretchLastSection( true );
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
+#else
+ myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
+#endif
+ myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
+ QVBoxLayout* l = new QVBoxLayout( centralWidget() );
+ l->setMargin( 0 );
+ l->addWidget( myInfo );
+ connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
+ connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
+ connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
+}
+
+/*!
+ \brief Show mesh element information.
+ \param ids Nodes / elements IDs.
+*/
+void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
+{
+ clearInternal();
+ TreeWriter writer( myInfo, new ItemCreator( this ) );
+ writeInfo( &writer, ids );
+}
+
+/*!
+ \brief Show node information
+ \param node mesh node for showing
+ \param index index of current node
+ \param nbNodes number of unique nodes in element
+ \param parentItem parent item of tree
+*/
+void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* node, int index,
+ int nbNodes, QTreeWidgetItem* parentItem )
+{
+ // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
+ // // node number and ID
+ // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
+ // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
+ // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
+ // nodeItem->setData( 1, TypeRole, ElemConnectivity );
+ // nodeItem->setData( 1, IdRole, node->GetID() );
+ // nodeItem->setExpanded( false );
+ // // node coordinates
+ // QTreeWidgetItem* coordItem = createItem( nodeItem );
+ // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
+ // QTreeWidgetItem* xItem = createItem( coordItem );
+ // xItem->setText( 0, "X" );
+ // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
+ // QTreeWidgetItem* yItem = createItem( coordItem );
+ // yItem->setText( 0, "Y" );
+ // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
+ // QTreeWidgetItem* zItem = createItem( coordItem );
+ // zItem->setText( 0, "Z" );
+ // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
+ // // node connectivity
+ // QTreeWidgetItem* nconItem = createItem( nodeItem );
+ // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
+ // Connectivity connectivity = nodeConnectivity( node );
+ // if ( !connectivity.isEmpty() ) {
+ // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
+ // if ( !con.isEmpty() ) {
+ // QTreeWidgetItem* i = createItem( nconItem );
+ // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
+ // i->setText( 1, con );
+ // }
+ // con = formatConnectivity( connectivity, SMDSAbs_Edge );
+ // if ( !con.isEmpty() ) {
+ // QTreeWidgetItem* i = createItem( nconItem );
+ // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
+ // i->setText( 1, con );
+ // i->setData( 1, TypeRole, NodeConnectivity );
+ // }
+ // con = formatConnectivity( connectivity, SMDSAbs_Ball );
+ // if ( !con.isEmpty() ) {
+ // QTreeWidgetItem* i = createItem( nconItem );
+ // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
+ // i->setText( 1, con );
+ // i->setData( 1, TypeRole, NodeConnectivity );
+ // }
+ // con = formatConnectivity( connectivity, SMDSAbs_Face );
+ // if ( !con.isEmpty() ) {
+ // QTreeWidgetItem* i = createItem( nconItem );
+ // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
+ // i->setText( 1, con );
+ // i->setData( 1, TypeRole, NodeConnectivity );
+ // }
+ // con = formatConnectivity( connectivity, SMDSAbs_Volume );
+ // if ( !con.isEmpty() ) {
+ // QTreeWidgetItem* i = createItem( nconItem );
+ // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
+ // i->setText( 1, con );
+ // i->setData( 1, TypeRole, NodeConnectivity );
+ // }
+ // }
+}
+/*!
+ \brief Internal clean-up (reset widget)
+*/
+void SMESHGUI_TreeElemInfo::clearInternal()
+{
+ myInfo->clear();
+ myInfo->repaint();
+}
+
+/*!
+ \brief Create new item and add it to the tree.
+ \param parent Parent tree widget item. Defaults to 0 (top-level item).
+ \param options Item flags. Defaults to 0 (none).
+ \return New tree widget item.
+*/
+QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
+{
+ QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
+ setTreeItemAttributes( item, options | Expanded | Editable );
+
+ if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
+ {
+ QString resName = expandedResource( parent );
+ parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
+ }
+
+ return item;
+}
+
+void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
+{
+ QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
+ if ( widgets.isEmpty() ) return;
+ QTreeWidgetItem* aTreeItem = widgets.first();
+ int type = aTreeItem->data( 1, TypeRole ).toInt();
+ if (( type == ElemConnectivity || type == NodeConnectivity ) &&
+ ( !aTreeItem->text( 1 ).isEmpty() ))
+ {
+ QMenu menu;
+ QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
+ if ( menu.exec( e->globalPos() ) == a )
+ emit( itemInfo( type, aTreeItem->text( 1 )) );
+ }
+}
+
+void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
+{
+ if ( theItem ) {
+ int type = theItem->data( 1, TypeRole ).toInt();
+ emit( itemInfo( type, theItem->text( 1 )) );
+ }
+}
+
+void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
+{
+ if ( theItem )
+ SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
+}
+
+QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
+{
+ return QString("Expanded_") + ( what()==ShowElements ? "E_" : "N_" ) + theItem->text(0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class InfoComputor
+/// \brief Mesh information computor.
+/// \internal
+///
+/// The class is created for different computation operations. Currently it is
+/// used to compute size and number of underlying nodes for given group.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \brief Constructor.
+ \param parent Parent object.
+ \param proxy Object to compute information on (group).
+ \param item Tree widget item, referenced by this computer.
+ \param operation Value to compute.
+ \internal
+*/
+InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
+ : QObject( parent ), myProxy( proxy ), myOperation( operation )
+{
+}
+
+/*!
+ \brief Compute requested information.
+ \internal
+*/
+void InfoComputor::compute()
+{
+ if ( myProxy )
+ {
+ SUIT_OverrideCursor wc;
+ myProxy.load();
+ switch ( myOperation )
+ {
+ case GrpSize:
+ myProxy.size( true ); // force size computation
+ emit computed();
+ break;
+ case GrpNbNodes:
+ myProxy.nbNodes( true ); // force size computation
+ emit computed();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_AddInfo
+/// \brief Show additional information on selected object.
+///
+/// Displays an additional information about selected object: mesh, sub-mesh
+/// or group.
+///
+/// \todo Rewrite saveInfo() method to print all data, not currently shown only.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \brief Constructor.
+ \param parent Parent widget. Defaults to 0.
+*/
+SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
+{
+ QVBoxLayout* l = new QVBoxLayout( this );
+ l->setMargin( 0 );
+ l->setSpacing( SPACING );
+
+ myTree = new QTreeWidget( this );
+
+ myTree->setColumnCount( 2 );
+ myTree->header()->setStretchLastSection( true );
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ myTree->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
+#else
+ myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
+#endif
+ myTree->header()->hide();
+
+ l->addWidget( myTree );
+}
+
+/*!
+ \brief Destructor.
+*/
+SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
+{
+}
+
+/*!
+ \brief Show information on given object.
+ \param proxy Object to show information on (mesh, sub-mesh, group).
+*/
+void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
+{
+ // reset panel
+ setProperty( "group_index", 0 );
+ setProperty( "submesh_index", 0 );
+ myComputors.clear();
+ myTree->clear();
+
+ // then fill panel with data if object is not null
+ if ( proxy )
+ {
+ myProxy = proxy;
+
+ // name
+ QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
+ nameItem->setText( 0, tr( "NAME" ) );
+ nameItem->setText( 1, proxy.name() );
+
+ // object info
+ if ( proxy.type() == SMESH::SelectionProxy::Mesh )
+ meshInfo( proxy, nameItem );
+ else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
+ subMeshInfo( proxy, nameItem );
+ else if ( proxy.type() >= SMESH::SelectionProxy::Group )
+ groupInfo( proxy, nameItem );
+ }
+}
+
+/*!
+ \brief Update information in panel.
+*/
+void SMESHGUI_AddInfo::updateInfo()
+{
+ showInfo( myProxy );
+}
+
+/*!
+ \brief Reset panel (clear all data).
+*/
+void SMESHGUI_AddInfo::clear()
+{
+ myTree->clear();
+}
+
+/*!
+ \brief Create new item and add it to the tree.
+ \param parent Parent tree widget item. Defaults to 0 (top-level item).
+ \param options Item flags. Defaults to 0 (none).
+ \return New tree widget item.
+*/
+QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
+{
+ QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
+ new QTreeWidgetItem( myTree->invisibleRootItem() );
+ setTreeItemAttributes( item, options | Expanded );
+ return item;
+}
+
+/*!
+ \brief Show information on mesh.
+ \param proxy Proxy object (mesh).
+ \param parent Parent tree item.
+*/
+void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
+{
+ if ( !proxy )
+ return;
+
+ QString shapeName = proxy.shapeName();
+ SMESH::MedInfo inf = proxy.medFileInfo();
+
+ // type
+ QTreeWidgetItem* typeItem = createItem( parent, Bold );
+ typeItem->setText( 0, tr( "TYPE" ) );
+ if ( !shapeName.isEmpty() )
+ {
+ typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
+ // shape
+ QTreeWidgetItem* gobjItem = createItem( parent, Bold );
+ gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
+ gobjItem->setText( 1, shapeName );
+ }
+ else if ( inf.isValid() )
+ {
+ typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
+ // med file information
+ QTreeWidgetItem* fileItem = createItem( parent, Bold );
+ fileItem->setText( 0, tr( "FILE_NAME" ) );
+ fileItem->setText( 1, inf.fileName() );
+ QTreeWidgetItem* sizeItem = createItem( parent, Bold );
+ sizeItem->setText( 0, tr( "FILE_SIZE" ) );
+ sizeItem->setText( 1, QString::number( inf.size() ) );
+ QTreeWidgetItem* versionItem = createItem( parent, Bold );
+ versionItem->setText( 0, tr( "FILE_VERSION" ) );
+ versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
+ }
+ else
+ {
+ typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
+ }
+
+ // groups
+ myGroups = proxy.groups();
+ showGroups();
+
+ // sub-meshes
+ mySubMeshes = proxy.submeshes();
+ showSubMeshes();
+}
+
+/*!
+ \brief Show information on sub-mesh.
+ \param proxy Proxy object (sub-mesh).
+ \param parent Parent tree item.
+*/
+void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
+{
+ if ( !proxy )
+ return;
+