1 // Copyright (C) 2007-2019 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 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2151 myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2153 myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2155 myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
2156 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2158 l->addWidget( myInfo );
2159 connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
2160 connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2161 connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2165 \brief Show mesh element information.
2166 \param ids Nodes / elements IDs.
2168 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
2171 TreeWriter writer( myInfo, new ItemCreator( this ) );
2172 writeInfo( &writer, ids );
2176 \brief Show node information
2177 \param node mesh node for showing
2178 \param index index of current node
2179 \param nbNodes number of unique nodes in element
2180 \param parentItem parent item of tree
2182 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* node, int index,
2183 int nbNodes, QTreeWidgetItem* parentItem )
2185 // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
2186 // // node number and ID
2187 // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
2188 // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
2189 // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
2190 // nodeItem->setData( 1, TypeRole, ElemConnectivity );
2191 // nodeItem->setData( 1, IdRole, node->GetID() );
2192 // nodeItem->setExpanded( false );
2193 // // node coordinates
2194 // QTreeWidgetItem* coordItem = createItem( nodeItem );
2195 // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
2196 // QTreeWidgetItem* xItem = createItem( coordItem );
2197 // xItem->setText( 0, "X" );
2198 // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2199 // QTreeWidgetItem* yItem = createItem( coordItem );
2200 // yItem->setText( 0, "Y" );
2201 // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2202 // QTreeWidgetItem* zItem = createItem( coordItem );
2203 // zItem->setText( 0, "Z" );
2204 // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2205 // // node connectivity
2206 // QTreeWidgetItem* nconItem = createItem( nodeItem );
2207 // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
2208 // Connectivity connectivity = nodeConnectivity( node );
2209 // if ( !connectivity.isEmpty() ) {
2210 // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
2211 // if ( !con.isEmpty() ) {
2212 // QTreeWidgetItem* i = createItem( nconItem );
2213 // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
2214 // i->setText( 1, con );
2216 // con = formatConnectivity( connectivity, SMDSAbs_Edge );
2217 // if ( !con.isEmpty() ) {
2218 // QTreeWidgetItem* i = createItem( nconItem );
2219 // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
2220 // i->setText( 1, con );
2221 // i->setData( 1, TypeRole, NodeConnectivity );
2223 // con = formatConnectivity( connectivity, SMDSAbs_Ball );
2224 // if ( !con.isEmpty() ) {
2225 // QTreeWidgetItem* i = createItem( nconItem );
2226 // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
2227 // i->setText( 1, con );
2228 // i->setData( 1, TypeRole, NodeConnectivity );
2230 // con = formatConnectivity( connectivity, SMDSAbs_Face );
2231 // if ( !con.isEmpty() ) {
2232 // QTreeWidgetItem* i = createItem( nconItem );
2233 // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
2234 // i->setText( 1, con );
2235 // i->setData( 1, TypeRole, NodeConnectivity );
2237 // con = formatConnectivity( connectivity, SMDSAbs_Volume );
2238 // if ( !con.isEmpty() ) {
2239 // QTreeWidgetItem* i = createItem( nconItem );
2240 // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
2241 // i->setText( 1, con );
2242 // i->setData( 1, TypeRole, NodeConnectivity );
2247 \brief Internal clean-up (reset widget)
2249 void SMESHGUI_TreeElemInfo::clearInternal()
2256 \brief Create new item and add it to the tree.
2257 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2258 \param options Item flags. Defaults to 0 (none).
2259 \return New tree widget item.
2261 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
2263 QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
2264 setTreeItemAttributes( item, options | Expanded | Editable );
2266 if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
2268 QString resName = expandedResource( parent );
2269 parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
2275 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2277 QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2278 if ( widgets.isEmpty() ) return;
2279 QTreeWidgetItem* aTreeItem = widgets.first();
2280 int type = aTreeItem->data( 1, TypeRole ).toInt();
2281 if (( type == ElemConnectivity || type == NodeConnectivity ) &&
2282 ( !aTreeItem->text( 1 ).isEmpty() ))
2285 QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
2286 if ( menu.exec( e->globalPos() ) == a )
2287 emit( itemInfo( type, aTreeItem->text( 1 )) );
2291 void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
2294 int type = theItem->data( 1, TypeRole ).toInt();
2295 emit( itemInfo( type, theItem->text( 1 )) );
2299 void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
2302 SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
2305 QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
2307 return QString("Expanded_") + ( what()==ShowElements ? "E_" : "N_" ) + theItem->text(0);
2310 ////////////////////////////////////////////////////////////////////////////////
2311 /// \class InfoComputor
2312 /// \brief Mesh information computor.
2315 /// The class is created for different computation operations. Currently it is
2316 /// used to compute size and number of underlying nodes for given group.
2317 ////////////////////////////////////////////////////////////////////////////////
2321 \param parent Parent object.
2322 \param proxy Object to compute information on (group).
2323 \param item Tree widget item, referenced by this computer.
2324 \param operation Value to compute.
2327 InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
2328 : QObject( parent ), myProxy( proxy ), myOperation( operation )
2333 \brief Compute requested information.
2336 void InfoComputor::compute()
2340 SUIT_OverrideCursor wc;
2342 switch ( myOperation )
2345 myProxy.size( true ); // force size computation
2349 myProxy.nbNodes( true ); // force size computation
2358 ////////////////////////////////////////////////////////////////////////////////
2359 /// \class SMESHGUI_AddInfo
2360 /// \brief Show additional information on selected object.
2362 /// Displays an additional information about selected object: mesh, sub-mesh
2365 /// \todo Rewrite saveInfo() method to print all data, not currently shown only.
2366 ////////////////////////////////////////////////////////////////////////////////
2370 \param parent Parent widget. Defaults to 0.
2372 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
2374 QVBoxLayout* l = new QVBoxLayout( this );
2376 l->setSpacing( SPACING );
2378 myTree = new QTreeWidget( this );
2380 myTree->setColumnCount( 2 );
2381 myTree->header()->setStretchLastSection( true );
2382 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2383 myTree->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2385 myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2387 myTree->header()->hide();
2389 l->addWidget( myTree );
2395 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2400 \brief Show information on given object.
2401 \param proxy Object to show information on (mesh, sub-mesh, group).
2403 void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
2406 setProperty( "group_index", 0 );
2407 setProperty( "submesh_index", 0 );
2408 myComputors.clear();
2411 // then fill panel with data if object is not null
2417 QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
2418 nameItem->setText( 0, tr( "NAME" ) );
2419 nameItem->setText( 1, proxy.name() );
2422 if ( proxy.type() == SMESH::SelectionProxy::Mesh )
2423 meshInfo( proxy, nameItem );
2424 else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
2425 subMeshInfo( proxy, nameItem );
2426 else if ( proxy.type() >= SMESH::SelectionProxy::Group )
2427 groupInfo( proxy, nameItem );
2432 \brief Update information in panel.
2434 void SMESHGUI_AddInfo::updateInfo()
2436 showInfo( myProxy );
2440 \brief Reset panel (clear all data).
2442 void SMESHGUI_AddInfo::clear()
2448 \brief Create new item and add it to the tree.
2449 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2450 \param options Item flags. Defaults to 0 (none).
2451 \return New tree widget item.
2453 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
2455 QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
2456 new QTreeWidgetItem( myTree->invisibleRootItem() );
2457 setTreeItemAttributes( item, options | Expanded );
2462 \brief Show information on mesh.
2463 \param proxy Proxy object (mesh).
2464 \param parent Parent tree item.
2466 void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2471 QString shapeName = proxy.shapeName();
2472 SMESH::MedInfo inf = proxy.medFileInfo();
2475 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2476 typeItem->setText( 0, tr( "TYPE" ) );
2477 if ( !shapeName.isEmpty() )
2479 typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2481 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2482 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2483 gobjItem->setText( 1, shapeName );
2485 else if ( inf.isValid() )
2487 typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2488 // med file information
2489 QTreeWidgetItem* fileItem = createItem( parent, Bold );
2490 fileItem->setText( 0, tr( "FILE_NAME" ) );
2491 fileItem->setText( 1, inf.fileName() );
2492 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2493 sizeItem->setText( 0, tr( "FILE_SIZE" ) );
2494 sizeItem->setText( 1, QString::number( inf.size() ) );
2495 QTreeWidgetItem* versionItem = createItem( parent, Bold );
2496 versionItem->setText( 0, tr( "FILE_VERSION" ) );
2497 versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
2501 typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2505 myGroups = proxy.groups();
2509 mySubMeshes = proxy.submeshes();
2514 \brief Show information on sub-mesh.
2515 \param proxy Proxy object (sub-mesh).
2516 \param parent Parent tree item.
2518 void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2523 bool isShort = parent->parent() != 0;
2528 SMESH::SelectionProxy meshProxy = proxy.mesh();
2531 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2532 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2533 nameItem->setText( 1, meshProxy.name() );
2538 QString shapeName = proxy.shapeName();
2539 if ( !shapeName.isEmpty() )
2541 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2542 gobjItem->setText( 1, shapeName );
2547 \brief Show information on group.
2548 \param proxy Proxy object (group).
2549 \param parent Parent tree item.
2551 void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2556 bool isShort = parent->parent() != 0;
2561 SMESH::SelectionProxy meshProxy = proxy.mesh();
2564 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2565 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2566 nameItem->setText( 1, meshProxy.name() );
2571 SMESH::SelectionProxy::Type type = proxy.type();
2572 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2573 typeItem->setText( 0, tr( "TYPE" ) );
2574 if ( type == SMESH::SelectionProxy::GroupStd )
2576 typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2578 else if ( type == SMESH::SelectionProxy::GroupGeom )
2580 typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2582 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2583 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2584 gobjItem->setText( 1, proxy.shapeName() );
2586 else if ( type == SMESH::SelectionProxy::GroupFilter )
2588 typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2592 int etype = proxy.groupElementType();
2595 QString typeName = tr( "UNKNOWN" );
2599 typeName = tr( "NODE" );
2602 typeName = tr( "EDGE" );
2605 typeName = tr( "FACE" );
2608 typeName = tr( "VOLUME" );
2611 typeName = tr( "0DELEM" );
2614 typeName = tr( "BALL" );
2619 QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2620 etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2621 etypeItem->setText( 1, typeName );
2625 // note: size is not computed for group on filter for performance reasons, see IPAL52831
2626 bool meshLoaded = proxy.isMeshLoaded();
2627 int size = proxy.size();
2629 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2630 sizeItem->setText( 0, tr( "SIZE" ) );
2633 sizeItem->setText( 1, QString::number( size ) );
2637 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2638 myTree->setItemWidget( sizeItem, 1, btn );
2639 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
2640 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2641 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2642 myComputors.append( comp );
2646 QTreeWidgetItem* colorItem = createItem( parent, Bold );
2647 colorItem->setText( 0, tr( "COLOR" ) );
2648 colorItem->setBackground( 1, proxy.color() );
2650 // nb of underlying nodes
2651 if ( etype != SMESH::NODE )
2653 QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2654 nodesItem->setText( 0, tr( "NB_NODES" ) );
2656 int nbNodes = proxy.nbNodes();
2659 nodesItem->setText( 1, QString::number( nbNodes ) );
2663 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2664 myTree->setItemWidget( nodesItem, 1, btn );
2665 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
2666 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2667 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2668 myComputors.append( comp );
2674 \brief Update information on child groups.
2676 void SMESHGUI_AddInfo::showGroups()
2678 // remove all computors
2679 myComputors.clear();
2681 // tree root should be the first top level item
2682 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2686 int idx = property( "group_index" ).toInt();
2688 // find sub-meshes top-level container item
2689 QTreeWidgetItem* itemGroups = 0;
2690 for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
2692 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
2694 itemGroups = parent->child( i );
2696 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
2698 extra->updateControls( myGroups.count(), idx );
2699 // clear: remove all group items
2700 while ( itemGroups->childCount() )
2701 delete itemGroups->child( 0 );
2705 QMap<int, QTreeWidgetItem*> grpItems;
2706 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
2708 SMESH::SelectionProxy grp = myGroups[i];
2712 int grpType = grp.groupElementType();
2714 // create top-level groups container item if it does not exist
2717 itemGroups = createItem( parent, Bold | AllColumns );
2718 itemGroups->setText( 0, tr( "GROUPS" ) );
2719 itemGroups->setData( 0, Qt::UserRole, GroupsId );
2721 // if necessary, create extra widget to show information by chunks
2722 if ( myGroups.count() > blockSize() )
2724 ExtraWidget* extra = new ExtraWidget( this, true );
2725 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2726 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2727 myTree->setItemWidget( itemGroups, 1, extra );
2728 extra->updateControls( myGroups.count(), idx );
2732 // create container item corresponding to particular element type
2733 if ( !grpItems.contains( grpType ) )
2735 grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
2736 grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2737 itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
2741 QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
2742 nameItem->setText( 0, grp.name().trimmed() ); // trim name
2745 groupInfo( grp, nameItem );
2750 \brief Update information on child sub-meshes.
2752 void SMESHGUI_AddInfo::showSubMeshes()
2754 // tree root should be the first top level item
2755 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2759 int idx = property( "submesh_index" ).toInt();
2761 // find sub-meshes top-level container item
2762 QTreeWidgetItem* itemSubMeshes = 0;
2763 for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
2765 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
2767 itemSubMeshes = parent->child( i );
2769 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
2771 extra->updateControls( mySubMeshes.count(), idx );
2772 // clear: remove all sub-mesh items
2773 while ( itemSubMeshes->childCount() )
2774 delete itemSubMeshes->child( 0 );
2778 QMap<int, QTreeWidgetItem*> smItems;
2779 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
2781 SMESH::SelectionProxy sm = mySubMeshes[i];
2785 int smType = sm.shapeType();
2788 else if ( smType == GEOM::COMPSOLID )
2789 smType = GEOM::COMPOUND;
2791 // create top-level sub-meshes container item if it does not exist
2792 if ( !itemSubMeshes )
2794 itemSubMeshes = createItem( parent, Bold | AllColumns );
2795 itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2796 itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
2798 // if necessary, create extra widget to show information by chunks
2799 if ( mySubMeshes.count() > blockSize() )
2801 ExtraWidget* extra = new ExtraWidget( this, true );
2802 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2803 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2804 myTree->setItemWidget( itemSubMeshes, 1, extra );
2805 extra->updateControls( mySubMeshes.count(), idx );
2809 // create container item corresponding to particular shape type
2810 if ( !smItems.contains( smType ) )
2812 smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
2813 smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2814 itemSubMeshes->insertChild( smType, smItems[ smType ] );
2818 QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
2819 nameItem->setText( 0, sm.name().trimmed() ); // trim name
2822 subMeshInfo( sm, nameItem );
2827 \brief Show previous chunk of information on child groups.
2829 void SMESHGUI_AddInfo::showPreviousGroups()
2831 int idx = property( "group_index" ).toInt();
2832 setProperty( "group_index", idx-1 );
2837 \brief Show next chunk of information on child groups.
2839 void SMESHGUI_AddInfo::showNextGroups()
2841 int idx = property( "group_index" ).toInt();
2842 setProperty( "group_index", idx+1 );
2847 \brief Show previous chunk of information on child sub-meshes.
2849 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2851 int idx = property( "submesh_index" ).toInt();
2852 setProperty( "submesh_index", idx-1 );
2857 \brief Show next chunk of information on child sub-meshes.
2859 void SMESHGUI_AddInfo::showNextSubMeshes()
2861 int idx = property( "submesh_index" ).toInt();
2862 setProperty( "submesh_index", idx+1 );
2867 \brief Write information from panel to output stream.
2868 \param out Text stream output.
2870 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2873 QString title = tr( "ADDITIONAL_INFO" );
2874 out << ruler( title.size() ) << endl;
2875 out << title << endl;
2876 out << ruler( title.size() ) << endl;
2880 QTreeWidgetItemIterator it( myTree );
2883 if ( !( ( *it )->text(0) ).isEmpty() )
2885 out << indent( itemDepth( *it ) ) << ( *it )->text(0);
2886 if ( ( *it )->text(0) == tr( "COLOR" ) )
2887 out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
2888 else if ( !( ( *it )->text(1) ).isEmpty() )
2889 out << ":" << spacing() << ( *it )->text(1);
2897 ////////////////////////////////////////////////////////////////////////////////
2898 /// \class GroupCombo
2899 /// \brief Customized combo box to manage list of mesh groups.
2901 ////////////////////////////////////////////////////////////////////////////////
2903 class GroupCombo: public QComboBox
2905 class Item: public QStandardItem
2908 SMESH::SelectionProxy myGroup;
2909 Item( const SMESH::SelectionProxy& group )
2912 setText( myGroup.name() );
2914 SMESH::SelectionProxy group()
2920 SMESH::SelectionProxy myProxy;
2923 GroupCombo( QWidget* );
2924 void setSource( const SMESH::SelectionProxy& );
2925 SMESH::SelectionProxy currentGroup() const;
2930 \param parent Parent widget.
2933 GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
2935 setModel( new QStandardItemModel( this ) );
2939 \brief Set mesh source.
2940 \param obj Mesh source.
2943 void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
2945 if ( myProxy == proxy )
2950 bool blocked = blockSignals( true );
2951 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2956 if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
2958 QList<SMESH::SelectionProxy> groups = myProxy.groups();
2959 for ( int i = 0; i < groups.count(); ++i )
2963 QString name = groups[i].name();
2964 if ( !name.isEmpty() )
2965 m->appendRow( new Item( groups[i] ) );
2968 setCurrentIndex( -1 ); // for performance reasons
2970 else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
2972 m->appendRow( new Item( myProxy ) );
2973 setCurrentIndex( 0 );
2977 blockSignals( blocked );
2981 \brief Get currently selected group.
2982 \return Selected group.
2985 SMESH::SelectionProxy GroupCombo::currentGroup() const
2987 SMESH::SelectionProxy group;
2988 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2989 if ( currentIndex() >= 0 )
2990 group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
2994 ////////////////////////////////////////////////////////////////////////////////
2995 /// \class SMESHGUI_MeshInfoDlg
2996 /// \brief Mesh information dialog box
2998 /// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
2999 /// \todo Add selection button to reactivate selection on move from other dlg.
3000 ////////////////////////////////////////////////////////////////////////////////
3004 \param parent Parent widget.
3005 \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
3007 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
3011 setAttribute( Qt::WA_DeleteOnClose, true );
3012 setWindowTitle( tr( "MESH_INFO" ) );
3013 setSizeGripEnabled( true );
3015 myTabWidget = new QTabWidget( this );
3019 myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
3020 myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
3024 QWidget* w = new QWidget( myTabWidget );
3026 myMode = new QButtonGroup( this );
3027 myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
3028 myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
3029 myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
3030 myMode->button( NodeMode )->setChecked( true );
3031 myID = new QLineEdit( w );
3032 myID->setValidator( new SMESHGUI_IdValidator( this ) );
3033 myGroups = new GroupCombo( w );
3034 QStackedWidget* stack = new QStackedWidget( w );
3035 stack->addWidget( myID );
3036 stack->addWidget( myGroups );
3037 myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
3038 myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
3040 int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
3041 mode = qMin( 1, qMax( 0, mode ) );
3044 myElemInfo = new SMESHGUI_SimpleElemInfo( w );
3046 myElemInfo = new SMESHGUI_TreeElemInfo( w );
3047 stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
3049 QGridLayout* elemLayout = new QGridLayout( w );
3050 elemLayout->setMargin( MARGIN );
3051 elemLayout->setSpacing( SPACING );
3052 elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
3053 elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
3054 elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
3055 elemLayout->addWidget( stack, 0, 3 );
3056 elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
3057 elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
3059 myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
3063 myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
3064 myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
3068 myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
3069 myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
3073 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3074 okBtn->setAutoDefault( true );
3075 okBtn->setDefault( true );
3077 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3078 dumpBtn->setAutoDefault( true );
3079 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3080 helpBtn->setAutoDefault( true );
3082 QHBoxLayout* btnLayout = new QHBoxLayout;
3083 btnLayout->setSpacing( SPACING );
3084 btnLayout->setMargin( 0 );
3086 btnLayout->addWidget( okBtn );
3087 btnLayout->addWidget( dumpBtn );
3088 btnLayout->addStretch( 10 );
3089 btnLayout->addWidget( helpBtn );
3093 QVBoxLayout* l = new QVBoxLayout ( this );
3094 l->setMargin( MARGIN );
3095 l->setSpacing( SPACING );
3096 l->addWidget( myTabWidget );
3097 l->addLayout( btnLayout );
3101 myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
3103 // set-up connections
3105 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3106 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3107 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3108 connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
3109 connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
3110 connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
3111 connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
3112 connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
3113 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3114 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3115 connect( myElemInfo, SIGNAL( itemInfo( int, QString ) ), this, SLOT( showItemInfo( int, QString ) ) );
3116 connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
3120 myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
3127 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
3133 \brief Show mesh information on given object.
3134 \param io Interactive object.
3136 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3139 showInfo( SMESH::SelectionProxy( io ) );
3143 \brief Show mesh information on given object.
3144 \param proxy Selection proxy.
3146 void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3148 SUIT_OverrideCursor wc;
3155 SMESH::SMESH_IDSource_var obj = myProxy.object();
3158 myBaseInfo->showInfo( proxy );
3160 // "Additional info" tab
3161 myAddInfo->showInfo( proxy );
3163 // "Quality info" tab
3164 // Note: for performance reasons we update it only if it is currently active
3165 if ( myTabWidget->currentIndex() == CtrlInfo )
3166 myCtrlInfo->showInfo( proxy );
3168 // "Element info" tab
3169 myGroups->setSource( proxy );
3170 if ( myMode->checkedId() == GroupMode ) {
3171 SMESH::SelectionProxy group = myGroups->currentGroup();
3173 myElemInfo->showInfo( group );
3175 myElemInfo->clear();
3178 SVTK_Selector* selector = SMESH::GetSelector();
3181 if ( myProxy.actor() && selector ) { //todo: actor()?
3182 nb = myMode->checkedId() == NodeMode ?
3183 SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
3184 SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
3187 myID->setText( ID.trimmed() );
3189 QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
3190 foreach ( ID, idTxt )
3191 ids << ID.trimmed().toUInt();
3192 myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
3196 myElemInfo->clear();
3202 \brief Update information.
3204 void SMESHGUI_MeshInfoDlg::updateInfo()
3206 SALOME_ListIO selected;
3207 SMESHGUI::selectionMgr()->selectedObjects( selected );
3209 if ( selected.Extent() == 1 )
3210 showInfo( selected.First() );
3212 showInfo( myProxy );
3216 \brief Clean-up on dialog closing.
3218 void SMESHGUI_MeshInfoDlg::reject()
3220 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3221 selMgr->clearFilters();
3222 SMESH::SetPointRepresentation( false );
3223 if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
3224 viewWindow->SetSelectionMode( ActorSelection );
3226 myIDPreview->SetPointsLabeled( false );
3230 \brief Process keyboard event.
3231 \param e Key press event.
3233 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
3235 QDialog::keyPressEvent( e );
3236 if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
3243 \brief Set-up selection mode for currently selected page.
3245 void SMESHGUI_MeshInfoDlg::updateSelection()
3247 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3249 disconnect( selMgr, 0, this, 0 );
3250 selMgr->clearFilters();
3252 int selMode = ActorSelection;
3253 if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == NodeMode )
3254 selMode = NodeSelection;
3255 else if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == ElemMode )
3256 selMode = CellSelection;
3257 SMESH::SetPointRepresentation( selMode == NodeSelection );
3258 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3259 aViewWindow->SetSelectionMode( selMode );
3261 SMESH::SelectionProxy previous = myProxy;
3262 QString ids = myID->text().trimmed();
3265 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3268 if ( myProxy && myProxy == previous && !ids.isEmpty() ) {
3269 myID->setText( ids );
3275 \brief Show documentation on selected dialog page.
3277 void SMESHGUI_MeshInfoDlg::help()
3279 QString helpPage = "mesh_infos.html";
3280 switch ( myTabWidget->currentIndex() )
3283 helpPage += "#advanced-mesh-infos-anchor";
3286 helpPage += "#mesh-element-info-anchor";
3289 helpPage += "#mesh-addition-info-anchor";
3292 helpPage += "#mesh-quality-info-anchor";
3297 SMESH::ShowHelpFile( helpPage );
3301 \brief Deactivate dialog box.
3303 void SMESHGUI_MeshInfoDlg::deactivate()
3305 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3309 \brief Called when users switches between node / element modes.
3311 void SMESHGUI_MeshInfoDlg::modeChanged()
3313 emit( switchMode( myMode->checkedId() == GroupMode ? 1 : 0 ) );
3319 \brief Called when users prints mesh element ID in the corresponding field.
3321 void SMESHGUI_MeshInfoDlg::idChanged()
3323 myIDPreview->SetPointsLabeled( false );
3326 TColStd_MapOfInteger ID;
3328 std::vector<int> idVec;
3329 std::list< gp_XYZ > aGrCentersXYZ;
3331 const bool isElem = ( myMode->checkedId() == ElemMode );
3332 QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
3333 foreach ( QString tid, idTxt ) {
3334 long id = tid.toUInt();
3335 if ( isElem ? myProxy.hasElement( id ) : myProxy.hasNode( id ))
3339 if ( isElem && myProxy.actor() && myProxy.elementGravityCenter( id, xyz ))
3341 idVec.push_back( id );
3342 aGrCentersXYZ.push_back( xyz );
3346 SVTK_Selector* selector = SMESH::GetSelector();
3347 if ( myProxy.actor() && selector ) {
3348 Handle(SALOME_InteractiveObject) IO = myProxy.actor()->getIO();
3349 selector->AddOrRemoveIndex( IO, ID, false );
3350 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3352 if ( myMode->checkedId() == NodeMode )
3353 myIDPreview->SetPointsData( myProxy.actor()->GetObject()->GetMesh(), ID );
3355 myIDPreview->SetElemsData( idVec, aGrCentersXYZ );
3357 bool showIDs = ( !ID.IsEmpty() &&
3358 myIDPreviewCheck->isChecked() &&
3359 myTabWidget->currentIndex() == ElemInfo );
3360 myIDPreview->SetPointsLabeled( showIDs, myProxy.actor()->GetVisibility() );
3362 aViewWindow->highlight( IO, true, true );
3363 aViewWindow->Repaint();
3366 myElemInfo->showInfo( myProxy, ids, isElem );
3371 * \brief Show IDs clicked
3373 void SMESHGUI_MeshInfoDlg::idPreviewChange( bool isOn )
3375 myIDPreview->SetPointsLabeled( isOn && !myID->text().simplified().isEmpty() );
3376 SMESHGUI::resourceMgr()->setValue("SMESH", "id_preview_resource", isOn );
3377 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3378 aViewWindow->Repaint();
3381 void SMESHGUI_MeshInfoDlg::showItemInfo( int type, const QString& ids )
3383 if ( !ids.isEmpty() && ( type == NodeConnectivity || type == ElemConnectivity )) {
3384 myMode->button( type - NodeConnectivity )->click();
3385 myID->setText( ids );
3390 \brief Dump information to file.
3392 void SMESHGUI_MeshInfoDlg::dump()
3394 DumpFileDlg fd( this );
3395 fd.setWindowTitle( tr( "SAVE_INFO" ) );
3396 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
3397 fd.setChecked( BaseInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_base", true ) );
3398 fd.setChecked( ElemInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_elem", true ) );
3399 fd.setChecked( AddInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_add", true ) );
3400 fd.setChecked( CtrlInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_ctrl", true ) );
3401 if ( fd.exec() == QDialog::Accepted )
3403 QString fileName = fd.selectedFile();
3404 if ( !fileName.isEmpty() ) {
3405 QFile file( fileName );
3406 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
3409 QTextStream out( &file );
3410 if ( fd.isChecked( BaseInfo ) ) myBaseInfo->saveInfo( out );
3411 if ( fd.isChecked( ElemInfo ) ) myElemInfo->saveInfo( out );
3412 if ( fd.isChecked( AddInfo ) ) myAddInfo->saveInfo( out );
3413 if ( fd.isChecked( CtrlInfo ) ) myCtrlInfo->saveInfo( out );
3418 ////////////////////////////////////////////////////////////////////////////////
3419 /// \class SMESHGUI_CtrlInfo
3420 /// \brief Show quality statistics information on selected object.
3422 /// Displays quality controls statistics about selected object: mesh, sub-mesh,
3423 /// group or arbitrary ID source.
3424 ////////////////////////////////////////////////////////////////////////////////
3428 \param parent Parent widget. Defaults to 0.
3430 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent ): SMESHGUI_Info( parent )
3432 QGridLayout* l = new QGridLayout( this );
3433 l->setMargin( MARGIN );
3434 l->setSpacing( SPACING );
3436 QIcon aComputeIcon( SUIT_Session::session()->resourceMgr()->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3437 SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3440 QLabel* aNameLab = createLabel( tr( "NAME_LAB" ), this, Bold );
3441 QLabel* aName = createField( this, "ctrlName" );
3442 aName->setMinimumWidth( 150 );
3446 QLabel* aNodesLab = createLabel( tr( "NODES_INFO" ), this, Bold );
3447 QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3448 QLabel* aNodesFree = createField( this, "ctrlNodesFree" );
3449 myWidgets << aNodesFree;
3450 myPredicates << aFilterMgr->CreateFreeNodes();
3452 QLabel* aNodesNbConnLab = new QLabel( tr( "MAX_NODE_CONNECTIVITY" ), this );
3453 QLabel* aNodesNbConn = createField( this, "ctrlNodesCnty" );
3454 myWidgets << aNodesNbConn;
3455 myNodeConnFunctor = aFilterMgr->CreateNodeConnectivityNumber();
3457 QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3458 QLabel* aNodesDouble = createField( this, "ctrlNodesDouble" );
3459 myWidgets << aNodesDouble;
3460 myPredicates << aFilterMgr->CreateEqualNodes();
3461 QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3462 myToleranceWidget = new SMESHGUI_SpinBox( this );
3463 myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3464 myToleranceWidget->setAcceptNames( false );
3465 myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3468 QLabel* anEdgesLab = createLabel( tr( "EDGES_INFO" ), this, Bold );
3469 QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ), this );
3470 QLabel* anEdgesDouble = createField( this, "ctrlEdgesDouble" );
3471 myWidgets << anEdgesDouble;
3472 myPredicates << aFilterMgr->CreateEqualEdges();
3475 QLabel* aFacesLab = createLabel( tr( "FACES_INFO" ), this, Bold );
3476 QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3477 QLabel* aFacesDouble = createField( this, "ctrlFacesDouble" );
3478 myWidgets << aFacesDouble;
3479 myPredicates << aFilterMgr->CreateEqualFaces();
3480 QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3481 QLabel* aFacesOver = createField( this, "ctrlFacesOver" );
3482 myWidgets << aFacesOver;
3483 myPredicates << aFilterMgr->CreateOverConstrainedFace();
3484 QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3485 myPlot = createPlot( this );
3486 myAspectRatio = aFilterMgr->CreateAspectRatio();
3489 QLabel* aVolumesLab = createLabel( tr( "VOLUMES_INFO" ), this, Bold );
3490 QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3491 QLabel* aVolumesDouble = createField( this, "ctrlVolumesDouble" );
3492 myWidgets << aVolumesDouble;
3493 myPredicates << aFilterMgr->CreateEqualVolumes();
3494 QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3495 QLabel* aVolumesOver = createField( this, "ctrlVolumesOver" );
3496 myWidgets << aVolumesOver;
3497 myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3498 QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3499 myPlot3D = createPlot( this );
3500 myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3502 QToolButton* aFreeNodesBtn = new QToolButton( this );
3503 aFreeNodesBtn->setIcon(aComputeIcon);
3504 myButtons << aFreeNodesBtn; //0
3506 QToolButton* aNodesNbConnBtn = new QToolButton( this );
3507 aNodesNbConnBtn->setIcon(aComputeIcon);
3508 myButtons << aNodesNbConnBtn; //1
3510 QToolButton* aDoubleNodesBtn = new QToolButton( this );
3511 aDoubleNodesBtn->setIcon(aComputeIcon);
3512 myButtons << aDoubleNodesBtn; //2
3514 QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3515 aDoubleEdgesBtn->setIcon(aComputeIcon);
3516 myButtons << aDoubleEdgesBtn; //3
3518 QToolButton* aDoubleFacesBtn = new QToolButton( this );
3519 aDoubleFacesBtn->setIcon(aComputeIcon);
3520 myButtons << aDoubleFacesBtn; //4
3522 QToolButton* aOverContFacesBtn = new QToolButton( this );
3523 aOverContFacesBtn->setIcon(aComputeIcon);
3524 myButtons << aOverContFacesBtn; //5
3526 QToolButton* aComputeFaceBtn = new QToolButton( this );
3527 aComputeFaceBtn->setIcon(aComputeIcon);
3528 myButtons << aComputeFaceBtn; //6
3530 QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3531 aDoubleVolumesBtn->setIcon(aComputeIcon);
3532 myButtons << aDoubleVolumesBtn; //7
3534 QToolButton* aOverContVolumesBtn = new QToolButton( this );
3535 aOverContVolumesBtn->setIcon(aComputeIcon);
3536 myButtons << aOverContVolumesBtn; //8
3538 QToolButton* aComputeVolumeBtn = new QToolButton( this );
3539 aComputeVolumeBtn->setIcon(aComputeIcon);
3540 myButtons << aComputeVolumeBtn; //9
3542 connect( aComputeFaceBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3543 connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3544 connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3545 connect( aNodesNbConnBtn, SIGNAL( clicked() ), this, SLOT( computeNodesNbConnInfo() ) );
3546 connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3547 connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3548 connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3549 connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3550 connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3551 connect( aOverContVolumesBtn,SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3552 connect( myToleranceWidget, SIGNAL( valueChanged( double ) ), this, SLOT( setTolerance( double ) ) );
3554 l->addWidget( aNameLab, 0, 0 ); //0
3555 l->addWidget( aName, 0, 1, 1, 2 ); //1
3556 l->addWidget( aNodesLab, 1, 0, 1, 3 ); //2
3557 l->addWidget( aNodesFreeLab, 2, 0 ); //3
3558 l->addWidget( aNodesFree, 2, 1 ); //4
3559 l->addWidget( aFreeNodesBtn, 2, 2 ); //5
3560 l->addWidget( aNodesNbConnLab, 3, 0 ); //6
3561 l->addWidget( aNodesNbConn, 3, 1 ); //7
3562 l->addWidget( aNodesNbConnBtn, 3, 2 ); //8
3563 l->addWidget( aNodesDoubleLab, 4, 0 ); //9
3564 l->addWidget( aNodesDouble, 4, 1 ); //10
3565 l->addWidget( aDoubleNodesBtn, 4, 2 ); //11
3566 l->addWidget( aToleranceLab, 5, 0 ); //12
3567 l->addWidget( myToleranceWidget, 5, 1 ); //13
3568 l->addWidget( anEdgesLab, 6, 0, 1, 3 ); //14
3569 l->addWidget( anEdgesDoubleLab, 7, 0 ); //15
3570 l->addWidget( anEdgesDouble, 7, 1 ); //16
3571 l->addWidget( aDoubleEdgesBtn, 7, 2 ); //17
3572 l->addWidget( aFacesLab, 8, 0, 1, 3 ); //18
3573 l->addWidget( aFacesDoubleLab, 9, 0 ); //19
3574 l->addWidget( aFacesDouble, 9, 1 ); //20
3575 l->addWidget( aDoubleFacesBtn, 9, 2 ); //21
3576 l->addWidget( aFacesOverLab, 10, 0 ); //22
3577 l->addWidget( aFacesOver, 10, 1 ); //23
3578 l->addWidget( aOverContFacesBtn, 10, 2 ); //24
3579 l->addWidget( anAspectRatioLab, 11, 0 ); //25
3580 l->addWidget( aComputeFaceBtn, 11, 2 ); //26
3581 l->addWidget( myPlot, 12, 0, 1, 3 );//27
3582 l->addWidget( aVolumesLab, 13, 0, 1, 3 );//28
3583 l->addWidget( aVolumesDoubleLab, 14, 0 ); //29
3584 l->addWidget( aVolumesDouble, 14, 1 ); //30
3585 l->addWidget( aDoubleVolumesBtn, 14, 2 ); //31
3586 l->addWidget( aVolumesOverLab, 15, 0 ); //32
3587 l->addWidget( aVolumesOver, 15, 1 ); //33
3588 l->addWidget( aOverContVolumesBtn,15, 2 ); //34
3589 l->addWidget( anAspectRatio3DLab, 16, 0 ); //35
3590 l->addWidget( aComputeVolumeBtn, 16, 2 ); //36
3591 l->addWidget( myPlot3D, 17, 0, 1, 3 );//37
3593 l->setColumnStretch( 0, 0 );
3594 l->setColumnStretch( 1, 5 );
3595 l->setRowStretch ( 12, 5 );
3596 l->setRowStretch ( 17, 5 );
3597 l->setRowStretch ( 18, 1 );
3605 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3610 \brief Create plot widget.
3611 \param parent Parent widget.
3612 \return New plot widget.
3614 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3616 QwtPlot* aPlot = new QwtPlot( parent );
3617 aPlot->setMinimumSize( 100, 100 );
3618 QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3619 xFont.setPointSize( 5 );
3620 QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3621 yFont.setPointSize( 5 );
3622 aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3623 aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3629 \brief Show information on given object.
3630 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
3632 void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
3640 SMESH::SMESH_IDSource_var obj = proxy.object();
3642 myWidgets[0]->setText( proxy.name() );
3644 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3645 if ( mesh->_is_nil() ) return;
3647 const bool meshLoaded = mesh->IsLoaded();
3648 if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3649 // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3650 for ( int i = 0; i < myButtons.count(); ++i )
3651 myButtons[i]->setEnabled( true );
3653 SMESH::long_array_var nbElemsByType = obj->GetNbElementsByType();
3654 if ( ! &nbElemsByType.in() ) return;
3656 const CORBA::Long ctrlLimit =
3657 meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3660 const CORBA::Long nbNodes = nbElemsByType[ SMESH::NODE ];
3661 // const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3662 // nbElemsByType[ SMESH::FACE ] +
3663 // nbElemsByType[ SMESH::VOLUME ] );
3664 if ( nbNodes > 0 ) {
3665 if ( nbNodes <= ctrlLimit ) {
3667 computeFreeNodesInfo();
3668 // node connectivity number
3669 computeNodesNbConnInfo();
3671 computeDoubleNodesInfo();
3674 myButtons[0]->setEnabled( true );
3675 myButtons[1]->setEnabled( true );
3676 myButtons[2]->setEnabled( true );
3680 for( int i=2; i<=13; i++)
3681 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3685 if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3687 if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3688 computeDoubleEdgesInfo();
3690 myButtons[3]->setEnabled( true );
3693 for( int i=14; i<=17; i++)
3694 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3698 if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3699 if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3701 computeDoubleFacesInfo();
3702 // over constrained faces
3703 computeOverConstrainedFacesInfo();
3704 // aspect Ratio histogram
3705 computeAspectRatio();
3708 myButtons[4]->setEnabled( true );
3709 myButtons[5]->setEnabled( true );
3710 myButtons[6]->setEnabled( true );
3712 #ifdef DISABLE_PLOT2DVIEWER
3713 for( int i=25; i<=27; i++)
3714 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3718 for( int i=18; i<=27; i++)
3719 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3723 if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3724 if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3726 computeDoubleVolumesInfo();
3727 // over constrained volumes
3728 computeOverConstrainedVolumesInfo();
3729 // aspect Ratio 3D histogram
3730 computeAspectRatio3D();
3733 myButtons[7]->setEnabled( true );
3734 myButtons[8]->setEnabled( true );
3735 myButtons[9]->setEnabled( true );
3737 #ifdef DISABLE_PLOT2DVIEWER
3738 for( int i=35; i<=37; i++)
3739 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3743 for( int i=28; i<=37; i++)
3744 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3748 //================================================================================
3750 * \brief Computes and shows nb of elements satisfying a given predicate
3751 * \param [in] ft - a predicate type (SMESH::FunctorType)
3752 * \param [in] iBut - index of one of myButtons to disable
3753 * \param [in] iWdg - index of one of myWidgets to show the computed number
3755 //================================================================================
3757 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3759 myButtons[ iBut ]->setEnabled( false );
3760 myWidgets[ iWdg ]->setText( "" );
3765 SUIT_OverrideCursor wc;
3767 SMESH::SMESH_IDSource_var obj = myProxy.object();
3768 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3770 if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3773 showInfo( myProxy ); // try to show all values
3774 if ( !myWidgets[ iWdg ]->text().isEmpty() )
3775 return; // <ft> predicate already computed
3777 // look for a predicate of type <ft>
3778 for ( int i = 0; i < myPredicates.count(); ++i )
3779 if ( myPredicates[i]->GetFunctorType() == ft )
3781 CORBA::Long nb = myPredicates[i]->NbSatisfying( obj );
3782 myWidgets[ iWdg ]->setText( QString::number( nb ) );
3786 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3788 computeNb( SMESH::FT_FreeNodes, 0, 1 );
3791 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3793 computeNb( SMESH::FT_EqualNodes, 2, 3 );
3796 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3798 computeNb( SMESH::FT_EqualEdges, 3, 4 );
3801 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3803 computeNb( SMESH::FT_EqualFaces, 4, 5 );
3806 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3808 computeNb( SMESH::FT_OverConstrainedFace, 5, 6 );
3811 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3813 computeNb( SMESH::FT_EqualVolumes, 7, 7 );
3816 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3818 computeNb( SMESH::FT_OverConstrainedVolume, 8, 8 );
3821 void SMESHGUI_CtrlInfo::computeNodesNbConnInfo()
3823 myButtons[ 1 ]->setEnabled( false );
3824 myWidgets[ 2 ]->setText( "" );
3829 SUIT_OverrideCursor wc;
3831 SMESH::SMESH_IDSource_var obj = myProxy.object();
3832 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3834 if ( !mesh->IsLoaded() )
3837 showInfo( myProxy ); // try to show all values
3838 if ( !myWidgets[ 2 ]->text().isEmpty() )
3839 return; // already computed
3841 myNodeConnFunctor->SetMesh( mesh );
3842 SMESH::Histogram_var histogram =
3843 myNodeConnFunctor->GetLocalHistogram( 1, /*isLogarithmic=*/false, obj );
3845 myWidgets[ 2 ]->setText( QString::number( histogram[0].max ) );
3848 void SMESHGUI_CtrlInfo::computeAspectRatio()
3850 #ifndef DISABLE_PLOT2DVIEWER
3851 myButtons[6]->setEnabled( false );
3856 SUIT_OverrideCursor wc;
3858 SMESH::SMESH_IDSource_var obj = myProxy.object();
3859 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3861 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3862 if ( aHistogram && !aHistogram->isEmpty() ) {
3863 QwtPlotItem* anItem = aHistogram->createPlotItem();
3864 anItem->attach( myPlot );
3871 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3873 #ifndef DISABLE_PLOT2DVIEWER
3874 myButtons[9]->setEnabled( false );
3879 SUIT_OverrideCursor wc;
3881 SMESH::SMESH_IDSource_var obj = myProxy.object();
3882 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3884 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3885 if ( aHistogram && !aHistogram->isEmpty() ) {
3886 QwtPlotItem* anItem = aHistogram->createPlotItem();
3887 anItem->attach( myPlot3D );
3895 \brief Internal clean-up (reset widget)
3897 void SMESHGUI_CtrlInfo::clearInternal()
3899 for( int i=0; i<=37; i++)
3900 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( true );
3901 for( int i=0; i<=9; i++)
3902 myButtons[i]->setEnabled( false );
3903 myPlot->detachItems();
3904 myPlot3D->detachItems();
3907 myWidgets[0]->setText( QString() );
3908 for ( int i = 1; i < myWidgets.count(); i++ )
3909 myWidgets[i]->setText( "" );
3912 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3914 myButtons[2]->setEnabled( true );
3915 myWidgets[3]->setText("");
3916 for ( int i = 0; i < myPredicates.count(); ++i )
3917 if ( myPredicates[i]->GetFunctorType() == SMESH::FT_EqualNodes )
3919 SMESH::EqualNodes_var functor = SMESH::EqualNodes::_narrow( myPredicates[i] );
3920 if ( !functor->_is_nil() )
3921 functor->SetTolerance( theTolerance );
3925 #ifndef DISABLE_PLOT2DVIEWER
3926 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3928 SUIT_OverrideCursor wc;
3930 SMESH::SMESH_IDSource_var obj = myProxy.object();
3931 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3933 if ( !mesh->IsLoaded() )
3935 aNumFun->SetMesh( mesh );
3937 CORBA::Long cprecision = 6;
3938 if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) )
3939 cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3940 aNumFun->SetPrecision( cprecision );
3942 int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3944 SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3945 /*isLogarithmic=*/false,
3947 Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3948 aHistogram->setColor( palette().color( QPalette::Highlight ) );
3949 if ( &histogramVar.in() )
3951 for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3952 aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3953 if ( histogramVar->length() >= 2 )
3954 aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3960 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
3963 QString title = tr( "CTRL_INFO" );
3964 out << ruler( title.size() ) << endl;
3965 out << title << endl;
3966 out << ruler( title.size() ) << endl;
3970 out << tr( "NAME_LAB" ) << " " << myWidgets[0]->text() << endl;
3971 out << tr( "NODES_INFO" ) << endl;
3972 out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
3973 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_NODES" ) << ": " << myWidgets[2]->text() << endl;
3974 out << tr( "EDGES_INFO" ) << endl;
3975 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_EDGES" ) << ": " << myWidgets[3]->text() << endl;
3976 out << tr( "FACES_INFO" ) << endl;
3977 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_FACES" ) << ": " << myWidgets[4]->text() << endl;
3978 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[5]->text() << endl;
3979 out << tr( "VOLUMES_INFO" ) << endl;
3980 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ) << ": " << myWidgets[6]->text() << endl;
3981 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[7]->text() << endl;
3984 ////////////////////////////////////////////////////////////////////////////////
3985 /// \class SMESHGUI_CtrlInfoDlg
3986 /// \brief Overall Mesh Quality dialog.
3987 /// \todo Add selection button to reactivate selection on move from other dlg.
3988 ////////////////////////////////////////////////////////////////////////////////
3992 \param parent parent widget
3994 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
3997 setAttribute( Qt::WA_DeleteOnClose, true );
3998 setWindowTitle( tr( "CTRL_INFO" ) );
3999 setMinimumSize( 400, 600 );
4001 myCtrlInfo = new SMESHGUI_CtrlInfo( this );
4004 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
4005 okBtn->setAutoDefault( true );
4006 okBtn->setDefault( true );
4008 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
4009 dumpBtn->setAutoDefault( true );
4010 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
4011 helpBtn->setAutoDefault( true );
4013 QHBoxLayout* btnLayout = new QHBoxLayout;
4014 btnLayout->setSpacing( SPACING );
4015 btnLayout->setMargin( 0 );
4017 btnLayout->addWidget( okBtn );
4018 btnLayout->addWidget( dumpBtn );
4019 btnLayout->addStretch( 10 );
4020 btnLayout->addWidget( helpBtn );
4022 QVBoxLayout* l = new QVBoxLayout ( this );
4024 l->setSpacing( SPACING );
4025 l->addWidget( myCtrlInfo );
4026 l->addLayout( btnLayout );
4028 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
4029 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
4030 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
4031 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
4032 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
4040 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
4045 \brief Show mesh quality information on given object.
4046 \param io Interactive object.
4048 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
4051 showInfo( SMESH::SelectionProxy( io ) );
4055 \brief Show mesh quality information on given object.
4056 \param proxy Selection proxy.
4058 void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
4060 SUIT_OverrideCursor wc;
4066 myCtrlInfo->showInfo( proxy );
4070 \brief Show mesh information
4072 void SMESHGUI_CtrlInfoDlg::updateInfo()
4074 SALOME_ListIO selected;
4075 SMESHGUI::selectionMgr()->selectedObjects( selected );
4077 if ( selected.Extent() == 1 )
4078 showInfo( selected.First() );
4080 showInfo( myProxy );
4084 \brief Perform clean-up actions on the dialog box closing.
4086 void SMESHGUI_CtrlInfoDlg::reject()
4088 SMESH::SetPointRepresentation( false );
4093 \brief Setup selection mode depending on the current dialog box state.
4095 void SMESHGUI_CtrlInfoDlg::updateSelection()
4097 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
4098 disconnect( selMgr, 0, this, 0 );
4099 SMESH::SetPointRepresentation( false );
4100 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4105 \brief Deactivate dialog box.
4107 void SMESHGUI_CtrlInfoDlg::deactivate()
4109 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4113 \brief Dump information to file.
4115 void SMESHGUI_CtrlInfoDlg::dump()
4117 DumpFileDlg fd( this, false );
4118 fd.setWindowTitle( tr( "SAVE_INFO" ) );
4119 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
4120 if ( fd.exec() == QDialog::Accepted )
4122 QString fileName = fd.selectedFile();
4123 if ( !fileName.isEmpty() ) {
4124 QFile file( fileName );
4125 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
4128 QTextStream out( &file );
4129 myCtrlInfo->saveInfo( out );
4135 \brief Show documentation on dialog.
4137 void SMESHGUI_CtrlInfoDlg::help()
4139 SMESH::ShowHelpFile( "mesh_infos.html#mesh-quality-info-anchor" );