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"//todo:remove?
26 #include "SMDS_VolumeTool.hxx"//todo:remove?
27 #include "SMESH_Actor.h"//todo:remove?
29 #include "SMESHGUI_FilterUtils.h"
30 #include "SMESHGUI_IdPreview.h"
31 #include "SMESHGUI_IdValidator.h"
32 #include "SMESHGUI_SpinBox.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
36 #include <SUIT_FileDlg.h>
37 #include <SUIT_OverrideCursor.h>
38 #include <SUIT_ResourceMgr.h>
39 #include <SUIT_Session.h>
40 #include <SVTK_ViewWindow.h>
41 #include <LightApp_SelectionMgr.h>
43 #include <SALOMEDSClient_Study.hxx>
45 #include <QApplication>
46 #include <QButtonGroup>
49 #include <QContextMenuEvent>
50 #include <QGridLayout>
51 #include <QHBoxLayout>
52 #include <QHeaderView>
53 #include <QItemDelegate>
58 #include <QPushButton>
59 #include <QRadioButton>
60 #include <QStackedWidget>
61 #include <QStandardItemModel>
63 #include <QTextBrowser>
64 #include <QTextStream>
65 #include <QToolButton>
66 #include <QTreeWidget>
67 #include <QVBoxLayout>
69 ////////////////////////////////////////////////////////////////////////////////
71 /// \brief Field widget.
73 ////////////////////////////////////////////////////////////////////////////////
75 class Field : public QLabel
78 Field( QWidget*, const QString& = QString() );
79 bool event( QEvent* );
84 \param parent Parent widget.
85 \param name Field name. Defauls to null string.
87 Field::Field( QWidget* parent, const QString& name ): QLabel( parent )
89 setFrameStyle( QLabel::StyledPanel | QLabel::Sunken );
90 setAlignment( Qt::AlignCenter );
91 setAutoFillBackground( true );
92 QPalette pal = palette();
93 QColor base = QApplication::palette().color( QPalette::Active, QPalette::Base );
94 pal.setColor( QPalette::Window, base );
96 setMinimumWidth( 60 );
97 if ( !name.isEmpty() )
98 setObjectName( name );
102 \brief Event handler. Redefined from QLabel.
104 bool Field::event( QEvent* e )
106 if ( e->type() == QEvent::DynamicPropertyChange )
108 QDynamicPropertyChangeEvent* ce = (QDynamicPropertyChangeEvent*)e;
109 if ( ce->propertyName() == "value" && property( "value" ).isValid() )
111 setText( QString::number( property( "value" ).toInt() ) );
112 setProperty( "value", QVariant() );
116 return QLabel::event( e );
119 ////////////////////////////////////////////////////////////////////////////////
120 /// \class TreeItemCreator
121 /// \brief Generic tree item creator.
123 ////////////////////////////////////////////////////////////////////////////////
125 class TreeItemCreator
129 virtual ~TreeItemCreator() {}
130 virtual QTreeWidgetItem* createItem( QTreeWidgetItem*, int ) = 0;
133 ////////////////////////////////////////////////////////////////////////////////
134 // General purpose services.
135 ////////////////////////////////////////////////////////////////////////////////
139 const int SPACING = 6;
140 const int MARGIN = 9;
159 TypeRole = Qt::UserRole + 10,
165 NodeConnectivity = 100,
170 \brief Get item's depth in the tree.
171 \param item Tree widget item.
172 \return Item's depth in the tree widget (top-level item has zero depth).
175 int itemDepth( QTreeWidgetItem* item )
177 QList<QTreeWidgetItem*> parents;
179 while ( parents.last()->parent() )
180 parents << parents.last()->parent();
181 return parents.size()-1;
185 \brief Get chunk size.
196 \return Spacer string.
202 static QChar spacer = ' ';
203 return QString( size, spacer );
208 \param length Indent size. Defaults to 1.
209 \return Indentation string.
212 QString indent( int length = 1 )
215 static QChar spacer = ' ';
216 return QString( size * length, spacer );
221 \param spacer Spacer.
222 \param length Indent size. Defaults to 1.
223 \return Indentation string.
226 QString indent( const QString& spacer, uint length = 1 )
229 while( length-- > 0 )
235 \brief Get group separator.
236 \param length Length of ruler (number of symbols). Defaults to 80.
237 \return Ruler string.
240 QString ruler( int length = 80 )
242 static QChar ruler = '-';
243 return QString( length, ruler );
247 \brief Get text value from label.
248 \param w Widget (QLabel).
249 \return Value string.
252 QString widgetValue( QWidget* w )
255 if ( qobject_cast<QLabel*>( w ) )
256 v = qobject_cast<QLabel*>( w )->text();
261 \brief Get font for given options.
262 \param font Initial font.
263 \param options Font attributes.
266 QFont fontFromOptions( const QFont& font, int options )
269 f.setBold( options & Bold );
270 f.setItalic( options & Italic );
275 \brief Set font attributes to given widget.
277 \param options Font attributes.
279 void setFontAttributes( QWidget* w, int options )
282 w->setFont( fontFromOptions( w->font(), options ) );
286 \brief Set attributes to given tree item.
287 \param item Tree widget item.
288 \param options Item attributes.
290 void setTreeItemAttributes( QTreeWidgetItem* item, int options )
292 if ( item && item->treeWidget() )
294 for ( int i = 0; i < item->treeWidget()->columnCount(); i++ )
296 if ( i == 0 || options & AllColumns )
297 item->setFont( i, fontFromOptions( item->font( 0 ), options) );
300 if ( options & Expanded )
301 item->setExpanded( true );
302 if ( options & Editable )
303 item->setFlags( item->flags() | Qt::ItemIsEditable );
308 \param parent Parent widget.
309 \param options Label options. Defaults to 0 (none).
312 QLabel* createLabel( QWidget* parent, int options = 0 )
314 QLabel* lab = new QLabel( parent );
315 setFontAttributes( lab, options );
321 \param text Label text.
322 \param parent Parent widget.
323 \param options Label options. Defaults to 0 (none).
326 QLabel* createLabel( const QString& text, QWidget* parent, int options = 0 )
328 QLabel* lab = createLabel( parent, options );
329 lab->setText( text );
334 \brief Create information field.
335 \param parent Parent widget.
336 \param name Field's object. Default to null string.
339 QLabel* createField( QWidget* parent, const QString& name = QString() )
341 return new Field( parent, name );
345 \brief Create information field.
346 \param parent Parent widget.
347 \param options Label options.
348 \param name Field's object. Default to null string.
351 QLabel* createField( QWidget* parent, int options, const QString& name = QString() )
353 QLabel* field = createField( parent, name );
354 setFontAttributes( field, options );
360 \param parent Parent widget.
361 \param orientation Ruler orientation. Defaults to horizontal.
364 QWidget* createSeparator( QWidget* parent, Qt::Orientation orientation = Qt::Horizontal )
366 QFrame* line = new QFrame( parent );
367 line->setFrameShape( orientation == Qt::Horizontal ? QFrame::HLine : QFrame::HLine );
368 line->setFrameShadow( QFrame::Sunken );
373 \brief Decorate text as bold.
374 \param text Initial text.
375 \return Decorated text.
377 QString bold( const QString& text )
379 return QString("<b>%1</b>").arg( text );
383 \brief Format connectivity data to string representation.
384 \param connectivity Connectivity map.
385 \param type Element type.
386 \return Stringifed representation of the connectivity.
388 QString formatConnectivity( SMESH::Connectivity connectivity, int type )
391 if ( connectivity.contains( type ) )
393 QList<int> elements = connectivity[ type ];
395 foreach( int id, elements )
396 str << QString::number( id );
398 return str.join( " " );
400 } // end of anonymous namespace
402 ////////////////////////////////////////////////////////////////////////////////
403 /// \class SMESHGUI_Info
404 /// \brief Base widget for all information panes.
405 ////////////////////////////////////////////////////////////////////////////////
409 \param parent Parent widget. Defaults to 0.
411 SMESHGUI_Info::SMESHGUI_Info( QWidget* parent ): QWidget( parent )
415 ////////////////////////////////////////////////////////////////////////////////
416 /// \class ExtraWidget
417 /// \brief Auxiliary widget to browse between chunks of information.
419 ////////////////////////////////////////////////////////////////////////////////
421 class ExtraWidget : public QWidget
424 ExtraWidget( QWidget*, bool = false );
425 void updateControls( int, int );
436 \param parent Parent widget.
437 \param briefSummary Show summary in brief format. Defaults to \c false.
439 ExtraWidget::ExtraWidget( QWidget* parent, bool briefSummary ): QWidget( parent ), brief( briefSummary )
441 current = new QLabel( this );
442 current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
443 prev = new QPushButton( "<<", this );
444 next = new QPushButton( ">>", this );
445 QHBoxLayout* hbl = new QHBoxLayout( this );
447 hbl->setSpacing( SPACING );
449 hbl->addWidget( current );
450 hbl->addWidget( prev );
451 hbl->addWidget( next );
455 \brief Update controls.
456 \param total Total number of items.
457 \param index Current index.
459 void ExtraWidget::updateControls( int total, int index )
461 setVisible( total > blockSize() );
462 QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
463 current->setText( format.arg( index*blockSize()+1 ).arg( qMin( index*blockSize()+blockSize(), total ) ).arg( total ) );
464 prev->setEnabled( index > 0 );
465 next->setEnabled( (index+1)*blockSize() < total );
468 ////////////////////////////////////////////////////////////////////////////////
469 /// \class DumpFileDlg
470 /// \brief Standard Save File dialog box, customized for dump info operation.
472 ////////////////////////////////////////////////////////////////////////////////
474 class DumpFileDlg : public SUIT_FileDlg
476 QMap<int, QCheckBox*> myControls;
478 DumpFileDlg( QWidget*, bool = true );
479 bool isChecked( int ) const;
480 void setChecked( int, bool );
485 \param parent Parent widget.
486 \param showControls Show additional controls. Defaults to \c true.
489 DumpFileDlg::DumpFileDlg( QWidget* parent, bool showControls ): SUIT_FileDlg( parent, false, true, true )
493 QWidget* hB = new QWidget( this );
494 myControls[SMESHGUI_MeshInfoDlg::BaseInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_BASE_INFO" ), hB );
495 myControls[SMESHGUI_MeshInfoDlg::ElemInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ELEM_INFO" ), hB );
496 myControls[SMESHGUI_MeshInfoDlg::AddInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ADD_INFO" ), hB );
497 myControls[SMESHGUI_MeshInfoDlg::CtrlInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_CTRL_INFO" ), hB );
499 QGridLayout* layout = new QGridLayout( hB );
500 layout->setMargin( 0 );
501 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::BaseInfo], 0, 0 );
502 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::ElemInfo], 0, 1 );
503 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::AddInfo], 1, 0 );
504 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::CtrlInfo], 1, 1 );
506 addWidgets( 0, hB, 0 );
511 \brief Get control's value.
512 \param option Control identifier.
513 \return Control value.
516 bool DumpFileDlg::isChecked( int option ) const
518 return myControls.contains( option ) ? myControls[option]->isChecked() : false;
522 \brief Set control's initial value.
523 \param option Control identifier.
524 \param value Control value.
527 void DumpFileDlg::setChecked( int option, bool value )
529 if ( myControls.contains( option ) )
530 myControls[option]->setChecked( value );
533 ////////////////////////////////////////////////////////////////////////////////
534 /// \class SMESHGUI_BaseInfo
535 /// \brief Show basic information on selected object.
537 /// Displays the base information about selected object: mesh, sub-mesh, group
538 /// or arbitrary ID source.
539 /// \todo Hide unnecessary widgets (e.g. for mesh group).
540 ////////////////////////////////////////////////////////////////////////////////
544 \param parent Parent widget. Defaults to 0.
546 SMESHGUI_BaseInfo::SMESHGUI_BaseInfo( QWidget* parent ): SMESHGUI_Info( parent )
548 QGridLayout* l = new QGridLayout( this );
549 l->setMargin( MARGIN );
550 l->setSpacing( SPACING );
554 addWidget( createLabel( tr( "NAME_LAB" ), this, Bold ), iName, iLabel );
555 addWidget( createField( this, "meshName" ), iName, iSingle, 4 )->setMinimumWidth( 150 );
557 addWidget( createLabel( tr( "OBJECT_LAB" ), this, Bold ), iObject, iLabel );
558 addWidget( createField( this, "meshType" ), iObject, iSingle, 4 )->setMinimumWidth( 150 );
560 addWidget( createSeparator( this ), iObjectEnd, iLabel, 5 );
564 addWidget( createLabel( tr( "NODES_LAB" ), this, Bold ), iNodes, iLabel );
565 addWidget( createField( this, "nbNodes" ), iNodes, iTotal );
567 addWidget( createSeparator( this ), iNodesEnd, iLabel, 5 );
571 addWidget( createLabel( tr( "ELEMENTS_LAB" ), this, Bold ), iElementsTitle, iLabel );
572 addWidget( createLabel( tr( "TOTAL_LAB" ), this, Italic ), iElementsTitle, iTotal );
573 addWidget( createLabel( tr( "LINEAR_LAB" ), this, Italic ), iElementsTitle, iLinear );
574 addWidget( createLabel( tr( "QUADRATIC_LAB" ), this, Italic ), iElementsTitle, iQuadratic );
575 addWidget( createLabel( tr( "BI_QUADRATIC_LAB" ), this, Italic ), iElementsTitle, iBiQuadratic );
577 addWidget( createSeparator( this ), iElementsTitleEnd, iTotal, 4 );
579 addWidget( createField( this, "totalNbElems" ), iElementsTotal, iTotal );
580 addWidget( createField( this, "totalNbLinearElems" ), iElementsTotal, iLinear );
581 addWidget( createField( this, "totalNbQuadraticElems" ), iElementsTotal, iQuadratic );
582 addWidget( createField( this, "totalNbBiQuadraticElems" ), iElementsTotal, iBiQuadratic );
584 addWidget( createSeparator( this ), iElementsTotalEnd, iTotal, 4 );
585 // - 0D elements info
586 addWidget( createLabel( tr( "0D_LAB" ), this, Bold | Italic ), i0D, iLabel );
587 addWidget( createField( this, "nb0D" ), i0D, iTotal );
589 addWidget( createSeparator( this ), i0DEnd, iTotal, 4 );
591 addWidget( createLabel( tr( "BALL_LAB" ), this, Bold | Italic ), iBalls, iLabel );
592 addWidget( createField( this, "nbBall" ), iBalls, iTotal );
594 addWidget( createSeparator( this ), iBallsEnd, iTotal, 4 );
595 // - 1D elements info
596 addWidget( createLabel( tr( "1D_LAB" ), this, Bold | Italic ), i1D, iLabel );
597 addWidget( createField( this, "nb1D" ), i1D, iTotal );
598 addWidget( createField( this, "nbLinear1D" ), i1D, iLinear );
599 addWidget( createField( this, "nbQuadratic1D" ), i1D, iQuadratic );
601 addWidget( createSeparator( this ), i1DEnd, iTotal, 4 );
602 // - 2D elements info
604 addWidget( createLabel( tr( "2D_LAB" ), this, Bold | Italic ), i2D, iLabel );
605 addWidget( createField( this, "nb2D" ), i2D, iTotal );
606 addWidget( createField( this, "nbLinear2D" ), i2D, iLinear );
607 addWidget( createField( this, "nbQuadratic2D" ), i2D, iQuadratic );
608 addWidget( createField( this, "nbBiQuadratic2D" ), i2D, iBiQuadratic );
610 addWidget( createLabel( tr( "TRIANGLES_LAB" ), this, Italic ), i2DTriangles, iLabel );
611 addWidget( createField( this, Italic, "nbTriangle" ), i2DTriangles, iTotal );
612 addWidget( createField( this, Italic, "nbLinearTriangle" ), i2DTriangles, iLinear );
613 addWidget( createField( this, Italic, "nbQuadraticTriangle" ), i2DTriangles, iQuadratic );
614 addWidget( createField( this, Italic, "nbBiQuadraticTriangle" ), i2DTriangles, iBiQuadratic );
616 addWidget( createLabel( tr( "QUADRANGLES_LAB" ), this, Italic ), i2DQuadrangles, iLabel );
617 addWidget( createField( this, Italic, "nbQuadrangle" ), i2DQuadrangles, iTotal );
618 addWidget( createField( this, Italic, "nbLinearQuadrangle" ), i2DQuadrangles, iLinear );
619 addWidget( createField( this, Italic, "nbQuadraticQuadrangle" ), i2DQuadrangles, iQuadratic );
620 addWidget( createField( this, Italic, "nbBiQuadraticQuadrangle" ), i2DQuadrangles, iBiQuadratic );
622 addWidget( createLabel( tr( "POLYGONS_LAB" ), this, Italic ), i2DPolygons, iLabel );
623 addWidget( createField( this, Italic, "nbPolygon" ), i2DPolygons, iTotal );
624 addWidget( createField( this, Italic, "nbLinearPolygon" ), i2DPolygons, iLinear );
625 addWidget( createField( this, Italic, "nbQuadraticPolygon" ), i2DPolygons, iQuadratic );
627 addWidget( createSeparator( this ), i2DEnd, iTotal, 4 );
628 // - 3D elements info
630 addWidget( createLabel( tr( "3D_LAB" ), this, Bold | Italic ), i3D, iLabel );
631 addWidget( createField( this, "nb3D" ), i3D, iTotal );
632 addWidget( createField( this, "nbLinear3D" ), i3D, iLinear );
633 addWidget( createField( this, "nbQuadratic3D" ), i3D, iQuadratic );
634 addWidget( createField( this, "nbBiQuadratic3D" ), i3D, iBiQuadratic );
636 addWidget( createLabel( tr( "TETRAHEDRONS_LAB" ), this, Italic ), i3DTetrahedrons, iLabel );
637 addWidget( createField( this, Italic, "nbTetrahedron" ), i3DTetrahedrons, iTotal );
638 addWidget( createField( this, Italic, "nbLinearTetrahedron" ), i3DTetrahedrons, iLinear );
639 addWidget( createField( this, Italic, "nbQudraticTetrahedron" ), i3DTetrahedrons, iQuadratic );
641 addWidget( createLabel( tr( "HEXAHEDONRS_LAB" ), this, Italic ), i3DHexahedrons, iLabel );
642 addWidget( createField( this, Italic, "nbHexahedron" ), i3DHexahedrons, iTotal );
643 addWidget( createField( this, Italic, "nbLinearHexahedron" ), i3DHexahedrons, iLinear );
644 addWidget( createField( this, Italic, "nbQuadraticHexahedron" ), i3DHexahedrons, iQuadratic );
645 addWidget( createField( this, Italic, "nbBiQuadraticHexahedron" ), i3DHexahedrons, iBiQuadratic );
647 addWidget( createLabel( tr( "PYRAMIDS_LAB" ), this, Italic ), i3DPyramids, iLabel );
648 addWidget( createField( this, Italic, "nbPyramid" ), i3DPyramids, iTotal );
649 addWidget( createField( this, Italic, "nbLinearPyramid" ), i3DPyramids, iLinear );
650 addWidget( createField( this, Italic, "nbQuadraticPyramid" ), i3DPyramids, iQuadratic );
652 addWidget( createLabel( tr( "PRISMS_LAB" ), this, Italic ), i3DPrisms, iLabel );
653 addWidget( createField( this, Italic, "nbPrism" ), i3DPrisms, iTotal );
654 addWidget( createField( this, Italic, "nbLinearPrism" ), i3DPrisms, iLinear );
655 addWidget( createField( this, Italic, "nbQuadraticPrism" ), i3DPrisms, iQuadratic );
656 addWidget( createField( this, Italic, "nbBiQuadraticPrism" ), i3DPrisms, iBiQuadratic );
657 // --+ hexagonal prisms
658 addWidget( createLabel( tr( "HEX_PRISMS_LAB" ), this, Italic ), i3DHexaPrisms, iLabel );
659 addWidget( createField( this, Italic, "nbHexagonalPrism" ), i3DHexaPrisms, iTotal );
661 addWidget( createLabel( tr( "POLYHEDRONS_LAB" ), this, Italic ), i3DPolyhedrons, iLabel );
662 addWidget( createField( this, Italic, "nbPolyhedron" ), i3DPolyhedrons, iTotal );
665 QPushButton* loadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
666 loadBtn->setAutoDefault( true );
667 connect( loadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
668 addWidget( loadBtn, iEnd, iSingle, 4 );
670 // additional layout set-up
671 l->setColumnStretch( iLabel, 0 );
672 l->setColumnStretch( iTotal, 5 );
673 l->setColumnStretch( iLinear, 5 );
674 l->setColumnStretch( iQuadratic, 5 );
675 l->setColumnStretch( iBiQuadratic, 5 );
676 l->setRowStretch( iElementsEnd, 5 );
678 // set initial values
685 SMESHGUI_BaseInfo::~SMESHGUI_BaseInfo()
690 \brief Show information on given object.
691 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
693 void SMESHGUI_BaseInfo::showInfo( const SMESH::SelectionProxy& proxy )
698 // then fill panel with data if object is not null
703 SMESH::MeshInfo info = proxy.meshInfo();
707 widget( iName, iSingle )->setProperty( "text", proxy.name() );
710 SMESH::SelectionProxy::Type type = proxy.type();
711 if ( type == SMESH::SelectionProxy::Mesh )
713 typeName = tr( "OBJECT_MESH" );
715 else if ( type == SMESH::SelectionProxy::Submesh )
717 typeName = tr( "OBJECT_SUBMESH" );
719 else if ( type >= SMESH::SelectionProxy::Group )
721 switch( proxy.groupElementType() )
723 case SMESH::NODE: typeName = tr( "OBJECT_GROUP_NODES" ); break;
724 case SMESH::EDGE: typeName = tr( "OBJECT_GROUP_EDGES" ); break;
725 case SMESH::FACE: typeName = tr( "OBJECT_GROUP_FACES" ); break;
726 case SMESH::VOLUME: typeName = tr( "OBJECT_GROUP_VOLUMES" ); break;
727 case SMESH::ELEM0D: typeName = tr( "OBJECT_GROUP_0DELEMS" ); break;
728 case SMESH::BALL: typeName = tr( "OBJECT_GROUP_BALLS" ); break;
729 default: typeName = tr( "OBJECT_GROUP" ); break;
732 if ( type == SMESH::SelectionProxy::GroupStd )
733 subType = tr( "OBJECT_GROUP_STANDALONE" );
734 else if ( type == SMESH::SelectionProxy::GroupGeom )
735 subType = tr( "OBJECT_GROUP_GEOM" );
736 else if ( type == SMESH::SelectionProxy::GroupFilter )
737 subType = tr( "OBJECT_GROUP_FILTER" );
738 if ( !subType.isEmpty() )
739 typeName = QString( "%1 %2" ).arg( typeName, subType );
741 widget( iObject, iSingle )->setProperty( "text", typeName );
744 uint nbNodes = info[SMDSEntity_Node];
745 widget( iNodes, iTotal )->setProperty( "value", nbNodes );
748 // - 0D elements info
749 uint nb0d = info[SMDSEntity_0D];
750 widget( i0D, iTotal )->setProperty( "value", nb0d );
752 uint nbBalls = info[SMDSEntity_Ball];
753 widget( iBalls, iTotal )->setProperty( "value", nbBalls );
754 // - 1D elements info
755 uint nb1dLin = info[SMDSEntity_Edge];
756 uint nb1dQua = info[SMDSEntity_Quad_Edge];
757 uint nb1d = nb1dLin + nb1dQua;
758 widget( i1D, iLinear )->setProperty( "value", nb1dLin );
759 widget( i1D, iQuadratic )->setProperty( "value", nb1dQua );
760 widget( i1D, iTotal )->setProperty( "value", nb1d );
761 // - 2D elements info
763 uint nbTriLin = info[SMDSEntity_Triangle];
764 uint nbTriQua = info[SMDSEntity_Quad_Triangle];
765 uint nbTriBiq = info[SMDSEntity_BiQuad_Triangle];
766 uint nbTri = nbTriLin + nbTriQua + nbTriBiq;
767 widget( i2DTriangles, iLinear )->setProperty( "value", nbTriLin );
768 widget( i2DTriangles, iQuadratic )->setProperty( "value", nbTriQua );
769 widget( i2DTriangles, iBiQuadratic )->setProperty( "value", nbTriBiq );
770 widget( i2DTriangles, iTotal )->setProperty( "value", nbTri );
772 uint nbQuadLin = info[SMDSEntity_Quadrangle];
773 uint nbQuadQua = info[SMDSEntity_Quad_Quadrangle];
774 uint nbQuadBiq = info[SMDSEntity_BiQuad_Quadrangle];
775 uint nbQuad = nbQuadLin + nbQuadQua + nbQuadBiq;
776 widget( i2DQuadrangles, iLinear )->setProperty( "value", nbQuadLin );
777 widget( i2DQuadrangles, iQuadratic )->setProperty( "value", nbQuadQua );
778 widget( i2DQuadrangles, iBiQuadratic )->setProperty( "value", nbQuadBiq );
779 widget( i2DQuadrangles, iTotal )->setProperty( "value", nbQuad );
781 uint nbPolyLin = info[SMDSEntity_Polygon];
782 uint nbPolyQua = info[SMDSEntity_Quad_Polygon];
783 uint nbPoly = nbPolyLin + nbPolyQua;
784 widget( i2DPolygons, iLinear )->setProperty( "value", nbPolyLin );
785 widget( i2DPolygons, iQuadratic )->setProperty( "value", nbPolyQua );
786 widget( i2DPolygons, iTotal )->setProperty( "value", nbPoly );
788 uint nb2dLin = nbTriLin + nbQuadLin + nbPolyLin;
789 uint nb2dQua = nbTriQua + nbQuadQua + nbPolyQua;
790 uint nb2dBiq = nbTriBiq + nbQuadBiq;
791 uint nb2d = nb2dLin + nb2dQua + nb2dBiq;
792 widget( i2D, iLinear )->setProperty( "value", nb2dLin );
793 widget( i2D, iQuadratic )->setProperty( "value", nb2dQua );
794 widget( i2D, iBiQuadratic )->setProperty( "value", nb2dBiq );
795 widget( i2D, iTotal )->setProperty( "value", nb2d );
796 // - 3D elements info
798 uint nbTetraLin = info[SMDSEntity_Tetra];
799 uint nbTetraQua = info[SMDSEntity_Quad_Tetra];
800 uint nbTetra = nbTetraLin + nbTetraQua;
801 widget( i3DTetrahedrons, iLinear )->setProperty( "value", nbTetraLin );
802 widget( i3DTetrahedrons, iQuadratic )->setProperty( "value", nbTetraQua );
803 widget( i3DTetrahedrons, iTotal )->setProperty( "value", nbTetra );
805 uint nbHexaLin = info[SMDSEntity_Hexa];
806 uint nbHexaQua = info[SMDSEntity_Quad_Hexa];
807 uint nbHexaBiq = info[SMDSEntity_TriQuad_Hexa];
808 uint nbHexa = nbHexaLin + nbHexaQua + nbHexaBiq;
809 widget( i3DHexahedrons, iLinear )->setProperty( "value", nbHexaLin );
810 widget( i3DHexahedrons, iQuadratic )->setProperty( "value", nbHexaQua );
811 widget( i3DHexahedrons, iBiQuadratic )->setProperty( "value", nbHexaBiq );
812 widget( i3DHexahedrons, iTotal )->setProperty( "value", nbHexa );
814 uint nbPyraLin = info[SMDSEntity_Pyramid];
815 uint nbPyraQua = info[SMDSEntity_Quad_Pyramid];
816 uint nbPyra = nbPyraLin + nbPyraQua;
817 widget( i3DPyramids, iLinear )->setProperty( "value", nbPyraLin );
818 widget( i3DPyramids, iQuadratic )->setProperty( "value", nbPyraQua );
819 widget( i3DPyramids, iTotal )->setProperty( "value", nbPyra );
821 uint nbPentaLin = info[SMDSEntity_Penta];
822 uint nbPentaQua = info[SMDSEntity_Quad_Penta];
823 uint nbPentaBiq = info[SMDSEntity_BiQuad_Penta];
824 uint nbPenta = nbPentaLin + nbPentaQua + nbPentaBiq;
825 widget( i3DPrisms, iLinear )->setProperty( "value", nbPentaLin );
826 widget( i3DPrisms, iQuadratic )->setProperty( "value", nbPentaQua );
827 widget( i3DPrisms, iBiQuadratic )->setProperty( "value", nbPentaBiq );
828 widget( i3DPrisms, iTotal )->setProperty( "value", nbPenta );
829 // --+ hexagonal prisms
830 uint nbHexaPri = info[SMDSEntity_Hexagonal_Prism];
831 widget( i3DHexaPrisms, iTotal )->setProperty( "value", nbHexaPri );
833 uint nbPolyhedra = info[SMDSEntity_Polyhedra];
834 widget( i3DPolyhedrons, iTotal )->setProperty( "value", nbPolyhedra );
836 uint nb3dLin = nbTetraLin + nbHexaLin + nbPyraLin + nbPentaLin + nbHexaPri + nbPolyhedra;
837 uint nb3dQua = nbTetraQua + nbHexaQua + nbPyraQua + nbPentaQua;
838 uint nb3dBiq = nbHexaBiq + nbPentaBiq;
839 uint nb3d = nb3dLin + nb3dQua + nb3dBiq;
840 widget( i3D, iLinear )->setProperty( "value", nb3dLin );
841 widget( i3D, iQuadratic )->setProperty( "value", nb3dQua );
842 widget( i3D, iBiQuadratic )->setProperty( "value", nb3dBiq );
843 widget( i3D, iTotal )->setProperty( "value", nb3d );
845 uint nbElemLin = nb1dLin + nb2dLin + nb3dLin;
846 uint nbElemQua = nb1dQua + nb2dQua + nb3dQua;
847 uint nbElemBiq = nb2dBiq + nb3dBiq;
848 uint nbElem = nb0d + nbBalls + nb1d + nb2d + nb3d;
849 widget( iElementsTotal, iLinear )->setProperty( "value", nbElemLin );
850 widget( iElementsTotal, iQuadratic )->setProperty( "value", nbElemQua );
851 widget( iElementsTotal, iBiQuadratic )->setProperty( "value", nbElemBiq );
852 widget( iElementsTotal, iTotal )->setProperty( "value", nbElem );
854 // show 'Load' button if data was not loaded yet
855 widget( iEnd, iSingle )->setVisible( !proxy.isValid() );
857 // until data is loaded from study file, type of elements in a sub-mesh or group
858 // can be undefined in some cases
859 if ( !proxy.isValid() )
861 // two cases are possible:
862 // 1. type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
863 // 2. there is no info at all (for a group on geom or on filter)
864 if ( info.count( SMDSEntity_Node, SMDSEntity_Last ) > 0 ) // believe it is a sub-mesh
866 if ( nb2dLin + nb2dQua + nb2dBiq > 0 )
868 // we know nothing about triangles, quadranges and polygons
869 for ( int i = i2DTriangles; i < i2DEnd; i++ )
871 for ( int j = iTotal; j < iNbColumns; j++ )
873 if ( widget( i, j ) )
874 widget( i, j )->setProperty( "text", "?" );
877 // we don't know if elements are linear, quadratic or bi-quadratic
878 for ( int j = iLinear; j < iNbColumns; j++ )
880 if ( widget( i2D, j ) )
881 widget( i2D, j )->setProperty( "text", "?" );
882 if ( widget( iElementsTotal, j ) )
883 widget( iElementsTotal, j )->setProperty( "text", "?" );
886 else if ( nb3dLin + nb3dQua + nb3dBiq > 0 )
888 // we know nothing about tetras, hexas, etc.
889 for ( int i = i3DTetrahedrons; i < i3DEnd; i++ )
891 for ( int j = iTotal; j < iNbColumns; j++ )
893 if ( widget( i, j ) )
894 widget( i, j )->setProperty( "text", "?" );
897 // we don't know if elements are linear, quadratic or bi-quadratic
898 for ( int j = iLinear; j < iNbColumns; j++ )
900 if ( widget( i3D, j ) )
901 widget( i3D, j )->setProperty( "text", "?" );
902 if ( widget( iElementsTotal, j ) )
903 widget( iElementsTotal, j )->setProperty( "text", "?" );
909 // we know nothing about nodes :(
910 widget( iNodes, iTotal )->setProperty( "text", "?" );
911 // we know nothing about elements :(
912 for ( int i = iElementsTotal; i < iElementsEnd; i++ )
914 for ( int j = iTotal; j < iNbColumns; j++ )
916 if ( widget( i, j ) )
917 widget( i, j )->setProperty( "text", "?" );
926 \brief Update information in panel.
928 void SMESHGUI_BaseInfo::updateInfo()
934 \brief Load mesh from a study file.
936 void SMESHGUI_BaseInfo::loadMesh()
938 SUIT_OverrideCursor wc;
947 \brief Reset panel (clear all data).
949 void SMESHGUI_BaseInfo::clear()
952 widget( iName, iSingle )->setProperty( "text", QString() );
954 widget( iObject, iSingle )->setProperty( "text", QString() );
956 widget( iNodes, iTotal )->setProperty( "value", 0 );
958 for ( int i = iElementsTotal; i < iElementsEnd; i++ )
960 for ( int j = iTotal; j < iNbColumns; j++ )
962 if ( widget( i, j ) )
963 widget( i, j )->setProperty( "value", 0 );
969 \brief Register widget in a grid.
970 \param w Widget being added.
971 \param row Row index in a grid.
972 \param column Column index in a grid.
973 \param colspan Number of columns to span in a grid. Defaults to 1.
974 \return Just added widget.
976 QWidget* SMESHGUI_BaseInfo::addWidget( QWidget* w, int row, int column, int colspan )
978 if ( !myWidgets.contains( row ) )
979 myWidgets[row] = wlist();
980 myWidgets[row][column] = w;
981 dynamic_cast<QGridLayout*>( layout() )->addWidget( w, row, column, 1, colspan );
986 \brief Get registered widget.
987 \param row Row index in a grid.
988 \param column Column index in a grid.
989 \return Widget stored in a given grid cell (0 if there's no widget).
991 QWidget* SMESHGUI_BaseInfo::widget( int row, int column ) const
993 return myWidgets.contains( row ) && myWidgets[row].contains( column ) ? myWidgets[row][column] : 0;
997 \brief Get text value from registered widget.
998 \param row Row index in a grid.
999 \param column Column index in a grid.
1000 \return Value string (empty string if no label in given cell).
1002 QString SMESHGUI_BaseInfo::value( int row, int column ) const
1004 return widgetValue( widget( row, column ) );
1008 \brief Show/hide group(s) of widgets.
1009 \param startRow Starting grid row.
1010 \param lastRow Last grid row.
1011 \param on Visibility flag.
1013 void SMESHGUI_BaseInfo::setFieldsVisible( int startRow, int lastRow, bool on )
1015 startRow = qMax( 0, startRow );
1016 lastRow = qMin( lastRow, (int)iEnd );
1017 for ( int i = startRow; i <= lastRow; i++ )
1019 wlist widgets = myWidgets[i];
1020 foreach ( QWidget* w, widgets )
1021 w->setVisible( on );
1026 \brief Write information from panel to ouput stream.
1027 \param out Text stream output.
1029 void SMESHGUI_BaseInfo::saveInfo( QTextStream& out )
1032 QString title = tr( "BASE_INFO" );
1033 out << ruler( title.size() ) << endl;
1034 out << title << endl;
1035 out << ruler( title.size() ) << endl;
1040 out << tr( "NAME_LAB" ) << spacing() << value( iName, iSingle ) << endl;
1042 out << tr( "OBJECT_LAB" ) << spacing() << value( iObject, iSingle ) << endl;
1043 // - --- (separator)
1047 out << tr( "NODES_LAB" ) << spacing() << value( iNodes, iTotal ) << endl;
1048 // - --- (separator)
1052 QString lin = tr( "LINEAR_LAB" ) + ":" + spacing();
1053 QString qua = tr( "QUADRATIC_LAB" ) + ":" + spacing();
1054 QString biq = tr( "BI_QUADRATIC_LAB" ) + ":" + spacing();
1056 out << tr( "ELEMENTS_LAB" ) << spacing() << value( iElementsTotal, iTotal ) << endl;
1057 out << indent(1) << lin << value( iElementsTotal, iLinear ) << endl;
1058 out << indent(1) << qua << value( iElementsTotal, iQuadratic ) << endl;
1059 out << indent(1) << biq << value( iElementsTotal, iBiQuadratic ) << endl;
1060 // - --- (separator)
1062 // - 0D elements info
1063 out << indent(1) << tr( "0D_LAB" ) << spacing() << value( i0D, iTotal ) << endl;
1064 // - --- (separator)
1067 out << indent(1) << tr( "BALL_LAB" ) << spacing() << value( iBalls, iTotal ) << endl;
1068 // - --- (separator)
1070 // - 1D elements info
1071 out << indent(1) << tr( "1D_LAB" ) << spacing() << value( i1D, iTotal ) << endl;
1072 out << indent(2) << lin << value( i1D, iLinear ) << endl;
1073 out << indent(2) << qua << value( i1D, iQuadratic ) << endl;
1074 // - --- (separator)
1076 // - 2D elements info
1078 out << indent(1) << tr( "2D_LAB" ) << spacing() << value( i2D, iTotal ) << endl;
1079 out << indent(2) << lin << value( i2D, iLinear ) << endl;
1080 out << indent(2) << qua << value( i2D, iQuadratic ) << endl;
1081 out << indent(2) << biq << value( i2D, iBiQuadratic ) << endl;
1082 // - --- (separator)
1085 out << indent(2) << tr( "TRIANGLES_LAB" ) << spacing() << value( i2DTriangles, iTotal ) << endl;
1086 out << indent(3) << lin << value( i2DTriangles, iLinear ) << endl;
1087 out << indent(3) << qua << value( i2DTriangles, iQuadratic ) << endl;
1088 out << indent(3) << biq << value( i2DTriangles, iBiQuadratic ) << endl;
1090 out << indent(2) << tr( "QUADRANGLES_LAB" ) << spacing() << value( i2DQuadrangles, iTotal ) << endl;
1091 out << indent(3) << lin << value( i2DQuadrangles, iLinear ) << endl;
1092 out << indent(3) << qua << value( i2DQuadrangles, iQuadratic ) << endl;
1093 out << indent(3) << biq << value( i2DQuadrangles, iBiQuadratic ) << endl;
1095 out << indent(2) << tr( "POLYGONS_LAB" ) << spacing() << value( i2DPolygons, iTotal ) << endl;
1096 out << indent(3) << lin << value( i2DPolygons, iLinear ) << endl;
1097 out << indent(3) << qua << value( i2DPolygons, iQuadratic ) << endl;
1098 // - --- (separator)
1100 // - 3D elements info
1102 out << indent(1) << tr( "3D_LAB" ) << spacing() << value( i3D, iTotal ) << endl;
1103 out << indent(2) << lin << value( i3D, iLinear ) << endl;
1104 out << indent(2) << qua << value( i3D, iQuadratic ) << endl;
1105 out << indent(2) << biq << value( i3D, iBiQuadratic ) << endl;
1106 // - --- (separator)
1109 out << indent(2) << tr( "TETRAHEDRONS_LAB" ) << spacing() << value( i3DTetrahedrons, iTotal ) << endl;
1110 out << indent(3) << lin << value( i3DTetrahedrons, iLinear ) << endl;
1111 out << indent(3) << qua << value( i3DTetrahedrons, iQuadratic ) << endl;
1113 out << indent(2) << tr( "HEXAHEDONRS_LAB" ) << spacing() << value( i3DHexahedrons, iTotal ) << endl;
1114 out << indent(3) << lin << value( i3DHexahedrons, iLinear ) << endl;
1115 out << indent(3) << qua << value( i3DHexahedrons, iQuadratic ) << endl;
1116 out << indent(3) << biq << value( i3DHexahedrons, iBiQuadratic ) << endl;
1118 out << indent(2) << tr( "PYRAMIDS_LAB" ) << spacing() << value( i3DPyramids, iTotal ) << endl;
1119 out << indent(3) << lin << value( i3DPyramids, iLinear ) << endl;
1120 out << indent(3) << qua << value( i3DPyramids, iQuadratic ) << endl;
1122 out << indent(2) << tr( "PRISMS_LAB" ) << spacing() << value( i3DPrisms, iTotal ) << endl;
1123 out << indent(3) << lin << value( i3DPrisms, iLinear ) << endl;
1124 out << indent(3) << qua << value( i3DPrisms, iQuadratic ) << endl;
1125 out << indent(3) << biq << value( i3DPrisms, iBiQuadratic ) << endl;
1126 // --+ hexagonal prisms
1127 out << indent(2) << tr( "HEX_PRISMS_LAB" ) << spacing() << value( i3DHexaPrisms, iTotal ) << endl;
1129 out << indent(2) << tr( "POLYHEDRONS_LAB" ) << spacing() << value( i3DPolyhedrons, iTotal ) << endl;
1130 // - --- (separator)
1134 ////////////////////////////////////////////////////////////////////////////////
1135 /// \class InfoWriter
1136 /// \brief Base info writer class.
1138 ////////////////////////////////////////////////////////////////////////////////
1146 InfoWriter( bool = false );
1147 void write( const QString&, bool = false );
1148 void write( const QString&, const QString&, bool = false );
1149 void write( const QString&, int, bool = false );
1150 void write( const QString&, double, bool = false );
1151 void write( const QString&, const SMESH::XYZ&, bool = false );
1152 virtual void indent() {}
1153 virtual void unindent() {}
1154 virtual void separator() {}
1156 virtual void put( const QString&, const QString&, bool = false ) = 0;
1159 InfoWriter::InfoWriter( bool r ): myRecursive(r)
1161 myPrecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1164 void InfoWriter::write( const QString& key, bool emphasize )
1166 put( key, QString(), emphasize );
1169 void InfoWriter::write( const QString& key, const QString& value, bool emphasize )
1171 put( key, value, emphasize );
1174 void InfoWriter::write( const QString& key, int value, bool emphasize )
1176 put( key, QString::number( value ), emphasize );
1179 void InfoWriter::write( const QString& key, double value, bool emphasize )
1181 put( key, QString::number( value, myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) ), emphasize );
1184 void InfoWriter::write( const QString& key, const SMESH::XYZ& value, bool emphasize )
1188 write( key, emphasize );
1190 write( "X", value.x() );
1191 write( "Y", value.y() );
1192 write( "Z", value.z() );
1198 vl << QString::number( value.x(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1199 vl << QString::number( value.y(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1200 vl << QString::number( value.z(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1201 put( key, vl.join( ", " ), emphasize );
1205 ////////////////////////////////////////////////////////////////////////////////
1206 /// \class SimpleWriter
1207 /// \brief Base text writer.
1209 ////////////////////////////////////////////////////////////////////////////////
1211 class SimpleWriter: public InfoWriter
1221 void put( const QString&, const QString&, bool );
1222 virtual QString spacer() const;
1223 virtual QString decorate( const QString& ) const;
1224 virtual void dumpLine( const QString& ) = 0;
1227 SimpleWriter::SimpleWriter(): InfoWriter(false), myIndent(0)
1231 void SimpleWriter::indent()
1236 void SimpleWriter::unindent()
1238 myIndent = qMax( myIndent-1, 0 );
1241 void SimpleWriter::separator()
1246 QString SimpleWriter::spacer() const
1251 QString SimpleWriter::decorate( const QString& s ) const
1256 void SimpleWriter::put( const QString& key, const QString& value, bool emphasize )
1259 line += ::indent( spacer(), myIndent*4 );
1260 line += decorate( key );
1261 if ( !value.isEmpty() )
1264 line += emphasize ? decorate( value ) : value;
1269 ////////////////////////////////////////////////////////////////////////////////
1270 /// \class StreamWriter
1271 /// \brief Writer for QTextStream.
1273 ////////////////////////////////////////////////////////////////////////////////
1275 class StreamWriter: public SimpleWriter
1279 StreamWriter( QTextStream& );
1281 void dumpLine( const QString& );
1284 StreamWriter::StreamWriter( QTextStream& out ): SimpleWriter(), myOut(out)
1288 void StreamWriter::dumpLine( const QString& line )
1294 ////////////////////////////////////////////////////////////////////////////////
1295 /// \class TextWriter
1296 /// \brief Writer for QTextBrowser.
1298 ////////////////////////////////////////////////////////////////////////////////
1300 class TextWriter: public SimpleWriter
1302 QTextBrowser* myInfo;
1304 TextWriter( QTextBrowser* );
1306 QString spacer() const;
1307 QString decorate( const QString& ) const;
1308 void dumpLine( const QString& );
1311 TextWriter::TextWriter( QTextBrowser* w ): SimpleWriter(), myInfo(w)
1315 QString TextWriter::spacer() const
1320 QString TextWriter::decorate( const QString& s ) const
1325 void TextWriter::dumpLine( const QString& line )
1327 myInfo->append( line );
1330 ////////////////////////////////////////////////////////////////////////////////
1331 /// \class TreeWriter
1332 /// \brief Writer for QTreeWidget.
1334 ////////////////////////////////////////////////////////////////////////////////
1336 class TreeWriter: public InfoWriter
1338 QTreeWidget* myInfo;
1339 QTreeWidgetItem* myCurrentItem;
1340 TreeItemCreator* myCreator;
1342 TreeWriter( QTreeWidget*, TreeItemCreator* );
1347 void put( const QString&, const QString&, bool = false );
1350 TreeWriter::TreeWriter( QTreeWidget* w, TreeItemCreator* c ):
1351 InfoWriter(true), myInfo(w), myCurrentItem(0), myCreator(c)
1355 TreeWriter::~TreeWriter()
1360 void TreeWriter::put( const QString& key, const QString& value, bool emphasize )
1362 std::string sss = myCurrentItem ? myCurrentItem->text(0).toStdString() : "";
1364 if ( emphasize ) options |= AllColumns;
1365 QTreeWidgetItem* item = myCreator->createItem( myCurrentItem, options );
1366 item->setText( 0, key );
1367 if ( !value.isEmpty() )
1368 item->setText( 1, value );
1371 void TreeWriter::indent()
1373 QTreeWidgetItem* item = myCurrentItem ? myCurrentItem : myInfo->invisibleRootItem();
1374 if ( item->childCount() > 0 )
1375 myCurrentItem = item->child( item->childCount()-1 );
1378 void TreeWriter::unindent()
1380 if ( myCurrentItem )
1381 myCurrentItem = myCurrentItem->parent();
1384 ////////////////////////////////////////////////////////////////////////////////
1385 /// \class SMESHGUI_ElemInfo
1386 /// \brief Base class for the mesh element information widget.
1388 /// Displays the detail information about given mesh node(s) or element(s).
1389 /// Default class does not provide working implementation but onle general
1390 /// functionalities; main work is done in sub-classes.
1391 ////////////////////////////////////////////////////////////////////////////////
1395 \param parent Parent widget. Defaults to 0.
1397 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent ): SMESHGUI_Info( parent ), myWhat( ShowNone )
1399 myFrame = new QWidget( this );
1400 myExtra = new ExtraWidget( this );
1402 QVBoxLayout* vbl = new QVBoxLayout( this );
1403 vbl->setMargin( 0 );
1404 vbl->setSpacing( SPACING );
1405 vbl->addWidget( myFrame );
1406 vbl->addWidget( myExtra );
1408 connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
1409 connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
1417 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
1422 \brief Show information on given node / element.
1423 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1424 \param id Mesh node / element ID.
1425 \param isElement If \c true, show element info; otherwise show node info.
1427 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, uint id, bool isElement )
1431 showInfo( proxy, ids, isElement );
1435 \brief Show information on given nodes / elements.
1436 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1437 \param ids Mesh nodes / elements IDs.
1438 \param isElement If \c true, show element info; otherwise show node info.
1440 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, QSet<uint> ids, bool isElement )
1448 QList<uint> newIds = ids.toList();
1450 int what = isElement ? ShowElements : ShowNodes;
1452 if ( myProxy == proxy && myIDs == newIds && myWhat == what )
1456 myProxy.refresh(); // try to re-initialize actor
1465 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1469 \brief Show information on given group.
1470 \param proxy Object to compute information on (group).
1472 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy )
1474 if ( !proxy || proxy.groupElementType() == SMESH::ALL ) // null proxy or not a group
1480 showInfo( proxy, proxy.ids(), proxy.groupElementType() != SMESH::NODE );
1484 \brief Reset panel (clear all data).
1486 void SMESHGUI_ElemInfo::clear()
1495 \brief Get central area widget.
1496 \return Central widget.
1498 QWidget* SMESHGUI_ElemInfo::centralWidget() const
1504 \brief Get current mesh proxy object information is shown on.
1505 \return Current proxy.
1507 SMESH::SelectionProxy SMESHGUI_ElemInfo::proxy() const
1513 \brief Get current info mode.
1514 \return Current panel mode.
1516 int SMESHGUI_ElemInfo::what() const
1522 \brief Get title for given element type.
1523 \param type Mesh element type.
1524 \param multiple Use plural form. Defaults to \c false.
1525 \return Element type's title.
1527 QString SMESHGUI_ElemInfo::type2str( int type, bool multiple )
1533 title = multiple ? tr( "EDGES" ) : tr( "EDGE" ) ; break;
1535 title = multiple ? tr( "FACES" ) : tr( "FACE" ); break;
1536 case SMDSAbs_Volume:
1537 title = multiple ? tr( "VOLUMES" ) : tr( "VOLUME" ); break;
1538 case SMDSAbs_0DElement:
1539 title = multiple ? tr( "0D_ELEMENTS" ) : tr( "0D_ELEMENT" ); break;
1541 title = multiple ? tr( "BALL_ELEMENTS" ) : tr( "BALL" ); break;
1549 \brief Get title for given shape type.
1550 \param type Shape type.
1551 \return Shape type's title.
1553 QString SMESHGUI_ElemInfo::stype2str( int type )
1559 title = tr( "GEOM_VERTEX" ); break;
1561 title = tr( "GEOM_EDGE" ); break;
1563 title = tr( "GEOM_FACE" ); break;
1566 title = tr( "GEOM_SOLID" ); break;
1573 \brief Get title for given element type.
1574 \param type Mesh element type.
1575 \return Element type's title.
1577 QString SMESHGUI_ElemInfo::etype2str( int type )
1582 case SMESH::Entity_0D:
1583 title = tr( "SMESH_ELEM0D" ); break;
1584 case SMESH::Entity_Edge:
1585 title = tr( "SMESH_EDGE" ); break;
1586 case SMESH::Entity_Quad_Edge:
1587 title = tr( "SMESH_QUADRATIC_EDGE" ); break;
1588 case SMESH::Entity_Triangle:
1589 title = tr( "SMESH_TRIANGLE" ); break;
1590 case SMESH::Entity_Quad_Triangle:
1591 title = tr( "SMESH_QUADRATIC_TRIANGLE" ); break;
1592 case SMESH::Entity_BiQuad_Triangle:
1593 title = tr( "SMESH_BIQUADRATIC_TRIANGLE" ); break;
1594 case SMESH::Entity_Quadrangle:
1595 title = tr( "SMESH_QUADRANGLE" ); break;
1596 case SMESH::Entity_Quad_Quadrangle:
1597 title = tr( "SMESH_QUADRATIC_QUADRANGLE" ); break;
1598 case SMESH::Entity_BiQuad_Quadrangle:
1599 title = tr( "SMESH_BIQUADRATIC_QUADRANGLE" ); break;
1600 case SMESH::Entity_Polygon:
1601 title = tr( "SMESH_POLYGON" ); break;
1602 case SMESH::Entity_Quad_Polygon:
1603 title = tr( "SMESH_QUADRATIC_POLYGON" ); break;
1604 case SMESH::Entity_Tetra:
1605 title = tr( "SMESH_TETRAHEDRON" ); break;
1606 case SMESH::Entity_Quad_Tetra:
1607 title = tr( "SMESH_QUADRATIC_TETRAHEDRON" ); break;
1608 case SMESH::Entity_Pyramid:
1609 title = tr( "SMESH_PYRAMID" ); break;
1610 case SMESH::Entity_Quad_Pyramid:
1611 title = tr( "SMESH_QUADRATIC_PYRAMID" ); break;
1612 case SMESH::Entity_Hexa:
1613 title = tr( "SMESH_HEXAHEDRON" ); break;
1614 case SMESH::Entity_Quad_Hexa:
1615 title = tr( "SMESH_QUADRATIC_HEXAHEDRON" ); break;
1616 case SMESH::Entity_TriQuad_Hexa:
1617 title = tr( "SMESH_TRIQUADRATIC_HEXAHEDRON" ); break;
1618 case SMESH::Entity_Penta:
1619 title = tr( "SMESH_PENTA" ); break;
1620 case SMESH::Entity_Quad_Penta:
1621 title = tr( "SMESH_QUADRATIC_PENTAHEDRON" ); break;
1622 case SMESH::Entity_BiQuad_Penta:
1623 title = tr( "SMESH_BIQUADRATIC_PENTAHEDRON" ); break;
1624 case SMESH::Entity_Hexagonal_Prism:
1625 title = tr( "SMESH_HEX_PRISM" ); break;
1626 case SMESH::Entity_Polyhedra:
1627 title = tr( "SMESH_POLYEDRON" ); break;
1628 case SMESH::Entity_Quad_Polyhedra:
1629 title = tr( "SMESH_QUADRATIC_POLYEDRON" ); break;
1630 case SMESH::Entity_Ball:
1631 title = tr( "SMESH_BALL" ); break;
1639 \brief Get title for given quality control.
1640 \param type Mesh control type.
1641 \return Quality control's title.
1643 QString SMESHGUI_ElemInfo::ctrl2str( int control )
1648 case SMESH::FT_AspectRatio:
1649 title = tr( "ASPECTRATIO_ELEMENTS" ); break;
1650 case SMESH::FT_AspectRatio3D:
1651 title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
1652 case SMESH::FT_Warping:
1653 title = tr( "WARP_ELEMENTS" ); break;
1654 case SMESH::FT_MinimumAngle:
1655 title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
1656 case SMESH::FT_Taper:
1657 title = tr( "TAPER_ELEMENTS" ); break;
1658 case SMESH::FT_Skew:
1659 title = tr( "SKEW_ELEMENTS" ); break;
1660 case SMESH::FT_Area:
1661 title = tr( "AREA_ELEMENTS" ); break;
1662 case SMESH::FT_Volume3D:
1663 title = tr( "VOLUME_3D_ELEMENTS" ); break;
1664 case SMESH::FT_MaxElementLength2D:
1665 title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
1666 case SMESH::FT_MaxElementLength3D:
1667 title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
1668 case SMESH::FT_Length:
1669 title = tr( "LENGTH_EDGES" ); break;
1670 case SMESH::FT_Length2D:
1671 title = tr( "MIN_ELEM_EDGE" ); break;
1672 case SMESH::FT_BallDiameter:
1673 title = tr( "BALL_DIAMETER" ); break;
1681 \brief Write information on given mesh nodes / elements.
1682 \param writer Information writer.
1683 \param ids Nodes / elements IDs.
1685 void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
1690 bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1691 int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ?
1692 SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
1695 SMESH::Connectivity connectivity;
1696 SMESH::Position position;
1699 foreach ( uint id, ids )
1701 writer->separator();
1703 if ( what() == ShowNodes )
1706 // - check that node exists
1707 if ( !proxy().hasNode( id ) )
1710 writer->write( tr( "NODE" ), (int)id, true );
1713 ok = proxy().nodeCoordinates( id, xyz );
1716 writer->write( tr( "COORDINATES" ), xyz );
1719 ok = proxy().nodeConnectivity( id, connectivity );
1722 if ( !connectivity.isEmpty() )
1724 writer->write( tr( "CONNECTIVITY" ) );
1726 for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
1728 QString formatted = formatConnectivity( connectivity, i );
1729 if ( !formatted.isEmpty() )
1730 writer->write( type2str( i, true ), formatted ); //todo: TypeRole: NodeConnectivity
1736 writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
1740 ok = proxy().nodePosition( id, position );
1741 if ( ok && position.isValid() )
1743 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1745 if ( position.hasU() )
1746 writer->write( tr("U_POSITION"), position.u() );
1747 if ( position.hasV() )
1748 writer->write( tr("V_POSITION"), position.v() );
1751 // - groups node belongs to
1752 QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
1753 bool topCreated = false;
1754 foreach( SMESH::SelectionProxy group, groups )
1756 if ( group && !group.name().isEmpty() )
1760 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1764 writer->write( group.name().trimmed() ); // trim name
1768 int type = group.type();
1769 if ( type == SMESH::SelectionProxy::GroupStd )
1771 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1773 else if ( type == SMESH::SelectionProxy::GroupGeom )
1775 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1776 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1778 else if ( type == SMESH::SelectionProxy::GroupFilter )
1780 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1782 int size = group.size();
1784 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1785 QColor color = group.color();
1786 if ( color.isValid() )
1787 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1796 else if ( what() == ShowElements )
1798 // show element info
1799 // - check that element exists
1800 if ( !proxy().hasElement( id ) )
1803 int type = proxy().elementType( id );
1804 if ( type == SMESH::ALL )
1806 writer->write( type2str( type ), (int)id, true );
1809 type = proxy().elementEntityType( id );
1810 writer->write( tr( "TYPE" ), etype2str( type ) );
1812 ok = proxy().elementConnectivity( id, connectivity );
1815 if ( !connectivity.isEmpty() )
1817 QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
1818 if ( !formatted.isEmpty() )
1819 writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
1823 ok = proxy().elementPosition( id, position );
1824 if ( ok && position.isValid() )
1826 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1829 ok = proxy().elementGravityCenter( id, xyz );
1832 writer->write( tr( "GRAVITY_CENTER" ), xyz );
1835 ok = proxy().elementNormal( id, xyz );
1838 writer->write( tr( "NORMAL_VECTOR" ), xyz );
1841 bool topCreated = false;
1842 for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
1844 QString ctrlTitle = ctrl2str( i );
1845 if ( ctrlTitle.isEmpty() )
1849 writer->write( tr( "CONTROLS" ) );
1854 if ( proxy().elementControl( id, i, cprecision, value ) )
1855 writer->write( ctrlTitle, value );
1859 // - groups element belongs to
1860 QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
1862 foreach( SMESH::SelectionProxy group, groups )
1864 if ( group && !group.name().isEmpty() )
1868 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1872 writer->write( group.name().trimmed() ); // trim name
1876 int type = group.type();
1877 if ( type == SMESH::SelectionProxy::GroupStd )
1879 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1881 else if ( type == SMESH::SelectionProxy::GroupGeom )
1883 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1884 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1886 else if ( type == SMESH::SelectionProxy::GroupFilter )
1888 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1890 int size = group.size();
1892 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1893 QColor color = group.color();
1894 if ( color.isValid() )
1895 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1908 \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
1909 \brief Show information on given mesh nodes / elements.
1911 This function has to be redefined in sub-classes.
1913 \param ids Nodes / elements IDs.
1917 \brief Internal clean-up (reset panel).
1919 Default implementation does nothing; the method has to be redefined
1920 in sub-classes to perform internal clean-up.
1922 void SMESHGUI_ElemInfo::clearInternal()
1927 \brief Show previous chunk of information.
1929 void SMESHGUI_ElemInfo::showPrevious()
1931 myIndex = qMax( 0, myIndex-1 );
1933 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1937 \brief Show next chunk of information.
1939 void SMESHGUI_ElemInfo::showNext()
1941 myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
1943 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1947 \brief Update control widget state.
1949 void SMESHGUI_ElemInfo::updateControls()
1951 myExtra->updateControls( myIDs.count(), myIndex );
1955 \brief Write information from panel to ouput stream.
1956 \param out Text stream output.
1958 void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
1961 QString title = tr( "ELEM_INFO" );
1962 out << ruler( title.size() ) << endl;
1963 out << title << endl;
1964 out << ruler( title.size() ) << endl;
1968 StreamWriter writer( out );
1969 writeInfo( &writer, myIDs );
1973 ////////////////////////////////////////////////////////////////////////////////
1974 /// \class SMESHGUI_SimpleElemInfo
1975 /// \brief Show mesh element information in the simple text area.
1976 ////////////////////////////////////////////////////////////////////////////////
1980 \param parent Parent widget. Defaults to 0.
1982 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
1983 : SMESHGUI_ElemInfo( parent )
1985 myInfo = new QTextBrowser( centralWidget() );
1986 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
1988 l->addWidget( myInfo );
1992 \brief Show mesh element information.
1993 \param ids Nodes / elements IDs.
1995 void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
1998 TextWriter writer( myInfo );
1999 writeInfo( &writer, ids );
2003 \brief Internal clean-up (reset widget)
2005 void SMESHGUI_SimpleElemInfo::clearInternal()
2010 ////////////////////////////////////////////////////////////////////////////////
2011 /// \class SMESHGUI_TreeElemInfo::ItemDelegate
2012 /// \brief Item delegate for tree mesh info widget.
2014 ////////////////////////////////////////////////////////////////////////////////
2016 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
2019 ItemDelegate( QObject* );
2020 QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
2027 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
2032 \brief Redefined from QItemDelegate.
2035 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
2037 QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
2038 if ( qobject_cast<QLineEdit*>( w ) )
2039 qobject_cast<QLineEdit*>( w )->setReadOnly( true );
2043 ////////////////////////////////////////////////////////////////////////////////
2044 /// \class SMESHGUI_TreeElemInfo::ItemCreator
2045 /// \brief Item creator for tree mesh info widget.
2047 ////////////////////////////////////////////////////////////////////////////////
2049 class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
2051 SMESHGUI_TreeElemInfo* myView;
2053 ItemCreator( SMESHGUI_TreeElemInfo* );
2054 QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
2059 \param view Parent view.
2062 SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
2067 \brief Create new tree item.
2068 \param parent Parent tree item.
2069 \param options Item options.
2070 \return New tree widget item.
2073 QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
2075 return myView->createItem( parent, options );
2078 ////////////////////////////////////////////////////////////////////////////////
2079 /// \class SMESHGUI_TreeElemInfo
2080 /// \brief Show mesh element information as the tree.
2081 ////////////////////////////////////////////////////////////////////////////////
2085 \param parent Parent widget. Defaults to 0.
2087 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
2088 : SMESHGUI_ElemInfo( parent )
2090 myInfo = new QTreeWidget( centralWidget() );
2091 myInfo->setColumnCount( 2 );
2092 myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
2093 myInfo->header()->setStretchLastSection( true );
2094 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2095 myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2097 myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2099 myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
2100 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2102 l->addWidget( myInfo );
2103 connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
2107 \brief Show mesh element information.
2108 \param ids Nodes / elements IDs.
2110 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
2113 TreeWriter writer( myInfo, new ItemCreator( this ) );
2114 writeInfo( &writer, ids );
2118 \brief Show node information
2119 \param node mesh node for showing
2120 \param index index of current node
2121 \param nbNodes number of unique nodes in element
2122 \param parentItem parent item of tree
2124 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* node, int index,
2125 int nbNodes, QTreeWidgetItem* parentItem )
2127 // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
2128 // // node number and ID
2129 // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
2130 // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
2131 // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
2132 // nodeItem->setData( 1, TypeRole, ElemConnectivity );
2133 // nodeItem->setData( 1, IdRole, node->GetID() );
2134 // nodeItem->setExpanded( false );
2135 // // node coordinates
2136 // QTreeWidgetItem* coordItem = createItem( nodeItem );
2137 // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
2138 // QTreeWidgetItem* xItem = createItem( coordItem );
2139 // xItem->setText( 0, "X" );
2140 // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2141 // QTreeWidgetItem* yItem = createItem( coordItem );
2142 // yItem->setText( 0, "Y" );
2143 // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2144 // QTreeWidgetItem* zItem = createItem( coordItem );
2145 // zItem->setText( 0, "Z" );
2146 // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2147 // // node connectivity
2148 // QTreeWidgetItem* nconItem = createItem( nodeItem );
2149 // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
2150 // Connectivity connectivity = nodeConnectivity( node );
2151 // if ( !connectivity.isEmpty() ) {
2152 // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
2153 // if ( !con.isEmpty() ) {
2154 // QTreeWidgetItem* i = createItem( nconItem );
2155 // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
2156 // i->setText( 1, con );
2158 // con = formatConnectivity( connectivity, SMDSAbs_Edge );
2159 // if ( !con.isEmpty() ) {
2160 // QTreeWidgetItem* i = createItem( nconItem );
2161 // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
2162 // i->setText( 1, con );
2163 // i->setData( 1, TypeRole, NodeConnectivity );
2165 // con = formatConnectivity( connectivity, SMDSAbs_Ball );
2166 // if ( !con.isEmpty() ) {
2167 // QTreeWidgetItem* i = createItem( nconItem );
2168 // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
2169 // i->setText( 1, con );
2170 // i->setData( 1, TypeRole, NodeConnectivity );
2172 // con = formatConnectivity( connectivity, SMDSAbs_Face );
2173 // if ( !con.isEmpty() ) {
2174 // QTreeWidgetItem* i = createItem( nconItem );
2175 // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
2176 // i->setText( 1, con );
2177 // i->setData( 1, TypeRole, NodeConnectivity );
2179 // con = formatConnectivity( connectivity, SMDSAbs_Volume );
2180 // if ( !con.isEmpty() ) {
2181 // QTreeWidgetItem* i = createItem( nconItem );
2182 // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
2183 // i->setText( 1, con );
2184 // i->setData( 1, TypeRole, NodeConnectivity );
2189 \brief Internal clean-up (reset widget)
2191 void SMESHGUI_TreeElemInfo::clearInternal()
2198 \brief Create new item and add it to the tree.
2199 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2200 \param options Item flags. Defaults to 0 (none).
2201 \return New tree widget item.
2203 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
2205 QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
2206 setTreeItemAttributes( item, options | Expanded | Editable );
2210 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2212 QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2213 if ( widgets.isEmpty() ) return;
2214 QTreeWidgetItem* aTreeItem = widgets.first();
2215 int type = aTreeItem->data( 1, TypeRole ).toInt();
2216 int id = aTreeItem->data( 1, IdRole ).toInt();
2218 QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
2219 if ( type == ElemConnectivity && id > 0 && menu.exec( e->globalPos() ) == a )
2220 emit( itemInfo( id ));
2221 else if ( type == NodeConnectivity && menu.exec( e->globalPos() ) == a )
2222 emit( itemInfo( aTreeItem->text( 1 )) );
2225 void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
2228 int type = theItem->data( 1, TypeRole ).toInt();
2229 int id = theItem->data( 1, IdRole ).toInt();
2230 if ( type == ElemConnectivity && id > 0 )
2231 emit( itemInfo( id ));
2232 else if ( type == NodeConnectivity )
2233 emit( itemInfo( theItem->text( 1 )) );
2237 ////////////////////////////////////////////////////////////////////////////////
2238 /// \class InfoComputor
2239 /// \brief Mesh information computor.
2242 /// The class is created for different computation operations. Currently it is
2243 /// used to compute size and number of underlying nodes for given group.
2244 ////////////////////////////////////////////////////////////////////////////////
2248 \param parent Parent object.
2249 \param proxy Object to compute information on (group).
2250 \param item Tree widget item, referenced by this computer.
2251 \param operation Value to compute.
2254 InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
2255 : QObject( parent ), myProxy( proxy ), myOperation( operation )
2260 \brief Compute requested information.
2263 void InfoComputor::compute()
2267 SUIT_OverrideCursor wc;
2268 switch ( myOperation )
2271 myProxy.size( true ); // force size computation
2275 myProxy.nbNodes( true ); // force size computation
2284 ////////////////////////////////////////////////////////////////////////////////
2285 /// \class SMESHGUI_AddInfo
2286 /// \brief Show additional information on selected object.
2288 /// Displays an additional information about selected object: mesh, sub-mesh
2291 /// \todo Rewrite saveInfo() method to print all data, not currently shown only.
2292 ////////////////////////////////////////////////////////////////////////////////
2296 \param parent Parent widget. Defaults to 0.
2298 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
2300 QVBoxLayout* l = new QVBoxLayout( this );
2302 l->setSpacing( SPACING );
2304 myTree = new QTreeWidget( this );
2306 myTree->setColumnCount( 2 );
2307 myTree->header()->setStretchLastSection( true );
2308 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2309 myTree->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2311 myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2313 myTree->header()->hide();
2315 l->addWidget( myTree );
2321 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2326 \brief Show information on given object.
2327 \param proxy Object to show information on (mesh, sub-mesh, group).
2329 void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
2332 setProperty( "group_index", 0 );
2333 setProperty( "submesh_index", 0 );
2334 myComputors.clear();
2337 // then fill panel with data if object is not null
2343 QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
2344 nameItem->setText( 0, tr( "NAME" ) );
2345 nameItem->setText( 1, proxy.name() );
2348 if ( proxy.type() == SMESH::SelectionProxy::Mesh )
2349 meshInfo( proxy, nameItem );
2350 else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
2351 subMeshInfo( proxy, nameItem );
2352 else if ( proxy.type() >= SMESH::SelectionProxy::Group )
2353 groupInfo( proxy, nameItem );
2358 \brief Update information in panel.
2360 void SMESHGUI_AddInfo::updateInfo()
2362 showInfo( myProxy );
2366 \brief Reset panel (clear all data).
2368 void SMESHGUI_AddInfo::clear()
2374 \brief Create new item and add it to the tree.
2375 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2376 \param options Item flags. Defaults to 0 (none).
2377 \return New tree widget item.
2379 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
2381 QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
2382 new QTreeWidgetItem( myTree->invisibleRootItem() );
2383 setTreeItemAttributes( item, options | Expanded );
2388 \brief Show information on mesh.
2389 \param proxy Proxy object (mesh).
2390 \param parent Parent tree item.
2392 void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2397 QString shapeName = proxy.shapeName();
2398 SMESH::MedInfo inf = proxy.medFileInfo();
2401 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2402 typeItem->setText( 0, tr( "TYPE" ) );
2403 if ( !shapeName.isEmpty() )
2405 typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2407 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2408 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2409 gobjItem->setText( 1, shapeName );
2411 else if ( inf.isValid() )
2413 typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2414 // med file information
2415 QTreeWidgetItem* fileItem = createItem( parent, Bold );
2416 fileItem->setText( 0, tr( "FILE_NAME" ) );
2417 fileItem->setText( 1, inf.fileName() );
2418 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2419 sizeItem->setText( 0, tr( "FILE_SIZE" ) );
2420 sizeItem->setText( 1, QString::number( inf.size() ) );
2421 QTreeWidgetItem* versionItem = createItem( parent, Bold );
2422 versionItem->setText( 0, tr( "FILE_VERSION" ) );
2423 versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
2427 typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2431 myGroups = proxy.groups();
2435 mySubMeshes = proxy.submeshes();
2440 \brief Show information on sub-mesh.
2441 \param proxy Proxy object (sub-mesh).
2442 \param parent Parent tree item.
2444 void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2449 bool isShort = parent->parent() != 0;
2454 SMESH::SelectionProxy meshProxy = proxy.mesh();
2457 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2458 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2459 nameItem->setText( 1, meshProxy.name() );
2464 QString shapeName = proxy.shapeName();
2465 if ( !shapeName.isEmpty() )
2467 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2468 gobjItem->setText( 1, shapeName );
2473 \brief Show information on group.
2474 \param proxy Proxy object (group).
2475 \param parent Parent tree item.
2477 void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2482 bool isShort = parent->parent() != 0;
2487 SMESH::SelectionProxy meshProxy = proxy.mesh();
2490 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2491 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2492 nameItem->setText( 1, meshProxy.name() );
2497 SMESH::SelectionProxy::Type type = proxy.type();
2498 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2499 typeItem->setText( 0, tr( "TYPE" ) );
2500 if ( type == SMESH::SelectionProxy::GroupStd )
2502 typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2504 else if ( type == SMESH::SelectionProxy::GroupGeom )
2506 typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2508 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2509 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2510 gobjItem->setText( 1, proxy.shapeName() );
2512 else if ( type == SMESH::SelectionProxy::GroupFilter )
2514 typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2518 int etype = proxy.groupElementType();
2521 QString typeName = tr( "UNKNOWN" );
2525 typeName = tr( "NODE" );
2528 typeName = tr( "EDGE" );
2531 typeName = tr( "FACE" );
2534 typeName = tr( "VOLUME" );
2537 typeName = tr( "0DELEM" );
2540 typeName = tr( "BALL" );
2545 QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2546 etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2547 etypeItem->setText( 1, typeName );
2551 // note: size is not computed for group on filter for performance reasons, see IPAL52831
2552 bool meshLoaded = proxy.isMeshLoaded();
2553 int size = proxy.size();
2555 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2556 sizeItem->setText( 0, tr( "SIZE" ) );
2559 sizeItem->setText( 1, QString::number( size ) );
2563 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2564 myTree->setItemWidget( sizeItem, 1, btn );
2565 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
2566 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2567 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2568 myComputors.append( comp );
2572 QTreeWidgetItem* colorItem = createItem( parent, Bold );
2573 colorItem->setText( 0, tr( "COLOR" ) );
2574 colorItem->setBackground( 1, proxy.color() );
2576 // nb of underlying nodes
2577 if ( etype != SMESH::NODE )
2579 QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2580 nodesItem->setText( 0, tr( "NB_NODES" ) );
2582 int nbNodes = proxy.nbNodes();
2585 nodesItem->setText( 1, QString::number( nbNodes ) );
2589 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2590 myTree->setItemWidget( nodesItem, 1, btn );
2591 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
2592 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2593 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2594 myComputors.append( comp );
2600 \brief Update information on child groups.
2602 void SMESHGUI_AddInfo::showGroups()
2604 // remove all computors
2605 myComputors.clear();
2607 // tree root should be the first top level item
2608 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2612 int idx = property( "group_index" ).toInt();
2614 // find sub-meshes top-level container item
2615 QTreeWidgetItem* itemGroups = 0;
2616 for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
2618 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
2620 itemGroups = parent->child( i );
2622 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
2624 extra->updateControls( myGroups.count(), idx );
2625 // clear: remove all group items
2626 while ( itemGroups->childCount() )
2627 delete itemGroups->child( 0 );
2631 QMap<int, QTreeWidgetItem*> grpItems;
2632 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
2634 SMESH::SelectionProxy grp = myGroups[i];
2638 int grpType = grp.groupElementType();
2640 // create top-level groups container item if it does not exist
2643 itemGroups = createItem( parent, Bold | AllColumns );
2644 itemGroups->setText( 0, tr( "GROUPS" ) );
2645 itemGroups->setData( 0, Qt::UserRole, GroupsId );
2647 // if necessary, create extra widget to show information by chunks
2648 if ( myGroups.count() > blockSize() )
2650 ExtraWidget* extra = new ExtraWidget( this, true );
2651 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2652 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2653 myTree->setItemWidget( itemGroups, 1, extra );
2654 extra->updateControls( myGroups.count(), idx );
2658 // create container item corresponding to particular element type
2659 if ( !grpItems.contains( grpType ) )
2661 grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
2662 grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2663 itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
2667 QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
2668 nameItem->setText( 0, grp.name().trimmed() ); // trim name
2671 groupInfo( grp, nameItem );
2676 \brief Update information on child sub-meshes.
2678 void SMESHGUI_AddInfo::showSubMeshes()
2680 // tree root should be the first top level item
2681 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2685 int idx = property( "submesh_index" ).toInt();
2687 // find sub-meshes top-level container item
2688 QTreeWidgetItem* itemSubMeshes = 0;
2689 for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
2691 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
2693 itemSubMeshes = parent->child( i );
2695 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
2697 extra->updateControls( mySubMeshes.count(), idx );
2698 // clear: remove all sub-mesh items
2699 while ( itemSubMeshes->childCount() )
2700 delete itemSubMeshes->child( 0 );
2704 QMap<int, QTreeWidgetItem*> smItems;
2705 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
2707 SMESH::SelectionProxy sm = mySubMeshes[i];
2711 int smType = sm.shapeType();
2714 else if ( smType == GEOM::COMPSOLID )
2715 smType = GEOM::COMPOUND;
2717 // create top-level sub-meshes container item if it does not exist
2718 if ( !itemSubMeshes )
2720 itemSubMeshes = createItem( parent, Bold | AllColumns );
2721 itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2722 itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
2724 // if necessary, create extra widget to show information by chunks
2725 if ( mySubMeshes.count() > blockSize() )
2727 ExtraWidget* extra = new ExtraWidget( this, true );
2728 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2729 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2730 myTree->setItemWidget( itemSubMeshes, 1, extra );
2731 extra->updateControls( mySubMeshes.count(), idx );
2735 // create container item corresponding to particular shape type
2736 if ( !smItems.contains( smType ) )
2738 smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
2739 smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2740 itemSubMeshes->insertChild( smType, smItems[ smType ] );
2744 QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
2745 nameItem->setText( 0, sm.name().trimmed() ); // trim name
2748 subMeshInfo( sm, nameItem );
2753 \brief Show previous chunk of information on child groups.
2755 void SMESHGUI_AddInfo::showPreviousGroups()
2757 int idx = property( "group_index" ).toInt();
2758 setProperty( "group_index", idx-1 );
2763 \brief Show next chunk of information on child groups.
2765 void SMESHGUI_AddInfo::showNextGroups()
2767 int idx = property( "group_index" ).toInt();
2768 setProperty( "group_index", idx+1 );
2773 \brief Show previous chunk of information on child sub-meshes.
2775 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2777 int idx = property( "submesh_index" ).toInt();
2778 setProperty( "submesh_index", idx-1 );
2783 \brief Show next chunk of information on child sub-meshes.
2785 void SMESHGUI_AddInfo::showNextSubMeshes()
2787 int idx = property( "submesh_index" ).toInt();
2788 setProperty( "submesh_index", idx+1 );
2793 \brief Write information from panel to ouput stream.
2794 \param out Text stream output.
2796 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2799 QString title = tr( "ADDITIONAL_INFO" );
2800 out << ruler( title.size() ) << endl;
2801 out << title << endl;
2802 out << ruler( title.size() ) << endl;
2806 QTreeWidgetItemIterator it( myTree );
2809 if ( !( ( *it )->text(0) ).isEmpty() )
2811 out << indent( itemDepth( *it ) ) << ( *it )->text(0);
2812 if ( ( *it )->text(0) == tr( "COLOR" ) )
2813 out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
2814 else if ( !( ( *it )->text(1) ).isEmpty() )
2815 out << ":" << spacing() << ( *it )->text(1);
2823 ////////////////////////////////////////////////////////////////////////////////
2824 /// \class GroupCombo
2825 /// \brief Customized combo box to manage list of mesh groups.
2827 ////////////////////////////////////////////////////////////////////////////////
2829 class GroupCombo: public QComboBox
2831 class Item: public QStandardItem
2834 SMESH::SelectionProxy myGroup;
2835 Item( const SMESH::SelectionProxy& group )
2838 setText( myGroup.name() );
2840 SMESH::SelectionProxy group()
2846 SMESH::SelectionProxy myProxy;
2849 GroupCombo( QWidget* );
2850 void setSource( const SMESH::SelectionProxy& );
2851 SMESH::SelectionProxy currentGroup() const;
2856 \param parent Parent widget.
2859 GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
2861 setModel( new QStandardItemModel( this ) );
2865 \brief Set mesh source.
2866 \param obj Mesh source.
2869 void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
2871 if ( myProxy == proxy )
2876 bool blocked = blockSignals( true );
2877 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2882 if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
2884 QList<SMESH::SelectionProxy> groups = myProxy.groups();
2885 for ( int i = 0; i < groups.count(); ++i )
2889 QString name = groups[i].name();
2890 if ( !name.isEmpty() )
2891 m->appendRow( new Item( groups[i] ) );
2894 setCurrentIndex( -1 ); // for performance reasons
2896 else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
2898 m->appendRow( new Item( myProxy ) );
2899 setCurrentIndex( 0 );
2903 blockSignals( blocked );
2907 \brief Get currently selected group.
2908 \return Selected group.
2911 SMESH::SelectionProxy GroupCombo::currentGroup() const
2913 SMESH::SelectionProxy group;
2914 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2915 if ( currentIndex() >= 0 )
2916 group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
2920 ////////////////////////////////////////////////////////////////////////////////
2921 /// \class SMESHGUI_MeshInfoDlg
2922 /// \brief Mesh information dialog box
2924 /// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
2925 /// \todo Add selection button to reactivate selection on move from other dlg.
2926 ////////////////////////////////////////////////////////////////////////////////
2930 \param parent Parent widget.
2931 \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
2933 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
2937 setAttribute( Qt::WA_DeleteOnClose, true );
2938 setWindowTitle( tr( "MESH_INFO" ) );
2939 setSizeGripEnabled( true );
2941 myTabWidget = new QTabWidget( this );
2945 myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
2946 myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
2950 QWidget* w = new QWidget( myTabWidget );
2952 myMode = new QButtonGroup( this );
2953 myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
2954 myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
2955 myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
2956 myMode->button( NodeMode )->setChecked( true );
2957 myID = new QLineEdit( w );
2958 myID->setValidator( new SMESHGUI_IdValidator( this ) );
2959 myGroups = new GroupCombo( w );
2960 QStackedWidget* stack = new QStackedWidget( w );
2961 stack->addWidget( myID );
2962 stack->addWidget( myGroups );
2963 myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
2964 myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
2966 int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
2967 mode = qMin( 1, qMax( 0, mode ) );
2970 myElemInfo = new SMESHGUI_SimpleElemInfo( w );
2972 myElemInfo = new SMESHGUI_TreeElemInfo( w );
2973 stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
2975 QGridLayout* elemLayout = new QGridLayout( w );
2976 elemLayout->setMargin( MARGIN );
2977 elemLayout->setSpacing( SPACING );
2978 elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
2979 elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
2980 elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
2981 elemLayout->addWidget( stack, 0, 3 );
2982 elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
2983 elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
2985 myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
2989 myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
2990 myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
2994 myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
2995 myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
2999 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3000 okBtn->setAutoDefault( true );
3001 okBtn->setDefault( true );
3003 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3004 dumpBtn->setAutoDefault( true );
3005 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3006 helpBtn->setAutoDefault( true );
3008 QHBoxLayout* btnLayout = new QHBoxLayout;
3009 btnLayout->setSpacing( SPACING );
3010 btnLayout->setMargin( 0 );
3012 btnLayout->addWidget( okBtn );
3013 btnLayout->addWidget( dumpBtn );
3014 btnLayout->addStretch( 10 );
3015 btnLayout->addWidget( helpBtn );
3019 QVBoxLayout* l = new QVBoxLayout ( this );
3020 l->setMargin( MARGIN );
3021 l->setSpacing( SPACING );
3022 l->addWidget( myTabWidget );
3023 l->addLayout( btnLayout );
3027 myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
3029 // set-up connections
3031 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3032 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3033 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3034 connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
3035 connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
3036 connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
3037 connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
3038 connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
3039 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3040 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3041 connect( myElemInfo, SIGNAL( itemInfo( int ) ), this, SLOT( showItemInfo( int ) ) );
3042 connect( myElemInfo, SIGNAL( itemInfo( QString ) ), this, SLOT( showItemInfo( QString ) ) );
3043 connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
3047 myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
3054 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
3060 \brief Show mesh information on given object.
3061 \param io Interactive object.
3063 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3066 showInfo( SMESH::SelectionProxy( io ) );
3070 \brief Show mesh information on given object.
3071 \param proxy Selection proxy.
3073 void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3075 SUIT_OverrideCursor wc;
3082 SMESH::SMESH_IDSource_var obj = myProxy.object();
3085 myBaseInfo->showInfo( proxy );
3087 // "Additional info" tab
3088 myAddInfo->showInfo( proxy );
3090 // "Quality info" tab
3091 // Note: for performance reasons we update it only if it is currently active
3092 if ( myTabWidget->currentIndex() == CtrlInfo )
3093 myCtrlInfo->showInfo( proxy );
3095 // "Element info" tab
3096 myGroups->setSource( proxy );
3097 if ( myMode->checkedId() == GroupMode ) {
3098 SMESH::SelectionProxy group = myGroups->currentGroup();
3100 myElemInfo->showInfo( group );
3102 myElemInfo->clear();
3105 SVTK_Selector* selector = SMESH::GetSelector();
3108 if ( myProxy.actor() && selector ) { //todo: actor()?
3109 nb = myMode->checkedId() == NodeMode ?
3110 SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
3111 SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
3114 myID->setText( ID.trimmed() );
3116 QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
3117 foreach ( ID, idTxt )
3118 ids << ID.trimmed().toUInt();
3119 myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
3123 myElemInfo->clear();
3129 \brief Update information.
3131 void SMESHGUI_MeshInfoDlg::updateInfo()
3133 SALOME_ListIO selected;
3134 SMESHGUI::selectionMgr()->selectedObjects( selected );
3136 if ( selected.Extent() == 1 )
3137 showInfo( selected.First() );
3139 showInfo( myProxy );
3143 \brief Clean-up on dialog closing.
3145 void SMESHGUI_MeshInfoDlg::reject()
3147 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3148 selMgr->clearFilters();
3149 SMESH::SetPointRepresentation( false );
3150 if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
3151 viewWindow->SetSelectionMode( ActorSelection );
3153 myIDPreview->SetPointsLabeled( false );
3157 \brief Process keyboard event.
3158 \param e Key press event.
3160 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
3162 QDialog::keyPressEvent( e );
3163 if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
3170 \brief Set-up selection mode for currently selected page.
3172 void SMESHGUI_MeshInfoDlg::updateSelection()
3174 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3176 disconnect( selMgr, 0, this, 0 );
3177 selMgr->clearFilters();
3179 int selMode = ActorSelection;
3180 if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == NodeMode )
3181 selMode = NodeSelection;
3182 else if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == ElemMode )
3183 selMode = CellSelection;
3184 SMESH::SetPointRepresentation( selMode == NodeSelection );
3185 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3186 aViewWindow->SetSelectionMode( selMode );
3188 SMESH::SelectionProxy previous = myProxy;
3189 QString ids = myID->text().trimmed();
3192 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3195 if ( myProxy && myProxy == previous && !ids.isEmpty() ) {
3196 myID->setText( ids );
3202 \brief Show documentation on selected dialog page.
3204 void SMESHGUI_MeshInfoDlg::help()
3206 QString helpPage = "mesh_infos.html";
3207 switch ( myTabWidget->currentIndex() )
3210 helpPage += "#advanced-mesh-infos-anchor";
3213 helpPage += "#mesh-element-info-anchor";
3216 helpPage += "#mesh-addition-info-anchor";
3219 helpPage += "#mesh-quality-info-anchor";
3224 SMESH::ShowHelpFile( helpPage );
3228 \brief Deactivate dialog box.
3230 void SMESHGUI_MeshInfoDlg::deactivate()
3232 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3236 \brief Called when users switches between node / element modes.
3238 void SMESHGUI_MeshInfoDlg::modeChanged()
3240 emit( switchMode( myMode->checkedId() == GroupMode ? 1 : 0 ) );
3246 \brief Called when users prints mesh element ID in the corresponding field.
3248 void SMESHGUI_MeshInfoDlg::idChanged()
3250 myIDPreview->SetPointsLabeled( false );
3252 SVTK_Selector* selector = SMESH::GetSelector();
3253 if ( myProxy.actor() && selector ) { //todo: actor()?
3254 Handle(SALOME_InteractiveObject) IO = myProxy.actor()->getIO(); //todo: actor()?
3255 TColStd_MapOfInteger ID;
3257 std::vector<int> idVec;
3258 std::list< gp_XYZ > aGrCentersXYZ;
3259 QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
3260 foreach ( QString tid, idTxt ) {
3261 long id = tid.trimmed().toUInt();
3262 const SMDS_MeshElement* e = myMode->checkedId() == ElemMode ?
3263 myProxy.actor()->GetObject()->GetMesh()->FindElement( id ) : //todo: actor()?
3264 myProxy.actor()->GetObject()->GetMesh()->FindNode( id ); //todo: actor()?
3268 if ( myMode->checkedId() == ElemMode )
3270 idVec.push_back( id );
3271 // aGrCentersXYZ.push_back( myElemInfo->gravityCenter( e ) ); //todo?
3275 selector->AddOrRemoveIndex( IO, ID, false );
3276 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) {
3278 if ( myMode->checkedId() == NodeMode )
3279 myIDPreview->SetPointsData( myProxy.actor()->GetObject()->GetMesh(), ID ); //todo: actor()?
3281 myIDPreview->SetElemsData( idVec, aGrCentersXYZ );
3283 bool showIDs = ( !ID.IsEmpty() &&
3284 myIDPreviewCheck->isChecked() &&
3285 myTabWidget->currentIndex() == ElemInfo );
3286 myIDPreview->SetPointsLabeled( showIDs, myProxy.actor()->GetVisibility() ); //todo: actor()?
3288 aViewWindow->highlight( IO, true, true );
3289 aViewWindow->Repaint();
3291 myElemInfo->showInfo( myProxy, ids, myMode->checkedId() == ElemMode );
3296 * \brief Show IDs clicked
3298 void SMESHGUI_MeshInfoDlg::idPreviewChange( bool isOn )
3300 myIDPreview->SetPointsLabeled( isOn && !myID->text().simplified().isEmpty() );
3301 SMESHGUI::resourceMgr()->setValue("SMESH", "id_preview_resource", isOn );
3302 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3303 aViewWindow->Repaint();
3306 void SMESHGUI_MeshInfoDlg::showItemInfo( int id )
3308 if ( id > 0 && myProxy.actor()->GetObject()->GetMesh()->FindNode( id ) ) { //todo: actor()?
3309 myMode->button( NodeMode )->click();
3310 myID->setText( QString::number( id ) );
3314 void SMESHGUI_MeshInfoDlg::showItemInfo( const QString& theStr )
3316 if ( !theStr.isEmpty() ) {
3317 myMode->button( ElemMode )->click();
3318 myID->setText( theStr );
3323 \brief Dump information to file.
3325 void SMESHGUI_MeshInfoDlg::dump()
3327 DumpFileDlg fd( this );
3328 fd.setWindowTitle( tr( "SAVE_INFO" ) );
3329 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
3330 fd.setChecked( BaseInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_base", true ) );
3331 fd.setChecked( ElemInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_elem", true ) );
3332 fd.setChecked( AddInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_add", true ) );
3333 fd.setChecked( CtrlInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_ctrl", true ) );
3334 if ( fd.exec() == QDialog::Accepted )
3336 QString fileName = fd.selectedFile();
3337 if ( !fileName.isEmpty() ) {
3338 QFile file( fileName );
3339 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
3342 QTextStream out( &file );
3343 if ( fd.isChecked( BaseInfo ) ) myBaseInfo->saveInfo( out );
3344 if ( fd.isChecked( ElemInfo ) ) myElemInfo->saveInfo( out );
3345 if ( fd.isChecked( AddInfo ) ) myAddInfo->saveInfo( out );
3346 if ( fd.isChecked( CtrlInfo ) ) myCtrlInfo->saveInfo( out );
3351 ////////////////////////////////////////////////////////////////////////////////
3352 /// \class SMESHGUI_CtrlInfo
3353 /// \brief Show quality statistics information on selected object.
3355 /// Displays quality controls statistics about selected object: mesh, sub-mesh,
3356 /// group or arbitrary ID source.
3357 ////////////////////////////////////////////////////////////////////////////////
3361 \param parent Parent widget. Defaults to 0.
3363 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent ): SMESHGUI_Info( parent )
3365 QGridLayout* l = new QGridLayout( this );
3366 l->setMargin( MARGIN );
3367 l->setSpacing( SPACING );
3369 QIcon aComputeIcon( SUIT_Session::session()->resourceMgr()->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3370 SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3373 QLabel* aNameLab = createLabel( tr( "NAME_LAB" ), this, Bold );
3374 QLabel* aName = createField( this, "ctrlName" );
3375 aName->setMinimumWidth( 150 );
3379 QLabel* aNodesLab = createLabel( tr( "NODES_INFO" ), this, Bold );
3380 QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3381 QLabel* aNodesFree = createField( this, "ctrlNodesFree" );
3382 myWidgets << aNodesFree;
3383 myPredicates << aFilterMgr->CreateFreeNodes();
3385 QLabel* aNodesNbConnLab = new QLabel( tr( "MAX_NODE_CONNECTIVITY" ), this );
3386 QLabel* aNodesNbConn = createField( this, "ctrlNodesCnty" );
3387 myWidgets << aNodesNbConn;
3388 myNodeConnFunctor = aFilterMgr->CreateNodeConnectivityNumber();
3390 QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3391 QLabel* aNodesDouble = createField( this, "ctrlNodesDouble" );
3392 myWidgets << aNodesDouble;
3393 myPredicates << aFilterMgr->CreateEqualNodes();
3394 QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3395 myToleranceWidget = new SMESHGUI_SpinBox( this );
3396 myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3397 myToleranceWidget->setAcceptNames( false );
3398 myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3401 QLabel* anEdgesLab = createLabel( tr( "EDGES_INFO" ), this, Bold );
3402 QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ), this );
3403 QLabel* anEdgesDouble = createField( this, "ctrlEdgesDouble" );
3404 myWidgets << anEdgesDouble;
3405 myPredicates << aFilterMgr->CreateEqualEdges();
3408 QLabel* aFacesLab = createLabel( tr( "FACES_INFO" ), this, Bold );
3409 QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3410 QLabel* aFacesDouble = createField( this, "ctrlFacesDouble" );
3411 myWidgets << aFacesDouble;
3412 myPredicates << aFilterMgr->CreateEqualFaces();
3413 QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3414 QLabel* aFacesOver = createField( this, "ctrlFacesOver" );
3415 myWidgets << aFacesOver;
3416 myPredicates << aFilterMgr->CreateOverConstrainedFace();
3417 QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3418 myPlot = createPlot( this );
3419 myAspectRatio = aFilterMgr->CreateAspectRatio();
3422 QLabel* aVolumesLab = createLabel( tr( "VOLUMES_INFO" ), this, Bold );
3423 QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3424 QLabel* aVolumesDouble = createField( this, "ctrlVolumesDouble" );
3425 myWidgets << aVolumesDouble;
3426 myPredicates << aFilterMgr->CreateEqualVolumes();
3427 QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3428 QLabel* aVolumesOver = createField( this, "ctrlVolumesOver" );
3429 myWidgets << aVolumesOver;
3430 myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3431 QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3432 myPlot3D = createPlot( this );
3433 myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3435 QToolButton* aFreeNodesBtn = new QToolButton( this );
3436 aFreeNodesBtn->setIcon(aComputeIcon);
3437 myButtons << aFreeNodesBtn; //0
3439 QToolButton* aNodesNbConnBtn = new QToolButton( this );
3440 aNodesNbConnBtn->setIcon(aComputeIcon);
3441 myButtons << aNodesNbConnBtn; //1
3443 QToolButton* aDoubleNodesBtn = new QToolButton( this );
3444 aDoubleNodesBtn->setIcon(aComputeIcon);
3445 myButtons << aDoubleNodesBtn; //2
3447 QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3448 aDoubleEdgesBtn->setIcon(aComputeIcon);
3449 myButtons << aDoubleEdgesBtn; //3
3451 QToolButton* aDoubleFacesBtn = new QToolButton( this );
3452 aDoubleFacesBtn->setIcon(aComputeIcon);
3453 myButtons << aDoubleFacesBtn; //4
3455 QToolButton* aOverContFacesBtn = new QToolButton( this );
3456 aOverContFacesBtn->setIcon(aComputeIcon);
3457 myButtons << aOverContFacesBtn; //5
3459 QToolButton* aComputeFaceBtn = new QToolButton( this );
3460 aComputeFaceBtn->setIcon(aComputeIcon);
3461 myButtons << aComputeFaceBtn; //6
3463 QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3464 aDoubleVolumesBtn->setIcon(aComputeIcon);
3465 myButtons << aDoubleVolumesBtn; //7
3467 QToolButton* aOverContVolumesBtn = new QToolButton( this );
3468 aOverContVolumesBtn->setIcon(aComputeIcon);
3469 myButtons << aOverContVolumesBtn; //8
3471 QToolButton* aComputeVolumeBtn = new QToolButton( this );
3472 aComputeVolumeBtn->setIcon(aComputeIcon);
3473 myButtons << aComputeVolumeBtn; //9
3475 connect( aComputeFaceBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3476 connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3477 connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3478 connect( aNodesNbConnBtn, SIGNAL( clicked() ), this, SLOT( computeNodesNbConnInfo() ) );
3479 connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3480 connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3481 connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3482 connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3483 connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3484 connect( aOverContVolumesBtn,SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3485 connect( myToleranceWidget, SIGNAL( valueChanged( double ) ), this, SLOT( setTolerance( double ) ) );
3487 l->addWidget( aNameLab, 0, 0 ); //0
3488 l->addWidget( aName, 0, 1, 1, 2 ); //1
3489 l->addWidget( aNodesLab, 1, 0, 1, 3 ); //2
3490 l->addWidget( aNodesFreeLab, 2, 0 ); //3
3491 l->addWidget( aNodesFree, 2, 1 ); //4
3492 l->addWidget( aFreeNodesBtn, 2, 2 ); //5
3493 l->addWidget( aNodesNbConnLab, 3, 0 ); //6
3494 l->addWidget( aNodesNbConn, 3, 1 ); //7
3495 l->addWidget( aNodesNbConnBtn, 3, 2 ); //8
3496 l->addWidget( aNodesDoubleLab, 4, 0 ); //9
3497 l->addWidget( aNodesDouble, 4, 1 ); //10
3498 l->addWidget( aDoubleNodesBtn, 4, 2 ); //11
3499 l->addWidget( aToleranceLab, 5, 0 ); //12
3500 l->addWidget( myToleranceWidget, 5, 1 ); //13
3501 l->addWidget( anEdgesLab, 6, 0, 1, 3 ); //14
3502 l->addWidget( anEdgesDoubleLab, 7, 0 ); //15
3503 l->addWidget( anEdgesDouble, 7, 1 ); //16
3504 l->addWidget( aDoubleEdgesBtn, 7, 2 ); //17
3505 l->addWidget( aFacesLab, 8, 0, 1, 3 ); //18
3506 l->addWidget( aFacesDoubleLab, 9, 0 ); //19
3507 l->addWidget( aFacesDouble, 9, 1 ); //20
3508 l->addWidget( aDoubleFacesBtn, 9, 2 ); //21
3509 l->addWidget( aFacesOverLab, 10, 0 ); //22
3510 l->addWidget( aFacesOver, 10, 1 ); //23
3511 l->addWidget( aOverContFacesBtn, 10, 2 ); //24
3512 l->addWidget( anAspectRatioLab, 11, 0 ); //25
3513 l->addWidget( aComputeFaceBtn, 11, 2 ); //26
3514 l->addWidget( myPlot, 12, 0, 1, 3 );//27
3515 l->addWidget( aVolumesLab, 13, 0, 1, 3 );//28
3516 l->addWidget( aVolumesDoubleLab, 14, 0 ); //29
3517 l->addWidget( aVolumesDouble, 14, 1 ); //30
3518 l->addWidget( aDoubleVolumesBtn, 14, 2 ); //31
3519 l->addWidget( aVolumesOverLab, 15, 0 ); //32
3520 l->addWidget( aVolumesOver, 15, 1 ); //33
3521 l->addWidget( aOverContVolumesBtn,15, 2 ); //34
3522 l->addWidget( anAspectRatio3DLab, 16, 0 ); //35
3523 l->addWidget( aComputeVolumeBtn, 16, 2 ); //36
3524 l->addWidget( myPlot3D, 17, 0, 1, 3 );//37
3526 l->setColumnStretch( 0, 0 );
3527 l->setColumnStretch( 1, 5 );
3528 l->setRowStretch ( 12, 5 );
3529 l->setRowStretch ( 17, 5 );
3530 l->setRowStretch ( 18, 1 );
3538 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3543 \brief Create plot widget.
3544 \param parent Parent widget.
3545 \return New plot widget.
3547 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3549 QwtPlot* aPlot = new QwtPlot( parent );
3550 aPlot->setMinimumSize( 100, 100 );
3551 QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3552 xFont.setPointSize( 5 );
3553 QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3554 yFont.setPointSize( 5 );
3555 aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3556 aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3562 \brief Show information on given object.
3563 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
3565 void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
3573 SMESH::SMESH_IDSource_var obj = proxy.object();
3575 myWidgets[0]->setText( proxy.name() );
3577 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3578 if ( mesh->_is_nil() ) return;
3580 const bool meshLoaded = mesh->IsLoaded();
3581 if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3582 // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3583 for ( int i = 0; i < myButtons.count(); ++i )
3584 myButtons[i]->setEnabled( true );
3586 SMESH::long_array_var nbElemsByType = obj->GetNbElementsByType();
3587 if ( ! &nbElemsByType.in() ) return;
3589 const CORBA::Long ctrlLimit =
3590 meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3593 const CORBA::Long nbNodes = nbElemsByType[ SMESH::NODE ];
3594 // const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3595 // nbElemsByType[ SMESH::FACE ] +
3596 // nbElemsByType[ SMESH::VOLUME ] );
3597 if ( nbNodes > 0 ) {
3598 if ( nbNodes <= ctrlLimit ) {
3600 computeFreeNodesInfo();
3601 // node connectivity number
3602 computeNodesNbConnInfo();
3604 computeDoubleNodesInfo();
3607 myButtons[0]->setEnabled( true );
3608 myButtons[1]->setEnabled( true );
3609 myButtons[2]->setEnabled( true );
3613 for( int i=2; i<=13; i++)
3614 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3618 if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3620 if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3621 computeDoubleEdgesInfo();
3623 myButtons[3]->setEnabled( true );
3626 for( int i=14; i<=17; i++)
3627 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3631 if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3632 if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3634 computeDoubleFacesInfo();
3635 // over constrained faces
3636 computeOverConstrainedFacesInfo();
3637 // aspect Ratio histogram
3638 computeAspectRatio();
3641 myButtons[4]->setEnabled( true );
3642 myButtons[5]->setEnabled( true );
3643 myButtons[6]->setEnabled( true );
3645 #ifdef DISABLE_PLOT2DVIEWER
3646 for( int i=25; i<=27; i++)
3647 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3651 for( int i=18; i<=27; i++)
3652 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3656 if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3657 if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3659 computeDoubleVolumesInfo();
3660 // over constrained volumes
3661 computeOverConstrainedVolumesInfo();
3662 // aspect Ratio 3D histogram
3663 computeAspectRatio3D();
3666 myButtons[7]->setEnabled( true );
3667 myButtons[8]->setEnabled( true );
3668 myButtons[9]->setEnabled( true );
3670 #ifdef DISABLE_PLOT2DVIEWER
3671 for( int i=35; i<=37; i++)
3672 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3676 for( int i=28; i<=37; i++)
3677 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3681 //================================================================================
3683 * \brief Computes and shows nb of elements satisfying a given predicate
3684 * \param [in] ft - a predicate type (SMESH::FunctorType)
3685 * \param [in] iBut - index of one of myButtons to disable
3686 * \param [in] iWdg - index of one of myWidgets to show the computed number
3688 //================================================================================
3690 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3692 myButtons[ iBut ]->setEnabled( false );
3693 myWidgets[ iWdg ]->setText( "" );
3698 SUIT_OverrideCursor wc;
3700 SMESH::SMESH_IDSource_var obj = myProxy.object();
3701 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3703 if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3706 showInfo( myProxy ); // try to show all values
3707 if ( !myWidgets[ iWdg ]->text().isEmpty() )
3708 return; // <ft> predicate already computed
3710 // look for a predicate of type <ft>
3711 for ( int i = 0; i < myPredicates.count(); ++i )
3712 if ( myPredicates[i]->GetFunctorType() == ft )
3714 CORBA::Long nb = myPredicates[i]->NbSatisfying( obj );
3715 myWidgets[ iWdg ]->setText( QString::number( nb ) );
3719 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3721 computeNb( SMESH::FT_FreeNodes, 0, 1 );
3724 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3726 computeNb( SMESH::FT_EqualNodes, 2, 3 );
3729 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3731 computeNb( SMESH::FT_EqualEdges, 3, 4 );
3734 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3736 computeNb( SMESH::FT_EqualFaces, 4, 5 );
3739 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3741 computeNb( SMESH::FT_OverConstrainedFace, 5, 6 );
3744 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3746 computeNb( SMESH::FT_EqualVolumes, 7, 7 );
3749 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3751 computeNb( SMESH::FT_OverConstrainedVolume, 8, 8 );
3754 void SMESHGUI_CtrlInfo::computeNodesNbConnInfo()
3756 myButtons[ 1 ]->setEnabled( false );
3757 myWidgets[ 2 ]->setText( "" );
3762 SUIT_OverrideCursor wc;
3764 SMESH::SMESH_IDSource_var obj = myProxy.object();
3765 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3767 if ( !mesh->IsLoaded() )
3770 showInfo( myProxy ); // try to show all values
3771 if ( !myWidgets[ 2 ]->text().isEmpty() )
3772 return; // already computed
3774 myNodeConnFunctor->SetMesh( mesh );
3775 SMESH::Histogram_var histogram =
3776 myNodeConnFunctor->GetLocalHistogram( 1, /*isLogarithmic=*/false, obj );
3778 myWidgets[ 2 ]->setText( QString::number( histogram[0].max ) );
3781 void SMESHGUI_CtrlInfo::computeAspectRatio()
3783 #ifndef DISABLE_PLOT2DVIEWER
3784 myButtons[6]->setEnabled( false );
3789 SUIT_OverrideCursor wc;
3791 SMESH::SMESH_IDSource_var obj = myProxy.object();
3792 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3794 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3795 if ( aHistogram && !aHistogram->isEmpty() ) {
3796 QwtPlotItem* anItem = aHistogram->createPlotItem();
3797 anItem->attach( myPlot );
3804 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3806 #ifndef DISABLE_PLOT2DVIEWER
3807 myButtons[9]->setEnabled( false );
3812 SUIT_OverrideCursor wc;
3814 SMESH::SMESH_IDSource_var obj = myProxy.object();
3815 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3817 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3818 if ( aHistogram && !aHistogram->isEmpty() ) {
3819 QwtPlotItem* anItem = aHistogram->createPlotItem();
3820 anItem->attach( myPlot3D );
3828 \brief Internal clean-up (reset widget)
3830 void SMESHGUI_CtrlInfo::clearInternal()
3832 for( int i=0; i<=37; i++)
3833 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( true );
3834 for( int i=0; i<=9; i++)
3835 myButtons[i]->setEnabled( false );
3836 myPlot->detachItems();
3837 myPlot3D->detachItems();
3840 myWidgets[0]->setText( QString() );
3841 for ( int i = 1; i < myWidgets.count(); i++ )
3842 myWidgets[i]->setText( "" );
3845 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3847 //SMESH::long_array_var anElems = getElementsByType( SMESH::NODE );
3848 myButtons[1]->setEnabled( true );
3849 myWidgets[2]->setText("");
3852 #ifndef DISABLE_PLOT2DVIEWER
3853 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3855 SUIT_OverrideCursor wc;
3857 SMESH::SMESH_IDSource_var obj = myProxy.object();
3858 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3860 if ( !mesh->IsLoaded() )
3862 aNumFun->SetMesh( mesh );
3864 CORBA::Long cprecision = 6;
3865 if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) )
3866 cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3867 aNumFun->SetPrecision( cprecision );
3869 int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3871 SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3872 /*isLogarithmic=*/false,
3874 Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3875 aHistogram->setColor( palette().color( QPalette::Highlight ) );
3876 if ( &histogramVar.in() )
3878 for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3879 aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3880 if ( histogramVar->length() >= 2 )
3881 aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3887 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
3890 QString title = tr( "CTRL_INFO" );
3891 out << ruler( title.size() ) << endl;
3892 out << title << endl;
3893 out << ruler( title.size() ) << endl;
3897 out << tr( "NAME_LAB" ) << " " << myWidgets[0]->text() << endl;
3898 out << tr( "NODES_INFO" ) << endl;
3899 out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
3900 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_NODES" ) << ": " << myWidgets[2]->text() << endl;
3901 out << tr( "EDGES_INFO" ) << endl;
3902 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_EDGES" ) << ": " << myWidgets[3]->text() << endl;
3903 out << tr( "FACES_INFO" ) << endl;
3904 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_FACES" ) << ": " << myWidgets[4]->text() << endl;
3905 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[5]->text() << endl;
3906 out << tr( "VOLUMES_INFO" ) << endl;
3907 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ) << ": " << myWidgets[6]->text() << endl;
3908 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[7]->text() << endl;
3911 ////////////////////////////////////////////////////////////////////////////////
3912 /// \class SMESHGUI_CtrlInfoDlg
3913 /// \brief Overall Mesh Quality dialog.
3914 /// \todo Add selection button to reactivate selection on move from other dlg.
3915 ////////////////////////////////////////////////////////////////////////////////
3919 \param parent parent widget
3921 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
3924 setAttribute( Qt::WA_DeleteOnClose, true );
3925 setWindowTitle( tr( "CTRL_INFO" ) );
3926 setMinimumSize( 400, 600 );
3928 myCtrlInfo = new SMESHGUI_CtrlInfo( this );
3931 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3932 okBtn->setAutoDefault( true );
3933 okBtn->setDefault( true );
3935 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3936 dumpBtn->setAutoDefault( true );
3937 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3938 helpBtn->setAutoDefault( true );
3940 QHBoxLayout* btnLayout = new QHBoxLayout;
3941 btnLayout->setSpacing( SPACING );
3942 btnLayout->setMargin( 0 );
3944 btnLayout->addWidget( okBtn );
3945 btnLayout->addWidget( dumpBtn );
3946 btnLayout->addStretch( 10 );
3947 btnLayout->addWidget( helpBtn );
3949 QVBoxLayout* l = new QVBoxLayout ( this );
3951 l->setSpacing( SPACING );
3952 l->addWidget( myCtrlInfo );
3953 l->addLayout( btnLayout );
3955 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3956 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3957 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3958 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3959 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3967 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
3972 \brief Show mesh quality information on given object.
3973 \param io Interactive object.
3975 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3978 showInfo( SMESH::SelectionProxy( io ) );
3982 \brief Show mesh quality information on given object.
3983 \param proxy Selection proxy.
3985 void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3987 SUIT_OverrideCursor wc;
3993 myCtrlInfo->showInfo( proxy );
3997 \brief Show mesh information
3999 void SMESHGUI_CtrlInfoDlg::updateInfo()
4001 SALOME_ListIO selected;
4002 SMESHGUI::selectionMgr()->selectedObjects( selected );
4004 if ( selected.Extent() == 1 )
4005 showInfo( selected.First() );
4007 showInfo( myProxy );
4011 \brief Perform clean-up actions on the dialog box closing.
4013 void SMESHGUI_CtrlInfoDlg::reject()
4015 SMESH::SetPointRepresentation( false );
4020 \brief Setup selection mode depending on the current dialog box state.
4022 void SMESHGUI_CtrlInfoDlg::updateSelection()
4024 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
4025 disconnect( selMgr, 0, this, 0 );
4026 SMESH::SetPointRepresentation( false );
4027 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4032 \brief Deactivate dialog box.
4034 void SMESHGUI_CtrlInfoDlg::deactivate()
4036 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4040 \brief Dump information to file.
4042 void SMESHGUI_CtrlInfoDlg::dump()
4044 DumpFileDlg fd( this, false );
4045 fd.setWindowTitle( tr( "SAVE_INFO" ) );
4046 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
4047 if ( fd.exec() == QDialog::Accepted )
4049 QString fileName = fd.selectedFile();
4050 if ( !fileName.isEmpty() ) {
4051 QFile file( fileName );
4052 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
4055 QTextStream out( &file );
4056 myCtrlInfo->saveInfo( out );
4062 \brief Show documentation on dialog.
4064 void SMESHGUI_CtrlInfoDlg::help()
4066 SMESH::ShowHelpFile( "mesh_infos.html#mesh-quality-info-anchor" );