Salome HOME
9e76f5cd90095d957afe1df936f62d0159b083d0
[modules/geom.git] / src / EntityGUI / EntityGUI_FieldDlg.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : EntityGUI_FieldDlg.cxx
24
25 #include "EntityGUI_FieldDlg.h"
26
27 #include <DlgRef.h>
28 #include <GEOMBase.h>
29 #include <GEOMBase_Skeleton.h>
30 #include <GEOM_Displayer.h>
31 #include <GeometryGUI.h>
32
33 #include <SalomeApp_Application.h>
34 #include <SalomeApp_Study.h>
35 #include <SalomeApp_Tools.h>
36 #include <SalomeApp_IntSpinBox.h>
37 #include <SalomeApp_DoubleSpinBox.h>
38
39 #include <LightApp_SelectionMgr.h>
40
41 #include <OCCViewer_ViewModel.h>
42 #include <OCCViewer_ViewManager.h>
43 #include <SVTK_ViewModel.h>
44 #include <SALOME_Prs.h>
45 #include <SALOME_ListIO.hxx>
46
47 #include <SUIT_Desktop.h>
48 #include <SUIT_MessageBox.h>
49 #include <SUIT_OverrideCursor.h>
50 #include <SUIT_ResourceMgr.h>
51 #include <SUIT_Session.h>
52 #include <SUIT_ViewWindow.h>
53 #include <SUIT_ViewManager.h>
54
55 #include <QComboBox>
56 #include <QGridLayout>
57 #include <QGroupBox>
58 #include <QHeaderView>
59 #include <QInputDialog>
60 #include <QLabel>
61 #include <QLineEdit>
62 #include <QPushButton>
63 #include <QTableWidget>
64 #include <QVBoxLayout>
65
66 #include <AIS_ListOfInteractive.hxx>
67 #include <AIS_ListIteratorOfListOfInteractive.hxx>
68
69 #include <TopExp.hxx>
70 #include <TopExp_Explorer.hxx>
71 #include <TopTools_IndexedMapOfShape.hxx>
72 #include <TColStd_IndexedMapOfInteger.hxx>
73 #include <TColStd_MapOfInteger.hxx>
74 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
75
76 #include <limits>
77
78 #include <SALOMEDS_wrap.hxx>
79 #include <GEOMImpl_Types.hxx>
80
81 #ifdef max
82   #undef max
83 #endif
84
85
86 const int theIntLimit = std::numeric_limits<int>::max() - 10;
87
88 /*
89   Class       : EntityGUI_FieldDlg::CheckItem
90   Description : Bool item.
91 */
92 class EntityGUI_FieldDlg::CheckItem : public QTableWidgetItem
93 {
94 public:
95   static int     Type();
96
97   CheckItem( bool = false );
98   ~CheckItem();
99
100   void  setValue( bool );
101   bool  value() const;
102 };
103
104 int EntityGUI_FieldDlg::CheckItem::Type()
105 {
106   return QTableWidgetItem::UserType + 2;
107 }
108
109 EntityGUI_FieldDlg::CheckItem::CheckItem( bool value )
110  : QTableWidgetItem( Type() )
111 {
112   Qt::ItemFlags f = flags();
113   f = f | Qt::ItemIsUserCheckable;
114   f = f & ~Qt::ItemIsTristate;
115   f = f & ~Qt::ItemIsEditable;
116   setFlags( f );
117   setValue(value);
118 }
119
120 EntityGUI_FieldDlg::CheckItem::~CheckItem()
121 {
122 }
123
124 void EntityGUI_FieldDlg::CheckItem::setValue( bool value )
125 {
126   setCheckState( value ? Qt::Checked : Qt::Unchecked );
127 }
128
129 bool EntityGUI_FieldDlg::CheckItem::value() const
130 {
131   return checkState() == Qt::Checked;
132 }
133
134 /*
135   Class       : EntityGUI_FieldDlg::IntSpinItem
136   Description : Integer spin table item.
137 */
138
139 class EntityGUI_FieldDlg::IntSpinItem : public QTableWidgetItem
140 {
141 public:
142   static int     Type();
143
144   IntSpinItem( const int theValue );
145
146   int            value() const;
147   void           setValue( const int theValue );
148
149   void           clear();
150 };
151
152 int EntityGUI_FieldDlg::IntSpinItem::Type()
153 {
154   return QTableWidgetItem::UserType + 3;
155 }
156
157 EntityGUI_FieldDlg::IntSpinItem::IntSpinItem( const int theValue )
158  : QTableWidgetItem( Type() )
159 {
160   setValue( theValue );
161 }
162
163 int EntityGUI_FieldDlg::IntSpinItem::value() const
164 {
165   bool ok = false;
166   int value = data( Qt::UserRole ).toInt( &ok );
167   return ok ? value : 0; 
168 }
169
170 void EntityGUI_FieldDlg::IntSpinItem::setValue( const int theValue )
171 {
172   setData( Qt::UserRole, theValue );
173   setText( QString::number( theValue ) ); 
174 }
175
176 void EntityGUI_FieldDlg::IntSpinItem::clear()
177 {
178   setText( "" );
179 }
180
181 /*
182   Class       : EntityGUI_FieldDlg::DoubleSpinItem
183   Description : Double spin table item.
184 */
185
186 class EntityGUI_FieldDlg::DoubleSpinItem : public QTableWidgetItem
187 {
188 public:
189   static int     Type();
190
191   DoubleSpinItem( const double theValue, const int thePrecision=6 );
192
193   double         value() const;
194   void           setValue( const double theValue );
195
196   int            precision() const;
197   void           setPrecision( const int thePrecision );
198
199   void           clear();
200 };
201
202 int EntityGUI_FieldDlg::DoubleSpinItem::Type()
203 {
204   return QTableWidgetItem::UserType + 4;
205 }
206
207 EntityGUI_FieldDlg::DoubleSpinItem::DoubleSpinItem( const double theValue,
208                                                     const int    thePrecision)
209  : QTableWidgetItem( Type() )
210 {
211   setValue( theValue );
212   setPrecision( thePrecision );
213 }
214
215 double EntityGUI_FieldDlg::DoubleSpinItem::value() const
216 {
217   bool ok = false;
218   double value = data( Qt::UserRole ).toDouble( &ok );
219   return ok ? value : 0; 
220 }
221
222 void EntityGUI_FieldDlg::DoubleSpinItem::setValue( const double theValue )
223 {
224   setData( Qt::UserRole, theValue );
225   setText( QString::number( theValue ) ); 
226 }
227
228 int EntityGUI_FieldDlg::DoubleSpinItem::precision() const
229 {
230   bool ok = false;
231   int precision = data( Qt::UserRole + 1 ).toInt( &ok );
232   return ok ? precision : 0; 
233 }
234
235 void EntityGUI_FieldDlg::DoubleSpinItem::setPrecision( const int thePrecision )
236 {
237   setData( Qt::UserRole + 1, thePrecision );
238 }
239
240 void EntityGUI_FieldDlg::DoubleSpinItem::clear()
241 {
242   setText( "" );
243 }
244
245 /*
246   Class       : EntityGUI_FieldDlg::ComboDelegate
247   Description : Table used by this widget
248 */
249
250 class EntityGUI_FieldDlg::Delegate : public QItemDelegate
251 {
252 public:
253   Delegate( QObject* = 0 );
254   ~Delegate();
255   
256   QWidget*      createEditor( QWidget*, const QStyleOptionViewItem&,
257                               const QModelIndex& ) const;
258   
259   void          setEditorData( QWidget*, const QModelIndex& ) const;
260   void          setModelData( QWidget*, QAbstractItemModel*, const QModelIndex& ) const;
261   
262   void          updateEditorGeometry( QWidget*, const QStyleOptionViewItem&, 
263                                       const QModelIndex& ) const;
264 private:
265   StepTable* myTable;
266 };
267
268 EntityGUI_FieldDlg::Delegate::Delegate( QObject* parent )
269   : QItemDelegate( parent ), 
270     myTable( dynamic_cast<EntityGUI_FieldDlg::StepTable*>( parent ) )
271 {
272 }
273   
274 EntityGUI_FieldDlg::Delegate::~Delegate()
275 {
276 }
277
278 QWidget* EntityGUI_FieldDlg::Delegate::createEditor( QWidget* parent,
279                                                      const QStyleOptionViewItem& option,
280                                                      const QModelIndex& index ) const
281 {
282   QVariant aData = index.data( Qt::UserRole );
283   QVariant::Type aDataType = aData.type();
284   if( aDataType == QVariant::Int ) {
285     bool ok = false;
286     int aValue = aData.toInt( &ok );
287     if ( ok ) {
288       SalomeApp_IntSpinBox* intSpin = new SalomeApp_IntSpinBox( -theIntLimit, theIntLimit, 1, parent, false, true );
289       intSpin->setFrame( false );
290       intSpin->setValue( aValue );
291       return intSpin;
292     }
293   }
294   else if( aDataType == QVariant::Double ) {
295     bool ok = false;
296     double aValue = aData.toDouble( &ok );
297     if ( ok ) {
298       int aPrecision = index.data( Qt::UserRole + 1 ).toInt( &ok );
299       if ( !ok )
300         aPrecision = 0;
301
302       SalomeApp_DoubleSpinBox* dblSpin = new SalomeApp_DoubleSpinBox( -1.e20, 1.e20, 1, aPrecision, 20, parent, false, true );
303       dblSpin->setFrame( false );
304       dblSpin->setValue( aValue );
305       return dblSpin;
306     }
307   }
308   return QItemDelegate::createEditor( parent, option, index );
309 }
310
311 void EntityGUI_FieldDlg::Delegate::setEditorData( QWidget* editor, 
312                                                   const QModelIndex& index ) const
313 {
314   QVariant data = index.model()->data( index, Qt::DisplayRole );
315   QString value = data.toString();
316   bool bOk = false;
317   if ( SalomeApp_DoubleSpinBox* dblSpin = dynamic_cast<SalomeApp_DoubleSpinBox*>( editor ) ) {
318     if( data.type() == QVariant::Double ) {
319       double valueDouble = data.toDouble( &bOk );
320       if( bOk )
321         dblSpin->setValue( valueDouble );
322     }
323   }
324   if ( !bOk ) QItemDelegate::setEditorData( editor, index );
325 }
326
327 void EntityGUI_FieldDlg::Delegate::setModelData( QWidget* editor,
328                                                  QAbstractItemModel* model,
329                                                  const QModelIndex& index) const
330 {
331   QString oldData = myTable->text( index.row(), index.column() );
332
333   if( SalomeApp_IntSpinBox* intSpin = dynamic_cast<SalomeApp_IntSpinBox*>( editor ) )
334     model->setData( index, intSpin->value(), Qt::DisplayRole );
335   else if( SalomeApp_DoubleSpinBox* dblSpin = dynamic_cast<SalomeApp_DoubleSpinBox*>( editor ) )
336     model->setData( index, dblSpin->value(), Qt::DisplayRole );
337   else
338     QItemDelegate::setModelData( editor, model, index );
339
340   QString newData = myTable->text( index.row(), index.column() );
341   if ( newData != oldData )
342     myTable->setIsChanged();
343 }
344
345 void EntityGUI_FieldDlg::Delegate::updateEditorGeometry( QWidget* editor,
346                                                          const QStyleOptionViewItem& option, 
347                                                          const QModelIndex& /*index*/ ) const
348 {
349   editor->setGeometry( option.rect );
350 }
351
352 //=======================================================================
353 // name    : EntityGUI_FieldDlg::StepTable::Table
354 // Purpose : Constructor
355 //=======================================================================
356 EntityGUI_FieldDlg::StepTable::StepTable (int stepID, int dataType,
357                                           int nbRows, int nbComps,
358                                           QString shapeName, QStringList headers,
359                                           GEOM::GEOM_FieldStep_ptr stepVar,
360                                           QWidget* parent)
361   : QTableWidget(0, nbComps+1, parent),
362     myDataType( dataType ),
363     myStepID( stepID ),
364     myStamp( 0 ),
365     myStep( GEOM::GEOM_FieldStep::_duplicate( stepVar )),
366     myIsChanged( false )
367 {
368   setDim( nbRows, shapeName, stepVar->_is_nil() );
369
370   setHorizontalHeaderLabels( headers );
371   verticalHeader()->hide();
372
373   // set custom item delegate
374   setItemDelegate( new Delegate(this) );
375   // set edit triggers by default
376   setReadOnly( false );
377
378   if ( stepVar->_is_nil() )
379   {
380     connect( horizontalHeader(), SIGNAL( sectionDoubleClicked( int ) ), this, SLOT( headerDblClicked( int ) ) );
381
382     return;
383   }
384   myStamp = stepVar->GetStamp();
385
386   const int nbColumns = nbComps + 1;
387
388   switch ( dataType )
389   {
390   case 0:
391   {
392     GEOM::GEOM_BoolFieldStep_var bs = GEOM::GEOM_BoolFieldStep::_narrow( stepVar );
393     if ( !bs->_is_nil() )
394     {
395       GEOM::short_array_var vals = bs->GetValues();
396       if ( (int)vals->length() == nbRows * nbComps )
397         for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
398           for ( int iC = 1; iC < nbColumns; ++iC )
399             setItem( iR, iC, new CheckItem( vals[ iV++ ]));
400     }
401     connect( this, SIGNAL( itemClicked(QTableWidgetItem *)), this, SLOT( setIsChanged() ));
402     break;
403   }
404   case 1:
405   {
406     GEOM::GEOM_IntFieldStep_var is = GEOM::GEOM_IntFieldStep::_narrow( stepVar );
407     if ( !is->_is_nil() )
408     {
409       GEOM::ListOfLong_var vals = is->GetValues();
410       if ( (int)vals->length() == nbRows * nbComps )
411         for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
412           for ( int iC = 1; iC < nbColumns; ++iC )
413             setItem( iR, iC, new IntSpinItem( vals[ iV++ ]));
414     }
415     break;
416   }
417   case 2:
418   {
419     GEOM::GEOM_DoubleFieldStep_var ds = GEOM::GEOM_DoubleFieldStep::_narrow( stepVar );
420     if ( !ds->_is_nil() )
421     {
422       GEOM::ListOfDouble_var vals = ds->GetValues();
423       if ( (int)vals->length() == nbRows * nbComps )
424         for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
425           for ( int iC = 1; iC < nbColumns; ++iC )
426             setItem( iR, iC, new DoubleSpinItem( vals[ iV++ ]));
427     }
428     break;
429   }
430   default:
431     GEOM::GEOM_StringFieldStep_var ss = GEOM::GEOM_StringFieldStep::_narrow( stepVar );
432     if ( !ss->_is_nil() )
433     {
434       GEOM::string_array_var vals = ss->GetValues();
435       if ( (int)vals->length() == nbRows * nbComps )
436         for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
437           for ( int iC = 1; iC < nbColumns; ++iC )
438             setItem( iR, iC, new QTableWidgetItem( vals[ iV++ ].in() ));
439     }
440     break;
441   }
442 }
443
444 //=======================================================================
445 // name    : EntityGUI_FieldDlg::StepTable::~StepTable
446 // Purpose : Destructor
447 //=======================================================================
448 EntityGUI_FieldDlg::StepTable::~StepTable()
449 {
450 }
451
452 //=======================================================================
453 // name    : EntityGUI_FieldDlg::StepTable::minimumSizeHint
454 // Purpose : Get minimum size for the table
455 //=======================================================================
456 QSize EntityGUI_FieldDlg::StepTable::minimumSizeHint() const
457 {
458   QSize s = QTableWidget::minimumSizeHint();
459   QHeaderView* hv = horizontalHeader();
460   if ( hv )
461     s.setWidth( qMax( s.width(), hv->length() ) );
462   return s;
463 }
464
465 //=======================================================================
466 // name    : EntityGUI_FieldDlg::StepTable::setEditable
467 // Purpose : Set editable of specified cell
468 //=======================================================================
469 void EntityGUI_FieldDlg::StepTable::setEditable (bool isEditable,
470                                                  int row, int col)
471 {
472   QTableWidgetItem* anItem = item( row, col );
473   if ( anItem ) {
474     bool isSignalsBlocked = signalsBlocked();
475     blockSignals( true );
476
477     Qt::ItemFlags f = anItem->flags();
478     if ( !isEditable ) f = f & ~Qt::ItemIsEditable;
479     else f = f | Qt::ItemIsEditable;
480     anItem->setFlags( f );
481     
482     blockSignals( isSignalsBlocked );
483   }
484 }
485
486 //=======================================================================
487 // name    : EntityGUI_FieldDlg::StepTable::isEditable
488 // Purpose : Verify whether cell is editable
489 //=======================================================================
490 bool EntityGUI_FieldDlg::StepTable::isEditable (int row, int col) const
491 {
492   QTableWidgetItem* anItem = item( row, col );
493   return anItem == 0 || anItem->flags() & Qt::ItemIsEditable;
494 }
495
496 void EntityGUI_FieldDlg::StepTable::setReadOnly( bool on )
497 {
498   setEditTriggers( on ? 
499                    QAbstractItemView::NoEditTriggers  :
500                    QAbstractItemView::AllEditTriggers );
501 }
502
503 bool EntityGUI_FieldDlg::StepTable::isReadOnly() const
504 {
505   return editTriggers() == QAbstractItemView::NoEditTriggers;
506 }
507
508 //=======================================================================
509 // name    : EntityGUI_FieldDlg::StepTable::insertRows
510 // Purpose : Insert rows (virtual redefined)
511 //=======================================================================
512 void EntityGUI_FieldDlg::StepTable::insertRows (int row, int count)
513 {
514   while ( count-- ) insertRow( row );
515 }
516
517 //=======================================================================
518 // name    : EntityGUI_FieldDlg::StepTable::text
519 // Purpose : Get text from cell (virtual redefined)
520 //=======================================================================
521 QString EntityGUI_FieldDlg::StepTable::text (int row, int col)
522 {
523   closePersistentEditor( currentItem() );
524   QTableWidgetItem* anItem = item( row, col );
525   return anItem ? anItem->text() : QString();
526 }
527
528 QList<int> EntityGUI_FieldDlg::StepTable::selectedRows()
529 {
530   QList<QTableWidgetItem*> selItems = selectedItems();
531   QTableWidgetItem* anItem;
532   QList<int> rows;
533
534   foreach( anItem, selItems ) {
535     int r = row( anItem );
536     if ( !rows.contains( r ) ) rows.append( r );
537   }
538
539   qSort( rows );
540   return rows;
541 }
542
543 //=======================================================================
544 //function : selectRows
545 //purpose  : 
546 //=======================================================================
547
548 void EntityGUI_FieldDlg::StepTable::selectRows(const QList<int>& rows)
549 {
550   closePersistentEditor( currentItem() );
551
552   QList<QTableWidgetSelectionRange> ranges = selectedRanges();
553   for ( int i = 0; i < ranges.count(); ++i )
554     setRangeSelected( ranges[i], false );
555
556   QList<int>::const_iterator row = rows.begin();
557   for ( ; row != rows.end(); ++row )
558     // QTableWidgetSelectionRange ( int top, int left, int bottom, int right )
559     setRangeSelected ( QTableWidgetSelectionRange(*row,0,*row,0), true );
560 }
561
562 //=======================================================================
563 //function : setDim
564 //purpose  : change nb rows in the table
565 //=======================================================================
566
567 void EntityGUI_FieldDlg::StepTable::setDim( int nbRows, QString shapeName, bool setDefault )
568 {
569   closePersistentEditor( currentItem() );
570   int curNbRows = rowCount();
571   if ( nbRows < curNbRows )
572   {
573     while ( nbRows < curNbRows )
574       removeRow( --curNbRows );
575   }
576   else if ( nbRows > curNbRows )
577   {
578     int nbColumns = columnCount();
579     for ( ; nbRows > curNbRows; ++curNbRows )
580     {
581       insertRow( curNbRows );
582       if ( setDefault )
583         for ( int iC = 1; iC < nbColumns; ++iC )
584           setItem( curNbRows, iC, newDefaultItem() );
585     }
586   }
587
588   int indexWidth = 1, maxNbR = 10;
589   while ( nbRows >= maxNbR )
590     ++indexWidth, maxNbR *= 10;
591   shapeName = shapeName.toLower() + "_%1";
592   for ( int iR = 0; iR < nbRows; ++iR )
593   {
594     setItem( iR, 0, new QTableWidgetItem( shapeName.arg( iR+1, indexWidth, 10, QChar('0') )));
595     setEditable( false, iR, 0 );
596   }
597 }
598
599 //=======================================================================
600 //function : setNbComps
601 //purpose  : 
602 //=======================================================================
603
604 void EntityGUI_FieldDlg::StepTable::setNbComps( int nbComps )
605 {
606   closePersistentEditor( currentItem() );
607   nbComps++; // add sub-shape column
608   int curNbCols = columnCount();
609   if ( nbComps < curNbCols )
610   {
611     while ( nbComps < curNbCols )
612       removeColumn( --curNbCols );
613   }
614   else if ( nbComps > curNbCols )
615   {
616     int nbRows = rowCount();
617     for ( ; nbComps > curNbCols; ++curNbCols )
618     {
619       insertColumn( curNbCols );
620       setHorizontalHeaderItem( curNbCols,
621                                new QTableWidgetItem(QString("Comp %1").arg( curNbCols )));
622       for ( int iR = 0; iR < nbRows; ++iR )
623         setItem( iR, curNbCols, newDefaultItem() );
624     }
625   }
626 }
627
628 //=======================================================================
629 //function : setDataType
630 //purpose  : change type of data
631 //=======================================================================
632
633 void EntityGUI_FieldDlg::StepTable::setDataType( int dataType )
634 {
635   myDataType = dataType;
636
637   int nbRows = rowCount();
638   int nbColumns = columnCount();
639
640   for ( int iR = 0; iR < nbRows; ++iR )
641     for ( int iC = 1; iC < nbColumns; ++iC )
642       setItem( iR, iC, newDefaultItem() );
643 }
644
645 //=======================================================================
646 //function : newDefaultItem
647 //purpose  : creates a table item with a default value
648 //=======================================================================
649
650 QTableWidgetItem * EntityGUI_FieldDlg::StepTable::newDefaultItem()
651 {
652   switch( myDataType ) {
653   case 0: return new CheckItem(false);
654   case 1: return new IntSpinItem(0);
655   case 2: return new DoubleSpinItem(0);
656   default:;
657   }
658   return new QTableWidgetItem(""); // string
659 }
660
661 //=======================================================================
662 //function : getHeaders
663 //purpose  : 
664 //=======================================================================
665
666 QStringList EntityGUI_FieldDlg::StepTable::getHeaders()
667 {
668   QStringList headers;
669   int nbColumns = columnCount();
670   for ( int iC = 0; iC < nbColumns; ++iC )
671     headers << horizontalHeaderItem( iC )->text();
672   return headers;
673 }
674
675 //=======================================================================
676 //function : setHeaders
677 //purpose  : 
678 //=======================================================================
679
680 void EntityGUI_FieldDlg::StepTable::setHeaders(const QStringList& headers)
681 {
682   setHorizontalHeaderLabels( headers );
683 }
684
685 //=======================================================================
686 //function : setValues
687 //purpose  : store values from this table to a field step
688 //=======================================================================
689
690 void EntityGUI_FieldDlg::StepTable::setValues(GEOM::GEOM_FieldStep_var& step)
691 {
692   closePersistentEditor( currentItem() );
693
694   if ( step->GetStamp() != myStamp )
695     step->SetStamp( myStamp );
696
697   if ( step->_is_equivalent( myStep ) && !myIsChanged )
698     return;
699
700   const int nbColumns = columnCount();
701   const int nbComps = nbColumns - 1;
702   const int nbRows = rowCount();
703
704   switch ( myDataType ) {
705   case 0:
706   {
707     GEOM::GEOM_BoolFieldStep_var bs = GEOM::GEOM_BoolFieldStep::_narrow( step );
708     if ( !bs->_is_nil() )
709     {
710       GEOM::short_array_var vals = new GEOM::short_array();
711       vals->length( nbRows * nbComps );
712       for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
713         for ( int iC = 1; iC < nbColumns; ++iC )
714           vals[ iV++ ] = ((CheckItem*)item( iR, iC ))->value();
715       bs->SetValues( vals );
716     }
717     break;
718   }
719   case 1:
720   {
721     GEOM::GEOM_IntFieldStep_var is = GEOM::GEOM_IntFieldStep::_narrow( step );
722     if ( !is->_is_nil() )
723     {
724       GEOM::ListOfLong_var vals = new GEOM::ListOfLong();
725       vals->length( nbRows * nbComps );
726       for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
727         for ( int iC = 1; iC < nbColumns; ++iC )
728           vals[ iV++ ] = text( iR, iC ).toInt();
729       is->SetValues( vals );
730     }
731     break;
732   }
733   case 2:
734   {
735     GEOM::GEOM_DoubleFieldStep_var ds = GEOM::GEOM_DoubleFieldStep::_narrow( step );
736     if ( !ds->_is_nil() )
737     {
738       GEOM::ListOfDouble_var vals = new GEOM::ListOfDouble();
739       vals->length( nbRows * nbComps );
740       for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
741         for ( int iC = 1; iC < nbColumns; ++iC )
742           vals[ iV++ ] = text( iR, iC ).toDouble();
743       ds->SetValues( vals );
744     }
745     break;
746   }
747   default:
748
749     GEOM::GEOM_StringFieldStep_var ss = GEOM::GEOM_StringFieldStep::_narrow( step );
750     if ( !ss->_is_nil() )
751     {
752       GEOM::string_array_var vals = new GEOM::string_array();
753       vals->length( nbRows * nbComps );
754       for ( int iV = 0, iR = 0; iR < nbRows; ++iR )
755         for ( int iC = 1; iC < nbColumns; ++iC )
756           vals[ iV++ ] = item( iR, iC )->text().toUtf8().constData();
757       ss->SetValues( vals );
758     }
759   }
760
761   myIsChanged = false;
762
763   return;
764 }
765
766 //=======================================================================
767 //function : headerDblClicked
768 //purpose  : rename column, called when used double-clicks on the header
769 //=======================================================================
770
771 void EntityGUI_FieldDlg::StepTable::headerDblClicked( int section )
772 {
773   if ( section > 0 ) {
774     bool bOk;
775     QString label = QInputDialog::getText( this, EntityGUI_FieldDlg::tr( "RENAME_COMPONENT" ),
776                                            EntityGUI_FieldDlg::tr ( "COMPONENT_NAME" ), QLineEdit::Normal,
777                                            horizontalHeaderItem( section )->text(), &bOk );
778     if ( bOk && !label.isEmpty() )
779       horizontalHeaderItem( section )->setText( label );
780   }
781 }
782
783 //=======================================================================
784 //function : EntityGUI_FieldDlg
785 //purpose  : 
786 //=======================================================================
787
788 EntityGUI_FieldDlg::EntityGUI_FieldDlg (GeometryGUI* theGeometryGUI,
789                                         GEOM::GEOM_Field_ptr theField, int stepID,
790                                         QWidget* parent,
791                                         bool modal, Qt::WindowFlags fl)
792   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
793     myIsCreation( CORBA::is_nil( theField )),
794     myField( GEOM::GEOM_Field::_duplicate( theField )),
795     myCurStepID( stepID ),
796     myCurStepTable( NULL ),
797     myIsHiddenMain( false )
798 {
799   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
800   QPixmap iconSelect (resMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
801
802   setWindowTitle(myIsCreation ? tr("CREATE_FIELD_TITLE") : tr("EDIT_FIELD_TITLE"));
803
804   // Shape type button group
805   mainFrame()->GroupConstructors->hide();
806
807   // Field name
808   mainFrame()->GroupBoxName->setTitle(tr("FIELD_NAME"));
809
810   // Field properties
811
812   QGroupBox* propGroup = new QGroupBox(tr("PROPERTIES"), centralWidget());
813   QGridLayout* propLayout = new QGridLayout(propGroup);
814   propLayout->setMargin(9);
815   propLayout->setSpacing(6);
816
817   // shape
818   QLabel* shapeLabel = new QLabel(tr("SHAPE"), propGroup);
819   myShapeSelBtn = new QPushButton(propGroup);
820   myShapeSelBtn->setIcon(iconSelect);
821   myShapeSelBtn->setEnabled( myIsCreation );
822   myShapeName = new QLineEdit(propGroup);
823   myShapeName->setReadOnly(true);
824   myShapeName->setEnabled( myIsCreation );
825
826   // data type
827   QLabel* typeLabel = new QLabel( tr("DATA_TYPE"), propGroup );
828   myTypeCombo = new QComboBox( propGroup );
829   myTypeCombo->insertItem( GEOM::FDT_Bool,   tr("BOOL"));
830   myTypeCombo->insertItem( GEOM::FDT_Int,    tr("INT"));
831   myTypeCombo->insertItem( GEOM::FDT_Double, tr("DOUBLE"));
832   myTypeCombo->insertItem( GEOM::FDT_String, tr("STRING"));
833   myTypeCombo->setCurrentIndex( GEOM::FDT_Double ); // double
834
835   // dimension
836   QLabel* dimLabel = new QLabel( tr("SHAPE_TYPE"), propGroup );
837   myDimCombo = new QComboBox( propGroup );
838
839   // nb components
840   QLabel* nbCompsLabel = new QLabel( tr("NB_COMPS"), propGroup );
841   myNbCompsSpin = new SalomeApp_IntSpinBox( 1, 1000, 1, propGroup, true, true );
842   myNbCompsSpin->setValue( 1 );
843   propLayout->addWidget(shapeLabel,         0, 0);
844   propLayout->addWidget(myShapeSelBtn,      0, 1);
845   propLayout->addWidget(myShapeName,        0, 2);
846   propLayout->addWidget(typeLabel,          1, 0, 1, 2);
847   propLayout->addWidget(myTypeCombo,        1, 2);
848   propLayout->addWidget(dimLabel,           2, 0, 1, 2);
849   propLayout->addWidget(myDimCombo,         2, 2);
850   propLayout->addWidget(nbCompsLabel,       3, 0, 1, 2);
851   propLayout->addWidget(myNbCompsSpin,      3, 2);
852   // propLayout->addWidget(shapeLabel,         0, 0);
853   // propLayout->addWidget(myShapeName,        0, 1);
854   // propLayout->addWidget(typeLabel,          1, 0);
855   // propLayout->addWidget(myTypeCombo,        1, 1);
856   // propLayout->addWidget(dimLabel,           2, 0);
857   // propLayout->addWidget(myDimCombo,         2, 1);
858   // propLayout->addWidget(nbCompsLabel,       3, 0);
859   // propLayout->addWidget(myNbCompsSpin,      3, 1);
860
861   propLayout->setColumnStretch(2, 5);
862
863   // Field values
864
865   QGroupBox* valsGroup = new QGroupBox(tr("VALUES"), centralWidget());
866   QGridLayout* valsLayout = new QGridLayout(valsGroup);
867   valsLayout->setMargin(9);
868   valsLayout->setSpacing(6);
869
870   // value table
871   mySwitchTableWdg = new QWidget(valsGroup);
872   QVBoxLayout* switchTableGrpLayout = new QVBoxLayout(mySwitchTableWdg);
873   switchTableGrpLayout->setMargin(0);
874   switchTableGrpLayout->setSpacing(0);
875
876   // step add/rm controls
877   QPushButton* addStepBtn = new QPushButton( tr("ADD_STEP"), valsGroup );
878   QLabel* curStepLbl = new QLabel(tr("STEP"), valsGroup );
879   myStepEdit = new QLineEdit( valsGroup );
880   myStepsCombo = new QComboBox(valsGroup);
881   myStepsCombo->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
882   myRmStepBtn = new QPushButton( tr("REMOVE_STEP"), valsGroup );
883
884   // step browse controls
885   myPrevStepBtn = new QPushButton( tr("PREV_STEP"), valsGroup );
886   QLabel* stampLbl = new QLabel(tr("STAMP"), valsGroup );
887   myStampSpin = new SalomeApp_IntSpinBox( -theIntLimit, theIntLimit, 1, valsGroup, true, true);
888   myNextStepBtn = new QPushButton( tr("NEXT_STEP"), valsGroup );
889   
890   valsLayout->addWidget(mySwitchTableWdg,   0, 0, 1, 5);
891   valsLayout->addWidget(addStepBtn,         1, 0);
892   valsLayout->addWidget(curStepLbl,         1, 1);
893   valsLayout->addWidget(myStepEdit,         1, 2);
894   valsLayout->addWidget(myStepsCombo,       1, 3);
895   valsLayout->addWidget(myRmStepBtn,        1, 4);
896   valsLayout->addWidget(myPrevStepBtn,      2, 0);
897   valsLayout->addWidget(stampLbl,           2, 1);
898   valsLayout->addWidget(myStampSpin,        2, 2, 1, 2);
899   valsLayout->addWidget(myNextStepBtn,      2, 4);
900
901   valsLayout->setColumnStretch(3, 5);
902   valsLayout->setRowStretch   (0, 5);
903
904   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
905   layout->setMargin(0); layout->setSpacing(6);
906   layout->addWidget(propGroup);
907   layout->addWidget(valsGroup);
908
909   setHelpFileName("geom_field_page.html");
910
911   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
912   connect(aSelMgr,       SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
913
914   connect(myPrevStepBtn, SIGNAL(clicked()),                 this, SLOT( onPrevStep() ));
915   connect(myNextStepBtn, SIGNAL(clicked()),                 this, SLOT( onNextStep() ));
916   connect(addStepBtn,    SIGNAL(clicked()),                 this, SLOT( onAddStep() ));
917   connect(myRmStepBtn,   SIGNAL(clicked()),                 this, SLOT( onRmStep() ));
918   connect(myStampSpin,   SIGNAL(valueChanged(int)),         this, SLOT( onStampChange() ));
919   connect(myStepsCombo,  SIGNAL(currentIndexChanged(int)),  this, SLOT( showCurStep() ));
920   connect(myStepsCombo,  SIGNAL(activated(int)),            this, SLOT( showCurStep() ));
921
922   connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
923   connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
924
925   Init();
926   //updateState();
927 }
928
929 //=======================================================================
930 //function : ~EntityGUI_FieldDlg
931 //purpose  : 
932 //=======================================================================
933
934 EntityGUI_FieldDlg::~EntityGUI_FieldDlg()
935 {
936   GEOM_Displayer* aDisplayer = getDisplayer();
937   if (myIsHiddenMain) {
938     aDisplayer->Display(myShape);
939     myIsHiddenMain = false;
940   }
941   // if ( !myField->_is_nil())
942   //   aDisplayer->Display(myField);
943
944   QListIterator<int> anIter( myHiddenFieldStepIds );
945   while( anIter.hasNext() )
946   {
947     const int aStepId = anIter.next();
948     GEOM::GEOM_FieldStep_var step = myField->GetStep( aStepId );
949     if( !step->_is_nil() )
950       aDisplayer->Display( step, false );
951   }
952   aDisplayer->UpdateViewer();
953 }
954
955 //=================================================================================
956 // function : Init()
957 // purpose  :
958 //=================================================================================
959 void EntityGUI_FieldDlg::Init()
960 {
961   myDmMode = -1;
962   myHiddenFieldStepIds.clear();
963   myStepsCombo->clear();
964
965   if ( myIsCreation || myField->_is_nil() )
966   {
967     myIsCreation = true;
968     myStepTables.clear();
969     if ( myCurStepTable )
970       myCurStepTable->hide();
971     myCurStepTable = NULL;
972     myCurStepID = 0;
973
974     initName(tr("FIELD_PREFIX"));
975     myStampSpin->setValue(0);
976
977     SelectionIntoArgument();
978
979     onAddStep();
980
981     connect(myShapeSelBtn, SIGNAL(clicked()),                 this, SLOT(SetEditCurrentArgument()));
982     connect(myTypeCombo,   SIGNAL(currentIndexChanged(int)),  this, SLOT( onTypeChange()));
983     connect(myDimCombo,    SIGNAL(currentIndexChanged(int)),  this, SLOT( onDimChange()));
984     connect(myNbCompsSpin, SIGNAL(valueChanged(int)),         this, SLOT( onNbCompsChange()));
985
986   }
987   else // edition
988   {
989     // 1) get and sort step IDs
990     // 2) hide all displayed field steps' presentations
991     GEOM_Displayer* aDisplayer = getDisplayer();
992     GEOM::ListOfLong_var stepIDs = myField->GetSteps();
993     size_t i;
994     QList< int > stepsList;
995     for ( i = 0; i < stepIDs->length(); ++i )
996     {
997       int aStepId = stepIDs[i];
998       stepsList.push_back( aStepId );
999       GEOM::GEOM_FieldStep_var step = myField->GetStep( aStepId );
1000       if( !step->_is_nil() )
1001       {
1002         QString anEntry( step->GetStudyEntry() );
1003         if( aDisplayer->IsDisplayed( anEntry ) )
1004         {
1005           aDisplayer->Erase( step, false, false );
1006           myHiddenFieldStepIds << aStepId;
1007         }
1008       }
1009     }
1010     qSort( stepsList.begin(), stepsList.end() );
1011
1012     myIsCreation = false;
1013
1014     CORBA::String_var fName = myField->GetName();
1015     myMainFrame->ResultName->setText( fName.in() );
1016
1017     myShape = myField->GetShape();
1018     CORBA::String_var sName;
1019     if ( !myShape->_is_nil() )
1020       sName = myShape->GetName();
1021     myShapeName->setText( sName.in() ? sName.in() : "");
1022
1023     myTypeCombo->setCurrentIndex( myField->GetDataType() );
1024
1025     updateDims( myField->GetDimension() );
1026     updateShapeIDs();
1027
1028     GEOM::string_array_var compNames = myField->GetComponents();
1029     myNbCompsSpin->setValue( compNames->length() );
1030
1031     myShapeSelBtn->setEnabled( false );
1032     myShapeName->setEnabled( false );
1033     myTypeCombo->setEnabled( false );
1034     myDimCombo->setEnabled( false );
1035     myNbCompsSpin->setEnabled( false );
1036
1037     myStepsCombo->blockSignals( true );
1038     for ( i = 0; i < stepIDs->length(); ++i )
1039     {
1040       myStepsCombo->insertItem( i, QString::number( stepsList[i] ));
1041       if ( myCurStepID == stepsList[i] )
1042         myStepsCombo->setCurrentIndex( i );
1043     }
1044     // if ( myStepsCombo->count() == 0 )
1045     //   myStepsCombo->insertItem( 0, QString::number( myCurStepID ));
1046     myStepsCombo->blockSignals( false );
1047
1048     showCurStep();
1049     activateSelection();
1050   }
1051 }
1052
1053 //=================================================================================
1054 // function : enterEvent()
1055 // purpose  :
1056 //=================================================================================
1057 void EntityGUI_FieldDlg::enterEvent(QEvent*)
1058 {
1059   if (!buttonCancel()->isEnabled())
1060     ActivateThisDialog();
1061 }
1062
1063 //=================================================================================
1064 // function : ClickOnOk()
1065 // purpose  :
1066 //=================================================================================
1067 void EntityGUI_FieldDlg::ClickOnOk()
1068 {
1069   setIsApplyAndClose(true);
1070   if (ClickOnApply())
1071     ClickOnCancel();
1072   setIsApplyAndClose(false);
1073 }
1074
1075 //=================================================================================
1076 // function : ClickOnApply()
1077 // purpose  :
1078 //=================================================================================
1079 bool EntityGUI_FieldDlg::ClickOnApply()
1080 {
1081   if(!isApplyAndClose()) {
1082     setIsDisableBrowsing( true );
1083     setIsDisplayResult( false );
1084   }
1085
1086   QString msg;
1087   if ( !isValid( msg ) ) {
1088     showError( msg );
1089     return false;
1090   }
1091   SUIT_OverrideCursor wc;
1092   SUIT_Session::session()->activeApplication()->putInfo( "" );
1093
1094   try {
1095     if ( openCommand() )
1096       if (!execute (/*isApplyAndClose()*/))
1097       {
1098         abortCommand();
1099         showError();
1100         return false;
1101       }
1102   }
1103   catch( const SALOME::SALOME_Exception& e ) {
1104     SalomeApp_Tools::QtCatchCorbaException( e );
1105     abortCommand();
1106     return false;
1107   }
1108   commitCommand();
1109
1110   if(!isApplyAndClose()) {
1111     setIsDisableBrowsing( false );
1112     setIsDisplayResult( true );
1113   }
1114
1115   if ( myIsCreation )
1116   {
1117     myField = GEOM::GEOM_Field::_nil();
1118     if ( !isApplyAndClose() )
1119       Init();
1120   }
1121   return true;
1122 }
1123
1124 //=================================================================================
1125 // function : ActivateThisDialog()
1126 // purpose  :
1127 //=================================================================================
1128 void EntityGUI_FieldDlg::ActivateThisDialog()
1129 {
1130   GEOMBase_Skeleton::ActivateThisDialog();
1131
1132   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
1133           this, SLOT(SelectionIntoArgument()));
1134
1135   activateSelection();
1136 }
1137
1138 //=================================================================================
1139 // function : SetEditCurrentArgument()
1140 // purpose  :
1141 //=================================================================================
1142 void EntityGUI_FieldDlg::SetEditCurrentArgument()
1143 {
1144   myEditCurrentArgument = myShapeName;
1145   SelectionIntoArgument();
1146 }
1147
1148 //=================================================================================
1149 // function : SelectionIntoArgument()
1150 // purpose  : Called when selection has changed
1151 //=================================================================================
1152 void EntityGUI_FieldDlg::SelectionIntoArgument()
1153 {
1154   if (myEditCurrentArgument == myShapeName ||  // Selection of a shape is active
1155       myShape->_is_nil())
1156   {
1157     myShapeName->setText("");
1158     myShape = GEOM::GEOM_Object::_nil();
1159
1160     LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
1161     SALOME_ListIO aSelList;
1162     aSelMgr->selectedObjects(aSelList);
1163     int nbSel = aSelList.Extent();
1164
1165     if (nbSel == 1) {
1166       GEOM::GEOM_Object_var anObj =
1167         GEOMBase::ConvertIOinGEOMObject(aSelList.First());
1168
1169       if ( GEOMBase::IsShape(anObj) && anObj->IsMainShape() ) {
1170         if (myIsHiddenMain) {
1171           GEOM_Displayer* aDisplayer = getDisplayer();
1172           aDisplayer->Display(myShape);
1173           myIsHiddenMain = false;
1174         }
1175         myShapeName->setText(GEOMBase::GetName(anObj));
1176
1177         if ( !anObj->_is_nil() && !anObj->IsSame( myShape ))
1178         {
1179           myShape = anObj;
1180           myShapeMap.Clear();
1181           myEditCurrentArgument = 0;
1182
1183           // re-fill myDimCombo
1184           //const int curDim = getDim();
1185           updateDims( -100 );
1186
1187           // update table
1188           onDimChange();
1189         }
1190       }
1191     }
1192     else {
1193       if (myIsHiddenMain) {
1194         GEOM_Displayer* aDisplayer = getDisplayer();
1195         aDisplayer->Display(myShape);
1196         myIsHiddenMain = false;
1197       }
1198     }
1199   }
1200   else // select rows of a table according to shape selection
1201   {
1202     if ( !myCurStepTable )
1203       return;
1204
1205     bool isSignalsBlocked = myCurStepTable->signalsBlocked();
1206     myCurStepTable->blockSignals(true);
1207
1208     QList< int > rowsToSelect;
1209     TColStd_IndexedMapOfInteger aMapIndex;
1210     if ( getSelectedSubshapes(aMapIndex ))
1211       for (int ii = 1, nn = aMapIndex.Extent(); ii <= nn; ii++) {
1212         const int shapeID = aMapIndex( ii );
1213         for (int row = 0, n = myShapeIDs.size(); row < n; row++)
1214           if ( myShapeIDs[row] == shapeID ) {
1215             rowsToSelect.push_back( row );
1216             break;
1217           }
1218       }
1219     myCurStepTable->selectRows( rowsToSelect );
1220
1221     myCurStepTable->blockSignals(isSignalsBlocked);
1222   }
1223 }
1224
1225 //=================================================================================
1226 // function : onDimChange()
1227 // purpose  : update dialog at change of dimension
1228 //=================================================================================
1229 void EntityGUI_FieldDlg::onDimChange()
1230 {
1231   // get order of sub-shapes - myShapeIDs
1232   updateShapeIDs();
1233
1234   // update size of tables
1235   const int nbRows = myShapeIDs.size();
1236   QString subName = ( getDim() == -1 ) ? tr("WHOLE_SHAPE_VHEADER") : myDimCombo->currentText();
1237   QMap< int, StepTable* >::iterator tblIt = myStepTables.begin();
1238   for ( ; tblIt != myStepTables.end(); ++tblIt )
1239     if ( tblIt.value() )
1240       tblIt.value()->setDim( nbRows, subName );
1241
1242   activateSelection();
1243 }
1244
1245 //=======================================================================
1246 //function : onNbCompsChange
1247 //purpose  : 
1248 //=======================================================================
1249
1250 void EntityGUI_FieldDlg::onNbCompsChange()
1251 {
1252   QMap< int, StepTable* >::iterator tblIt = myStepTables.begin();
1253   for ( ; tblIt != myStepTables.end(); ++tblIt )
1254     if ( tblIt.value() )
1255       tblIt.value()->setNbComps( getNbComps() );
1256 }
1257
1258 //=======================================================================
1259 //function : onTypeChange
1260 //purpose  : 
1261 //=======================================================================
1262
1263 void EntityGUI_FieldDlg::onTypeChange()
1264 {
1265   QMap< int, StepTable* >::iterator tblIt = myStepTables.begin();
1266   for ( ; tblIt != myStepTables.end(); ++tblIt )
1267     if ( tblIt.value() )
1268       tblIt.value()->setDataType( myTypeCombo->currentIndex() );
1269 }
1270
1271 //=================================================================================
1272 // function : onPrevStep()
1273 // purpose  :
1274 //=================================================================================
1275 void EntityGUI_FieldDlg::onPrevStep()
1276 {
1277   int i = myStepsCombo->currentIndex();
1278   if ( i > 0 )
1279   {
1280     myStepsCombo->setCurrentIndex( i-1 );
1281     showCurStep();
1282   }
1283 }
1284
1285 //=================================================================================
1286 // function : onNextStep()
1287 // purpose  :
1288 //=================================================================================
1289 void EntityGUI_FieldDlg::onNextStep()
1290 {
1291   int i = myStepsCombo->currentIndex();
1292   if ( i+1 < myStepsCombo->count() )
1293   {
1294     myStepsCombo->setCurrentIndex( i+1 );
1295     showCurStep();
1296   }
1297 }
1298
1299 static int findInCombo( QComboBox* where, int what, bool& ok )
1300 {
1301   int idx = 0;
1302   ok = false;
1303
1304   for ( ; idx < where->count() && !ok; idx++ ) {
1305     int step = where->itemText( idx ).toInt();
1306     if ( step == what ) {
1307       ok = true;
1308     }
1309     else if ( step > what )
1310       break;
1311   }
1312   
1313   return idx;
1314 }
1315
1316 //=======================================================================
1317 //function : onAddStep
1318 //purpose  : 
1319 //=======================================================================
1320 void EntityGUI_FieldDlg::onAddStep()
1321 {
1322   int step = 0;
1323
1324   if ( !myStepEdit->text().isEmpty() )
1325     step = myStepEdit->text().toInt();
1326   bool ok = false;
1327   int idx = findInCombo( myStepsCombo, step, ok );
1328   
1329   if ( ok ) {
1330     SUIT_MessageBox::critical(this, QObject::tr("ERR_ERROR"),
1331                               tr("ERR_STEP_EXISTS"));
1332     return;
1333   }
1334
1335   myStepsCombo->insertItem( idx, QString::number( step ));
1336   myStepsCombo->setCurrentIndex( idx );
1337   myRemovedSteps.remove( getCurStepID() );
1338   //showCurStep();
1339 }
1340
1341 //=======================================================================
1342 //function : onRmStep
1343 //purpose  : 
1344 //=======================================================================
1345 void EntityGUI_FieldDlg::onRmStep()
1346 {
1347   if ( myStepsCombo->count() > 1 )
1348   {
1349     myStepTables.remove( getCurStepID() );
1350     myRemovedSteps.insert( getCurStepID() );
1351     if ( myCurStepTable )
1352       myCurStepTable->hide();
1353     myCurStepTable = NULL;
1354     myStepsCombo->removeItem( myStepsCombo->currentIndex() );
1355     //showCurStep();
1356   }
1357 }
1358
1359 //=======================================================================
1360 //function : onStampChange
1361 //purpose  : 
1362 //=======================================================================
1363 void EntityGUI_FieldDlg::onStampChange()
1364 {
1365   if ( myCurStepTable )
1366     myCurStepTable->setStamp( myStampSpin->value() );
1367 }
1368
1369 //=======================================================================
1370 //function : showCurStep
1371 //purpose  : 
1372 //=======================================================================
1373 void EntityGUI_FieldDlg::showCurStep()
1374 {
1375   myCurStepID = getCurStepID(); 
1376   myStepEdit->setText(QString::number( myCurStepID ));
1377
1378   QStringList headers;
1379   if ( myCurStepTable )
1380   {
1381     if ( myCurStepTable->getStepID() == myCurStepID )
1382     {
1383       myCurStepTable->show();
1384       return;
1385     }
1386     else
1387     {
1388       myCurStepTable->hide();
1389       headers = myCurStepTable->getHeaders();
1390       myCurStepTable->getStamp();
1391     }
1392   }
1393
1394   if ( myStepTables.count ( myCurStepID ))
1395   {
1396     myCurStepTable = myStepTables[ myCurStepID ];
1397     myCurStepTable->setHeaders( headers );
1398   }
1399   else
1400   {
1401     // if ( myStepsCombo->count() == 0 )
1402     //   return; // edit a field with no steps
1403
1404     // get step values
1405     GEOM::GEOM_FieldStep_var stepVar;
1406     if ( !myField->_is_nil() )
1407       stepVar = myField->GetStep( myCurStepID );
1408
1409     int nbComps = getNbComps();
1410     if ( headers.count() == 0 )
1411     {
1412       headers << tr("SUB_SHAPE_HEADER");
1413       if ( !myIsCreation && !myField->_is_nil() )
1414       {
1415         GEOM::string_array_var compNames = myField->GetComponents();
1416         for ( int iC = 0; iC < (int)compNames->length(); ++iC )
1417           headers << compNames[ iC ].in();
1418       }
1419       else
1420       {
1421         for ( int iC = 0; iC < nbComps; ++iC )
1422           headers << QString("Comp %1").arg( iC + 1 );
1423       }
1424     }
1425     QString subName = ( getDim() == -1 ) ? tr("WHOLE_SHAPE_VHEADER") : myDimCombo->currentText();
1426     myCurStepTable = new StepTable( myCurStepID, getDataType(), myShapeIDs.size(),
1427                                     nbComps, subName, headers, stepVar, mySwitchTableWdg );
1428     myStepTables[ myCurStepID ] = myCurStepTable;
1429     mySwitchTableWdg->layout()->addWidget( myCurStepTable );
1430   }
1431   myCurStepTable->show();
1432   myStampSpin->setValue( myCurStepTable->getStamp() );
1433
1434   connect(myCurStepTable, SIGNAL(itemSelectionChanged()), this, SLOT( highlightSubShapes() ));
1435
1436   myPrevStepBtn->setEnabled( myStepsCombo->currentIndex() > 0 );
1437   myNextStepBtn->setEnabled( myStepsCombo->currentIndex()+1 < myStepsCombo->count() );
1438   myRmStepBtn->setEnabled( myStepsCombo->count() > 1 );
1439 }
1440
1441 //=================================================================================
1442 // function : getSelectedSubshapes
1443 // purpose  :
1444 //=================================================================================
1445 int EntityGUI_FieldDlg::getSelectedSubshapes (TColStd_IndexedMapOfInteger& theMapIndex)
1446 {
1447   theMapIndex.Clear();
1448
1449   SalomeApp_Application* app = myGeomGUI->getApp();
1450   if (!app || myShape->_is_nil())
1451     return 0;
1452
1453   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
1454   SALOME_ListIO aSelList;
1455   aSelMgr->selectedObjects(aSelList);
1456
1457   // try to find out and process the global selection
1458   // (of not published objects and of published sub-shapes)
1459   {
1460     SALOME_ListIteratorOfListIO anIter (aSelList);
1461     for (int i = 0; anIter.More(); anIter.Next(), i++)
1462     {
1463       Handle(SALOME_InteractiveObject) anIObj = anIter.Value();
1464       QString anEntry = anIObj->getEntry();
1465       QString str = "_";
1466       int index = anEntry.lastIndexOf(str);
1467       if (index > 0) // selection among special preview
1468       {
1469         anEntry.remove(0, index+1);
1470         int anIndex = anEntry.toInt();
1471         if (anIndex)
1472           theMapIndex.Add(anIndex);
1473       }
1474       else // selection among published shapes
1475       {
1476         SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>(app->activeStudy());
1477         if (!appStudy) return 0;
1478         _PTR(Study) aStudy = appStudy->studyDS();
1479
1480         _PTR(SObject) aSObj (aStudy->FindObjectID(anEntry.toUtf8().constData()));
1481         if ( ! GeometryGUI::IsInGeomComponent( aSObj )) continue;
1482         GEOM::GEOM_Object_var aGeomObj =
1483           GEOM::GEOM_Object::_narrow(GeometryGUI::ClientSObjectToObject(aSObj));
1484         TopoDS_Shape aShape;
1485         if (GEOMBase::GetShape(aGeomObj, aShape)) {
1486           if (aGeomObj->GetType() == GEOM_GROUP || aShape.ShapeType() == getShapeType())
1487           {
1488             TopExp_Explorer anExp (aShape, getShapeType());
1489             for (; anExp.More(); anExp.Next()) {
1490               TopoDS_Shape aSubShape = anExp.Current();
1491               int anIndex = myShapeMap.FindIndex(aSubShape);
1492               if (anIndex == 0) {
1493                 SUIT_MessageBox::warning(app->desktop(), QObject::tr("WRN_WARNING"),
1494                                          tr("WRN_NOT_SUBSHAPE"));
1495               }
1496               theMapIndex.Add(anIndex);
1497             }
1498           }
1499         }
1500       }
1501     } // for aSelList
1502   }
1503
1504   return theMapIndex.Extent();
1505 }
1506
1507 //=================================================================================
1508 // function : getShapeType()
1509 // purpose  :
1510 //=================================================================================
1511 TopAbs_ShapeEnum EntityGUI_FieldDlg::getShapeType(int* dim) const
1512 {
1513   
1514   switch ( dim ? *dim : getDim() )
1515   {
1516   case 0:  return TopAbs_VERTEX;
1517   case 1:  return TopAbs_EDGE;
1518   case 2:  return TopAbs_FACE;
1519   case 3:  return TopAbs_SOLID;
1520   default: return TopAbs_SHAPE;
1521   }
1522 }
1523
1524 //=======================================================================
1525 //function : getDim
1526 //purpose  : 
1527 //=======================================================================
1528 int EntityGUI_FieldDlg::getDim() const
1529 {
1530   int i = myDimCombo->currentIndex();
1531   return ( i < 0 ) ? -1 : myDimCombo->itemData( i ).toInt();
1532 }
1533
1534 //=======================================================================
1535 //function : getDataType
1536 //purpose  : 
1537 //=======================================================================
1538 int EntityGUI_FieldDlg::getDataType() const
1539 {
1540   return myTypeCombo->currentIndex();
1541 }
1542
1543 //=======================================================================
1544 //function : getCurStepID
1545 //purpose  : 
1546 //=======================================================================
1547 int EntityGUI_FieldDlg::getCurStepID() const
1548 {
1549   if ( myStepsCombo->count() > 0 )
1550     return myStepsCombo->currentText().toInt();
1551   return myCurStepID;
1552 }
1553
1554 //=======================================================================
1555 //function : getNbComps
1556 //purpose  : 
1557 //=======================================================================
1558 int EntityGUI_FieldDlg::getNbComps() const
1559 {
1560   return myNbCompsSpin->value();
1561 }
1562
1563 //=================================================================================
1564 // function : updateShapeIDs()
1565 // purpose  : update myShapeIDs
1566 //=================================================================================
1567 void EntityGUI_FieldDlg::updateShapeIDs()
1568 {
1569   myShapeIDs.clear();
1570   //myShapeMap.Clear();
1571   if ( !myShape->_is_nil() )
1572   {
1573     TopoDS_Shape aShape =
1574       GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), myShape);
1575     if ( myShapeMap.IsEmpty() )
1576       TopExp::MapShapes(aShape, myShapeMap);
1577     TopAbs_ShapeEnum shapeType = getShapeType();
1578     if ( shapeType == TopAbs_SHAPE )
1579     {
1580       myShapeIDs.push_back( 1 );
1581     }
1582     else
1583     {
1584       TopTools_IndexedMapOfShape dimSubShapesMap;
1585       TopExp::MapShapes(aShape, shapeType, dimSubShapesMap);
1586       myShapeIDs.resize( dimSubShapesMap.Extent() );
1587       for ( int i = 1; i <= dimSubShapesMap.Extent(); ++i )
1588         myShapeIDs[i-1] = myShapeMap.FindIndex( dimSubShapesMap(i) );
1589     }
1590   }
1591 }
1592
1593 //=======================================================================
1594 //function : updateDims
1595 //purpose  : update myDimCombo
1596 //=======================================================================
1597 void EntityGUI_FieldDlg::updateDims(int curDim)
1598 {
1599   myDimCombo->blockSignals( true );
1600   myDimCombo->clear();
1601   TopoDS_Shape aShape =
1602     GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), myShape);
1603
1604   if ( !aShape.IsNull() )
1605   {
1606     const char* subNames[4] = { "VERTEX","EDGE","FACE","SOLID" };
1607     TopExp_Explorer exp;
1608     for ( int dim = 0; dim < 4; ++dim )
1609     {
1610       exp.Init( aShape, getShapeType(&dim));
1611       if ( exp.More() && !aShape.IsSame( exp.Current() ))
1612         myDimCombo->insertItem( dim, tr( subNames[dim] ), dim );
1613     }
1614     myDimCombo->insertItem( 4, tr("WHOLE"), -1 );
1615
1616     int idx = myDimCombo->findData( curDim );
1617     if ( idx != -1 )
1618       myDimCombo->setCurrentIndex( idx );
1619     else 
1620       myDimCombo->setCurrentIndex( myDimCombo->count()-1-(myDimCombo->count()>1?1:0) );
1621   }
1622   myDimCombo->blockSignals( false );
1623 }
1624
1625 //=================================================================================
1626 // function : activateSelection
1627 // purpose  : Activate local selection
1628 //=================================================================================
1629 void EntityGUI_FieldDlg::activateSelection()
1630 {
1631   //bool isApply = ((QPushButton*)sender() == buttonApply());
1632   if(!isApplyAndClose())
1633     erasePreview(false);
1634
1635   // local selection
1636   if (!myShape->_is_nil() &&
1637       !myEditCurrentArgument &&
1638       myShapeIDs.size() > 1 ) // shape type is already chosen by user
1639   {
1640     GEOM_Displayer*   aDisplayer = getDisplayer();
1641     CORBA::String_var aMainEntry = myShape->GetStudyEntry();
1642
1643     //display mode for main shape
1644     if ( myDmMode == -1 ) {
1645       SALOME_View* view = GEOM_Displayer::GetActiveView();
1646       if (view) {
1647         Handle(SALOME_InteractiveObject) io =
1648           new SALOME_InteractiveObject (aMainEntry.in(), "GEOM", "TEMP_IO");
1649         if ( view->isVisible( io ) ) {
1650           Handle(GEOM_AISShape) aSh = GEOMBase::ConvertIOinGEOMAISShape( io, true );
1651           if(!aSh.IsNull()) {
1652             myDmMode = aSh->isTopLevel() ? aSh->prevDisplayMode() : aSh->DisplayMode();
1653           }
1654           // Hide main shape, if explode on VERTEX
1655           if(getShapeType() != TopAbs_VERTEX) {
1656             aDisplayer->Erase(myShape, false, false);
1657             myIsHiddenMain = true;
1658           }
1659         }
1660         else
1661           myDmMode = SUIT_Session::session()->resourceMgr()->integerValue( "Geometry", "display_mode" );
1662       }
1663     }
1664     aDisplayer->SetDisplayMode(myDmMode);
1665
1666     // Mantis issue 0021421: do not hide main shape, if explode on VERTEX
1667     if (getShapeType() == TopAbs_VERTEX) {
1668       if (myIsHiddenMain)
1669         aDisplayer->Display(myShape);
1670     }
1671     //aDisplayer->Erase(myField, false, false); ------- NOR YET implemented
1672
1673     QColor aColor = SUIT_Session::session()->resourceMgr()->colorValue( "Geometry", "editField_color" );
1674     Quantity_NameOfColor aCol = SalomeApp_Tools::color( aColor ).Name();
1675
1676     if(!isApplyAndClose()) {
1677       SUIT_ViewWindow* aViewWindow = 0;
1678       SUIT_Study* activeStudy = SUIT_Session::session()->activeApplication()->activeStudy();
1679       if (activeStudy)
1680         aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
1681       if (aViewWindow == 0) return;
1682
1683       SUIT_ViewManager* aViewManager = aViewWindow->getViewManager();
1684       if (aViewManager->getType() != OCCViewer_Viewer::Type() &&
1685           aViewManager->getType() != SVTK_Viewer::Type())
1686         return;
1687
1688       SUIT_ViewModel* aViewModel = aViewManager->getViewModel();
1689       SALOME_View* aView = dynamic_cast<SALOME_View*>(aViewModel);
1690       if (aView == 0) return;
1691
1692       TopoDS_Shape aMainShape = myShapeMap(1);
1693       for ( int i = 0; i < myShapeIDs.size(); ++i )
1694       {
1695         int index = myShapeIDs[ i ];
1696         TopoDS_Shape aSubShape = myShapeMap( index );
1697         QString anEntry = QString( "TEMP_" ) + aMainEntry.in() + QString("_%1").arg(index);
1698         Handle(SALOME_InteractiveObject) io =
1699           new SALOME_InteractiveObject(anEntry.toUtf8(), "GEOM", "TEMP_IO");
1700         aDisplayer->SetColor( aCol );
1701         SALOME_Prs* aPrs = aDisplayer->buildSubshapePresentation(aSubShape, anEntry, aView);
1702         if (aPrs) {
1703           displayPreview(aPrs, true, false); // append, do not update
1704           // TODO: map or delete Prs
1705         }
1706       }
1707       aDisplayer->UnsetDisplayMode();
1708       aDisplayer->UnsetColor();
1709       aDisplayer->UpdateViewer();
1710     }
1711   }
1712
1713   globalSelection(GEOM_ALLSHAPES);
1714
1715   SelectionIntoArgument();
1716 }
1717
1718 //=================================================================================
1719 // function : highlightSubShapes
1720 // purpose  : select objects corresponding to selected table rows
1721 //=================================================================================
1722 void EntityGUI_FieldDlg::highlightSubShapes()
1723 {
1724   if (CORBA::is_nil(myShape) || !myCurStepTable )
1725     return;
1726
1727   TColStd_MapOfInteger anIds;
1728   QList<int> rows = myCurStepTable->selectedRows();
1729   int ii = 0, nn = rows.count();
1730   for (; ii < nn; ii++)
1731   {
1732     int shapeNum = rows[ ii ];
1733     if ( shapeNum < myShapeIDs.size() )
1734       anIds.Add( myShapeIDs[ shapeNum ]);
1735   }
1736
1737   SalomeApp_Application* app = myGeomGUI->getApp();
1738   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
1739   aSelMgr->clearSelected();
1740   if ( anIds.IsEmpty() )
1741     return;
1742
1743   SUIT_ViewWindow* aViewWindow = 0;
1744   SUIT_Study* activeStudy = app->activeStudy();
1745   if (activeStudy)
1746     aViewWindow = app->desktop()->activeWindow();
1747   if (aViewWindow == 0) return;
1748
1749   SUIT_ViewManager* aViewManager = aViewWindow->getViewManager();
1750   if (aViewManager->getType() != OCCViewer_Viewer::Type() &&
1751       aViewManager->getType() != SVTK_Viewer::Type())
1752     return;
1753
1754   SUIT_ViewModel* aViewModel = aViewManager->getViewModel();
1755   SALOME_View* aView = dynamic_cast<SALOME_View*>(aViewModel);
1756   if (aView == 0) return;
1757
1758   // TODO??: use here GEOMBase_Helper::myPreview instead of ic->DisplayedObjects()
1759
1760   OCCViewer_Viewer* v3d = ((OCCViewer_ViewManager*)aViewManager)->getOCCViewer();
1761   Handle(AIS_InteractiveContext) ic = v3d->getAISContext();
1762   AIS_ListOfInteractive List;
1763   //ic->DisplayedObjects(List);
1764   ic->ObjectsInside(List); // Mantis issue 0021367
1765
1766   SALOME_ListIO aSelList;
1767
1768   // To highlight the selected sub-shape in Object Browser, if it's already published under the main shape
1769   GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations();
1770   QMap<int, QString> childsMap;
1771   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>(app->activeStudy());
1772   if (appStudy) {
1773     _PTR(Study) aStudy = appStudy->studyDS();
1774     CORBA::String_var aMainEntry = myShape->GetStudyEntry();
1775     _PTR(SObject) aSObj = aStudy->FindObjectID( aMainEntry.in() );
1776     _PTR(ChildIterator) anIt = aStudy->NewChildIterator(aSObj);
1777     if ( GeometryGUI::IsInGeomComponent( aSObj ))
1778       for (anIt->InitEx(true); anIt->More(); anIt->Next()) {
1779         GEOM::GEOM_Object_var aChild =
1780           GEOM::GEOM_Object::_narrow(GeometryGUI::ClientSObjectToObject(anIt->Value()));
1781         if (!CORBA::is_nil(aChild)) {
1782           int index = aLocOp->GetSubShapeIndex(myShape, aChild);
1783           if ( anIds.Contains( index )) {
1784             CORBA::String_var aChildEntry = aChild->GetStudyEntry();
1785             //childsMap.insert(index, aChildEntry.in());
1786             Handle(SALOME_InteractiveObject) tmpIO =
1787               new SALOME_InteractiveObject( aChildEntry.in(), "GEOM", "TEMP_IO");
1788             aSelList.Append(tmpIO);
1789           }
1790         }
1791       }
1792   }
1793
1794   AIS_ListIteratorOfListOfInteractive ite (List);
1795   for (; ite.More(); ite.Next()) {
1796     if (ite.Value()->IsInstance(STANDARD_TYPE(GEOM_AISShape))) {
1797       Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast(ite.Value());
1798       if (aSh->hasIO()) {
1799         Handle(SALOME_InteractiveObject) anIO = aSh->getIO();
1800         QString anEntry = anIO->getEntry();
1801         int index = anEntry.lastIndexOf("_");
1802         anEntry.remove(0, index+1);
1803         int anIndex = anEntry.toInt();
1804         if (anIds.Contains(anIndex)) {
1805           aSelList.Append(anIO);
1806           // if (childsMap.contains (anIndex)) {
1807           //   Handle(SALOME_InteractiveObject) tmpIO = new SALOME_InteractiveObject(childsMap.value(anIndex).toUtf8().constData(), "GEOM", "TEMP_IO");
1808           //   aSelList.Append(tmpIO);
1809           // }
1810         }
1811       }
1812     }
1813   }
1814   aSelMgr->setSelectedObjects(aSelList);
1815 }
1816
1817 //=================================================================================
1818 // function : createOperation
1819 // purpose  :
1820 //=================================================================================
1821 GEOM::GEOM_IOperations_ptr EntityGUI_FieldDlg::createOperation()
1822 {
1823   return getGeomEngine()->GetIFieldOperations();
1824 }
1825
1826 #define RETURN_WITH_MSG(a, b) \
1827   if ((a)) { \
1828     theMessage += (b); \
1829     return false; \
1830   }
1831
1832 //=================================================================================
1833 // function : isValid()
1834 // purpose  : Verify validity of input data
1835 //=================================================================================
1836 bool EntityGUI_FieldDlg::isValid(QString& theMessage)
1837 {
1838   SalomeApp_Study* study = getStudy();
1839   RETURN_WITH_MSG  (!study, tr("GEOM_NO_STUDY"))
1840   RETURN_WITH_MSG  (study->studyDS()->GetProperties()->IsLocked(), tr("GEOM_STUDY_LOCKED"))
1841
1842   if ( myIsCreation ) {
1843     RETURN_WITH_MSG(CORBA::is_nil(myShape), tr("NO_SHAPE"))
1844   }
1845   else {
1846     RETURN_WITH_MSG(CORBA::is_nil(myShape), tr("NO_FIELD"))
1847   }
1848
1849   QString aName = getNewObjectName().trimmed();
1850   RETURN_WITH_MSG  (aName.isEmpty(), tr("EMPTY_NAME"))
1851
1852   RETURN_WITH_MSG  ( !myCurStepTable, tr("NO_VALUES"))
1853   return true;
1854 }
1855
1856 //=================================================================================
1857 // function : execute
1858 // purpose  :
1859 //=================================================================================
1860 bool EntityGUI_FieldDlg::execute()
1861 {
1862   SALOMEDS::Study_var aStudyDS = GeometryGUI::getStudyServant();
1863   SALOMEDS::StudyBuilder_var aBuilder = aStudyDS->NewBuilder();
1864
1865   QString aName = getNewObjectName().trimmed();
1866   QStringList anEntryList;
1867
1868   if ( myField->_is_nil() ) // create field
1869   {
1870     QStringList columnNames = myCurStepTable->getHeaders();
1871     int nbComps = columnNames.count() - 1;
1872     GEOM::string_array_var compNames = new GEOM::string_array();
1873     compNames->length( nbComps );
1874     for ( int iC = 0; iC < nbComps; ++iC )
1875       compNames[ iC ] = columnNames[ iC+1 ].toUtf8().constData();
1876
1877     GEOM::GEOM_IFieldOperations_var anOper = GEOM::GEOM_IFieldOperations::_narrow(getOperation());
1878     myField = anOper->CreateField( myShape,
1879                                    aName.toUtf8().constData(),
1880                                    GEOM::field_data_type( getDataType() ),
1881                                    CORBA::Short( getDim() ),
1882                                    compNames );
1883     if ( myField->_is_nil() )
1884       return false;
1885     
1886     SALOMEDS::SObject_wrap aSO =
1887       getGeomEngine()->AddInStudy( myField, aName.toUtf8().constData(), myShape );
1888     if ( !aSO->_is_nil() ) {
1889       myField->UnRegister();
1890       CORBA::String_var entry = aSO->GetID();
1891       anEntryList << entry.in();
1892     }
1893   }
1894   else // update field name
1895   {
1896     myField->SetName( aName.toUtf8().constData() );
1897
1898     CORBA::String_var entry = myField->GetStudyEntry();
1899     if ( entry.in() ) {
1900       SALOMEDS::SObject_wrap SO = aStudyDS->FindObjectID( entry.in() );
1901       if ( !SO->_is_nil() ) {
1902         aBuilder->SetName(SO, aName.toUtf8().constData());
1903       }
1904     }
1905   }
1906
1907   // create / update steps
1908   QMap< int, StepTable* >::iterator i_tbl = myStepTables.begin();
1909   for ( ; i_tbl != myStepTables.end(); ++i_tbl )
1910   {
1911     StepTable* tbl = i_tbl.value();
1912     QString stepName = (tr("STEP")+" %1 %2").arg( tbl->getStepID() ).arg( tbl->getStamp() );
1913
1914     GEOM::GEOM_FieldStep_var step = tbl->getStep();
1915     if ( step->_is_nil() )
1916     {
1917       step = myField->GetStep( tbl->getStepID() );
1918       if ( step->_is_nil() )
1919       {
1920         step = myField->AddStep( tbl->getStepID(), tbl->getStamp() );
1921
1922         SALOMEDS::SObject_wrap aSO =
1923           getGeomEngine()->AddInStudy( step, stepName.toUtf8().constData(), myField );
1924         if ( /*!myIsCreation &&*/ !aSO->_is_nil() ) {
1925           step->UnRegister();
1926           CORBA::String_var entry = aSO->GetID();
1927           anEntryList << entry.in();
1928         }
1929       }
1930     }
1931     else if ( step->GetStamp() != tbl->getStamp() )
1932     {
1933       // update a stamp in the object browser
1934       CORBA::String_var entry = step->GetStudyEntry();
1935       if ( entry.in() ) {
1936         SALOMEDS::SObject_wrap SO = aStudyDS->FindObjectID( entry.in() );
1937         if ( !SO->_is_nil() )
1938           aBuilder->SetName( SO, stepName.toUtf8().constData() );
1939       }
1940     }
1941
1942     tbl->setValues( step );
1943
1944     // update the presentation if it is displayed
1945     CORBA::String_var aStepEntry = step->GetStudyEntry();
1946     Handle(SALOME_InteractiveObject) aStepIO =
1947       new SALOME_InteractiveObject( aStepEntry.in(), "GEOM", "TEMP_IO" );
1948     getDisplayer()->Redisplay( aStepIO, false, false );
1949   }
1950   getDisplayer()->UpdateViewer();
1951
1952   // remove steps
1953   if ( !myIsCreation )
1954   {
1955     QSet< int >::iterator stepID = myRemovedSteps.begin();
1956     for ( ; stepID != myRemovedSteps.end(); ++stepID )
1957     {
1958       GEOM::GEOM_FieldStep_var step = myField->GetStep( *stepID );
1959       if ( !step->_is_nil() )
1960       {
1961         CORBA::String_var entry = step->GetStudyEntry();
1962         myField->RemoveStep( *stepID );
1963
1964         if ( entry.in() ) {
1965           SALOMEDS::SObject_wrap SO = aStudyDS->FindObjectID( entry.in() );
1966           if ( !SO->_is_nil() )
1967             aBuilder->RemoveObjectWithChildren( SO );
1968         }
1969       }
1970     }
1971   }
1972   myRemovedSteps.clear();
1973
1974   updateObjBrowser();
1975
1976   if( SUIT_Application* anApp = SUIT_Session::session()->activeApplication() ) {
1977     LightApp_Application* aLightApp = dynamic_cast<LightApp_Application*>( anApp );
1978     if( aLightApp && !isDisableBrowsing() && anEntryList.count() )
1979     {
1980       aLightApp->browseObjects( anEntryList, isApplyAndClose(), isOptimizedBrowsing() );
1981       anApp->putInfo( QObject::tr("GEOM_PRP_DONE") );
1982     }
1983   }
1984
1985   return true;
1986 }
1987
1988 //=================================================================================
1989 // function : getSourceObjects
1990 // purpose  : virtual method to get source objects
1991 //=================================================================================
1992 QList<GEOM::GeomObjPtr> EntityGUI_FieldDlg::getSourceObjects()
1993 {
1994   QList<GEOM::GeomObjPtr> res;
1995   GEOM::GeomObjPtr aGeomObjPtr(myField->GetShape());
1996   res << aGeomObjPtr;
1997   return res;
1998 }