Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/gui.git] / src / QDS / QDS_RadioBox.cxx
1 // Copyright (C) 2005  CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "QDS_RadioBox.h"
20
21 #include <DDS_Dictionary.h>
22
23 #include <TCollection_AsciiString.hxx>
24 #include <TColStd_HArray1OfInteger.hxx>
25 #include <TColStd_HArray1OfExtendedString.hxx>
26
27 #include <qobjectlist.h>
28 #include <qbuttongroup.h>
29 #include <qradiobutton.h>
30
31 /*
32   \class QDS_RadioBox
33   
34   Datum with control corresponding to button group with set of exclusive radio buttons.
35   This control used for datum with enumerable values. It can be used for datum which has
36   type of value 'List'. Each radio button of combobox defined two properties:
37   integer identifier and string name. All operations on radio buttons performed via identifier.
38
39   If datum label text is specified then it displayed in group box title.
40 */
41
42 /*!
43   Constructor. Create radio button box datum object with datum identifier \aid under widget \aparent.
44   Parameter \aflags define behaviour of datum and set of created subwidgets. Default value of this
45   parameter is QDS::Control. Parameter \acomp specify the component name which will be used during
46   search of dictionary item.
47 */
48 QDS_RadioBox::QDS_RadioBox( const QString& id, QWidget* parent, const int flags, const QString& comp )
49 : QDS_Datum( id, parent, flags & ~( Label | Units ), comp )
50 {
51 }
52
53 /*!
54   Destructor.
55 */
56 QDS_RadioBox::~QDS_RadioBox()
57 {
58 }
59
60 /*!
61   Returns number of buttons in radio box. If total is 'false' then only
62   visible buttons are taken into account otherwise all buttons.
63 */
64 int QDS_RadioBox::count( bool total ) const
65 {
66   if ( total )
67     return myValue.count();
68   else
69   {
70     QPtrList<QRadioButton> bList;
71     buttons( bList );
72     return bList.count();
73   }
74 }
75
76 /*!
77   Returns list of button identifiers \aids. If \atotal is 'false' then only visible
78   buttons are taken into account otherwise all buttons.
79 */
80 void QDS_RadioBox::values( QValueList<int>& ids, bool total ) const
81 {
82   ids.clear();
83   for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it )
84     if ( total || ( myState.contains( *it ) && myState[*it] ) )
85       ids.append( *it );
86 }
87
88 /*!
89   Returns visible state of button specified by \aid.
90 */
91 bool QDS_RadioBox::state( const int id ) const
92 {
93   bool state = false;
94   if ( myState.contains( id ) )
95     state = myState[id];
96   return state;
97 }
98
99 /*!
100   Sets the visible state of button specified by \aid. If \aid is -1 then specified
101   state will be set to all buttons. If \aappend is set then keep status for other
102   buttons otherwise status of other buttons will be cleared.
103 */
104 void QDS_RadioBox::setState( const bool on, const int id, const bool append )
105 {
106   QValueList<int> lst;
107   if ( id < 0 )
108   {
109     for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it )
110       lst.append( it.key() );
111   }
112   else
113     lst.append( id );
114
115   setState( on, lst, append );
116 }
117
118 /*!
119   Sets the visible state of buttons specified by list of identifiers \aids.
120   If \aappend is set then keep status for other buttons otherwise status of other
121   buttons will be cleared.
122 */
123 void QDS_RadioBox::setState( const bool on, const QValueList<int>& ids, const bool append )
124 {
125   if ( ids.isEmpty() && append )
126     return;
127
128   bool changed = false;
129
130   QMap<int, int> aMap;
131   for ( uint i = 0; i < ids.count(); i++ )
132     aMap.insert( *ids.at( i ), 0 );
133
134   for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it )
135   {
136     if ( aMap.contains( it.key() ) )
137     {
138       if ( it.data() != on )
139       {
140         it.data() = on;
141         changed = true;
142       }
143     }
144     else if ( !append && it.data() == on )
145     {
146       it.data() = !on;
147       changed = true;
148     }
149   }
150   if ( changed )
151     updateRadioBox();
152 }
153
154 /*!
155   Sets the custom user buttons into the radio box. User buttons like standard dictionary
156   button from list will be added into the radio box. This functionality allow to user override
157   buttons.
158 */
159 void QDS_RadioBox::setValues( const QValueList<int>& ids, const QStringList& names )
160 {
161   if ( ids.count() != names.count() )
162     return;
163
164   myUserIds = ids;
165   myUserNames = names;
166 }
167
168 /*!
169   This is an overloaded member function, provided for convenience.
170   It behaves essentially like the above function. It creates
171   QValueList (0, 1, 2 ... ) and call previous method
172 */
173 void QDS_RadioBox::setValues( const QStringList& names )
174 {
175   QValueList< int > ids;
176   for ( int i = 0, n = names.count(); i < n; i++ )
177     ids.append( i );
178   setValues( ids, names );
179 }
180
181 /*!
182   Returns string from radio box. Reimplemented. String which contains identifier of
183   currently selected button returned.
184 */
185 QString QDS_RadioBox::getString() const
186 {
187   QString res;
188   QButtonGroup* bg = buttonGroup();
189   if ( bg )
190   {
191     int id = bg->selectedId();
192     if ( id != -1 )
193       res = QString::number( id );
194   }
195   return res;
196 }
197
198 /*!
199   Sets the string into radio box. Reimplemented. Button with identifier from specified
200   string \atxt became selected in radio box.
201 */
202 void QDS_RadioBox::setString( const QString& txt )
203 {
204   QButtonGroup* bg = buttonGroup();
205   if ( !bg )
206     return;
207
208   int oldId = bg->selectedId();
209
210   if ( txt.isEmpty() )
211   {
212     QPtrList<QRadioButton> bList;
213     buttons( bList );
214     for ( QPtrListIterator<QRadioButton> it( bList ); it.current(); ++it )
215       it.current()->setChecked( false );
216   }
217   else
218   {
219     bool ok;
220     int id = txt.toInt( &ok );
221     if ( !ok )
222       id = -1;
223
224     bool block = signalsBlocked();
225     blockSignals( true );
226     bg->setButton( id );
227     blockSignals( block );
228   }
229
230   int newId = bg->selectedId();
231
232   if ( oldId != newId )
233   {
234     onParamChanged();
235     QString str = getString();
236     emit activated( newId );
237     emit paramChanged();
238     emit paramChanged( str );
239   }
240 }
241
242 /*!
243   Returns pointer to QButtonGroup widget.
244 */
245 QButtonGroup* QDS_RadioBox::buttonGroup() const
246 {
247   return ::qt_cast<QButtonGroup*>( controlWidget() );
248 }
249
250 /*!
251   Create QButtonGroup widget as control subwidget.
252 */
253 QWidget* QDS_RadioBox::createControl( QWidget* parent )
254 {
255   QButtonGroup* bg = new QButtonGroup( 1, Qt::Vertical, "", parent );
256   bg->setExclusive( true );
257   bg->setRadioButtonExclusive( true );
258   return bg;
259 }
260
261 /*!
262   Notification about active unit system changing. Reimplemented from QDS_Datum.
263   Update radio box content.
264 */
265 void QDS_RadioBox::unitSystemChanged( const QString& system )
266 {
267   QDS_Datum::unitSystemChanged( system );
268
269   Handle(TColStd_HArray1OfInteger) anIds;
270   Handle(TColStd_HArray1OfExtendedString) aValues, anIcons;
271
272   Handle(DDS_DicItem) aDicItem = dicItem();
273   if ( !aDicItem.IsNull() )
274     aDicItem->GetListOfValues( aValues, anIds, anIcons );
275
276   myValue.clear();
277   myDataIds.clear();
278
279   QMap<int, QString> userMap;
280   QIntList::iterator iIt = myUserIds.begin();
281   QStringList::iterator sIt = myUserNames.begin();
282   for ( ; iIt != myUserIds.end() && sIt != myUserNames.end(); ++iIt, ++sIt )
283     userMap.insert( *iIt, *sIt );
284
285   if ( !anIds.IsNull() && !aValues.IsNull() &&
286        anIds->Length() == aValues->Length() )
287   {
288     for ( int i = anIds->Lower(); i <= anIds->Upper(); i++ )
289     {
290       QString aValue;
291       int id = anIds->Value( i );
292       if ( userMap.contains( id  ) )
293         aValue = userMap[id];
294       else
295         aValue = toQString( aValues->Value( i ) );
296
297       myDataIds.append( id );
298       myValue.insert( id, aValue );
299       myState.insert( id, true );
300     }
301   }
302
303   for ( iIt = myUserIds.begin(); iIt != myUserIds.end(); ++iIt )
304   {
305     int id = *iIt;
306     if ( !myValue.contains( id  ) )
307     {
308       myDataIds.append( id );
309       myValue.insert( id, userMap[id] );
310     }
311   }
312
313   QIntList del, add;
314   for ( IdStateMap::Iterator it1 = myState.begin(); it1 != myState.end(); ++it1 )
315     if ( !myValue.contains( it1.key() ) )
316       del.append( it1.key() );
317
318   for ( IdValueMap::Iterator it2 = myValue.begin(); it2 != myValue.end(); ++it2 )
319     if ( !myState.contains( it2.key() ) )
320       add.append( it2.key() );
321
322   for ( QIntList::iterator iter1 = del.begin(); iter1 != del.end(); ++iter1 )
323     myState.remove( *iter1 );
324
325   for ( QIntList::iterator iter2 = add.begin(); iter2 != add.end(); ++iter2 )
326     myState.insert( *iter2, true );
327
328   QButtonGroup* bg = buttonGroup();
329   if ( bg )
330     bg->setTitle( label() );
331
332   updateRadioBox();
333 }
334
335 /*!
336   Notify about activation radio button.
337 */
338 void QDS_RadioBox::onToggled( bool on )
339 {
340   if ( !on )
341     return;
342
343   onParamChanged();
344   emit paramChanged();
345   QString str = getString();
346   emit paramChanged( str );
347 }
348
349 /*!
350   Updates RadioBox after have change of visible state or buttons have been inserted/removed.
351 */
352 void QDS_RadioBox::updateRadioBox()
353 {
354   QButtonGroup* bg = buttonGroup();
355   if ( !bg )
356     return;
357
358   int curId = bg->selectedId();
359
360   QPtrList<QRadioButton> bList;
361   buttons( bList );
362   for ( QPtrListIterator<QRadioButton> itr( bList ); itr.current(); ++itr )
363     delete itr.current();
364
365   for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it )
366   {
367     int id = *it;
368     if ( !myValue.contains( id ) || !myState.contains( id ) || !myState[id] )
369       continue;
370
371     QRadioButton* rb = new QRadioButton( myValue[id], bg );
372     bg->insert( rb, id );
373
374     connect( rb, SIGNAL( toggled( bool ) ), this, SLOT( onToggled( bool ) ) );
375   }
376
377   if ( curId != -1 )
378   {
379     int id = curId;
380     if ( !bg->find( id ) )
381     {
382       QPtrList<QRadioButton> bList;
383       buttons( bList );
384       if ( !bList.isEmpty() )
385         id = bg->id( bList.getFirst() );
386     }
387
388     bool block = signalsBlocked();
389     blockSignals( true );
390     bg->setButton( id );
391     blockSignals( block );
392   }
393
394   if ( curId != bg->selectedId() )
395   {
396     onParamChanged();
397     emit paramChanged();
398     emit paramChanged( getString() );
399   }
400 }
401
402 /*!
403   Returns the list of the radio buttons from the button group.
404 */
405 void QDS_RadioBox::buttons( QPtrList<QRadioButton>& lst ) const
406 {
407   lst.setAutoDelete( false );
408   lst.clear();
409
410   QButtonGroup* bg = buttonGroup();
411   if ( !bg )
412     return;
413
414   QObjectList* objs = bg->queryList( "QRadioButton" );
415   if ( objs )
416   {
417     for ( QObjectListIt it( *objs ); it.current(); ++it )
418     {
419       QRadioButton* rb = ::qt_cast<QRadioButton*>( it.current() );
420       if ( rb )
421         lst.append( rb );
422     }
423   }
424   delete objs;
425 }