1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, 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 Field widget.
72 ////////////////////////////////////////////////////////////////////////////////
74 class Field : public QLabel
77 Field( QWidget*, const QString& = QString() );
78 bool event( QEvent* );
83 \param parent Parent widget.
84 \param name Field name. Defaults to null string.
86 Field::Field( 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 Field::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 Field's object. Default to null string.
338 QLabel* createField( QWidget* parent, const QString& name = QString() )
340 return new Field( 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_MinimumAngle:
1678 title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
1679 case SMESH::FT_Taper:
1680 title = tr( "TAPER_ELEMENTS" ); break;
1681 case SMESH::FT_Skew:
1682 title = tr( "SKEW_ELEMENTS" ); break;
1683 case SMESH::FT_Area:
1684 title = tr( "AREA_ELEMENTS" ); break;
1685 case SMESH::FT_Volume3D:
1686 title = tr( "VOLUME_3D_ELEMENTS" ); break;
1687 case SMESH::FT_MaxElementLength2D:
1688 title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
1689 case SMESH::FT_MaxElementLength3D:
1690 title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
1691 case SMESH::FT_Length:
1692 title = tr( "LENGTH_EDGES" ); break;
1693 case SMESH::FT_Length2D:
1694 case SMESH::FT_Length3D:
1695 title = tr( "MIN_ELEM_EDGE" ); break;
1696 case SMESH::FT_BallDiameter:
1697 title = tr( "BALL_DIAMETER" ); break;
1705 \brief Write information on given mesh nodes / elements.
1706 \param writer Information writer.
1707 \param ids Nodes / elements IDs.
1709 void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
1714 bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1715 int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ?
1716 SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
1719 SMESH::Connectivity connectivity;
1720 SMESH::Position position;
1723 foreach ( uint id, ids )
1725 writer->separator();
1727 if ( what() == ShowNodes )
1730 // - check that node exists
1731 if ( !proxy().hasNode( id ) )
1734 writer->write( tr( "NODE" ), (int)id, true );
1737 ok = proxy().nodeCoordinates( id, xyz );
1740 writer->write( tr( "COORDINATES" ), xyz );
1743 ok = proxy().nodeConnectivity( id, connectivity );
1746 if ( !connectivity.isEmpty() )
1748 writer->write( tr( "CONNECTIVITY" ) );
1750 for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
1752 QString formatted = formatConnectivity( connectivity, i );
1753 if ( !formatted.isEmpty() )
1754 writer->write( type2str( i, true ), formatted );
1760 writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
1764 ok = proxy().nodePosition( id, position );
1765 if ( ok && position.isValid() )
1767 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1769 if ( position.hasU() )
1770 writer->write( tr("U_POSITION"), position.u() );
1771 if ( position.hasV() )
1772 writer->write( tr("V_POSITION"), position.v() );
1775 // - groups node belongs to
1776 QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
1777 bool topCreated = false;
1778 foreach( SMESH::SelectionProxy group, groups )
1780 if ( group && !group.name().isEmpty() )
1784 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1788 writer->write( group.name().trimmed() ); // trim name
1792 int type = group.type();
1793 if ( type == SMESH::SelectionProxy::GroupStd )
1795 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1797 else if ( type == SMESH::SelectionProxy::GroupGeom )
1799 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1800 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1802 else if ( type == SMESH::SelectionProxy::GroupFilter )
1804 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1806 int size = group.size();
1808 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1809 QColor color = group.color();
1810 if ( color.isValid() )
1811 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1820 else if ( what() == ShowElements )
1822 // show element info
1823 // - check that element exists
1824 if ( !proxy().hasElement( id ) )
1827 int type = proxy().elementType( id );
1828 if ( type == SMESH::ALL )
1830 writer->write( type2str( type ), (int)id, true );
1833 type = proxy().elementEntityType( id );
1834 writer->write( tr( "TYPE" ), etype2str( type ) );
1836 if ( type == SMESH::Entity_Polyhedra ||
1837 type == SMESH::Entity_Quad_Polyhedra )
1840 ok = proxy().perFaceConnectivity( id, connectivity, nbNodes );
1841 if ( ok && !connectivity.isEmpty() )
1843 writer->write( tr( "NB_NODES" ), nbNodes );
1844 writer->write( tr( "CONNECTIVITY" ) );
1846 int nbFaces = connectivity.size();
1847 for ( int iF = 1; iF <= nbFaces; ++iF )
1849 QString formatted = formatConnectivity( connectivity, -iF );
1850 writer->write(( type2str( SMDSAbs_Face, 0 ) + " %1 / %2" ).arg( iF ).arg( nbFaces ),
1858 ok = proxy().elementConnectivity( id, connectivity );
1859 if ( ok && !connectivity.isEmpty() )
1861 QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
1862 if ( !formatted.isEmpty() )
1864 writer->write( tr( "NB_NODES" ), connectivity[ SMDSAbs_Node ].size() );
1865 writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
1870 ok = proxy().elementPosition( id, position );
1871 if ( ok && position.isValid() )
1873 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1876 ok = proxy().elementGravityCenter( id, xyz );
1879 writer->write( tr( "GRAVITY_CENTER" ), xyz );
1882 ok = proxy().elementNormal( id, xyz );
1885 writer->write( tr( "NORMAL_VECTOR" ), xyz );
1888 bool topCreated = false;
1889 for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
1891 QString ctrlTitle = ctrl2str( i );
1892 if ( ctrlTitle.isEmpty() )
1896 writer->write( tr( "CONTROLS" ) );
1901 if ( proxy().elementControl( id, i, cprecision, value ) )
1902 writer->write( ctrlTitle, value );
1906 // - groups element belongs to
1907 QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
1909 foreach( SMESH::SelectionProxy group, groups )
1911 if ( group && !group.name().isEmpty() )
1915 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1919 writer->write( group.name().trimmed() ); // trim name
1923 int type = group.type();
1924 if ( type == SMESH::SelectionProxy::GroupStd )
1926 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1928 else if ( type == SMESH::SelectionProxy::GroupGeom )
1930 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1931 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1933 else if ( type == SMESH::SelectionProxy::GroupFilter )
1935 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1937 int size = group.size();
1939 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1940 QColor color = group.color();
1941 if ( color.isValid() )
1942 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1955 \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
1956 \brief Show information on given mesh nodes / elements.
1958 This function has to be redefined in sub-classes.
1960 \param ids Nodes / elements IDs.
1964 \brief Internal clean-up (reset panel).
1966 Default implementation does nothing; the method has to be redefined
1967 in sub-classes to perform internal clean-up.
1969 void SMESHGUI_ElemInfo::clearInternal()
1974 \brief Show previous chunk of information.
1976 void SMESHGUI_ElemInfo::showPrevious()
1978 myIndex = qMax( 0, myIndex-1 );
1980 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1984 \brief Show next chunk of information.
1986 void SMESHGUI_ElemInfo::showNext()
1988 myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
1990 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1994 \brief Update control widget state.
1996 void SMESHGUI_ElemInfo::updateControls()
1998 myExtra->updateControls( myIDs.count(), myIndex );
2002 \brief Write information from panel to output stream.
2003 \param out Text stream output.
2005 void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
2008 QString title = tr( "ELEM_INFO" );
2009 out << ruler( title.size() ) << endl;
2010 out << title << endl;
2011 out << ruler( title.size() ) << endl;
2015 StreamWriter writer( out );
2016 writeInfo( &writer, myIDs );
2020 ////////////////////////////////////////////////////////////////////////////////
2021 /// \class SMESHGUI_SimpleElemInfo
2022 /// \brief Show mesh element information in the simple text area.
2023 ////////////////////////////////////////////////////////////////////////////////
2027 \param parent Parent widget. Defaults to 0.
2029 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
2030 : SMESHGUI_ElemInfo( parent )
2032 myInfo = new QTextBrowser( centralWidget() );
2033 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2035 l->addWidget( myInfo );
2037 connect( myInfo, SIGNAL( anchorClicked(QUrl)), this, SLOT( connectivityClicked( QUrl )));
2041 \brief Show mesh element information.
2042 \param ids Nodes / elements IDs.
2044 void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
2047 TextWriter writer( myInfo );
2048 writeInfo( &writer, ids );
2052 \brief Internal clean-up (reset widget)
2054 void SMESHGUI_SimpleElemInfo::clearInternal()
2059 void SMESHGUI_SimpleElemInfo::connectivityClicked(const QUrl & url)
2061 int type = ( url.scheme()[0] == 'n' ) ? NodeConnectivity : ElemConnectivity;
2062 QString ids = url.path(); // excess chars will be filtered off by SMESHGUI_IdValidator
2063 emit( itemInfo( type, ids ));
2066 ////////////////////////////////////////////////////////////////////////////////
2067 /// \class SMESHGUI_TreeElemInfo::ItemDelegate
2068 /// \brief Item delegate for tree mesh info widget.
2070 ////////////////////////////////////////////////////////////////////////////////
2072 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
2075 ItemDelegate( QObject* );
2076 QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
2083 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
2088 \brief Redefined from QItemDelegate.
2091 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
2093 QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
2094 if ( qobject_cast<QLineEdit*>( w ) )
2095 qobject_cast<QLineEdit*>( w )->setReadOnly( true );
2099 ////////////////////////////////////////////////////////////////////////////////
2100 /// \class SMESHGUI_TreeElemInfo::ItemCreator
2101 /// \brief Item creator for tree mesh info widget.
2103 ////////////////////////////////////////////////////////////////////////////////
2105 class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
2107 SMESHGUI_TreeElemInfo* myView;
2109 ItemCreator( SMESHGUI_TreeElemInfo* );
2110 QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
2115 \param view Parent view.
2118 SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
2123 \brief Create new tree item.
2124 \param parent Parent tree item.
2125 \param options Item options.
2126 \return New tree widget item.
2129 QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
2131 return myView->createItem( parent, options );
2134 ////////////////////////////////////////////////////////////////////////////////
2135 /// \class SMESHGUI_TreeElemInfo
2136 /// \brief Show mesh element information as the tree.
2137 ////////////////////////////////////////////////////////////////////////////////
2141 \param parent Parent widget. Defaults to 0.
2143 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
2144 : SMESHGUI_ElemInfo( parent )
2146 myInfo = new QTreeWidget( centralWidget() );
2147 myInfo->setColumnCount( 2 );
2148 myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
2149 myInfo->header()->setStretchLastSection( true );
2150 myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2151 myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
2152 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2154 l->addWidget( myInfo );
2155 connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
2156 connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2157 connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2161 \brief Show mesh element information.
2162 \param ids Nodes / elements IDs.
2164 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
2167 TreeWriter writer( myInfo, new ItemCreator( this ) );
2168 writeInfo( &writer, ids );
2172 \brief Show node information
2173 \param node mesh node for showing
2174 \param index index of current node
2175 \param nbNodes number of unique nodes in element
2176 \param parentItem parent item of tree
2178 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* /*node*/, int /*index*/,
2179 int /*nbNodes*/, QTreeWidgetItem* /*parentItem*/ )
2181 // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
2182 // // node number and ID
2183 // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
2184 // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
2185 // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
2186 // nodeItem->setData( 1, TypeRole, ElemConnectivity );
2187 // nodeItem->setData( 1, IdRole, node->GetID() );
2188 // nodeItem->setExpanded( false );
2189 // // node coordinates
2190 // QTreeWidgetItem* coordItem = createItem( nodeItem );
2191 // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
2192 // QTreeWidgetItem* xItem = createItem( coordItem );
2193 // xItem->setText( 0, "X" );
2194 // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2195 // QTreeWidgetItem* yItem = createItem( coordItem );
2196 // yItem->setText( 0, "Y" );
2197 // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2198 // QTreeWidgetItem* zItem = createItem( coordItem );
2199 // zItem->setText( 0, "Z" );
2200 // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2201 // // node connectivity
2202 // QTreeWidgetItem* nconItem = createItem( nodeItem );
2203 // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
2204 // Connectivity connectivity = nodeConnectivity( node );
2205 // if ( !connectivity.isEmpty() ) {
2206 // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
2207 // if ( !con.isEmpty() ) {
2208 // QTreeWidgetItem* i = createItem( nconItem );
2209 // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
2210 // i->setText( 1, con );
2212 // con = formatConnectivity( connectivity, SMDSAbs_Edge );
2213 // if ( !con.isEmpty() ) {
2214 // QTreeWidgetItem* i = createItem( nconItem );
2215 // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
2216 // i->setText( 1, con );
2217 // i->setData( 1, TypeRole, NodeConnectivity );
2219 // con = formatConnectivity( connectivity, SMDSAbs_Ball );
2220 // if ( !con.isEmpty() ) {
2221 // QTreeWidgetItem* i = createItem( nconItem );
2222 // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
2223 // i->setText( 1, con );
2224 // i->setData( 1, TypeRole, NodeConnectivity );
2226 // con = formatConnectivity( connectivity, SMDSAbs_Face );
2227 // if ( !con.isEmpty() ) {
2228 // QTreeWidgetItem* i = createItem( nconItem );
2229 // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
2230 // i->setText( 1, con );
2231 // i->setData( 1, TypeRole, NodeConnectivity );
2233 // con = formatConnectivity( connectivity, SMDSAbs_Volume );
2234 // if ( !con.isEmpty() ) {
2235 // QTreeWidgetItem* i = createItem( nconItem );
2236 // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
2237 // i->setText( 1, con );
2238 // i->setData( 1, TypeRole, NodeConnectivity );
2243 \brief Internal clean-up (reset widget)
2245 void SMESHGUI_TreeElemInfo::clearInternal()
2252 \brief Create new item and add it to the tree.
2253 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2254 \param options Item flags. Defaults to 0 (none).
2255 \return New tree widget item.
2257 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
2259 QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
2260 setTreeItemAttributes( item, options | Expanded | Editable );
2262 if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
2264 QString resName = expandedResource( parent );
2265 parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
2271 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2273 QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2274 if ( widgets.isEmpty() ) return;
2275 QTreeWidgetItem* aTreeItem = widgets.first();
2276 int type = aTreeItem->data( 1, TypeRole ).toInt();
2277 if (( type == ElemConnectivity || type == NodeConnectivity ) &&
2278 ( !aTreeItem->text( 1 ).isEmpty() ))
2281 QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
2282 if ( menu.exec( e->globalPos() ) == a )
2283 emit( itemInfo( type, aTreeItem->text( 1 )) );
2287 void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int /*theColumn*/ )
2290 int type = theItem->data( 1, TypeRole ).toInt();
2291 emit( itemInfo( type, theItem->text( 1 )) );
2295 void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
2298 SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
2301 QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
2303 return QString("Expanded_") + ( what()==ShowElements ? "E_" : "N_" ) + theItem->text(0);
2306 ////////////////////////////////////////////////////////////////////////////////
2307 /// \class InfoComputor
2308 /// \brief Mesh information computor.
2311 /// The class is created for different computation operations. Currently it is
2312 /// used to compute size and number of underlying nodes for given group.
2313 ////////////////////////////////////////////////////////////////////////////////
2317 \param parent Parent object.
2318 \param proxy Object to compute information on (group).
2319 \param item Tree widget item, referenced by this computer.
2320 \param operation Value to compute.
2323 InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
2324 : QObject( parent ), myProxy( proxy ), myOperation( operation )
2329 \brief Compute requested information.
2332 void InfoComputor::compute()
2336 SUIT_OverrideCursor wc;
2338 switch ( myOperation )
2341 myProxy.size( true ); // force size computation
2345 myProxy.nbNodes( true ); // force size computation
2354 ////////////////////////////////////////////////////////////////////////////////
2355 /// \class SMESHGUI_AddInfo
2356 /// \brief Show additional information on selected object.
2358 /// Displays an additional information about selected object: mesh, sub-mesh
2361 /// \todo Rewrite saveInfo() method to print all data, not currently shown only.
2362 ////////////////////////////////////////////////////////////////////////////////
2366 \param parent Parent widget. Defaults to 0.
2368 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
2370 QVBoxLayout* l = new QVBoxLayout( this );
2372 l->setSpacing( SPACING );
2374 myTree = new QTreeWidget( this );
2376 myTree->setColumnCount( 2 );
2377 myTree->header()->setStretchLastSection( true );
2378 myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2379 myTree->header()->hide();
2381 l->addWidget( myTree );
2387 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2392 \brief Show information on given object.
2393 \param proxy Object to show information on (mesh, sub-mesh, group).
2395 void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
2398 setProperty( "group_index", 0 );
2399 setProperty( "submesh_index", 0 );
2400 myComputors.clear();
2403 // then fill panel with data if object is not null
2409 QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
2410 nameItem->setText( 0, tr( "NAME" ) );
2411 nameItem->setText( 1, proxy.name() );
2414 if ( proxy.type() == SMESH::SelectionProxy::Mesh )
2415 meshInfo( proxy, nameItem );
2416 else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
2417 subMeshInfo( proxy, nameItem );
2418 else if ( proxy.type() >= SMESH::SelectionProxy::Group )
2419 groupInfo( proxy, nameItem );
2424 \brief Update information in panel.
2426 void SMESHGUI_AddInfo::updateInfo()
2428 showInfo( myProxy );
2432 \brief Reset panel (clear all data).
2434 void SMESHGUI_AddInfo::clear()
2440 \brief Create new item and add it to the tree.
2441 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2442 \param options Item flags. Defaults to 0 (none).
2443 \return New tree widget item.
2445 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
2447 QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
2448 new QTreeWidgetItem( myTree->invisibleRootItem() );
2449 setTreeItemAttributes( item, options | Expanded );
2454 \brief Show information on mesh.
2455 \param proxy Proxy object (mesh).
2456 \param parent Parent tree item.
2458 void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2463 QString shapeName = proxy.shapeName();
2464 SMESH::MedInfo inf = proxy.medFileInfo();
2467 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2468 typeItem->setText( 0, tr( "TYPE" ) );
2469 if ( !shapeName.isEmpty() )
2471 typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2473 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2474 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2475 gobjItem->setText( 1, shapeName );
2477 else if ( inf.isValid() )
2479 typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2480 // med file information
2481 QTreeWidgetItem* fileItem = createItem( parent, Bold );
2482 fileItem->setText( 0, tr( "FILE_NAME" ) );
2483 fileItem->setText( 1, inf.fileName() );
2484 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2485 sizeItem->setText( 0, tr( "FILE_SIZE" ) );
2486 sizeItem->setText( 1, QString::number( inf.size() ) );
2487 QTreeWidgetItem* versionItem = createItem( parent, Bold );
2488 versionItem->setText( 0, tr( "FILE_VERSION" ) );
2489 versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
2493 typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2497 myGroups = proxy.groups();
2501 mySubMeshes = proxy.submeshes();
2506 \brief Show information on sub-mesh.
2507 \param proxy Proxy object (sub-mesh).
2508 \param parent Parent tree item.
2510 void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2515 bool isShort = parent->parent() != 0;
2520 SMESH::SelectionProxy meshProxy = proxy.mesh();
2523 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2524 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2525 nameItem->setText( 1, meshProxy.name() );
2530 QString shapeName = proxy.shapeName();
2531 if ( !shapeName.isEmpty() )
2533 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2534 gobjItem->setText( 1, shapeName );
2539 \brief Show information on group.
2540 \param proxy Proxy object (group).
2541 \param parent Parent tree item.
2543 void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2548 bool isShort = parent->parent() != 0;
2553 SMESH::SelectionProxy meshProxy = proxy.mesh();
2556 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2557 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2558 nameItem->setText( 1, meshProxy.name() );
2563 SMESH::SelectionProxy::Type type = proxy.type();
2564 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2565 typeItem->setText( 0, tr( "TYPE" ) );
2566 if ( type == SMESH::SelectionProxy::GroupStd )
2568 typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2570 else if ( type == SMESH::SelectionProxy::GroupGeom )
2572 typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2574 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2575 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2576 gobjItem->setText( 1, proxy.shapeName() );
2578 else if ( type == SMESH::SelectionProxy::GroupFilter )
2580 typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2584 int etype = proxy.groupElementType();
2587 QString typeName = tr( "UNKNOWN" );
2591 typeName = tr( "NODE" );
2594 typeName = tr( "EDGE" );
2597 typeName = tr( "FACE" );
2600 typeName = tr( "VOLUME" );
2603 typeName = tr( "0DELEM" );
2606 typeName = tr( "BALL" );
2611 QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2612 etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2613 etypeItem->setText( 1, typeName );
2617 // note: size is not computed for group on filter for performance reasons, see IPAL52831
2618 bool meshLoaded = proxy.isMeshLoaded();
2619 int size = proxy.size();
2621 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2622 sizeItem->setText( 0, tr( "SIZE" ) );
2625 sizeItem->setText( 1, QString::number( size ) );
2629 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2630 myTree->setItemWidget( sizeItem, 1, btn );
2631 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
2632 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2633 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2634 myComputors.append( comp );
2638 QTreeWidgetItem* colorItem = createItem( parent, Bold );
2639 colorItem->setText( 0, tr( "COLOR" ) );
2640 colorItem->setBackground( 1, proxy.color() );
2642 // nb of underlying nodes
2643 if ( etype != SMESH::NODE )
2645 QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2646 nodesItem->setText( 0, tr( "NB_NODES" ) );
2648 int nbNodes = proxy.nbNodes();
2651 nodesItem->setText( 1, QString::number( nbNodes ) );
2655 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2656 myTree->setItemWidget( nodesItem, 1, btn );
2657 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
2658 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2659 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2660 myComputors.append( comp );
2666 \brief Update information on child groups.
2668 void SMESHGUI_AddInfo::showGroups()
2670 // remove all computors
2671 myComputors.clear();
2673 // tree root should be the first top level item
2674 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2678 int idx = property( "group_index" ).toInt();
2680 // find sub-meshes top-level container item
2681 QTreeWidgetItem* itemGroups = 0;
2682 for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
2684 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
2686 itemGroups = parent->child( i );
2688 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
2690 extra->updateControls( myGroups.count(), idx );
2691 // clear: remove all group items
2692 while ( itemGroups->childCount() )
2693 delete itemGroups->child( 0 );
2697 QMap<int, QTreeWidgetItem*> grpItems;
2698 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
2700 SMESH::SelectionProxy grp = myGroups[i];
2704 int grpType = grp.groupElementType();
2706 // create top-level groups container item if it does not exist
2709 itemGroups = createItem( parent, Bold | AllColumns );
2710 itemGroups->setText( 0, tr( "GROUPS" ) );
2711 itemGroups->setData( 0, Qt::UserRole, GroupsId );
2713 // if necessary, create extra widget to show information by chunks
2714 if ( myGroups.count() > blockSize() )
2716 ExtraWidget* extra = new ExtraWidget( this, true );
2717 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2718 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2719 myTree->setItemWidget( itemGroups, 1, extra );
2720 extra->updateControls( myGroups.count(), idx );
2724 // create container item corresponding to particular element type
2725 if ( !grpItems.contains( grpType ) )
2727 grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
2728 grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2729 itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
2733 QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
2734 nameItem->setText( 0, grp.name().trimmed() ); // trim name
2737 groupInfo( grp, nameItem );
2742 \brief Update information on child sub-meshes.
2744 void SMESHGUI_AddInfo::showSubMeshes()
2746 // tree root should be the first top level item
2747 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2751 int idx = property( "submesh_index" ).toInt();
2753 // find sub-meshes top-level container item
2754 QTreeWidgetItem* itemSubMeshes = 0;
2755 for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
2757 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
2759 itemSubMeshes = parent->child( i );
2761 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
2763 extra->updateControls( mySubMeshes.count(), idx );
2764 // clear: remove all sub-mesh items
2765 while ( itemSubMeshes->childCount() )
2766 delete itemSubMeshes->child( 0 );
2770 QMap<int, QTreeWidgetItem*> smItems;
2771 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
2773 SMESH::SelectionProxy sm = mySubMeshes[i];
2777 int smType = sm.shapeType();
2780 else if ( smType == GEOM::COMPSOLID )
2781 smType = GEOM::COMPOUND;
2783 // create top-level sub-meshes container item if it does not exist
2784 if ( !itemSubMeshes )
2786 itemSubMeshes = createItem( parent, Bold | AllColumns );
2787 itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2788 itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
2790 // if necessary, create extra widget to show information by chunks
2791 if ( mySubMeshes.count() > blockSize() )
2793 ExtraWidget* extra = new ExtraWidget( this, true );
2794 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2795 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2796 myTree->setItemWidget( itemSubMeshes, 1, extra );
2797 extra->updateControls( mySubMeshes.count(), idx );
2801 // create container item corresponding to particular shape type
2802 if ( !smItems.contains( smType ) )
2804 smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
2805 smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2806 itemSubMeshes->insertChild( smType, smItems[ smType ] );
2810 QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
2811 nameItem->setText( 0, sm.name().trimmed() ); // trim name
2814 subMeshInfo( sm, nameItem );
2819 \brief Show previous chunk of information on child groups.
2821 void SMESHGUI_AddInfo::showPreviousGroups()
2823 int idx = property( "group_index" ).toInt();
2824 setProperty( "group_index", idx-1 );
2829 \brief Show next chunk of information on child groups.
2831 void SMESHGUI_AddInfo::showNextGroups()
2833 int idx = property( "group_index" ).toInt();
2834 setProperty( "group_index", idx+1 );
2839 \brief Show previous chunk of information on child sub-meshes.
2841 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2843 int idx = property( "submesh_index" ).toInt();
2844 setProperty( "submesh_index", idx-1 );
2849 \brief Show next chunk of information on child sub-meshes.
2851 void SMESHGUI_AddInfo::showNextSubMeshes()
2853 int idx = property( "submesh_index" ).toInt();
2854 setProperty( "submesh_index", idx+1 );
2859 \brief Write information from panel to output stream.
2860 \param out Text stream output.
2862 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2865 QString title = tr( "ADDITIONAL_INFO" );
2866 out << ruler( title.size() ) << endl;
2867 out << title << endl;
2868 out << ruler( title.size() ) << endl;
2872 QTreeWidgetItemIterator it( myTree );
2875 if ( !( ( *it )->text(0) ).isEmpty() )
2877 out << indent( itemDepth( *it ) ) << ( *it )->text(0);
2878 if ( ( *it )->text(0) == tr( "COLOR" ) )
2879 out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
2880 else if ( !( ( *it )->text(1) ).isEmpty() )
2881 out << ":" << spacing() << ( *it )->text(1);
2889 ////////////////////////////////////////////////////////////////////////////////
2890 /// \class GroupCombo
2891 /// \brief Customized combo box to manage list of mesh groups.
2893 ////////////////////////////////////////////////////////////////////////////////
2895 class GroupCombo: public QComboBox
2897 class Item: public QStandardItem
2900 SMESH::SelectionProxy myGroup;
2901 Item( const SMESH::SelectionProxy& group )
2904 setText( myGroup.name() );
2906 SMESH::SelectionProxy group()
2912 SMESH::SelectionProxy myProxy;
2915 GroupCombo( QWidget* );
2916 void setSource( const SMESH::SelectionProxy& );
2917 SMESH::SelectionProxy currentGroup() const;
2922 \param parent Parent widget.
2925 GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
2927 setModel( new QStandardItemModel( this ) );
2931 \brief Set mesh source.
2932 \param obj Mesh source.
2935 void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
2937 if ( myProxy == proxy )
2942 bool blocked = blockSignals( true );
2943 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2948 if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
2950 QList<SMESH::SelectionProxy> groups = myProxy.groups();
2951 for ( int i = 0; i < groups.count(); ++i )
2955 QString name = groups[i].name();
2956 if ( !name.isEmpty() )
2957 m->appendRow( new Item( groups[i] ) );
2960 setCurrentIndex( -1 ); // for performance reasons
2962 else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
2964 m->appendRow( new Item( myProxy ) );
2965 setCurrentIndex( 0 );
2969 blockSignals( blocked );
2973 \brief Get currently selected group.
2974 \return Selected group.
2977 SMESH::SelectionProxy GroupCombo::currentGroup() const
2979 SMESH::SelectionProxy group;
2980 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2981 if ( currentIndex() >= 0 )
2982 group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
2986 ////////////////////////////////////////////////////////////////////////////////
2987 /// \class SMESHGUI_MeshInfoDlg
2988 /// \brief Mesh information dialog box
2990 /// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
2991 /// \todo Add selection button to reactivate selection on move from other dlg.
2992 ////////////////////////////////////////////////////////////////////////////////
2996 \param parent Parent widget.
2997 \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
2999 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
3003 setAttribute( Qt::WA_DeleteOnClose, true );
3004 setWindowTitle( tr( "MESH_INFO" ) );
3005 setSizeGripEnabled( true );
3007 myTabWidget = new QTabWidget( this );
3011 myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
3012 myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
3016 QWidget* w = new QWidget( myTabWidget );
3018 myMode = new QButtonGroup( this );
3019 myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
3020 myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
3021 myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
3022 myMode->button( NodeMode )->setChecked( true );
3023 myID = new QLineEdit( w );
3024 myID->setValidator( new SMESHGUI_IdValidator( this ) );
3025 myGroups = new GroupCombo( w );
3026 QStackedWidget* stack = new QStackedWidget( w );
3027 stack->addWidget( myID );
3028 stack->addWidget( myGroups );
3029 myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
3030 myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
3032 int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
3033 mode = qMin( 1, qMax( 0, mode ) );
3036 myElemInfo = new SMESHGUI_SimpleElemInfo( w );
3038 myElemInfo = new SMESHGUI_TreeElemInfo( w );
3039 stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
3041 QGridLayout* elemLayout = new QGridLayout( w );
3042 elemLayout->setMargin( MARGIN );
3043 elemLayout->setSpacing( SPACING );
3044 elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
3045 elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
3046 elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
3047 elemLayout->addWidget( stack, 0, 3 );
3048 elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
3049 elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
3051 myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
3055 myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
3056 myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
3060 myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
3061 myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
3065 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3066 okBtn->setAutoDefault( true );
3067 okBtn->setDefault( true );
3069 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3070 dumpBtn->setAutoDefault( true );
3071 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3072 helpBtn->setAutoDefault( true );
3074 QHBoxLayout* btnLayout = new QHBoxLayout;
3075 btnLayout->setSpacing( SPACING );
3076 btnLayout->setMargin( 0 );
3078 btnLayout->addWidget( okBtn );
3079 btnLayout->addWidget( dumpBtn );
3080 btnLayout->addStretch( 10 );
3081 btnLayout->addWidget( helpBtn );
3085 QVBoxLayout* l = new QVBoxLayout ( this );
3086 l->setMargin( MARGIN );
3087 l->setSpacing( SPACING );
3088 l->addWidget( myTabWidget );
3089 l->addLayout( btnLayout );
3093 myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
3095 // set-up connections
3097 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3098 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3099 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3100 connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
3101 connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
3102 connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
3103 connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
3104 connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
3105 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3106 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3107 connect( myElemInfo, SIGNAL( itemInfo( int, QString ) ), this, SLOT( showItemInfo( int, QString ) ) );
3108 connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
3112 myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
3119 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
3125 \brief Show mesh information on given object.
3126 \param io Interactive object.
3128 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3131 showInfo( SMESH::SelectionProxy( io ) );
3135 \brief Show mesh information on given object.
3136 \param proxy Selection proxy.
3138 void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3140 SUIT_OverrideCursor wc;
3147 SMESH::SMESH_IDSource_var obj = myProxy.object();
3150 myBaseInfo->showInfo( proxy );
3152 // "Additional info" tab
3153 myAddInfo->showInfo( proxy );
3155 // "Quality info" tab
3156 // Note: for performance reasons we update it only if it is currently active
3157 if ( myTabWidget->currentIndex() == CtrlInfo )
3158 myCtrlInfo->showInfo( proxy );
3160 // "Element info" tab
3161 myGroups->setSource( proxy );
3162 if ( myMode->checkedId() == GroupMode ) {
3163 SMESH::SelectionProxy group = myGroups->currentGroup();
3165 myElemInfo->showInfo( group );
3167 myElemInfo->clear();
3170 SVTK_Selector* selector = SMESH::GetSelector();
3173 if ( myProxy.actor() && selector ) { //todo: actor()?
3174 nb = myMode->checkedId() == NodeMode ?
3175 SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
3176 SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
3179 myID->setText( ID.trimmed() );
3181 QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
3182 foreach ( ID, idTxt )
3183 ids << ID.trimmed().toUInt();
3184 myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
3188 myElemInfo->clear();
3194 \brief Update information.
3196 void SMESHGUI_MeshInfoDlg::updateInfo()
3198 SALOME_ListIO selected;
3199 SMESHGUI::selectionMgr()->selectedObjects( selected );
3201 if ( selected.Extent() == 1 )
3202 showInfo( selected.First() );
3204 showInfo( myProxy );
3208 \brief Clean-up on dialog closing.
3210 void SMESHGUI_MeshInfoDlg::reject()
3212 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3213 selMgr->clearFilters();
3214 SMESH::SetPointRepresentation( false );
3215 if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
3216 viewWindow->SetSelectionMode( ActorSelection );
3218 myIDPreview->SetPointsLabeled( false );
3222 \brief Process keyboard event.
3223 \param e Key press event.
3225 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
3227 QDialog::keyPressEvent( e );
3228 if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
3235 \brief Set-up selection mode for currently selected page.
3237 void SMESHGUI_MeshInfoDlg::updateSelection()
3239 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3241 disconnect( selMgr, 0, this, 0 );
3242 selMgr->clearFilters();
3244 int selMode = ActorSelection;
3245 if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == NodeMode )
3246 selMode = NodeSelection;
3247 else if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == ElemMode )
3248 selMode = CellSelection;
3249 SMESH::SetPointRepresentation( selMode == NodeSelection );
3250 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3251 aViewWindow->SetSelectionMode( selMode );
3253 SMESH::SelectionProxy previous = myProxy;
3254 QString ids = myID->text().trimmed();
3257 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3260 if ( myProxy && myProxy == previous && !ids.isEmpty() ) {
3261 myID->setText( ids );
3267 \brief Show documentation on selected dialog page.
3269 void SMESHGUI_MeshInfoDlg::help()
3271 QString helpPage = "mesh_infos.html";
3272 switch ( myTabWidget->currentIndex() )
3275 helpPage += "#advanced-mesh-infos-anchor";
3278 helpPage += "#mesh-element-info-anchor";
3281 helpPage += "#mesh-addition-info-anchor";
3284 helpPage += "#mesh-quality-info-anchor";
3289 SMESH::ShowHelpFile( helpPage );
3293 \brief Deactivate dialog box.
3295 void SMESHGUI_MeshInfoDlg::deactivate()
3297 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3301 \brief Called when users switches between node / element modes.
3303 void SMESHGUI_MeshInfoDlg::modeChanged()
3305 emit( switchMode( myMode->checkedId() == GroupMode ? 1 : 0 ) );
3311 \brief Called when users prints mesh element ID in the corresponding field.
3313 void SMESHGUI_MeshInfoDlg::idChanged()
3315 myIDPreview->SetPointsLabeled( false );
3320 std::vector<int> idVec;
3321 std::list< gp_XYZ > aGrCentersXYZ;
3323 const bool isElem = ( myMode->checkedId() == ElemMode );
3324 QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
3325 foreach ( QString tid, idTxt ) {
3326 long id = tid.toUInt();
3327 if ( isElem ? myProxy.hasElement( id ) : myProxy.hasNode( id ))
3331 if ( isElem && myProxy.actor() && myProxy.elementGravityCenter( id, xyz ))
3333 idVec.push_back( id );
3334 aGrCentersXYZ.push_back( xyz );
3338 SVTK_Selector* selector = SMESH::GetSelector();
3339 if ( myProxy.actor() && selector ) {
3340 Handle(SALOME_InteractiveObject) IO = myProxy.actor()->getIO();
3341 selector->AddOrRemoveIndex( IO, ID, false );
3342 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3344 if ( myMode->checkedId() == NodeMode )
3345 myIDPreview->SetPointsData( myProxy.actor()->GetObject()->GetMesh(), ID );
3347 myIDPreview->SetElemsData( idVec, aGrCentersXYZ );
3349 bool showIDs = ( !ID.IsEmpty() &&
3350 myIDPreviewCheck->isChecked() &&
3351 myTabWidget->currentIndex() == ElemInfo );
3352 myIDPreview->SetPointsLabeled( showIDs, myProxy.actor()->GetVisibility() );
3354 aViewWindow->highlight( IO, true, true );
3355 aViewWindow->Repaint();
3358 myElemInfo->showInfo( myProxy, ids, isElem );
3363 * \brief Show IDs clicked
3365 void SMESHGUI_MeshInfoDlg::idPreviewChange( bool isOn )
3367 myIDPreview->SetPointsLabeled( isOn && !myID->text().simplified().isEmpty() );
3368 SMESHGUI::resourceMgr()->setValue("SMESH", "id_preview_resource", isOn );
3369 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3370 aViewWindow->Repaint();
3373 void SMESHGUI_MeshInfoDlg::showItemInfo( int type, const QString& ids )
3375 if ( !ids.isEmpty() && ( type == NodeConnectivity || type == ElemConnectivity )) {
3376 myMode->button( type - NodeConnectivity )->click();
3377 myID->setText( ids );
3382 \brief Dump information to file.
3384 void SMESHGUI_MeshInfoDlg::dump()
3386 DumpFileDlg fd( this );
3387 fd.setWindowTitle( tr( "SAVE_INFO" ) );
3388 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
3389 fd.setChecked( BaseInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_base", true ) );
3390 fd.setChecked( ElemInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_elem", true ) );
3391 fd.setChecked( AddInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_add", true ) );
3392 fd.setChecked( CtrlInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_ctrl", true ) );
3393 if ( fd.exec() == QDialog::Accepted )
3395 QString fileName = fd.selectedFile();
3396 if ( !fileName.isEmpty() ) {
3397 QFile file( fileName );
3398 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
3401 QTextStream out( &file );
3402 if ( fd.isChecked( BaseInfo ) ) myBaseInfo->saveInfo( out );
3403 if ( fd.isChecked( ElemInfo ) ) myElemInfo->saveInfo( out );
3404 if ( fd.isChecked( AddInfo ) ) myAddInfo->saveInfo( out );
3405 if ( fd.isChecked( CtrlInfo ) )
3407 myCtrlInfo->showInfo( myProxy ); // it saves what is shown only
3408 myCtrlInfo->saveInfo( out );
3414 ////////////////////////////////////////////////////////////////////////////////
3415 /// \class SMESHGUI_CtrlInfo
3416 /// \brief Show quality statistics information on selected object.
3418 /// Displays quality controls statistics about selected object: mesh, sub-mesh,
3419 /// group or arbitrary ID source.
3420 ////////////////////////////////////////////////////////////////////////////////
3424 \param parent Parent widget. Defaults to 0.
3426 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent ): SMESHGUI_Info( parent )
3428 QGridLayout* l = new QGridLayout( this );
3429 l->setMargin( MARGIN );
3430 l->setSpacing( SPACING );
3432 QIcon aComputeIcon( SUIT_Session::session()->resourceMgr()->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3433 SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3435 // QToolBox with MeshInfo
3436 myMeshTB = new QToolBox(this);
3439 QLabel* aNameLab = createLabel( tr( "NAME_LAB" ), this, Bold );
3440 QLabel* aName = createField( this, "ctrlName" );
3441 aName->setMinimumWidth( 150 );
3445 QLabel* aNodesLab = createLabel( tr( "NODES_INFO" ), this, Bold );
3446 QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3447 QLabel* aNodesFree = createField( this, "ctrlNodesFree" );
3448 myWidgets << aNodesFree;
3449 myPredicates << aFilterMgr->CreateFreeNodes();
3451 QLabel* aNodesNbConnLab = new QLabel( tr( "MAX_NODE_CONNECTIVITY" ), this );
3452 QLabel* aNodesNbConn = createField( this, "ctrlNodesCnty" );
3453 myWidgets << aNodesNbConn;
3454 myNodeConnFunctor = aFilterMgr->CreateNodeConnectivityNumber();
3456 QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3457 QLabel* aNodesDouble = createField( this, "ctrlNodesDouble" );
3458 myWidgets << aNodesDouble;
3459 myPredicates << aFilterMgr->CreateEqualNodes();
3460 QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3461 myToleranceWidget = new SMESHGUI_SpinBox( this );
3462 myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3463 myToleranceWidget->setAcceptNames( false );
3464 myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3467 QLabel* anEdgesLab = createLabel( tr( "EDGES_INFO" ), this, Bold );
3468 QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ), this );
3469 QLabel* anEdgesDouble = createField( this, "ctrlEdgesDouble" );
3470 myWidgets << anEdgesDouble;
3471 myPredicates << aFilterMgr->CreateEqualEdges();
3474 QLabel* aFacesLab = createLabel( tr( "FACES_INFO" ), this, Bold );
3475 QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3476 QLabel* aFacesDouble = createField( this, "ctrlFacesDouble" );
3477 myWidgets << aFacesDouble;
3478 myPredicates << aFilterMgr->CreateEqualFaces();
3479 QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3480 QLabel* aFacesOver = createField( this, "ctrlFacesOver" );
3481 myWidgets << aFacesOver;
3482 myPredicates << aFilterMgr->CreateOverConstrainedFace();
3483 QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3484 myPlot = createPlot( this );
3485 myAspectRatio = aFilterMgr->CreateAspectRatio();
3488 QLabel* aVolumesLab = createLabel( tr( "VOLUMES_INFO" ), this, Bold );
3489 QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3490 QLabel* aVolumesDouble = createField( this, "ctrlVolumesDouble" );
3491 myWidgets << aVolumesDouble;
3492 myPredicates << aFilterMgr->CreateEqualVolumes();
3493 QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3494 QLabel* aVolumesOver = createField( this, "ctrlVolumesOver" );
3495 myWidgets << aVolumesOver;
3496 myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3497 QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3498 myPlot3D = createPlot( this );
3499 myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3501 QToolButton* aFreeNodesBtn = new QToolButton( this );
3502 aFreeNodesBtn->setIcon(aComputeIcon);
3503 myButtons << aFreeNodesBtn; //0
3505 QToolButton* aNodesNbConnBtn = new QToolButton( this );
3506 aNodesNbConnBtn->setIcon(aComputeIcon);
3507 myButtons << aNodesNbConnBtn; //1
3509 QToolButton* aDoubleNodesBtn = new QToolButton( this );
3510 aDoubleNodesBtn->setIcon(aComputeIcon);
3511 myButtons << aDoubleNodesBtn; //2
3513 QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3514 aDoubleEdgesBtn->setIcon(aComputeIcon);
3515 myButtons << aDoubleEdgesBtn; //3
3517 QToolButton* aDoubleFacesBtn = new QToolButton( this );
3518 aDoubleFacesBtn->setIcon(aComputeIcon);
3519 myButtons << aDoubleFacesBtn; //4
3521 QToolButton* aOverContFacesBtn = new QToolButton( this );
3522 aOverContFacesBtn->setIcon(aComputeIcon);
3523 myButtons << aOverContFacesBtn; //5
3525 QToolButton* aComputeFaceBtn = new QToolButton( this );
3526 aComputeFaceBtn->setIcon(aComputeIcon);
3527 myButtons << aComputeFaceBtn; //6
3529 QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3530 aDoubleVolumesBtn->setIcon(aComputeIcon);
3531 myButtons << aDoubleVolumesBtn; //7
3533 QToolButton* aOverContVolumesBtn = new QToolButton( this );
3534 aOverContVolumesBtn->setIcon(aComputeIcon);
3535 myButtons << aOverContVolumesBtn; //8
3537 QToolButton* aComputeVolumeBtn = new QToolButton( this );
3538 aComputeVolumeBtn->setIcon(aComputeIcon);
3539 myButtons << aComputeVolumeBtn; //9
3541 connect( aComputeFaceBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3542 connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3543 connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3544 connect( aNodesNbConnBtn, SIGNAL( clicked() ), this, SLOT( computeNodesNbConnInfo() ) );
3545 connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3546 connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3547 connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3548 connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3549 connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3550 connect( aOverContVolumesBtn,SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3551 connect( myToleranceWidget, SIGNAL( valueChanged( double ) ), this, SLOT( setTolerance( double ) ) );
3552 this->setTolerance(myToleranceWidget->GetValue());
3554 l->addWidget( aNameLab, 0, 0 ); //0
3555 l->addWidget( aName, 0, 1 ); //1
3558 QWidget* NodeGrp = new QWidget();
3559 QGridLayout* NodeLayout = new QGridLayout(NodeGrp);
3560 NodeLayout->setSpacing(SPACING); NodeLayout->setMargin(MARGIN);
3562 NodeLayout->addWidget( aNodesFreeLab, 0, 0 );
3563 NodeLayout->addWidget( aNodesFree, 0, 1 );
3564 NodeLayout->addWidget( aFreeNodesBtn, 0, 2 );
3565 NodeLayout->addWidget( aNodesNbConnLab, 1, 0 );
3566 NodeLayout->addWidget( aNodesNbConn, 1, 1 );
3567 NodeLayout->addWidget( aNodesNbConnBtn, 1, 2 );
3568 NodeLayout->addWidget( aNodesDoubleLab, 2, 0 );
3569 NodeLayout->addWidget( aNodesDouble, 2, 1 );
3570 NodeLayout->addWidget( aDoubleNodesBtn, 2, 2 );
3571 NodeLayout->addWidget( aToleranceLab, 3, 0 );
3572 NodeLayout->addWidget( myToleranceWidget, 3, 1 );
3573 NodeLayout->addWidget( myToleranceWidget, 3, 1 );
3574 NodeLayout->setRowStretch(4, 5);
3576 myMeshTB->addItem(NodeGrp, aNodesLab->text());
3577 aNodesLab->setVisible(false);
3580 QWidget* EdgeGrp = new QWidget();
3581 QGridLayout* EdgeLayout = new QGridLayout(EdgeGrp);
3582 EdgeLayout->setSpacing(SPACING); EdgeLayout->setMargin(MARGIN);
3584 EdgeLayout->addWidget( anEdgesDoubleLab, 0, 0 );
3585 EdgeLayout->addWidget( anEdgesDouble, 0, 1 );
3586 EdgeLayout->addWidget( aDoubleEdgesBtn, 0, 2 );
3587 EdgeLayout->setRowStretch(1, 5);
3589 myMeshTB->addItem(EdgeGrp, anEdgesLab->text());
3590 anEdgesLab->setVisible(false);
3593 QWidget* FaceGrp = new QWidget();
3594 QGridLayout* FaceLayout = new QGridLayout(FaceGrp);
3595 FaceLayout->setSpacing(SPACING); FaceLayout->setMargin(MARGIN);
3597 FaceLayout->addWidget( aFacesDoubleLab, 0, 0 );
3598 FaceLayout->addWidget( aFacesDouble, 0, 1 );
3599 FaceLayout->addWidget( aDoubleFacesBtn, 0, 2 );
3600 FaceLayout->addWidget( aFacesOverLab, 1, 0 );
3601 FaceLayout->addWidget( aFacesOver, 1, 1 );
3602 FaceLayout->addWidget( aOverContFacesBtn, 1, 2 );
3603 FaceLayout->addWidget( anAspectRatioLab, 2, 0 );
3604 FaceLayout->addWidget( aComputeFaceBtn, 2, 2 );
3605 FaceLayout->addWidget( myPlot, 3, 0, 1, 3 );
3607 myMeshTB->addItem(FaceGrp, aFacesLab->text());
3608 aFacesLab->setVisible(false);
3611 QWidget* VolumeGrp = new QWidget();
3612 QGridLayout* VolumeLayout = new QGridLayout(VolumeGrp);
3613 VolumeLayout->setSpacing(SPACING); VolumeLayout->setMargin(MARGIN);
3615 VolumeLayout->addWidget( aVolumesDoubleLab, 0, 0 );
3616 VolumeLayout->addWidget( aVolumesDouble, 0, 1 );
3617 VolumeLayout->addWidget( aDoubleVolumesBtn, 0, 2 );
3618 VolumeLayout->addWidget( aVolumesOverLab, 1, 0 );
3619 VolumeLayout->addWidget( aVolumesOver, 1, 1 );
3620 VolumeLayout->addWidget( aOverContVolumesBtn,1, 2 );
3621 VolumeLayout->addWidget( anAspectRatio3DLab, 2, 0 );
3622 VolumeLayout->addWidget( aComputeVolumeBtn, 2, 2 );
3623 VolumeLayout->addWidget( myPlot3D, 3, 0, 1, 3 );
3625 myMeshTB->addItem(VolumeGrp, aVolumesLab->text());
3626 aVolumesLab->setVisible(false);
3628 l->addWidget( myMeshTB, 1, 0, 1, 2 ); //2
3629 l->setRowStretch( 2, 5 );
3637 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3642 \brief Create plot widget.
3643 \param parent Parent widget.
3644 \return New plot widget.
3646 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3648 QwtPlot* aPlot = new QwtPlot( parent );
3649 aPlot->setMinimumSize( 100, 100 );
3650 QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3651 xFont.setPointSize( 5 );
3652 QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3653 yFont.setPointSize( 5 );
3654 aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3655 aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3661 \brief Show information on given object.
3662 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
3664 void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
3672 SMESH::SMESH_IDSource_var obj = proxy.object();
3674 myWidgets[0]->setText( proxy.name() );
3676 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3677 if ( mesh->_is_nil() ) return;
3679 const bool meshLoaded = mesh->IsLoaded();
3680 if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3681 // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3682 for ( int i = 0; i < myButtons.count(); ++i )
3683 myButtons[i]->setEnabled( true );
3685 SMESH::smIdType_array_var nbElemsByType = obj->GetNbElementsByType();
3686 if ( ! &nbElemsByType.in() ) return;
3688 const CORBA::Long ctrlLimit =
3689 meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3692 const SMESH::smIdType nbNodes = nbElemsByType[ SMESH::NODE ];
3693 // const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3694 // nbElemsByType[ SMESH::FACE ] +
3695 // nbElemsByType[ SMESH::VOLUME ] );
3696 if ( nbNodes > 0 ) {
3697 if ( nbNodes <= ctrlLimit ) {
3699 computeFreeNodesInfo();
3700 // node connectivity number
3701 computeNodesNbConnInfo();
3703 computeDoubleNodesInfo();
3706 myButtons[0]->setEnabled( true );
3707 myButtons[1]->setEnabled( true );
3708 myButtons[2]->setEnabled( true );
3712 myMeshTB->setItemEnabled(0, false );
3713 myMeshTB->widget(0)->setVisible( false );
3717 if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3719 if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3720 computeDoubleEdgesInfo();
3722 myButtons[3]->setEnabled( true );
3725 myMeshTB->setItemEnabled(1, false );
3726 myMeshTB->widget(1)->setVisible( false );
3730 if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3731 if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3733 computeDoubleFacesInfo();
3734 // over constrained faces
3735 computeOverConstrainedFacesInfo();
3736 // aspect Ratio histogram
3737 computeAspectRatio();
3740 myButtons[4]->setEnabled( true );
3741 myButtons[5]->setEnabled( true );
3742 myButtons[6]->setEnabled( true );
3746 myMeshTB->setItemEnabled(2, false );
3747 myMeshTB->widget(2)->setVisible( false );
3751 if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3752 if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3754 computeDoubleVolumesInfo();
3755 // over constrained volumes
3756 computeOverConstrainedVolumesInfo();
3757 // aspect Ratio 3D histogram
3758 computeAspectRatio3D();
3761 myButtons[7]->setEnabled( true );
3762 myButtons[8]->setEnabled( true );
3763 myButtons[9]->setEnabled( true );
3767 myMeshTB->setItemEnabled(3, false );
3768 myMeshTB->widget(3)->setVisible( false );
3770 myMeshTB->setCurrentIndex(0);
3771 myMeshTB->setVisible( (nbNodes + nbElemsByType[ SMESH::EDGE ] +
3772 nbElemsByType[ SMESH::FACE ] +
3773 nbElemsByType[ SMESH::VOLUME ]) > 0 );
3776 //================================================================================
3778 * \brief Computes and shows nb of elements satisfying a given predicate
3779 * \param [in] ft - a predicate type (SMESH::FunctorType)
3780 * \param [in] iBut - index of one of myButtons to disable
3781 * \param [in] iWdg - index of one of myWidgets to show the computed number
3783 //================================================================================
3785 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3787 myButtons[ iBut ]->setEnabled( false );
3788 myWidgets[ iWdg ]->setText( "" );
3793 SUIT_OverrideCursor wc;
3795 SMESH::SMESH_IDSource_var obj = myProxy.object();
3796 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3798 if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3801 showInfo( myProxy ); // try to show all values
3802 if ( !myWidgets[ iWdg ]->text().isEmpty() )
3803 return; // <ft> predicate already computed
3805 // look for a predicate of type <ft>
3806 for ( int i = 0; i < myPredicates.count(); ++i )
3807 if ( myPredicates[i]->GetFunctorType() == ft )
3809 CORBA::Long nb = myPredicates[i]->NbSatisfying( obj );
3810 myWidgets[ iWdg ]->setText( QString::number( nb ) );
3814 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3816 computeNb( SMESH::FT_FreeNodes, 0, 1 );
3819 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3821 computeNb( SMESH::FT_EqualNodes, 2, 3 );
3824 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3826 computeNb( SMESH::FT_EqualEdges, 3, 4 );
3829 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3831 computeNb( SMESH::FT_EqualFaces, 4, 5 );
3834 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3836 computeNb( SMESH::FT_OverConstrainedFace, 5, 6 );
3839 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3841 computeNb( SMESH::FT_EqualVolumes, 7, 7 );
3844 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3846 computeNb( SMESH::FT_OverConstrainedVolume, 8, 8 );
3849 void SMESHGUI_CtrlInfo::computeNodesNbConnInfo()
3851 myButtons[ 1 ]->setEnabled( false );
3852 myWidgets[ 2 ]->setText( "" );
3857 SUIT_OverrideCursor wc;
3859 SMESH::SMESH_IDSource_var obj = myProxy.object();
3860 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3862 if ( !mesh->IsLoaded() )
3865 showInfo( myProxy ); // try to show all values
3866 if ( !myWidgets[ 2 ]->text().isEmpty() )
3867 return; // already computed
3869 myNodeConnFunctor->SetMesh( mesh );
3870 SMESH::Histogram_var histogram =
3871 myNodeConnFunctor->GetLocalHistogram( 1, /*isLogarithmic=*/false, obj );
3873 myWidgets[ 2 ]->setText( QString::number( histogram[0].max ) );
3876 void SMESHGUI_CtrlInfo::computeAspectRatio()
3878 #ifndef DISABLE_PLOT2DVIEWER
3879 myButtons[6]->setEnabled( false );
3884 SUIT_OverrideCursor wc;
3886 SMESH::SMESH_IDSource_var obj = myProxy.object();
3887 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3889 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3890 if ( aHistogram && !aHistogram->isEmpty() ) {
3891 QwtPlotItem* anItem = aHistogram->createPlotItem();
3892 anItem->attach( myPlot );
3899 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3901 #ifndef DISABLE_PLOT2DVIEWER
3902 myButtons[9]->setEnabled( false );
3907 SUIT_OverrideCursor wc;
3909 SMESH::SMESH_IDSource_var obj = myProxy.object();
3910 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3912 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3913 if ( aHistogram && !aHistogram->isEmpty() ) {
3914 QwtPlotItem* anItem = aHistogram->createPlotItem();
3915 anItem->attach( myPlot3D );
3923 \brief Internal clean-up (reset widget)
3925 void SMESHGUI_CtrlInfo::clearInternal()
3927 for (int i=0; i<=3;i++) {
3928 myMeshTB->setItemEnabled(i, true );
3929 myMeshTB->widget(i)->setVisible( true );
3931 for( int i=0; i<=9; i++)
3932 myButtons[i]->setEnabled( false );
3933 myPlot->detachItems();
3934 myPlot3D->detachItems();
3937 myWidgets[0]->setText( QString() );
3938 for ( int i = 1; i < myWidgets.count(); i++ )
3939 myWidgets[i]->setText( "" );
3942 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3944 myButtons[2]->setEnabled( true );
3945 myWidgets[3]->setText("");
3946 for ( int i = 0; i < myPredicates.count(); ++i )
3947 if ( myPredicates[i]->GetFunctorType() == SMESH::FT_EqualNodes )
3949 SMESH::EqualNodes_var functor = SMESH::EqualNodes::_narrow( myPredicates[i] );
3950 if ( !functor->_is_nil() )
3951 functor->SetTolerance( theTolerance );
3955 #ifndef DISABLE_PLOT2DVIEWER
3956 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3958 SUIT_OverrideCursor wc;
3960 SMESH::SMESH_IDSource_var obj = myProxy.object();
3961 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3963 if ( !mesh->IsLoaded() )
3965 aNumFun->SetMesh( mesh );
3967 CORBA::Long cprecision = 6;
3968 if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) )
3969 cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3970 aNumFun->SetPrecision( cprecision );
3972 int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3974 SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3975 /*isLogarithmic=*/false,
3977 Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3978 aHistogram->setColor( palette().color( QPalette::Highlight ) );
3979 if ( &histogramVar.in() )
3981 for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3982 aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3983 if ( histogramVar->length() >= 2 )
3984 aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3990 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
3993 QString title = tr( "CTRL_INFO" );
3994 out << ruler( title.size() ) << endl;
3995 out << title << endl;
3996 out << ruler( title.size() ) << endl;
4000 out << tr( "NAME_LAB" ) << " " << myWidgets[0]->text() << endl;
4001 out << tr( "NODES_INFO" ) << endl;
4002 out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
4003 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_NODES" ) << ": " << myWidgets[3]->text() << endl;
4004 out << tr( "EDGES_INFO" ) << endl;
4005 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_EDGES" ) << ": " << myWidgets[4]->text() << endl;
4006 out << tr( "FACES_INFO" ) << endl;
4007 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_FACES" ) << ": " << myWidgets[5]->text() << endl;
4008 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[6]->text() << endl;
4009 out << tr( "VOLUMES_INFO" ) << endl;
4010 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ) << ": " << myWidgets[7]->text() << endl;
4011 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[8]->text() << endl;
4014 ////////////////////////////////////////////////////////////////////////////////
4015 /// \class SMESHGUI_CtrlInfoDlg
4016 /// \brief Overall Mesh Quality dialog.
4017 /// \todo Add selection button to reactivate selection on move from other dlg.
4018 ////////////////////////////////////////////////////////////////////////////////
4022 \param parent parent widget
4024 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
4027 setAttribute( Qt::WA_DeleteOnClose, true );
4028 setWindowTitle( tr( "CTRL_INFO" ) );
4029 setMinimumSize( 400, 600 );
4031 myCtrlInfo = new SMESHGUI_CtrlInfo( this );
4034 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
4035 okBtn->setAutoDefault( true );
4036 okBtn->setDefault( true );
4038 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
4039 dumpBtn->setAutoDefault( true );
4040 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
4041 helpBtn->setAutoDefault( true );
4043 QHBoxLayout* btnLayout = new QHBoxLayout;
4044 btnLayout->setSpacing( SPACING );
4045 btnLayout->setMargin( 0 );
4047 btnLayout->addWidget( okBtn );
4048 btnLayout->addWidget( dumpBtn );
4049 btnLayout->addStretch( 10 );
4050 btnLayout->addWidget( helpBtn );
4052 QVBoxLayout* l = new QVBoxLayout ( this );
4054 l->setSpacing( SPACING );
4055 l->addWidget( myCtrlInfo );
4056 l->addLayout( btnLayout );
4058 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
4059 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
4060 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
4061 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
4062 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
4070 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
4075 \brief Show mesh quality information on given object.
4076 \param io Interactive object.
4078 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
4081 showInfo( SMESH::SelectionProxy( io ) );
4085 \brief Show mesh quality information on given object.
4086 \param proxy Selection proxy.
4088 void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
4090 SUIT_OverrideCursor wc;
4096 myCtrlInfo->showInfo( proxy );
4100 \brief Show mesh information
4102 void SMESHGUI_CtrlInfoDlg::updateInfo()
4104 SALOME_ListIO selected;
4105 SMESHGUI::selectionMgr()->selectedObjects( selected );
4107 if ( selected.Extent() == 1 )
4108 showInfo( selected.First() );
4110 showInfo( myProxy );
4114 \brief Perform clean-up actions on the dialog box closing.
4116 void SMESHGUI_CtrlInfoDlg::reject()
4118 SMESH::SetPointRepresentation( false );
4123 \brief Setup selection mode depending on the current dialog box state.
4125 void SMESHGUI_CtrlInfoDlg::updateSelection()
4127 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
4128 disconnect( selMgr, 0, this, 0 );
4129 SMESH::SetPointRepresentation( false );
4130 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4135 \brief Deactivate dialog box.
4137 void SMESHGUI_CtrlInfoDlg::deactivate()
4139 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4143 \brief Dump information to file.
4145 void SMESHGUI_CtrlInfoDlg::dump()
4147 DumpFileDlg fd( this, false );
4148 fd.setWindowTitle( tr( "SAVE_INFO" ) );
4149 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
4150 if ( fd.exec() == QDialog::Accepted )
4152 QString fileName = fd.selectedFile();
4153 if ( !fileName.isEmpty() ) {
4154 QFile file( fileName );
4155 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
4158 QTextStream out( &file );
4159 myCtrlInfo->saveInfo( out );
4165 \brief Show documentation on dialog.
4167 void SMESHGUI_CtrlInfoDlg::help()
4169 SMESH::ShowHelpFile( "mesh_infos.html#mesh-quality-info-anchor" );