1 // Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "SMESHGUI_MeshInfo.h"
25 #include "SMDS_Mesh.hxx"
26 #include "SMESH_Actor.h"
28 #include "SMESHGUI_FilterUtils.h"
29 #include "SMESHGUI_IdPreview.h"
30 #include "SMESHGUI_IdValidator.h"
31 #include "SMESHGUI_SpinBox.h"
32 #include "SMESHGUI_Utils.h"
33 #include "SMESHGUI_VTKUtils.h"
35 #include <SUIT_FileDlg.h>
36 #include <SUIT_OverrideCursor.h>
37 #include <SUIT_ResourceMgr.h>
38 #include <SUIT_Session.h>
39 #include <SVTK_ViewWindow.h>
40 #include <LightApp_SelectionMgr.h>
42 #include <SALOMEDSClient_Study.hxx>
44 #include <QApplication>
45 #include <QButtonGroup>
48 #include <QContextMenuEvent>
49 #include <QGridLayout>
50 #include <QHBoxLayout>
51 #include <QHeaderView>
52 #include <QItemDelegate>
57 #include <QPushButton>
58 #include <QRadioButton>
59 #include <QStackedWidget>
60 #include <QStandardItemModel>
62 #include <QTextBrowser>
63 #include <QTextStream>
64 #include <QToolButton>
65 #include <QTreeWidget>
66 #include <QVBoxLayout>
68 ////////////////////////////////////////////////////////////////////////////////
70 /// \brief FieldInfo widget.
72 ////////////////////////////////////////////////////////////////////////////////
74 class FieldInfo : public QLabel
77 FieldInfo( QWidget*, const QString& = QString() );
78 bool event( QEvent* );
83 \param parent Parent widget.
84 \param name FieldInfo name. Defaults to null string.
86 FieldInfo::FieldInfo( QWidget* parent, const QString& name ): QLabel( parent )
88 setFrameStyle( QLabel::StyledPanel | QLabel::Sunken );
89 setAlignment( Qt::AlignCenter );
90 setAutoFillBackground( true );
91 QPalette pal = palette();
92 QColor base = QApplication::palette().color( QPalette::Active, QPalette::Base );
93 pal.setColor( QPalette::Window, base );
95 setMinimumWidth( 60 );
96 if ( !name.isEmpty() )
97 setObjectName( name );
101 \brief Event handler. Redefined from QLabel.
103 bool FieldInfo::event( QEvent* e )
105 if ( e->type() == QEvent::DynamicPropertyChange )
107 QDynamicPropertyChangeEvent* ce = (QDynamicPropertyChangeEvent*)e;
108 if ( ce->propertyName() == "value" && property( "value" ).isValid() )
110 setText( QString::number( property( "value" ).toInt() ) );
111 setProperty( "value", QVariant() );
115 return QLabel::event( e );
118 ////////////////////////////////////////////////////////////////////////////////
119 /// \class TreeItemCreator
120 /// \brief Generic tree item creator.
122 ////////////////////////////////////////////////////////////////////////////////
124 class TreeItemCreator
128 virtual ~TreeItemCreator() {}
129 virtual QTreeWidgetItem* createItem( QTreeWidgetItem*, int ) = 0;
132 ////////////////////////////////////////////////////////////////////////////////
133 // General purpose services.
134 ////////////////////////////////////////////////////////////////////////////////
138 const int SPACING = 6;
139 const int MARGIN = 9;
158 TypeRole = Qt::UserRole + 10,
164 NodeConnectivity = 100,
169 \brief Get item's depth in the tree.
170 \param item Tree widget item.
171 \return Item's depth in the tree widget (top-level item has zero depth).
174 int itemDepth( QTreeWidgetItem* item )
176 QList<QTreeWidgetItem*> parents;
178 while ( parents.last()->parent() )
179 parents << parents.last()->parent();
180 return parents.size()-1;
184 \brief Get chunk size.
195 \return Spacer string.
201 static QChar spacer = ' ';
202 return QString( size, spacer );
207 \param length Indent size. Defaults to 1.
208 \return Indentation string.
211 QString indent( int length = 1 )
214 static QChar spacer = ' ';
215 return QString( size * length, spacer );
220 \param spacer Spacer.
221 \param length Indent size. Defaults to 1.
222 \return Indentation string.
225 QString indent( const QString& spacer, uint length = 1 )
228 while( length-- > 0 )
234 \brief Get group separator.
235 \param length Length of ruler (number of symbols). Defaults to 80.
236 \return Ruler string.
239 QString ruler( int length = 80 )
241 static QChar ruler = '-';
242 return QString( length, ruler );
246 \brief Get text value from label.
247 \param w Widget (QLabel).
248 \return Value string.
251 QString widgetValue( QWidget* w )
254 if ( qobject_cast<QLabel*>( w ) )
255 v = qobject_cast<QLabel*>( w )->text();
260 \brief Get font for given options.
261 \param font Initial font.
262 \param options Font attributes.
265 QFont fontFromOptions( const QFont& font, int options )
268 f.setBold( options & Bold );
269 f.setItalic( options & Italic );
274 \brief Set font attributes to given widget.
276 \param options Font attributes.
278 void setFontAttributes( QWidget* w, int options )
281 w->setFont( fontFromOptions( w->font(), options ) );
285 \brief Set attributes to given tree item.
286 \param item Tree widget item.
287 \param options Item attributes.
289 void setTreeItemAttributes( QTreeWidgetItem* item, int options )
291 if ( item && item->treeWidget() )
293 for ( int i = 0; i < item->treeWidget()->columnCount(); i++ )
295 if ( i == 0 || options & AllColumns )
296 item->setFont( i, fontFromOptions( item->font( 0 ), options) );
299 if ( options & Expanded )
300 item->setExpanded( true );
301 if ( options & Editable )
302 item->setFlags( item->flags() | Qt::ItemIsEditable );
307 \param parent Parent widget.
308 \param options Label options. Defaults to 0 (none).
311 QLabel* createLabel( QWidget* parent, int options = 0 )
313 QLabel* lab = new QLabel( parent );
314 setFontAttributes( lab, options );
320 \param text Label text.
321 \param parent Parent widget.
322 \param options Label options. Defaults to 0 (none).
325 QLabel* createLabel( const QString& text, QWidget* parent, int options = 0 )
327 QLabel* lab = createLabel( parent, options );
328 lab->setText( text );
333 \brief Create information field.
334 \param parent Parent widget.
335 \param name FieldInfo's object. Default to null string.
336 \return New FieldInfo.
338 QLabel* createField( QWidget* parent, const QString& name = QString() )
340 return new FieldInfo( parent, name );
344 \brief Create information field.
345 \param parent Parent widget.
346 \param options Label options.
347 \param name Field's object. Default to null string.
350 QLabel* createField( QWidget* parent, int options, const QString& name = QString() )
352 QLabel* field = createField( parent, name );
353 setFontAttributes( field, options );
359 \param parent Parent widget.
360 \param orientation Ruler orientation. Defaults to horizontal.
363 QWidget* createSeparator( QWidget* parent, Qt::Orientation orientation = Qt::Horizontal )
365 QFrame* line = new QFrame( parent );
366 line->setFrameShape( orientation == Qt::Horizontal ? QFrame::HLine : QFrame::HLine );
367 line->setFrameShadow( QFrame::Sunken );
372 \brief Decorate text as bold.
373 \param text Initial text.
374 \return Decorated text.
376 QString bold( const QString& text )
378 return QString("<b>%1</b>").arg( text );
382 \brief Format connectivity data to string representation.
383 \param connectivity Connectivity map.
384 \param type Element type or face index if negative
385 \return Stringified representation of the connectivity.
387 QString formatConnectivity( SMESH::Connectivity connectivity, int type )
391 bool isNodal = ( type == SMDSAbs_Node || type < 0 );
393 if ( connectivity.contains( type ))
395 QList<int> elements = connectivity[ type ];
396 if ( !isNodal ) // order of nodes is important
398 foreach( int id, elements )
399 str << QString::number( id );
401 // wrap IDs into an html link, to be treated by QTextBrowser used by SMESHGUI_SimpleElemInfo
402 QString s = str.join( " " );
403 result = ( "<a href = \"" + // URL:
404 QString( isNodal ? "nodes" : "elems" ) + "://" + // protocol
405 QString( "host.com/") + // QUrl return nothing if host missing
407 s + "</a>" ); // anchor text
411 } // end of anonymous namespace
413 ////////////////////////////////////////////////////////////////////////////////
414 /// \class SMESHGUI_Info
415 /// \brief Base widget for all information panes.
416 ////////////////////////////////////////////////////////////////////////////////
420 \param parent Parent widget. Defaults to 0.
422 SMESHGUI_Info::SMESHGUI_Info( QWidget* parent ): QWidget( parent )
426 ////////////////////////////////////////////////////////////////////////////////
427 /// \class ExtraWidget
428 /// \brief Auxiliary widget to browse between chunks of information.
430 ////////////////////////////////////////////////////////////////////////////////
432 class ExtraWidget : public QWidget
435 ExtraWidget( QWidget*, bool = false );
436 void updateControls( int, int );
447 \param parent Parent widget.
448 \param briefSummary Show summary in brief format. Defaults to \c false.
450 ExtraWidget::ExtraWidget( QWidget* parent, bool briefSummary ): QWidget( parent ), brief( briefSummary )
452 current = new QLabel( this );
453 current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
454 prev = new QPushButton( "<<", this );
455 next = new QPushButton( ">>", this );
456 QHBoxLayout* hbl = new QHBoxLayout( this );
458 hbl->setSpacing( SPACING );
460 hbl->addWidget( current );
461 hbl->addWidget( prev );
462 hbl->addWidget( next );
466 \brief Update controls.
467 \param total Total number of items.
468 \param index Current index.
470 void ExtraWidget::updateControls( int total, int index )
472 setVisible( total > blockSize() );
473 QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
474 current->setText( format.arg( index*blockSize()+1 ).arg( qMin( index*blockSize()+blockSize(), total ) ).arg( total ) );
475 prev->setEnabled( index > 0 );
476 next->setEnabled( (index+1)*blockSize() < total );
479 ////////////////////////////////////////////////////////////////////////////////
480 /// \class DumpFileDlg
481 /// \brief Standard Save File dialog box, customized for dump info operation.
483 ////////////////////////////////////////////////////////////////////////////////
485 class DumpFileDlg : public SUIT_FileDlg
487 QMap<int, QCheckBox*> myControls;
489 DumpFileDlg( QWidget*, bool = true );
490 bool isChecked( int ) const;
491 void setChecked( int, bool );
496 \param parent Parent widget.
497 \param showControls Show additional controls. Defaults to \c true.
500 DumpFileDlg::DumpFileDlg( QWidget* parent, bool showControls ): SUIT_FileDlg( parent, false, true, true )
504 QWidget* hB = new QWidget( this );
505 myControls[SMESHGUI_MeshInfoDlg::BaseInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_BASE_INFO" ), hB );
506 myControls[SMESHGUI_MeshInfoDlg::ElemInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ELEM_INFO" ), hB );
507 myControls[SMESHGUI_MeshInfoDlg::AddInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ADD_INFO" ), hB );
508 myControls[SMESHGUI_MeshInfoDlg::CtrlInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_CTRL_INFO" ), hB );
510 QGridLayout* layout = new QGridLayout( hB );
511 layout->setMargin( 0 );
512 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::BaseInfo], 0, 0 );
513 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::ElemInfo], 0, 1 );
514 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::AddInfo], 1, 0 );
515 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::CtrlInfo], 1, 1 );
517 addWidgets( 0, hB, 0 );
522 \brief Get control's value.
523 \param option Control identifier.
524 \return Control value.
527 bool DumpFileDlg::isChecked( int option ) const
529 return myControls.contains( option ) ? myControls[option]->isChecked() : false;
533 \brief Set control's initial value.
534 \param option Control identifier.
535 \param value Control value.
538 void DumpFileDlg::setChecked( int option, bool value )
540 if ( myControls.contains( option ) )
541 myControls[option]->setChecked( value );
544 ////////////////////////////////////////////////////////////////////////////////
545 /// \class SMESHGUI_BaseInfo
546 /// \brief Show basic information on selected object.
548 /// Displays the base information about selected object: mesh, sub-mesh, group
549 /// or arbitrary ID source.
550 /// \todo Hide unnecessary widgets (e.g. for mesh group).
551 ////////////////////////////////////////////////////////////////////////////////
555 \param parent Parent widget. Defaults to 0.
557 SMESHGUI_BaseInfo::SMESHGUI_BaseInfo( QWidget* parent ): SMESHGUI_Info( parent )
559 QGridLayout* l = new QGridLayout( this );
560 l->setMargin( MARGIN );
561 l->setSpacing( SPACING );
565 addWidget( createLabel( tr( "NAME_LAB" ), this, Bold ), iName, iLabel );
566 addWidget( createField( this, "meshName" ), iName, iSingle, 4 )->setMinimumWidth( 150 );
568 addWidget( createLabel( tr( "OBJECT_LAB" ), this, Bold ), iObject, iLabel );
569 addWidget( createField( this, "meshType" ), iObject, iSingle, 4 )->setMinimumWidth( 150 );
571 addWidget( createSeparator( this ), iObjectEnd, iLabel, 5 );
575 addWidget( createLabel( tr( "NODES_LAB" ), this, Bold ), iNodes, iLabel );
576 addWidget( createField( this, "nbNodes" ), iNodes, iTotal );
578 addWidget( createSeparator( this ), iNodesEnd, iLabel, 5 );
582 addWidget( createLabel( tr( "ELEMENTS_LAB" ), this, Bold ), iElementsTitle, iLabel );
583 addWidget( createLabel( tr( "TOTAL_LAB" ), this, Italic ), iElementsTitle, iTotal );
584 addWidget( createLabel( tr( "LINEAR_LAB" ), this, Italic ), iElementsTitle, iLinear );
585 addWidget( createLabel( tr( "QUADRATIC_LAB" ), this, Italic ), iElementsTitle, iQuadratic );
586 addWidget( createLabel( tr( "BI_QUADRATIC_LAB" ), this, Italic ), iElementsTitle, iBiQuadratic );
588 addWidget( createSeparator( this ), iElementsTitleEnd, iTotal, 4 );
590 addWidget( createField( this, "totalNbElems" ), iElementsTotal, iTotal );
591 addWidget( createField( this, "totalNbLinearElems" ), iElementsTotal, iLinear );
592 addWidget( createField( this, "totalNbQuadraticElems" ), iElementsTotal, iQuadratic );
593 addWidget( createField( this, "totalNbBiQuadraticElems" ), iElementsTotal, iBiQuadratic );
595 addWidget( createSeparator( this ), iElementsTotalEnd, iTotal, 4 );
596 // - 0D elements info
597 addWidget( createLabel( tr( "0D_LAB" ), this, Bold | Italic ), i0D, iLabel );
598 addWidget( createField( this, "nb0D" ), i0D, iTotal );
600 addWidget( createSeparator( this ), i0DEnd, iTotal, 4 );
602 addWidget( createLabel( tr( "BALL_LAB" ), this, Bold | Italic ), iBalls, iLabel );
603 addWidget( createField( this, "nbBall" ), iBalls, iTotal );
605 addWidget( createSeparator( this ), iBallsEnd, iTotal, 4 );
606 // - 1D elements info
607 addWidget( createLabel( tr( "1D_LAB" ), this, Bold | Italic ), i1D, iLabel );
608 addWidget( createField( this, "nb1D" ), i1D, iTotal );
609 addWidget( createField( this, "nbLinear1D" ), i1D, iLinear );
610 addWidget( createField( this, "nbQuadratic1D" ), i1D, iQuadratic );
612 addWidget( createSeparator( this ), i1DEnd, iTotal, 4 );
613 // - 2D elements info
615 addWidget( createLabel( tr( "2D_LAB" ), this, Bold | Italic ), i2D, iLabel );
616 addWidget( createField( this, "nb2D" ), i2D, iTotal );
617 addWidget( createField( this, "nbLinear2D" ), i2D, iLinear );
618 addWidget( createField( this, "nbQuadratic2D" ), i2D, iQuadratic );
619 addWidget( createField( this, "nbBiQuadratic2D" ), i2D, iBiQuadratic );
621 addWidget( createLabel( tr( "TRIANGLES_LAB" ), this, Italic ), i2DTriangles, iLabel );
622 addWidget( createField( this, Italic, "nbTriangle" ), i2DTriangles, iTotal );
623 addWidget( createField( this, Italic, "nbLinearTriangle" ), i2DTriangles, iLinear );
624 addWidget( createField( this, Italic, "nbQuadraticTriangle" ), i2DTriangles, iQuadratic );
625 addWidget( createField( this, Italic, "nbBiQuadraticTriangle" ), i2DTriangles, iBiQuadratic );
627 addWidget( createLabel( tr( "QUADRANGLES_LAB" ), this, Italic ), i2DQuadrangles, iLabel );
628 addWidget( createField( this, Italic, "nbQuadrangle" ), i2DQuadrangles, iTotal );
629 addWidget( createField( this, Italic, "nbLinearQuadrangle" ), i2DQuadrangles, iLinear );
630 addWidget( createField( this, Italic, "nbQuadraticQuadrangle" ), i2DQuadrangles, iQuadratic );
631 addWidget( createField( this, Italic, "nbBiQuadraticQuadrangle" ), i2DQuadrangles, iBiQuadratic );
633 addWidget( createLabel( tr( "POLYGONS_LAB" ), this, Italic ), i2DPolygons, iLabel );
634 addWidget( createField( this, Italic, "nbPolygon" ), i2DPolygons, iTotal );
635 addWidget( createField( this, Italic, "nbLinearPolygon" ), i2DPolygons, iLinear );
636 addWidget( createField( this, Italic, "nbQuadraticPolygon" ), i2DPolygons, iQuadratic );
638 addWidget( createSeparator( this ), i2DEnd, iTotal, 4 );
639 // - 3D elements info
641 addWidget( createLabel( tr( "3D_LAB" ), this, Bold | Italic ), i3D, iLabel );
642 addWidget( createField( this, "nb3D" ), i3D, iTotal );
643 addWidget( createField( this, "nbLinear3D" ), i3D, iLinear );
644 addWidget( createField( this, "nbQuadratic3D" ), i3D, iQuadratic );
645 addWidget( createField( this, "nbBiQuadratic3D" ), i3D, iBiQuadratic );
647 addWidget( createLabel( tr( "TETRAHEDRONS_LAB" ), this, Italic ), i3DTetrahedrons, iLabel );
648 addWidget( createField( this, Italic, "nbTetrahedron" ), i3DTetrahedrons, iTotal );
649 addWidget( createField( this, Italic, "nbLinearTetrahedron" ), i3DTetrahedrons, iLinear );
650 addWidget( createField( this, Italic, "nbQudraticTetrahedron" ), i3DTetrahedrons, iQuadratic );
652 addWidget( createLabel( tr( "HEXAHEDONRS_LAB" ), this, Italic ), i3DHexahedrons, iLabel );
653 addWidget( createField( this, Italic, "nbHexahedron" ), i3DHexahedrons, iTotal );
654 addWidget( createField( this, Italic, "nbLinearHexahedron" ), i3DHexahedrons, iLinear );
655 addWidget( createField( this, Italic, "nbQuadraticHexahedron" ), i3DHexahedrons, iQuadratic );
656 addWidget( createField( this, Italic, "nbBiQuadraticHexahedron" ), i3DHexahedrons, iBiQuadratic );
658 addWidget( createLabel( tr( "PYRAMIDS_LAB" ), this, Italic ), i3DPyramids, iLabel );
659 addWidget( createField( this, Italic, "nbPyramid" ), i3DPyramids, iTotal );
660 addWidget( createField( this, Italic, "nbLinearPyramid" ), i3DPyramids, iLinear );
661 addWidget( createField( this, Italic, "nbQuadraticPyramid" ), i3DPyramids, iQuadratic );
663 addWidget( createLabel( tr( "PRISMS_LAB" ), this, Italic ), i3DPrisms, iLabel );
664 addWidget( createField( this, Italic, "nbPrism" ), i3DPrisms, iTotal );
665 addWidget( createField( this, Italic, "nbLinearPrism" ), i3DPrisms, iLinear );
666 addWidget( createField( this, Italic, "nbQuadraticPrism" ), i3DPrisms, iQuadratic );
667 addWidget( createField( this, Italic, "nbBiQuadraticPrism" ), i3DPrisms, iBiQuadratic );
668 // --+ hexagonal prisms
669 addWidget( createLabel( tr( "HEX_PRISMS_LAB" ), this, Italic ), i3DHexaPrisms, iLabel );
670 addWidget( createField( this, Italic, "nbHexagonalPrism" ), i3DHexaPrisms, iTotal );
672 addWidget( createLabel( tr( "POLYHEDRONS_LAB" ), this, Italic ), i3DPolyhedrons, iLabel );
673 addWidget( createField( this, Italic, "nbPolyhedron" ), i3DPolyhedrons, iTotal );
676 QPushButton* loadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
677 loadBtn->setAutoDefault( true );
678 connect( loadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
679 addWidget( loadBtn, iEnd, iSingle, 4 );
681 // additional layout set-up
682 l->setColumnStretch( iLabel, 0 );
683 l->setColumnStretch( iTotal, 5 );
684 l->setColumnStretch( iLinear, 5 );
685 l->setColumnStretch( iQuadratic, 5 );
686 l->setColumnStretch( iBiQuadratic, 5 );
687 l->setRowStretch( iElementsEnd, 5 );
689 // set initial values
696 SMESHGUI_BaseInfo::~SMESHGUI_BaseInfo()
701 \brief Show information on given object.
702 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
704 void SMESHGUI_BaseInfo::showInfo( const SMESH::SelectionProxy& proxy )
709 // then fill panel with data if object is not null
714 SMESH::MeshInfo info = proxy.meshInfo();
718 widget( iName, iSingle )->setProperty( "text", proxy.name() );
721 SMESH::SelectionProxy::Type type = proxy.type();
722 if ( type == SMESH::SelectionProxy::Mesh )
724 typeName = tr( "OBJECT_MESH" );
726 else if ( type == SMESH::SelectionProxy::Submesh )
728 typeName = tr( "OBJECT_SUBMESH" );
730 else if ( type >= SMESH::SelectionProxy::Group )
732 switch( proxy.groupElementType() )
734 case SMESH::NODE: typeName = tr( "OBJECT_GROUP_NODES" ); break;
735 case SMESH::EDGE: typeName = tr( "OBJECT_GROUP_EDGES" ); break;
736 case SMESH::FACE: typeName = tr( "OBJECT_GROUP_FACES" ); break;
737 case SMESH::VOLUME: typeName = tr( "OBJECT_GROUP_VOLUMES" ); break;
738 case SMESH::ELEM0D: typeName = tr( "OBJECT_GROUP_0DELEMS" ); break;
739 case SMESH::BALL: typeName = tr( "OBJECT_GROUP_BALLS" ); break;
740 default: typeName = tr( "OBJECT_GROUP" ); break;
743 if ( type == SMESH::SelectionProxy::GroupStd )
744 subType = tr( "OBJECT_GROUP_STANDALONE" );
745 else if ( type == SMESH::SelectionProxy::GroupGeom )
746 subType = tr( "OBJECT_GROUP_GEOM" );
747 else if ( type == SMESH::SelectionProxy::GroupFilter )
748 subType = tr( "OBJECT_GROUP_FILTER" );
749 if ( !subType.isEmpty() )
750 typeName = QString( "%1 %2" ).arg( typeName, subType );
752 widget( iObject, iSingle )->setProperty( "text", typeName );
755 uint nbNodes = info[SMDSEntity_Node];
756 widget( iNodes, iTotal )->setProperty( "value", nbNodes );
759 // - 0D elements info
760 uint nb0d = info[SMDSEntity_0D];
761 widget( i0D, iTotal )->setProperty( "value", nb0d );
763 uint nbBalls = info[SMDSEntity_Ball];
764 widget( iBalls, iTotal )->setProperty( "value", nbBalls );
765 // - 1D elements info
766 uint nb1dLin = info[SMDSEntity_Edge];
767 uint nb1dQua = info[SMDSEntity_Quad_Edge];
768 uint nb1d = nb1dLin + nb1dQua;
769 widget( i1D, iLinear )->setProperty( "value", nb1dLin );
770 widget( i1D, iQuadratic )->setProperty( "value", nb1dQua );
771 widget( i1D, iTotal )->setProperty( "value", nb1d );
772 // - 2D elements info
774 uint nbTriLin = info[SMDSEntity_Triangle];
775 uint nbTriQua = info[SMDSEntity_Quad_Triangle];
776 uint nbTriBiq = info[SMDSEntity_BiQuad_Triangle];
777 uint nbTri = nbTriLin + nbTriQua + nbTriBiq;
778 widget( i2DTriangles, iLinear )->setProperty( "value", nbTriLin );
779 widget( i2DTriangles, iQuadratic )->setProperty( "value", nbTriQua );
780 widget( i2DTriangles, iBiQuadratic )->setProperty( "value", nbTriBiq );
781 widget( i2DTriangles, iTotal )->setProperty( "value", nbTri );
783 uint nbQuadLin = info[SMDSEntity_Quadrangle];
784 uint nbQuadQua = info[SMDSEntity_Quad_Quadrangle];
785 uint nbQuadBiq = info[SMDSEntity_BiQuad_Quadrangle];
786 uint nbQuad = nbQuadLin + nbQuadQua + nbQuadBiq;
787 widget( i2DQuadrangles, iLinear )->setProperty( "value", nbQuadLin );
788 widget( i2DQuadrangles, iQuadratic )->setProperty( "value", nbQuadQua );
789 widget( i2DQuadrangles, iBiQuadratic )->setProperty( "value", nbQuadBiq );
790 widget( i2DQuadrangles, iTotal )->setProperty( "value", nbQuad );
792 uint nbPolyLin = info[SMDSEntity_Polygon];
793 uint nbPolyQua = info[SMDSEntity_Quad_Polygon];
794 uint nbPoly = nbPolyLin + nbPolyQua;
795 widget( i2DPolygons, iLinear )->setProperty( "value", nbPolyLin );
796 widget( i2DPolygons, iQuadratic )->setProperty( "value", nbPolyQua );
797 widget( i2DPolygons, iTotal )->setProperty( "value", nbPoly );
799 uint nb2dLin = nbTriLin + nbQuadLin + nbPolyLin;
800 uint nb2dQua = nbTriQua + nbQuadQua + nbPolyQua;
801 uint nb2dBiq = nbTriBiq + nbQuadBiq;
802 uint nb2d = nb2dLin + nb2dQua + nb2dBiq;
803 widget( i2D, iLinear )->setProperty( "value", nb2dLin );
804 widget( i2D, iQuadratic )->setProperty( "value", nb2dQua );
805 widget( i2D, iBiQuadratic )->setProperty( "value", nb2dBiq );
806 widget( i2D, iTotal )->setProperty( "value", nb2d );
807 // - 3D elements info
809 uint nbTetraLin = info[SMDSEntity_Tetra];
810 uint nbTetraQua = info[SMDSEntity_Quad_Tetra];
811 uint nbTetra = nbTetraLin + nbTetraQua;
812 widget( i3DTetrahedrons, iLinear )->setProperty( "value", nbTetraLin );
813 widget( i3DTetrahedrons, iQuadratic )->setProperty( "value", nbTetraQua );
814 widget( i3DTetrahedrons, iTotal )->setProperty( "value", nbTetra );
816 uint nbHexaLin = info[SMDSEntity_Hexa];
817 uint nbHexaQua = info[SMDSEntity_Quad_Hexa];
818 uint nbHexaBiq = info[SMDSEntity_TriQuad_Hexa];
819 uint nbHexa = nbHexaLin + nbHexaQua + nbHexaBiq;
820 widget( i3DHexahedrons, iLinear )->setProperty( "value", nbHexaLin );
821 widget( i3DHexahedrons, iQuadratic )->setProperty( "value", nbHexaQua );
822 widget( i3DHexahedrons, iBiQuadratic )->setProperty( "value", nbHexaBiq );
823 widget( i3DHexahedrons, iTotal )->setProperty( "value", nbHexa );
825 uint nbPyraLin = info[SMDSEntity_Pyramid];
826 uint nbPyraQua = info[SMDSEntity_Quad_Pyramid];
827 uint nbPyra = nbPyraLin + nbPyraQua;
828 widget( i3DPyramids, iLinear )->setProperty( "value", nbPyraLin );
829 widget( i3DPyramids, iQuadratic )->setProperty( "value", nbPyraQua );
830 widget( i3DPyramids, iTotal )->setProperty( "value", nbPyra );
832 uint nbPentaLin = info[SMDSEntity_Penta];
833 uint nbPentaQua = info[SMDSEntity_Quad_Penta];
834 uint nbPentaBiq = info[SMDSEntity_BiQuad_Penta];
835 uint nbPenta = nbPentaLin + nbPentaQua + nbPentaBiq;
836 widget( i3DPrisms, iLinear )->setProperty( "value", nbPentaLin );
837 widget( i3DPrisms, iQuadratic )->setProperty( "value", nbPentaQua );
838 widget( i3DPrisms, iBiQuadratic )->setProperty( "value", nbPentaBiq );
839 widget( i3DPrisms, iTotal )->setProperty( "value", nbPenta );
840 // --+ hexagonal prisms
841 uint nbHexaPri = info[SMDSEntity_Hexagonal_Prism];
842 widget( i3DHexaPrisms, iTotal )->setProperty( "value", nbHexaPri );
844 uint nbPolyhedra = info[SMDSEntity_Polyhedra];
845 widget( i3DPolyhedrons, iTotal )->setProperty( "value", nbPolyhedra );
847 uint nb3dLin = nbTetraLin + nbHexaLin + nbPyraLin + nbPentaLin + nbHexaPri + nbPolyhedra;
848 uint nb3dQua = nbTetraQua + nbHexaQua + nbPyraQua + nbPentaQua;
849 uint nb3dBiq = nbHexaBiq + nbPentaBiq;
850 uint nb3d = nb3dLin + nb3dQua + nb3dBiq;
851 widget( i3D, iLinear )->setProperty( "value", nb3dLin );
852 widget( i3D, iQuadratic )->setProperty( "value", nb3dQua );
853 widget( i3D, iBiQuadratic )->setProperty( "value", nb3dBiq );
854 widget( i3D, iTotal )->setProperty( "value", nb3d );
856 uint nbElemLin = nb1dLin + nb2dLin + nb3dLin;
857 uint nbElemQua = nb1dQua + nb2dQua + nb3dQua;
858 uint nbElemBiq = nb2dBiq + nb3dBiq;
859 uint nbElem = nb0d + nbBalls + nb1d + nb2d + nb3d;
860 widget( iElementsTotal, iLinear )->setProperty( "value", nbElemLin );
861 widget( iElementsTotal, iQuadratic )->setProperty( "value", nbElemQua );
862 widget( iElementsTotal, iBiQuadratic )->setProperty( "value", nbElemBiq );
863 widget( iElementsTotal, iTotal )->setProperty( "value", nbElem );
865 // show 'Load' button if data was not loaded yet
866 widget( iEnd, iSingle )->setVisible( !proxy.isValid() );
868 // until data is loaded from study file, type of elements in a sub-mesh or group
869 // can be undefined in some cases
870 if ( !proxy.isValid() )
872 // two cases are possible:
873 // 1. type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
874 // 2. there is no info at all (for a group on geom or on filter)
875 if ( info.count( SMDSEntity_Node, SMDSEntity_Last ) > 0 ) // believe it is a sub-mesh
877 if ( nb2dLin + nb2dQua + nb2dBiq > 0 )
879 // we know nothing about triangles, quadranges and polygons
880 for ( int i = i2DTriangles; i < i2DEnd; i++ )
882 for ( int j = iTotal; j < iNbColumns; j++ )
884 if ( widget( i, j ) )
885 widget( i, j )->setProperty( "text", "?" );
888 // we don't know if elements are linear, quadratic or bi-quadratic
889 for ( int j = iLinear; j < iNbColumns; j++ )
891 if ( widget( i2D, j ) )
892 widget( i2D, j )->setProperty( "text", "?" );
893 if ( widget( iElementsTotal, j ) )
894 widget( iElementsTotal, j )->setProperty( "text", "?" );
897 else if ( nb3dLin + nb3dQua + nb3dBiq > 0 )
899 // we know nothing about tetras, hexas, etc.
900 for ( int i = i3DTetrahedrons; i < i3DEnd; i++ )
902 for ( int j = iTotal; j < iNbColumns; j++ )
904 if ( widget( i, j ) )
905 widget( i, j )->setProperty( "text", "?" );
908 // we don't know if elements are linear, quadratic or bi-quadratic
909 for ( int j = iLinear; j < iNbColumns; j++ )
911 if ( widget( i3D, j ) )
912 widget( i3D, j )->setProperty( "text", "?" );
913 if ( widget( iElementsTotal, j ) )
914 widget( iElementsTotal, j )->setProperty( "text", "?" );
920 // we know nothing about nodes :(
921 widget( iNodes, iTotal )->setProperty( "text", "?" );
922 // we know nothing about elements :(
923 for ( int i = iElementsTotal; i < iElementsEnd; i++ )
925 for ( int j = iTotal; j < iNbColumns; j++ )
927 if ( widget( i, j ) )
928 widget( i, j )->setProperty( "text", "?" );
937 \brief Update information in panel.
939 void SMESHGUI_BaseInfo::updateInfo()
945 \brief Load mesh from a study file.
947 void SMESHGUI_BaseInfo::loadMesh()
949 SUIT_OverrideCursor wc;
958 \brief Reset panel (clear all data).
960 void SMESHGUI_BaseInfo::clear()
963 widget( iName, iSingle )->setProperty( "text", QString() );
965 widget( iObject, iSingle )->setProperty( "text", QString() );
967 widget( iNodes, iTotal )->setProperty( "value", 0 );
969 for ( int i = iElementsTotal; i < iElementsEnd; i++ )
971 for ( int j = iTotal; j < iNbColumns; j++ )
973 if ( widget( i, j ) )
974 widget( i, j )->setProperty( "value", 0 );
977 // hide 'Load' button
978 widget( iEnd, iSingle )->setVisible( false );
982 \brief Register widget in a grid.
983 \param w Widget being added.
984 \param row Row index in a grid.
985 \param column Column index in a grid.
986 \param colspan Number of columns to span in a grid. Defaults to 1.
987 \return Just added widget.
989 QWidget* SMESHGUI_BaseInfo::addWidget( QWidget* w, int row, int column, int colspan )
991 if ( !myWidgets.contains( row ) )
992 myWidgets[row] = wlist();
993 myWidgets[row][column] = w;
994 dynamic_cast<QGridLayout*>( layout() )->addWidget( w, row, column, 1, colspan );
999 \brief Get registered widget.
1000 \param row Row index in a grid.
1001 \param column Column index in a grid.
1002 \return Widget stored in a given grid cell (0 if there's no widget).
1004 QWidget* SMESHGUI_BaseInfo::widget( int row, int column ) const
1006 return myWidgets.contains( row ) && myWidgets[row].contains( column ) ? myWidgets[row][column] : 0;
1010 \brief Get text value from registered widget.
1011 \param row Row index in a grid.
1012 \param column Column index in a grid.
1013 \return Value string (empty string if no label in given cell).
1015 QString SMESHGUI_BaseInfo::value( int row, int column ) const
1017 return widgetValue( widget( row, column ) );
1021 \brief Show/hide group(s) of widgets.
1022 \param startRow Starting grid row.
1023 \param lastRow Last grid row.
1024 \param on Visibility flag.
1026 void SMESHGUI_BaseInfo::setFieldsVisible( int startRow, int lastRow, bool on )
1028 startRow = qMax( 0, startRow );
1029 lastRow = qMin( lastRow, (int)iEnd );
1030 for ( int i = startRow; i <= lastRow; i++ )
1032 wlist widgets = myWidgets[i];
1033 foreach ( QWidget* w, widgets )
1034 w->setVisible( on );
1039 \brief Write information from panel to output stream.
1040 \param out Text stream output.
1042 void SMESHGUI_BaseInfo::saveInfo( QTextStream& out )
1045 QString title = tr( "BASE_INFO" );
1046 out << ruler( title.size() ) << endl;
1047 out << title << endl;
1048 out << ruler( title.size() ) << endl;
1053 out << tr( "NAME_LAB" ) << spacing() << value( iName, iSingle ) << endl;
1055 out << tr( "OBJECT_LAB" ) << spacing() << value( iObject, iSingle ) << endl;
1056 // - --- (separator)
1060 out << tr( "NODES_LAB" ) << spacing() << value( iNodes, iTotal ) << endl;
1061 // - --- (separator)
1065 QString lin = tr( "LINEAR_LAB" ) + ":" + spacing();
1066 QString qua = tr( "QUADRATIC_LAB" ) + ":" + spacing();
1067 QString biq = tr( "BI_QUADRATIC_LAB" ) + ":" + spacing();
1069 out << tr( "ELEMENTS_LAB" ) << spacing() << value( iElementsTotal, iTotal ) << endl;
1070 out << indent(1) << lin << value( iElementsTotal, iLinear ) << endl;
1071 out << indent(1) << qua << value( iElementsTotal, iQuadratic ) << endl;
1072 out << indent(1) << biq << value( iElementsTotal, iBiQuadratic ) << endl;
1073 // - --- (separator)
1075 // - 0D elements info
1076 out << indent(1) << tr( "0D_LAB" ) << spacing() << value( i0D, iTotal ) << endl;
1077 // - --- (separator)
1080 out << indent(1) << tr( "BALL_LAB" ) << spacing() << value( iBalls, iTotal ) << endl;
1081 // - --- (separator)
1083 // - 1D elements info
1084 out << indent(1) << tr( "1D_LAB" ) << spacing() << value( i1D, iTotal ) << endl;
1085 out << indent(2) << lin << value( i1D, iLinear ) << endl;
1086 out << indent(2) << qua << value( i1D, iQuadratic ) << endl;
1087 // - --- (separator)
1089 // - 2D elements info
1091 out << indent(1) << tr( "2D_LAB" ) << spacing() << value( i2D, iTotal ) << endl;
1092 out << indent(2) << lin << value( i2D, iLinear ) << endl;
1093 out << indent(2) << qua << value( i2D, iQuadratic ) << endl;
1094 out << indent(2) << biq << value( i2D, iBiQuadratic ) << endl;
1095 // - --- (separator)
1098 out << indent(2) << tr( "TRIANGLES_LAB" ) << spacing() << value( i2DTriangles, iTotal ) << endl;
1099 out << indent(3) << lin << value( i2DTriangles, iLinear ) << endl;
1100 out << indent(3) << qua << value( i2DTriangles, iQuadratic ) << endl;
1101 out << indent(3) << biq << value( i2DTriangles, iBiQuadratic ) << endl;
1103 out << indent(2) << tr( "QUADRANGLES_LAB" ) << spacing() << value( i2DQuadrangles, iTotal ) << endl;
1104 out << indent(3) << lin << value( i2DQuadrangles, iLinear ) << endl;
1105 out << indent(3) << qua << value( i2DQuadrangles, iQuadratic ) << endl;
1106 out << indent(3) << biq << value( i2DQuadrangles, iBiQuadratic ) << endl;
1108 out << indent(2) << tr( "POLYGONS_LAB" ) << spacing() << value( i2DPolygons, iTotal ) << endl;
1109 out << indent(3) << lin << value( i2DPolygons, iLinear ) << endl;
1110 out << indent(3) << qua << value( i2DPolygons, iQuadratic ) << endl;
1111 // - --- (separator)
1113 // - 3D elements info
1115 out << indent(1) << tr( "3D_LAB" ) << spacing() << value( i3D, iTotal ) << endl;
1116 out << indent(2) << lin << value( i3D, iLinear ) << endl;
1117 out << indent(2) << qua << value( i3D, iQuadratic ) << endl;
1118 out << indent(2) << biq << value( i3D, iBiQuadratic ) << endl;
1119 // - --- (separator)
1122 out << indent(2) << tr( "TETRAHEDRONS_LAB" ) << spacing() << value( i3DTetrahedrons, iTotal ) << endl;
1123 out << indent(3) << lin << value( i3DTetrahedrons, iLinear ) << endl;
1124 out << indent(3) << qua << value( i3DTetrahedrons, iQuadratic ) << endl;
1126 out << indent(2) << tr( "HEXAHEDONRS_LAB" ) << spacing() << value( i3DHexahedrons, iTotal ) << endl;
1127 out << indent(3) << lin << value( i3DHexahedrons, iLinear ) << endl;
1128 out << indent(3) << qua << value( i3DHexahedrons, iQuadratic ) << endl;
1129 out << indent(3) << biq << value( i3DHexahedrons, iBiQuadratic ) << endl;
1131 out << indent(2) << tr( "PYRAMIDS_LAB" ) << spacing() << value( i3DPyramids, iTotal ) << endl;
1132 out << indent(3) << lin << value( i3DPyramids, iLinear ) << endl;
1133 out << indent(3) << qua << value( i3DPyramids, iQuadratic ) << endl;
1135 out << indent(2) << tr( "PRISMS_LAB" ) << spacing() << value( i3DPrisms, iTotal ) << endl;
1136 out << indent(3) << lin << value( i3DPrisms, iLinear ) << endl;
1137 out << indent(3) << qua << value( i3DPrisms, iQuadratic ) << endl;
1138 out << indent(3) << biq << value( i3DPrisms, iBiQuadratic ) << endl;
1139 // --+ hexagonal prisms
1140 out << indent(2) << tr( "HEX_PRISMS_LAB" ) << spacing() << value( i3DHexaPrisms, iTotal ) << endl;
1142 out << indent(2) << tr( "POLYHEDRONS_LAB" ) << spacing() << value( i3DPolyhedrons, iTotal ) << endl;
1143 // - --- (separator)
1147 ////////////////////////////////////////////////////////////////////////////////
1148 /// \class InfoWriter
1149 /// \brief Base info writer class.
1151 ////////////////////////////////////////////////////////////////////////////////
1159 InfoWriter( bool = false );
1160 void write( const QString&, bool = false );
1161 void write( const QString&, const QString&, bool = false );
1162 void write( const QString&, int, bool = false );
1163 void write( const QString&, double, bool = false );
1164 void write( const QString&, const SMESH::XYZ&, bool = false );
1165 virtual void indent() {}
1166 virtual void unindent() {}
1167 virtual void separator() {}
1169 virtual void put( const QString&, const QString&, bool = false ) = 0;
1172 InfoWriter::InfoWriter( bool r ): myRecursive(r)
1174 myPrecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1177 void InfoWriter::write( const QString& key, bool emphasize )
1179 put( key, QString(), emphasize );
1182 void InfoWriter::write( const QString& key, const QString& value, bool emphasize )
1184 put( key, value, emphasize );
1187 void InfoWriter::write( const QString& key, int value, bool emphasize )
1189 put( key, QString::number( value ), emphasize );
1192 void InfoWriter::write( const QString& key, double value, bool emphasize )
1194 put( key, QString::number( value, myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) ), emphasize );
1197 void InfoWriter::write( const QString& key, const SMESH::XYZ& value, bool emphasize )
1201 write( key, emphasize );
1203 write( "X", value.x() );
1204 write( "Y", value.y() );
1205 write( "Z", value.z() );
1211 vl << QString::number( value.x(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1212 vl << QString::number( value.y(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1213 vl << QString::number( value.z(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1214 put( key, vl.join( ", " ), emphasize );
1218 ////////////////////////////////////////////////////////////////////////////////
1219 /// \class SimpleWriter
1220 /// \brief Base text writer.
1222 ////////////////////////////////////////////////////////////////////////////////
1224 class SimpleWriter: public InfoWriter
1234 void put( const QString&, const QString&, bool );
1235 virtual QString spacer() const;
1236 virtual QString decorate( const QString& ) const;
1237 virtual void dumpLine( const QString& ) = 0;
1240 SimpleWriter::SimpleWriter(): InfoWriter(false), myIndent(0)
1244 void SimpleWriter::indent()
1249 void SimpleWriter::unindent()
1251 myIndent = qMax( myIndent-1, 0 );
1254 void SimpleWriter::separator()
1259 QString SimpleWriter::spacer() const
1264 QString SimpleWriter::decorate( const QString& s ) const
1269 void SimpleWriter::put( const QString& key, const QString& value, bool emphasize )
1272 line += ::indent( spacer(), myIndent*4 );
1273 line += decorate( key );
1274 if ( !value.isEmpty() )
1277 line += emphasize ? decorate( value ) : value;
1282 ////////////////////////////////////////////////////////////////////////////////
1283 /// \class StreamWriter
1284 /// \brief Writer for QTextStream.
1286 ////////////////////////////////////////////////////////////////////////////////
1288 class StreamWriter: public SimpleWriter
1292 StreamWriter( QTextStream& );
1294 void dumpLine( const QString& );
1297 StreamWriter::StreamWriter( QTextStream& out ): SimpleWriter(), myOut(out)
1301 void StreamWriter::dumpLine( const QString& line )
1307 ////////////////////////////////////////////////////////////////////////////////
1308 /// \class TextWriter
1309 /// \brief Writer for QTextBrowser.
1311 ////////////////////////////////////////////////////////////////////////////////
1313 class TextWriter: public SimpleWriter
1315 QTextBrowser* myInfo;
1317 TextWriter( QTextBrowser* );
1319 QString spacer() const;
1320 QString decorate( const QString& ) const;
1321 void dumpLine( const QString& );
1324 TextWriter::TextWriter( QTextBrowser* w ): SimpleWriter(), myInfo(w)
1328 QString TextWriter::spacer() const
1333 QString TextWriter::decorate( const QString& s ) const
1338 void TextWriter::dumpLine( const QString& line )
1340 myInfo->append( line );
1343 ////////////////////////////////////////////////////////////////////////////////
1344 /// \class TreeWriter
1345 /// \brief Writer for QTreeWidget.
1347 ////////////////////////////////////////////////////////////////////////////////
1349 class TreeWriter: public InfoWriter
1351 QTreeWidget* myInfo;
1352 QTreeWidgetItem* myCurrentItem;
1353 TreeItemCreator* myCreator;
1355 TreeWriter( QTreeWidget*, TreeItemCreator* );
1360 void put( const QString&, const QString&, bool = false );
1363 TreeWriter::TreeWriter( QTreeWidget* w, TreeItemCreator* c ):
1364 InfoWriter(true), myInfo(w), myCurrentItem(0), myCreator(c)
1368 TreeWriter::~TreeWriter()
1373 void TreeWriter::put( const QString& key, const QString& value, bool emphasize )
1375 //std::string sss = myCurrentItem ? myCurrentItem->text(0).toStdString() : "";
1377 if ( emphasize ) options |= AllColumns;
1378 QTreeWidgetItem* item = myCreator->createItem( myCurrentItem, options );
1379 item->setText( 0, key );
1380 if ( !value.isEmpty() )
1382 QString val = value;
1383 if ( value.startsWith( "<a href" )) // connectivity encoded as: <a href = "nodes://host/1 2">1 2</a>
1385 int role = ( value[11] == 'n' ) ? NodeConnectivity : ElemConnectivity;
1386 val = value.mid( value.lastIndexOf( '>', -5 ) + 1 ); // ==> 1 2</a>
1388 item->setData( 1, TypeRole, role );
1390 item->setText( 1, val );
1394 void TreeWriter::indent()
1396 QTreeWidgetItem* item = myCurrentItem ? myCurrentItem : myInfo->invisibleRootItem();
1397 if ( item->childCount() > 0 )
1398 myCurrentItem = item->child( item->childCount()-1 );
1401 void TreeWriter::unindent()
1403 if ( myCurrentItem )
1404 myCurrentItem = myCurrentItem->parent();
1407 ////////////////////////////////////////////////////////////////////////////////
1408 /// \class SMESHGUI_ElemInfo
1409 /// \brief Base class for the mesh element information widget.
1411 /// Displays the detail information about given mesh node(s) or element(s).
1412 /// Default class does not provide working implementation but onle general
1413 /// functionalities; main work is done in sub-classes.
1414 ////////////////////////////////////////////////////////////////////////////////
1418 \param parent Parent widget. Defaults to 0.
1420 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent ): SMESHGUI_Info( parent ), myWhat( ShowNone )
1422 myFrame = new QWidget( this );
1423 myExtra = new ExtraWidget( this );
1425 QVBoxLayout* vbl = new QVBoxLayout( this );
1426 vbl->setMargin( 0 );
1427 vbl->setSpacing( SPACING );
1428 vbl->addWidget( myFrame );
1429 vbl->addWidget( myExtra );
1431 connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
1432 connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
1440 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
1445 \brief Show information on given node / element.
1446 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1447 \param id Mesh node / element ID.
1448 \param isElement If \c true, show element info; otherwise show node info.
1450 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, uint id, bool isElement )
1454 showInfo( proxy, ids, isElement );
1458 \brief Show information on given nodes / elements.
1459 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1460 \param ids Mesh nodes / elements IDs.
1461 \param isElement If \c true, show element info; otherwise show node info.
1463 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, QSet<uint> ids, bool isElement )
1471 QList<uint> newIds = ids.toList();
1473 int what = isElement ? ShowElements : ShowNodes;
1475 if ( myProxy == proxy && myIDs == newIds && myWhat == what )
1479 myProxy.refresh(); // try to re-initialize actor
1488 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1492 \brief Show information on given group.
1493 \param proxy Object to compute information on (group).
1495 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy )
1497 if ( !proxy || proxy.groupElementType() == SMESH::ALL ) // null proxy or not a group
1503 showInfo( proxy, proxy.ids(), proxy.groupElementType() != SMESH::NODE );
1507 \brief Reset panel (clear all data).
1509 void SMESHGUI_ElemInfo::clear()
1518 \brief Get central area widget.
1519 \return Central widget.
1521 QWidget* SMESHGUI_ElemInfo::centralWidget() const
1527 \brief Get current mesh proxy object information is shown on.
1528 \return Current proxy.
1530 SMESH::SelectionProxy SMESHGUI_ElemInfo::proxy() const
1536 \brief Get current info mode.
1537 \return Current panel mode.
1539 int SMESHGUI_ElemInfo::what() const
1545 \brief Get title for given element type.
1546 \param type Mesh element type.
1547 \param multiple Use plural form. Defaults to \c false.
1548 \return Element type's title.
1550 QString SMESHGUI_ElemInfo::type2str( int type, bool multiple )
1556 title = multiple ? tr( "EDGES" ) : tr( "EDGE" ) ; break;
1558 title = multiple ? tr( "FACES" ) : tr( "FACE" ); break;
1559 case SMDSAbs_Volume:
1560 title = multiple ? tr( "VOLUMES" ) : tr( "VOLUME" ); break;
1561 case SMDSAbs_0DElement:
1562 title = multiple ? tr( "0D_ELEMENTS" ) : tr( "0D_ELEMENT" ); break;
1564 title = multiple ? tr( "BALL_ELEMENTS" ) : tr( "BALL" ); break;
1572 \brief Get title for given shape type.
1573 \param type Shape type.
1574 \return Shape type's title.
1576 QString SMESHGUI_ElemInfo::stype2str( int type )
1582 title = tr( "GEOM_VERTEX" ); break;
1584 title = tr( "GEOM_EDGE" ); break;
1586 title = tr( "GEOM_FACE" ); break;
1589 title = tr( "GEOM_SOLID" ); break;
1596 \brief Get title for given element type.
1597 \param type Mesh element type.
1598 \return Element type's title.
1600 QString SMESHGUI_ElemInfo::etype2str( int type )
1605 case SMESH::Entity_0D:
1606 title = tr( "SMESH_ELEM0D" ); break;
1607 case SMESH::Entity_Edge:
1608 title = tr( "SMESH_EDGE" ); break;
1609 case SMESH::Entity_Quad_Edge:
1610 title = tr( "SMESH_QUADRATIC_EDGE" ); break;
1611 case SMESH::Entity_Triangle:
1612 title = tr( "SMESH_TRIANGLE" ); break;
1613 case SMESH::Entity_Quad_Triangle:
1614 title = tr( "SMESH_QUADRATIC_TRIANGLE" ); break;
1615 case SMESH::Entity_BiQuad_Triangle:
1616 title = tr( "SMESH_BIQUADRATIC_TRIANGLE" ); break;
1617 case SMESH::Entity_Quadrangle:
1618 title = tr( "SMESH_QUADRANGLE" ); break;
1619 case SMESH::Entity_Quad_Quadrangle:
1620 title = tr( "SMESH_QUADRATIC_QUADRANGLE" ); break;
1621 case SMESH::Entity_BiQuad_Quadrangle:
1622 title = tr( "SMESH_BIQUADRATIC_QUADRANGLE" ); break;
1623 case SMESH::Entity_Polygon:
1624 title = tr( "SMESH_POLYGON" ); break;
1625 case SMESH::Entity_Quad_Polygon:
1626 title = tr( "SMESH_QUADRATIC_POLYGON" ); break;
1627 case SMESH::Entity_Tetra:
1628 title = tr( "SMESH_TETRAHEDRON" ); break;
1629 case SMESH::Entity_Quad_Tetra:
1630 title = tr( "SMESH_QUADRATIC_TETRAHEDRON" ); break;
1631 case SMESH::Entity_Pyramid:
1632 title = tr( "SMESH_PYRAMID" ); break;
1633 case SMESH::Entity_Quad_Pyramid:
1634 title = tr( "SMESH_QUADRATIC_PYRAMID" ); break;
1635 case SMESH::Entity_Hexa:
1636 title = tr( "SMESH_HEXAHEDRON" ); break;
1637 case SMESH::Entity_Quad_Hexa:
1638 title = tr( "SMESH_QUADRATIC_HEXAHEDRON" ); break;
1639 case SMESH::Entity_TriQuad_Hexa:
1640 title = tr( "SMESH_TRIQUADRATIC_HEXAHEDRON" ); break;
1641 case SMESH::Entity_Penta:
1642 title = tr( "SMESH_PENTA" ); break;
1643 case SMESH::Entity_Quad_Penta:
1644 title = tr( "SMESH_QUADRATIC_PENTAHEDRON" ); break;
1645 case SMESH::Entity_BiQuad_Penta:
1646 title = tr( "SMESH_BIQUADRATIC_PENTAHEDRON" ); break;
1647 case SMESH::Entity_Hexagonal_Prism:
1648 title = tr( "SMESH_HEX_PRISM" ); break;
1649 case SMESH::Entity_Polyhedra:
1650 title = tr( "SMESH_POLYEDRON" ); break;
1651 case SMESH::Entity_Quad_Polyhedra:
1652 title = tr( "SMESH_QUADRATIC_POLYEDRON" ); break;
1653 case SMESH::Entity_Ball:
1654 title = tr( "SMESH_BALL" ); break;
1662 \brief Get title for given quality control.
1663 \param type Mesh control type.
1664 \return Quality control's title.
1666 QString SMESHGUI_ElemInfo::ctrl2str( int control )
1671 case SMESH::FT_AspectRatio:
1672 title = tr( "ASPECTRATIO_ELEMENTS" ); break;
1673 case SMESH::FT_AspectRatio3D:
1674 title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
1675 case SMESH::FT_Warping:
1676 title = tr( "WARP_ELEMENTS" ); break;
1677 case SMESH::FT_Warping3D:
1678 title = tr( "WARP_3D_ELEMENTS" ); break;
1679 case SMESH::FT_MinimumAngle:
1680 title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
1681 case SMESH::FT_Taper:
1682 title = tr( "TAPER_ELEMENTS" ); break;
1683 case SMESH::FT_Skew:
1684 title = tr( "SKEW_ELEMENTS" ); break;
1685 case SMESH::FT_Area:
1686 title = tr( "AREA_ELEMENTS" ); break;
1687 case SMESH::FT_Volume3D:
1688 title = tr( "VOLUME_3D_ELEMENTS" ); break;
1689 case SMESH::FT_ScaledJacobian:
1690 title = tr( "SCALED_JACOBIAN" ); break;
1691 case SMESH::FT_MaxElementLength2D:
1692 title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
1693 case SMESH::FT_MaxElementLength3D:
1694 title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
1695 case SMESH::FT_Length:
1696 title = tr( "LENGTH_EDGES" ); break;
1697 case SMESH::FT_Length2D:
1698 case SMESH::FT_Length3D:
1699 title = tr( "MIN_ELEM_EDGE" ); break;
1700 case SMESH::FT_BallDiameter:
1701 title = tr( "BALL_DIAMETER" ); break;
1709 \brief Write information on given mesh nodes / elements.
1710 \param writer Information writer.
1711 \param ids Nodes / elements IDs.
1713 void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
1718 bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1719 int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ?
1720 SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
1723 SMESH::Connectivity connectivity;
1724 SMESH::Position position;
1727 foreach ( uint id, ids )
1729 writer->separator();
1731 if ( what() == ShowNodes )
1734 // - check that node exists
1735 if ( !proxy().hasNode( id ) )
1738 writer->write( tr( "NODE" ), (int)id, true );
1741 ok = proxy().nodeCoordinates( id, xyz );
1744 writer->write( tr( "COORDINATES" ), xyz );
1747 ok = proxy().nodeConnectivity( id, connectivity );
1750 if ( !connectivity.isEmpty() )
1752 writer->write( tr( "CONNECTIVITY" ) );
1754 for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
1756 QString formatted = formatConnectivity( connectivity, i );
1757 if ( !formatted.isEmpty() )
1758 writer->write( type2str( i, true ), formatted );
1764 writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
1768 ok = proxy().nodePosition( id, position );
1769 if ( ok && position.isValid() )
1771 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1773 if ( position.hasU() )
1774 writer->write( tr("U_POSITION"), position.u() );
1775 if ( position.hasV() )
1776 writer->write( tr("V_POSITION"), position.v() );
1779 // - groups node belongs to
1780 QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
1781 bool topCreated = false;
1782 foreach( SMESH::SelectionProxy group, groups )
1784 if ( group && !group.name().isEmpty() )
1788 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1792 writer->write( group.name().trimmed() ); // trim name
1796 int type = group.type();
1797 if ( type == SMESH::SelectionProxy::GroupStd )
1799 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1801 else if ( type == SMESH::SelectionProxy::GroupGeom )
1803 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1804 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1806 else if ( type == SMESH::SelectionProxy::GroupFilter )
1808 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1810 int size = group.size();
1812 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1813 QColor color = group.color();
1814 if ( color.isValid() )
1815 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1824 else if ( what() == ShowElements )
1826 // show element info
1827 // - check that element exists
1828 if ( !proxy().hasElement( id ) )
1831 int type = proxy().elementType( id );
1832 if ( type == SMESH::ALL )
1834 writer->write( type2str( type ), (int)id, true );
1837 type = proxy().elementEntityType( id );
1838 writer->write( tr( "TYPE" ), etype2str( type ) );
1840 if ( type == SMESH::Entity_Polyhedra ||
1841 type == SMESH::Entity_Quad_Polyhedra )
1844 ok = proxy().perFaceConnectivity( id, connectivity, nbNodes );
1845 if ( ok && !connectivity.isEmpty() )
1847 writer->write( tr( "NB_NODES" ), nbNodes );
1848 writer->write( tr( "CONNECTIVITY" ) );
1850 int nbFaces = connectivity.size();
1851 for ( int iF = 1; iF <= nbFaces; ++iF )
1853 QString formatted = formatConnectivity( connectivity, -iF );
1854 writer->write(( type2str( SMDSAbs_Face, 0 ) + " %1 / %2" ).arg( iF ).arg( nbFaces ),
1862 ok = proxy().elementConnectivity( id, connectivity );
1863 if ( ok && !connectivity.isEmpty() )
1865 QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
1866 if ( !formatted.isEmpty() )
1868 writer->write( tr( "NB_NODES" ), connectivity[ SMDSAbs_Node ].size() );
1869 writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
1874 ok = proxy().elementPosition( id, position );
1875 if ( ok && position.isValid() )
1877 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1880 ok = proxy().elementGravityCenter( id, xyz );
1883 writer->write( tr( "GRAVITY_CENTER" ), xyz );
1886 ok = proxy().elementNormal( id, xyz );
1889 writer->write( tr( "NORMAL_VECTOR" ), xyz );
1892 bool topCreated = false;
1893 for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
1895 QString ctrlTitle = ctrl2str( i );
1896 if ( ctrlTitle.isEmpty() )
1900 writer->write( tr( "CONTROLS" ) );
1905 if ( proxy().elementControl( id, i, cprecision, value ) )
1906 writer->write( ctrlTitle, value );
1910 // - groups element belongs to
1911 QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
1913 foreach( SMESH::SelectionProxy group, groups )
1915 if ( group && !group.name().isEmpty() )
1919 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1923 writer->write( group.name().trimmed() ); // trim name
1927 int type = group.type();
1928 if ( type == SMESH::SelectionProxy::GroupStd )
1930 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1932 else if ( type == SMESH::SelectionProxy::GroupGeom )
1934 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1935 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1937 else if ( type == SMESH::SelectionProxy::GroupFilter )
1939 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1941 int size = group.size();
1943 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1944 QColor color = group.color();
1945 if ( color.isValid() )
1946 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1959 \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
1960 \brief Show information on given mesh nodes / elements.
1962 This function has to be redefined in sub-classes.
1964 \param ids Nodes / elements IDs.
1968 \brief Internal clean-up (reset panel).
1970 Default implementation does nothing; the method has to be redefined
1971 in sub-classes to perform internal clean-up.
1973 void SMESHGUI_ElemInfo::clearInternal()
1978 \brief Show previous chunk of information.
1980 void SMESHGUI_ElemInfo::showPrevious()
1982 myIndex = qMax( 0, myIndex-1 );
1984 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1988 \brief Show next chunk of information.
1990 void SMESHGUI_ElemInfo::showNext()
1992 myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
1994 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1998 \brief Update control widget state.
2000 void SMESHGUI_ElemInfo::updateControls()
2002 myExtra->updateControls( myIDs.count(), myIndex );
2006 \brief Write information from panel to output stream.
2007 \param out Text stream output.
2009 void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
2012 QString title = tr( "ELEM_INFO" );
2013 out << ruler( title.size() ) << endl;
2014 out << title << endl;
2015 out << ruler( title.size() ) << endl;
2019 StreamWriter writer( out );
2020 writeInfo( &writer, myIDs );
2024 ////////////////////////////////////////////////////////////////////////////////
2025 /// \class SMESHGUI_SimpleElemInfo
2026 /// \brief Show mesh element information in the simple text area.
2027 ////////////////////////////////////////////////////////////////////////////////
2031 \param parent Parent widget. Defaults to 0.
2033 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
2034 : SMESHGUI_ElemInfo( parent )
2036 myInfo = new QTextBrowser( centralWidget() );
2037 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2039 l->addWidget( myInfo );
2041 connect( myInfo, SIGNAL( anchorClicked(QUrl)), this, SLOT( connectivityClicked( QUrl )));
2045 \brief Show mesh element information.
2046 \param ids Nodes / elements IDs.
2048 void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
2051 TextWriter writer( myInfo );
2052 writeInfo( &writer, ids );
2056 \brief Internal clean-up (reset widget)
2058 void SMESHGUI_SimpleElemInfo::clearInternal()
2063 void SMESHGUI_SimpleElemInfo::connectivityClicked(const QUrl & url)
2065 int type = ( url.scheme()[0] == 'n' ) ? NodeConnectivity : ElemConnectivity;
2066 QString ids = url.path(); // excess chars will be filtered off by SMESHGUI_IdValidator
2067 emit( itemInfo( type, ids ));
2070 ////////////////////////////////////////////////////////////////////////////////
2071 /// \class SMESHGUI_TreeElemInfo::ItemDelegate
2072 /// \brief Item delegate for tree mesh info widget.
2074 ////////////////////////////////////////////////////////////////////////////////
2076 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
2079 ItemDelegate( QObject* );
2080 QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
2087 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
2092 \brief Redefined from QItemDelegate.
2095 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
2097 QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
2098 if ( qobject_cast<QLineEdit*>( w ) )
2099 qobject_cast<QLineEdit*>( w )->setReadOnly( true );
2103 ////////////////////////////////////////////////////////////////////////////////
2104 /// \class SMESHGUI_TreeElemInfo::ItemCreator
2105 /// \brief Item creator for tree mesh info widget.
2107 ////////////////////////////////////////////////////////////////////////////////
2109 class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
2111 SMESHGUI_TreeElemInfo* myView;
2113 ItemCreator( SMESHGUI_TreeElemInfo* );
2114 QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
2119 \param view Parent view.
2122 SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
2127 \brief Create new tree item.
2128 \param parent Parent tree item.
2129 \param options Item options.
2130 \return New tree widget item.
2133 QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
2135 return myView->createItem( parent, options );
2138 ////////////////////////////////////////////////////////////////////////////////
2139 /// \class SMESHGUI_TreeElemInfo
2140 /// \brief Show mesh element information as the tree.
2141 ////////////////////////////////////////////////////////////////////////////////
2145 \param parent Parent widget. Defaults to 0.
2147 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
2148 : SMESHGUI_ElemInfo( parent )
2150 myInfo = new QTreeWidget( centralWidget() );
2151 myInfo->setColumnCount( 2 );
2152 myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
2153 myInfo->header()->setStretchLastSection( true );
2154 myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2155 myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
2156 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2158 l->addWidget( myInfo );
2159 connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
2160 connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2161 connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2165 \brief Show mesh element information.
2166 \param ids Nodes / elements IDs.
2168 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
2171 TreeWriter writer( myInfo, new ItemCreator( this ) );
2172 writeInfo( &writer, ids );
2176 \brief Show node information
2177 \param node mesh node for showing
2178 \param index index of current node
2179 \param nbNodes number of unique nodes in element
2180 \param parentItem parent item of tree
2182 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* /*node*/, int /*index*/,
2183 int /*nbNodes*/, QTreeWidgetItem* /*parentItem*/ )
2185 // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
2186 // // node number and ID
2187 // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
2188 // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
2189 // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
2190 // nodeItem->setData( 1, TypeRole, ElemConnectivity );
2191 // nodeItem->setData( 1, IdRole, node->GetID() );
2192 // nodeItem->setExpanded( false );
2193 // // node coordinates
2194 // QTreeWidgetItem* coordItem = createItem( nodeItem );
2195 // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
2196 // QTreeWidgetItem* xItem = createItem( coordItem );
2197 // xItem->setText( 0, "X" );
2198 // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2199 // QTreeWidgetItem* yItem = createItem( coordItem );
2200 // yItem->setText( 0, "Y" );
2201 // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2202 // QTreeWidgetItem* zItem = createItem( coordItem );
2203 // zItem->setText( 0, "Z" );
2204 // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2205 // // node connectivity
2206 // QTreeWidgetItem* nconItem = createItem( nodeItem );
2207 // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
2208 // Connectivity connectivity = nodeConnectivity( node );
2209 // if ( !connectivity.isEmpty() ) {
2210 // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
2211 // if ( !con.isEmpty() ) {
2212 // QTreeWidgetItem* i = createItem( nconItem );
2213 // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
2214 // i->setText( 1, con );
2216 // con = formatConnectivity( connectivity, SMDSAbs_Edge );
2217 // if ( !con.isEmpty() ) {
2218 // QTreeWidgetItem* i = createItem( nconItem );
2219 // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
2220 // i->setText( 1, con );
2221 // i->setData( 1, TypeRole, NodeConnectivity );
2223 // con = formatConnectivity( connectivity, SMDSAbs_Ball );
2224 // if ( !con.isEmpty() ) {
2225 // QTreeWidgetItem* i = createItem( nconItem );
2226 // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
2227 // i->setText( 1, con );
2228 // i->setData( 1, TypeRole, NodeConnectivity );
2230 // con = formatConnectivity( connectivity, SMDSAbs_Face );
2231 // if ( !con.isEmpty() ) {
2232 // QTreeWidgetItem* i = createItem( nconItem );
2233 // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
2234 // i->setText( 1, con );
2235 // i->setData( 1, TypeRole, NodeConnectivity );
2237 // con = formatConnectivity( connectivity, SMDSAbs_Volume );
2238 // if ( !con.isEmpty() ) {
2239 // QTreeWidgetItem* i = createItem( nconItem );
2240 // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
2241 // i->setText( 1, con );
2242 // i->setData( 1, TypeRole, NodeConnectivity );
2247 \brief Internal clean-up (reset widget)
2249 void SMESHGUI_TreeElemInfo::clearInternal()
2256 \brief Create new item and add it to the tree.
2257 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2258 \param options Item flags. Defaults to 0 (none).
2259 \return New tree widget item.
2261 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
2263 QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
2264 setTreeItemAttributes( item, options | Expanded | Editable );
2266 if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
2268 QString resName = expandedResource( parent );
2269 parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
2275 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2277 QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2278 if ( widgets.isEmpty() ) return;
2279 QTreeWidgetItem* aTreeItem = widgets.first();
2280 int type = aTreeItem->data( 1, TypeRole ).toInt();
2281 if (( type == ElemConnectivity || type == NodeConnectivity ) &&
2282 ( !aTreeItem->text( 1 ).isEmpty() ))
2285 QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
2286 if ( menu.exec( e->globalPos() ) == a )
2287 emit( itemInfo( type, aTreeItem->text( 1 )) );
2291 void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int /*theColumn*/ )
2294 int type = theItem->data( 1, TypeRole ).toInt();
2295 emit( itemInfo( type, theItem->text( 1 )) );
2299 void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
2302 SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
2305 QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
2307 return QString("Expanded_") + ( what()==ShowElements ? "E_" : "N_" ) + theItem->text(0);
2310 ////////////////////////////////////////////////////////////////////////////////
2311 /// \class InfoComputor
2312 /// \brief Mesh information computor.
2315 /// The class is created for different computation operations. Currently it is
2316 /// used to compute size and number of underlying nodes for given group.
2317 ////////////////////////////////////////////////////////////////////////////////
2321 \param parent Parent object.
2322 \param proxy Object to compute information on (group).
2323 \param item Tree widget item, referenced by this computer.
2324 \param operation Value to compute.
2327 InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
2328 : QObject( parent ), myProxy( proxy ), myOperation( operation )
2333 \brief Compute requested information.
2336 void InfoComputor::compute()
2340 SUIT_OverrideCursor wc;
2342 switch ( myOperation )
2345 myProxy.size( true ); // force size computation
2349 myProxy.nbNodes( true ); // force size computation
2358 ////////////////////////////////////////////////////////////////////////////////
2359 /// \class SMESHGUI_AddInfo
2360 /// \brief Show additional information on selected object.
2362 /// Displays an additional information about selected object: mesh, sub-mesh
2365 /// \todo Rewrite saveInfo() method to print all data, not currently shown only.
2366 ////////////////////////////////////////////////////////////////////////////////
2370 \param parent Parent widget. Defaults to 0.
2372 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
2374 QVBoxLayout* l = new QVBoxLayout( this );
2376 l->setSpacing( SPACING );
2378 myTree = new QTreeWidget( this );
2380 myTree->setColumnCount( 2 );
2381 myTree->header()->setStretchLastSection( true );
2382 myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2383 myTree->header()->hide();
2385 l->addWidget( myTree );
2391 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2396 \brief Show information on given object.
2397 \param proxy Object to show information on (mesh, sub-mesh, group).
2399 void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
2402 setProperty( "group_index", 0 );
2403 setProperty( "submesh_index", 0 );
2404 myComputors.clear();
2407 // then fill panel with data if object is not null
2413 QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
2414 nameItem->setText( 0, tr( "NAME" ) );
2415 nameItem->setText( 1, proxy.name() );
2418 if ( proxy.type() == SMESH::SelectionProxy::Mesh )
2419 meshInfo( proxy, nameItem );
2420 else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
2421 subMeshInfo( proxy, nameItem );
2422 else if ( proxy.type() >= SMESH::SelectionProxy::Group )
2423 groupInfo( proxy, nameItem );
2428 \brief Update information in panel.
2430 void SMESHGUI_AddInfo::updateInfo()
2432 showInfo( myProxy );
2436 \brief Reset panel (clear all data).
2438 void SMESHGUI_AddInfo::clear()
2444 \brief Create new item and add it to the tree.
2445 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2446 \param options Item flags. Defaults to 0 (none).
2447 \return New tree widget item.
2449 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
2451 QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
2452 new QTreeWidgetItem( myTree->invisibleRootItem() );
2453 setTreeItemAttributes( item, options | Expanded );
2458 \brief Show information on mesh.
2459 \param proxy Proxy object (mesh).
2460 \param parent Parent tree item.
2462 void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2467 QString shapeName = proxy.shapeName();
2468 SMESH::MedInfo inf = proxy.medFileInfo();
2471 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2472 typeItem->setText( 0, tr( "TYPE" ) );
2473 if ( !shapeName.isEmpty() )
2475 typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2477 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2478 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2479 gobjItem->setText( 1, shapeName );
2481 else if ( inf.isValid() )
2483 typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2484 // med file information
2485 QTreeWidgetItem* fileItem = createItem( parent, Bold );
2486 fileItem->setText( 0, tr( "FILE_NAME" ) );
2487 fileItem->setText( 1, inf.fileName() );
2488 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2489 sizeItem->setText( 0, tr( "FILE_SIZE" ) );
2490 sizeItem->setText( 1, QString::number( inf.size() ) );
2491 QTreeWidgetItem* versionItem = createItem( parent, Bold );
2492 versionItem->setText( 0, tr( "FILE_VERSION" ) );
2493 versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
2497 typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2501 myGroups = proxy.groups();
2505 mySubMeshes = proxy.submeshes();
2510 \brief Show information on sub-mesh.
2511 \param proxy Proxy object (sub-mesh).
2512 \param parent Parent tree item.
2514 void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2519 bool isShort = parent->parent() != 0;
2524 SMESH::SelectionProxy meshProxy = proxy.mesh();
2527 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2528 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2529 nameItem->setText( 1, meshProxy.name() );
2534 QString shapeName = proxy.shapeName();
2535 if ( !shapeName.isEmpty() )
2537 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2538 gobjItem->setText( 1, shapeName );
2543 \brief Show information on group.
2544 \param proxy Proxy object (group).
2545 \param parent Parent tree item.
2547 void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2552 bool isShort = parent->parent() != 0;
2557 SMESH::SelectionProxy meshProxy = proxy.mesh();
2560 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2561 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2562 nameItem->setText( 1, meshProxy.name() );
2567 SMESH::SelectionProxy::Type type = proxy.type();
2568 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2569 typeItem->setText( 0, tr( "TYPE" ) );
2570 if ( type == SMESH::SelectionProxy::GroupStd )
2572 typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2574 else if ( type == SMESH::SelectionProxy::GroupGeom )
2576 typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2578 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2579 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2580 gobjItem->setText( 1, proxy.shapeName() );
2582 else if ( type == SMESH::SelectionProxy::GroupFilter )
2584 typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2588 int etype = proxy.groupElementType();
2591 QString typeName = tr( "UNKNOWN" );
2595 typeName = tr( "NODE" );
2598 typeName = tr( "EDGE" );
2601 typeName = tr( "FACE" );
2604 typeName = tr( "VOLUME" );
2607 typeName = tr( "0DELEM" );
2610 typeName = tr( "BALL" );
2615 QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2616 etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2617 etypeItem->setText( 1, typeName );
2621 // note: size is not computed for group on filter for performance reasons, see IPAL52831
2622 bool meshLoaded = proxy.isMeshLoaded();
2623 int size = proxy.size();
2625 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2626 sizeItem->setText( 0, tr( "SIZE" ) );
2629 sizeItem->setText( 1, QString::number( size ) );
2633 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2634 myTree->setItemWidget( sizeItem, 1, btn );
2635 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
2636 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2637 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2638 myComputors.append( comp );
2642 QTreeWidgetItem* colorItem = createItem( parent, Bold );
2643 colorItem->setText( 0, tr( "COLOR" ) );
2644 colorItem->setBackground( 1, proxy.color() );
2646 // nb of underlying nodes
2647 if ( etype != SMESH::NODE )
2649 QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2650 nodesItem->setText( 0, tr( "NB_NODES" ) );
2652 int nbNodes = proxy.nbNodes();
2655 nodesItem->setText( 1, QString::number( nbNodes ) );
2659 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2660 myTree->setItemWidget( nodesItem, 1, btn );
2661 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
2662 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2663 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2664 myComputors.append( comp );
2670 \brief Update information on child groups.
2672 void SMESHGUI_AddInfo::showGroups()
2674 // remove all computors
2675 myComputors.clear();
2677 // tree root should be the first top level item
2678 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2682 int idx = property( "group_index" ).toInt();
2684 // find sub-meshes top-level container item
2685 QTreeWidgetItem* itemGroups = 0;
2686 for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
2688 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
2690 itemGroups = parent->child( i );
2692 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
2694 extra->updateControls( myGroups.count(), idx );
2695 // clear: remove all group items
2696 while ( itemGroups->childCount() )
2697 delete itemGroups->child( 0 );
2701 QMap<int, QTreeWidgetItem*> grpItems;
2702 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
2704 SMESH::SelectionProxy grp = myGroups[i];
2708 int grpType = grp.groupElementType();
2710 // create top-level groups container item if it does not exist
2713 itemGroups = createItem( parent, Bold | AllColumns );
2714 itemGroups->setText( 0, tr( "GROUPS" ) );
2715 itemGroups->setData( 0, Qt::UserRole, GroupsId );
2717 // if necessary, create extra widget to show information by chunks
2718 if ( myGroups.count() > blockSize() )
2720 ExtraWidget* extra = new ExtraWidget( this, true );
2721 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2722 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2723 myTree->setItemWidget( itemGroups, 1, extra );
2724 extra->updateControls( myGroups.count(), idx );
2728 // create container item corresponding to particular element type
2729 if ( !grpItems.contains( grpType ) )
2731 grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
2732 grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2733 itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
2737 QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
2738 nameItem->setText( 0, grp.name().trimmed() ); // trim name
2741 groupInfo( grp, nameItem );
2746 \brief Update information on child sub-meshes.
2748 void SMESHGUI_AddInfo::showSubMeshes()
2750 // tree root should be the first top level item
2751 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2755 int idx = property( "submesh_index" ).toInt();
2757 // find sub-meshes top-level container item
2758 QTreeWidgetItem* itemSubMeshes = 0;
2759 for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
2761 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
2763 itemSubMeshes = parent->child( i );
2765 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
2767 extra->updateControls( mySubMeshes.count(), idx );
2768 // clear: remove all sub-mesh items
2769 while ( itemSubMeshes->childCount() )
2770 delete itemSubMeshes->child( 0 );
2774 QMap<int, QTreeWidgetItem*> smItems;
2775 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
2777 SMESH::SelectionProxy sm = mySubMeshes[i];
2781 int smType = sm.shapeType();
2784 else if ( smType == GEOM::COMPSOLID )
2785 smType = GEOM::COMPOUND;
2787 // create top-level sub-meshes container item if it does not exist
2788 if ( !itemSubMeshes )
2790 itemSubMeshes = createItem( parent, Bold | AllColumns );
2791 itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2792 itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
2794 // if necessary, create extra widget to show information by chunks
2795 if ( mySubMeshes.count() > blockSize() )
2797 ExtraWidget* extra = new ExtraWidget( this, true );
2798 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2799 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2800 myTree->setItemWidget( itemSubMeshes, 1, extra );
2801 extra->updateControls( mySubMeshes.count(), idx );
2805 // create container item corresponding to particular shape type
2806 if ( !smItems.contains( smType ) )
2808 smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
2809 smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2810 itemSubMeshes->insertChild( smType, smItems[ smType ] );
2814 QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
2815 nameItem->setText( 0, sm.name().trimmed() ); // trim name
2818 subMeshInfo( sm, nameItem );
2823 \brief Show previous chunk of information on child groups.
2825 void SMESHGUI_AddInfo::showPreviousGroups()
2827 int idx = property( "group_index" ).toInt();
2828 setProperty( "group_index", idx-1 );
2833 \brief Show next chunk of information on child groups.
2835 void SMESHGUI_AddInfo::showNextGroups()
2837 int idx = property( "group_index" ).toInt();
2838 setProperty( "group_index", idx+1 );
2843 \brief Show previous chunk of information on child sub-meshes.
2845 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2847 int idx = property( "submesh_index" ).toInt();
2848 setProperty( "submesh_index", idx-1 );
2853 \brief Show next chunk of information on child sub-meshes.
2855 void SMESHGUI_AddInfo::showNextSubMeshes()
2857 int idx = property( "submesh_index" ).toInt();
2858 setProperty( "submesh_index", idx+1 );
2863 \brief Write information from panel to output stream.
2864 \param out Text stream output.
2866 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2869 QString title = tr( "ADDITIONAL_INFO" );
2870 out << ruler( title.size() ) << endl;
2871 out << title << endl;
2872 out << ruler( title.size() ) << endl;
2876 QTreeWidgetItemIterator it( myTree );
2879 if ( !( ( *it )->text(0) ).isEmpty() )
2881 out << indent( itemDepth( *it ) ) << ( *it )->text(0);
2882 if ( ( *it )->text(0) == tr( "COLOR" ) )
2883 out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
2884 else if ( !( ( *it )->text(1) ).isEmpty() )
2885 out << ":" << spacing() << ( *it )->text(1);
2893 ////////////////////////////////////////////////////////////////////////////////
2894 /// \class GroupCombo
2895 /// \brief Customized combo box to manage list of mesh groups.
2897 ////////////////////////////////////////////////////////////////////////////////
2899 class GroupCombo: public QComboBox
2901 class Item: public QStandardItem
2904 SMESH::SelectionProxy myGroup;
2905 Item( const SMESH::SelectionProxy& group )
2908 setText( myGroup.name() );
2910 SMESH::SelectionProxy group()
2916 SMESH::SelectionProxy myProxy;
2919 GroupCombo( QWidget* );
2920 void setSource( const SMESH::SelectionProxy& );
2921 SMESH::SelectionProxy currentGroup() const;
2926 \param parent Parent widget.
2929 GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
2931 setModel( new QStandardItemModel( this ) );
2935 \brief Set mesh source.
2936 \param obj Mesh source.
2939 void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
2941 if ( myProxy == proxy )
2946 bool blocked = blockSignals( true );
2947 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2952 if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
2954 QList<SMESH::SelectionProxy> groups = myProxy.groups();
2955 for ( int i = 0; i < groups.count(); ++i )
2959 QString name = groups[i].name();
2960 if ( !name.isEmpty() )
2961 m->appendRow( new Item( groups[i] ) );
2964 setCurrentIndex( -1 ); // for performance reasons
2966 else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
2968 m->appendRow( new Item( myProxy ) );
2969 setCurrentIndex( 0 );
2973 blockSignals( blocked );
2977 \brief Get currently selected group.
2978 \return Selected group.
2981 SMESH::SelectionProxy GroupCombo::currentGroup() const
2983 SMESH::SelectionProxy group;
2984 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2985 if ( currentIndex() >= 0 )
2986 group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
2990 ////////////////////////////////////////////////////////////////////////////////
2991 /// \class SMESHGUI_MeshInfoDlg
2992 /// \brief Mesh information dialog box
2994 /// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
2995 /// \todo Add selection button to reactivate selection on move from other dlg.
2996 ////////////////////////////////////////////////////////////////////////////////
3000 \param parent Parent widget.
3001 \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
3003 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
3007 setAttribute( Qt::WA_DeleteOnClose, true );
3008 setWindowTitle( tr( "MESH_INFO" ) );
3009 setSizeGripEnabled( true );
3011 myTabWidget = new QTabWidget( this );
3015 myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
3016 myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
3020 QWidget* w = new QWidget( myTabWidget );
3022 myMode = new QButtonGroup( this );
3023 myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
3024 myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
3025 myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
3026 myMode->button( NodeMode )->setChecked( true );
3027 myID = new QLineEdit( w );
3028 myID->setValidator( new SMESHGUI_IdValidator( this ) );
3029 myGroups = new GroupCombo( w );
3030 QStackedWidget* stack = new QStackedWidget( w );
3031 stack->addWidget( myID );
3032 stack->addWidget( myGroups );
3033 myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
3034 myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
3036 int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
3037 mode = qMin( 1, qMax( 0, mode ) );
3040 myElemInfo = new SMESHGUI_SimpleElemInfo( w );
3042 myElemInfo = new SMESHGUI_TreeElemInfo( w );
3043 stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
3045 QGridLayout* elemLayout = new QGridLayout( w );
3046 elemLayout->setMargin( MARGIN );
3047 elemLayout->setSpacing( SPACING );
3048 elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
3049 elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
3050 elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
3051 elemLayout->addWidget( stack, 0, 3 );
3052 elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
3053 elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
3055 myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
3059 myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
3060 myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
3064 myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
3065 myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
3069 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3070 okBtn->setAutoDefault( true );
3071 okBtn->setDefault( true );
3073 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3074 dumpBtn->setAutoDefault( true );
3075 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3076 helpBtn->setAutoDefault( true );
3078 QHBoxLayout* btnLayout = new QHBoxLayout;
3079 btnLayout->setSpacing( SPACING );
3080 btnLayout->setMargin( 0 );
3082 btnLayout->addWidget( okBtn );
3083 btnLayout->addWidget( dumpBtn );
3084 btnLayout->addStretch( 10 );
3085 btnLayout->addWidget( helpBtn );
3089 QVBoxLayout* l = new QVBoxLayout ( this );
3090 l->setMargin( MARGIN );
3091 l->setSpacing( SPACING );
3092 l->addWidget( myTabWidget );
3093 l->addLayout( btnLayout );
3097 myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
3099 // set-up connections
3101 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3102 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3103 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3104 connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
3105 connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
3106 connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
3107 connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
3108 connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
3109 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3110 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3111 connect( myElemInfo, SIGNAL( itemInfo( int, QString ) ), this, SLOT( showItemInfo( int, QString ) ) );
3112 connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
3116 myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
3123 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
3129 \brief Show mesh information on given object.
3130 \param io Interactive object.
3132 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3135 showInfo( SMESH::SelectionProxy( io ) );
3139 \brief Show mesh information on given object.
3140 \param proxy Selection proxy.
3142 void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3144 SUIT_OverrideCursor wc;
3151 SMESH::SMESH_IDSource_var obj = myProxy.object();
3154 myBaseInfo->showInfo( proxy );
3156 // "Additional info" tab
3157 myAddInfo->showInfo( proxy );
3159 // "Quality info" tab
3160 // Note: for performance reasons we update it only if it is currently active
3161 if ( myTabWidget->currentIndex() == CtrlInfo )
3162 myCtrlInfo->showInfo( proxy );
3164 // "Element info" tab
3165 myGroups->setSource( proxy );
3166 if ( myMode->checkedId() == GroupMode ) {
3167 SMESH::SelectionProxy group = myGroups->currentGroup();
3169 myElemInfo->showInfo( group );
3171 myElemInfo->clear();
3174 SVTK_Selector* selector = SMESH::GetSelector();
3177 if ( myProxy.actor() && selector ) { //todo: actor()?
3178 nb = myMode->checkedId() == NodeMode ?
3179 SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
3180 SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
3183 myID->setText( ID.trimmed() );
3185 QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
3186 foreach ( ID, idTxt )
3187 ids << ID.trimmed().toUInt();
3188 myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
3192 myElemInfo->clear();
3198 \brief Update information.
3200 void SMESHGUI_MeshInfoDlg::updateInfo()
3202 SALOME_ListIO selected;
3203 SMESHGUI::selectionMgr()->selectedObjects( selected );
3205 if ( selected.Extent() == 1 )
3206 showInfo( selected.First() );
3208 showInfo( myProxy );
3212 \brief Clean-up on dialog closing.
3214 void SMESHGUI_MeshInfoDlg::reject()
3216 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3217 selMgr->clearFilters();
3218 SMESH::SetPointRepresentation( false );
3219 if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
3220 viewWindow->SetSelectionMode( ActorSelection );
3222 myIDPreview->SetPointsLabeled( false );
3226 \brief Process keyboard event.
3227 \param e Key press event.
3229 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
3231 QDialog::keyPressEvent( e );
3232 if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
3239 \brief Set-up selection mode for currently selected page.
3241 void SMESHGUI_MeshInfoDlg::updateSelection()
3243 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3245 disconnect( selMgr, 0, this, 0 );
3246 selMgr->clearFilters();
3248 int selMode = ActorSelection;
3249 if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == NodeMode )
3250 selMode = NodeSelection;
3251 else if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == ElemMode )
3252 selMode = CellSelection;
3253 SMESH::SetPointRepresentation( selMode == NodeSelection );
3254 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3255 aViewWindow->SetSelectionMode( selMode );
3257 SMESH::SelectionProxy previous = myProxy;
3258 QString ids = myID->text().trimmed();
3261 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3264 if ( myProxy && myProxy == previous && !ids.isEmpty() ) {
3265 myID->setText( ids );
3271 \brief Show documentation on selected dialog page.
3273 void SMESHGUI_MeshInfoDlg::help()
3275 QString helpPage = "mesh_infos.html";
3276 switch ( myTabWidget->currentIndex() )
3279 helpPage += "#advanced-mesh-infos-anchor";
3282 helpPage += "#mesh-element-info-anchor";
3285 helpPage += "#mesh-addition-info-anchor";
3288 helpPage += "#mesh-quality-info-anchor";
3293 SMESH::ShowHelpFile( helpPage );
3297 \brief Deactivate dialog box.
3299 void SMESHGUI_MeshInfoDlg::deactivate()
3301 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3305 \brief Called when users switches between node / element modes.
3307 void SMESHGUI_MeshInfoDlg::modeChanged()
3309 emit( switchMode( myMode->checkedId() == GroupMode ? 1 : 0 ) );
3315 \brief Called when users prints mesh element ID in the corresponding field.
3317 void SMESHGUI_MeshInfoDlg::idChanged()
3319 myIDPreview->SetPointsLabeled( false );
3324 std::vector<int> idVec;
3325 std::list< gp_XYZ > aGrCentersXYZ;
3327 const bool isElem = ( myMode->checkedId() == ElemMode );
3328 QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
3329 foreach ( QString tid, idTxt ) {
3330 long id = tid.toUInt();
3331 if ( isElem ? myProxy.hasElement( id ) : myProxy.hasNode( id ))
3335 if ( isElem && myProxy.actor() && myProxy.elementGravityCenter( id, xyz ))
3337 idVec.push_back( id );
3338 aGrCentersXYZ.push_back( xyz );
3342 SVTK_Selector* selector = SMESH::GetSelector();
3343 if ( myProxy.actor() && selector ) {
3344 Handle(SALOME_InteractiveObject) IO = myProxy.actor()->getIO();
3345 selector->AddOrRemoveIndex( IO, ID, false );
3346 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3348 if ( myMode->checkedId() == NodeMode )
3349 myIDPreview->SetPointsData( myProxy.actor()->GetObject()->GetMesh(), ID );
3351 myIDPreview->SetElemsData( idVec, aGrCentersXYZ );
3353 bool showIDs = ( !ID.IsEmpty() &&
3354 myIDPreviewCheck->isChecked() &&
3355 myTabWidget->currentIndex() == ElemInfo );
3356 myIDPreview->SetPointsLabeled( showIDs, myProxy.actor()->GetVisibility() );
3358 aViewWindow->highlight( IO, true, true );
3359 aViewWindow->Repaint();
3362 myElemInfo->showInfo( myProxy, ids, isElem );
3367 * \brief Show IDs clicked
3369 void SMESHGUI_MeshInfoDlg::idPreviewChange( bool isOn )
3371 myIDPreview->SetPointsLabeled( isOn && !myID->text().simplified().isEmpty() );
3372 SMESHGUI::resourceMgr()->setValue("SMESH", "id_preview_resource", isOn );
3373 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3374 aViewWindow->Repaint();
3377 void SMESHGUI_MeshInfoDlg::showItemInfo( int type, const QString& ids )
3379 if ( !ids.isEmpty() && ( type == NodeConnectivity || type == ElemConnectivity )) {
3380 myMode->button( type - NodeConnectivity )->click();
3381 myID->setText( ids );
3386 \brief Dump information to file.
3388 void SMESHGUI_MeshInfoDlg::dump()
3390 DumpFileDlg fd( this );
3391 fd.setWindowTitle( tr( "SAVE_INFO" ) );
3392 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
3393 fd.setChecked( BaseInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_base", true ) );
3394 fd.setChecked( ElemInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_elem", true ) );
3395 fd.setChecked( AddInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_add", true ) );
3396 fd.setChecked( CtrlInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_ctrl", true ) );
3397 if ( fd.exec() == QDialog::Accepted )
3399 QString fileName = fd.selectedFile();
3400 if ( !fileName.isEmpty() ) {
3401 QFile file( fileName );
3402 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
3405 QTextStream out( &file );
3406 if ( fd.isChecked( BaseInfo ) ) myBaseInfo->saveInfo( out );
3407 if ( fd.isChecked( ElemInfo ) ) myElemInfo->saveInfo( out );
3408 if ( fd.isChecked( AddInfo ) ) myAddInfo->saveInfo( out );
3409 if ( fd.isChecked( CtrlInfo ) )
3411 myCtrlInfo->showInfo( myProxy ); // it saves what is shown only
3412 myCtrlInfo->saveInfo( out );
3418 ////////////////////////////////////////////////////////////////////////////////
3419 /// \class SMESHGUI_CtrlInfo
3420 /// \brief Show quality statistics information on selected object.
3422 /// Displays quality controls statistics about selected object: mesh, sub-mesh,
3423 /// group or arbitrary ID source.
3424 ////////////////////////////////////////////////////////////////////////////////
3428 \param parent Parent widget. Defaults to 0.
3430 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent ): SMESHGUI_Info( parent )
3432 QGridLayout* l = new QGridLayout( this );
3433 l->setMargin( MARGIN );
3434 l->setSpacing( SPACING );
3436 QIcon aComputeIcon( SUIT_Session::session()->resourceMgr()->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3437 SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3439 // QToolBox with MeshInfo
3440 myMeshTB = new QToolBox(this);
3443 QLabel* aNameLab = createLabel( tr( "NAME_LAB" ), this, Bold );
3444 QLabel* aName = createField( this, "ctrlName" );
3445 aName->setMinimumWidth( 150 );
3449 QLabel* aNodesLab = createLabel( tr( "NODES_INFO" ), this, Bold );
3450 QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3451 QLabel* aNodesFree = createField( this, "ctrlNodesFree" );
3452 myWidgets << aNodesFree;
3453 myPredicates << aFilterMgr->CreateFreeNodes();
3455 QLabel* aNodesNbConnLab = new QLabel( tr( "MAX_NODE_CONNECTIVITY" ), this );
3456 QLabel* aNodesNbConn = createField( this, "ctrlNodesCnty" );
3457 myWidgets << aNodesNbConn;
3458 myNodeConnFunctor = aFilterMgr->CreateNodeConnectivityNumber();
3460 QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3461 QLabel* aNodesDouble = createField( this, "ctrlNodesDouble" );
3462 myWidgets << aNodesDouble;
3463 myPredicates << aFilterMgr->CreateEqualNodes();
3464 QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3465 myToleranceWidget = new SMESHGUI_SpinBox( this );
3466 myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3467 myToleranceWidget->setAcceptNames( false );
3468 myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3471 QLabel* anEdgesLab = createLabel( tr( "EDGES_INFO" ), this, Bold );
3472 QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ), this );
3473 QLabel* anEdgesDouble = createField( this, "ctrlEdgesDouble" );
3474 myWidgets << anEdgesDouble;
3475 myPredicates << aFilterMgr->CreateEqualEdges();
3478 QLabel* aFacesLab = createLabel( tr( "FACES_INFO" ), this, Bold );
3479 QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3480 QLabel* aFacesDouble = createField( this, "ctrlFacesDouble" );
3481 myWidgets << aFacesDouble;
3482 myPredicates << aFilterMgr->CreateEqualFaces();
3483 QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3484 QLabel* aFacesOver = createField( this, "ctrlFacesOver" );
3485 myWidgets << aFacesOver;
3486 myPredicates << aFilterMgr->CreateOverConstrainedFace();
3487 QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3488 myPlot = createPlot( this );
3489 myAspectRatio = aFilterMgr->CreateAspectRatio();
3492 QLabel* aVolumesLab = createLabel( tr( "VOLUMES_INFO" ), this, Bold );
3493 QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3494 QLabel* aVolumesDouble = createField( this, "ctrlVolumesDouble" );
3495 myWidgets << aVolumesDouble;
3496 myPredicates << aFilterMgr->CreateEqualVolumes();
3497 QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3498 QLabel* aVolumesOver = createField( this, "ctrlVolumesOver" );
3499 myWidgets << aVolumesOver;
3500 myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3501 QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3502 myPlot3D = createPlot( this );
3503 myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3505 QToolButton* aFreeNodesBtn = new QToolButton( this );
3506 aFreeNodesBtn->setIcon(aComputeIcon);
3507 myButtons << aFreeNodesBtn; //0
3509 QToolButton* aNodesNbConnBtn = new QToolButton( this );
3510 aNodesNbConnBtn->setIcon(aComputeIcon);
3511 myButtons << aNodesNbConnBtn; //1
3513 QToolButton* aDoubleNodesBtn = new QToolButton( this );
3514 aDoubleNodesBtn->setIcon(aComputeIcon);
3515 myButtons << aDoubleNodesBtn; //2
3517 QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3518 aDoubleEdgesBtn->setIcon(aComputeIcon);
3519 myButtons << aDoubleEdgesBtn; //3
3521 QToolButton* aDoubleFacesBtn = new QToolButton( this );
3522 aDoubleFacesBtn->setIcon(aComputeIcon);
3523 myButtons << aDoubleFacesBtn; //4
3525 QToolButton* aOverContFacesBtn = new QToolButton( this );
3526 aOverContFacesBtn->setIcon(aComputeIcon);
3527 myButtons << aOverContFacesBtn; //5
3529 QToolButton* aComputeFaceBtn = new QToolButton( this );
3530 aComputeFaceBtn->setIcon(aComputeIcon);
3531 myButtons << aComputeFaceBtn; //6
3533 QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3534 aDoubleVolumesBtn->setIcon(aComputeIcon);
3535 myButtons << aDoubleVolumesBtn; //7
3537 QToolButton* aOverContVolumesBtn = new QToolButton( this );
3538 aOverContVolumesBtn->setIcon(aComputeIcon);
3539 myButtons << aOverContVolumesBtn; //8
3541 QToolButton* aComputeVolumeBtn = new QToolButton( this );
3542 aComputeVolumeBtn->setIcon(aComputeIcon);
3543 myButtons << aComputeVolumeBtn; //9
3545 connect( aComputeFaceBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3546 connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3547 connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3548 connect( aNodesNbConnBtn, SIGNAL( clicked() ), this, SLOT( computeNodesNbConnInfo() ) );
3549 connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3550 connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3551 connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3552 connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3553 connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3554 connect( aOverContVolumesBtn,SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3555 connect( myToleranceWidget, SIGNAL( valueChanged( double ) ), this, SLOT( setTolerance( double ) ) );
3556 this->setTolerance(myToleranceWidget->GetValue());
3558 l->addWidget( aNameLab, 0, 0 ); //0
3559 l->addWidget( aName, 0, 1 ); //1
3562 QWidget* NodeGrp = new QWidget();
3563 QGridLayout* NodeLayout = new QGridLayout(NodeGrp);
3564 NodeLayout->setSpacing(SPACING); NodeLayout->setMargin(MARGIN);
3566 NodeLayout->addWidget( aNodesFreeLab, 0, 0 );
3567 NodeLayout->addWidget( aNodesFree, 0, 1 );
3568 NodeLayout->addWidget( aFreeNodesBtn, 0, 2 );
3569 NodeLayout->addWidget( aNodesNbConnLab, 1, 0 );
3570 NodeLayout->addWidget( aNodesNbConn, 1, 1 );
3571 NodeLayout->addWidget( aNodesNbConnBtn, 1, 2 );
3572 NodeLayout->addWidget( aNodesDoubleLab, 2, 0 );
3573 NodeLayout->addWidget( aNodesDouble, 2, 1 );
3574 NodeLayout->addWidget( aDoubleNodesBtn, 2, 2 );
3575 NodeLayout->addWidget( aToleranceLab, 3, 0 );
3576 NodeLayout->addWidget( myToleranceWidget, 3, 1 );
3577 NodeLayout->addWidget( myToleranceWidget, 3, 1 );
3578 NodeLayout->setRowStretch(4, 5);
3580 myMeshTB->addItem(NodeGrp, aNodesLab->text());
3581 aNodesLab->setVisible(false);
3584 QWidget* EdgeGrp = new QWidget();
3585 QGridLayout* EdgeLayout = new QGridLayout(EdgeGrp);
3586 EdgeLayout->setSpacing(SPACING); EdgeLayout->setMargin(MARGIN);
3588 EdgeLayout->addWidget( anEdgesDoubleLab, 0, 0 );
3589 EdgeLayout->addWidget( anEdgesDouble, 0, 1 );
3590 EdgeLayout->addWidget( aDoubleEdgesBtn, 0, 2 );
3591 EdgeLayout->setRowStretch(1, 5);
3593 myMeshTB->addItem(EdgeGrp, anEdgesLab->text());
3594 anEdgesLab->setVisible(false);
3597 QWidget* FaceGrp = new QWidget();
3598 QGridLayout* FaceLayout = new QGridLayout(FaceGrp);
3599 FaceLayout->setSpacing(SPACING); FaceLayout->setMargin(MARGIN);
3601 FaceLayout->addWidget( aFacesDoubleLab, 0, 0 );
3602 FaceLayout->addWidget( aFacesDouble, 0, 1 );
3603 FaceLayout->addWidget( aDoubleFacesBtn, 0, 2 );
3604 FaceLayout->addWidget( aFacesOverLab, 1, 0 );
3605 FaceLayout->addWidget( aFacesOver, 1, 1 );
3606 FaceLayout->addWidget( aOverContFacesBtn, 1, 2 );
3607 FaceLayout->addWidget( anAspectRatioLab, 2, 0 );
3608 FaceLayout->addWidget( aComputeFaceBtn, 2, 2 );
3609 FaceLayout->addWidget( myPlot, 3, 0, 1, 3 );
3611 myMeshTB->addItem(FaceGrp, aFacesLab->text());
3612 aFacesLab->setVisible(false);
3615 QWidget* VolumeGrp = new QWidget();
3616 QGridLayout* VolumeLayout = new QGridLayout(VolumeGrp);
3617 VolumeLayout->setSpacing(SPACING); VolumeLayout->setMargin(MARGIN);
3619 VolumeLayout->addWidget( aVolumesDoubleLab, 0, 0 );
3620 VolumeLayout->addWidget( aVolumesDouble, 0, 1 );
3621 VolumeLayout->addWidget( aDoubleVolumesBtn, 0, 2 );
3622 VolumeLayout->addWidget( aVolumesOverLab, 1, 0 );
3623 VolumeLayout->addWidget( aVolumesOver, 1, 1 );
3624 VolumeLayout->addWidget( aOverContVolumesBtn,1, 2 );
3625 VolumeLayout->addWidget( anAspectRatio3DLab, 2, 0 );
3626 VolumeLayout->addWidget( aComputeVolumeBtn, 2, 2 );
3627 VolumeLayout->addWidget( myPlot3D, 3, 0, 1, 3 );
3629 myMeshTB->addItem(VolumeGrp, aVolumesLab->text());
3630 aVolumesLab->setVisible(false);
3632 l->addWidget( myMeshTB, 1, 0, 1, 2 ); //2
3633 l->setRowStretch( 2, 5 );
3641 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3646 \brief Create plot widget.
3647 \param parent Parent widget.
3648 \return New plot widget.
3650 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3652 QwtPlot* aPlot = new QwtPlot( parent );
3653 aPlot->setMinimumSize( 100, 100 );
3654 QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3655 xFont.setPointSize( 5 );
3656 QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3657 yFont.setPointSize( 5 );
3658 aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3659 aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3665 \brief Show information on given object.
3666 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
3668 void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
3676 SMESH::SMESH_IDSource_var obj = proxy.object();
3678 myWidgets[0]->setText( proxy.name() );
3680 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3681 if ( mesh->_is_nil() ) return;
3683 const bool meshLoaded = mesh->IsLoaded();
3684 if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3685 // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3686 for ( int i = 0; i < myButtons.count(); ++i )
3687 myButtons[i]->setEnabled( true );
3689 SMESH::smIdType_array_var nbElemsByType = obj->GetNbElementsByType();
3690 if ( ! &nbElemsByType.in() ) return;
3692 const CORBA::Long ctrlLimit =
3693 meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3696 const SMESH::smIdType nbNodes = nbElemsByType[ SMESH::NODE ];
3697 // const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3698 // nbElemsByType[ SMESH::FACE ] +
3699 // nbElemsByType[ SMESH::VOLUME ] );
3700 if ( nbNodes > 0 ) {
3701 if ( nbNodes <= ctrlLimit ) {
3703 computeFreeNodesInfo();
3704 // node connectivity number
3705 computeNodesNbConnInfo();
3707 computeDoubleNodesInfo();
3710 myButtons[0]->setEnabled( true );
3711 myButtons[1]->setEnabled( true );
3712 myButtons[2]->setEnabled( true );
3716 myMeshTB->setItemEnabled(0, false );
3717 myMeshTB->widget(0)->setVisible( false );
3721 if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3723 if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3724 computeDoubleEdgesInfo();
3726 myButtons[3]->setEnabled( true );
3729 myMeshTB->setItemEnabled(1, false );
3730 myMeshTB->widget(1)->setVisible( false );
3734 if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3735 if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3737 computeDoubleFacesInfo();
3738 // over constrained faces
3739 computeOverConstrainedFacesInfo();
3740 // aspect Ratio histogram
3741 computeAspectRatio();
3744 myButtons[4]->setEnabled( true );
3745 myButtons[5]->setEnabled( true );
3746 myButtons[6]->setEnabled( true );
3750 myMeshTB->setItemEnabled(2, false );
3751 myMeshTB->widget(2)->setVisible( false );
3755 if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3756 if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3758 computeDoubleVolumesInfo();
3759 // over constrained volumes
3760 computeOverConstrainedVolumesInfo();
3761 // aspect Ratio 3D histogram
3762 computeAspectRatio3D();
3765 myButtons[7]->setEnabled( true );
3766 myButtons[8]->setEnabled( true );
3767 myButtons[9]->setEnabled( true );
3771 myMeshTB->setItemEnabled(3, false );
3772 myMeshTB->widget(3)->setVisible( false );
3774 myMeshTB->setCurrentIndex(0);
3775 myMeshTB->setVisible( (nbNodes + nbElemsByType[ SMESH::EDGE ] +
3776 nbElemsByType[ SMESH::FACE ] +
3777 nbElemsByType[ SMESH::VOLUME ]) > 0 );
3780 //================================================================================
3782 * \brief Computes and shows nb of elements satisfying a given predicate
3783 * \param [in] ft - a predicate type (SMESH::FunctorType)
3784 * \param [in] iBut - index of one of myButtons to disable
3785 * \param [in] iWdg - index of one of myWidgets to show the computed number
3787 //================================================================================
3789 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3791 myButtons[ iBut ]->setEnabled( false );
3792 myWidgets[ iWdg ]->setText( "" );
3797 SUIT_OverrideCursor wc;
3799 SMESH::SMESH_IDSource_var obj = myProxy.object();
3800 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3802 if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3805 showInfo( myProxy ); // try to show all values
3806 if ( !myWidgets[ iWdg ]->text().isEmpty() )
3807 return; // <ft> predicate already computed
3809 // look for a predicate of type <ft>
3810 for ( int i = 0; i < myPredicates.count(); ++i )
3811 if ( myPredicates[i]->GetFunctorType() == ft )
3813 CORBA::Long nb = myPredicates[i]->NbSatisfying( obj );
3814 myWidgets[ iWdg ]->setText( QString::number( nb ) );
3818 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3820 computeNb( SMESH::FT_FreeNodes, 0, 1 );
3823 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3825 computeNb( SMESH::FT_EqualNodes, 2, 3 );
3828 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3830 computeNb( SMESH::FT_EqualEdges, 3, 4 );
3833 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3835 computeNb( SMESH::FT_EqualFaces, 4, 5 );
3838 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3840 computeNb( SMESH::FT_OverConstrainedFace, 5, 6 );
3843 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3845 computeNb( SMESH::FT_EqualVolumes, 7, 7 );
3848 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3850 computeNb( SMESH::FT_OverConstrainedVolume, 8, 8 );
3853 void SMESHGUI_CtrlInfo::computeNodesNbConnInfo()
3855 myButtons[ 1 ]->setEnabled( false );
3856 myWidgets[ 2 ]->setText( "" );
3861 SUIT_OverrideCursor wc;
3863 SMESH::SMESH_IDSource_var obj = myProxy.object();
3864 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3866 if ( !mesh->IsLoaded() )
3869 showInfo( myProxy ); // try to show all values
3870 if ( !myWidgets[ 2 ]->text().isEmpty() )
3871 return; // already computed
3873 myNodeConnFunctor->SetMesh( mesh );
3874 SMESH::Histogram_var histogram =
3875 myNodeConnFunctor->GetLocalHistogram( 1, /*isLogarithmic=*/false, obj );
3877 myWidgets[ 2 ]->setText( QString::number( histogram[0].max ) );
3880 void SMESHGUI_CtrlInfo::computeAspectRatio()
3882 #ifndef DISABLE_PLOT2DVIEWER
3883 myButtons[6]->setEnabled( false );
3888 SUIT_OverrideCursor wc;
3890 SMESH::SMESH_IDSource_var obj = myProxy.object();
3891 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3893 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3894 if ( aHistogram && !aHistogram->isEmpty() ) {
3895 QwtPlotItem* anItem = aHistogram->createPlotItem();
3896 anItem->attach( myPlot );
3903 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3905 #ifndef DISABLE_PLOT2DVIEWER
3906 myButtons[9]->setEnabled( false );
3911 SUIT_OverrideCursor wc;
3913 SMESH::SMESH_IDSource_var obj = myProxy.object();
3914 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3916 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3917 if ( aHistogram && !aHistogram->isEmpty() ) {
3918 QwtPlotItem* anItem = aHistogram->createPlotItem();
3919 anItem->attach( myPlot3D );
3927 \brief Internal clean-up (reset widget)
3929 void SMESHGUI_CtrlInfo::clearInternal()
3931 for (int i=0; i<=3;i++) {
3932 myMeshTB->setItemEnabled(i, true );
3933 myMeshTB->widget(i)->setVisible( true );
3935 for( int i=0; i<=9; i++)
3936 myButtons[i]->setEnabled( false );
3937 myPlot->detachItems();
3938 myPlot3D->detachItems();
3941 myWidgets[0]->setText( QString() );
3942 for ( int i = 1; i < myWidgets.count(); i++ )
3943 myWidgets[i]->setText( "" );
3946 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3948 myButtons[2]->setEnabled( true );
3949 myWidgets[3]->setText("");
3950 for ( int i = 0; i < myPredicates.count(); ++i )
3951 if ( myPredicates[i]->GetFunctorType() == SMESH::FT_EqualNodes )
3953 SMESH::EqualNodes_var functor = SMESH::EqualNodes::_narrow( myPredicates[i] );
3954 if ( !functor->_is_nil() )
3955 functor->SetTolerance( theTolerance );
3959 #ifndef DISABLE_PLOT2DVIEWER
3960 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3962 SUIT_OverrideCursor wc;
3964 SMESH::SMESH_IDSource_var obj = myProxy.object();
3965 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3967 if ( !mesh->IsLoaded() )
3969 aNumFun->SetMesh( mesh );
3971 CORBA::Long cprecision = 6;
3972 if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) )
3973 cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3974 aNumFun->SetPrecision( cprecision );
3976 int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3978 SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3979 /*isLogarithmic=*/false,
3981 Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3982 aHistogram->setColor( palette().color( QPalette::Highlight ) );
3983 if ( &histogramVar.in() )
3985 for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3986 aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3987 if ( histogramVar->length() >= 2 )
3988 aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3994 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
3997 QString title = tr( "CTRL_INFO" );
3998 out << ruler( title.size() ) << endl;
3999 out << title << endl;
4000 out << ruler( title.size() ) << endl;
4004 out << tr( "NAME_LAB" ) << " " << myWidgets[0]->text() << endl;
4005 out << tr( "NODES_INFO" ) << endl;
4006 out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
4007 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_NODES" ) << ": " << myWidgets[3]->text() << endl;
4008 out << tr( "EDGES_INFO" ) << endl;
4009 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_EDGES" ) << ": " << myWidgets[4]->text() << endl;
4010 out << tr( "FACES_INFO" ) << endl;
4011 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_FACES" ) << ": " << myWidgets[5]->text() << endl;
4012 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[6]->text() << endl;
4013 out << tr( "VOLUMES_INFO" ) << endl;
4014 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ) << ": " << myWidgets[7]->text() << endl;
4015 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[8]->text() << endl;
4018 ////////////////////////////////////////////////////////////////////////////////
4019 /// \class SMESHGUI_CtrlInfoDlg
4020 /// \brief Overall Mesh Quality dialog.
4021 /// \todo Add selection button to reactivate selection on move from other dlg.
4022 ////////////////////////////////////////////////////////////////////////////////
4026 \param parent parent widget
4028 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
4031 setAttribute( Qt::WA_DeleteOnClose, true );
4032 setWindowTitle( tr( "CTRL_INFO" ) );
4033 setMinimumSize( 400, 600 );
4035 myCtrlInfo = new SMESHGUI_CtrlInfo( this );
4038 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
4039 okBtn->setAutoDefault( true );
4040 okBtn->setDefault( true );
4042 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
4043 dumpBtn->setAutoDefault( true );
4044 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
4045 helpBtn->setAutoDefault( true );
4047 QHBoxLayout* btnLayout = new QHBoxLayout;
4048 btnLayout->setSpacing( SPACING );
4049 btnLayout->setMargin( 0 );
4051 btnLayout->addWidget( okBtn );
4052 btnLayout->addWidget( dumpBtn );
4053 btnLayout->addStretch( 10 );
4054 btnLayout->addWidget( helpBtn );
4056 QVBoxLayout* l = new QVBoxLayout ( this );
4058 l->setSpacing( SPACING );
4059 l->addWidget( myCtrlInfo );
4060 l->addLayout( btnLayout );
4062 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
4063 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
4064 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
4065 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
4066 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
4074 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
4079 \brief Show mesh quality information on given object.
4080 \param io Interactive object.
4082 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
4085 showInfo( SMESH::SelectionProxy( io ) );
4089 \brief Show mesh quality information on given object.
4090 \param proxy Selection proxy.
4092 void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
4094 SUIT_OverrideCursor wc;
4100 myCtrlInfo->showInfo( proxy );
4104 \brief Show mesh information
4106 void SMESHGUI_CtrlInfoDlg::updateInfo()
4108 SALOME_ListIO selected;
4109 SMESHGUI::selectionMgr()->selectedObjects( selected );
4111 if ( selected.Extent() == 1 )
4112 showInfo( selected.First() );
4114 showInfo( myProxy );
4118 \brief Perform clean-up actions on the dialog box closing.
4120 void SMESHGUI_CtrlInfoDlg::reject()
4122 SMESH::SetPointRepresentation( false );
4127 \brief Setup selection mode depending on the current dialog box state.
4129 void SMESHGUI_CtrlInfoDlg::updateSelection()
4131 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
4132 disconnect( selMgr, 0, this, 0 );
4133 SMESH::SetPointRepresentation( false );
4134 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4139 \brief Deactivate dialog box.
4141 void SMESHGUI_CtrlInfoDlg::deactivate()
4143 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4147 \brief Dump information to file.
4149 void SMESHGUI_CtrlInfoDlg::dump()
4151 DumpFileDlg fd( this, false );
4152 fd.setWindowTitle( tr( "SAVE_INFO" ) );
4153 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
4154 if ( fd.exec() == QDialog::Accepted )
4156 QString fileName = fd.selectedFile();
4157 if ( !fileName.isEmpty() ) {
4158 QFile file( fileName );
4159 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
4162 QTextStream out( &file );
4163 myCtrlInfo->saveInfo( out );
4169 \brief Show documentation on dialog.
4171 void SMESHGUI_CtrlInfoDlg::help()
4173 SMESH::ShowHelpFile( "mesh_infos.html#mesh-quality-info-anchor" );