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