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