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