1 // Copyright (C) 2007-2016 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. Defauls 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 Stringifed 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 );
980 \brief Register widget in a grid.
981 \param w Widget being added.
982 \param row Row index in a grid.
983 \param column Column index in a grid.
984 \param colspan Number of columns to span in a grid. Defaults to 1.
985 \return Just added widget.
987 QWidget* SMESHGUI_BaseInfo::addWidget( QWidget* w, int row, int column, int colspan )
989 if ( !myWidgets.contains( row ) )
990 myWidgets[row] = wlist();
991 myWidgets[row][column] = w;
992 dynamic_cast<QGridLayout*>( layout() )->addWidget( w, row, column, 1, colspan );
997 \brief Get registered widget.
998 \param row Row index in a grid.
999 \param column Column index in a grid.
1000 \return Widget stored in a given grid cell (0 if there's no widget).
1002 QWidget* SMESHGUI_BaseInfo::widget( int row, int column ) const
1004 return myWidgets.contains( row ) && myWidgets[row].contains( column ) ? myWidgets[row][column] : 0;
1008 \brief Get text value from registered widget.
1009 \param row Row index in a grid.
1010 \param column Column index in a grid.
1011 \return Value string (empty string if no label in given cell).
1013 QString SMESHGUI_BaseInfo::value( int row, int column ) const
1015 return widgetValue( widget( row, column ) );
1019 \brief Show/hide group(s) of widgets.
1020 \param startRow Starting grid row.
1021 \param lastRow Last grid row.
1022 \param on Visibility flag.
1024 void SMESHGUI_BaseInfo::setFieldsVisible( int startRow, int lastRow, bool on )
1026 startRow = qMax( 0, startRow );
1027 lastRow = qMin( lastRow, (int)iEnd );
1028 for ( int i = startRow; i <= lastRow; i++ )
1030 wlist widgets = myWidgets[i];
1031 foreach ( QWidget* w, widgets )
1032 w->setVisible( on );
1037 \brief Write information from panel to ouput stream.
1038 \param out Text stream output.
1040 void SMESHGUI_BaseInfo::saveInfo( QTextStream& out )
1043 QString title = tr( "BASE_INFO" );
1044 out << ruler( title.size() ) << endl;
1045 out << title << endl;
1046 out << ruler( title.size() ) << endl;
1051 out << tr( "NAME_LAB" ) << spacing() << value( iName, iSingle ) << endl;
1053 out << tr( "OBJECT_LAB" ) << spacing() << value( iObject, iSingle ) << endl;
1054 // - --- (separator)
1058 out << tr( "NODES_LAB" ) << spacing() << value( iNodes, iTotal ) << endl;
1059 // - --- (separator)
1063 QString lin = tr( "LINEAR_LAB" ) + ":" + spacing();
1064 QString qua = tr( "QUADRATIC_LAB" ) + ":" + spacing();
1065 QString biq = tr( "BI_QUADRATIC_LAB" ) + ":" + spacing();
1067 out << tr( "ELEMENTS_LAB" ) << spacing() << value( iElementsTotal, iTotal ) << endl;
1068 out << indent(1) << lin << value( iElementsTotal, iLinear ) << endl;
1069 out << indent(1) << qua << value( iElementsTotal, iQuadratic ) << endl;
1070 out << indent(1) << biq << value( iElementsTotal, iBiQuadratic ) << endl;
1071 // - --- (separator)
1073 // - 0D elements info
1074 out << indent(1) << tr( "0D_LAB" ) << spacing() << value( i0D, iTotal ) << endl;
1075 // - --- (separator)
1078 out << indent(1) << tr( "BALL_LAB" ) << spacing() << value( iBalls, iTotal ) << endl;
1079 // - --- (separator)
1081 // - 1D elements info
1082 out << indent(1) << tr( "1D_LAB" ) << spacing() << value( i1D, iTotal ) << endl;
1083 out << indent(2) << lin << value( i1D, iLinear ) << endl;
1084 out << indent(2) << qua << value( i1D, iQuadratic ) << endl;
1085 // - --- (separator)
1087 // - 2D elements info
1089 out << indent(1) << tr( "2D_LAB" ) << spacing() << value( i2D, iTotal ) << endl;
1090 out << indent(2) << lin << value( i2D, iLinear ) << endl;
1091 out << indent(2) << qua << value( i2D, iQuadratic ) << endl;
1092 out << indent(2) << biq << value( i2D, iBiQuadratic ) << endl;
1093 // - --- (separator)
1096 out << indent(2) << tr( "TRIANGLES_LAB" ) << spacing() << value( i2DTriangles, iTotal ) << endl;
1097 out << indent(3) << lin << value( i2DTriangles, iLinear ) << endl;
1098 out << indent(3) << qua << value( i2DTriangles, iQuadratic ) << endl;
1099 out << indent(3) << biq << value( i2DTriangles, iBiQuadratic ) << endl;
1101 out << indent(2) << tr( "QUADRANGLES_LAB" ) << spacing() << value( i2DQuadrangles, iTotal ) << endl;
1102 out << indent(3) << lin << value( i2DQuadrangles, iLinear ) << endl;
1103 out << indent(3) << qua << value( i2DQuadrangles, iQuadratic ) << endl;
1104 out << indent(3) << biq << value( i2DQuadrangles, iBiQuadratic ) << endl;
1106 out << indent(2) << tr( "POLYGONS_LAB" ) << spacing() << value( i2DPolygons, iTotal ) << endl;
1107 out << indent(3) << lin << value( i2DPolygons, iLinear ) << endl;
1108 out << indent(3) << qua << value( i2DPolygons, iQuadratic ) << endl;
1109 // - --- (separator)
1111 // - 3D elements info
1113 out << indent(1) << tr( "3D_LAB" ) << spacing() << value( i3D, iTotal ) << endl;
1114 out << indent(2) << lin << value( i3D, iLinear ) << endl;
1115 out << indent(2) << qua << value( i3D, iQuadratic ) << endl;
1116 out << indent(2) << biq << value( i3D, iBiQuadratic ) << endl;
1117 // - --- (separator)
1120 out << indent(2) << tr( "TETRAHEDRONS_LAB" ) << spacing() << value( i3DTetrahedrons, iTotal ) << endl;
1121 out << indent(3) << lin << value( i3DTetrahedrons, iLinear ) << endl;
1122 out << indent(3) << qua << value( i3DTetrahedrons, iQuadratic ) << endl;
1124 out << indent(2) << tr( "HEXAHEDONRS_LAB" ) << spacing() << value( i3DHexahedrons, iTotal ) << endl;
1125 out << indent(3) << lin << value( i3DHexahedrons, iLinear ) << endl;
1126 out << indent(3) << qua << value( i3DHexahedrons, iQuadratic ) << endl;
1127 out << indent(3) << biq << value( i3DHexahedrons, iBiQuadratic ) << endl;
1129 out << indent(2) << tr( "PYRAMIDS_LAB" ) << spacing() << value( i3DPyramids, iTotal ) << endl;
1130 out << indent(3) << lin << value( i3DPyramids, iLinear ) << endl;
1131 out << indent(3) << qua << value( i3DPyramids, iQuadratic ) << endl;
1133 out << indent(2) << tr( "PRISMS_LAB" ) << spacing() << value( i3DPrisms, iTotal ) << endl;
1134 out << indent(3) << lin << value( i3DPrisms, iLinear ) << endl;
1135 out << indent(3) << qua << value( i3DPrisms, iQuadratic ) << endl;
1136 out << indent(3) << biq << value( i3DPrisms, iBiQuadratic ) << endl;
1137 // --+ hexagonal prisms
1138 out << indent(2) << tr( "HEX_PRISMS_LAB" ) << spacing() << value( i3DHexaPrisms, iTotal ) << endl;
1140 out << indent(2) << tr( "POLYHEDRONS_LAB" ) << spacing() << value( i3DPolyhedrons, iTotal ) << endl;
1141 // - --- (separator)
1145 ////////////////////////////////////////////////////////////////////////////////
1146 /// \class InfoWriter
1147 /// \brief Base info writer class.
1149 ////////////////////////////////////////////////////////////////////////////////
1157 InfoWriter( bool = false );
1158 void write( const QString&, bool = false );
1159 void write( const QString&, const QString&, bool = false );
1160 void write( const QString&, int, bool = false );
1161 void write( const QString&, double, bool = false );
1162 void write( const QString&, const SMESH::XYZ&, bool = false );
1163 virtual void indent() {}
1164 virtual void unindent() {}
1165 virtual void separator() {}
1167 virtual void put( const QString&, const QString&, bool = false ) = 0;
1170 InfoWriter::InfoWriter( bool r ): myRecursive(r)
1172 myPrecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1175 void InfoWriter::write( const QString& key, bool emphasize )
1177 put( key, QString(), emphasize );
1180 void InfoWriter::write( const QString& key, const QString& value, bool emphasize )
1182 put( key, value, emphasize );
1185 void InfoWriter::write( const QString& key, int value, bool emphasize )
1187 put( key, QString::number( value ), emphasize );
1190 void InfoWriter::write( const QString& key, double value, bool emphasize )
1192 put( key, QString::number( value, myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) ), emphasize );
1195 void InfoWriter::write( const QString& key, const SMESH::XYZ& value, bool emphasize )
1199 write( key, emphasize );
1201 write( "X", value.x() );
1202 write( "Y", value.y() );
1203 write( "Z", value.z() );
1209 vl << QString::number( value.x(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1210 vl << QString::number( value.y(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1211 vl << QString::number( value.z(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1212 put( key, vl.join( ", " ), emphasize );
1216 ////////////////////////////////////////////////////////////////////////////////
1217 /// \class SimpleWriter
1218 /// \brief Base text writer.
1220 ////////////////////////////////////////////////////////////////////////////////
1222 class SimpleWriter: public InfoWriter
1232 void put( const QString&, const QString&, bool );
1233 virtual QString spacer() const;
1234 virtual QString decorate( const QString& ) const;
1235 virtual void dumpLine( const QString& ) = 0;
1238 SimpleWriter::SimpleWriter(): InfoWriter(false), myIndent(0)
1242 void SimpleWriter::indent()
1247 void SimpleWriter::unindent()
1249 myIndent = qMax( myIndent-1, 0 );
1252 void SimpleWriter::separator()
1257 QString SimpleWriter::spacer() const
1262 QString SimpleWriter::decorate( const QString& s ) const
1267 void SimpleWriter::put( const QString& key, const QString& value, bool emphasize )
1270 line += ::indent( spacer(), myIndent*4 );
1271 line += decorate( key );
1272 if ( !value.isEmpty() )
1275 line += emphasize ? decorate( value ) : value;
1280 ////////////////////////////////////////////////////////////////////////////////
1281 /// \class StreamWriter
1282 /// \brief Writer for QTextStream.
1284 ////////////////////////////////////////////////////////////////////////////////
1286 class StreamWriter: public SimpleWriter
1290 StreamWriter( QTextStream& );
1292 void dumpLine( const QString& );
1295 StreamWriter::StreamWriter( QTextStream& out ): SimpleWriter(), myOut(out)
1299 void StreamWriter::dumpLine( const QString& line )
1305 ////////////////////////////////////////////////////////////////////////////////
1306 /// \class TextWriter
1307 /// \brief Writer for QTextBrowser.
1309 ////////////////////////////////////////////////////////////////////////////////
1311 class TextWriter: public SimpleWriter
1313 QTextBrowser* myInfo;
1315 TextWriter( QTextBrowser* );
1317 QString spacer() const;
1318 QString decorate( const QString& ) const;
1319 void dumpLine( const QString& );
1322 TextWriter::TextWriter( QTextBrowser* w ): SimpleWriter(), myInfo(w)
1326 QString TextWriter::spacer() const
1331 QString TextWriter::decorate( const QString& s ) const
1336 void TextWriter::dumpLine( const QString& line )
1338 myInfo->append( line );
1341 ////////////////////////////////////////////////////////////////////////////////
1342 /// \class TreeWriter
1343 /// \brief Writer for QTreeWidget.
1345 ////////////////////////////////////////////////////////////////////////////////
1347 class TreeWriter: public InfoWriter
1349 QTreeWidget* myInfo;
1350 QTreeWidgetItem* myCurrentItem;
1351 TreeItemCreator* myCreator;
1353 TreeWriter( QTreeWidget*, TreeItemCreator* );
1358 void put( const QString&, const QString&, bool = false );
1361 TreeWriter::TreeWriter( QTreeWidget* w, TreeItemCreator* c ):
1362 InfoWriter(true), myInfo(w), myCurrentItem(0), myCreator(c)
1366 TreeWriter::~TreeWriter()
1371 void TreeWriter::put( const QString& key, const QString& value, bool emphasize )
1373 //std::string sss = myCurrentItem ? myCurrentItem->text(0).toStdString() : "";
1375 if ( emphasize ) options |= AllColumns;
1376 QTreeWidgetItem* item = myCreator->createItem( myCurrentItem, options );
1377 item->setText( 0, key );
1378 if ( !value.isEmpty() )
1380 QString val = value;
1381 if ( value.startsWith( "<a href" )) // connectivity encoded as: <a href = "nodes://host/1 2">1 2</a>
1383 int role = ( value[11] == 'n' ) ? NodeConnectivity : ElemConnectivity;
1384 val = value.mid( value.lastIndexOf( '>', -5 ) + 1 ); // ==> 1 2</a>
1386 item->setData( 1, TypeRole, role );
1388 item->setText( 1, val );
1392 void TreeWriter::indent()
1394 QTreeWidgetItem* item = myCurrentItem ? myCurrentItem : myInfo->invisibleRootItem();
1395 if ( item->childCount() > 0 )
1396 myCurrentItem = item->child( item->childCount()-1 );
1399 void TreeWriter::unindent()
1401 if ( myCurrentItem )
1402 myCurrentItem = myCurrentItem->parent();
1405 ////////////////////////////////////////////////////////////////////////////////
1406 /// \class SMESHGUI_ElemInfo
1407 /// \brief Base class for the mesh element information widget.
1409 /// Displays the detail information about given mesh node(s) or element(s).
1410 /// Default class does not provide working implementation but onle general
1411 /// functionalities; main work is done in sub-classes.
1412 ////////////////////////////////////////////////////////////////////////////////
1416 \param parent Parent widget. Defaults to 0.
1418 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent ): SMESHGUI_Info( parent ), myWhat( ShowNone )
1420 myFrame = new QWidget( this );
1421 myExtra = new ExtraWidget( this );
1423 QVBoxLayout* vbl = new QVBoxLayout( this );
1424 vbl->setMargin( 0 );
1425 vbl->setSpacing( SPACING );
1426 vbl->addWidget( myFrame );
1427 vbl->addWidget( myExtra );
1429 connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
1430 connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
1438 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
1443 \brief Show information on given node / element.
1444 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1445 \param id Mesh node / element ID.
1446 \param isElement If \c true, show element info; otherwise show node info.
1448 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, uint id, bool isElement )
1452 showInfo( proxy, ids, isElement );
1456 \brief Show information on given nodes / elements.
1457 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1458 \param ids Mesh nodes / elements IDs.
1459 \param isElement If \c true, show element info; otherwise show node info.
1461 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, QSet<uint> ids, bool isElement )
1469 QList<uint> newIds = ids.toList();
1471 int what = isElement ? ShowElements : ShowNodes;
1473 if ( myProxy == proxy && myIDs == newIds && myWhat == what )
1477 myProxy.refresh(); // try to re-initialize actor
1486 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1490 \brief Show information on given group.
1491 \param proxy Object to compute information on (group).
1493 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy )
1495 if ( !proxy || proxy.groupElementType() == SMESH::ALL ) // null proxy or not a group
1501 showInfo( proxy, proxy.ids(), proxy.groupElementType() != SMESH::NODE );
1505 \brief Reset panel (clear all data).
1507 void SMESHGUI_ElemInfo::clear()
1516 \brief Get central area widget.
1517 \return Central widget.
1519 QWidget* SMESHGUI_ElemInfo::centralWidget() const
1525 \brief Get current mesh proxy object information is shown on.
1526 \return Current proxy.
1528 SMESH::SelectionProxy SMESHGUI_ElemInfo::proxy() const
1534 \brief Get current info mode.
1535 \return Current panel mode.
1537 int SMESHGUI_ElemInfo::what() const
1543 \brief Get title for given element type.
1544 \param type Mesh element type.
1545 \param multiple Use plural form. Defaults to \c false.
1546 \return Element type's title.
1548 QString SMESHGUI_ElemInfo::type2str( int type, bool multiple )
1554 title = multiple ? tr( "EDGES" ) : tr( "EDGE" ) ; break;
1556 title = multiple ? tr( "FACES" ) : tr( "FACE" ); break;
1557 case SMDSAbs_Volume:
1558 title = multiple ? tr( "VOLUMES" ) : tr( "VOLUME" ); break;
1559 case SMDSAbs_0DElement:
1560 title = multiple ? tr( "0D_ELEMENTS" ) : tr( "0D_ELEMENT" ); break;
1562 title = multiple ? tr( "BALL_ELEMENTS" ) : tr( "BALL" ); break;
1570 \brief Get title for given shape type.
1571 \param type Shape type.
1572 \return Shape type's title.
1574 QString SMESHGUI_ElemInfo::stype2str( int type )
1580 title = tr( "GEOM_VERTEX" ); break;
1582 title = tr( "GEOM_EDGE" ); break;
1584 title = tr( "GEOM_FACE" ); break;
1587 title = tr( "GEOM_SOLID" ); break;
1594 \brief Get title for given element type.
1595 \param type Mesh element type.
1596 \return Element type's title.
1598 QString SMESHGUI_ElemInfo::etype2str( int type )
1603 case SMESH::Entity_0D:
1604 title = tr( "SMESH_ELEM0D" ); break;
1605 case SMESH::Entity_Edge:
1606 title = tr( "SMESH_EDGE" ); break;
1607 case SMESH::Entity_Quad_Edge:
1608 title = tr( "SMESH_QUADRATIC_EDGE" ); break;
1609 case SMESH::Entity_Triangle:
1610 title = tr( "SMESH_TRIANGLE" ); break;
1611 case SMESH::Entity_Quad_Triangle:
1612 title = tr( "SMESH_QUADRATIC_TRIANGLE" ); break;
1613 case SMESH::Entity_BiQuad_Triangle:
1614 title = tr( "SMESH_BIQUADRATIC_TRIANGLE" ); break;
1615 case SMESH::Entity_Quadrangle:
1616 title = tr( "SMESH_QUADRANGLE" ); break;
1617 case SMESH::Entity_Quad_Quadrangle:
1618 title = tr( "SMESH_QUADRATIC_QUADRANGLE" ); break;
1619 case SMESH::Entity_BiQuad_Quadrangle:
1620 title = tr( "SMESH_BIQUADRATIC_QUADRANGLE" ); break;
1621 case SMESH::Entity_Polygon:
1622 title = tr( "SMESH_POLYGON" ); break;
1623 case SMESH::Entity_Quad_Polygon:
1624 title = tr( "SMESH_QUADRATIC_POLYGON" ); break;
1625 case SMESH::Entity_Tetra:
1626 title = tr( "SMESH_TETRAHEDRON" ); break;
1627 case SMESH::Entity_Quad_Tetra:
1628 title = tr( "SMESH_QUADRATIC_TETRAHEDRON" ); break;
1629 case SMESH::Entity_Pyramid:
1630 title = tr( "SMESH_PYRAMID" ); break;
1631 case SMESH::Entity_Quad_Pyramid:
1632 title = tr( "SMESH_QUADRATIC_PYRAMID" ); break;
1633 case SMESH::Entity_Hexa:
1634 title = tr( "SMESH_HEXAHEDRON" ); break;
1635 case SMESH::Entity_Quad_Hexa:
1636 title = tr( "SMESH_QUADRATIC_HEXAHEDRON" ); break;
1637 case SMESH::Entity_TriQuad_Hexa:
1638 title = tr( "SMESH_TRIQUADRATIC_HEXAHEDRON" ); break;
1639 case SMESH::Entity_Penta:
1640 title = tr( "SMESH_PENTA" ); break;
1641 case SMESH::Entity_Quad_Penta:
1642 title = tr( "SMESH_QUADRATIC_PENTAHEDRON" ); break;
1643 case SMESH::Entity_BiQuad_Penta:
1644 title = tr( "SMESH_BIQUADRATIC_PENTAHEDRON" ); break;
1645 case SMESH::Entity_Hexagonal_Prism:
1646 title = tr( "SMESH_HEX_PRISM" ); break;
1647 case SMESH::Entity_Polyhedra:
1648 title = tr( "SMESH_POLYEDRON" ); break;
1649 case SMESH::Entity_Quad_Polyhedra:
1650 title = tr( "SMESH_QUADRATIC_POLYEDRON" ); break;
1651 case SMESH::Entity_Ball:
1652 title = tr( "SMESH_BALL" ); break;
1660 \brief Get title for given quality control.
1661 \param type Mesh control type.
1662 \return Quality control's title.
1664 QString SMESHGUI_ElemInfo::ctrl2str( int control )
1669 case SMESH::FT_AspectRatio:
1670 title = tr( "ASPECTRATIO_ELEMENTS" ); break;
1671 case SMESH::FT_AspectRatio3D:
1672 title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
1673 case SMESH::FT_Warping:
1674 title = tr( "WARP_ELEMENTS" ); break;
1675 case SMESH::FT_MinimumAngle:
1676 title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
1677 case SMESH::FT_Taper:
1678 title = tr( "TAPER_ELEMENTS" ); break;
1679 case SMESH::FT_Skew:
1680 title = tr( "SKEW_ELEMENTS" ); break;
1681 case SMESH::FT_Area:
1682 title = tr( "AREA_ELEMENTS" ); break;
1683 case SMESH::FT_Volume3D:
1684 title = tr( "VOLUME_3D_ELEMENTS" ); break;
1685 case SMESH::FT_MaxElementLength2D:
1686 title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
1687 case SMESH::FT_MaxElementLength3D:
1688 title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
1689 case SMESH::FT_Length:
1690 title = tr( "LENGTH_EDGES" ); break;
1691 case SMESH::FT_Length2D:
1692 case SMESH::FT_Length3D:
1693 title = tr( "MIN_ELEM_EDGE" ); break;
1694 case SMESH::FT_BallDiameter:
1695 title = tr( "BALL_DIAMETER" ); break;
1703 \brief Write information on given mesh nodes / elements.
1704 \param writer Information writer.
1705 \param ids Nodes / elements IDs.
1707 void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
1712 bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1713 int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ?
1714 SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
1717 SMESH::Connectivity connectivity;
1718 SMESH::Position position;
1721 foreach ( uint id, ids )
1723 writer->separator();
1725 if ( what() == ShowNodes )
1728 // - check that node exists
1729 if ( !proxy().hasNode( id ) )
1732 writer->write( tr( "NODE" ), (int)id, true );
1735 ok = proxy().nodeCoordinates( id, xyz );
1738 writer->write( tr( "COORDINATES" ), xyz );
1741 ok = proxy().nodeConnectivity( id, connectivity );
1744 if ( !connectivity.isEmpty() )
1746 writer->write( tr( "CONNECTIVITY" ) );
1748 for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
1750 QString formatted = formatConnectivity( connectivity, i );
1751 if ( !formatted.isEmpty() )
1752 writer->write( type2str( i, true ), formatted );
1758 writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
1762 ok = proxy().nodePosition( id, position );
1763 if ( ok && position.isValid() )
1765 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1767 if ( position.hasU() )
1768 writer->write( tr("U_POSITION"), position.u() );
1769 if ( position.hasV() )
1770 writer->write( tr("V_POSITION"), position.v() );
1773 // - groups node belongs to
1774 QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
1775 bool topCreated = false;
1776 foreach( SMESH::SelectionProxy group, groups )
1778 if ( group && !group.name().isEmpty() )
1782 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1786 writer->write( group.name().trimmed() ); // trim name
1790 int type = group.type();
1791 if ( type == SMESH::SelectionProxy::GroupStd )
1793 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1795 else if ( type == SMESH::SelectionProxy::GroupGeom )
1797 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1798 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1800 else if ( type == SMESH::SelectionProxy::GroupFilter )
1802 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1804 int size = group.size();
1806 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1807 QColor color = group.color();
1808 if ( color.isValid() )
1809 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1818 else if ( what() == ShowElements )
1820 // show element info
1821 // - check that element exists
1822 if ( !proxy().hasElement( id ) )
1825 int type = proxy().elementType( id );
1826 if ( type == SMESH::ALL )
1828 writer->write( type2str( type ), (int)id, true );
1831 type = proxy().elementEntityType( id );
1832 writer->write( tr( "TYPE" ), etype2str( type ) );
1834 if ( type == SMESH::Entity_Polyhedra ||
1835 type == SMESH::Entity_Quad_Polyhedra )
1838 ok = proxy().perFaceConnectivity( id, connectivity, nbNodes );
1839 if ( ok && !connectivity.isEmpty() )
1841 writer->write( tr( "NB_NODES" ), nbNodes );
1842 writer->write( tr( "CONNECTIVITY" ) );
1844 int nbFaces = connectivity.size();
1845 for ( int iF = 1; iF <= nbFaces; ++iF )
1847 QString formatted = formatConnectivity( connectivity, -iF );
1848 writer->write(( type2str( SMDSAbs_Face, 0 ) + " %1 / %2" ).arg( iF ).arg( nbFaces ),
1856 ok = proxy().elementConnectivity( id, connectivity );
1857 if ( ok && !connectivity.isEmpty() )
1859 QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
1860 if ( !formatted.isEmpty() )
1862 writer->write( tr( "NB_NODES" ), connectivity[ SMDSAbs_Node ].size() );
1863 writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
1868 ok = proxy().elementPosition( id, position );
1869 if ( ok && position.isValid() )
1871 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1874 ok = proxy().elementGravityCenter( id, xyz );
1877 writer->write( tr( "GRAVITY_CENTER" ), xyz );
1880 ok = proxy().elementNormal( id, xyz );
1883 writer->write( tr( "NORMAL_VECTOR" ), xyz );
1886 bool topCreated = false;
1887 for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
1889 QString ctrlTitle = ctrl2str( i );
1890 if ( ctrlTitle.isEmpty() )
1894 writer->write( tr( "CONTROLS" ) );
1899 if ( proxy().elementControl( id, i, cprecision, value ) )
1900 writer->write( ctrlTitle, value );
1904 // - groups element belongs to
1905 QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
1907 foreach( SMESH::SelectionProxy group, groups )
1909 if ( group && !group.name().isEmpty() )
1913 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1917 writer->write( group.name().trimmed() ); // trim name
1921 int type = group.type();
1922 if ( type == SMESH::SelectionProxy::GroupStd )
1924 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1926 else if ( type == SMESH::SelectionProxy::GroupGeom )
1928 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1929 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1931 else if ( type == SMESH::SelectionProxy::GroupFilter )
1933 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1935 int size = group.size();
1937 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1938 QColor color = group.color();
1939 if ( color.isValid() )
1940 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1953 \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
1954 \brief Show information on given mesh nodes / elements.
1956 This function has to be redefined in sub-classes.
1958 \param ids Nodes / elements IDs.
1962 \brief Internal clean-up (reset panel).
1964 Default implementation does nothing; the method has to be redefined
1965 in sub-classes to perform internal clean-up.
1967 void SMESHGUI_ElemInfo::clearInternal()
1972 \brief Show previous chunk of information.
1974 void SMESHGUI_ElemInfo::showPrevious()
1976 myIndex = qMax( 0, myIndex-1 );
1978 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1982 \brief Show next chunk of information.
1984 void SMESHGUI_ElemInfo::showNext()
1986 myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
1988 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1992 \brief Update control widget state.
1994 void SMESHGUI_ElemInfo::updateControls()
1996 myExtra->updateControls( myIDs.count(), myIndex );
2000 \brief Write information from panel to ouput stream.
2001 \param out Text stream output.
2003 void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
2006 QString title = tr( "ELEM_INFO" );
2007 out << ruler( title.size() ) << endl;
2008 out << title << endl;
2009 out << ruler( title.size() ) << endl;
2013 StreamWriter writer( out );
2014 writeInfo( &writer, myIDs );
2018 ////////////////////////////////////////////////////////////////////////////////
2019 /// \class SMESHGUI_SimpleElemInfo
2020 /// \brief Show mesh element information in the simple text area.
2021 ////////////////////////////////////////////////////////////////////////////////
2025 \param parent Parent widget. Defaults to 0.
2027 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
2028 : SMESHGUI_ElemInfo( parent )
2030 myInfo = new QTextBrowser( centralWidget() );
2031 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2033 l->addWidget( myInfo );
2035 connect( myInfo, SIGNAL( anchorClicked(QUrl)), this, SLOT( connectivityClicked( QUrl )));
2039 \brief Show mesh element information.
2040 \param ids Nodes / elements IDs.
2042 void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
2045 TextWriter writer( myInfo );
2046 writeInfo( &writer, ids );
2050 \brief Internal clean-up (reset widget)
2052 void SMESHGUI_SimpleElemInfo::clearInternal()
2057 void SMESHGUI_SimpleElemInfo::connectivityClicked(const QUrl & url)
2059 int type = ( url.scheme()[0] == 'n' ) ? NodeConnectivity : ElemConnectivity;
2060 QString ids = url.path(); // excess chars will be filtered off by SMESHGUI_IdValidator
2061 emit( itemInfo( type, ids ));
2064 ////////////////////////////////////////////////////////////////////////////////
2065 /// \class SMESHGUI_TreeElemInfo::ItemDelegate
2066 /// \brief Item delegate for tree mesh info widget.
2068 ////////////////////////////////////////////////////////////////////////////////
2070 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
2073 ItemDelegate( QObject* );
2074 QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
2081 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
2086 \brief Redefined from QItemDelegate.
2089 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
2091 QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
2092 if ( qobject_cast<QLineEdit*>( w ) )
2093 qobject_cast<QLineEdit*>( w )->setReadOnly( true );
2097 ////////////////////////////////////////////////////////////////////////////////
2098 /// \class SMESHGUI_TreeElemInfo::ItemCreator
2099 /// \brief Item creator for tree mesh info widget.
2101 ////////////////////////////////////////////////////////////////////////////////
2103 class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
2105 SMESHGUI_TreeElemInfo* myView;
2107 ItemCreator( SMESHGUI_TreeElemInfo* );
2108 QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
2113 \param view Parent view.
2116 SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
2121 \brief Create new tree item.
2122 \param parent Parent tree item.
2123 \param options Item options.
2124 \return New tree widget item.
2127 QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
2129 return myView->createItem( parent, options );
2132 ////////////////////////////////////////////////////////////////////////////////
2133 /// \class SMESHGUI_TreeElemInfo
2134 /// \brief Show mesh element information as the tree.
2135 ////////////////////////////////////////////////////////////////////////////////
2139 \param parent Parent widget. Defaults to 0.
2141 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
2142 : SMESHGUI_ElemInfo( parent )
2144 myInfo = new QTreeWidget( centralWidget() );
2145 myInfo->setColumnCount( 2 );
2146 myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
2147 myInfo->header()->setStretchLastSection( true );
2148 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2149 myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2151 myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2153 myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
2154 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2156 l->addWidget( myInfo );
2157 connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
2158 connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2159 connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2163 \brief Show mesh element information.
2164 \param ids Nodes / elements IDs.
2166 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
2169 TreeWriter writer( myInfo, new ItemCreator( this ) );
2170 writeInfo( &writer, ids );
2174 \brief Show node information
2175 \param node mesh node for showing
2176 \param index index of current node
2177 \param nbNodes number of unique nodes in element
2178 \param parentItem parent item of tree
2180 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* node, int index,
2181 int nbNodes, QTreeWidgetItem* parentItem )
2183 // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
2184 // // node number and ID
2185 // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
2186 // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
2187 // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
2188 // nodeItem->setData( 1, TypeRole, ElemConnectivity );
2189 // nodeItem->setData( 1, IdRole, node->GetID() );
2190 // nodeItem->setExpanded( false );
2191 // // node coordinates
2192 // QTreeWidgetItem* coordItem = createItem( nodeItem );
2193 // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
2194 // QTreeWidgetItem* xItem = createItem( coordItem );
2195 // xItem->setText( 0, "X" );
2196 // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2197 // QTreeWidgetItem* yItem = createItem( coordItem );
2198 // yItem->setText( 0, "Y" );
2199 // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2200 // QTreeWidgetItem* zItem = createItem( coordItem );
2201 // zItem->setText( 0, "Z" );
2202 // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2203 // // node connectivity
2204 // QTreeWidgetItem* nconItem = createItem( nodeItem );
2205 // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
2206 // Connectivity connectivity = nodeConnectivity( node );
2207 // if ( !connectivity.isEmpty() ) {
2208 // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
2209 // if ( !con.isEmpty() ) {
2210 // QTreeWidgetItem* i = createItem( nconItem );
2211 // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
2212 // i->setText( 1, con );
2214 // con = formatConnectivity( connectivity, SMDSAbs_Edge );
2215 // if ( !con.isEmpty() ) {
2216 // QTreeWidgetItem* i = createItem( nconItem );
2217 // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
2218 // i->setText( 1, con );
2219 // i->setData( 1, TypeRole, NodeConnectivity );
2221 // con = formatConnectivity( connectivity, SMDSAbs_Ball );
2222 // if ( !con.isEmpty() ) {
2223 // QTreeWidgetItem* i = createItem( nconItem );
2224 // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
2225 // i->setText( 1, con );
2226 // i->setData( 1, TypeRole, NodeConnectivity );
2228 // con = formatConnectivity( connectivity, SMDSAbs_Face );
2229 // if ( !con.isEmpty() ) {
2230 // QTreeWidgetItem* i = createItem( nconItem );
2231 // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
2232 // i->setText( 1, con );
2233 // i->setData( 1, TypeRole, NodeConnectivity );
2235 // con = formatConnectivity( connectivity, SMDSAbs_Volume );
2236 // if ( !con.isEmpty() ) {
2237 // QTreeWidgetItem* i = createItem( nconItem );
2238 // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
2239 // i->setText( 1, con );
2240 // i->setData( 1, TypeRole, NodeConnectivity );
2245 \brief Internal clean-up (reset widget)
2247 void SMESHGUI_TreeElemInfo::clearInternal()
2254 \brief Create new item and add it to the tree.
2255 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2256 \param options Item flags. Defaults to 0 (none).
2257 \return New tree widget item.
2259 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
2261 QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
2262 setTreeItemAttributes( item, options | Expanded | Editable );
2264 if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
2266 QString resName = expandedResource( parent );
2267 parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
2273 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2275 QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2276 if ( widgets.isEmpty() ) return;
2277 QTreeWidgetItem* aTreeItem = widgets.first();
2278 int type = aTreeItem->data( 1, TypeRole ).toInt();
2279 if (( type == ElemConnectivity || type == NodeConnectivity ) &&
2280 ( !aTreeItem->text( 1 ).isEmpty() ))
2283 QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
2284 if ( menu.exec( e->globalPos() ) == a )
2285 emit( itemInfo( type, aTreeItem->text( 1 )) );
2289 void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
2292 int type = theItem->data( 1, TypeRole ).toInt();
2293 emit( itemInfo( type, theItem->text( 1 )) );
2297 void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
2300 SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
2303 QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
2305 return QString("Expanded_") + ( what()==ShowElements ? "E_" : "N_" ) + theItem->text(0);
2308 ////////////////////////////////////////////////////////////////////////////////
2309 /// \class InfoComputor
2310 /// \brief Mesh information computor.
2313 /// The class is created for different computation operations. Currently it is
2314 /// used to compute size and number of underlying nodes for given group.
2315 ////////////////////////////////////////////////////////////////////////////////
2319 \param parent Parent object.
2320 \param proxy Object to compute information on (group).
2321 \param item Tree widget item, referenced by this computer.
2322 \param operation Value to compute.
2325 InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
2326 : QObject( parent ), myProxy( proxy ), myOperation( operation )
2331 \brief Compute requested information.
2334 void InfoComputor::compute()
2338 SUIT_OverrideCursor wc;
2339 switch ( myOperation )
2342 myProxy.size( true ); // force size computation
2346 myProxy.nbNodes( true ); // force size computation
2355 ////////////////////////////////////////////////////////////////////////////////
2356 /// \class SMESHGUI_AddInfo
2357 /// \brief Show additional information on selected object.
2359 /// Displays an additional information about selected object: mesh, sub-mesh
2362 /// \todo Rewrite saveInfo() method to print all data, not currently shown only.
2363 ////////////////////////////////////////////////////////////////////////////////
2367 \param parent Parent widget. Defaults to 0.
2369 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
2371 QVBoxLayout* l = new QVBoxLayout( this );
2373 l->setSpacing( SPACING );
2375 myTree = new QTreeWidget( this );
2377 myTree->setColumnCount( 2 );
2378 myTree->header()->setStretchLastSection( true );
2379 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2380 myTree->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2382 myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2384 myTree->header()->hide();
2386 l->addWidget( myTree );
2392 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2397 \brief Show information on given object.
2398 \param proxy Object to show information on (mesh, sub-mesh, group).
2400 void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
2403 setProperty( "group_index", 0 );
2404 setProperty( "submesh_index", 0 );
2405 myComputors.clear();
2408 // then fill panel with data if object is not null
2414 QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
2415 nameItem->setText( 0, tr( "NAME" ) );
2416 nameItem->setText( 1, proxy.name() );
2419 if ( proxy.type() == SMESH::SelectionProxy::Mesh )
2420 meshInfo( proxy, nameItem );
2421 else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
2422 subMeshInfo( proxy, nameItem );
2423 else if ( proxy.type() >= SMESH::SelectionProxy::Group )
2424 groupInfo( proxy, nameItem );
2429 \brief Update information in panel.
2431 void SMESHGUI_AddInfo::updateInfo()
2433 showInfo( myProxy );
2437 \brief Reset panel (clear all data).
2439 void SMESHGUI_AddInfo::clear()
2445 \brief Create new item and add it to the tree.
2446 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2447 \param options Item flags. Defaults to 0 (none).
2448 \return New tree widget item.
2450 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
2452 QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
2453 new QTreeWidgetItem( myTree->invisibleRootItem() );
2454 setTreeItemAttributes( item, options | Expanded );
2459 \brief Show information on mesh.
2460 \param proxy Proxy object (mesh).
2461 \param parent Parent tree item.
2463 void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2468 QString shapeName = proxy.shapeName();
2469 SMESH::MedInfo inf = proxy.medFileInfo();
2472 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2473 typeItem->setText( 0, tr( "TYPE" ) );
2474 if ( !shapeName.isEmpty() )
2476 typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2478 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2479 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2480 gobjItem->setText( 1, shapeName );
2482 else if ( inf.isValid() )
2484 typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2485 // med file information
2486 QTreeWidgetItem* fileItem = createItem( parent, Bold );
2487 fileItem->setText( 0, tr( "FILE_NAME" ) );
2488 fileItem->setText( 1, inf.fileName() );
2489 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2490 sizeItem->setText( 0, tr( "FILE_SIZE" ) );
2491 sizeItem->setText( 1, QString::number( inf.size() ) );
2492 QTreeWidgetItem* versionItem = createItem( parent, Bold );
2493 versionItem->setText( 0, tr( "FILE_VERSION" ) );
2494 versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
2498 typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2502 myGroups = proxy.groups();
2506 mySubMeshes = proxy.submeshes();
2511 \brief Show information on sub-mesh.
2512 \param proxy Proxy object (sub-mesh).
2513 \param parent Parent tree item.
2515 void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2520 bool isShort = parent->parent() != 0;
2525 SMESH::SelectionProxy meshProxy = proxy.mesh();
2528 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2529 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2530 nameItem->setText( 1, meshProxy.name() );
2535 QString shapeName = proxy.shapeName();
2536 if ( !shapeName.isEmpty() )
2538 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2539 gobjItem->setText( 1, shapeName );
2544 \brief Show information on group.
2545 \param proxy Proxy object (group).
2546 \param parent Parent tree item.
2548 void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2553 bool isShort = parent->parent() != 0;
2558 SMESH::SelectionProxy meshProxy = proxy.mesh();
2561 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2562 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2563 nameItem->setText( 1, meshProxy.name() );
2568 SMESH::SelectionProxy::Type type = proxy.type();
2569 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2570 typeItem->setText( 0, tr( "TYPE" ) );
2571 if ( type == SMESH::SelectionProxy::GroupStd )
2573 typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2575 else if ( type == SMESH::SelectionProxy::GroupGeom )
2577 typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2579 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2580 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2581 gobjItem->setText( 1, proxy.shapeName() );
2583 else if ( type == SMESH::SelectionProxy::GroupFilter )
2585 typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2589 int etype = proxy.groupElementType();
2592 QString typeName = tr( "UNKNOWN" );
2596 typeName = tr( "NODE" );
2599 typeName = tr( "EDGE" );
2602 typeName = tr( "FACE" );
2605 typeName = tr( "VOLUME" );
2608 typeName = tr( "0DELEM" );
2611 typeName = tr( "BALL" );
2616 QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2617 etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2618 etypeItem->setText( 1, typeName );
2622 // note: size is not computed for group on filter for performance reasons, see IPAL52831
2623 bool meshLoaded = proxy.isMeshLoaded();
2624 int size = proxy.size();
2626 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2627 sizeItem->setText( 0, tr( "SIZE" ) );
2630 sizeItem->setText( 1, QString::number( size ) );
2634 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2635 myTree->setItemWidget( sizeItem, 1, btn );
2636 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
2637 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2638 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2639 myComputors.append( comp );
2643 QTreeWidgetItem* colorItem = createItem( parent, Bold );
2644 colorItem->setText( 0, tr( "COLOR" ) );
2645 colorItem->setBackground( 1, proxy.color() );
2647 // nb of underlying nodes
2648 if ( etype != SMESH::NODE )
2650 QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2651 nodesItem->setText( 0, tr( "NB_NODES" ) );
2653 int nbNodes = proxy.nbNodes();
2656 nodesItem->setText( 1, QString::number( nbNodes ) );
2660 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2661 myTree->setItemWidget( nodesItem, 1, btn );
2662 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
2663 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2664 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2665 myComputors.append( comp );
2671 \brief Update information on child groups.
2673 void SMESHGUI_AddInfo::showGroups()
2675 // remove all computors
2676 myComputors.clear();
2678 // tree root should be the first top level item
2679 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2683 int idx = property( "group_index" ).toInt();
2685 // find sub-meshes top-level container item
2686 QTreeWidgetItem* itemGroups = 0;
2687 for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
2689 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
2691 itemGroups = parent->child( i );
2693 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
2695 extra->updateControls( myGroups.count(), idx );
2696 // clear: remove all group items
2697 while ( itemGroups->childCount() )
2698 delete itemGroups->child( 0 );
2702 QMap<int, QTreeWidgetItem*> grpItems;
2703 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
2705 SMESH::SelectionProxy grp = myGroups[i];
2709 int grpType = grp.groupElementType();
2711 // create top-level groups container item if it does not exist
2714 itemGroups = createItem( parent, Bold | AllColumns );
2715 itemGroups->setText( 0, tr( "GROUPS" ) );
2716 itemGroups->setData( 0, Qt::UserRole, GroupsId );
2718 // if necessary, create extra widget to show information by chunks
2719 if ( myGroups.count() > blockSize() )
2721 ExtraWidget* extra = new ExtraWidget( this, true );
2722 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2723 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2724 myTree->setItemWidget( itemGroups, 1, extra );
2725 extra->updateControls( myGroups.count(), idx );
2729 // create container item corresponding to particular element type
2730 if ( !grpItems.contains( grpType ) )
2732 grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
2733 grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2734 itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
2738 QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
2739 nameItem->setText( 0, grp.name().trimmed() ); // trim name
2742 groupInfo( grp, nameItem );
2747 \brief Update information on child sub-meshes.
2749 void SMESHGUI_AddInfo::showSubMeshes()
2751 // tree root should be the first top level item
2752 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2756 int idx = property( "submesh_index" ).toInt();
2758 // find sub-meshes top-level container item
2759 QTreeWidgetItem* itemSubMeshes = 0;
2760 for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
2762 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
2764 itemSubMeshes = parent->child( i );
2766 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
2768 extra->updateControls( mySubMeshes.count(), idx );
2769 // clear: remove all sub-mesh items
2770 while ( itemSubMeshes->childCount() )
2771 delete itemSubMeshes->child( 0 );
2775 QMap<int, QTreeWidgetItem*> smItems;
2776 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
2778 SMESH::SelectionProxy sm = mySubMeshes[i];
2782 int smType = sm.shapeType();
2785 else if ( smType == GEOM::COMPSOLID )
2786 smType = GEOM::COMPOUND;
2788 // create top-level sub-meshes container item if it does not exist
2789 if ( !itemSubMeshes )
2791 itemSubMeshes = createItem( parent, Bold | AllColumns );
2792 itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2793 itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
2795 // if necessary, create extra widget to show information by chunks
2796 if ( mySubMeshes.count() > blockSize() )
2798 ExtraWidget* extra = new ExtraWidget( this, true );
2799 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2800 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2801 myTree->setItemWidget( itemSubMeshes, 1, extra );
2802 extra->updateControls( mySubMeshes.count(), idx );
2806 // create container item corresponding to particular shape type
2807 if ( !smItems.contains( smType ) )
2809 smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
2810 smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2811 itemSubMeshes->insertChild( smType, smItems[ smType ] );
2815 QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
2816 nameItem->setText( 0, sm.name().trimmed() ); // trim name
2819 subMeshInfo( sm, nameItem );
2824 \brief Show previous chunk of information on child groups.
2826 void SMESHGUI_AddInfo::showPreviousGroups()
2828 int idx = property( "group_index" ).toInt();
2829 setProperty( "group_index", idx-1 );
2834 \brief Show next chunk of information on child groups.
2836 void SMESHGUI_AddInfo::showNextGroups()
2838 int idx = property( "group_index" ).toInt();
2839 setProperty( "group_index", idx+1 );
2844 \brief Show previous chunk of information on child sub-meshes.
2846 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2848 int idx = property( "submesh_index" ).toInt();
2849 setProperty( "submesh_index", idx-1 );
2854 \brief Show next chunk of information on child sub-meshes.
2856 void SMESHGUI_AddInfo::showNextSubMeshes()
2858 int idx = property( "submesh_index" ).toInt();
2859 setProperty( "submesh_index", idx+1 );
2864 \brief Write information from panel to ouput stream.
2865 \param out Text stream output.
2867 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2870 QString title = tr( "ADDITIONAL_INFO" );
2871 out << ruler( title.size() ) << endl;
2872 out << title << endl;
2873 out << ruler( title.size() ) << endl;
2877 QTreeWidgetItemIterator it( myTree );
2880 if ( !( ( *it )->text(0) ).isEmpty() )
2882 out << indent( itemDepth( *it ) ) << ( *it )->text(0);
2883 if ( ( *it )->text(0) == tr( "COLOR" ) )
2884 out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
2885 else if ( !( ( *it )->text(1) ).isEmpty() )
2886 out << ":" << spacing() << ( *it )->text(1);
2894 ////////////////////////////////////////////////////////////////////////////////
2895 /// \class GroupCombo
2896 /// \brief Customized combo box to manage list of mesh groups.
2898 ////////////////////////////////////////////////////////////////////////////////
2900 class GroupCombo: public QComboBox
2902 class Item: public QStandardItem
2905 SMESH::SelectionProxy myGroup;
2906 Item( const SMESH::SelectionProxy& group )
2909 setText( myGroup.name() );
2911 SMESH::SelectionProxy group()
2917 SMESH::SelectionProxy myProxy;
2920 GroupCombo( QWidget* );
2921 void setSource( const SMESH::SelectionProxy& );
2922 SMESH::SelectionProxy currentGroup() const;
2927 \param parent Parent widget.
2930 GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
2932 setModel( new QStandardItemModel( this ) );
2936 \brief Set mesh source.
2937 \param obj Mesh source.
2940 void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
2942 if ( myProxy == proxy )
2947 bool blocked = blockSignals( true );
2948 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2953 if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
2955 QList<SMESH::SelectionProxy> groups = myProxy.groups();
2956 for ( int i = 0; i < groups.count(); ++i )
2960 QString name = groups[i].name();
2961 if ( !name.isEmpty() )
2962 m->appendRow( new Item( groups[i] ) );
2965 setCurrentIndex( -1 ); // for performance reasons
2967 else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
2969 m->appendRow( new Item( myProxy ) );
2970 setCurrentIndex( 0 );
2974 blockSignals( blocked );
2978 \brief Get currently selected group.
2979 \return Selected group.
2982 SMESH::SelectionProxy GroupCombo::currentGroup() const
2984 SMESH::SelectionProxy group;
2985 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2986 if ( currentIndex() >= 0 )
2987 group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
2991 ////////////////////////////////////////////////////////////////////////////////
2992 /// \class SMESHGUI_MeshInfoDlg
2993 /// \brief Mesh information dialog box
2995 /// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
2996 /// \todo Add selection button to reactivate selection on move from other dlg.
2997 ////////////////////////////////////////////////////////////////////////////////
3001 \param parent Parent widget.
3002 \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
3004 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
3008 setAttribute( Qt::WA_DeleteOnClose, true );
3009 setWindowTitle( tr( "MESH_INFO" ) );
3010 setSizeGripEnabled( true );
3012 myTabWidget = new QTabWidget( this );
3016 myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
3017 myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
3021 QWidget* w = new QWidget( myTabWidget );
3023 myMode = new QButtonGroup( this );
3024 myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
3025 myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
3026 myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
3027 myMode->button( NodeMode )->setChecked( true );
3028 myID = new QLineEdit( w );
3029 myID->setValidator( new SMESHGUI_IdValidator( this ) );
3030 myGroups = new GroupCombo( w );
3031 QStackedWidget* stack = new QStackedWidget( w );
3032 stack->addWidget( myID );
3033 stack->addWidget( myGroups );
3034 myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
3035 myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
3037 int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
3038 mode = qMin( 1, qMax( 0, mode ) );
3041 myElemInfo = new SMESHGUI_SimpleElemInfo( w );
3043 myElemInfo = new SMESHGUI_TreeElemInfo( w );
3044 stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
3046 QGridLayout* elemLayout = new QGridLayout( w );
3047 elemLayout->setMargin( MARGIN );
3048 elemLayout->setSpacing( SPACING );
3049 elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
3050 elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
3051 elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
3052 elemLayout->addWidget( stack, 0, 3 );
3053 elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
3054 elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
3056 myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
3060 myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
3061 myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
3065 myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
3066 myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
3070 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3071 okBtn->setAutoDefault( true );
3072 okBtn->setDefault( true );
3074 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3075 dumpBtn->setAutoDefault( true );
3076 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3077 helpBtn->setAutoDefault( true );
3079 QHBoxLayout* btnLayout = new QHBoxLayout;
3080 btnLayout->setSpacing( SPACING );
3081 btnLayout->setMargin( 0 );
3083 btnLayout->addWidget( okBtn );
3084 btnLayout->addWidget( dumpBtn );
3085 btnLayout->addStretch( 10 );
3086 btnLayout->addWidget( helpBtn );
3090 QVBoxLayout* l = new QVBoxLayout ( this );
3091 l->setMargin( MARGIN );
3092 l->setSpacing( SPACING );
3093 l->addWidget( myTabWidget );
3094 l->addLayout( btnLayout );
3098 myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
3100 // set-up connections
3102 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3103 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3104 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3105 connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
3106 connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
3107 connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
3108 connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
3109 connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
3110 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3111 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3112 connect( myElemInfo, SIGNAL( itemInfo( int, QString ) ), this, SLOT( showItemInfo( int, QString ) ) );
3113 connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
3117 myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
3124 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
3130 \brief Show mesh information on given object.
3131 \param io Interactive object.
3133 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3136 showInfo( SMESH::SelectionProxy( io ) );
3140 \brief Show mesh information on given object.
3141 \param proxy Selection proxy.
3143 void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3145 SUIT_OverrideCursor wc;
3152 SMESH::SMESH_IDSource_var obj = myProxy.object();
3155 myBaseInfo->showInfo( proxy );
3157 // "Additional info" tab
3158 myAddInfo->showInfo( proxy );
3160 // "Quality info" tab
3161 // Note: for performance reasons we update it only if it is currently active
3162 if ( myTabWidget->currentIndex() == CtrlInfo )
3163 myCtrlInfo->showInfo( proxy );
3165 // "Element info" tab
3166 myGroups->setSource( proxy );
3167 if ( myMode->checkedId() == GroupMode ) {
3168 SMESH::SelectionProxy group = myGroups->currentGroup();
3170 myElemInfo->showInfo( group );
3172 myElemInfo->clear();
3175 SVTK_Selector* selector = SMESH::GetSelector();
3178 if ( myProxy.actor() && selector ) { //todo: actor()?
3179 nb = myMode->checkedId() == NodeMode ?
3180 SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
3181 SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
3184 myID->setText( ID.trimmed() );
3186 QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
3187 foreach ( ID, idTxt )
3188 ids << ID.trimmed().toUInt();
3189 myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
3193 myElemInfo->clear();
3199 \brief Update information.
3201 void SMESHGUI_MeshInfoDlg::updateInfo()
3203 SALOME_ListIO selected;
3204 SMESHGUI::selectionMgr()->selectedObjects( selected );
3206 if ( selected.Extent() == 1 )
3207 showInfo( selected.First() );
3209 showInfo( myProxy );
3213 \brief Clean-up on dialog closing.
3215 void SMESHGUI_MeshInfoDlg::reject()
3217 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3218 selMgr->clearFilters();
3219 SMESH::SetPointRepresentation( false );
3220 if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
3221 viewWindow->SetSelectionMode( ActorSelection );
3223 myIDPreview->SetPointsLabeled( false );
3227 \brief Process keyboard event.
3228 \param e Key press event.
3230 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
3232 QDialog::keyPressEvent( e );
3233 if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
3240 \brief Set-up selection mode for currently selected page.
3242 void SMESHGUI_MeshInfoDlg::updateSelection()
3244 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3246 disconnect( selMgr, 0, this, 0 );
3247 selMgr->clearFilters();
3249 int selMode = ActorSelection;
3250 if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == NodeMode )
3251 selMode = NodeSelection;
3252 else if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == ElemMode )
3253 selMode = CellSelection;
3254 SMESH::SetPointRepresentation( selMode == NodeSelection );
3255 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3256 aViewWindow->SetSelectionMode( selMode );
3258 SMESH::SelectionProxy previous = myProxy;
3259 QString ids = myID->text().trimmed();
3262 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3265 if ( myProxy && myProxy == previous && !ids.isEmpty() ) {
3266 myID->setText( ids );
3272 \brief Show documentation on selected dialog page.
3274 void SMESHGUI_MeshInfoDlg::help()
3276 QString helpPage = "mesh_infos.html";
3277 switch ( myTabWidget->currentIndex() )
3280 helpPage += "#advanced-mesh-infos-anchor";
3283 helpPage += "#mesh-element-info-anchor";
3286 helpPage += "#mesh-addition-info-anchor";
3289 helpPage += "#mesh-quality-info-anchor";
3294 SMESH::ShowHelpFile( helpPage );
3298 \brief Deactivate dialog box.
3300 void SMESHGUI_MeshInfoDlg::deactivate()
3302 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3306 \brief Called when users switches between node / element modes.
3308 void SMESHGUI_MeshInfoDlg::modeChanged()
3310 emit( switchMode( myMode->checkedId() == GroupMode ? 1 : 0 ) );
3316 \brief Called when users prints mesh element ID in the corresponding field.
3318 void SMESHGUI_MeshInfoDlg::idChanged()
3320 myIDPreview->SetPointsLabeled( false );
3323 TColStd_MapOfInteger ID;
3325 std::vector<int> idVec;
3326 std::list< gp_XYZ > aGrCentersXYZ;
3328 const bool isElem = ( myMode->checkedId() == ElemMode );
3329 QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
3330 foreach ( QString tid, idTxt ) {
3331 long id = tid.toUInt();
3332 if ( isElem ? myProxy.hasElement( id ) : myProxy.hasNode( id ))
3336 if ( isElem && myProxy.actor() && myProxy.elementGravityCenter( id, xyz ))
3338 idVec.push_back( id );
3339 aGrCentersXYZ.push_back( xyz );
3343 SVTK_Selector* selector = SMESH::GetSelector();
3344 if ( myProxy.actor() && selector ) {
3345 Handle(SALOME_InteractiveObject) IO = myProxy.actor()->getIO();
3346 selector->AddOrRemoveIndex( IO, ID, false );
3347 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3349 if ( myMode->checkedId() == NodeMode )
3350 myIDPreview->SetPointsData( myProxy.actor()->GetObject()->GetMesh(), ID );
3352 myIDPreview->SetElemsData( idVec, aGrCentersXYZ );
3354 bool showIDs = ( !ID.IsEmpty() &&
3355 myIDPreviewCheck->isChecked() &&
3356 myTabWidget->currentIndex() == ElemInfo );
3357 myIDPreview->SetPointsLabeled( showIDs, myProxy.actor()->GetVisibility() );
3359 aViewWindow->highlight( IO, true, true );
3360 aViewWindow->Repaint();
3363 myElemInfo->showInfo( myProxy, ids, isElem );
3368 * \brief Show IDs clicked
3370 void SMESHGUI_MeshInfoDlg::idPreviewChange( bool isOn )
3372 myIDPreview->SetPointsLabeled( isOn && !myID->text().simplified().isEmpty() );
3373 SMESHGUI::resourceMgr()->setValue("SMESH", "id_preview_resource", isOn );
3374 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3375 aViewWindow->Repaint();
3378 void SMESHGUI_MeshInfoDlg::showItemInfo( int type, const QString& ids )
3380 if ( !ids.isEmpty() && ( type == NodeConnectivity || type == ElemConnectivity )) {
3381 myMode->button( type - NodeConnectivity )->click();
3382 myID->setText( ids );
3387 \brief Dump information to file.
3389 void SMESHGUI_MeshInfoDlg::dump()
3391 DumpFileDlg fd( this );
3392 fd.setWindowTitle( tr( "SAVE_INFO" ) );
3393 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
3394 fd.setChecked( BaseInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_base", true ) );
3395 fd.setChecked( ElemInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_elem", true ) );
3396 fd.setChecked( AddInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_add", true ) );
3397 fd.setChecked( CtrlInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_ctrl", true ) );
3398 if ( fd.exec() == QDialog::Accepted )
3400 QString fileName = fd.selectedFile();
3401 if ( !fileName.isEmpty() ) {
3402 QFile file( fileName );
3403 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
3406 QTextStream out( &file );
3407 if ( fd.isChecked( BaseInfo ) ) myBaseInfo->saveInfo( out );
3408 if ( fd.isChecked( ElemInfo ) ) myElemInfo->saveInfo( out );
3409 if ( fd.isChecked( AddInfo ) ) myAddInfo->saveInfo( out );
3410 if ( fd.isChecked( CtrlInfo ) ) myCtrlInfo->saveInfo( out );
3415 ////////////////////////////////////////////////////////////////////////////////
3416 /// \class SMESHGUI_CtrlInfo
3417 /// \brief Show quality statistics information on selected object.
3419 /// Displays quality controls statistics about selected object: mesh, sub-mesh,
3420 /// group or arbitrary ID source.
3421 ////////////////////////////////////////////////////////////////////////////////
3425 \param parent Parent widget. Defaults to 0.
3427 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent ): SMESHGUI_Info( parent )
3429 QGridLayout* l = new QGridLayout( this );
3430 l->setMargin( MARGIN );
3431 l->setSpacing( SPACING );
3433 QIcon aComputeIcon( SUIT_Session::session()->resourceMgr()->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3434 SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3437 QLabel* aNameLab = createLabel( tr( "NAME_LAB" ), this, Bold );
3438 QLabel* aName = createField( this, "ctrlName" );
3439 aName->setMinimumWidth( 150 );
3443 QLabel* aNodesLab = createLabel( tr( "NODES_INFO" ), this, Bold );
3444 QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3445 QLabel* aNodesFree = createField( this, "ctrlNodesFree" );
3446 myWidgets << aNodesFree;
3447 myPredicates << aFilterMgr->CreateFreeNodes();
3449 QLabel* aNodesNbConnLab = new QLabel( tr( "MAX_NODE_CONNECTIVITY" ), this );
3450 QLabel* aNodesNbConn = createField( this, "ctrlNodesCnty" );
3451 myWidgets << aNodesNbConn;
3452 myNodeConnFunctor = aFilterMgr->CreateNodeConnectivityNumber();
3454 QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3455 QLabel* aNodesDouble = createField( this, "ctrlNodesDouble" );
3456 myWidgets << aNodesDouble;
3457 myPredicates << aFilterMgr->CreateEqualNodes();
3458 QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3459 myToleranceWidget = new SMESHGUI_SpinBox( this );
3460 myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3461 myToleranceWidget->setAcceptNames( false );
3462 myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3465 QLabel* anEdgesLab = createLabel( tr( "EDGES_INFO" ), this, Bold );
3466 QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ), this );
3467 QLabel* anEdgesDouble = createField( this, "ctrlEdgesDouble" );
3468 myWidgets << anEdgesDouble;
3469 myPredicates << aFilterMgr->CreateEqualEdges();
3472 QLabel* aFacesLab = createLabel( tr( "FACES_INFO" ), this, Bold );
3473 QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3474 QLabel* aFacesDouble = createField( this, "ctrlFacesDouble" );
3475 myWidgets << aFacesDouble;
3476 myPredicates << aFilterMgr->CreateEqualFaces();
3477 QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3478 QLabel* aFacesOver = createField( this, "ctrlFacesOver" );
3479 myWidgets << aFacesOver;
3480 myPredicates << aFilterMgr->CreateOverConstrainedFace();
3481 QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3482 myPlot = createPlot( this );
3483 myAspectRatio = aFilterMgr->CreateAspectRatio();
3486 QLabel* aVolumesLab = createLabel( tr( "VOLUMES_INFO" ), this, Bold );
3487 QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3488 QLabel* aVolumesDouble = createField( this, "ctrlVolumesDouble" );
3489 myWidgets << aVolumesDouble;
3490 myPredicates << aFilterMgr->CreateEqualVolumes();
3491 QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3492 QLabel* aVolumesOver = createField( this, "ctrlVolumesOver" );
3493 myWidgets << aVolumesOver;
3494 myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3495 QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3496 myPlot3D = createPlot( this );
3497 myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3499 QToolButton* aFreeNodesBtn = new QToolButton( this );
3500 aFreeNodesBtn->setIcon(aComputeIcon);
3501 myButtons << aFreeNodesBtn; //0
3503 QToolButton* aNodesNbConnBtn = new QToolButton( this );
3504 aNodesNbConnBtn->setIcon(aComputeIcon);
3505 myButtons << aNodesNbConnBtn; //1
3507 QToolButton* aDoubleNodesBtn = new QToolButton( this );
3508 aDoubleNodesBtn->setIcon(aComputeIcon);
3509 myButtons << aDoubleNodesBtn; //2
3511 QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3512 aDoubleEdgesBtn->setIcon(aComputeIcon);
3513 myButtons << aDoubleEdgesBtn; //3
3515 QToolButton* aDoubleFacesBtn = new QToolButton( this );
3516 aDoubleFacesBtn->setIcon(aComputeIcon);
3517 myButtons << aDoubleFacesBtn; //4
3519 QToolButton* aOverContFacesBtn = new QToolButton( this );
3520 aOverContFacesBtn->setIcon(aComputeIcon);
3521 myButtons << aOverContFacesBtn; //5
3523 QToolButton* aComputeFaceBtn = new QToolButton( this );
3524 aComputeFaceBtn->setIcon(aComputeIcon);
3525 myButtons << aComputeFaceBtn; //6
3527 QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3528 aDoubleVolumesBtn->setIcon(aComputeIcon);
3529 myButtons << aDoubleVolumesBtn; //7
3531 QToolButton* aOverContVolumesBtn = new QToolButton( this );
3532 aOverContVolumesBtn->setIcon(aComputeIcon);
3533 myButtons << aOverContVolumesBtn; //8
3535 QToolButton* aComputeVolumeBtn = new QToolButton( this );
3536 aComputeVolumeBtn->setIcon(aComputeIcon);
3537 myButtons << aComputeVolumeBtn; //9
3539 connect( aComputeFaceBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3540 connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3541 connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3542 connect( aNodesNbConnBtn, SIGNAL( clicked() ), this, SLOT( computeNodesNbConnInfo() ) );
3543 connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3544 connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3545 connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3546 connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3547 connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3548 connect( aOverContVolumesBtn,SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3549 connect( myToleranceWidget, SIGNAL( valueChanged( double ) ), this, SLOT( setTolerance( double ) ) );
3551 l->addWidget( aNameLab, 0, 0 ); //0
3552 l->addWidget( aName, 0, 1, 1, 2 ); //1
3553 l->addWidget( aNodesLab, 1, 0, 1, 3 ); //2
3554 l->addWidget( aNodesFreeLab, 2, 0 ); //3
3555 l->addWidget( aNodesFree, 2, 1 ); //4
3556 l->addWidget( aFreeNodesBtn, 2, 2 ); //5
3557 l->addWidget( aNodesNbConnLab, 3, 0 ); //6
3558 l->addWidget( aNodesNbConn, 3, 1 ); //7
3559 l->addWidget( aNodesNbConnBtn, 3, 2 ); //8
3560 l->addWidget( aNodesDoubleLab, 4, 0 ); //9
3561 l->addWidget( aNodesDouble, 4, 1 ); //10
3562 l->addWidget( aDoubleNodesBtn, 4, 2 ); //11
3563 l->addWidget( aToleranceLab, 5, 0 ); //12
3564 l->addWidget( myToleranceWidget, 5, 1 ); //13
3565 l->addWidget( anEdgesLab, 6, 0, 1, 3 ); //14
3566 l->addWidget( anEdgesDoubleLab, 7, 0 ); //15
3567 l->addWidget( anEdgesDouble, 7, 1 ); //16
3568 l->addWidget( aDoubleEdgesBtn, 7, 2 ); //17
3569 l->addWidget( aFacesLab, 8, 0, 1, 3 ); //18
3570 l->addWidget( aFacesDoubleLab, 9, 0 ); //19
3571 l->addWidget( aFacesDouble, 9, 1 ); //20
3572 l->addWidget( aDoubleFacesBtn, 9, 2 ); //21
3573 l->addWidget( aFacesOverLab, 10, 0 ); //22
3574 l->addWidget( aFacesOver, 10, 1 ); //23
3575 l->addWidget( aOverContFacesBtn, 10, 2 ); //24
3576 l->addWidget( anAspectRatioLab, 11, 0 ); //25
3577 l->addWidget( aComputeFaceBtn, 11, 2 ); //26
3578 l->addWidget( myPlot, 12, 0, 1, 3 );//27
3579 l->addWidget( aVolumesLab, 13, 0, 1, 3 );//28
3580 l->addWidget( aVolumesDoubleLab, 14, 0 ); //29
3581 l->addWidget( aVolumesDouble, 14, 1 ); //30
3582 l->addWidget( aDoubleVolumesBtn, 14, 2 ); //31
3583 l->addWidget( aVolumesOverLab, 15, 0 ); //32
3584 l->addWidget( aVolumesOver, 15, 1 ); //33
3585 l->addWidget( aOverContVolumesBtn,15, 2 ); //34
3586 l->addWidget( anAspectRatio3DLab, 16, 0 ); //35
3587 l->addWidget( aComputeVolumeBtn, 16, 2 ); //36
3588 l->addWidget( myPlot3D, 17, 0, 1, 3 );//37
3590 l->setColumnStretch( 0, 0 );
3591 l->setColumnStretch( 1, 5 );
3592 l->setRowStretch ( 12, 5 );
3593 l->setRowStretch ( 17, 5 );
3594 l->setRowStretch ( 18, 1 );
3602 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3607 \brief Create plot widget.
3608 \param parent Parent widget.
3609 \return New plot widget.
3611 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3613 QwtPlot* aPlot = new QwtPlot( parent );
3614 aPlot->setMinimumSize( 100, 100 );
3615 QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3616 xFont.setPointSize( 5 );
3617 QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3618 yFont.setPointSize( 5 );
3619 aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3620 aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3626 \brief Show information on given object.
3627 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
3629 void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
3637 SMESH::SMESH_IDSource_var obj = proxy.object();
3639 myWidgets[0]->setText( proxy.name() );
3641 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3642 if ( mesh->_is_nil() ) return;
3644 const bool meshLoaded = mesh->IsLoaded();
3645 if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3646 // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3647 for ( int i = 0; i < myButtons.count(); ++i )
3648 myButtons[i]->setEnabled( true );
3650 SMESH::long_array_var nbElemsByType = obj->GetNbElementsByType();
3651 if ( ! &nbElemsByType.in() ) return;
3653 const CORBA::Long ctrlLimit =
3654 meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3657 const CORBA::Long nbNodes = nbElemsByType[ SMESH::NODE ];
3658 // const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3659 // nbElemsByType[ SMESH::FACE ] +
3660 // nbElemsByType[ SMESH::VOLUME ] );
3661 if ( nbNodes > 0 ) {
3662 if ( nbNodes <= ctrlLimit ) {
3664 computeFreeNodesInfo();
3665 // node connectivity number
3666 computeNodesNbConnInfo();
3668 computeDoubleNodesInfo();
3671 myButtons[0]->setEnabled( true );
3672 myButtons[1]->setEnabled( true );
3673 myButtons[2]->setEnabled( true );
3677 for( int i=2; i<=13; i++)
3678 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3682 if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3684 if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3685 computeDoubleEdgesInfo();
3687 myButtons[3]->setEnabled( true );
3690 for( int i=14; i<=17; i++)
3691 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3695 if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3696 if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3698 computeDoubleFacesInfo();
3699 // over constrained faces
3700 computeOverConstrainedFacesInfo();
3701 // aspect Ratio histogram
3702 computeAspectRatio();
3705 myButtons[4]->setEnabled( true );
3706 myButtons[5]->setEnabled( true );
3707 myButtons[6]->setEnabled( true );
3709 #ifdef DISABLE_PLOT2DVIEWER
3710 for( int i=25; i<=27; i++)
3711 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3715 for( int i=18; i<=27; i++)
3716 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3720 if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3721 if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3723 computeDoubleVolumesInfo();
3724 // over constrained volumes
3725 computeOverConstrainedVolumesInfo();
3726 // aspect Ratio 3D histogram
3727 computeAspectRatio3D();
3730 myButtons[7]->setEnabled( true );
3731 myButtons[8]->setEnabled( true );
3732 myButtons[9]->setEnabled( true );
3734 #ifdef DISABLE_PLOT2DVIEWER
3735 for( int i=35; i<=37; i++)
3736 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3740 for( int i=28; i<=37; i++)
3741 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3745 //================================================================================
3747 * \brief Computes and shows nb of elements satisfying a given predicate
3748 * \param [in] ft - a predicate type (SMESH::FunctorType)
3749 * \param [in] iBut - index of one of myButtons to disable
3750 * \param [in] iWdg - index of one of myWidgets to show the computed number
3752 //================================================================================
3754 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3756 myButtons[ iBut ]->setEnabled( false );
3757 myWidgets[ iWdg ]->setText( "" );
3762 SUIT_OverrideCursor wc;
3764 SMESH::SMESH_IDSource_var obj = myProxy.object();
3765 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3767 if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3770 showInfo( myProxy ); // try to show all values
3771 if ( !myWidgets[ iWdg ]->text().isEmpty() )
3772 return; // <ft> predicate already computed
3774 // look for a predicate of type <ft>
3775 for ( int i = 0; i < myPredicates.count(); ++i )
3776 if ( myPredicates[i]->GetFunctorType() == ft )
3778 CORBA::Long nb = myPredicates[i]->NbSatisfying( obj );
3779 myWidgets[ iWdg ]->setText( QString::number( nb ) );
3783 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3785 computeNb( SMESH::FT_FreeNodes, 0, 1 );
3788 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3790 computeNb( SMESH::FT_EqualNodes, 2, 3 );
3793 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3795 computeNb( SMESH::FT_EqualEdges, 3, 4 );
3798 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3800 computeNb( SMESH::FT_EqualFaces, 4, 5 );
3803 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3805 computeNb( SMESH::FT_OverConstrainedFace, 5, 6 );
3808 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3810 computeNb( SMESH::FT_EqualVolumes, 7, 7 );
3813 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3815 computeNb( SMESH::FT_OverConstrainedVolume, 8, 8 );
3818 void SMESHGUI_CtrlInfo::computeNodesNbConnInfo()
3820 myButtons[ 1 ]->setEnabled( false );
3821 myWidgets[ 2 ]->setText( "" );
3826 SUIT_OverrideCursor wc;
3828 SMESH::SMESH_IDSource_var obj = myProxy.object();
3829 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3831 if ( !mesh->IsLoaded() )
3834 showInfo( myProxy ); // try to show all values
3835 if ( !myWidgets[ 2 ]->text().isEmpty() )
3836 return; // already computed
3838 myNodeConnFunctor->SetMesh( mesh );
3839 SMESH::Histogram_var histogram =
3840 myNodeConnFunctor->GetLocalHistogram( 1, /*isLogarithmic=*/false, obj );
3842 myWidgets[ 2 ]->setText( QString::number( histogram[0].max ) );
3845 void SMESHGUI_CtrlInfo::computeAspectRatio()
3847 #ifndef DISABLE_PLOT2DVIEWER
3848 myButtons[6]->setEnabled( false );
3853 SUIT_OverrideCursor wc;
3855 SMESH::SMESH_IDSource_var obj = myProxy.object();
3856 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3858 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3859 if ( aHistogram && !aHistogram->isEmpty() ) {
3860 QwtPlotItem* anItem = aHistogram->createPlotItem();
3861 anItem->attach( myPlot );
3868 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3870 #ifndef DISABLE_PLOT2DVIEWER
3871 myButtons[9]->setEnabled( false );
3876 SUIT_OverrideCursor wc;
3878 SMESH::SMESH_IDSource_var obj = myProxy.object();
3879 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3881 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3882 if ( aHistogram && !aHistogram->isEmpty() ) {
3883 QwtPlotItem* anItem = aHistogram->createPlotItem();
3884 anItem->attach( myPlot3D );
3892 \brief Internal clean-up (reset widget)
3894 void SMESHGUI_CtrlInfo::clearInternal()
3896 for( int i=0; i<=37; i++)
3897 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( true );
3898 for( int i=0; i<=9; i++)
3899 myButtons[i]->setEnabled( false );
3900 myPlot->detachItems();
3901 myPlot3D->detachItems();
3904 myWidgets[0]->setText( QString() );
3905 for ( int i = 1; i < myWidgets.count(); i++ )
3906 myWidgets[i]->setText( "" );
3909 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3911 //SMESH::long_array_var anElems = getElementsByType( SMESH::NODE );
3912 myButtons[1]->setEnabled( true );
3913 myWidgets[2]->setText("");
3916 #ifndef DISABLE_PLOT2DVIEWER
3917 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3919 SUIT_OverrideCursor wc;
3921 SMESH::SMESH_IDSource_var obj = myProxy.object();
3922 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3924 if ( !mesh->IsLoaded() )
3926 aNumFun->SetMesh( mesh );
3928 CORBA::Long cprecision = 6;
3929 if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) )
3930 cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3931 aNumFun->SetPrecision( cprecision );
3933 int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3935 SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3936 /*isLogarithmic=*/false,
3938 Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3939 aHistogram->setColor( palette().color( QPalette::Highlight ) );
3940 if ( &histogramVar.in() )
3942 for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3943 aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3944 if ( histogramVar->length() >= 2 )
3945 aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3951 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
3954 QString title = tr( "CTRL_INFO" );
3955 out << ruler( title.size() ) << endl;
3956 out << title << endl;
3957 out << ruler( title.size() ) << endl;
3961 out << tr( "NAME_LAB" ) << " " << myWidgets[0]->text() << endl;
3962 out << tr( "NODES_INFO" ) << endl;
3963 out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
3964 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_NODES" ) << ": " << myWidgets[2]->text() << endl;
3965 out << tr( "EDGES_INFO" ) << endl;
3966 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_EDGES" ) << ": " << myWidgets[3]->text() << endl;
3967 out << tr( "FACES_INFO" ) << endl;
3968 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_FACES" ) << ": " << myWidgets[4]->text() << endl;
3969 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[5]->text() << endl;
3970 out << tr( "VOLUMES_INFO" ) << endl;
3971 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ) << ": " << myWidgets[6]->text() << endl;
3972 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[7]->text() << endl;
3975 ////////////////////////////////////////////////////////////////////////////////
3976 /// \class SMESHGUI_CtrlInfoDlg
3977 /// \brief Overall Mesh Quality dialog.
3978 /// \todo Add selection button to reactivate selection on move from other dlg.
3979 ////////////////////////////////////////////////////////////////////////////////
3983 \param parent parent widget
3985 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
3988 setAttribute( Qt::WA_DeleteOnClose, true );
3989 setWindowTitle( tr( "CTRL_INFO" ) );
3990 setMinimumSize( 400, 600 );
3992 myCtrlInfo = new SMESHGUI_CtrlInfo( this );
3995 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3996 okBtn->setAutoDefault( true );
3997 okBtn->setDefault( true );
3999 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
4000 dumpBtn->setAutoDefault( true );
4001 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
4002 helpBtn->setAutoDefault( true );
4004 QHBoxLayout* btnLayout = new QHBoxLayout;
4005 btnLayout->setSpacing( SPACING );
4006 btnLayout->setMargin( 0 );
4008 btnLayout->addWidget( okBtn );
4009 btnLayout->addWidget( dumpBtn );
4010 btnLayout->addStretch( 10 );
4011 btnLayout->addWidget( helpBtn );
4013 QVBoxLayout* l = new QVBoxLayout ( this );
4015 l->setSpacing( SPACING );
4016 l->addWidget( myCtrlInfo );
4017 l->addLayout( btnLayout );
4019 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
4020 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
4021 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
4022 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
4023 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
4031 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
4036 \brief Show mesh quality information on given object.
4037 \param io Interactive object.
4039 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
4042 showInfo( SMESH::SelectionProxy( io ) );
4046 \brief Show mesh quality information on given object.
4047 \param proxy Selection proxy.
4049 void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
4051 SUIT_OverrideCursor wc;
4057 myCtrlInfo->showInfo( proxy );
4061 \brief Show mesh information
4063 void SMESHGUI_CtrlInfoDlg::updateInfo()
4065 SALOME_ListIO selected;
4066 SMESHGUI::selectionMgr()->selectedObjects( selected );
4068 if ( selected.Extent() == 1 )
4069 showInfo( selected.First() );
4071 showInfo( myProxy );
4075 \brief Perform clean-up actions on the dialog box closing.
4077 void SMESHGUI_CtrlInfoDlg::reject()
4079 SMESH::SetPointRepresentation( false );
4084 \brief Setup selection mode depending on the current dialog box state.
4086 void SMESHGUI_CtrlInfoDlg::updateSelection()
4088 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
4089 disconnect( selMgr, 0, this, 0 );
4090 SMESH::SetPointRepresentation( false );
4091 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4096 \brief Deactivate dialog box.
4098 void SMESHGUI_CtrlInfoDlg::deactivate()
4100 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4104 \brief Dump information to file.
4106 void SMESHGUI_CtrlInfoDlg::dump()
4108 DumpFileDlg fd( this, false );
4109 fd.setWindowTitle( tr( "SAVE_INFO" ) );
4110 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
4111 if ( fd.exec() == QDialog::Accepted )
4113 QString fileName = fd.selectedFile();
4114 if ( !fileName.isEmpty() ) {
4115 QFile file( fileName );
4116 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
4119 QTextStream out( &file );
4120 myCtrlInfo->saveInfo( out );
4126 \brief Show documentation on dialog.
4128 void SMESHGUI_CtrlInfoDlg::help()
4130 SMESH::ShowHelpFile( "mesh_infos.html#mesh-quality-info-anchor" );