Salome HOME
0054504: Exception when accessing VTK renderer with libSalomePy module
[modules/gui.git] / src / QDS / QDS_RadioBox.cxx
1 // Copyright (C) 2007-2016  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 #include "QDS_RadioBox.h"
24
25 #include <TColStd_HArray1OfInteger.hxx>
26 #include <TColStd_HArray1OfExtendedString.hxx>
27
28 #include <QButtonGroup>
29 #include <QGroupBox>
30 #include <QVBoxLayout>
31 #include <QRadioButton>
32
33 /*
34   \class QDS_RadioBox
35   \brief Datum with control corresponding to button group with set of exclusive radio buttons.
36
37   This control used for datum with enumerable values. It can be used for datum which has
38   type of value 'List'. Each radio button of group box is defined by two properties:
39   integer identifier and string name. All operations on radio buttons are performed via identifier.
40
41   If datum label text is specified, then it is displayed in the group box title.
42 */
43
44 /*!
45   \brief Constructor. 
46
47   Create radio button box datum object with datum identifier \a id and parent widget \a parent.
48   
49   Parameter \a flags defines behaviour of datum and set of created
50   subwidgets. Default value of this parameter is QDS::All. 
51   
52   Parameter \a comp specifies the component name which will be used
53   when searching the dictionary item.
54
55   \param id datum identifier
56   \param parent parent widget
57   \param flags datum flags
58   \param comp component
59 */
60 QDS_RadioBox::QDS_RadioBox( const QString& id, QWidget* parent, const int flags, const QString& comp )
61 : QDS_Datum( id, parent, flags & ~( Label | Units ), comp ),
62   myButtonGroup( 0 )
63 {
64 }
65
66 /*!
67   \brief Destructor.
68 */
69 QDS_RadioBox::~QDS_RadioBox()
70 {
71 }
72
73 /*!
74   \brief Get number of buttons in radio box.
75
76   If \a total is \c false, only visible buttons are taken into account; 
77   otherwise total number of buttons is returned
78
79   \param total get number of visible buttons if \c true and total number of buttons if \c false
80   \return requested number of items
81 */
82 int QDS_RadioBox::count( bool total ) const
83 {
84   if ( total )
85     return myValue.count();
86   else
87   {
88     QList<QRadioButton*> bList;
89     buttons( bList );
90     return bList.count();
91   }
92 }
93
94 /*!
95   \brief Get buttons identifiers.
96   \param ids returned list of buttons IDs
97   \param total take into account only visible buttons if \c true and all buttons if \c false
98 */
99 void QDS_RadioBox::values( QList<int>& ids, bool total ) const
100 {
101   ids.clear();
102   for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it )
103     if ( total || ( myState.contains( *it ) && myState[*it] ) )
104       ids.append( *it );
105 }
106
107 /*!
108   \brief Get visibility state of the button specified by \a id.
109   \param id button ID
110   \return item visibility state
111 */
112 bool QDS_RadioBox::state( const int id ) const
113 {
114   bool state = false;
115   if ( myState.contains( id ) )
116     state = myState[id];
117   return state;
118 }
119
120 /*!
121   \brief Set the visibility state of the button specified by \a id.
122
123   If \a id is -1 then specified state will be set to all buttons.
124
125   If \a append is set to \c true, keep current status for other buttons,
126   otherwise status of other buttons is cleared.
127
128   \param on new visibility state
129   \param id button ID
130   \param append if \c true, keep original status for other buttons
131 */
132 void QDS_RadioBox::setState( const bool on, const int id, const bool append )
133 {
134   QList<int> lst;
135   if ( id < 0 )
136   {
137     for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it )
138       lst.append( it.key() );
139   }
140   else
141     lst.append( id );
142
143   setState( on, lst, append );
144 }
145
146 /*!
147   \brief Set the visibility state of buttons specified by \a ids.
148
149   If \a append is set to \c true, keep the current status for other buttons,
150   otherwise status of other buttons is cleared.
151
152   \param on new visibility state
153   \param ids buttons IDs list
154   \param append if \c true, keep original status for other buttons
155 */
156 void QDS_RadioBox::setState( const bool on, const QList<int>& ids, const bool append )
157 {
158   if ( ids.isEmpty() && append )
159     return;
160
161   bool changed = false;
162
163   QMap<int, int> aMap;
164   for ( uint i = 0; i < ids.count(); i++ )
165     aMap.insert( ids.at( i ), 0 );
166
167   for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it )
168   {
169     if ( aMap.contains( it.key() ) )
170     {
171       if ( it.value() != on )
172       {
173         it.value() = on;
174         changed = true;
175       }
176     }
177     else if ( !append && it.value() == on )
178     {
179       it.value() = !on;
180       changed = true;
181     }
182   }
183   if ( changed )
184     updateRadioBox();
185 }
186
187 /*!
188   \brief Set the custom user buttons into the radio box.
189
190   User items like standard dictionary buttons will be added
191   into the radio box. This function allows user to customize
192   buttons.
193
194   \param ids buttons IDs
195   \param names buttons names
196 */
197 void QDS_RadioBox::setValues( const QList<int>& ids, const QStringList& names )
198 {
199   if ( ids.count() != names.count() )
200     return;
201
202   myUserIds = ids;
203   myUserNames = names;
204 }
205
206 /*!
207   \brief Set the custom user buttons into the radio box.
208   \overload
209
210   User buttons like standard dictionary buttons will be added
211   into the radio box. This function allows user to customize
212   buttons.
213
214   Uses (0, 1, 2 ... ) as buttons IDs.
215
216   \param names buttons names
217 */
218 void QDS_RadioBox::setValues( const QStringList& names )
219 {
220   QList< int > ids;
221   for ( int i = 0, n = names.count(); i < n; i++ )
222     ids.append( i );
223   setValues( ids, names );
224 }
225
226 /*!
227   \brief Get string from the radio box.
228
229   String which contains identifier of the currently selected button is returned.
230   \return identifier of the current button converted to string
231 */
232 QString QDS_RadioBox::getString() const
233 {
234   QString res;
235   QButtonGroup* bg = buttonGroup();
236   if ( bg )
237   {
238     int id = bg->checkedId();
239     if ( id != -1 )
240       res = QString::number( id );
241   }
242   return res;
243 }
244
245 /*!
246   \brief Set the string value to the radio box widget.
247
248   Button with the identifier from specified string \a txt becomes selected in the radio box.
249
250   \param txt string value
251 */
252 void QDS_RadioBox::setString( const QString& txt )
253 {
254   QButtonGroup* bg = buttonGroup();
255   if ( !bg )
256     return;
257
258   int oldId = bg->checkedId();
259
260   if ( txt.isEmpty() )
261   {
262     QList<QRadioButton*> bList;
263     buttons( bList );
264     QListIterator<QRadioButton*> it( bList );
265     while ( it.hasNext() )
266       it.next()->setChecked( false );
267   }
268   else
269   {
270     bool ok;
271     int id = txt.toInt( &ok );
272     if ( !ok )
273       id = -1;
274
275     bool block = signalsBlocked();
276     blockSignals( true );
277     bg->button(id)->setChecked(true);
278     blockSignals( block );
279   }
280
281   int newId = bg->checkedId();
282
283   if ( oldId != newId )
284   {
285     onParamChanged();
286     QString str = getString();
287     emit activated( newId );
288     emit paramChanged();
289     emit paramChanged( str );
290   }
291 }
292
293 /*!
294   \brief Get internal button group.
295   \return pointer to the QButtonGroup object
296 */
297 QButtonGroup* QDS_RadioBox::buttonGroup() const
298 {
299   return myButtonGroup;
300 }
301
302 /*!
303   \brief Get internal group box widget.
304   \return pointer to the QGroupBox widget
305 */
306 QGroupBox* QDS_RadioBox::groupBox() const
307 {
308   return ::qobject_cast<QGroupBox*>( controlWidget() );
309 }
310
311 /*!
312   \brief Get radio button group box widget.
313   \return internal group box widget
314 */
315 QWidget* QDS_RadioBox::createControl( QWidget* parent )
316 {
317   myButtonGroup = new QButtonGroup( parent );
318   myButtonGroup->setExclusive( true );
319
320   QGroupBox *gb = new QGroupBox( "", parent );
321   QVBoxLayout *vbox = new QVBoxLayout;
322   vbox->addStretch(1);
323   gb->setLayout(vbox);
324   return gb;
325 }
326
327 /*!
328   \brief Process notification about active units system changing.
329
330   Update radio box contents.
331   
332   \param system new active units system
333 */
334 void QDS_RadioBox::unitSystemChanged( const QString& system )
335 {
336   QDS_Datum::unitSystemChanged( system );
337
338   Handle(TColStd_HArray1OfInteger) anIds;
339   Handle(TColStd_HArray1OfExtendedString) aValues, anIcons;
340
341   Handle(DDS_DicItem) aDicItem = dicItem();
342   if ( !aDicItem.IsNull() )
343     aDicItem->GetListOfValues( aValues, anIds, anIcons );
344
345   myValue.clear();
346   myDataIds.clear();
347
348   QMap<int, QString> userMap;
349   QIntList::iterator iIt = myUserIds.begin();
350   QStringList::iterator sIt = myUserNames.begin();
351   for ( ; iIt != myUserIds.end() && sIt != myUserNames.end(); ++iIt, ++sIt )
352     userMap.insert( *iIt, *sIt );
353
354   if ( !anIds.IsNull() && !aValues.IsNull() &&
355        anIds->Length() == aValues->Length() )
356   {
357     for ( int i = anIds->Lower(); i <= anIds->Upper(); i++ )
358     {
359       QString aValue;
360       int id = anIds->Value( i );
361       if ( userMap.contains( id  ) )
362         aValue = userMap[id];
363       else
364         aValue = toQString( aValues->Value( i ) );
365
366       myDataIds.append( id );
367       myValue.insert( id, aValue );
368       myState.insert( id, true );
369     }
370   }
371
372   for ( iIt = myUserIds.begin(); iIt != myUserIds.end(); ++iIt )
373   {
374     int id = *iIt;
375     if ( !myValue.contains( id  ) )
376     {
377       myDataIds.append( id );
378       myValue.insert( id, userMap[id] );
379     }
380   }
381
382   QIntList del, add;
383   for ( IdStateMap::Iterator it1 = myState.begin(); it1 != myState.end(); ++it1 )
384     if ( !myValue.contains( it1.key() ) )
385       del.append( it1.key() );
386
387   for ( IdValueMap::Iterator it2 = myValue.begin(); it2 != myValue.end(); ++it2 )
388     if ( !myState.contains( it2.key() ) )
389       add.append( it2.key() );
390
391   for ( QIntList::iterator iter1 = del.begin(); iter1 != del.end(); ++iter1 )
392     myState.remove( *iter1 );
393
394   for ( QIntList::iterator iter2 = add.begin(); iter2 != add.end(); ++iter2 )
395     myState.insert( *iter2, true );
396
397   QGroupBox* gb = groupBox();
398   if ( gb ) gb->setTitle( label() );
399
400   updateRadioBox();
401 }
402
403 /*!
404   \brief Called when user toggles any radio button.
405   \param on new radio button state
406 */
407 void QDS_RadioBox::onToggled( bool on )
408 {
409   if ( !on )
410     return;
411
412   onParamChanged();
413   emit paramChanged();
414   QString str = getString();
415   emit paramChanged( str );
416 }
417
418 /*!
419   \brief Update radio box.
420 */
421 void QDS_RadioBox::updateRadioBox()
422 {
423   QButtonGroup* bg = buttonGroup();
424   if ( !bg )
425     return;
426
427   QGroupBox* gb = groupBox();
428   if ( !gb )
429     return;
430
431   int curId = bg->checkedId();
432
433   QList<QRadioButton*> bList;
434   buttons( bList );
435   QListIterator<QRadioButton*> itr( bList );
436   while ( itr.hasNext() ) {
437     QRadioButton* aButton = itr.next();
438     if ( gb->layout() ) gb->layout()->removeWidget(aButton);
439     delete aButton;
440   }
441
442   for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it )
443   {
444     int id = *it;
445     if ( !myValue.contains( id ) || !myState.contains( id ) || !myState[id] )
446       continue;
447
448     QRadioButton* rb = new QRadioButton( myValue[id] );
449     ((QObject*)rb)->setParent( bg );
450     bg->addButton( rb, id );
451     if ( gb->layout() ) gb->layout()->addWidget(rb);
452
453     connect( rb, SIGNAL( toggled( bool ) ), this, SLOT( onToggled( bool ) ) );
454   }
455
456   if ( curId != -1 )
457   {
458     int id = curId;
459     if ( !bg->button( id ) )
460     {
461       QList<QRadioButton*> bList;
462       buttons( bList );
463       if ( !bList.isEmpty() )
464         id = bg->id( bList.empty() ? 0 : bList.first() );
465     }
466
467     bool block = signalsBlocked();
468     blockSignals( true );
469     bg->button(id)->setChecked(true);
470     blockSignals( block );
471   }
472
473   if ( curId != bg->checkedId() )
474   {
475     onParamChanged();
476     QString str = getString();
477     emit paramChanged();
478     emit paramChanged( str );
479   }
480 }
481
482 /*!
483   \brief Get all the radio buttons from the radio box.
484   \param lst returned list of radio buttons
485 */
486 void QDS_RadioBox::buttons( QList<QRadioButton*>& lst ) const
487 {
488   lst.clear();
489
490   QButtonGroup* bg = buttonGroup();
491   if ( !bg )
492     return;
493
494   QList<QRadioButton*> objs = bg->findChildren<QRadioButton*>();
495   QListIterator<QRadioButton*> it( objs );
496   while ( it.hasNext() )
497     lst.append( it.next() );
498 }
499
500 /*!
501   \fn void QDS_RadioBox::activated( int id );
502   \brief The signal is emitted when any radio button is toggled.
503   \param id button ID
504 */