Salome HOME
Libraries for several kinds of controls (line edit, spinbox, combobox, ...). These...
[modules/gui.git] / src / QDS / QDS_Datum.cxx
1 #include "QDS_Datum.h"
2
3 #include "QDS_Validator.h"
4
5 #include <DDS_Dictionary.h>
6
7 #include <qtimer.h>
8 #include <qlabel.h>
9 #include <qwidget.h>
10 #include <qlayout.h>
11 #include <qtooltip.h>
12 #include <qwhatsthis.h>
13 #include <qvalidator.h>
14 #include <qmessagebox.h>
15
16 /*!
17   Class: QDS_Datum::Wrapper
18   Descr: Wrapper widget for sub widgets. [internal]
19 */
20
21 class QDS_Datum::Wrapper : public QWidget
22 {
23 public:
24   Wrapper( QWidget* = 0 );
25   virtual ~Wrapper();
26
27   QWidget*      widget() const;
28   void          setWidget( QWidget* );
29
30   virtual bool  eventFilter( QObject*, QEvent* );
31
32 protected:
33   virtual void  resizeEvent( QResizeEvent* );
34
35 private:
36   QWidget*      myWid;
37 };
38
39
40 QDS_Datum::Wrapper::Wrapper( QWidget* parent )
41 : QWidget( parent ),
42 myWid( 0 )
43 {
44   QHBoxLayout* base = new QHBoxLayout( this );
45   base->setAutoAdd( true );
46 }
47
48 QDS_Datum::Wrapper::~Wrapper()
49 {
50 }
51
52 QWidget* QDS_Datum::Wrapper::widget() const
53 {
54   return myWid;
55 }
56
57 void QDS_Datum::Wrapper::setWidget( QWidget* wid )
58 {
59   if ( myWid == wid )
60     return;
61
62   if ( myWid )
63     myWid->removeEventFilter( this );
64
65   myWid = wid;
66
67   if ( !myWid )
68     return;
69
70   if ( myWid->parent() != this )
71     myWid->reparent( this, QPoint( 0, 0 ) );
72
73   setFocusProxy( myWid );
74
75   myWid->updateGeometry();
76   updateGeometry();
77
78   myWid->installEventFilter( this );
79 }
80
81 bool QDS_Datum::Wrapper::eventFilter( QObject* o, QEvent* e )
82 {
83   if ( e->type() == QEvent::Resize && o == widget() )
84   {
85     QResizeEvent* re = (QResizeEvent*)e;
86     if ( re->size() != size() )
87       resize( re->size() );
88   }
89   return QWidget::eventFilter( o, e );
90 }
91
92 void QDS_Datum::Wrapper::resizeEvent( QResizeEvent* e )
93 {
94   QWidget::resizeEvent( e );
95
96   if ( widget() && widget()->size() != size() )
97     widget()->resize( size() );
98 }
99
100 /*!
101   Class: QDS_Datum
102   Descr: Base class for control used data dictionary. [public]
103 */
104
105 QDS_Datum::QDS_Datum( const QString& id, QWidget* parent, const int flags, const QString& comp )
106 : QObject( parent ),
107 myId( id ),
108 myLabel( 0 ),
109 myUnits( 0 ),
110 myControl( 0 ),
111 myFlags( flags ),
112 myInitialised( false )
113 {
114   if ( myFlags & Label )
115     myWrapper.insert( Label, new Wrapper( parent ) );
116   if ( myFlags & Control )
117     myWrapper.insert( Control, new Wrapper( parent ) );
118   if ( myFlags & Units )
119     myWrapper.insert( Units, new Wrapper( parent ) );
120
121   for ( QMap<int, Wrapper*>::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it )
122     connect( it.data(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
123
124   Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
125   if ( aDict.IsNull() )
126     return;
127
128   TCollection_AsciiString anId = toAsciiString( id );
129   TCollection_AsciiString aComp = toAsciiString( comp );
130
131   setDicItem( aDict->GetDicItem( anId, aComp ) );
132
133   QTimer::singleShot( 0, this, SLOT( onInitDatum() ) );
134
135   if ( parent )
136     parent->installEventFilter( this );
137
138   insertDatum( this );
139 }
140
141 QDS_Datum::~QDS_Datum()
142 {
143   removeDatum( this );
144
145   delete myLabel;
146   delete myUnits;
147   delete myControl;
148 /*
149   for ( QMap<int, Wrapper*>::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it )
150     delete it.data();
151 */
152 }
153
154 QString QDS_Datum::id() const
155 {
156   initDatum();
157
158   return myId;
159 }
160
161 int QDS_Datum::type() const
162 {
163   initDatum();
164
165   int res = DDS_DicItem::Unknown;
166   if ( !myDicItem.IsNull() )
167     res = myDicItem->GetType();
168   return res;
169 }
170
171 QString QDS_Datum::label() const
172 {
173   initDatum();
174
175   QString labStr;
176   if ( !myDicItem.IsNull() )
177     labStr = toQString( myDicItem->GetLabel() );
178
179   if ( flags() & NotAccel )
180     labStr = removeAccel( labStr );
181
182   return labStr;
183 }
184
185 QString QDS_Datum::units() const
186 {
187   initDatum();
188
189   QString unitStr;
190   if ( !myDicItem.IsNull() )
191     unitStr = toQString( myDicItem->GetUnits() );
192   return unitStr;
193 }
194
195 QString QDS_Datum::filter() const
196 {
197   initDatum();
198
199   QString fltr;
200   if ( !myDicItem.IsNull() )
201     fltr = toQString( myDicItem->GetFilter() );
202   return fltr;
203 }
204
205 QString QDS_Datum::format() const
206 {
207   initDatum();
208
209   QString fmtStr;
210   if ( !myDicItem.IsNull() )
211     fmtStr = toQString( myDicItem->GetFormat( false ) );
212   return fmtStr;
213 }
214
215 QString QDS_Datum::defaultValue() const
216 {
217   initDatum();
218
219   QString pref = prefix();
220   QString suff = suffix();
221
222   QString def;
223   if ( !myDicItem.IsNull() )
224     def = toQString( myDicItem->GetDefaultValue() );
225
226   QString aDef = def.stripWhiteSpace();
227   if ( !pref.isEmpty() && aDef.left( pref.length() ) == pref )
228     aDef = aDef.mid( pref.length() );
229
230   if ( !suff.isEmpty() && aDef.right( suff.length() ) == suff )
231     aDef = aDef.mid( 0, aDef.length() - suff.length() );
232
233   return aDef;
234 }
235
236 QString QDS_Datum::minimumValue() const
237 {
238   initDatum();
239
240   QString min;
241   if ( !myDicItem.IsNull() )
242     min = format( format(), type(), myDicItem->GetMinValue() );
243   return min;
244 }
245
246 QString QDS_Datum::maximumValue() const
247 {
248   initDatum();
249
250   QString max;
251   if ( !myDicItem.IsNull() )
252     max = format( format(), type(), myDicItem->GetMaxValue() );
253   return max;
254 }
255
256 QString QDS_Datum::longDescription() const
257 {
258   initDatum();
259
260   QString ldStr;
261   if ( !myDicItem.IsNull() )
262     ldStr = toQString( myDicItem->GetLongDescription() );
263   return ldStr;
264 }
265
266 QString QDS_Datum::shortDescription() const
267 {
268   initDatum();
269
270   QString sdStr;
271   if ( !myDicItem.IsNull() )
272     sdStr = toQString( myDicItem->GetLongDescription() );
273   return sdStr;
274 }
275
276 QString QDS_Datum::stringValue() const
277 {
278   initDatum();
279
280   if ( getString() == myTargetValue )
281     return mySourceValue;
282   else
283     return getString();
284 }
285
286 double QDS_Datum::doubleValue() const
287 {
288   initDatum();
289
290   double res = 0;
291   if ( !myTargetValue.isNull() && myTargetValue == getString() )
292     res = mySourceValue.toDouble();
293   else
294   {
295     res = getString().toDouble();
296     if ( !myDicItem.IsNull() )
297       res = myDicItem->ToSI( res );
298   }
299
300   return res;
301 }
302
303 int QDS_Datum::integerValue() const
304 {
305   initDatum();
306
307   int res = 0;
308   if ( !myTargetValue.isNull() && myTargetValue == getString() )
309     res = mySourceValue.toInt();
310   else
311   {
312     double val = getString().toDouble();
313     if ( !myDicItem.IsNull() )
314       res = (int)myDicItem->ToSI( val );
315   }
316
317   return res;
318 }
319
320 QString QDS_Datum::text() const
321 {
322   initDatum();
323
324   QString aLabel = label();
325   QString aData  = stringValue();
326   QString aUnits = units();
327
328   QString res = aLabel;
329   if ( !res.isEmpty() && !aData.isEmpty() )
330     res += QString( ": " );
331
332   res += aData;
333   if ( !aUnits.isEmpty() )
334     res += QString( " " ) + aUnits;
335
336   return res;
337 }
338
339 bool QDS_Datum::isEmpty() const
340 {
341   return stringValue().isEmpty();
342 }
343
344 void QDS_Datum::reset()
345 {
346   initDatum();
347
348   mySourceValue = defaultValue();
349   setString( format( ( myFlags & NotFormat ) ? (QString) "" : format(), type(), mySourceValue ) );
350   invalidateCache();
351
352   onParamChanged();
353   QString str = getString();
354   emit paramChanged();
355   emit paramChanged( str );
356 }
357
358 void QDS_Datum::clear()
359 {
360   initDatum();
361
362   if ( !getString().isEmpty() )
363   {
364     mySourceValue = "";
365     setString( mySourceValue );
366     invalidateCache();
367
368     onParamChanged();
369     QString str = getString();
370     emit paramChanged();
371     emit paramChanged( str );
372   }
373 }
374
375 void QDS_Datum::setStringValue( const QString& txt )
376 {
377   initDatum();
378
379   mySourceValue = txt;
380   QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), txt );
381   setString( aStr );
382   myTargetValue = aStr;
383
384   onParamChanged();
385   QString str = getString();
386   emit paramChanged();
387   emit paramChanged( str );
388 }
389
390 void QDS_Datum::setDoubleValue( const double num )
391 {
392   initDatum();
393
394   mySourceValue = QString().setNum( num, 'g', 16 );
395   double val = num;
396   if ( !myDicItem.IsNull() )
397     val = myDicItem->FromSI( val );
398
399   QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
400   setString( aStr );
401   myTargetValue = aStr;
402
403   onParamChanged();
404   QString str = getString();
405   emit paramChanged();
406   emit paramChanged( str );
407 }
408
409 void QDS_Datum::setIntegerValue( const int num )
410 {
411   initDatum();
412
413   mySourceValue = QString().setNum( num );
414   double val = num;
415   if ( !myDicItem.IsNull() )
416     val = myDicItem->FromSI( val );
417
418   QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
419   setString( aStr );
420   myTargetValue = aStr;
421
422   onParamChanged();
423   QString str = getString();
424   emit paramChanged();
425   emit paramChanged( str );
426 }
427
428 /*!
429   Returns true if all subwidgets specified by 'element' enabled.
430 */
431 bool QDS_Datum::isEnabled( const int element ) const
432 {
433   initDatum();
434
435   bool res = true;
436   if ( element & Label )
437     res = res && labelWidget() && labelWidget()->isEnabled();
438   if ( element & Units )
439     res = res && unitsWidget() && unitsWidget()->isEnabled();
440   if ( element & Control )
441     res = res && controlWidget() && controlWidget()->isEnabled();
442   return res;
443 }
444
445 /*!
446   Enable/Disable subwidgets specified by 'element'.
447   Values: Label, Control, Units or their combinations.
448 */
449 void QDS_Datum::setEnabled( const bool on, const int element )
450 {
451   initDatum();
452
453   if ( element & Label && labelWidget() )
454     labelWidget()->setEnabled( on );
455   if ( element & Units && unitsWidget() )
456     unitsWidget()->setEnabled( on );
457   if ( element & Control && controlWidget() )
458     controlWidget()->setEnabled( on );
459 }
460
461 /*!
462   Enable/Disable control.
463 */
464 void QDS_Datum::setEnabled( bool on )
465 {
466   setEnabled( on, Control );
467 }
468
469 void QDS_Datum::setShown( const bool visible, const int flags )
470 {
471   if ( visible )
472     show( flags );
473   else
474     hide( flags );
475 }
476
477 /*!
478   Show subwidgets specified by 'element'.
479   Values: Label, Control, Units or their combinations.
480 */
481 void QDS_Datum::show( const int element )
482 {
483   initDatum();
484
485   if ( ( element & Label ) && labelWidget() )
486     labelWidget()->show();
487   if ( ( element & Units ) && unitsWidget() )
488     unitsWidget()->show();
489   if ( ( element & Control ) && controlWidget() )
490     controlWidget()->show();
491 }
492
493 /*!
494   Hide subwidgets specified by 'element'.
495   Values: Label, Control, Units or their combinations.
496 */
497 void QDS_Datum::hide( const int element )
498 {
499   initDatum();
500
501   if ( ( element & Label ) && labelWidget() )
502     labelWidget()->hide();
503   if ( ( element & Units ) && unitsWidget() )
504     unitsWidget()->hide();
505   if ( ( element & Control ) && controlWidget() )
506     controlWidget()->hide();
507 }
508
509 /*!
510   Returns subwidget specified by 'element'.
511   Possible values: Label, Control, Units.
512 */
513 QWidget* QDS_Datum::widget( const int element ) const
514 {
515   initDatum();
516   return wrapper( element );
517 }
518
519 /*!
520   Set the input focus on the control widget.
521 */
522 void QDS_Datum::setFocus()
523 {
524   initDatum();
525
526   if ( controlWidget() )
527     controlWidget()->setFocus();
528 }
529
530 /*!
531   Returns true if control contains valid value otherwise returns false
532   and display warning message box if parameter msgBox is set.
533 */
534 bool QDS_Datum::isValid( const bool msgBox, const QString& extMsg, const QString& extLabel ) const
535 {
536   initDatum();
537
538   if ( type() == DDS_DicItem::String && isDoubleFormat( format() ) )
539     return true;
540
541   bool aState = true;
542   QString aStr = getString();
543   if ( aStr.isEmpty() )
544     aState = false;
545   else
546     aState = validate( aStr );
547
548   if ( msgBox && !aState )
549   {
550     QString info;
551     if ( !label().isEmpty() )
552       info += tr( "DATA_INCORRECT_VALUE" ).arg( label() );
553     else if ( !extLabel.isEmpty() )
554       info += tr( "DATA_INCORRECT_VALUE" ).arg( extLabel );
555
556     QString typeStr;
557     switch ( type() )
558     {
559     case DDS_DicItem::String:
560       typeStr = tr( "DATA_STRING" );
561       break;
562     case DDS_DicItem::Integer:
563       typeStr = tr( "DATA_INTEGER" );
564       break;
565     case DDS_DicItem::Float:
566       typeStr = tr( "DATA_FLOAT" );
567       break;
568     default:
569       typeStr = tr( "DATA_NON_EMPTY" );
570       break;
571     }
572     info += ( info.isEmpty() ? (QString) "" : QString( "\n" ) ) + 
573             tr( "DATA_SHOULD_BE_VALUE" ).arg( typeStr );
574     QString limit;
575     if ( type() == DDS_DicItem::Float || type() == DDS_DicItem::Integer )
576     {
577       QString aMinValue = minValue();
578       QString aMaxValue = maxValue();
579       if ( !aMinValue.isEmpty() && !aMaxValue.isEmpty() )
580         limit = tr( "DATA_RANGE" ).arg( aMinValue ).arg( aMaxValue );
581       else if ( !aMinValue.isEmpty() )
582         limit = tr( "DATA_MIN_LIMIT" ).arg( aMinValue );
583       else if ( !aMaxValue.isEmpty() )
584         limit = tr( "DATA_MAX_LIMIT" ).arg( aMaxValue );
585     }
586     if ( !limit.isEmpty() )
587       info += limit;
588
589     info += QString( ".\n" ) + tr( "DATA_INPUT_VALUE" );
590
591     if ( !extMsg.isEmpty() )
592       info += QString( "\n" ) + extMsg;
593
594     QString msg;
595     for ( uint i = 0; i < info.length(); i++ )
596       if ( info.at( i ) == '\n' )
597         msg += QString( "<br>" );
598       else
599         msg += info.at( i );
600
601     info = QString( "<p><nobr>%1</nobr></p>" ).arg( msg );
602
603     QMessageBox::critical( controlWidget() ? controlWidget()->topLevelWidget() : 0,
604                            tr( "DATA_ERR_TITLE" ), info, tr( "BUT_OK" ) );
605     if ( controlWidget() )
606       controlWidget()->setFocus();
607   }
608   return aState;
609 }
610
611 /*!
612   Add widgets to the vertical layout.
613 */
614 void QDS_Datum::addTo( QVBoxLayout* l )
615 {
616   initDatum();
617
618   if ( !l )
619     return;
620
621   if ( wrapper( Label ) )
622     l->addWidget( wrapper( Label ) );
623   if ( wrapper( Control ) )
624     l->addWidget( wrapper( Control ) );
625   if ( wrapper( Units ) )
626     l->addWidget( wrapper( Units ) );
627 }
628
629 /*!
630   Add widgets to the horizaontal layout.
631 */
632 void QDS_Datum::addTo( QHBoxLayout* l )
633 {
634   initDatum();
635
636   if ( !l )
637     return;
638
639   if ( wrapper( Label ) )
640     l->addWidget( wrapper( Label ) );
641   if ( wrapper( Control ) )
642     l->addWidget( wrapper( Control ) );
643   if ( wrapper( Units ) )
644     l->addWidget( unitsWidget() );
645 }
646
647 /*!
648   Add widgets to the grid layout.
649 */
650 void QDS_Datum::addTo( QGridLayout* theLay, const int theRow, const int theCol, bool vertical )
651 {
652   initDatum();
653
654   if ( !theLay )
655     return;
656
657   int row = theRow;
658   int col = theCol;
659   if ( wrapper( Label ) )
660   {
661     theLay->addWidget( wrapper( Label ), row, col );
662     vertical ? row++ : col++;
663   }
664   if ( wrapper( Control ) )
665   {
666     theLay->addWidget( wrapper( Control ), row, col );
667     vertical ? row++ : col++;
668   }
669   if ( wrapper( Units ) )
670     theLay->addWidget( wrapper( Units ), row, col );
671 }
672
673 /*!
674   Set the aligment of Label or Units. For Control nothing happens.
675 */
676 void QDS_Datum::setAlignment( const int align, const int type )
677 {
678   initDatum();
679
680   if ( ( type & Label ) && labelWidget() )
681     labelWidget()->setAlignment( align );
682   if ( ( type & Units ) && unitsWidget() )
683     unitsWidget()->setAlignment( align );
684 }
685
686 bool QDS_Datum::eventFilter( QObject* o, QEvent* e )
687 {
688   if ( o == parent() )
689   {
690     if ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
691          ( e->type() == QEvent::ChildInserted && ((QChildEvent*)e)->child() == this ) )
692       initDatum();
693   }
694   return QObject::eventFilter( o, e );
695 }
696
697 /*!
698   Notify about parameter changing.
699 */
700 void QDS_Datum::onParamChanged()
701 {
702 }
703
704 /*!
705   Delayed initialization.
706 */
707 void QDS_Datum::onInitDatum()
708 {
709   initDatum();
710 }
711
712 /*!
713   Notify about subwidgets destroying. Allow to avoid repeated deleting in destructor.
714 */
715 void QDS_Datum::onDestroyed( QObject* obj )
716 {
717   myWrapper.remove( wrapperType( (Wrapper*)obj ) );
718 }
719
720 /*!
721   Returns QLabel instance which contains data dictionary label.
722 */
723 QLabel* QDS_Datum::labelWidget() const
724 {
725   initDatum();
726   return myLabel;
727 }
728
729 /*!
730   Returns QLabel instance which contains data dictionary units.
731 */
732 QLabel* QDS_Datum::unitsWidget() const
733 {
734   initDatum();
735   return myUnits;
736 }
737
738 /*!
739   Returns QWidget which contains user input data.
740 */
741 QWidget* QDS_Datum::controlWidget() const
742 {
743   initDatum();
744   return myControl;
745 }
746
747 /*!
748   Returns the dictionary item from the datum.
749 */
750 Handle(DDS_DicItem) QDS_Datum::dicItem() const
751 {
752   return myDicItem;
753 }
754
755 /*!
756   Set the dictionary item in to the datum.
757 */
758 void QDS_Datum::setDicItem( Handle(DDS_DicItem)& item )
759 {
760   myDicItem = item;
761 }
762
763 /*!
764   Creates QLabel widget for data label.
765 */
766 QLabel* QDS_Datum::createLabel( QWidget* parent )
767 {
768   return new QLabel( parent );
769 }
770
771 /*!
772   Creates QLabel widget for data units.
773 */
774 QLabel* QDS_Datum::createUnits( QWidget* parent )
775 {
776   return new QLabel( parent );
777 }
778
779 /*!
780   Returns validator accordance to data type.
781 */
782 QValidator* QDS_Datum::validator( const bool limits ) const
783 {
784   QValidator* aValidator = 0;
785
786   QString fltr = filter();
787
788   if ( type() == DDS_DicItem::String )
789   {
790     QString aFlags;
791     QString aFormat = canonicalFormat( format(), aFlags );
792
793     int len = -1;
794     int pos = aFormat.find( "." );
795     if ( pos != -1 )
796     {
797       QString numStr = aFormat.mid( pos + 1, aFormat.length() - pos - 2 );
798       bool ok;
799       int numVal = numStr.toInt( &ok );
800       if ( ok )
801         len = numVal;
802     }
803
804     QDS_StringValidator* aStrVal = new QDS_StringValidator( fltr, aFlags, (QObject*)this );
805     aStrVal->setLength( len );
806
807     aValidator = aStrVal;
808   }
809   else if ( type() == DDS_DicItem::Integer )
810   {
811     QDS_IntegerValidator* aIntVal = new QDS_IntegerValidator( fltr, (QObject*)this );
812
813     bool ok;
814     int limit;
815     limit = minValue().toInt( &ok );
816     if ( ok && limits )
817       aIntVal->setBottom( limit );
818     limit = maxValue().toInt( &ok );
819     if ( ok && limits )
820       aIntVal->setTop( limit );
821
822     aValidator = aIntVal;
823   }
824   else if ( type() == DDS_DicItem::Float )
825   {
826     QDS_DoubleValidator* aFloatVal = new QDS_DoubleValidator( fltr, (QObject*)this );
827
828     bool ok;
829     double limit;
830     limit = minValue().toDouble( &ok );
831     if ( ok && limits )
832       aFloatVal->setBottom( limit );
833     limit = maxValue().toDouble( &ok );
834     if ( ok && limits )
835       aFloatVal->setTop( limit );
836
837     aValidator = aFloatVal;
838   }
839
840   return aValidator;
841 }
842
843 /*!
844   Checks the given string are valid or not.
845 */
846 bool QDS_Datum::validate( const QString& txt ) const
847 {
848   if ( type() == DDS_DicItem::Unknown ||
849        type() == DDS_DicItem::String && isDoubleFormat( format() ) )
850     return true;
851
852   QValidator* aValidator = validator( true );
853
854   if ( !aValidator )
855     return true;
856
857   int pos = 0;
858   QString str( txt );
859   bool res = aValidator->validate( str, pos ) == QValidator::Acceptable;
860
861   delete aValidator;
862
863   return res;
864 }
865
866 /*!
867   Retrieves information from data dictionary and create subwidgets using virtual mechanism.
868   Virtual mechanism doesn't work in constructor and destructor, therefore this method should
869   be called outside the constructor.
870 */
871 void QDS_Datum::initialize()
872 {
873   if ( wrapper( Label ) )
874     wrapper( Label )->setWidget( myLabel = createLabel( wrapper( Label ) ) );
875   if ( wrapper( Control ) )
876     wrapper( Control )->setWidget( myControl = createControl( wrapper( Control ) ) );
877   if ( wrapper( Units ) )
878     wrapper( Units )->setWidget( myUnits = createUnits( wrapper( Units ) ) );
879
880   TCollection_AsciiString comp;
881   Handle(DDS_DicItem) item = dicItem();
882   if ( !item.IsNull() )
883     comp = item->GetComponent();
884
885   QString unitSystem;
886   Handle(DDS_Dictionary) dic = DDS_Dictionary::Get();
887   if ( !dic.IsNull() )
888     unitSystem = toQString( comp.IsEmpty() ? dic->GetActiveUnitSystem() :
889                                              dic->GetActiveUnitSystem( comp ) );
890
891   unitSystemChanged( unitSystem );
892
893   QWidget* ctrl = controlWidget();
894   if ( ctrl )
895   {
896     QString lDescr = longDescription();
897     QString sDescr = shortDescription();
898     if ( !sDescr.isEmpty() )
899       QToolTip::add( ctrl, sDescr );
900     if ( !lDescr.isEmpty() )
901       QWhatsThis::add( ctrl, lDescr );
902   }
903
904   if ( labelWidget() && ctrl && !( flags() & NotAccel ) )
905     labelWidget()->setBuddy( ctrl );
906 }
907
908 void QDS_Datum::unitSystemChanged( const QString& unitSystem )
909 {
910   QString labText = label();
911   QString unitText = unitsToText( units() );
912
913   if ( flags() & UnitsWithLabel )
914   {
915     if ( labText.isEmpty() )
916       labText = unitText;
917     else if ( !unitText.isEmpty() )
918       labText = QString( "%1 (%2)" ).arg( labText ).arg( unitText );
919     unitText = QString::null;
920   }
921
922   if ( labelWidget() )
923     labelWidget()->setText( labText );
924
925
926   if ( unitsWidget() )
927     unitsWidget()->setText( unitText );
928
929   reset();
930 }
931
932 /*!
933   Covert units into text presentation.
934 */
935 QString QDS_Datum::unitsToText( const QString& uni )
936 {
937   int pos = -1;
938   QString aUnits = uni;
939   while ( ( pos = aUnits.find( "**" ) ) != -1 )
940   {
941     aUnits = aUnits.mid( 0, pos ) + QString( "<tt><font size=+2><sup>" ) +
942              aUnits.mid( pos + 2, 1 ) + QString( "</sup></font></tt>" ) +
943              aUnits.mid( pos + 3 );
944   }
945   return aUnits;
946 }
947
948 /*!
949   Covert text presentation into internal units format.
950 */
951 QString QDS_Datum::textToUnits( const QString& txt )
952 {
953   int pos = -1;
954   QString aUnits = txt;
955   while ( ( pos = aUnits.find( "<sup>" ) ) != -1 )
956   {
957     aUnits.remove( pos, 5 );
958     aUnits.insert( pos, "**" );
959   }
960   while ( ( pos = aUnits.find( "</sup>" ) ) != -1 )
961     aUnits.remove( pos, 6 );
962   return aUnits;
963 }
964
965 /*!
966   Format the specified integer as data dictionary value.
967 */
968 QString QDS_Datum::format( const int num, const QString& id, const bool convert )
969 {
970   Handle(DDS_DicItem) anItem;
971   int aNum = num;
972   QString anUnit;
973   
974   QString aFormat;
975   int aType = DDS_DicItem::Unknown;
976   Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
977   if ( !aDict.IsNull() )
978   {
979     anItem = aDict->GetDicItem( toAsciiString( id ) );
980     if ( !anItem.IsNull() )
981     {
982       aType = anItem->GetType();
983       aFormat = toQString( anItem->GetFormat( false ) );
984       if ( convert )
985         aNum = anItem->FromSI( aNum );
986     }
987   }
988
989   return format( aFormat, aType, aNum );
990 }
991
992 /*!
993   Format the specified double as data dictionary value.
994 */
995 QString QDS_Datum::format( const double num, const QString& id, const bool convert )
996 {
997   Handle(DDS_DicItem) anItem;
998   double aNum = num;
999   QString anUnit;
1000   
1001   QString aFormat;
1002   int aType = DDS_DicItem::Unknown;
1003   Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1004   if ( !aDict.IsNull() )
1005   {
1006     anItem = aDict->GetDicItem( toAsciiString( id ) );
1007     if ( !anItem.IsNull() )
1008     {
1009       aType = anItem->GetType();
1010       aFormat = toQString( anItem->GetFormat( false ) );
1011       if ( convert )
1012         aNum = anItem->FromSI( aNum );
1013     }
1014   }
1015
1016   return format( aFormat, aType, aNum );
1017 }
1018
1019 /*!
1020   Format the specified string as data dictionary value.
1021 */
1022 QString QDS_Datum::format( const QString& str, const QString& id, const bool convert )
1023 {
1024   Handle(DDS_DicItem) anItem;
1025   QString aStr = str;
1026   QString anUnit;
1027
1028   QString aFormat;
1029   int aType = DDS_DicItem::Unknown;
1030   Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1031   if ( !aDict.IsNull() )
1032   {
1033     anItem = aDict->GetDicItem( toAsciiString( id ) );
1034     if ( !anItem.IsNull() )
1035     {
1036       aType = anItem->GetType();
1037       aFormat = toQString( anItem->GetFormat( false ) );
1038       if ( convert )
1039         aStr = QString::number( anItem->FromSI( aStr.toDouble() ), 'f', 16 );
1040     }
1041   }
1042
1043   return format( aFormat, aType, aStr );
1044 }
1045
1046 /*!
1047   Format the given string accordance to data format.
1048 */
1049 QString QDS_Datum::format( const QString& aFormat, const int aType, const int aValue )
1050 {
1051   QString txt;
1052
1053   if ( !aFormat.isEmpty() )
1054   {
1055     switch ( aType )
1056     {
1057     case DDS_DicItem::Float:
1058       txt = sprintf( aFormat, (double)aValue );
1059       txt = txt.stripWhiteSpace();
1060       break;
1061     case DDS_DicItem::Integer:
1062       txt = sprintf( aFormat, aValue );
1063       txt = txt.stripWhiteSpace();
1064       break;
1065     case DDS_DicItem::String:
1066     default:
1067       txt = sprintf( aFormat, aValue );
1068       break;
1069     }
1070   }
1071   else
1072     txt = QString().setNum( aValue );
1073
1074   return txt;
1075 }
1076
1077 /*!
1078   Format the given string accordance to data format.
1079 */
1080 QString QDS_Datum::format( const QString& aFormat, const int aType, const double aValue )
1081 {
1082   QString txt;
1083
1084   if ( !aFormat.isEmpty() )
1085   {
1086     switch ( aType )
1087     {
1088     case DDS_DicItem::Float:
1089       txt = QString().sprintf( aFormat, aValue );
1090       txt = txt.stripWhiteSpace();
1091       break;
1092     case DDS_DicItem::Integer:
1093       txt = QString().sprintf( aFormat, (int)aValue );
1094       txt = txt.stripWhiteSpace();
1095       break;
1096     case DDS_DicItem::String:
1097     default:
1098       txt = QString().sprintf( aFormat, aValue );
1099       break;
1100     }
1101   }
1102   else
1103     txt = QString().setNum( aValue, 'g', 16 );
1104
1105   return txt;
1106 }
1107
1108 /*!
1109   Format the given string accordance to data format.
1110 */
1111 QString QDS_Datum::format( const QString& aFormat, const int aType, const QString& aValue )
1112 {
1113   QString txt = aValue;
1114
1115   if ( aType != DDS_DicItem::String )
1116     txt = txt.stripWhiteSpace();
1117
1118   if ( aFormat.isEmpty() || txt.isEmpty() )
1119     return txt;
1120
1121   switch ( aType )
1122   {
1123   case DDS_DicItem::Float:
1124     txt = txt.replace( 'd', 'e' ).replace( 'D', 'E' );
1125     txt = sprintf( aFormat, txt.toDouble() );
1126     txt = txt.stripWhiteSpace();
1127     break;
1128   case DDS_DicItem::Integer:
1129     txt = sprintf( aFormat, txt.toInt() );
1130     txt = txt.stripWhiteSpace();
1131     break;
1132   case DDS_DicItem::String:
1133     txt = sprintf( aFormat, txt );
1134     break;
1135   }
1136
1137   return txt;
1138 }
1139
1140 /*!
1141   Wrapper around the standard sprintf function.
1142   Process some non standard flags from format string.
1143 */
1144 QString QDS_Datum::sprintf( const QString& fmt, const int val )
1145 {
1146   return QString().sprintf( canonicalFormat( fmt ), val );
1147 }
1148
1149 /*!
1150   Wrapper around the standard sprintf function.
1151   Process some non standard flags from format string.
1152 */
1153 QString QDS_Datum::sprintf( const QString& fmt, const double val )
1154 {
1155   return QString().sprintf( canonicalFormat( fmt ), val );
1156 }
1157
1158 /*!
1159   Wrapper around the standard sprintf function.
1160   Process some non standard flags from format string.
1161 */
1162 QString QDS_Datum::sprintf( const QString& fmt, const QString& val )
1163 {
1164   QString aFlags;
1165   QString aFormat = canonicalFormat( fmt, aFlags );
1166
1167   QString txt = val;
1168
1169   QRegExp rx( "^(%[0-9]*.?[0-9]*s)$" );
1170   if ( aFormat.find( rx ) != -1 )
1171   {
1172     // QString().sprintf() always expects string in UTF8 encoding, so we cannot use it here
1173     char* buf = new char[txt.length() + 1];
1174     ::sprintf( buf, aFormat.latin1(), (const char*)(txt.local8Bit()) );
1175     txt = QString::fromLocal8Bit( buf );
1176
1177     delete[] buf;
1178   }
1179
1180   if ( isDoubleFormat( aFormat ) )
1181   {
1182     /*bool isOk;
1183     double aVal = txt.toDouble( &isOk );
1184     if ( isOk )
1185     {
1186       txt = sprintf( aFormat, aVal );
1187       txt = txt.replace( 'e', 'D' );
1188     }*/
1189   }
1190
1191   if ( aFlags.contains( "u", false ) )
1192     txt = txt.upper();
1193   if ( aFlags.contains( "l", false ) )
1194     txt = txt.lower();
1195
1196   return txt;
1197 }
1198
1199 /*!
1200   Returns the canonical sprintf format.
1201 */
1202 QString QDS_Datum::canonicalFormat( const QString& fmt )
1203 {
1204   QString flags;
1205   return canonicalFormat( fmt, flags );
1206 }
1207
1208 /*!
1209   Returns the canonical sprintf format and non standard flags.
1210 */
1211 QString QDS_Datum::canonicalFormat( const QString& fmt, QString& flags )
1212 {
1213   QString newFmt = fmt;
1214   flags = QString::null;
1215
1216   QRegExp rx( "^(%[0-9]*.?[0-9]*)([a-z,A-Z]+)[g|c|d|i|o|u|x|e|f|n|p|s|X|E|G]$" );
1217   if ( rx.search( newFmt ) >= 0 )
1218   {
1219     flags = rx.cap( 2 );
1220     newFmt.remove( rx.pos( 2 ), flags.length() );
1221   }
1222   return newFmt;
1223 }
1224
1225 /*!
1226   Returns displayable units string for given DD ID
1227 */
1228 QString QDS_Datum::units( const QString& id )
1229 {
1230   QString anUnit;
1231   Handle(DDS_DicItem) anItem;
1232
1233   Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1234   if ( !aDict.IsNull() )
1235   {
1236     anItem = aDict->GetDicItem( toAsciiString( id ) );
1237     if ( !anItem.IsNull() )
1238       anUnit = unitsToText( toQString( anItem->GetUnits() ) );
1239   }
1240   return anUnit;
1241 }
1242
1243 /*!
1244   Get prefix string from format.
1245 */
1246 QString QDS_Datum::prefix() const
1247 {
1248   return QString::null;
1249 }
1250
1251 /*!
1252   Get suffix string from format.
1253 */
1254 QString QDS_Datum::suffix() const
1255 {
1256   return QString::null;
1257 }
1258
1259 /*!
1260   Get min value.
1261 */
1262 QString QDS_Datum::minValue() const
1263 {
1264   QString pref = prefix();
1265   QString suff = suffix();
1266
1267   QString aMin = minimumValue().stripWhiteSpace();
1268
1269   if ( !pref.isEmpty() && aMin.left( pref.length() ) == pref )
1270     aMin = aMin.mid( pref.length() );
1271
1272   if ( !suff.isEmpty() && aMin.right( suff.length() ) == suff )
1273     aMin = aMin.mid( 0, aMin.length() - suff.length() );
1274
1275   return aMin;
1276 }
1277
1278 /*!
1279   Get max value.
1280 */
1281 QString QDS_Datum::maxValue() const
1282 {
1283   QString pref = prefix();
1284   QString suff = suffix();
1285
1286   QString aMax = maximumValue().stripWhiteSpace();
1287
1288   if ( !pref.isEmpty() && aMax.left( pref.length() ) == pref )
1289     aMax = aMax.mid( pref.length() );
1290
1291   if ( !suff.isEmpty() && aMax.right( suff.length() ) == suff )
1292     aMax = aMax.mid( 0, aMax.length() - suff.length() );
1293
1294   return aMax;
1295 }
1296
1297 /*!
1298   Reset the numeric value cache.
1299 */
1300 void QDS_Datum::invalidateCache()
1301 {
1302   myTargetValue = QString::null;
1303 }
1304
1305 QString QDS_Datum::removeAccel( const QString& src )
1306 {
1307   QString trg = src;
1308
1309   for ( uint i = 0; i < trg.length(); )
1310   {
1311     if ( trg.mid( i, 2 ) == QString( "&&" ) )
1312       i += 2;
1313     else if ( trg.at( i ) == '&' )
1314       trg.remove( i, 1 );
1315     else
1316       i++;
1317   }
1318   return trg;
1319 }
1320
1321 bool QDS_Datum::isDoubleFormat( const QString& theFormat )
1322 {
1323   if ( theFormat.length() > 0 )
1324   {
1325     QChar c = theFormat[ (int)( theFormat.length() - 1 ) ];
1326       return c == 'f' || c == 'g' || c == 'e' || c == 'G' || c == 'E';
1327   }
1328   else
1329     return false;
1330 }
1331
1332 int QDS_Datum::flags() const
1333 {
1334   return myFlags;
1335 }
1336
1337 void QDS_Datum::initDatum() const
1338 {
1339   if ( myInitialised )
1340     return;
1341
1342   QDS_Datum* that = (QDS_Datum*)this;
1343   that->myInitialised = true;
1344   that->initialize();
1345
1346   if ( parent() )
1347     parent()->removeEventFilter( this );
1348 }
1349
1350 QDS_Datum::Wrapper* QDS_Datum::wrapper( QWidget* wid ) const
1351 {
1352   if ( !wid )
1353     return 0;
1354
1355   Wrapper* wrap = 0;
1356   for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && !wrap; ++it )
1357   {
1358     if ( it.data() && it.data()->widget() == wid )
1359       wrap = it.data();
1360   }
1361   return wrap;
1362 }
1363
1364 QDS_Datum::Wrapper* QDS_Datum::wrapper( const int id ) const
1365 {
1366   Wrapper* wrap = 0;
1367   if ( myWrapper.contains( id ) )
1368     wrap = myWrapper[id];
1369   return wrap;
1370 }
1371
1372 int QDS_Datum::wrapperType( QDS_Datum::Wrapper* wrap ) const
1373 {
1374   int id = -1;
1375   for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && id == -1; ++it )
1376   {
1377     if ( it.data() == wrap )
1378       id = it.key();
1379   }
1380   return id;
1381 }