Salome HOME
Libraries for several kinds of controls (line edit, spinbox, combobox, ...). These...
[modules/gui.git] / src / QDS / QDS_ComboBox.cxx
1 #include "QDS_ComboBox.h"
2
3 #include <DDS_Dictionary.h>
4
5 #include <TCollection_AsciiString.hxx>
6 #include <TColStd_HArray1OfInteger.hxx>
7 #include <TColStd_HArray1OfExtendedString.hxx>
8
9 #include <qlineedit.h>
10
11 /*!
12   Constructor.
13 */
14 QDS_ComboBox::QDS_ComboBox( const QString& id, QWidget* parent, const int flags, const QString& comp )
15 : QDS_Datum( id, parent, flags, comp )
16 {
17 }
18
19 /*!
20   Destructor.
21 */
22 QDS_ComboBox::~QDS_ComboBox()
23 {
24 }
25
26 /*!
27   Returns true if ComboBox allow to edit current Text.
28 */
29 bool QDS_ComboBox::editable() const
30 {
31   if ( comboBox() && comboBox()->lineEdit() )
32     return !comboBox()->lineEdit()->isReadOnly();
33   else
34     return false;
35 }
36
37 /*!
38   Sets the possibily of current text editing.
39 */
40 void QDS_ComboBox::setEditable( const bool on )
41 {
42   QComboBox* aCombo = comboBox();
43   if ( aCombo )
44     aCombo->setEditable( on );
45   if ( aCombo && aCombo->lineEdit() )
46   {
47     aCombo->lineEdit()->setReadOnly( !on );
48     aCombo->clearValidator();
49     if ( on )
50       aCombo->setValidator( validator() );
51   }
52 }
53
54 /*!
55   Returns number of items in ComboBox. If total is 'false' then only
56   visible items are taken into account otherwise all items.
57 */
58 int QDS_ComboBox::count( bool total ) const
59 {
60   if ( total )
61     return myValue.count();
62   else if ( comboBox() )
63     return comboBox()->count();
64   else
65     return 0;
66 }
67
68 /*!
69   Returns list of ids. If total is 'false' then only visible items
70   are taken into account otherwise all items.
71 */
72 void QDS_ComboBox::values( QValueList<int>& ids, bool total ) const
73 {
74   ids.clear();
75   for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it )
76     if ( total || ( myState.contains( *it ) && myState[*it] ) )
77       ids.append( *it );
78 }
79
80 /*!
81   Returns the current id as integer.
82 */
83 int QDS_ComboBox::integerValue() const
84 {
85   QComboBox* cb = comboBox();
86   QString cur = getString();
87   if ( cb && cb->count() > 0 && cb->currentItem() >= 0 )
88     cur = cb->text( cb->currentItem() );
89
90   if ( cb && cur == getString() )
91     return getId( cb->currentItem() );
92   else
93     return getId( getString() );
94 }
95
96 /*!
97   Returns the current id as double.
98 */
99 double QDS_ComboBox::doubleValue() const
100 {
101   QComboBox* cb = comboBox();
102   QString cur = getString();
103   if ( cb && cb->count() > 0 && cb->currentItem() >= 0 )
104     cur = cb->text( cb->currentItem() );
105
106   if ( cb && cur == getString() )
107     return getId( cb->currentItem() );
108   else
109     return getId( getString() );
110 }
111
112 /*!
113   Set the current item acording to specified id.
114 */
115 void QDS_ComboBox::setIntegerValue( const int id )
116 {
117   if ( myValue.contains( id ) )
118     setString( myValue[id] );
119   else 
120     setString( "" );
121 }
122
123 /*!
124   Get the integer part of specified value and use it as new current identifier.
125 */
126 void QDS_ComboBox::setDoubleValue( const double val )
127 {
128   int id = (int)val;
129   if ( myValue.contains( id ) )
130     setString( myValue[id] );
131   else if ( id == -1 )
132     setString( "" );
133 }
134
135 /*!
136   Returns visible state of identificator.
137 */
138 bool QDS_ComboBox::state( const int id ) const
139 {
140   bool state = false;
141   if ( myState.contains( id ) )
142     state = myState[id];
143   return state;
144 }
145
146 /*!
147   Sets the visible state of identificator. If 'id' is -1 then specified
148   state will be set to all ids.
149 */
150 void QDS_ComboBox::setState( const bool on, const int id, const bool append )
151 {
152   QValueList<int> lst;
153   if ( id < 0 )
154   {
155     for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it )
156       lst.append( it.key() );
157   }
158   else
159     lst.append( id );
160
161   setState( on, lst, append );
162 }
163
164 /*!
165   Sets the visible state of identificator from the specified list.
166 */
167 void QDS_ComboBox::setState( const bool on, const QValueList<int>& ids, const bool append )
168 {
169   if ( ids.isEmpty() && append )
170     return;
171
172   bool changed = false;
173
174   QMap<int, int> aMap;
175   for ( uint i = 0; i < ids.count(); i++ )
176     aMap.insert( *ids.at( i ), 0 );
177
178   for ( IdStateMap::Iterator it = myState.begin(); it != myState.end(); ++it )
179   {
180     if ( aMap.contains( it.key() ) )
181     {
182       if ( it.data() != on )
183       {
184         it.data() = on;
185         changed = true;
186       }
187     }
188     else if ( !append && it.data() == on )
189     {
190       it.data() = !on;
191       changed = true;
192     }
193   }
194   if ( changed )
195     updateComboBox();
196 }
197
198 /*!
199   Sets the user items into the combo box.
200 */
201 void QDS_ComboBox::setValues( const QValueList<int>& ids, const QStringList& names )
202 {
203   if ( ids.count() != names.count() )
204     return;
205
206   myUserIds = ids;
207   myUserNames = names;
208 }
209
210 /*!
211   This is an overloaded member function, provided for convenience.
212   It behaves essentially like the above function. It creates
213   QValueList (0, 1, 2 ... ) and call previous method
214 */
215 void QDS_ComboBox::setValues( const QStringList& names )
216 {
217   QValueList< int > ids;
218   for ( int i = 0, n = names.count(); i < n; i++ )
219     ids.append( i );
220   setValues( ids, names );
221 }
222
223 /*!
224   Sets the active item as item with default id. If default
225   not defined then first item will be used.
226 */
227 void QDS_ComboBox::reset()
228 {
229   int id = -1;
230   QString aDefValue = defaultValue();
231   if ( !aDefValue.isEmpty() )
232     id = aDefValue.toInt();
233
234   if ( id == -1 )
235     id = getId( 0 );
236
237   setIntegerValue( id );
238 }
239
240 /*!
241   Returns identifier from given ComboBox string item.
242 */
243 int QDS_ComboBox::stringToValue( const QString& str ) const
244 {
245   return getId( str );
246 }
247
248 /*!
249   Returns ComboBox string item from given identifier.
250 */
251 QString QDS_ComboBox::valueToString( const int val ) const
252 {
253   QString str;
254   if ( myValue.contains( val ) )
255     str = myValue[val];
256   return str;
257 }
258
259 /*!
260   Returns string from QLineEdit widget.
261 */
262 QString QDS_ComboBox::getString() const
263 {
264   QString res;
265   QtxComboBox* cb = comboBox();
266   if ( cb )
267   {
268     if ( !cb->editable() )
269     {
270       if ( !cb->isCleared() )
271         res = cb->currentText(); 
272     }
273     else
274       res = cb->lineEdit()->text();
275   }
276   return res;
277 }
278
279 /*!
280   Sets the string into QLineEdit widget.
281 */
282 void QDS_ComboBox::setString( const QString& txt )
283 {
284   QtxComboBox* cb = comboBox();
285   if ( !cb )
286     return;
287
288   bool isClear = cb->isCleared();
289   
290   int idx = -1;
291   for ( int i = 0; i < cb->count() && idx == -1; i++ )
292     if ( cb->text( i ) == txt )
293       idx = i;
294
295   int old = cb->currentItem();
296   if ( idx != -1 )
297     cb->setCurrentItem( idx );
298   else if ( txt.isEmpty() )
299   {
300     if ( !cb->editable() )
301       cb->setCurrentText( txt );
302     else
303       cb->lineEdit()->setText( txt );
304   }
305   if ( isClear != txt.isEmpty() || ( !isClear && old != cb->currentItem() ) )
306   {
307     onParamChanged();
308     QString str = getString();
309     emit activated( integerValue() );
310     emit activated( str );
311     emit paramChanged();
312     emit paramChanged( str );
313   }
314 }
315
316 /*!
317   Returns pointer to QtxComboBox widget.
318 */
319 QtxComboBox* QDS_ComboBox::comboBox() const
320 {
321   return ::qt_cast<QtxComboBox*>( controlWidget() );
322 }
323
324 /*!
325   Create QComboBox widget as control subwidget.
326 */
327 QWidget* QDS_ComboBox::createControl( QWidget* parent )
328 {
329   QtxComboBox* cb = new QtxComboBox( parent );
330   cb->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ) );
331   connect( cb, SIGNAL( textChanged( const QString& ) ), this,
332            SLOT( onTextChanged( const QString& ) ) );
333   connect( cb, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) );
334   return cb;
335 }
336
337 void QDS_ComboBox::unitSystemChanged( const QString& system )
338 {
339   QDS_Datum::unitSystemChanged( system );
340
341   Handle(TColStd_HArray1OfInteger) anIds;
342   Handle(TColStd_HArray1OfExtendedString) aValues, anIcons;
343
344   Handle(DDS_DicItem) aDicItem = dicItem();
345   if ( !aDicItem.IsNull() )
346     aDicItem->GetListOfValues( aValues, anIds, anIcons );
347
348   myValue.clear();
349   myIcons.clear();
350   myDataIds.clear();
351
352   QMap<int, QString> userMap;
353   QIntList::iterator iIt = myUserIds.begin();
354   QStringList::iterator sIt = myUserNames.begin();
355   for ( ; iIt != myUserIds.end() && sIt != myUserNames.end(); ++iIt, ++sIt )
356     userMap.insert( *iIt, *sIt );
357
358   if ( !anIds.IsNull() && !aValues.IsNull() &&
359        anIds->Length() == aValues->Length() )
360   {
361     for ( int i = anIds->Lower(); i <= anIds->Upper(); i++ )
362     {
363       QString aValue;
364       QPixmap aPixmap;
365       int id = anIds->Value( i );
366       if ( userMap.contains( id  ) )
367         aValue = userMap[id];
368       else
369       {
370         aValue = toQString( aValues->Value( i ) );
371         if ( !anIcons.IsNull() && i <= anIcons->Upper() )
372         {
373           QString anIconId = toQString( anIcons->Value( i ) );
374           if ( anIconId != "" )
375             aPixmap = QPixmap( anIconId );
376         }
377       }
378
379       myDataIds.append( id );
380       myValue.insert( id, aValue );
381       myState.insert( id, true );
382       if ( !aPixmap.isNull() )
383         myIcons.insert( id, aPixmap );
384     }
385   }
386
387   for ( iIt = myUserIds.begin(); iIt != myUserIds.end(); ++iIt )
388   {
389     int id = *iIt;
390     if ( !myValue.contains( id  ) )
391     {
392       myDataIds.append( id );
393       myValue.insert( id, userMap[id] );
394     }
395   }
396
397   QIntList del, add;
398   for ( IdStateMap::Iterator it1 = myState.begin(); it1 != myState.end(); ++it1 )
399     if ( !myValue.contains( it1.key() ) )
400       del.append( it1.key() );
401
402   for ( IdValueMap::Iterator it2 = myValue.begin(); it2 != myValue.end(); ++it2 )
403     if ( !myState.contains( it2.key() ) )
404       add.append( it2.key() );
405
406   for ( QIntList::iterator iter1 = del.begin(); iter1 != del.end(); ++iter1 )
407     myState.remove( *iter1 );
408
409   for ( QIntList::iterator iter2 = add.begin(); iter2 != add.end(); ++iter2 )
410     myState.insert( *iter2, true );
411
412   updateComboBox();
413 }
414
415 /*!
416   Notify about text changing in line edit of ComboBox.
417 */
418 void QDS_ComboBox::onTextChanged( const QString& )
419 {
420   onParamChanged();
421   emit paramChanged();
422   QString str = getString();
423   emit paramChanged( str );
424 }
425
426 /*!
427   Notify about activation new item.
428 */
429 void QDS_ComboBox::onActivated( int idx )
430 {
431   if ( comboBox() )
432     comboBox()->setCurrentItem( comboBox()->currentItem() );
433
434   int id = getId( idx );
435   if ( id != -1 )
436   {
437     onParamChanged();
438     QString str = getString();
439     emit activated( id );
440     emit activated( str );
441     emit paramChanged();
442     emit paramChanged( str );
443   }
444 }
445
446 /*!
447   Updates ComboBox after have change of visible state or items have been inserted / removed.
448 */
449 void QDS_ComboBox::updateComboBox()
450 {
451   QtxComboBox* cb = comboBox();
452
453   int curId = -1;
454
455   bool isClear = false;
456
457   if ( cb )
458   {
459     isClear = cb->isCleared();
460
461     curId = getId( cb->currentItem() );
462     cb->clear();
463   }
464
465   myIndex.clear();
466
467   int idx = 0;
468   for ( QIntList::const_iterator it = myDataIds.begin(); it != myDataIds.end(); ++it )
469   {
470     int id = *it;
471     if ( !myValue.contains( id ) || !myState.contains( id ) || !myState[id] )
472       continue;
473
474     myIndex.insert( id, idx++ );
475     if ( cb )
476     {
477       if ( myIcons.contains( id ) )
478         cb->insertItem( myIcons[id], myValue[id] );
479       else
480         cb->insertItem( myValue[id] );
481     }
482   }
483
484   if ( cb && cb->count() )
485   {
486     cb->setFont( cb->font() );
487     cb->updateGeometry();
488
489     if ( isClear )
490       cb->setCurrentText( "" );
491     else
492     {
493       if ( getIndex( curId ) != -1 )
494         cb->setCurrentItem( getIndex( curId ) );
495       if ( curId != getId( cb->currentItem() ) )
496         onActivated( cb->currentItem() );
497     }
498   }
499 }
500
501 /*!
502   Returns index of ComboBox item according to id.
503 */
504 int QDS_ComboBox::getIndex( const int id ) const
505 {
506   int idx = -1;
507   if ( myIndex.contains( id ) )
508     idx = myIndex[id];
509   return idx;
510 }
511
512 /*!
513   Returns index of ComboBox item according to string.
514 */
515 int QDS_ComboBox::getIndex( const QString& str ) const
516 {
517   int idx = -1;
518   QComboBox* cb = comboBox();
519   if ( cb )
520   {
521     for ( int i = 0; i < cb->count() && idx == -1; i++ )
522       if ( cb->text( i ) == str )
523         idx = i;
524   }
525   return idx;
526 }
527
528 /*!
529   Returns id according to ComboBox item index.
530 */
531 int QDS_ComboBox::getId( const int idx ) const
532 {
533   int id = -1;
534   IdIndexMap::ConstIterator it = myIndex.begin();
535   for (; it != myIndex.end() && id == -1; ++it )
536     if ( it.data() == idx )
537       id = it.key();
538   return id;
539 }
540
541 /*!
542   Returns id according to ComboBox item string.
543 */
544 int QDS_ComboBox::getId( const QString& str ) const
545 {
546   int id = -1;
547   int candidate = -1;
548   IdValueMap::ConstIterator it = myValue.begin();
549   for (; it != myValue.end() && id == -1; ++it )
550   {
551     if ( it.data() == str )
552     {
553       if ( state( it.key() ) )
554         id = it.key();
555       else
556         candidate = it.key();
557     }
558   }
559   if ( id == -1 )
560     id = candidate;
561
562   return id;
563 }