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