1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "SMESHGUI_MeshInfo.h"
25 #include "SMDS_Mesh.hxx"
26 #include "SMESH_Actor.h"
28 #include "SMESHGUI_FilterUtils.h"
29 #include "SMESHGUI_IdPreview.h"
30 #include "SMESHGUI_IdValidator.h"
31 #include "SMESHGUI_SpinBox.h"
32 #include "SMESHGUI_Utils.h"
33 #include "SMESHGUI_VTKUtils.h"
35 #include <SUIT_FileDlg.h>
36 #include <SUIT_OverrideCursor.h>
37 #include <SUIT_ResourceMgr.h>
38 #include <SUIT_Session.h>
39 #include <SVTK_ViewWindow.h>
40 #include <LightApp_SelectionMgr.h>
42 #include <SALOMEDSClient_Study.hxx>
44 #include <QApplication>
45 #include <QButtonGroup>
48 #include <QContextMenuEvent>
49 #include <QGridLayout>
50 #include <QHBoxLayout>
51 #include <QHeaderView>
52 #include <QItemDelegate>
57 #include <QPushButton>
58 #include <QRadioButton>
59 #include <QStackedWidget>
60 #include <QStandardItemModel>
62 #include <QTextBrowser>
63 #include <QTextStream>
64 #include <QToolButton>
65 #include <QTreeWidget>
66 #include <QVBoxLayout>
68 ////////////////////////////////////////////////////////////////////////////////
70 /// \brief Field widget.
72 ////////////////////////////////////////////////////////////////////////////////
74 class Field : public QLabel
77 Field( QWidget*, const QString& = QString() );
78 bool event( QEvent* );
83 \param parent Parent widget.
84 \param name Field name. Defauls to null string.
86 Field::Field( QWidget* parent, const QString& name ): QLabel( parent )
88 setFrameStyle( QLabel::StyledPanel | QLabel::Sunken );
89 setAlignment( Qt::AlignCenter );
90 setAutoFillBackground( true );
91 QPalette pal = palette();
92 QColor base = QApplication::palette().color( QPalette::Active, QPalette::Base );
93 pal.setColor( QPalette::Window, base );
95 setMinimumWidth( 60 );
96 if ( !name.isEmpty() )
97 setObjectName( name );
101 \brief Event handler. Redefined from QLabel.
103 bool Field::event( QEvent* e )
105 if ( e->type() == QEvent::DynamicPropertyChange )
107 QDynamicPropertyChangeEvent* ce = (QDynamicPropertyChangeEvent*)e;
108 if ( ce->propertyName() == "value" && property( "value" ).isValid() )
110 setText( QString::number( property( "value" ).toInt() ) );
111 setProperty( "value", QVariant() );
115 return QLabel::event( e );
118 ////////////////////////////////////////////////////////////////////////////////
119 /// \class TreeItemCreator
120 /// \brief Generic tree item creator.
122 ////////////////////////////////////////////////////////////////////////////////
124 class TreeItemCreator
128 virtual ~TreeItemCreator() {}
129 virtual QTreeWidgetItem* createItem( QTreeWidgetItem*, int ) = 0;
132 ////////////////////////////////////////////////////////////////////////////////
133 // General purpose services.
134 ////////////////////////////////////////////////////////////////////////////////
138 const int SPACING = 6;
139 const int MARGIN = 9;
158 TypeRole = Qt::UserRole + 10,
164 NodeConnectivity = 100,
169 \brief Get item's depth in the tree.
170 \param item Tree widget item.
171 \return Item's depth in the tree widget (top-level item has zero depth).
174 int itemDepth( QTreeWidgetItem* item )
176 QList<QTreeWidgetItem*> parents;
178 while ( parents.last()->parent() )
179 parents << parents.last()->parent();
180 return parents.size()-1;
184 \brief Get chunk size.
195 \return Spacer string.
201 static QChar spacer = ' ';
202 return QString( size, spacer );
207 \param length Indent size. Defaults to 1.
208 \return Indentation string.
211 QString indent( int length = 1 )
214 static QChar spacer = ' ';
215 return QString( size * length, spacer );
220 \param spacer Spacer.
221 \param length Indent size. Defaults to 1.
222 \return Indentation string.
225 QString indent( const QString& spacer, uint length = 1 )
228 while( length-- > 0 )
234 \brief Get group separator.
235 \param length Length of ruler (number of symbols). Defaults to 80.
236 \return Ruler string.
239 QString ruler( int length = 80 )
241 static QChar ruler = '-';
242 return QString( length, ruler );
246 \brief Get text value from label.
247 \param w Widget (QLabel).
248 \return Value string.
251 QString widgetValue( QWidget* w )
254 if ( qobject_cast<QLabel*>( w ) )
255 v = qobject_cast<QLabel*>( w )->text();
260 \brief Get font for given options.
261 \param font Initial font.
262 \param options Font attributes.
265 QFont fontFromOptions( const QFont& font, int options )
268 f.setBold( options & Bold );
269 f.setItalic( options & Italic );
274 \brief Set font attributes to given widget.
276 \param options Font attributes.
278 void setFontAttributes( QWidget* w, int options )
281 w->setFont( fontFromOptions( w->font(), options ) );
285 \brief Set attributes to given tree item.
286 \param item Tree widget item.
287 \param options Item attributes.
289 void setTreeItemAttributes( QTreeWidgetItem* item, int options )
291 if ( item && item->treeWidget() )
293 for ( int i = 0; i < item->treeWidget()->columnCount(); i++ )
295 if ( i == 0 || options & AllColumns )
296 item->setFont( i, fontFromOptions( item->font( 0 ), options) );
299 if ( options & Expanded )
300 item->setExpanded( true );
301 if ( options & Editable )
302 item->setFlags( item->flags() | Qt::ItemIsEditable );
307 \param parent Parent widget.
308 \param options Label options. Defaults to 0 (none).
311 QLabel* createLabel( QWidget* parent, int options = 0 )
313 QLabel* lab = new QLabel( parent );
314 setFontAttributes( lab, options );
320 \param text Label text.
321 \param parent Parent widget.
322 \param options Label options. Defaults to 0 (none).
325 QLabel* createLabel( const QString& text, QWidget* parent, int options = 0 )
327 QLabel* lab = createLabel( parent, options );
328 lab->setText( text );
333 \brief Create information field.
334 \param parent Parent widget.
335 \param name Field's object. Default to null string.
338 QLabel* createField( QWidget* parent, const QString& name = QString() )
340 return new Field( parent, name );
344 \brief Create information field.
345 \param parent Parent widget.
346 \param options Label options.
347 \param name Field's object. Default to null string.
350 QLabel* createField( QWidget* parent, int options, const QString& name = QString() )
352 QLabel* field = createField( parent, name );
353 setFontAttributes( field, options );
359 \param parent Parent widget.
360 \param orientation Ruler orientation. Defaults to horizontal.
363 QWidget* createSeparator( QWidget* parent, Qt::Orientation orientation = Qt::Horizontal )
365 QFrame* line = new QFrame( parent );
366 line->setFrameShape( orientation == Qt::Horizontal ? QFrame::HLine : QFrame::HLine );
367 line->setFrameShadow( QFrame::Sunken );
372 \brief Decorate text as bold.
373 \param text Initial text.
374 \return Decorated text.
376 QString bold( const QString& text )
378 return QString("<b>%1</b>").arg( text );
382 \brief Format connectivity data to string representation.
383 \param connectivity Connectivity map.
384 \param type Element type or face index if negative
385 \return Stringifed representation of the connectivity.
387 QString formatConnectivity( SMESH::Connectivity connectivity, int type )
391 bool isNodal = ( type == SMDSAbs_Node || type < 0 );
393 if ( connectivity.contains( type ))
395 QList<int> elements = connectivity[ type ];
396 if ( !isNodal ) // order of nodes is important
398 foreach( int id, elements )
399 str << QString::number( id );
401 // wrap IDs into an html link, to be treated by QTextBrowser used by SMESHGUI_SimpleElemInfo
402 QString s = str.join( " " );
403 result = ( "<a href = \"" + // URL:
404 QString( isNodal ? "nodes" : "elems" ) + "://" + // protocol
405 QString( "host.com/") + // QUrl return nothing if host missing
407 s + "</a>" ); // anchor text
411 } // end of anonymous namespace
413 ////////////////////////////////////////////////////////////////////////////////
414 /// \class SMESHGUI_Info
415 /// \brief Base widget for all information panes.
416 ////////////////////////////////////////////////////////////////////////////////
420 \param parent Parent widget. Defaults to 0.
422 SMESHGUI_Info::SMESHGUI_Info( QWidget* parent ): QWidget( parent )
426 ////////////////////////////////////////////////////////////////////////////////
427 /// \class ExtraWidget
428 /// \brief Auxiliary widget to browse between chunks of information.
430 ////////////////////////////////////////////////////////////////////////////////
432 class ExtraWidget : public QWidget
435 ExtraWidget( QWidget*, bool = false );
436 void updateControls( int, int );
447 \param parent Parent widget.
448 \param briefSummary Show summary in brief format. Defaults to \c false.
450 ExtraWidget::ExtraWidget( QWidget* parent, bool briefSummary ): QWidget( parent ), brief( briefSummary )
452 current = new QLabel( this );
453 current->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
454 prev = new QPushButton( "<<", this );
455 next = new QPushButton( ">>", this );
456 QHBoxLayout* hbl = new QHBoxLayout( this );
458 hbl->setSpacing( SPACING );
460 hbl->addWidget( current );
461 hbl->addWidget( prev );
462 hbl->addWidget( next );
466 \brief Update controls.
467 \param total Total number of items.
468 \param index Current index.
470 void ExtraWidget::updateControls( int total, int index )
472 setVisible( total > blockSize() );
473 QString format = brief ? QString( "%1-%2 / %3" ) : SMESHGUI_MeshInfoDlg::tr( "X_FROM_Y_ITEMS_SHOWN" );
474 current->setText( format.arg( index*blockSize()+1 ).arg( qMin( index*blockSize()+blockSize(), total ) ).arg( total ) );
475 prev->setEnabled( index > 0 );
476 next->setEnabled( (index+1)*blockSize() < total );
479 ////////////////////////////////////////////////////////////////////////////////
480 /// \class DumpFileDlg
481 /// \brief Standard Save File dialog box, customized for dump info operation.
483 ////////////////////////////////////////////////////////////////////////////////
485 class DumpFileDlg : public SUIT_FileDlg
487 QMap<int, QCheckBox*> myControls;
489 DumpFileDlg( QWidget*, bool = true );
490 bool isChecked( int ) const;
491 void setChecked( int, bool );
496 \param parent Parent widget.
497 \param showControls Show additional controls. Defaults to \c true.
500 DumpFileDlg::DumpFileDlg( QWidget* parent, bool showControls ): SUIT_FileDlg( parent, false, true, true )
504 QWidget* hB = new QWidget( this );
505 myControls[SMESHGUI_MeshInfoDlg::BaseInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_BASE_INFO" ), hB );
506 myControls[SMESHGUI_MeshInfoDlg::ElemInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ELEM_INFO" ), hB );
507 myControls[SMESHGUI_MeshInfoDlg::AddInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_ADD_INFO" ), hB );
508 myControls[SMESHGUI_MeshInfoDlg::CtrlInfo] = new QCheckBox( SMESHGUI::tr( "PREF_DUMP_CTRL_INFO" ), hB );
510 QGridLayout* layout = new QGridLayout( hB );
511 layout->setMargin( 0 );
512 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::BaseInfo], 0, 0 );
513 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::ElemInfo], 0, 1 );
514 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::AddInfo], 1, 0 );
515 layout->addWidget( myControls[SMESHGUI_MeshInfoDlg::CtrlInfo], 1, 1 );
517 addWidgets( 0, hB, 0 );
522 \brief Get control's value.
523 \param option Control identifier.
524 \return Control value.
527 bool DumpFileDlg::isChecked( int option ) const
529 return myControls.contains( option ) ? myControls[option]->isChecked() : false;
533 \brief Set control's initial value.
534 \param option Control identifier.
535 \param value Control value.
538 void DumpFileDlg::setChecked( int option, bool value )
540 if ( myControls.contains( option ) )
541 myControls[option]->setChecked( value );
544 ////////////////////////////////////////////////////////////////////////////////
545 /// \class SMESHGUI_BaseInfo
546 /// \brief Show basic information on selected object.
548 /// Displays the base information about selected object: mesh, sub-mesh, group
549 /// or arbitrary ID source.
550 /// \todo Hide unnecessary widgets (e.g. for mesh group).
551 ////////////////////////////////////////////////////////////////////////////////
555 \param parent Parent widget. Defaults to 0.
557 SMESHGUI_BaseInfo::SMESHGUI_BaseInfo( QWidget* parent ): SMESHGUI_Info( parent )
559 QGridLayout* l = new QGridLayout( this );
560 l->setMargin( MARGIN );
561 l->setSpacing( SPACING );
565 addWidget( createLabel( tr( "NAME_LAB" ), this, Bold ), iName, iLabel );
566 addWidget( createField( this, "meshName" ), iName, iSingle, 4 )->setMinimumWidth( 150 );
568 addWidget( createLabel( tr( "OBJECT_LAB" ), this, Bold ), iObject, iLabel );
569 addWidget( createField( this, "meshType" ), iObject, iSingle, 4 )->setMinimumWidth( 150 );
571 addWidget( createSeparator( this ), iObjectEnd, iLabel, 5 );
575 addWidget( createLabel( tr( "NODES_LAB" ), this, Bold ), iNodes, iLabel );
576 addWidget( createField( this, "nbNodes" ), iNodes, iTotal );
578 addWidget( createSeparator( this ), iNodesEnd, iLabel, 5 );
582 addWidget( createLabel( tr( "ELEMENTS_LAB" ), this, Bold ), iElementsTitle, iLabel );
583 addWidget( createLabel( tr( "TOTAL_LAB" ), this, Italic ), iElementsTitle, iTotal );
584 addWidget( createLabel( tr( "LINEAR_LAB" ), this, Italic ), iElementsTitle, iLinear );
585 addWidget( createLabel( tr( "QUADRATIC_LAB" ), this, Italic ), iElementsTitle, iQuadratic );
586 addWidget( createLabel( tr( "BI_QUADRATIC_LAB" ), this, Italic ), iElementsTitle, iBiQuadratic );
588 addWidget( createSeparator( this ), iElementsTitleEnd, iTotal, 4 );
590 addWidget( createField( this, "totalNbElems" ), iElementsTotal, iTotal );
591 addWidget( createField( this, "totalNbLinearElems" ), iElementsTotal, iLinear );
592 addWidget( createField( this, "totalNbQuadraticElems" ), iElementsTotal, iQuadratic );
593 addWidget( createField( this, "totalNbBiQuadraticElems" ), iElementsTotal, iBiQuadratic );
595 addWidget( createSeparator( this ), iElementsTotalEnd, iTotal, 4 );
596 // - 0D elements info
597 addWidget( createLabel( tr( "0D_LAB" ), this, Bold | Italic ), i0D, iLabel );
598 addWidget( createField( this, "nb0D" ), i0D, iTotal );
600 addWidget( createSeparator( this ), i0DEnd, iTotal, 4 );
602 addWidget( createLabel( tr( "BALL_LAB" ), this, Bold | Italic ), iBalls, iLabel );
603 addWidget( createField( this, "nbBall" ), iBalls, iTotal );
605 addWidget( createSeparator( this ), iBallsEnd, iTotal, 4 );
606 // - 1D elements info
607 addWidget( createLabel( tr( "1D_LAB" ), this, Bold | Italic ), i1D, iLabel );
608 addWidget( createField( this, "nb1D" ), i1D, iTotal );
609 addWidget( createField( this, "nbLinear1D" ), i1D, iLinear );
610 addWidget( createField( this, "nbQuadratic1D" ), i1D, iQuadratic );
612 addWidget( createSeparator( this ), i1DEnd, iTotal, 4 );
613 // - 2D elements info
615 addWidget( createLabel( tr( "2D_LAB" ), this, Bold | Italic ), i2D, iLabel );
616 addWidget( createField( this, "nb2D" ), i2D, iTotal );
617 addWidget( createField( this, "nbLinear2D" ), i2D, iLinear );
618 addWidget( createField( this, "nbQuadratic2D" ), i2D, iQuadratic );
619 addWidget( createField( this, "nbBiQuadratic2D" ), i2D, iBiQuadratic );
621 addWidget( createLabel( tr( "TRIANGLES_LAB" ), this, Italic ), i2DTriangles, iLabel );
622 addWidget( createField( this, Italic, "nbTriangle" ), i2DTriangles, iTotal );
623 addWidget( createField( this, Italic, "nbLinearTriangle" ), i2DTriangles, iLinear );
624 addWidget( createField( this, Italic, "nbQuadraticTriangle" ), i2DTriangles, iQuadratic );
625 addWidget( createField( this, Italic, "nbBiQuadraticTriangle" ), i2DTriangles, iBiQuadratic );
627 addWidget( createLabel( tr( "QUADRANGLES_LAB" ), this, Italic ), i2DQuadrangles, iLabel );
628 addWidget( createField( this, Italic, "nbQuadrangle" ), i2DQuadrangles, iTotal );
629 addWidget( createField( this, Italic, "nbLinearQuadrangle" ), i2DQuadrangles, iLinear );
630 addWidget( createField( this, Italic, "nbQuadraticQuadrangle" ), i2DQuadrangles, iQuadratic );
631 addWidget( createField( this, Italic, "nbBiQuadraticQuadrangle" ), i2DQuadrangles, iBiQuadratic );
633 addWidget( createLabel( tr( "POLYGONS_LAB" ), this, Italic ), i2DPolygons, iLabel );
634 addWidget( createField( this, Italic, "nbPolygon" ), i2DPolygons, iTotal );
635 addWidget( createField( this, Italic, "nbLinearPolygon" ), i2DPolygons, iLinear );
636 addWidget( createField( this, Italic, "nbQuadraticPolygon" ), i2DPolygons, iQuadratic );
638 addWidget( createSeparator( this ), i2DEnd, iTotal, 4 );
639 // - 3D elements info
641 addWidget( createLabel( tr( "3D_LAB" ), this, Bold | Italic ), i3D, iLabel );
642 addWidget( createField( this, "nb3D" ), i3D, iTotal );
643 addWidget( createField( this, "nbLinear3D" ), i3D, iLinear );
644 addWidget( createField( this, "nbQuadratic3D" ), i3D, iQuadratic );
645 addWidget( createField( this, "nbBiQuadratic3D" ), i3D, iBiQuadratic );
647 addWidget( createLabel( tr( "TETRAHEDRONS_LAB" ), this, Italic ), i3DTetrahedrons, iLabel );
648 addWidget( createField( this, Italic, "nbTetrahedron" ), i3DTetrahedrons, iTotal );
649 addWidget( createField( this, Italic, "nbLinearTetrahedron" ), i3DTetrahedrons, iLinear );
650 addWidget( createField( this, Italic, "nbQudraticTetrahedron" ), i3DTetrahedrons, iQuadratic );
652 addWidget( createLabel( tr( "HEXAHEDONRS_LAB" ), this, Italic ), i3DHexahedrons, iLabel );
653 addWidget( createField( this, Italic, "nbHexahedron" ), i3DHexahedrons, iTotal );
654 addWidget( createField( this, Italic, "nbLinearHexahedron" ), i3DHexahedrons, iLinear );
655 addWidget( createField( this, Italic, "nbQuadraticHexahedron" ), i3DHexahedrons, iQuadratic );
656 addWidget( createField( this, Italic, "nbBiQuadraticHexahedron" ), i3DHexahedrons, iBiQuadratic );
658 addWidget( createLabel( tr( "PYRAMIDS_LAB" ), this, Italic ), i3DPyramids, iLabel );
659 addWidget( createField( this, Italic, "nbPyramid" ), i3DPyramids, iTotal );
660 addWidget( createField( this, Italic, "nbLinearPyramid" ), i3DPyramids, iLinear );
661 addWidget( createField( this, Italic, "nbQuadraticPyramid" ), i3DPyramids, iQuadratic );
663 addWidget( createLabel( tr( "PRISMS_LAB" ), this, Italic ), i3DPrisms, iLabel );
664 addWidget( createField( this, Italic, "nbPrism" ), i3DPrisms, iTotal );
665 addWidget( createField( this, Italic, "nbLinearPrism" ), i3DPrisms, iLinear );
666 addWidget( createField( this, Italic, "nbQuadraticPrism" ), i3DPrisms, iQuadratic );
667 addWidget( createField( this, Italic, "nbBiQuadraticPrism" ), i3DPrisms, iBiQuadratic );
668 // --+ hexagonal prisms
669 addWidget( createLabel( tr( "HEX_PRISMS_LAB" ), this, Italic ), i3DHexaPrisms, iLabel );
670 addWidget( createField( this, Italic, "nbHexagonalPrism" ), i3DHexaPrisms, iTotal );
672 addWidget( createLabel( tr( "POLYHEDRONS_LAB" ), this, Italic ), i3DPolyhedrons, iLabel );
673 addWidget( createField( this, Italic, "nbPolyhedron" ), i3DPolyhedrons, iTotal );
676 QPushButton* loadBtn = new QPushButton( tr( "BUT_LOAD_MESH" ), this );
677 loadBtn->setAutoDefault( true );
678 connect( loadBtn, SIGNAL( clicked() ), this, SLOT( loadMesh() ) );
679 addWidget( loadBtn, iEnd, iSingle, 4 );
681 // additional layout set-up
682 l->setColumnStretch( iLabel, 0 );
683 l->setColumnStretch( iTotal, 5 );
684 l->setColumnStretch( iLinear, 5 );
685 l->setColumnStretch( iQuadratic, 5 );
686 l->setColumnStretch( iBiQuadratic, 5 );
687 l->setRowStretch( iElementsEnd, 5 );
689 // set initial values
696 SMESHGUI_BaseInfo::~SMESHGUI_BaseInfo()
701 \brief Show information on given object.
702 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
704 void SMESHGUI_BaseInfo::showInfo( const SMESH::SelectionProxy& proxy )
709 // then fill panel with data if object is not null
714 SMESH::MeshInfo info = proxy.meshInfo();
718 widget( iName, iSingle )->setProperty( "text", proxy.name() );
721 SMESH::SelectionProxy::Type type = proxy.type();
722 if ( type == SMESH::SelectionProxy::Mesh )
724 typeName = tr( "OBJECT_MESH" );
726 else if ( type == SMESH::SelectionProxy::Submesh )
728 typeName = tr( "OBJECT_SUBMESH" );
730 else if ( type >= SMESH::SelectionProxy::Group )
732 switch( proxy.groupElementType() )
734 case SMESH::NODE: typeName = tr( "OBJECT_GROUP_NODES" ); break;
735 case SMESH::EDGE: typeName = tr( "OBJECT_GROUP_EDGES" ); break;
736 case SMESH::FACE: typeName = tr( "OBJECT_GROUP_FACES" ); break;
737 case SMESH::VOLUME: typeName = tr( "OBJECT_GROUP_VOLUMES" ); break;
738 case SMESH::ELEM0D: typeName = tr( "OBJECT_GROUP_0DELEMS" ); break;
739 case SMESH::BALL: typeName = tr( "OBJECT_GROUP_BALLS" ); break;
740 default: typeName = tr( "OBJECT_GROUP" ); break;
743 if ( type == SMESH::SelectionProxy::GroupStd )
744 subType = tr( "OBJECT_GROUP_STANDALONE" );
745 else if ( type == SMESH::SelectionProxy::GroupGeom )
746 subType = tr( "OBJECT_GROUP_GEOM" );
747 else if ( type == SMESH::SelectionProxy::GroupFilter )
748 subType = tr( "OBJECT_GROUP_FILTER" );
749 if ( !subType.isEmpty() )
750 typeName = QString( "%1 %2" ).arg( typeName, subType );
752 widget( iObject, iSingle )->setProperty( "text", typeName );
755 uint nbNodes = info[SMDSEntity_Node];
756 widget( iNodes, iTotal )->setProperty( "value", nbNodes );
759 // - 0D elements info
760 uint nb0d = info[SMDSEntity_0D];
761 widget( i0D, iTotal )->setProperty( "value", nb0d );
763 uint nbBalls = info[SMDSEntity_Ball];
764 widget( iBalls, iTotal )->setProperty( "value", nbBalls );
765 // - 1D elements info
766 uint nb1dLin = info[SMDSEntity_Edge];
767 uint nb1dQua = info[SMDSEntity_Quad_Edge];
768 uint nb1d = nb1dLin + nb1dQua;
769 widget( i1D, iLinear )->setProperty( "value", nb1dLin );
770 widget( i1D, iQuadratic )->setProperty( "value", nb1dQua );
771 widget( i1D, iTotal )->setProperty( "value", nb1d );
772 // - 2D elements info
774 uint nbTriLin = info[SMDSEntity_Triangle];
775 uint nbTriQua = info[SMDSEntity_Quad_Triangle];
776 uint nbTriBiq = info[SMDSEntity_BiQuad_Triangle];
777 uint nbTri = nbTriLin + nbTriQua + nbTriBiq;
778 widget( i2DTriangles, iLinear )->setProperty( "value", nbTriLin );
779 widget( i2DTriangles, iQuadratic )->setProperty( "value", nbTriQua );
780 widget( i2DTriangles, iBiQuadratic )->setProperty( "value", nbTriBiq );
781 widget( i2DTriangles, iTotal )->setProperty( "value", nbTri );
783 uint nbQuadLin = info[SMDSEntity_Quadrangle];
784 uint nbQuadQua = info[SMDSEntity_Quad_Quadrangle];
785 uint nbQuadBiq = info[SMDSEntity_BiQuad_Quadrangle];
786 uint nbQuad = nbQuadLin + nbQuadQua + nbQuadBiq;
787 widget( i2DQuadrangles, iLinear )->setProperty( "value", nbQuadLin );
788 widget( i2DQuadrangles, iQuadratic )->setProperty( "value", nbQuadQua );
789 widget( i2DQuadrangles, iBiQuadratic )->setProperty( "value", nbQuadBiq );
790 widget( i2DQuadrangles, iTotal )->setProperty( "value", nbQuad );
792 uint nbPolyLin = info[SMDSEntity_Polygon];
793 uint nbPolyQua = info[SMDSEntity_Quad_Polygon];
794 uint nbPoly = nbPolyLin + nbPolyQua;
795 widget( i2DPolygons, iLinear )->setProperty( "value", nbPolyLin );
796 widget( i2DPolygons, iQuadratic )->setProperty( "value", nbPolyQua );
797 widget( i2DPolygons, iTotal )->setProperty( "value", nbPoly );
799 uint nb2dLin = nbTriLin + nbQuadLin + nbPolyLin;
800 uint nb2dQua = nbTriQua + nbQuadQua + nbPolyQua;
801 uint nb2dBiq = nbTriBiq + nbQuadBiq;
802 uint nb2d = nb2dLin + nb2dQua + nb2dBiq;
803 widget( i2D, iLinear )->setProperty( "value", nb2dLin );
804 widget( i2D, iQuadratic )->setProperty( "value", nb2dQua );
805 widget( i2D, iBiQuadratic )->setProperty( "value", nb2dBiq );
806 widget( i2D, iTotal )->setProperty( "value", nb2d );
807 // - 3D elements info
809 uint nbTetraLin = info[SMDSEntity_Tetra];
810 uint nbTetraQua = info[SMDSEntity_Quad_Tetra];
811 uint nbTetra = nbTetraLin + nbTetraQua;
812 widget( i3DTetrahedrons, iLinear )->setProperty( "value", nbTetraLin );
813 widget( i3DTetrahedrons, iQuadratic )->setProperty( "value", nbTetraQua );
814 widget( i3DTetrahedrons, iTotal )->setProperty( "value", nbTetra );
816 uint nbHexaLin = info[SMDSEntity_Hexa];
817 uint nbHexaQua = info[SMDSEntity_Quad_Hexa];
818 uint nbHexaBiq = info[SMDSEntity_TriQuad_Hexa];
819 uint nbHexa = nbHexaLin + nbHexaQua + nbHexaBiq;
820 widget( i3DHexahedrons, iLinear )->setProperty( "value", nbHexaLin );
821 widget( i3DHexahedrons, iQuadratic )->setProperty( "value", nbHexaQua );
822 widget( i3DHexahedrons, iBiQuadratic )->setProperty( "value", nbHexaBiq );
823 widget( i3DHexahedrons, iTotal )->setProperty( "value", nbHexa );
825 uint nbPyraLin = info[SMDSEntity_Pyramid];
826 uint nbPyraQua = info[SMDSEntity_Quad_Pyramid];
827 uint nbPyra = nbPyraLin + nbPyraQua;
828 widget( i3DPyramids, iLinear )->setProperty( "value", nbPyraLin );
829 widget( i3DPyramids, iQuadratic )->setProperty( "value", nbPyraQua );
830 widget( i3DPyramids, iTotal )->setProperty( "value", nbPyra );
832 uint nbPentaLin = info[SMDSEntity_Penta];
833 uint nbPentaQua = info[SMDSEntity_Quad_Penta];
834 uint nbPentaBiq = info[SMDSEntity_BiQuad_Penta];
835 uint nbPenta = nbPentaLin + nbPentaQua + nbPentaBiq;
836 widget( i3DPrisms, iLinear )->setProperty( "value", nbPentaLin );
837 widget( i3DPrisms, iQuadratic )->setProperty( "value", nbPentaQua );
838 widget( i3DPrisms, iBiQuadratic )->setProperty( "value", nbPentaBiq );
839 widget( i3DPrisms, iTotal )->setProperty( "value", nbPenta );
840 // --+ hexagonal prisms
841 uint nbHexaPri = info[SMDSEntity_Hexagonal_Prism];
842 widget( i3DHexaPrisms, iTotal )->setProperty( "value", nbHexaPri );
844 uint nbPolyhedra = info[SMDSEntity_Polyhedra];
845 widget( i3DPolyhedrons, iTotal )->setProperty( "value", nbPolyhedra );
847 uint nb3dLin = nbTetraLin + nbHexaLin + nbPyraLin + nbPentaLin + nbHexaPri + nbPolyhedra;
848 uint nb3dQua = nbTetraQua + nbHexaQua + nbPyraQua + nbPentaQua;
849 uint nb3dBiq = nbHexaBiq + nbPentaBiq;
850 uint nb3d = nb3dLin + nb3dQua + nb3dBiq;
851 widget( i3D, iLinear )->setProperty( "value", nb3dLin );
852 widget( i3D, iQuadratic )->setProperty( "value", nb3dQua );
853 widget( i3D, iBiQuadratic )->setProperty( "value", nb3dBiq );
854 widget( i3D, iTotal )->setProperty( "value", nb3d );
856 uint nbElemLin = nb1dLin + nb2dLin + nb3dLin;
857 uint nbElemQua = nb1dQua + nb2dQua + nb3dQua;
858 uint nbElemBiq = nb2dBiq + nb3dBiq;
859 uint nbElem = nb0d + nbBalls + nb1d + nb2d + nb3d;
860 widget( iElementsTotal, iLinear )->setProperty( "value", nbElemLin );
861 widget( iElementsTotal, iQuadratic )->setProperty( "value", nbElemQua );
862 widget( iElementsTotal, iBiQuadratic )->setProperty( "value", nbElemBiq );
863 widget( iElementsTotal, iTotal )->setProperty( "value", nbElem );
865 // show 'Load' button if data was not loaded yet
866 widget( iEnd, iSingle )->setVisible( !proxy.isValid() );
868 // until data is loaded from study file, type of elements in a sub-mesh or group
869 // can be undefined in some cases
870 if ( !proxy.isValid() )
872 // two cases are possible:
873 // 1. type of 2D or 3D elements is unknown but their nb is OK (for a sub-mesh)
874 // 2. there is no info at all (for a group on geom or on filter)
875 if ( info.count( SMDSEntity_Node, SMDSEntity_Last ) > 0 ) // believe it is a sub-mesh
877 if ( nb2dLin + nb2dQua + nb2dBiq > 0 )
879 // we know nothing about triangles, quadranges and polygons
880 for ( int i = i2DTriangles; i < i2DEnd; i++ )
882 for ( int j = iTotal; j < iNbColumns; j++ )
884 if ( widget( i, j ) )
885 widget( i, j )->setProperty( "text", "?" );
888 // we don't know if elements are linear, quadratic or bi-quadratic
889 for ( int j = iLinear; j < iNbColumns; j++ )
891 if ( widget( i2D, j ) )
892 widget( i2D, j )->setProperty( "text", "?" );
893 if ( widget( iElementsTotal, j ) )
894 widget( iElementsTotal, j )->setProperty( "text", "?" );
897 else if ( nb3dLin + nb3dQua + nb3dBiq > 0 )
899 // we know nothing about tetras, hexas, etc.
900 for ( int i = i3DTetrahedrons; i < i3DEnd; i++ )
902 for ( int j = iTotal; j < iNbColumns; j++ )
904 if ( widget( i, j ) )
905 widget( i, j )->setProperty( "text", "?" );
908 // we don't know if elements are linear, quadratic or bi-quadratic
909 for ( int j = iLinear; j < iNbColumns; j++ )
911 if ( widget( i3D, j ) )
912 widget( i3D, j )->setProperty( "text", "?" );
913 if ( widget( iElementsTotal, j ) )
914 widget( iElementsTotal, j )->setProperty( "text", "?" );
920 // we know nothing about nodes :(
921 widget( iNodes, iTotal )->setProperty( "text", "?" );
922 // we know nothing about elements :(
923 for ( int i = iElementsTotal; i < iElementsEnd; i++ )
925 for ( int j = iTotal; j < iNbColumns; j++ )
927 if ( widget( i, j ) )
928 widget( i, j )->setProperty( "text", "?" );
937 \brief Update information in panel.
939 void SMESHGUI_BaseInfo::updateInfo()
945 \brief Load mesh from a study file.
947 void SMESHGUI_BaseInfo::loadMesh()
949 SUIT_OverrideCursor wc;
958 \brief Reset panel (clear all data).
960 void SMESHGUI_BaseInfo::clear()
963 widget( iName, iSingle )->setProperty( "text", QString() );
965 widget( iObject, iSingle )->setProperty( "text", QString() );
967 widget( iNodes, iTotal )->setProperty( "value", 0 );
969 for ( int i = iElementsTotal; i < iElementsEnd; i++ )
971 for ( int j = iTotal; j < iNbColumns; j++ )
973 if ( widget( i, j ) )
974 widget( i, j )->setProperty( "value", 0 );
977 // hide 'Load' button
978 widget( iEnd, iSingle )->setVisible( false );
982 \brief Register widget in a grid.
983 \param w Widget being added.
984 \param row Row index in a grid.
985 \param column Column index in a grid.
986 \param colspan Number of columns to span in a grid. Defaults to 1.
987 \return Just added widget.
989 QWidget* SMESHGUI_BaseInfo::addWidget( QWidget* w, int row, int column, int colspan )
991 if ( !myWidgets.contains( row ) )
992 myWidgets[row] = wlist();
993 myWidgets[row][column] = w;
994 dynamic_cast<QGridLayout*>( layout() )->addWidget( w, row, column, 1, colspan );
999 \brief Get registered widget.
1000 \param row Row index in a grid.
1001 \param column Column index in a grid.
1002 \return Widget stored in a given grid cell (0 if there's no widget).
1004 QWidget* SMESHGUI_BaseInfo::widget( int row, int column ) const
1006 return myWidgets.contains( row ) && myWidgets[row].contains( column ) ? myWidgets[row][column] : 0;
1010 \brief Get text value from registered widget.
1011 \param row Row index in a grid.
1012 \param column Column index in a grid.
1013 \return Value string (empty string if no label in given cell).
1015 QString SMESHGUI_BaseInfo::value( int row, int column ) const
1017 return widgetValue( widget( row, column ) );
1021 \brief Show/hide group(s) of widgets.
1022 \param startRow Starting grid row.
1023 \param lastRow Last grid row.
1024 \param on Visibility flag.
1026 void SMESHGUI_BaseInfo::setFieldsVisible( int startRow, int lastRow, bool on )
1028 startRow = qMax( 0, startRow );
1029 lastRow = qMin( lastRow, (int)iEnd );
1030 for ( int i = startRow; i <= lastRow; i++ )
1032 wlist widgets = myWidgets[i];
1033 foreach ( QWidget* w, widgets )
1034 w->setVisible( on );
1039 \brief Write information from panel to ouput stream.
1040 \param out Text stream output.
1042 void SMESHGUI_BaseInfo::saveInfo( QTextStream& out )
1045 QString title = tr( "BASE_INFO" );
1046 out << ruler( title.size() ) << endl;
1047 out << title << endl;
1048 out << ruler( title.size() ) << endl;
1053 out << tr( "NAME_LAB" ) << spacing() << value( iName, iSingle ) << endl;
1055 out << tr( "OBJECT_LAB" ) << spacing() << value( iObject, iSingle ) << endl;
1056 // - --- (separator)
1060 out << tr( "NODES_LAB" ) << spacing() << value( iNodes, iTotal ) << endl;
1061 // - --- (separator)
1065 QString lin = tr( "LINEAR_LAB" ) + ":" + spacing();
1066 QString qua = tr( "QUADRATIC_LAB" ) + ":" + spacing();
1067 QString biq = tr( "BI_QUADRATIC_LAB" ) + ":" + spacing();
1069 out << tr( "ELEMENTS_LAB" ) << spacing() << value( iElementsTotal, iTotal ) << endl;
1070 out << indent(1) << lin << value( iElementsTotal, iLinear ) << endl;
1071 out << indent(1) << qua << value( iElementsTotal, iQuadratic ) << endl;
1072 out << indent(1) << biq << value( iElementsTotal, iBiQuadratic ) << endl;
1073 // - --- (separator)
1075 // - 0D elements info
1076 out << indent(1) << tr( "0D_LAB" ) << spacing() << value( i0D, iTotal ) << endl;
1077 // - --- (separator)
1080 out << indent(1) << tr( "BALL_LAB" ) << spacing() << value( iBalls, iTotal ) << endl;
1081 // - --- (separator)
1083 // - 1D elements info
1084 out << indent(1) << tr( "1D_LAB" ) << spacing() << value( i1D, iTotal ) << endl;
1085 out << indent(2) << lin << value( i1D, iLinear ) << endl;
1086 out << indent(2) << qua << value( i1D, iQuadratic ) << endl;
1087 // - --- (separator)
1089 // - 2D elements info
1091 out << indent(1) << tr( "2D_LAB" ) << spacing() << value( i2D, iTotal ) << endl;
1092 out << indent(2) << lin << value( i2D, iLinear ) << endl;
1093 out << indent(2) << qua << value( i2D, iQuadratic ) << endl;
1094 out << indent(2) << biq << value( i2D, iBiQuadratic ) << endl;
1095 // - --- (separator)
1098 out << indent(2) << tr( "TRIANGLES_LAB" ) << spacing() << value( i2DTriangles, iTotal ) << endl;
1099 out << indent(3) << lin << value( i2DTriangles, iLinear ) << endl;
1100 out << indent(3) << qua << value( i2DTriangles, iQuadratic ) << endl;
1101 out << indent(3) << biq << value( i2DTriangles, iBiQuadratic ) << endl;
1103 out << indent(2) << tr( "QUADRANGLES_LAB" ) << spacing() << value( i2DQuadrangles, iTotal ) << endl;
1104 out << indent(3) << lin << value( i2DQuadrangles, iLinear ) << endl;
1105 out << indent(3) << qua << value( i2DQuadrangles, iQuadratic ) << endl;
1106 out << indent(3) << biq << value( i2DQuadrangles, iBiQuadratic ) << endl;
1108 out << indent(2) << tr( "POLYGONS_LAB" ) << spacing() << value( i2DPolygons, iTotal ) << endl;
1109 out << indent(3) << lin << value( i2DPolygons, iLinear ) << endl;
1110 out << indent(3) << qua << value( i2DPolygons, iQuadratic ) << endl;
1111 // - --- (separator)
1113 // - 3D elements info
1115 out << indent(1) << tr( "3D_LAB" ) << spacing() << value( i3D, iTotal ) << endl;
1116 out << indent(2) << lin << value( i3D, iLinear ) << endl;
1117 out << indent(2) << qua << value( i3D, iQuadratic ) << endl;
1118 out << indent(2) << biq << value( i3D, iBiQuadratic ) << endl;
1119 // - --- (separator)
1122 out << indent(2) << tr( "TETRAHEDRONS_LAB" ) << spacing() << value( i3DTetrahedrons, iTotal ) << endl;
1123 out << indent(3) << lin << value( i3DTetrahedrons, iLinear ) << endl;
1124 out << indent(3) << qua << value( i3DTetrahedrons, iQuadratic ) << endl;
1126 out << indent(2) << tr( "HEXAHEDONRS_LAB" ) << spacing() << value( i3DHexahedrons, iTotal ) << endl;
1127 out << indent(3) << lin << value( i3DHexahedrons, iLinear ) << endl;
1128 out << indent(3) << qua << value( i3DHexahedrons, iQuadratic ) << endl;
1129 out << indent(3) << biq << value( i3DHexahedrons, iBiQuadratic ) << endl;
1131 out << indent(2) << tr( "PYRAMIDS_LAB" ) << spacing() << value( i3DPyramids, iTotal ) << endl;
1132 out << indent(3) << lin << value( i3DPyramids, iLinear ) << endl;
1133 out << indent(3) << qua << value( i3DPyramids, iQuadratic ) << endl;
1135 out << indent(2) << tr( "PRISMS_LAB" ) << spacing() << value( i3DPrisms, iTotal ) << endl;
1136 out << indent(3) << lin << value( i3DPrisms, iLinear ) << endl;
1137 out << indent(3) << qua << value( i3DPrisms, iQuadratic ) << endl;
1138 out << indent(3) << biq << value( i3DPrisms, iBiQuadratic ) << endl;
1139 // --+ hexagonal prisms
1140 out << indent(2) << tr( "HEX_PRISMS_LAB" ) << spacing() << value( i3DHexaPrisms, iTotal ) << endl;
1142 out << indent(2) << tr( "POLYHEDRONS_LAB" ) << spacing() << value( i3DPolyhedrons, iTotal ) << endl;
1143 // - --- (separator)
1147 ////////////////////////////////////////////////////////////////////////////////
1148 /// \class InfoWriter
1149 /// \brief Base info writer class.
1151 ////////////////////////////////////////////////////////////////////////////////
1159 InfoWriter( bool = false );
1160 void write( const QString&, bool = false );
1161 void write( const QString&, const QString&, bool = false );
1162 void write( const QString&, int, bool = false );
1163 void write( const QString&, double, bool = false );
1164 void write( const QString&, const SMESH::XYZ&, bool = false );
1165 virtual void indent() {}
1166 virtual void unindent() {}
1167 virtual void separator() {}
1169 virtual void put( const QString&, const QString&, bool = false ) = 0;
1172 InfoWriter::InfoWriter( bool r ): myRecursive(r)
1174 myPrecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
1177 void InfoWriter::write( const QString& key, bool emphasize )
1179 put( key, QString(), emphasize );
1182 void InfoWriter::write( const QString& key, const QString& value, bool emphasize )
1184 put( key, value, emphasize );
1187 void InfoWriter::write( const QString& key, int value, bool emphasize )
1189 put( key, QString::number( value ), emphasize );
1192 void InfoWriter::write( const QString& key, double value, bool emphasize )
1194 put( key, QString::number( value, myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) ), emphasize );
1197 void InfoWriter::write( const QString& key, const SMESH::XYZ& value, bool emphasize )
1201 write( key, emphasize );
1203 write( "X", value.x() );
1204 write( "Y", value.y() );
1205 write( "Z", value.z() );
1211 vl << QString::number( value.x(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1212 vl << QString::number( value.y(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1213 vl << QString::number( value.z(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
1214 put( key, vl.join( ", " ), emphasize );
1218 ////////////////////////////////////////////////////////////////////////////////
1219 /// \class SimpleWriter
1220 /// \brief Base text writer.
1222 ////////////////////////////////////////////////////////////////////////////////
1224 class SimpleWriter: public InfoWriter
1234 void put( const QString&, const QString&, bool );
1235 virtual QString spacer() const;
1236 virtual QString decorate( const QString& ) const;
1237 virtual void dumpLine( const QString& ) = 0;
1240 SimpleWriter::SimpleWriter(): InfoWriter(false), myIndent(0)
1244 void SimpleWriter::indent()
1249 void SimpleWriter::unindent()
1251 myIndent = qMax( myIndent-1, 0 );
1254 void SimpleWriter::separator()
1259 QString SimpleWriter::spacer() const
1264 QString SimpleWriter::decorate( const QString& s ) const
1269 void SimpleWriter::put( const QString& key, const QString& value, bool emphasize )
1272 line += ::indent( spacer(), myIndent*4 );
1273 line += decorate( key );
1274 if ( !value.isEmpty() )
1277 line += emphasize ? decorate( value ) : value;
1282 ////////////////////////////////////////////////////////////////////////////////
1283 /// \class StreamWriter
1284 /// \brief Writer for QTextStream.
1286 ////////////////////////////////////////////////////////////////////////////////
1288 class StreamWriter: public SimpleWriter
1292 StreamWriter( QTextStream& );
1294 void dumpLine( const QString& );
1297 StreamWriter::StreamWriter( QTextStream& out ): SimpleWriter(), myOut(out)
1301 void StreamWriter::dumpLine( const QString& line )
1307 ////////////////////////////////////////////////////////////////////////////////
1308 /// \class TextWriter
1309 /// \brief Writer for QTextBrowser.
1311 ////////////////////////////////////////////////////////////////////////////////
1313 class TextWriter: public SimpleWriter
1315 QTextBrowser* myInfo;
1317 TextWriter( QTextBrowser* );
1319 QString spacer() const;
1320 QString decorate( const QString& ) const;
1321 void dumpLine( const QString& );
1324 TextWriter::TextWriter( QTextBrowser* w ): SimpleWriter(), myInfo(w)
1328 QString TextWriter::spacer() const
1333 QString TextWriter::decorate( const QString& s ) const
1338 void TextWriter::dumpLine( const QString& line )
1340 myInfo->append( line );
1343 ////////////////////////////////////////////////////////////////////////////////
1344 /// \class TreeWriter
1345 /// \brief Writer for QTreeWidget.
1347 ////////////////////////////////////////////////////////////////////////////////
1349 class TreeWriter: public InfoWriter
1351 QTreeWidget* myInfo;
1352 QTreeWidgetItem* myCurrentItem;
1353 TreeItemCreator* myCreator;
1355 TreeWriter( QTreeWidget*, TreeItemCreator* );
1360 void put( const QString&, const QString&, bool = false );
1363 TreeWriter::TreeWriter( QTreeWidget* w, TreeItemCreator* c ):
1364 InfoWriter(true), myInfo(w), myCurrentItem(0), myCreator(c)
1368 TreeWriter::~TreeWriter()
1373 void TreeWriter::put( const QString& key, const QString& value, bool emphasize )
1375 //std::string sss = myCurrentItem ? myCurrentItem->text(0).toStdString() : "";
1377 if ( emphasize ) options |= AllColumns;
1378 QTreeWidgetItem* item = myCreator->createItem( myCurrentItem, options );
1379 item->setText( 0, key );
1380 if ( !value.isEmpty() )
1382 QString val = value;
1383 if ( value.startsWith( "<a href" )) // connectivity encoded as: <a href = "nodes://host/1 2">1 2</a>
1385 int role = ( value[11] == 'n' ) ? NodeConnectivity : ElemConnectivity;
1386 val = value.mid( value.lastIndexOf( '>', -5 ) + 1 ); // ==> 1 2</a>
1388 item->setData( 1, TypeRole, role );
1390 item->setText( 1, val );
1394 void TreeWriter::indent()
1396 QTreeWidgetItem* item = myCurrentItem ? myCurrentItem : myInfo->invisibleRootItem();
1397 if ( item->childCount() > 0 )
1398 myCurrentItem = item->child( item->childCount()-1 );
1401 void TreeWriter::unindent()
1403 if ( myCurrentItem )
1404 myCurrentItem = myCurrentItem->parent();
1407 ////////////////////////////////////////////////////////////////////////////////
1408 /// \class SMESHGUI_ElemInfo
1409 /// \brief Base class for the mesh element information widget.
1411 /// Displays the detail information about given mesh node(s) or element(s).
1412 /// Default class does not provide working implementation but onle general
1413 /// functionalities; main work is done in sub-classes.
1414 ////////////////////////////////////////////////////////////////////////////////
1418 \param parent Parent widget. Defaults to 0.
1420 SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent ): SMESHGUI_Info( parent ), myWhat( ShowNone )
1422 myFrame = new QWidget( this );
1423 myExtra = new ExtraWidget( this );
1425 QVBoxLayout* vbl = new QVBoxLayout( this );
1426 vbl->setMargin( 0 );
1427 vbl->setSpacing( SPACING );
1428 vbl->addWidget( myFrame );
1429 vbl->addWidget( myExtra );
1431 connect( myExtra->prev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) );
1432 connect( myExtra->next, SIGNAL( clicked() ), this, SLOT( showNext() ) );
1440 SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
1445 \brief Show information on given node / element.
1446 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1447 \param id Mesh node / element ID.
1448 \param isElement If \c true, show element info; otherwise show node info.
1450 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, uint id, bool isElement )
1454 showInfo( proxy, ids, isElement );
1458 \brief Show information on given nodes / elements.
1459 \param proxy Object to compute information on (mesh, sub-mesh, group, ID source).
1460 \param ids Mesh nodes / elements IDs.
1461 \param isElement If \c true, show element info; otherwise show node info.
1463 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, QSet<uint> ids, bool isElement )
1471 QList<uint> newIds = ids.toList();
1473 int what = isElement ? ShowElements : ShowNodes;
1475 if ( myProxy == proxy && myIDs == newIds && myWhat == what )
1479 myProxy.refresh(); // try to re-initialize actor
1488 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1492 \brief Show information on given group.
1493 \param proxy Object to compute information on (group).
1495 void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy )
1497 if ( !proxy || proxy.groupElementType() == SMESH::ALL ) // null proxy or not a group
1503 showInfo( proxy, proxy.ids(), proxy.groupElementType() != SMESH::NODE );
1507 \brief Reset panel (clear all data).
1509 void SMESHGUI_ElemInfo::clear()
1518 \brief Get central area widget.
1519 \return Central widget.
1521 QWidget* SMESHGUI_ElemInfo::centralWidget() const
1527 \brief Get current mesh proxy object information is shown on.
1528 \return Current proxy.
1530 SMESH::SelectionProxy SMESHGUI_ElemInfo::proxy() const
1536 \brief Get current info mode.
1537 \return Current panel mode.
1539 int SMESHGUI_ElemInfo::what() const
1545 \brief Get title for given element type.
1546 \param type Mesh element type.
1547 \param multiple Use plural form. Defaults to \c false.
1548 \return Element type's title.
1550 QString SMESHGUI_ElemInfo::type2str( int type, bool multiple )
1556 title = multiple ? tr( "EDGES" ) : tr( "EDGE" ) ; break;
1558 title = multiple ? tr( "FACES" ) : tr( "FACE" ); break;
1559 case SMDSAbs_Volume:
1560 title = multiple ? tr( "VOLUMES" ) : tr( "VOLUME" ); break;
1561 case SMDSAbs_0DElement:
1562 title = multiple ? tr( "0D_ELEMENTS" ) : tr( "0D_ELEMENT" ); break;
1564 title = multiple ? tr( "BALL_ELEMENTS" ) : tr( "BALL" ); break;
1572 \brief Get title for given shape type.
1573 \param type Shape type.
1574 \return Shape type's title.
1576 QString SMESHGUI_ElemInfo::stype2str( int type )
1582 title = tr( "GEOM_VERTEX" ); break;
1584 title = tr( "GEOM_EDGE" ); break;
1586 title = tr( "GEOM_FACE" ); break;
1589 title = tr( "GEOM_SOLID" ); break;
1596 \brief Get title for given element type.
1597 \param type Mesh element type.
1598 \return Element type's title.
1600 QString SMESHGUI_ElemInfo::etype2str( int type )
1605 case SMESH::Entity_0D:
1606 title = tr( "SMESH_ELEM0D" ); break;
1607 case SMESH::Entity_Edge:
1608 title = tr( "SMESH_EDGE" ); break;
1609 case SMESH::Entity_Quad_Edge:
1610 title = tr( "SMESH_QUADRATIC_EDGE" ); break;
1611 case SMESH::Entity_Triangle:
1612 title = tr( "SMESH_TRIANGLE" ); break;
1613 case SMESH::Entity_Quad_Triangle:
1614 title = tr( "SMESH_QUADRATIC_TRIANGLE" ); break;
1615 case SMESH::Entity_BiQuad_Triangle:
1616 title = tr( "SMESH_BIQUADRATIC_TRIANGLE" ); break;
1617 case SMESH::Entity_Quadrangle:
1618 title = tr( "SMESH_QUADRANGLE" ); break;
1619 case SMESH::Entity_Quad_Quadrangle:
1620 title = tr( "SMESH_QUADRATIC_QUADRANGLE" ); break;
1621 case SMESH::Entity_BiQuad_Quadrangle:
1622 title = tr( "SMESH_BIQUADRATIC_QUADRANGLE" ); break;
1623 case SMESH::Entity_Polygon:
1624 title = tr( "SMESH_POLYGON" ); break;
1625 case SMESH::Entity_Quad_Polygon:
1626 title = tr( "SMESH_QUADRATIC_POLYGON" ); break;
1627 case SMESH::Entity_Tetra:
1628 title = tr( "SMESH_TETRAHEDRON" ); break;
1629 case SMESH::Entity_Quad_Tetra:
1630 title = tr( "SMESH_QUADRATIC_TETRAHEDRON" ); break;
1631 case SMESH::Entity_Pyramid:
1632 title = tr( "SMESH_PYRAMID" ); break;
1633 case SMESH::Entity_Quad_Pyramid:
1634 title = tr( "SMESH_QUADRATIC_PYRAMID" ); break;
1635 case SMESH::Entity_Hexa:
1636 title = tr( "SMESH_HEXAHEDRON" ); break;
1637 case SMESH::Entity_Quad_Hexa:
1638 title = tr( "SMESH_QUADRATIC_HEXAHEDRON" ); break;
1639 case SMESH::Entity_TriQuad_Hexa:
1640 title = tr( "SMESH_TRIQUADRATIC_HEXAHEDRON" ); break;
1641 case SMESH::Entity_Penta:
1642 title = tr( "SMESH_PENTA" ); break;
1643 case SMESH::Entity_Quad_Penta:
1644 title = tr( "SMESH_QUADRATIC_PENTAHEDRON" ); break;
1645 case SMESH::Entity_BiQuad_Penta:
1646 title = tr( "SMESH_BIQUADRATIC_PENTAHEDRON" ); break;
1647 case SMESH::Entity_Hexagonal_Prism:
1648 title = tr( "SMESH_HEX_PRISM" ); break;
1649 case SMESH::Entity_Polyhedra:
1650 title = tr( "SMESH_POLYEDRON" ); break;
1651 case SMESH::Entity_Quad_Polyhedra:
1652 title = tr( "SMESH_QUADRATIC_POLYEDRON" ); break;
1653 case SMESH::Entity_Ball:
1654 title = tr( "SMESH_BALL" ); break;
1662 \brief Get title for given quality control.
1663 \param type Mesh control type.
1664 \return Quality control's title.
1666 QString SMESHGUI_ElemInfo::ctrl2str( int control )
1671 case SMESH::FT_AspectRatio:
1672 title = tr( "ASPECTRATIO_ELEMENTS" ); break;
1673 case SMESH::FT_AspectRatio3D:
1674 title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
1675 case SMESH::FT_Warping:
1676 title = tr( "WARP_ELEMENTS" ); break;
1677 case SMESH::FT_MinimumAngle:
1678 title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
1679 case SMESH::FT_Taper:
1680 title = tr( "TAPER_ELEMENTS" ); break;
1681 case SMESH::FT_Skew:
1682 title = tr( "SKEW_ELEMENTS" ); break;
1683 case SMESH::FT_Area:
1684 title = tr( "AREA_ELEMENTS" ); break;
1685 case SMESH::FT_Volume3D:
1686 title = tr( "VOLUME_3D_ELEMENTS" ); break;
1687 case SMESH::FT_MaxElementLength2D:
1688 title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
1689 case SMESH::FT_MaxElementLength3D:
1690 title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
1691 case SMESH::FT_Length:
1692 title = tr( "LENGTH_EDGES" ); break;
1693 case SMESH::FT_Length2D:
1694 case SMESH::FT_Length3D:
1695 title = tr( "MIN_ELEM_EDGE" ); break;
1696 case SMESH::FT_BallDiameter:
1697 title = tr( "BALL_DIAMETER" ); break;
1705 \brief Write information on given mesh nodes / elements.
1706 \param writer Information writer.
1707 \param ids Nodes / elements IDs.
1709 void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
1714 bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
1715 int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ?
1716 SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
1719 SMESH::Connectivity connectivity;
1720 SMESH::Position position;
1723 foreach ( uint id, ids )
1725 writer->separator();
1727 if ( what() == ShowNodes )
1730 // - check that node exists
1731 if ( !proxy().hasNode( id ) )
1734 writer->write( tr( "NODE" ), (int)id, true );
1737 ok = proxy().nodeCoordinates( id, xyz );
1740 writer->write( tr( "COORDINATES" ), xyz );
1743 ok = proxy().nodeConnectivity( id, connectivity );
1746 if ( !connectivity.isEmpty() )
1748 writer->write( tr( "CONNECTIVITY" ) );
1750 for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
1752 QString formatted = formatConnectivity( connectivity, i );
1753 if ( !formatted.isEmpty() )
1754 writer->write( type2str( i, true ), formatted );
1760 writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
1764 ok = proxy().nodePosition( id, position );
1765 if ( ok && position.isValid() )
1767 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1769 if ( position.hasU() )
1770 writer->write( tr("U_POSITION"), position.u() );
1771 if ( position.hasV() )
1772 writer->write( tr("V_POSITION"), position.v() );
1775 // - groups node belongs to
1776 QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
1777 bool topCreated = false;
1778 foreach( SMESH::SelectionProxy group, groups )
1780 if ( group && !group.name().isEmpty() )
1784 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1788 writer->write( group.name().trimmed() ); // trim name
1792 int type = group.type();
1793 if ( type == SMESH::SelectionProxy::GroupStd )
1795 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1797 else if ( type == SMESH::SelectionProxy::GroupGeom )
1799 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1800 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1802 else if ( type == SMESH::SelectionProxy::GroupFilter )
1804 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1806 int size = group.size();
1808 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1809 QColor color = group.color();
1810 if ( color.isValid() )
1811 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1820 else if ( what() == ShowElements )
1822 // show element info
1823 // - check that element exists
1824 if ( !proxy().hasElement( id ) )
1827 int type = proxy().elementType( id );
1828 if ( type == SMESH::ALL )
1830 writer->write( type2str( type ), (int)id, true );
1833 type = proxy().elementEntityType( id );
1834 writer->write( tr( "TYPE" ), etype2str( type ) );
1836 if ( type == SMESH::Entity_Polyhedra ||
1837 type == SMESH::Entity_Quad_Polyhedra )
1840 ok = proxy().perFaceConnectivity( id, connectivity, nbNodes );
1841 if ( ok && !connectivity.isEmpty() )
1843 writer->write( tr( "NB_NODES" ), nbNodes );
1844 writer->write( tr( "CONNECTIVITY" ) );
1846 int nbFaces = connectivity.size();
1847 for ( int iF = 1; iF <= nbFaces; ++iF )
1849 QString formatted = formatConnectivity( connectivity, -iF );
1850 writer->write(( type2str( SMDSAbs_Face, 0 ) + " %1 / %2" ).arg( iF ).arg( nbFaces ),
1858 ok = proxy().elementConnectivity( id, connectivity );
1859 if ( ok && !connectivity.isEmpty() )
1861 QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
1862 if ( !formatted.isEmpty() )
1864 writer->write( tr( "NB_NODES" ), connectivity[ SMDSAbs_Node ].size() );
1865 writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
1870 ok = proxy().elementPosition( id, position );
1871 if ( ok && position.isValid() )
1873 writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
1876 ok = proxy().elementGravityCenter( id, xyz );
1879 writer->write( tr( "GRAVITY_CENTER" ), xyz );
1882 ok = proxy().elementNormal( id, xyz );
1885 writer->write( tr( "NORMAL_VECTOR" ), xyz );
1888 bool topCreated = false;
1889 for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
1891 QString ctrlTitle = ctrl2str( i );
1892 if ( ctrlTitle.isEmpty() )
1896 writer->write( tr( "CONTROLS" ) );
1901 if ( proxy().elementControl( id, i, cprecision, value ) )
1902 writer->write( ctrlTitle, value );
1906 // - groups element belongs to
1907 QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
1909 foreach( SMESH::SelectionProxy group, groups )
1911 if ( group && !group.name().isEmpty() )
1915 writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
1919 writer->write( group.name().trimmed() ); // trim name
1923 int type = group.type();
1924 if ( type == SMESH::SelectionProxy::GroupStd )
1926 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
1928 else if ( type == SMESH::SelectionProxy::GroupGeom )
1930 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
1931 writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
1933 else if ( type == SMESH::SelectionProxy::GroupFilter )
1935 writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
1937 int size = group.size();
1939 writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
1940 QColor color = group.color();
1941 if ( color.isValid() )
1942 writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
1955 \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
1956 \brief Show information on given mesh nodes / elements.
1958 This function has to be redefined in sub-classes.
1960 \param ids Nodes / elements IDs.
1964 \brief Internal clean-up (reset panel).
1966 Default implementation does nothing; the method has to be redefined
1967 in sub-classes to perform internal clean-up.
1969 void SMESHGUI_ElemInfo::clearInternal()
1974 \brief Show previous chunk of information.
1976 void SMESHGUI_ElemInfo::showPrevious()
1978 myIndex = qMax( 0, myIndex-1 );
1980 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1984 \brief Show next chunk of information.
1986 void SMESHGUI_ElemInfo::showNext()
1988 myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
1990 information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
1994 \brief Update control widget state.
1996 void SMESHGUI_ElemInfo::updateControls()
1998 myExtra->updateControls( myIDs.count(), myIndex );
2002 \brief Write information from panel to ouput stream.
2003 \param out Text stream output.
2005 void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
2008 QString title = tr( "ELEM_INFO" );
2009 out << ruler( title.size() ) << endl;
2010 out << title << endl;
2011 out << ruler( title.size() ) << endl;
2015 StreamWriter writer( out );
2016 writeInfo( &writer, myIDs );
2020 ////////////////////////////////////////////////////////////////////////////////
2021 /// \class SMESHGUI_SimpleElemInfo
2022 /// \brief Show mesh element information in the simple text area.
2023 ////////////////////////////////////////////////////////////////////////////////
2027 \param parent Parent widget. Defaults to 0.
2029 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
2030 : SMESHGUI_ElemInfo( parent )
2032 myInfo = new QTextBrowser( centralWidget() );
2033 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2035 l->addWidget( myInfo );
2037 connect( myInfo, SIGNAL( anchorClicked(QUrl)), this, SLOT( connectivityClicked( QUrl )));
2041 \brief Show mesh element information.
2042 \param ids Nodes / elements IDs.
2044 void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
2047 TextWriter writer( myInfo );
2048 writeInfo( &writer, ids );
2052 \brief Internal clean-up (reset widget)
2054 void SMESHGUI_SimpleElemInfo::clearInternal()
2059 void SMESHGUI_SimpleElemInfo::connectivityClicked(const QUrl & url)
2061 int type = ( url.scheme()[0] == 'n' ) ? NodeConnectivity : ElemConnectivity;
2062 QString ids = url.path(); // excess chars will be filtered off by SMESHGUI_IdValidator
2063 emit( itemInfo( type, ids ));
2066 ////////////////////////////////////////////////////////////////////////////////
2067 /// \class SMESHGUI_TreeElemInfo::ItemDelegate
2068 /// \brief Item delegate for tree mesh info widget.
2070 ////////////////////////////////////////////////////////////////////////////////
2072 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
2075 ItemDelegate( QObject* );
2076 QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
2083 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
2088 \brief Redefined from QItemDelegate.
2091 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
2093 QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
2094 if ( qobject_cast<QLineEdit*>( w ) )
2095 qobject_cast<QLineEdit*>( w )->setReadOnly( true );
2099 ////////////////////////////////////////////////////////////////////////////////
2100 /// \class SMESHGUI_TreeElemInfo::ItemCreator
2101 /// \brief Item creator for tree mesh info widget.
2103 ////////////////////////////////////////////////////////////////////////////////
2105 class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
2107 SMESHGUI_TreeElemInfo* myView;
2109 ItemCreator( SMESHGUI_TreeElemInfo* );
2110 QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
2115 \param view Parent view.
2118 SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
2123 \brief Create new tree item.
2124 \param parent Parent tree item.
2125 \param options Item options.
2126 \return New tree widget item.
2129 QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
2131 return myView->createItem( parent, options );
2134 ////////////////////////////////////////////////////////////////////////////////
2135 /// \class SMESHGUI_TreeElemInfo
2136 /// \brief Show mesh element information as the tree.
2137 ////////////////////////////////////////////////////////////////////////////////
2141 \param parent Parent widget. Defaults to 0.
2143 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
2144 : SMESHGUI_ElemInfo( parent )
2146 myInfo = new QTreeWidget( centralWidget() );
2147 myInfo->setColumnCount( 2 );
2148 myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
2149 myInfo->header()->setStretchLastSection( true );
2150 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2151 myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2153 myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2155 myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
2156 QVBoxLayout* l = new QVBoxLayout( centralWidget() );
2158 l->addWidget( myInfo );
2159 connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
2160 connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2161 connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
2165 \brief Show mesh element information.
2166 \param ids Nodes / elements IDs.
2168 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
2171 TreeWriter writer( myInfo, new ItemCreator( this ) );
2172 writeInfo( &writer, ids );
2176 \brief Show node information
2177 \param node mesh node for showing
2178 \param index index of current node
2179 \param nbNodes number of unique nodes in element
2180 \param parentItem parent item of tree
2182 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* node, int index,
2183 int nbNodes, QTreeWidgetItem* parentItem )
2185 // int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
2186 // // node number and ID
2187 // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
2188 // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
2189 // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
2190 // nodeItem->setData( 1, TypeRole, ElemConnectivity );
2191 // nodeItem->setData( 1, IdRole, node->GetID() );
2192 // nodeItem->setExpanded( false );
2193 // // node coordinates
2194 // QTreeWidgetItem* coordItem = createItem( nodeItem );
2195 // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
2196 // QTreeWidgetItem* xItem = createItem( coordItem );
2197 // xItem->setText( 0, "X" );
2198 // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2199 // QTreeWidgetItem* yItem = createItem( coordItem );
2200 // yItem->setText( 0, "Y" );
2201 // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2202 // QTreeWidgetItem* zItem = createItem( coordItem );
2203 // zItem->setText( 0, "Z" );
2204 // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
2205 // // node connectivity
2206 // QTreeWidgetItem* nconItem = createItem( nodeItem );
2207 // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
2208 // Connectivity connectivity = nodeConnectivity( node );
2209 // if ( !connectivity.isEmpty() ) {
2210 // QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
2211 // if ( !con.isEmpty() ) {
2212 // QTreeWidgetItem* i = createItem( nconItem );
2213 // i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
2214 // i->setText( 1, con );
2216 // con = formatConnectivity( connectivity, SMDSAbs_Edge );
2217 // if ( !con.isEmpty() ) {
2218 // QTreeWidgetItem* i = createItem( nconItem );
2219 // i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
2220 // i->setText( 1, con );
2221 // i->setData( 1, TypeRole, NodeConnectivity );
2223 // con = formatConnectivity( connectivity, SMDSAbs_Ball );
2224 // if ( !con.isEmpty() ) {
2225 // QTreeWidgetItem* i = createItem( nconItem );
2226 // i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
2227 // i->setText( 1, con );
2228 // i->setData( 1, TypeRole, NodeConnectivity );
2230 // con = formatConnectivity( connectivity, SMDSAbs_Face );
2231 // if ( !con.isEmpty() ) {
2232 // QTreeWidgetItem* i = createItem( nconItem );
2233 // i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
2234 // i->setText( 1, con );
2235 // i->setData( 1, TypeRole, NodeConnectivity );
2237 // con = formatConnectivity( connectivity, SMDSAbs_Volume );
2238 // if ( !con.isEmpty() ) {
2239 // QTreeWidgetItem* i = createItem( nconItem );
2240 // i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
2241 // i->setText( 1, con );
2242 // i->setData( 1, TypeRole, NodeConnectivity );
2247 \brief Internal clean-up (reset widget)
2249 void SMESHGUI_TreeElemInfo::clearInternal()
2256 \brief Create new item and add it to the tree.
2257 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2258 \param options Item flags. Defaults to 0 (none).
2259 \return New tree widget item.
2261 QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
2263 QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
2264 setTreeItemAttributes( item, options | Expanded | Editable );
2266 if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
2268 QString resName = expandedResource( parent );
2269 parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
2275 void SMESHGUI_TreeElemInfo::contextMenuEvent( QContextMenuEvent* e )
2277 QList< QTreeWidgetItem* > widgets = myInfo->selectedItems();
2278 if ( widgets.isEmpty() ) return;
2279 QTreeWidgetItem* aTreeItem = widgets.first();
2280 int type = aTreeItem->data( 1, TypeRole ).toInt();
2281 if (( type == ElemConnectivity || type == NodeConnectivity ) &&
2282 ( !aTreeItem->text( 1 ).isEmpty() ))
2285 QAction* a = menu.addAction( tr( "SHOW_ITEM_INFO" ));
2286 if ( menu.exec( e->globalPos() ) == a )
2287 emit( itemInfo( type, aTreeItem->text( 1 )) );
2291 void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int theColumn )
2294 int type = theItem->data( 1, TypeRole ).toInt();
2295 emit( itemInfo( type, theItem->text( 1 )) );
2299 void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
2302 SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
2305 QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
2307 return QString("Expanded_") + ( what()==ShowElements ? "E_" : "N_" ) + theItem->text(0);
2310 ////////////////////////////////////////////////////////////////////////////////
2311 /// \class InfoComputor
2312 /// \brief Mesh information computor.
2315 /// The class is created for different computation operations. Currently it is
2316 /// used to compute size and number of underlying nodes for given group.
2317 ////////////////////////////////////////////////////////////////////////////////
2321 \param parent Parent object.
2322 \param proxy Object to compute information on (group).
2323 \param item Tree widget item, referenced by this computer.
2324 \param operation Value to compute.
2327 InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
2328 : QObject( parent ), myProxy( proxy ), myOperation( operation )
2333 \brief Compute requested information.
2336 void InfoComputor::compute()
2340 SUIT_OverrideCursor wc;
2341 switch ( myOperation )
2344 myProxy.size( true ); // force size computation
2348 myProxy.nbNodes( true ); // force size computation
2357 ////////////////////////////////////////////////////////////////////////////////
2358 /// \class SMESHGUI_AddInfo
2359 /// \brief Show additional information on selected object.
2361 /// Displays an additional information about selected object: mesh, sub-mesh
2364 /// \todo Rewrite saveInfo() method to print all data, not currently shown only.
2365 ////////////////////////////////////////////////////////////////////////////////
2369 \param parent Parent widget. Defaults to 0.
2371 SMESHGUI_AddInfo::SMESHGUI_AddInfo( QWidget* parent ): SMESHGUI_Info( parent )
2373 QVBoxLayout* l = new QVBoxLayout( this );
2375 l->setSpacing( SPACING );
2377 myTree = new QTreeWidget( this );
2379 myTree->setColumnCount( 2 );
2380 myTree->header()->setStretchLastSection( true );
2381 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
2382 myTree->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
2384 myTree->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
2386 myTree->header()->hide();
2388 l->addWidget( myTree );
2394 SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
2399 \brief Show information on given object.
2400 \param proxy Object to show information on (mesh, sub-mesh, group).
2402 void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
2405 setProperty( "group_index", 0 );
2406 setProperty( "submesh_index", 0 );
2407 myComputors.clear();
2410 // then fill panel with data if object is not null
2416 QTreeWidgetItem* nameItem = createItem( 0, Bold | AllColumns );
2417 nameItem->setText( 0, tr( "NAME" ) );
2418 nameItem->setText( 1, proxy.name() );
2421 if ( proxy.type() == SMESH::SelectionProxy::Mesh )
2422 meshInfo( proxy, nameItem );
2423 else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
2424 subMeshInfo( proxy, nameItem );
2425 else if ( proxy.type() >= SMESH::SelectionProxy::Group )
2426 groupInfo( proxy, nameItem );
2431 \brief Update information in panel.
2433 void SMESHGUI_AddInfo::updateInfo()
2435 showInfo( myProxy );
2439 \brief Reset panel (clear all data).
2441 void SMESHGUI_AddInfo::clear()
2447 \brief Create new item and add it to the tree.
2448 \param parent Parent tree widget item. Defaults to 0 (top-level item).
2449 \param options Item flags. Defaults to 0 (none).
2450 \return New tree widget item.
2452 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
2454 QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) :
2455 new QTreeWidgetItem( myTree->invisibleRootItem() );
2456 setTreeItemAttributes( item, options | Expanded );
2461 \brief Show information on mesh.
2462 \param proxy Proxy object (mesh).
2463 \param parent Parent tree item.
2465 void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2470 QString shapeName = proxy.shapeName();
2471 SMESH::MedInfo inf = proxy.medFileInfo();
2474 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2475 typeItem->setText( 0, tr( "TYPE" ) );
2476 if ( !shapeName.isEmpty() )
2478 typeItem->setText( 1, tr( "MESH_ON_GEOMETRY" ) );
2480 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2481 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2482 gobjItem->setText( 1, shapeName );
2484 else if ( inf.isValid() )
2486 typeItem->setText( 1, tr( "MESH_FROM_FILE" ) );
2487 // med file information
2488 QTreeWidgetItem* fileItem = createItem( parent, Bold );
2489 fileItem->setText( 0, tr( "FILE_NAME" ) );
2490 fileItem->setText( 1, inf.fileName() );
2491 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2492 sizeItem->setText( 0, tr( "FILE_SIZE" ) );
2493 sizeItem->setText( 1, QString::number( inf.size() ) );
2494 QTreeWidgetItem* versionItem = createItem( parent, Bold );
2495 versionItem->setText( 0, tr( "FILE_VERSION" ) );
2496 versionItem->setText( 1, inf.version() != "0" ? inf.version() : tr( "VERSION_UNKNOWN" ) );
2500 typeItem->setText( 1, tr( "STANDALONE_MESH" ) );
2504 myGroups = proxy.groups();
2508 mySubMeshes = proxy.submeshes();
2513 \brief Show information on sub-mesh.
2514 \param proxy Proxy object (sub-mesh).
2515 \param parent Parent tree item.
2517 void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2522 bool isShort = parent->parent() != 0;
2527 SMESH::SelectionProxy meshProxy = proxy.mesh();
2530 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2531 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2532 nameItem->setText( 1, meshProxy.name() );
2537 QString shapeName = proxy.shapeName();
2538 if ( !shapeName.isEmpty() )
2540 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2541 gobjItem->setText( 1, shapeName );
2546 \brief Show information on group.
2547 \param proxy Proxy object (group).
2548 \param parent Parent tree item.
2550 void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
2555 bool isShort = parent->parent() != 0;
2560 SMESH::SelectionProxy meshProxy = proxy.mesh();
2563 QTreeWidgetItem* nameItem = createItem( parent, Bold );
2564 nameItem->setText( 0, tr( "PARENT_MESH" ) );
2565 nameItem->setText( 1, meshProxy.name() );
2570 SMESH::SelectionProxy::Type type = proxy.type();
2571 QTreeWidgetItem* typeItem = createItem( parent, Bold );
2572 typeItem->setText( 0, tr( "TYPE" ) );
2573 if ( type == SMESH::SelectionProxy::GroupStd )
2575 typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
2577 else if ( type == SMESH::SelectionProxy::GroupGeom )
2579 typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
2581 QTreeWidgetItem* gobjItem = createItem( parent, Bold );
2582 gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
2583 gobjItem->setText( 1, proxy.shapeName() );
2585 else if ( type == SMESH::SelectionProxy::GroupFilter )
2587 typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
2591 int etype = proxy.groupElementType();
2594 QString typeName = tr( "UNKNOWN" );
2598 typeName = tr( "NODE" );
2601 typeName = tr( "EDGE" );
2604 typeName = tr( "FACE" );
2607 typeName = tr( "VOLUME" );
2610 typeName = tr( "0DELEM" );
2613 typeName = tr( "BALL" );
2618 QTreeWidgetItem* etypeItem = createItem( parent, Bold );
2619 etypeItem->setText( 0, tr( "ENTITY_TYPE" ) );
2620 etypeItem->setText( 1, typeName );
2624 // note: size is not computed for group on filter for performance reasons, see IPAL52831
2625 bool meshLoaded = proxy.isMeshLoaded();
2626 int size = proxy.size();
2628 QTreeWidgetItem* sizeItem = createItem( parent, Bold );
2629 sizeItem->setText( 0, tr( "SIZE" ) );
2632 sizeItem->setText( 1, QString::number( size ) );
2636 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2637 myTree->setItemWidget( sizeItem, 1, btn );
2638 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpSize );
2639 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2640 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2641 myComputors.append( comp );
2645 QTreeWidgetItem* colorItem = createItem( parent, Bold );
2646 colorItem->setText( 0, tr( "COLOR" ) );
2647 colorItem->setBackground( 1, proxy.color() );
2649 // nb of underlying nodes
2650 if ( etype != SMESH::NODE )
2652 QTreeWidgetItem* nodesItem = createItem( parent, Bold );
2653 nodesItem->setText( 0, tr( "NB_NODES" ) );
2655 int nbNodes = proxy.nbNodes();
2658 nodesItem->setText( 1, QString::number( nbNodes ) );
2662 QPushButton* btn = new QPushButton( meshLoaded ? tr( "COMPUTE" ) : tr( "LOAD" ), this );
2663 myTree->setItemWidget( nodesItem, 1, btn );
2664 InfoComputor* comp = new InfoComputor( this, proxy, InfoComputor::GrpNbNodes );
2665 connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
2666 connect( comp, SIGNAL( computed() ), this, SLOT( updateInfo() ) );
2667 myComputors.append( comp );
2673 \brief Update information on child groups.
2675 void SMESHGUI_AddInfo::showGroups()
2677 // remove all computors
2678 myComputors.clear();
2680 // tree root should be the first top level item
2681 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2685 int idx = property( "group_index" ).toInt();
2687 // find sub-meshes top-level container item
2688 QTreeWidgetItem* itemGroups = 0;
2689 for ( int i = 0; i < parent->childCount() && !itemGroups; i++ )
2691 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == GroupsId )
2693 itemGroups = parent->child( i );
2695 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemGroups, 1 ) );
2697 extra->updateControls( myGroups.count(), idx );
2698 // clear: remove all group items
2699 while ( itemGroups->childCount() )
2700 delete itemGroups->child( 0 );
2704 QMap<int, QTreeWidgetItem*> grpItems;
2705 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
2707 SMESH::SelectionProxy grp = myGroups[i];
2711 int grpType = grp.groupElementType();
2713 // create top-level groups container item if it does not exist
2716 itemGroups = createItem( parent, Bold | AllColumns );
2717 itemGroups->setText( 0, tr( "GROUPS" ) );
2718 itemGroups->setData( 0, Qt::UserRole, GroupsId );
2720 // if necessary, create extra widget to show information by chunks
2721 if ( myGroups.count() > blockSize() )
2723 ExtraWidget* extra = new ExtraWidget( this, true );
2724 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousGroups() ) );
2725 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextGroups() ) );
2726 myTree->setItemWidget( itemGroups, 1, extra );
2727 extra->updateControls( myGroups.count(), idx );
2731 // create container item corresponding to particular element type
2732 if ( !grpItems.contains( grpType ) )
2734 grpItems[ grpType ] = createItem( itemGroups, Bold | AllColumns );
2735 grpItems[ grpType ]->setText( 0, tr( QString( "GROUPS_%1" ).arg( grpType ).toLatin1().constData() ) );
2736 itemGroups->insertChild( grpType-1, grpItems[ grpType ] ); // -1 needed since 0 corresponds to SMESH::ALL
2740 QTreeWidgetItem* nameItem = createItem( grpItems[ grpType ] );
2741 nameItem->setText( 0, grp.name().trimmed() ); // trim name
2744 groupInfo( grp, nameItem );
2749 \brief Update information on child sub-meshes.
2751 void SMESHGUI_AddInfo::showSubMeshes()
2753 // tree root should be the first top level item
2754 QTreeWidgetItem* parent = myTree->topLevelItemCount() > 0 ? myTree->topLevelItem( 0 ) : 0;
2758 int idx = property( "submesh_index" ).toInt();
2760 // find sub-meshes top-level container item
2761 QTreeWidgetItem* itemSubMeshes = 0;
2762 for ( int i = 0; i < parent->childCount() && !itemSubMeshes; i++ )
2764 if ( parent->child( i )->data( 0, Qt::UserRole ).toInt() == SubMeshesId )
2766 itemSubMeshes = parent->child( i );
2768 ExtraWidget* extra = dynamic_cast<ExtraWidget*>( myTree->itemWidget( itemSubMeshes, 1 ) );
2770 extra->updateControls( mySubMeshes.count(), idx );
2771 // clear: remove all sub-mesh items
2772 while ( itemSubMeshes->childCount() )
2773 delete itemSubMeshes->child( 0 );
2777 QMap<int, QTreeWidgetItem*> smItems;
2778 for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
2780 SMESH::SelectionProxy sm = mySubMeshes[i];
2784 int smType = sm.shapeType();
2787 else if ( smType == GEOM::COMPSOLID )
2788 smType = GEOM::COMPOUND;
2790 // create top-level sub-meshes container item if it does not exist
2791 if ( !itemSubMeshes )
2793 itemSubMeshes = createItem( parent, Bold | AllColumns );
2794 itemSubMeshes->setText( 0, tr( "SUBMESHES" ) );
2795 itemSubMeshes->setData( 0, Qt::UserRole, SubMeshesId );
2797 // if necessary, create extra widget to show information by chunks
2798 if ( mySubMeshes.count() > blockSize() )
2800 ExtraWidget* extra = new ExtraWidget( this, true );
2801 connect( extra->prev, SIGNAL( clicked() ), this, SLOT( showPreviousSubMeshes() ) );
2802 connect( extra->next, SIGNAL( clicked() ), this, SLOT( showNextSubMeshes() ) );
2803 myTree->setItemWidget( itemSubMeshes, 1, extra );
2804 extra->updateControls( mySubMeshes.count(), idx );
2808 // create container item corresponding to particular shape type
2809 if ( !smItems.contains( smType ) )
2811 smItems[ smType ] = createItem( itemSubMeshes, Bold | AllColumns );
2812 smItems[ smType ]->setText( 0, tr( QString( "SUBMESHES_%1" ).arg( smType ).toLatin1().constData() ) );
2813 itemSubMeshes->insertChild( smType, smItems[ smType ] );
2817 QTreeWidgetItem* nameItem = createItem( smItems[ smType ] );
2818 nameItem->setText( 0, sm.name().trimmed() ); // trim name
2821 subMeshInfo( sm, nameItem );
2826 \brief Show previous chunk of information on child groups.
2828 void SMESHGUI_AddInfo::showPreviousGroups()
2830 int idx = property( "group_index" ).toInt();
2831 setProperty( "group_index", idx-1 );
2836 \brief Show next chunk of information on child groups.
2838 void SMESHGUI_AddInfo::showNextGroups()
2840 int idx = property( "group_index" ).toInt();
2841 setProperty( "group_index", idx+1 );
2846 \brief Show previous chunk of information on child sub-meshes.
2848 void SMESHGUI_AddInfo::showPreviousSubMeshes()
2850 int idx = property( "submesh_index" ).toInt();
2851 setProperty( "submesh_index", idx-1 );
2856 \brief Show next chunk of information on child sub-meshes.
2858 void SMESHGUI_AddInfo::showNextSubMeshes()
2860 int idx = property( "submesh_index" ).toInt();
2861 setProperty( "submesh_index", idx+1 );
2866 \brief Write information from panel to ouput stream.
2867 \param out Text stream output.
2869 void SMESHGUI_AddInfo::saveInfo( QTextStream &out )
2872 QString title = tr( "ADDITIONAL_INFO" );
2873 out << ruler( title.size() ) << endl;
2874 out << title << endl;
2875 out << ruler( title.size() ) << endl;
2879 QTreeWidgetItemIterator it( myTree );
2882 if ( !( ( *it )->text(0) ).isEmpty() )
2884 out << indent( itemDepth( *it ) ) << ( *it )->text(0);
2885 if ( ( *it )->text(0) == tr( "COLOR" ) )
2886 out << ":" << spacing() << ( ( ( *it )->background(1) ).color() ).name();
2887 else if ( !( ( *it )->text(1) ).isEmpty() )
2888 out << ":" << spacing() << ( *it )->text(1);
2896 ////////////////////////////////////////////////////////////////////////////////
2897 /// \class GroupCombo
2898 /// \brief Customized combo box to manage list of mesh groups.
2900 ////////////////////////////////////////////////////////////////////////////////
2902 class GroupCombo: public QComboBox
2904 class Item: public QStandardItem
2907 SMESH::SelectionProxy myGroup;
2908 Item( const SMESH::SelectionProxy& group )
2911 setText( myGroup.name() );
2913 SMESH::SelectionProxy group()
2919 SMESH::SelectionProxy myProxy;
2922 GroupCombo( QWidget* );
2923 void setSource( const SMESH::SelectionProxy& );
2924 SMESH::SelectionProxy currentGroup() const;
2929 \param parent Parent widget.
2932 GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
2934 setModel( new QStandardItemModel( this ) );
2938 \brief Set mesh source.
2939 \param obj Mesh source.
2942 void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
2944 if ( myProxy == proxy )
2949 bool blocked = blockSignals( true );
2950 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2955 if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
2957 QList<SMESH::SelectionProxy> groups = myProxy.groups();
2958 for ( int i = 0; i < groups.count(); ++i )
2962 QString name = groups[i].name();
2963 if ( !name.isEmpty() )
2964 m->appendRow( new Item( groups[i] ) );
2967 setCurrentIndex( -1 ); // for performance reasons
2969 else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
2971 m->appendRow( new Item( myProxy ) );
2972 setCurrentIndex( 0 );
2976 blockSignals( blocked );
2980 \brief Get currently selected group.
2981 \return Selected group.
2984 SMESH::SelectionProxy GroupCombo::currentGroup() const
2986 SMESH::SelectionProxy group;
2987 QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
2988 if ( currentIndex() >= 0 )
2989 group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
2993 ////////////////////////////////////////////////////////////////////////////////
2994 /// \class SMESHGUI_MeshInfoDlg
2995 /// \brief Mesh information dialog box
2997 /// \todo Move all business logic for element info to SMESHGUI_ElemInfo class.
2998 /// \todo Add selection button to reactivate selection on move from other dlg.
2999 ////////////////////////////////////////////////////////////////////////////////
3003 \param parent Parent widget.
3004 \param page Dialog page to show at start-up. Defaults to \c BaseInfo.
3006 SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page )
3010 setAttribute( Qt::WA_DeleteOnClose, true );
3011 setWindowTitle( tr( "MESH_INFO" ) );
3012 setSizeGripEnabled( true );
3014 myTabWidget = new QTabWidget( this );
3018 myBaseInfo = new SMESHGUI_BaseInfo( myTabWidget );
3019 myTabWidget->addTab( myBaseInfo, tr( "BASE_INFO" ) );
3023 QWidget* w = new QWidget( myTabWidget );
3025 myMode = new QButtonGroup( this );
3026 myMode->addButton( new QRadioButton( tr( "NODE_MODE" ), w ), NodeMode );
3027 myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode );
3028 myMode->addButton( new QRadioButton( tr( "GROUP_MODE" ), w ), GroupMode );
3029 myMode->button( NodeMode )->setChecked( true );
3030 myID = new QLineEdit( w );
3031 myID->setValidator( new SMESHGUI_IdValidator( this ) );
3032 myGroups = new GroupCombo( w );
3033 QStackedWidget* stack = new QStackedWidget( w );
3034 stack->addWidget( myID );
3035 stack->addWidget( myGroups );
3036 myIDPreviewCheck = new QCheckBox( tr( "SHOW_IDS" ), w );
3037 myIDPreview = new SMESHGUI_IdPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) );
3039 int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 );
3040 mode = qMin( 1, qMax( 0, mode ) );
3043 myElemInfo = new SMESHGUI_SimpleElemInfo( w );
3045 myElemInfo = new SMESHGUI_TreeElemInfo( w );
3046 stack->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
3048 QGridLayout* elemLayout = new QGridLayout( w );
3049 elemLayout->setMargin( MARGIN );
3050 elemLayout->setSpacing( SPACING );
3051 elemLayout->addWidget( myMode->button( NodeMode ), 0, 0 );
3052 elemLayout->addWidget( myMode->button( ElemMode ), 0, 1 );
3053 elemLayout->addWidget( myMode->button( GroupMode ), 0, 2 );
3054 elemLayout->addWidget( stack, 0, 3 );
3055 elemLayout->addWidget( myIDPreviewCheck, 1, 0, 1, 4 );
3056 elemLayout->addWidget( myElemInfo, 2, 0, 1, 4 );
3058 myTabWidget->addTab( w, tr( "ELEM_INFO" ) );
3062 myAddInfo = new SMESHGUI_AddInfo( myTabWidget );
3063 myTabWidget->addTab( myAddInfo, tr( "ADDITIONAL_INFO" ) );
3067 myCtrlInfo = new SMESHGUI_CtrlInfo( myTabWidget );
3068 myTabWidget->addTab( myCtrlInfo, tr( "CTRL_INFO" ) );
3072 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3073 okBtn->setAutoDefault( true );
3074 okBtn->setDefault( true );
3076 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
3077 dumpBtn->setAutoDefault( true );
3078 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
3079 helpBtn->setAutoDefault( true );
3081 QHBoxLayout* btnLayout = new QHBoxLayout;
3082 btnLayout->setSpacing( SPACING );
3083 btnLayout->setMargin( 0 );
3085 btnLayout->addWidget( okBtn );
3086 btnLayout->addWidget( dumpBtn );
3087 btnLayout->addStretch( 10 );
3088 btnLayout->addWidget( helpBtn );
3092 QVBoxLayout* l = new QVBoxLayout ( this );
3093 l->setMargin( MARGIN );
3094 l->setSpacing( SPACING );
3095 l->addWidget( myTabWidget );
3096 l->addLayout( btnLayout );
3100 myTabWidget->setCurrentIndex( qMax( (int)BaseInfo, qMin( (int)ElemInfo, page ) ) );
3102 // set-up connections
3104 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
3105 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
3106 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
3107 connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
3108 connect( myMode, SIGNAL( buttonClicked( int ) ), this, SLOT( modeChanged() ) );
3109 connect( myGroups, SIGNAL( currentIndexChanged( int ) ), this, SLOT( modeChanged() ) );
3110 connect( myID, SIGNAL( textChanged( QString ) ), this, SLOT( idChanged() ) );
3111 connect( myIDPreviewCheck, SIGNAL( toggled( bool ) ), this, SLOT( idPreviewChange( bool ) ) );
3112 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
3113 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
3114 connect( myElemInfo, SIGNAL( itemInfo( int, QString ) ), this, SLOT( showItemInfo( int, QString ) ) );
3115 connect( this, SIGNAL( switchMode( int ) ), stack, SLOT( setCurrentIndex( int ) ) );
3119 myIDPreviewCheck->setChecked( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "id_preview_resource", false ) );
3126 SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
3132 \brief Show mesh information on given object.
3133 \param io Interactive object.
3135 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
3138 showInfo( SMESH::SelectionProxy( io ) );
3142 \brief Show mesh information on given object.
3143 \param proxy Selection proxy.
3145 void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
3147 SUIT_OverrideCursor wc;
3154 SMESH::SMESH_IDSource_var obj = myProxy.object();
3157 myBaseInfo->showInfo( proxy );
3159 // "Additional info" tab
3160 myAddInfo->showInfo( proxy );
3162 // "Quality info" tab
3163 // Note: for performance reasons we update it only if it is currently active
3164 if ( myTabWidget->currentIndex() == CtrlInfo )
3165 myCtrlInfo->showInfo( proxy );
3167 // "Element info" tab
3168 myGroups->setSource( proxy );
3169 if ( myMode->checkedId() == GroupMode ) {
3170 SMESH::SelectionProxy group = myGroups->currentGroup();
3172 myElemInfo->showInfo( group );
3174 myElemInfo->clear();
3177 SVTK_Selector* selector = SMESH::GetSelector();
3180 if ( myProxy.actor() && selector ) { //todo: actor()?
3181 nb = myMode->checkedId() == NodeMode ?
3182 SMESH::GetNameOfSelectedElements( selector, myProxy.io(), ID ) :
3183 SMESH::GetNameOfSelectedNodes( selector, myProxy.io(), ID );
3186 myID->setText( ID.trimmed() );
3188 QStringList idTxt = ID.split( " ", QString::SkipEmptyParts );
3189 foreach ( ID, idTxt )
3190 ids << ID.trimmed().toUInt();
3191 myElemInfo->showInfo( proxy, ids, myMode->checkedId() == ElemMode );
3195 myElemInfo->clear();
3201 \brief Update information.
3203 void SMESHGUI_MeshInfoDlg::updateInfo()
3205 SALOME_ListIO selected;
3206 SMESHGUI::selectionMgr()->selectedObjects( selected );
3208 if ( selected.Extent() == 1 )
3209 showInfo( selected.First() );
3211 showInfo( myProxy );
3215 \brief Clean-up on dialog closing.
3217 void SMESHGUI_MeshInfoDlg::reject()
3219 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3220 selMgr->clearFilters();
3221 SMESH::SetPointRepresentation( false );
3222 if ( SVTK_ViewWindow* viewWindow = SMESH::GetViewWindow() )
3223 viewWindow->SetSelectionMode( ActorSelection );
3225 myIDPreview->SetPointsLabeled( false );
3229 \brief Process keyboard event.
3230 \param e Key press event.
3232 void SMESHGUI_MeshInfoDlg::keyPressEvent( QKeyEvent* e )
3234 QDialog::keyPressEvent( e );
3235 if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
3242 \brief Set-up selection mode for currently selected page.
3244 void SMESHGUI_MeshInfoDlg::updateSelection()
3246 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
3248 disconnect( selMgr, 0, this, 0 );
3249 selMgr->clearFilters();
3251 int selMode = ActorSelection;
3252 if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == NodeMode )
3253 selMode = NodeSelection;
3254 else if ( myTabWidget->currentIndex() == ElemInfo && myMode->checkedId() == ElemMode )
3255 selMode = CellSelection;
3256 SMESH::SetPointRepresentation( selMode == NodeSelection );
3257 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3258 aViewWindow->SetSelectionMode( selMode );
3260 SMESH::SelectionProxy previous = myProxy;
3261 QString ids = myID->text().trimmed();
3264 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3267 if ( myProxy && myProxy == previous && !ids.isEmpty() ) {
3268 myID->setText( ids );
3274 \brief Show documentation on selected dialog page.
3276 void SMESHGUI_MeshInfoDlg::help()
3278 QString helpPage = "mesh_infos.html";
3279 switch ( myTabWidget->currentIndex() )
3282 helpPage += "#advanced-mesh-infos-anchor";
3285 helpPage += "#mesh-element-info-anchor";
3288 helpPage += "#mesh-addition-info-anchor";
3291 helpPage += "#mesh-quality-info-anchor";
3296 SMESH::ShowHelpFile( helpPage );
3300 \brief Deactivate dialog box.
3302 void SMESHGUI_MeshInfoDlg::deactivate()
3304 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
3308 \brief Called when users switches between node / element modes.
3310 void SMESHGUI_MeshInfoDlg::modeChanged()
3312 emit( switchMode( myMode->checkedId() == GroupMode ? 1 : 0 ) );
3318 \brief Called when users prints mesh element ID in the corresponding field.
3320 void SMESHGUI_MeshInfoDlg::idChanged()
3322 myIDPreview->SetPointsLabeled( false );
3325 TColStd_MapOfInteger ID;
3327 std::vector<int> idVec;
3328 std::list< gp_XYZ > aGrCentersXYZ;
3330 const bool isElem = ( myMode->checkedId() == ElemMode );
3331 QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts );
3332 foreach ( QString tid, idTxt ) {
3333 long id = tid.toUInt();
3334 if ( isElem ? myProxy.hasElement( id ) : myProxy.hasNode( id ))
3338 if ( isElem && myProxy.actor() && myProxy.elementGravityCenter( id, xyz ))
3340 idVec.push_back( id );
3341 aGrCentersXYZ.push_back( xyz );
3345 SVTK_Selector* selector = SMESH::GetSelector();
3346 if ( myProxy.actor() && selector ) {
3347 Handle(SALOME_InteractiveObject) IO = myProxy.actor()->getIO();
3348 selector->AddOrRemoveIndex( IO, ID, false );
3349 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3351 if ( myMode->checkedId() == NodeMode )
3352 myIDPreview->SetPointsData( myProxy.actor()->GetObject()->GetMesh(), ID );
3354 myIDPreview->SetElemsData( idVec, aGrCentersXYZ );
3356 bool showIDs = ( !ID.IsEmpty() &&
3357 myIDPreviewCheck->isChecked() &&
3358 myTabWidget->currentIndex() == ElemInfo );
3359 myIDPreview->SetPointsLabeled( showIDs, myProxy.actor()->GetVisibility() );
3361 aViewWindow->highlight( IO, true, true );
3362 aViewWindow->Repaint();
3365 myElemInfo->showInfo( myProxy, ids, isElem );
3370 * \brief Show IDs clicked
3372 void SMESHGUI_MeshInfoDlg::idPreviewChange( bool isOn )
3374 myIDPreview->SetPointsLabeled( isOn && !myID->text().simplified().isEmpty() );
3375 SMESHGUI::resourceMgr()->setValue("SMESH", "id_preview_resource", isOn );
3376 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
3377 aViewWindow->Repaint();
3380 void SMESHGUI_MeshInfoDlg::showItemInfo( int type, const QString& ids )
3382 if ( !ids.isEmpty() && ( type == NodeConnectivity || type == ElemConnectivity )) {
3383 myMode->button( type - NodeConnectivity )->click();
3384 myID->setText( ids );
3389 \brief Dump information to file.
3391 void SMESHGUI_MeshInfoDlg::dump()
3393 DumpFileDlg fd( this );
3394 fd.setWindowTitle( tr( "SAVE_INFO" ) );
3395 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
3396 fd.setChecked( BaseInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_base", true ) );
3397 fd.setChecked( ElemInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_elem", true ) );
3398 fd.setChecked( AddInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_add", true ) );
3399 fd.setChecked( CtrlInfo, SMESHGUI::resourceMgr()->booleanValue( "SMESH", "info_dump_ctrl", true ) );
3400 if ( fd.exec() == QDialog::Accepted )
3402 QString fileName = fd.selectedFile();
3403 if ( !fileName.isEmpty() ) {
3404 QFile file( fileName );
3405 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
3408 QTextStream out( &file );
3409 if ( fd.isChecked( BaseInfo ) ) myBaseInfo->saveInfo( out );
3410 if ( fd.isChecked( ElemInfo ) ) myElemInfo->saveInfo( out );
3411 if ( fd.isChecked( AddInfo ) ) myAddInfo->saveInfo( out );
3412 if ( fd.isChecked( CtrlInfo ) ) myCtrlInfo->saveInfo( out );
3417 ////////////////////////////////////////////////////////////////////////////////
3418 /// \class SMESHGUI_CtrlInfo
3419 /// \brief Show quality statistics information on selected object.
3421 /// Displays quality controls statistics about selected object: mesh, sub-mesh,
3422 /// group or arbitrary ID source.
3423 ////////////////////////////////////////////////////////////////////////////////
3427 \param parent Parent widget. Defaults to 0.
3429 SMESHGUI_CtrlInfo::SMESHGUI_CtrlInfo( QWidget* parent ): SMESHGUI_Info( parent )
3431 QGridLayout* l = new QGridLayout( this );
3432 l->setMargin( MARGIN );
3433 l->setSpacing( SPACING );
3435 QIcon aComputeIcon( SUIT_Session::session()->resourceMgr()->loadPixmap( "SMESH", tr( "ICON_COMPUTE" ) ) );
3436 SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
3439 QLabel* aNameLab = createLabel( tr( "NAME_LAB" ), this, Bold );
3440 QLabel* aName = createField( this, "ctrlName" );
3441 aName->setMinimumWidth( 150 );
3445 QLabel* aNodesLab = createLabel( tr( "NODES_INFO" ), this, Bold );
3446 QLabel* aNodesFreeLab = new QLabel( tr( "NUMBER_OF_THE_FREE_NODES" ), this );
3447 QLabel* aNodesFree = createField( this, "ctrlNodesFree" );
3448 myWidgets << aNodesFree;
3449 myPredicates << aFilterMgr->CreateFreeNodes();
3451 QLabel* aNodesNbConnLab = new QLabel( tr( "MAX_NODE_CONNECTIVITY" ), this );
3452 QLabel* aNodesNbConn = createField( this, "ctrlNodesCnty" );
3453 myWidgets << aNodesNbConn;
3454 myNodeConnFunctor = aFilterMgr->CreateNodeConnectivityNumber();
3456 QLabel* aNodesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_NODES" ), this );
3457 QLabel* aNodesDouble = createField( this, "ctrlNodesDouble" );
3458 myWidgets << aNodesDouble;
3459 myPredicates << aFilterMgr->CreateEqualNodes();
3460 QLabel* aToleranceLab = new QLabel( tr( "DOUBLE_NODES_TOLERANCE" ), this );
3461 myToleranceWidget = new SMESHGUI_SpinBox( this );
3462 myToleranceWidget->RangeStepAndValidator(0.0000000001, 1000000.0, 0.0000001, "length_precision" );
3463 myToleranceWidget->setAcceptNames( false );
3464 myToleranceWidget->SetValue( SMESHGUI::resourceMgr()->doubleValue( "SMESH", "equal_nodes_tolerance", 1e-7 ) );
3467 QLabel* anEdgesLab = createLabel( tr( "EDGES_INFO" ), this, Bold );
3468 QLabel* anEdgesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_EDGES" ), this );
3469 QLabel* anEdgesDouble = createField( this, "ctrlEdgesDouble" );
3470 myWidgets << anEdgesDouble;
3471 myPredicates << aFilterMgr->CreateEqualEdges();
3474 QLabel* aFacesLab = createLabel( tr( "FACES_INFO" ), this, Bold );
3475 QLabel* aFacesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_FACES" ), this );
3476 QLabel* aFacesDouble = createField( this, "ctrlFacesDouble" );
3477 myWidgets << aFacesDouble;
3478 myPredicates << aFilterMgr->CreateEqualFaces();
3479 QLabel* aFacesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3480 QLabel* aFacesOver = createField( this, "ctrlFacesOver" );
3481 myWidgets << aFacesOver;
3482 myPredicates << aFilterMgr->CreateOverConstrainedFace();
3483 QLabel* anAspectRatioLab = new QLabel( tr( "ASPECT_RATIO_HISTOGRAM" ), this );
3484 myPlot = createPlot( this );
3485 myAspectRatio = aFilterMgr->CreateAspectRatio();
3488 QLabel* aVolumesLab = createLabel( tr( "VOLUMES_INFO" ), this, Bold );
3489 QLabel* aVolumesDoubleLab = new QLabel( tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ), this );
3490 QLabel* aVolumesDouble = createField( this, "ctrlVolumesDouble" );
3491 myWidgets << aVolumesDouble;
3492 myPredicates << aFilterMgr->CreateEqualVolumes();
3493 QLabel* aVolumesOverLab = new QLabel( tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ), this );
3494 QLabel* aVolumesOver = createField( this, "ctrlVolumesOver" );
3495 myWidgets << aVolumesOver;
3496 myPredicates << aFilterMgr->CreateOverConstrainedVolume();
3497 QLabel* anAspectRatio3DLab = new QLabel( tr( "ASPECT_RATIO_3D_HISTOGRAM" ), this );
3498 myPlot3D = createPlot( this );
3499 myAspectRatio3D = aFilterMgr->CreateAspectRatio3D();
3501 QToolButton* aFreeNodesBtn = new QToolButton( this );
3502 aFreeNodesBtn->setIcon(aComputeIcon);
3503 myButtons << aFreeNodesBtn; //0
3505 QToolButton* aNodesNbConnBtn = new QToolButton( this );
3506 aNodesNbConnBtn->setIcon(aComputeIcon);
3507 myButtons << aNodesNbConnBtn; //1
3509 QToolButton* aDoubleNodesBtn = new QToolButton( this );
3510 aDoubleNodesBtn->setIcon(aComputeIcon);
3511 myButtons << aDoubleNodesBtn; //2
3513 QToolButton* aDoubleEdgesBtn = new QToolButton( this );
3514 aDoubleEdgesBtn->setIcon(aComputeIcon);
3515 myButtons << aDoubleEdgesBtn; //3
3517 QToolButton* aDoubleFacesBtn = new QToolButton( this );
3518 aDoubleFacesBtn->setIcon(aComputeIcon);
3519 myButtons << aDoubleFacesBtn; //4
3521 QToolButton* aOverContFacesBtn = new QToolButton( this );
3522 aOverContFacesBtn->setIcon(aComputeIcon);
3523 myButtons << aOverContFacesBtn; //5
3525 QToolButton* aComputeFaceBtn = new QToolButton( this );
3526 aComputeFaceBtn->setIcon(aComputeIcon);
3527 myButtons << aComputeFaceBtn; //6
3529 QToolButton* aDoubleVolumesBtn = new QToolButton( this );
3530 aDoubleVolumesBtn->setIcon(aComputeIcon);
3531 myButtons << aDoubleVolumesBtn; //7
3533 QToolButton* aOverContVolumesBtn = new QToolButton( this );
3534 aOverContVolumesBtn->setIcon(aComputeIcon);
3535 myButtons << aOverContVolumesBtn; //8
3537 QToolButton* aComputeVolumeBtn = new QToolButton( this );
3538 aComputeVolumeBtn->setIcon(aComputeIcon);
3539 myButtons << aComputeVolumeBtn; //9
3541 connect( aComputeFaceBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio() ) );
3542 connect( aComputeVolumeBtn, SIGNAL( clicked() ), this, SLOT( computeAspectRatio3D() ) );
3543 connect( aFreeNodesBtn, SIGNAL( clicked() ), this, SLOT( computeFreeNodesInfo() ) );
3544 connect( aNodesNbConnBtn, SIGNAL( clicked() ), this, SLOT( computeNodesNbConnInfo() ) );
3545 connect( aDoubleNodesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleNodesInfo() ) );
3546 connect( aDoubleEdgesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleEdgesInfo() ) );
3547 connect( aDoubleFacesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleFacesInfo() ) );
3548 connect( aOverContFacesBtn, SIGNAL( clicked() ), this, SLOT( computeOverConstrainedFacesInfo() ) );
3549 connect( aDoubleVolumesBtn, SIGNAL( clicked() ), this, SLOT( computeDoubleVolumesInfo() ) );
3550 connect( aOverContVolumesBtn,SIGNAL( clicked() ), this, SLOT( computeOverConstrainedVolumesInfo() ) );
3551 connect( myToleranceWidget, SIGNAL( valueChanged( double ) ), this, SLOT( setTolerance( double ) ) );
3553 l->addWidget( aNameLab, 0, 0 ); //0
3554 l->addWidget( aName, 0, 1, 1, 2 ); //1
3555 l->addWidget( aNodesLab, 1, 0, 1, 3 ); //2
3556 l->addWidget( aNodesFreeLab, 2, 0 ); //3
3557 l->addWidget( aNodesFree, 2, 1 ); //4
3558 l->addWidget( aFreeNodesBtn, 2, 2 ); //5
3559 l->addWidget( aNodesNbConnLab, 3, 0 ); //6
3560 l->addWidget( aNodesNbConn, 3, 1 ); //7
3561 l->addWidget( aNodesNbConnBtn, 3, 2 ); //8
3562 l->addWidget( aNodesDoubleLab, 4, 0 ); //9
3563 l->addWidget( aNodesDouble, 4, 1 ); //10
3564 l->addWidget( aDoubleNodesBtn, 4, 2 ); //11
3565 l->addWidget( aToleranceLab, 5, 0 ); //12
3566 l->addWidget( myToleranceWidget, 5, 1 ); //13
3567 l->addWidget( anEdgesLab, 6, 0, 1, 3 ); //14
3568 l->addWidget( anEdgesDoubleLab, 7, 0 ); //15
3569 l->addWidget( anEdgesDouble, 7, 1 ); //16
3570 l->addWidget( aDoubleEdgesBtn, 7, 2 ); //17
3571 l->addWidget( aFacesLab, 8, 0, 1, 3 ); //18
3572 l->addWidget( aFacesDoubleLab, 9, 0 ); //19
3573 l->addWidget( aFacesDouble, 9, 1 ); //20
3574 l->addWidget( aDoubleFacesBtn, 9, 2 ); //21
3575 l->addWidget( aFacesOverLab, 10, 0 ); //22
3576 l->addWidget( aFacesOver, 10, 1 ); //23
3577 l->addWidget( aOverContFacesBtn, 10, 2 ); //24
3578 l->addWidget( anAspectRatioLab, 11, 0 ); //25
3579 l->addWidget( aComputeFaceBtn, 11, 2 ); //26
3580 l->addWidget( myPlot, 12, 0, 1, 3 );//27
3581 l->addWidget( aVolumesLab, 13, 0, 1, 3 );//28
3582 l->addWidget( aVolumesDoubleLab, 14, 0 ); //29
3583 l->addWidget( aVolumesDouble, 14, 1 ); //30
3584 l->addWidget( aDoubleVolumesBtn, 14, 2 ); //31
3585 l->addWidget( aVolumesOverLab, 15, 0 ); //32
3586 l->addWidget( aVolumesOver, 15, 1 ); //33
3587 l->addWidget( aOverContVolumesBtn,15, 2 ); //34
3588 l->addWidget( anAspectRatio3DLab, 16, 0 ); //35
3589 l->addWidget( aComputeVolumeBtn, 16, 2 ); //36
3590 l->addWidget( myPlot3D, 17, 0, 1, 3 );//37
3592 l->setColumnStretch( 0, 0 );
3593 l->setColumnStretch( 1, 5 );
3594 l->setRowStretch ( 12, 5 );
3595 l->setRowStretch ( 17, 5 );
3596 l->setRowStretch ( 18, 1 );
3604 SMESHGUI_CtrlInfo::~SMESHGUI_CtrlInfo()
3609 \brief Create plot widget.
3610 \param parent Parent widget.
3611 \return New plot widget.
3613 QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
3615 QwtPlot* aPlot = new QwtPlot( parent );
3616 aPlot->setMinimumSize( 100, 100 );
3617 QFont xFont = aPlot->axisFont( QwtPlot::xBottom );
3618 xFont.setPointSize( 5 );
3619 QFont yFont = aPlot->axisFont( QwtPlot::yLeft );
3620 yFont.setPointSize( 5 );
3621 aPlot->setAxisFont( QwtPlot::xBottom, xFont );
3622 aPlot->setAxisFont( QwtPlot::yLeft, yFont );
3628 \brief Show information on given object.
3629 \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
3631 void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
3639 SMESH::SMESH_IDSource_var obj = proxy.object();
3641 myWidgets[0]->setText( proxy.name() );
3643 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3644 if ( mesh->_is_nil() ) return;
3646 const bool meshLoaded = mesh->IsLoaded();
3647 if ( !meshLoaded ) // mesh not yet loaded from the hdf file
3648 // enable Compute buttons, just in case obj->GetNbElementsByType() fails
3649 for ( int i = 0; i < myButtons.count(); ++i )
3650 myButtons[i]->setEnabled( true );
3652 SMESH::long_array_var nbElemsByType = obj->GetNbElementsByType();
3653 if ( ! &nbElemsByType.in() ) return;
3655 const CORBA::Long ctrlLimit =
3656 meshLoaded ? SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_controls_limit", 3000 ) : -1;
3659 const CORBA::Long nbNodes = nbElemsByType[ SMESH::NODE ];
3660 // const CORBA::Long nbElems = ( nbElemsByType[ SMESH::EDGE ] +
3661 // nbElemsByType[ SMESH::FACE ] +
3662 // nbElemsByType[ SMESH::VOLUME ] );
3663 if ( nbNodes > 0 ) {
3664 if ( nbNodes <= ctrlLimit ) {
3666 computeFreeNodesInfo();
3667 // node connectivity number
3668 computeNodesNbConnInfo();
3670 computeDoubleNodesInfo();
3673 myButtons[0]->setEnabled( true );
3674 myButtons[1]->setEnabled( true );
3675 myButtons[2]->setEnabled( true );
3679 for( int i=2; i<=13; i++)
3680 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3684 if ( nbElemsByType[ SMESH::EDGE ] > 0 ) {
3686 if( nbElemsByType[ SMESH::EDGE ] <= ctrlLimit )
3687 computeDoubleEdgesInfo();
3689 myButtons[3]->setEnabled( true );
3692 for( int i=14; i<=17; i++)
3693 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3697 if ( nbElemsByType[ SMESH::FACE ] > 0 ) {
3698 if ( nbElemsByType[ SMESH::FACE ] <= ctrlLimit ) {
3700 computeDoubleFacesInfo();
3701 // over constrained faces
3702 computeOverConstrainedFacesInfo();
3703 // aspect Ratio histogram
3704 computeAspectRatio();
3707 myButtons[4]->setEnabled( true );
3708 myButtons[5]->setEnabled( true );
3709 myButtons[6]->setEnabled( true );
3711 #ifdef DISABLE_PLOT2DVIEWER
3712 for( int i=25; i<=27; i++)
3713 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3717 for( int i=18; i<=27; i++)
3718 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3722 if ( nbElemsByType[ SMESH::VOLUME ] > 0 ) {
3723 if ( nbElemsByType[ SMESH::VOLUME ] <= ctrlLimit ) {
3725 computeDoubleVolumesInfo();
3726 // over constrained volumes
3727 computeOverConstrainedVolumesInfo();
3728 // aspect Ratio 3D histogram
3729 computeAspectRatio3D();
3732 myButtons[7]->setEnabled( true );
3733 myButtons[8]->setEnabled( true );
3734 myButtons[9]->setEnabled( true );
3736 #ifdef DISABLE_PLOT2DVIEWER
3737 for( int i=35; i<=37; i++)
3738 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3742 for( int i=28; i<=37; i++)
3743 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( false );
3747 //================================================================================
3749 * \brief Computes and shows nb of elements satisfying a given predicate
3750 * \param [in] ft - a predicate type (SMESH::FunctorType)
3751 * \param [in] iBut - index of one of myButtons to disable
3752 * \param [in] iWdg - index of one of myWidgets to show the computed number
3754 //================================================================================
3756 void SMESHGUI_CtrlInfo::computeNb( int ft, int iBut, int iWdg )
3758 myButtons[ iBut ]->setEnabled( false );
3759 myWidgets[ iWdg ]->setText( "" );
3764 SUIT_OverrideCursor wc;
3766 SMESH::SMESH_IDSource_var obj = myProxy.object();
3767 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3769 if ( !mesh->_is_nil() && !mesh->IsLoaded() )
3772 showInfo( myProxy ); // try to show all values
3773 if ( !myWidgets[ iWdg ]->text().isEmpty() )
3774 return; // <ft> predicate already computed
3776 // look for a predicate of type <ft>
3777 for ( int i = 0; i < myPredicates.count(); ++i )
3778 if ( myPredicates[i]->GetFunctorType() == ft )
3780 CORBA::Long nb = myPredicates[i]->NbSatisfying( obj );
3781 myWidgets[ iWdg ]->setText( QString::number( nb ) );
3785 void SMESHGUI_CtrlInfo::computeFreeNodesInfo()
3787 computeNb( SMESH::FT_FreeNodes, 0, 1 );
3790 void SMESHGUI_CtrlInfo::computeDoubleNodesInfo()
3792 computeNb( SMESH::FT_EqualNodes, 2, 3 );
3795 void SMESHGUI_CtrlInfo::computeDoubleEdgesInfo()
3797 computeNb( SMESH::FT_EqualEdges, 3, 4 );
3800 void SMESHGUI_CtrlInfo::computeDoubleFacesInfo()
3802 computeNb( SMESH::FT_EqualFaces, 4, 5 );
3805 void SMESHGUI_CtrlInfo::computeOverConstrainedFacesInfo()
3807 computeNb( SMESH::FT_OverConstrainedFace, 5, 6 );
3810 void SMESHGUI_CtrlInfo::computeDoubleVolumesInfo()
3812 computeNb( SMESH::FT_EqualVolumes, 7, 7 );
3815 void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
3817 computeNb( SMESH::FT_OverConstrainedVolume, 8, 8 );
3820 void SMESHGUI_CtrlInfo::computeNodesNbConnInfo()
3822 myButtons[ 1 ]->setEnabled( false );
3823 myWidgets[ 2 ]->setText( "" );
3828 SUIT_OverrideCursor wc;
3830 SMESH::SMESH_IDSource_var obj = myProxy.object();
3831 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3833 if ( !mesh->IsLoaded() )
3836 showInfo( myProxy ); // try to show all values
3837 if ( !myWidgets[ 2 ]->text().isEmpty() )
3838 return; // already computed
3840 myNodeConnFunctor->SetMesh( mesh );
3841 SMESH::Histogram_var histogram =
3842 myNodeConnFunctor->GetLocalHistogram( 1, /*isLogarithmic=*/false, obj );
3844 myWidgets[ 2 ]->setText( QString::number( histogram[0].max ) );
3847 void SMESHGUI_CtrlInfo::computeAspectRatio()
3849 #ifndef DISABLE_PLOT2DVIEWER
3850 myButtons[6]->setEnabled( false );
3855 SUIT_OverrideCursor wc;
3857 SMESH::SMESH_IDSource_var obj = myProxy.object();
3858 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3860 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio );
3861 if ( aHistogram && !aHistogram->isEmpty() ) {
3862 QwtPlotItem* anItem = aHistogram->createPlotItem();
3863 anItem->attach( myPlot );
3870 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
3872 #ifndef DISABLE_PLOT2DVIEWER
3873 myButtons[9]->setEnabled( false );
3878 SUIT_OverrideCursor wc;
3880 SMESH::SMESH_IDSource_var obj = myProxy.object();
3881 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3883 Plot2d_Histogram* aHistogram = getHistogram( myAspectRatio3D );
3884 if ( aHistogram && !aHistogram->isEmpty() ) {
3885 QwtPlotItem* anItem = aHistogram->createPlotItem();
3886 anItem->attach( myPlot3D );
3894 \brief Internal clean-up (reset widget)
3896 void SMESHGUI_CtrlInfo::clearInternal()
3898 for( int i=0; i<=37; i++)
3899 dynamic_cast<QGridLayout*>(layout())->itemAt(i)->widget()->setVisible( true );
3900 for( int i=0; i<=9; i++)
3901 myButtons[i]->setEnabled( false );
3902 myPlot->detachItems();
3903 myPlot3D->detachItems();
3906 myWidgets[0]->setText( QString() );
3907 for ( int i = 1; i < myWidgets.count(); i++ )
3908 myWidgets[i]->setText( "" );
3911 void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
3913 //SMESH::long_array_var anElems = getElementsByType( SMESH::NODE );
3914 myButtons[1]->setEnabled( true );
3915 myWidgets[2]->setText("");
3918 #ifndef DISABLE_PLOT2DVIEWER
3919 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
3921 SUIT_OverrideCursor wc;
3923 SMESH::SMESH_IDSource_var obj = myProxy.object();
3924 SMESH::SMESH_Mesh_var mesh = obj->GetMesh();
3926 if ( !mesh->IsLoaded() )
3928 aNumFun->SetMesh( mesh );
3930 CORBA::Long cprecision = 6;
3931 if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) )
3932 cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
3933 aNumFun->SetPrecision( cprecision );
3935 int nbIntervals = SMESHGUI::resourceMgr()->integerValue( "SMESH", "scalar_bar_num_colors", false );
3937 SMESH::Histogram_var histogramVar = aNumFun->GetLocalHistogram( nbIntervals,
3938 /*isLogarithmic=*/false,
3940 Plot2d_Histogram* aHistogram = new Plot2d_Histogram();
3941 aHistogram->setColor( palette().color( QPalette::Highlight ) );
3942 if ( &histogramVar.in() )
3944 for ( size_t i = 0, nb = histogramVar->length(); i < nb; i++ )
3945 aHistogram->addPoint( 0.5 * ( histogramVar[i].min + histogramVar[i].max ), histogramVar[i].nbEvents );
3946 if ( histogramVar->length() >= 2 )
3947 aHistogram->setWidth( ( histogramVar[0].max - histogramVar[0].min ) * 0.8 );
3953 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
3956 QString title = tr( "CTRL_INFO" );
3957 out << ruler( title.size() ) << endl;
3958 out << title << endl;
3959 out << ruler( title.size() ) << endl;
3963 out << tr( "NAME_LAB" ) << " " << myWidgets[0]->text() << endl;
3964 out << tr( "NODES_INFO" ) << endl;
3965 out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
3966 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_NODES" ) << ": " << myWidgets[2]->text() << endl;
3967 out << tr( "EDGES_INFO" ) << endl;
3968 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_EDGES" ) << ": " << myWidgets[3]->text() << endl;
3969 out << tr( "FACES_INFO" ) << endl;
3970 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_FACES" ) << ": " << myWidgets[4]->text() << endl;
3971 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[5]->text() << endl;
3972 out << tr( "VOLUMES_INFO" ) << endl;
3973 out << indent() << tr( "NUMBER_OF_THE_DOUBLE_VOLUMES" ) << ": " << myWidgets[6]->text() << endl;
3974 out << indent() << tr( "NUMBER_OF_THE_OVER_CONSTRAINED" ) << ": " << myWidgets[7]->text() << endl;
3977 ////////////////////////////////////////////////////////////////////////////////
3978 /// \class SMESHGUI_CtrlInfoDlg
3979 /// \brief Overall Mesh Quality dialog.
3980 /// \todo Add selection button to reactivate selection on move from other dlg.
3981 ////////////////////////////////////////////////////////////////////////////////
3985 \param parent parent widget
3987 SMESHGUI_CtrlInfoDlg::SMESHGUI_CtrlInfoDlg( QWidget* parent )
3990 setAttribute( Qt::WA_DeleteOnClose, true );
3991 setWindowTitle( tr( "CTRL_INFO" ) );
3992 setMinimumSize( 400, 600 );
3994 myCtrlInfo = new SMESHGUI_CtrlInfo( this );
3997 QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
3998 okBtn->setAutoDefault( true );
3999 okBtn->setDefault( true );
4001 QPushButton* dumpBtn = new QPushButton( tr( "BUT_DUMP_MESH" ), this );
4002 dumpBtn->setAutoDefault( true );
4003 QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
4004 helpBtn->setAutoDefault( true );
4006 QHBoxLayout* btnLayout = new QHBoxLayout;
4007 btnLayout->setSpacing( SPACING );
4008 btnLayout->setMargin( 0 );
4010 btnLayout->addWidget( okBtn );
4011 btnLayout->addWidget( dumpBtn );
4012 btnLayout->addStretch( 10 );
4013 btnLayout->addWidget( helpBtn );
4015 QVBoxLayout* l = new QVBoxLayout ( this );
4017 l->setSpacing( SPACING );
4018 l->addWidget( myCtrlInfo );
4019 l->addLayout( btnLayout );
4021 connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
4022 connect( dumpBtn, SIGNAL( clicked() ), this, SLOT( dump() ) );
4023 connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
4024 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
4025 connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
4033 SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
4038 \brief Show mesh quality information on given object.
4039 \param io Interactive object.
4041 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
4044 showInfo( SMESH::SelectionProxy( io ) );
4048 \brief Show mesh quality information on given object.
4049 \param proxy Selection proxy.
4051 void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
4053 SUIT_OverrideCursor wc;
4059 myCtrlInfo->showInfo( proxy );
4063 \brief Show mesh information
4065 void SMESHGUI_CtrlInfoDlg::updateInfo()
4067 SALOME_ListIO selected;
4068 SMESHGUI::selectionMgr()->selectedObjects( selected );
4070 if ( selected.Extent() == 1 )
4071 showInfo( selected.First() );
4073 showInfo( myProxy );
4077 \brief Perform clean-up actions on the dialog box closing.
4079 void SMESHGUI_CtrlInfoDlg::reject()
4081 SMESH::SetPointRepresentation( false );
4086 \brief Setup selection mode depending on the current dialog box state.
4088 void SMESHGUI_CtrlInfoDlg::updateSelection()
4090 LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
4091 disconnect( selMgr, 0, this, 0 );
4092 SMESH::SetPointRepresentation( false );
4093 connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4098 \brief Deactivate dialog box.
4100 void SMESHGUI_CtrlInfoDlg::deactivate()
4102 disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
4106 \brief Dump information to file.
4108 void SMESHGUI_CtrlInfoDlg::dump()
4110 DumpFileDlg fd( this, false );
4111 fd.setWindowTitle( tr( "SAVE_INFO" ) );
4112 fd.setNameFilters( QStringList() << tr( "TEXT_FILES" ) );
4113 if ( fd.exec() == QDialog::Accepted )
4115 QString fileName = fd.selectedFile();
4116 if ( !fileName.isEmpty() ) {
4117 QFile file( fileName );
4118 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
4121 QTextStream out( &file );
4122 myCtrlInfo->saveInfo( out );
4128 \brief Show documentation on dialog.
4130 void SMESHGUI_CtrlInfoDlg::help()
4132 SMESH::ShowHelpFile( "mesh_infos.html#mesh-quality-info-anchor" );