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