+ 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;
+ 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;
+
+ bool isShort = parent->parent() != 0;
+
+ if ( !isShort )
+ {
+ // parent mesh
+ SMESH::SelectionProxy meshProxy = proxy.mesh();
+ if ( meshProxy )
+ {
+ QTreeWidgetItem* nameItem = createItem( parent, Bold );
+ nameItem->setText( 0, tr( "PARENT_MESH" ) );
+ nameItem->setText( 1, meshProxy.name() );
+ }
+ }
+
+ // shape
+ QString shapeName = proxy.shapeName();
+ if ( !shapeName.isEmpty() )
+ {
+ QTreeWidgetItem* gobjItem = createItem( parent, Bold );
+ gobjItem->setText( 1, shapeName );
+ }
+}
+
+/*!
+ \brief Show information on group.
+ \param proxy Proxy object (group).
+ \param parent Parent tree item.
+*/
+void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
+{
+ if ( !proxy )
+ return;
+
+ bool isShort = parent->parent() != 0;
+
+ if ( !isShort )
+ {
+ // parent mesh
+ SMESH::SelectionProxy meshProxy = proxy.mesh();
+ if ( meshProxy )
+ {
+ QTreeWidgetItem* nameItem = createItem( parent, Bold );
+ nameItem->setText( 0, tr( "PARENT_MESH" ) );
+ nameItem->setText( 1, meshProxy.name() );
+ }
+ }
+
+ // type
+ SMESH::SelectionProxy::Type type = proxy.type();
+ QTreeWidgetItem* typeItem = createItem( parent, Bold );
+ typeItem->setText( 0, tr( "TYPE" ) );
+ if ( type == SMESH::SelectionProxy::GroupStd )
+ {
+ typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
+ }
+ else if ( type == SMESH::SelectionProxy::GroupGeom )
+ {
+ typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
+ // shape
+ QTreeWidgetItem* gobjItem = createItem( parent, Bold );
+ gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
+ gobjItem->setText( 1, proxy.shapeName() );
+ }
+ else if ( type == SMESH::SelectionProxy::GroupFilter )
+ {
+ typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
+ }
+
+ // element type
+ int etype = proxy.groupElementType();
+ if ( !isShort )
+ {
+ QString typeName = tr( "UNKNOWN" );
+ switch( etype )
+ {
+ case SMESH::NODE:
+ typeName = tr( "NODE" );
+ break;
+ case SMESH::EDGE:
+ typeName = tr( "EDGE" );
+ break;
+ case SMESH::FACE:
+ typeName = tr( "FACE" );
+ break;
+ case SMESH::VOLUME:
+ typeName = tr( "VOLUME" );
+ break;
+ case SMESH::ELEM0D:
+ typeName = tr( "0DELEM" );
+ break;
+ case SMESH::BALL:
+ typeName = tr( "BALL" );
+ break;
+ default:
+ break;
+ }
+ QTreeWidgetItem* etypeItem = createItem( parent, Bold );
+ etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
+ etypeItem->setText( 1, typeName );
+ }
+
+ // size
+ // note: size is not computed for group on filter for performance reasons, see IPAL52831
+ bool meshLoaded = proxy.isMeshLoaded();
+ int size = proxy.size();
+
+ QTreeWidgetItem* sizeItem = createItem( parent, Bold );
+ sizeItem->setText( 0, tr( "SIZE" ) );
+ if ( size >= 0 )
+ {
+ sizeItem->setText( 1, QString::number( size ) );
+ }
+ else
+ {
+ QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
+ myTree->setItemWidget( sizeItem, 1, btn );
+ InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
+ connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
+ connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
+ myComputors.append( comp );
+ }
+
+ // color
+ QTreeWidgetItem* colorItem = createItem( parent, Bold );
+ colorItem->setText( 0, tr( "COLOR" ) );
+ colorItem->setBackground( 1, proxy.color() );
+
+ // nb of underlying nodes
+ if ( etype != SMESH::NODE )
+ {
+ QTreeWidgetItem* nodesItem = createItem( parent, Bold );
+ nodesItem->setText( 0, tr( "NB_NODES" ) );
+
+ int nbNodes = proxy.nbNodes();
+ if ( nbNodes >= 0 )
+ {
+ nodesItem->setText( 1, QString::number( nbNodes ) );
+ }
+ else
+ {
+ QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
+ myTree->setItemWidget( nodesItem, 1, btn );
+ InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
+ connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
+ connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
+ myComputors.append( comp );
+ }
+ }
+}
+
+/*!
+ \brief Update information on child groups.
+*/
+void SMESHGUI_AddInfo::showGroups()
+{
+ // remove all computors
+ myComputors.clear();
+
+ // tree root should be the first top level item
+ QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
+ if ( !parent )
+ return;
+
+ int idx = property( "group_index" ).toInt();
+
+ // find sub-meshes top-level container item
+ QTreeWidgetItem* itemGroups = 0;
+ for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
+ {
+ if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
+ {
+ itemGroups = parent->child( i );
+ // update controls
+ ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
+ if ( extra )
+ extra->updateControls( myGroups.count(), idx );
+ // clear: remove all group items
+ while ( itemGroups->childCount() )
+ delete itemGroups->child( 0 );
+ }
+ }
+
+ QMap<int, QTreeWidgetItem*> grpItems;
+ for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
+ {
+ SMESH::SelectionProxy grp = myGroups[i];
+ if ( !grp )
+ continue;
+
+ int grpType = grp.groupElementType();
+
+ // create top-level groups container item if it does not exist
+ if ( !itemGroups )
+ {
+ itemGroups = createItem( parent, Bold | AllColumns );
+ itemGroups->setText( 0, tr( "GROUPS" ) );
+ itemGroups->setData( 0, Qt::UserRole, GroupsId );
+
+ // if necessary, create extra widget to show information by chunks
+ if ( myGroups.count() > blockSize() )
+ {
+ ExtraWidget* extra = new ExtraWidget( this, true );
+ connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
+ connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
+ myTree->setItemWidget( itemGroups, 1, extra );
+ extra->updateControls( myGroups.count(), idx );
+ }
+ }
+
+ // create container item corresponding to particular element type
+ if ( !grpItems.contains( grpType ) )
+ {
+ grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
+ grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
+ itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
+ }
+
+ // name
+ QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
+ nameItem->setText( 0, grp.name().trimmed() ); // trim name
+
+ // group info
+ groupInfo( grp, nameItem );
+ }
+}
+
+/*!
+ \brief Update information on child sub-meshes.
+*/
+void SMESHGUI_AddInfo::showSubMeshes()
+{
+ // tree root should be the first top level item
+ QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
+ if ( !parent )
+ return;
+
+ int idx = property( "submesh_index" ).toInt();
+
+ // find sub-meshes top-level container item
+ QTreeWidgetItem* itemSubMeshes = 0;
+ for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
+ {
+ if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
+ {
+ itemSubMeshes = parent->child( i );
+ // update controls
+ ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
+ if ( extra )
+ extra->updateControls( mySubMeshes.count(), idx );
+ // clear: remove all sub-mesh items
+ while ( itemSubMeshes->childCount() )
+ delete itemSubMeshes->child( 0 );
+ }
+ }
+
+ QMap<int, QTreeWidgetItem*> smItems;
+ for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
+ {
+ SMESH::SelectionProxy sm = mySubMeshes[i];
+ if ( !sm )
+ continue;
+
+ int smType = sm.shapeType();
+ if ( smType < 0 )
+ continue;
+ else if ( smType == GEOM::COMPSOLID )
+ smType = GEOM::COMPOUND;
+
+ // create top-level sub-meshes container item if it does not exist
+ if ( !itemSubMeshes )
+ {
+ itemSubMeshes = createItem( parent, Bold | AllColumns );
+ itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
+ itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
+
+ // if necessary, create extra widget to show information by chunks
+ if ( mySubMeshes.count() > blockSize() )
+ {
+ ExtraWidget* extra = new ExtraWidget( this, true );
+ connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
+ connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
+ myTree->setItemWidget( itemSubMeshes, 1, extra );
+ extra->updateControls( mySubMeshes.count(), idx );
+ }
+ }
+
+ // create container item corresponding to particular shape type
+ if ( !smItems.contains( smType ) )
+ {
+ smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
+ smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
+ itemSubMeshes->insertChild( smType, smItems[ smType ] );
+ }
+
+ // name
+ QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
+ nameItem->setText( 0, sm.name().trimmed() ); // trim name
+
+ // submesh info
+ subMeshInfo( sm, nameItem );
+ }
+}
+
+/*!
+ \brief Show previous chunk of information on child groups.
+*/
+void SMESHGUI_AddInfo::showPreviousGroups()
+{
+ int idx = property( "group_index" ).toInt();
+ setProperty( "group_index", idx-1 );
+ showGroups();
+}
+
+/*!
+ \brief Show next chunk of information on child groups.
+*/
+void SMESHGUI_AddInfo::showNextGroups()
+{
+ int idx = property( "group_index" ).toInt();
+ setProperty( "group_index", idx+1 );
+ showGroups();
+}
+
+/*!
+ \brief Show previous chunk of information on child sub-meshes.
+*/
+void SMESHGUI_AddInfo::showPreviousSubMeshes()
+{
+ int idx = property( "submesh_index" ).toInt();
+ setProperty( "submesh_index", idx-1 );
+ showSubMeshes();
+}
+
+/*!
+ \brief Show next chunk of information on child sub-meshes.
+*/
+void SMESHGUI_AddInfo::showNextSubMeshes()
+{
+ int idx = property( "submesh_index" ).toInt();
+ setProperty( "submesh_index", idx+1 );
+ showSubMeshes();
+}
+
+/*!
+ \brief Write information from panel to ouput stream.
+ \param out Text stream output.
+*/
+void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
+{
+ // title
+ QString title = tr( "ADDITIONAL_INFO" );
+ out << ruler( title.size() ) << endl;
+ out << title << endl;
+ out << ruler( title.size() ) << endl;
+ out << endl;
+
+ // info
+ QTreeWidgetItemIterator it( myTree );
+ while ( *it )
+ {
+ if ( !( ( *it )->text(0) ).isEmpty() )
+ {
+ out << indent( itemDepth( *it ) ) << ( *it )->text(0);
+ if ( ( *it )->text(0) == tr( "COLOR" ) )
+ out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
+ else if ( !( ( *it )->text(1) ).isEmpty() )
+ out << ":" << spacing() << ( *it )->text(1);
+ out << endl;
+ }
+ ++it;
+ }
+ out << endl;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class GroupCombo
+/// \brief Customized combo box to manage list of mesh groups.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class GroupCombo: public QComboBox
+{
+ class Item: public QStandardItem
+ {
+ public:
+ SMESH::SelectionProxy myGroup;
+ Item( const SMESH::SelectionProxy& group )
+ {
+ myGroup = group;
+ setText( myGroup.name() );
+ }
+ SMESH::SelectionProxy group()
+ {
+ return myGroup;
+ }
+ };
+
+ SMESH::SelectionProxy myProxy;
+
+public:
+ GroupCombo( QWidget* );
+ void setSource( const SMESH::SelectionProxy& );
+ SMESH::SelectionProxy currentGroup() const;
+};
+
+/*!
+ \brief Contructor.
+ \param parent Parent widget.
+ \internal
+*/
+GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
+{
+ setModel( new QStandardItemModel( this ) );
+}
+
+/*!
+ \brief Set mesh source.
+ \param obj Mesh source.
+ \internal
+*/
+void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
+{
+ if ( myProxy == proxy )
+ return;
+
+ myProxy = proxy;
+
+ bool blocked = blockSignals( true );
+ QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
+ m->clear();
+
+ if ( myProxy )
+ {
+ if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
+ {
+ QList<SMESH::SelectionProxy> groups = myProxy.groups();
+ for ( int i = 0; i < groups.count(); ++i )
+ {
+ if ( groups[i] )
+ {
+ QString name = groups[i].name();
+ if ( !name.isEmpty() )
+ m->appendRow( new Item( groups[i] ) );
+ }
+ }
+ setCurrentIndex( -1 ); // for performance reasons
+ }
+ else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
+ {
+ m->appendRow( new Item( myProxy ) );
+ setCurrentIndex( 0 );
+ }
+ }
+
+ blockSignals( blocked );
+}
+
+/*!
+ \brief Get currently selected group.
+ \return Selected group.
+ \internal
+*/
+SMESH::SelectionProxy GroupCombo::currentGroup() const
+{
+ SMESH::SelectionProxy group;
+ QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
+ if ( currentIndex() >= 0 )
+ group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
+ return group;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_MeshInfoDlg
+/// \brief Mesh information dialog box
+///
+/// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
+/// \todo Add selection button to reactivate selection on move from other dlg.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \brief Constructor
+ \param parent Parent widget.
+ \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
+*/
+SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
+ : QDialog( parent )
+{
+ setModal( false );
+ setAttribute( Qt::WA_DeleteOnClose, true );
+ setWindowTitle( tr( "MESH_INFO" ) );
+ setSizeGripEnabled( true );
+
+ myTabWidget = new QTabWidget( this );
+
+ // base info
+
+ myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
+ myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
+
+ // elem info
+
+ QWidget* w = new QWidget( myTabWidget );
+
+ myMode = new QButtonGroup( this );
+ myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
+ myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
+ myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
+ myMode->button( NodeMode )->setChecked( true );
+ myID = new QLineEdit( w );
+ myID->setValidator( new SMESHGUI_IdValidator( this ) );
+ myGroups = new GroupCombo( w );
+ QStackedWidget* stack = new QStackedWidget( w );
+ stack->addWidget( myID );
+ stack->addWidget( myGroups );
+ myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
+ myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
+
+ int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
+ mode = qMin( 1, qMax( 0, mode ) );
+
+ if ( mode == 0 )
+ myElemInfo = new SMESHGUI_SimpleElemInfo( w );
+ else
+ myElemInfo = new SMESHGUI_TreeElemInfo( w );
+ stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+
+ QGridLayout* elemLayout = new QGridLayout( w );
+ elemLayout->setMargin( MARGIN );
+ elemLayout->setSpacing( SPACING );
+ elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
+ elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
+ elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
+ elemLayout->addWidget( stack, 0, 3 );
+ elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
+ elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
+
+ myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
+
+ // additional info
+
+ myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
+ myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
+
+ // controls info
+
+ myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
+ myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
+
+ // buttons
+
+ QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
+ okBtn->setAutoDefault( true );
+ okBtn->setDefault( true );
+ okBtn->setFocus();
+ QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
+ dumpBtn->setAutoDefault( true );
+ QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
+ helpBtn->setAutoDefault( true );
+
+ QHBoxLayout* btnLayout = new QHBoxLayout;
+ btnLayout->setSpacing( SPACING );
+ btnLayout->setMargin( 0 );
+
+ btnLayout->addWidget( okBtn );
+ btnLayout->addWidget( dumpBtn );
+ btnLayout->addStretch( 10 );
+ btnLayout->addWidget( helpBtn );
+
+ // arrange widgets
+
+ QVBoxLayout* l = new QVBoxLayout ( this );
+ l->setMargin( MARGIN );
+ l->setSpacing( SPACING );
+ l->addWidget( myTabWidget );
+ l->addLayout( btnLayout );
+
+ // set initial page
+
+ myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
+
+ // set-up connections
+
+ connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
+ connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
+ connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
+ connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
+ connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
+ connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
+ connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
+ connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
+ connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
+ connect( myElemInfo, SIGNAL( itemInfo( int, QString ) ), this, SLOT( showItemInfo( int, QString ) ) );
+ connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
+
+ // initialize
+
+ myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
+ updateSelection();
+}
+
+/*!
+ \brief Destructor.
+*/
+SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
+{
+ delete myIDPreview;
+}
+
+/*!
+ \brief Show mesh information on given object.
+ \param io Interactive object.
+*/
+void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
+{
+ if ( !io.IsNull() )
+ showInfo( SMESH::SelectionProxy( io ) );
+}
+
+/*!
+ \brief Show mesh information on given object.
+ \param proxy Selection proxy.
+*/
+void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
+{
+ SUIT_OverrideCursor wc;
+
+ if ( !proxy )
+ return;
+
+ myProxy = proxy;
+
+ SMESH::SMESH_IDSource_var obj = myProxy.object();
+
+ // "Base info" tab
+ myBaseInfo->showInfo( proxy );
+
+ // "Additional info" tab
+ myAddInfo->showInfo( proxy );
+
+ // "Quality info" tab
+ // Note: for performance reasons we update it only if it is currently active
+ if ( myTabWidget->currentIndex() == CtrlInfo )
+ myCtrlInfo->showInfo( proxy );
+
+ // "Element info" tab
+ myGroups->setSource( proxy );
+ if ( myMode->checkedId() == GroupMode ) {
+ SMESH::SelectionProxy group = myGroups->currentGroup();
+ if ( group )
+ myElemInfo->showInfo( group );
+ else
+ myElemInfo->clear();
+ }
+ else {
+ SVTK_Selector* selector = SMESH::GetSelector();
+ QString ID;
+ int nb = 0;
+ if ( myProxy.actor() && selector ) { //todo: actor()?
+ nb = myMode->checkedId() == NodeMode ?
+ SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
+ SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
+ }
+ if ( nb > 0 ) {
+ myID->setText( ID.trimmed() );
+ QSet<uint> ids;
+ QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
+ foreach ( ID, idTxt )
+ ids << ID.trimmed().toUInt();
+ myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
+ }
+ else {
+ myID->clear();
+ myElemInfo->clear();
+ }
+ }
+}
+
+/*!
+ \brief Update information.
+*/
+void SMESHGUI_MeshInfoDlg::updateInfo()
+{
+ SALOME_ListIO selected;
+ SMESHGUI::selectionMgr()->selectedObjects( selected );
+
+ if ( selected.Extent() == 1 )
+ showInfo( selected.First() );
+ else
+ showInfo( myProxy );
+}
+
+/*!
+ \brief Clean-up on dialog closing.
+*/
+void SMESHGUI_MeshInfoDlg::reject()
+{
+ LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
+ selMgr->clearFilters();
+ SMESH::SetPointRepresentation( false );
+ if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
+ viewWindow->SetSelectionMode( ActorSelection );
+ QDialog::reject();
+ myIDPreview->SetPointsLabeled( false );
+}
+
+/*!
+ \brief Process keyboard event.
+ \param e Key press event.
+*/
+void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
+{
+ QDialog::keyPressEvent( e );
+ if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
+ e->accept();
+ help();