1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "QDS_Datum.h"
29 #include <QMessageBox>
30 #include <QApplication>
32 #include "QDS_Validator.h"
33 #include <DDS_Dictionary.h>
36 \class QDS_Datum::Wrapper
38 \brief Wrapper for sub widgets.
41 class QDS_Datum::Wrapper : public QWidget
44 Wrapper( QWidget* = 0 );
47 QWidget* widget() const;
48 void setWidget( QWidget* );
50 virtual void setGeometry( int x, int y, int w, int h );
51 virtual void setSizePolicy( QSizePolicy );
59 \param parent parent widget
61 QDS_Datum::Wrapper::Wrapper( QWidget* parent )
65 setLayout( new QHBoxLayout() );
66 layout()->setSpacing( 0 );
67 layout()->setMargin( 0 );
68 setFocusPolicy( Qt::StrongFocus );
74 QDS_Datum::Wrapper::~Wrapper()
82 QWidget* QDS_Datum::Wrapper::widget() const
91 void QDS_Datum::Wrapper::setWidget( QWidget* wid )
93 if ( myWid == wid || !wid )
96 wid->setParent( this );
97 QHBoxLayout* hl = qobject_cast<QHBoxLayout*>( layout() );
99 hl->removeWidget( myWid );
100 hl->addWidget( wid );
103 setTabOrder( this, myWid );
104 setFocusProxy( myWid );
106 myWid->updateGeometry();
111 \brief Set size policy of the widget.
112 \param sp new size policy
114 void QDS_Datum::Wrapper::setSizePolicy( QSizePolicy sp )
116 QWidget::setSizePolicy( sp );
119 widget()->setSizePolicy( sp );
123 \brief Set widget geometry.
124 \param x horizontal position
125 \param y vertical position
126 \param w widget width
127 \param h widget height
129 void QDS_Datum::Wrapper::setGeometry( int x, int y, int w, int h )
131 QWidget::setGeometry( x, y, w, h );
133 if ( widget() && widget()->size() != size() )
134 widget()->setGeometry( 0, 0, width(), height() );
139 \brief Base class for all controls using the data dictionary.
141 Datum is successor of QObject (not QWidget). This object can have up to three
142 sub widgets named as QDS::Label, QDS::Control and QDS::Units.
143 User can prevent creation of any of them by setting corresponding subwidgets IDs
144 in the parameter \a flags of the constructor.
145 QDS::Label widget displays label of datum, QDS::Control widget allows
146 entering the value and QDS::Units widget displays measure units in the active
149 These widgets are constructed under the parent widget of the datum.
150 The sub widgets are layouted in the parent widget in the following order: first widget
151 is QDS::Label, it is followed by QDS::Control, and in the end is QDS::Units.
152 User can add these widgets to layout manually using method addTo().
153 Method widget() can be used to retrieve desired widget and place it into layout.
155 When QGroupBox is used as parent widget for datum object, all subwidgets are
156 arranged automatically by the group box according to the column and orientation
157 properties of the QGroupBox.
161 QGroupBox* box = new QGroupBox( 3, Qt::Horizontal, "datum box" );
162 QDS_Datum* d1 = new QDS_Datum( "datum_1", box, All );
163 QDS_Datum* d2 = new QDS_Datum( "datum_2", box, All );
164 QDS_Datum* d3 = new QDS_Datum( "datum_3", box, All );
167 In this example we create the QGroupBox with 3 horizontal columns.
168 All the created datum widgets will be placed automatically in 3 rows.
169 Datums will be placed from top to bottom one by one and aligned in he grid.
171 Datum value is stored as string. User can get/set this value:
172 - As string : stringValue()/setStringValue().
173 - As integer : integerValue()/setIntegerValue(). Value is converted to/from SI.
174 - As double : doubleValue()/setDoubleValue(). Value is converted to/from SI.
175 - As variant : value()/setValue().
177 User can enable/disable datum subwidgets with setEnabled() method, show/hide them
178 with show()/hide() methods, set input focus to datum with setFocus(), set widgets
179 alignment with setAlignment(), etc.
185 Create datum object with datum identifier \a id and parent widget \a parent.
187 Parameter \a flags defines behaviour of datum and set of created
188 subwidgets. Default value of this parameter is QDS::All.
190 Parameter \a comp specifies the component name which will be used
191 when searching the dictionary item.
193 Datum is self-registered in the global list by QDS::insertDatum().
195 \param id datum identifier
196 \param parent parent widget
197 \param flags datum flags
198 \param comp component
200 QDS_Datum::QDS_Datum( const QString& id, QWidget* parent, const int flags, const QString& comp )
207 myInitialised( false ),
210 if ( myFlags & Label )
211 myWrapper.insert( Label, new Wrapper( parent ) );
212 if ( myFlags & Control )
213 myWrapper.insert( Control, new Wrapper( parent ) );
214 if ( myFlags & Units )
215 myWrapper.insert( Units, new Wrapper( parent ) );
217 for ( QMap<int, Wrapper*>::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it )
218 connect( it.value(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
220 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
221 if ( aDict.IsNull() )
224 TCollection_AsciiString anId = toAsciiString( id );
225 TCollection_AsciiString aComp = toAsciiString( comp );
227 if ( aComp.IsEmpty() )
228 setDicItem( aDict->GetDicItem( anId ) );
230 setDicItem( aDict->GetDicItem( anId, aComp ) );
232 QTimer::singleShot( 0, this, SLOT( onInitDatum() ) );
235 parent->installEventFilter( this );
243 Destroy all subwidget. Datum is unregistered from the global list
244 by QDS::removeDatum().
246 QDS_Datum::~QDS_Datum()
254 for ( QMap<int, Wrapper*>::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it )
260 \brief Overloaded operator used to retrieve main subwidget named QDS::Control.
261 \return QDS::Control subwidget
263 QDS_Datum::operator QWidget*() const
265 return widget( Control );
269 \brief Get the datum ID.
272 QString QDS_Datum::id() const
280 \brief Get the datum value type.
281 \return datum value type
283 int QDS_Datum::type() const
287 int res = DDS_DicItem::Unknown;
288 if ( !myDicItem.IsNull() )
289 res = myDicItem->GetType();
294 \brief Return state of custom translation.
295 \return true if custom translation is enabled
297 bool QDS_Datum::isCustomTr() const
303 \brief Change state of custom translation.
305 Custom translation means that text labels of datums are translated
306 with help of standard Qt mechanism of internationalization. In this
307 case special records should be placed into *.ts files under context "QDS".
308 For example, if label has name "myLabel", the corresponding translation
313 <source>myLabel</source>
314 <translation>myLabel translation</translation>
318 If custom translation mechanism is deactivated, then labels will be shown
319 with text got from xml data dictionary file
321 By default, the custom translation is deactivated
323 \param on - if it is true, custom translation is activated, otherwise, deactivated
325 void QDS_Datum::enableCustomTr( const bool on )
328 labelWidget()->setText( label() );
332 \brief Get the datum label text.
335 QString QDS_Datum::label() const
340 if ( !myDicItem.IsNull() )
342 labStr = toQString( myDicItem->GetLabel() );
343 if( labStr.isNull() )
344 labStr = toQString( myDicItem->GetId() );
346 if( myTr && labStr.length()>0 )
348 QString dest = QApplication::translate( "QDS", labStr.toLatin1().constData() );
352 if ( flags() & NotAccel )
353 labStr = removeAccel( labStr );
358 \brief Get the datum units text.
361 QString QDS_Datum::units() const
366 if ( !myDicItem.IsNull() )
367 unitStr = toQString( myDicItem->GetUnits() );
372 \brief Get the datum filter string.
373 \return filter string
375 QString QDS_Datum::filter() const
380 if ( !myDicItem.IsNull() )
381 fltr = toQString( myDicItem->GetFilter() );
386 \brief Get the datum format string
387 \return format string
389 QString QDS_Datum::format() const
394 if ( !myDicItem.IsNull() )
395 fmtStr = toQString( myDicItem->GetFormat( false ) );
400 \brief Get the datum default value
401 \return default value
403 QString QDS_Datum::defaultValue() const
407 QString pref = prefix();
408 QString suff = suffix();
411 if ( !myDicItem.IsNull() )
412 def = toQString( myDicItem->GetDefaultValue() );
414 QString aDef = def.trimmed();
415 if ( !pref.isEmpty() && aDef.left( pref.length() ) == pref )
416 aDef = aDef.mid( pref.length() );
418 if ( !suff.isEmpty() && aDef.right( suff.length() ) == suff )
419 aDef = aDef.mid( 0, aDef.length() - suff.length() );
425 \brief Get the datum minimum value.
426 \return minimum value
428 QString QDS_Datum::minimumValue() const
433 if ( !myDicItem.IsNull() && myDicItem->HasData( DDS_DicItem::MinValue ) )
434 min = format( format(), type(), myDicItem->GetMinValue() );
439 \brief Get the datum maximum value.
440 \return maximum value
442 QString QDS_Datum::maximumValue() const
447 if ( !myDicItem.IsNull() && myDicItem->HasData( DDS_DicItem::MaxValue ) )
448 max = format( format(), type(), myDicItem->GetMaxValue() );
453 \brief Get the datum long description.
454 \return datum long description
456 QString QDS_Datum::longDescription() const
461 if ( !myDicItem.IsNull() )
462 ldStr = toQString( myDicItem->GetLongDescription() );
467 \brief Get the datum short description.
468 \return datum short description
470 QString QDS_Datum::shortDescription() const
475 if ( !myDicItem.IsNull() )
476 sdStr = toQString( myDicItem->GetLongDescription() );
481 \brief Get the datum options names.
482 \return datum options
484 QStringList QDS_Datum::options() const
487 if ( !dicItem().IsNull() )
489 TColStd_SequenceOfAsciiString lst;
490 dicItem()->GetOptionNames( lst );
491 for ( int i = 1; i <= lst.Length(); i++ )
492 res.append( toQString( lst.Value( i ) ) );
498 \brief Get datum option specified by \a name as QVariant.
499 \return the option value or invalid QVariant if the option does not exist
501 QVariant QDS_Datum::option( const QString& name ) const
504 if ( !dicItem().IsNull() )
505 res = QVariant( toQString( dicItem()->GetOption( toAsciiString( name ) ) ) );
510 \brief Get datum option specified by \a name as string.
511 \return the option value or null QString if the option does not exist
513 QString QDS_Datum::optionString( const QString& name ) const
516 if ( !dicItem().IsNull() )
517 res = toQString( dicItem()->GetOption( toAsciiString( name ) ) );
522 \brief Get datum option specified by \a name as double.
523 \return the option value or 0 if the option does not exist
525 double QDS_Datum::optionDouble( const QString& name ) const
528 QVariant opt = option( name );
529 if ( opt.isValid() && opt.canConvert( QVariant::Double ) )
530 res = opt.toDouble();
535 \brief Get datum option specified by \a name as integer.
536 \return the option value or 0 if the option does not exist
538 int QDS_Datum::optionInteger( const QString& name ) const
541 QVariant opt = option( name );
542 if ( opt.isValid() && opt.canConvert( QVariant::Int ) )
548 \brief Get the datum value as QVariant.
551 QVariant QDS_Datum::value() const
554 // trying to return QVariant containing value of correct data type
555 if ( dicItem().IsNull() )
564 case DDS_DicItem::Float:
567 case DDS_DicItem::Integer:
568 case DDS_DicItem::List:
569 val = integerValue();
571 case DDS_DicItem::String:
572 case DDS_DicItem::Unknown:
581 \brief Get the datum value as string.
582 \return datum value converted to string
584 QString QDS_Datum::stringValue() const
588 if ( getString() == myTargetValue )
589 return mySourceValue;
595 \brief Get the datum value as double.
597 The value is converted according to the measure units in the active units system
598 to measure units in "SI" units system.
600 \return datum value converted to double
602 double QDS_Datum::doubleValue() const
607 if ( !myTargetValue.isNull() && myTargetValue == getString() )
608 res = mySourceValue.toDouble();
611 res = getString().toDouble();
612 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
613 res = myDicItem->ToSI( res );
620 \brief Get the datum value as integer.
622 The value is converted according to the measure units in the active units system
623 to measure units in "SI" units system.
625 \return datum value converted to integer
627 int QDS_Datum::integerValue() const
632 if ( !myTargetValue.isNull() && myTargetValue == getString() )
633 res = mySourceValue.toInt();
636 double val = getString().toDouble();
637 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
638 res = (int)myDicItem->ToSI( val );
645 \brief Get the text data from datum.
647 Text consists of label, string value and units.
649 \return datum text data
651 QString QDS_Datum::text() const
655 QString aLabel = label();
656 QString aData = stringValue();
657 QString aUnits = units();
659 QString res = aLabel;
660 if ( !res.isEmpty() && !aData.isEmpty() )
661 res += QString( ": " );
664 if ( !aUnits.isEmpty() )
665 res += QString( " " ) + aUnits;
671 \brief Check if the datum is empty.
672 \return \c false if datum control has value entered
674 bool QDS_Datum::isEmpty() const
676 return stringValue().isEmpty();
680 \brief Reset datum state and set default value as current.
682 void QDS_Datum::reset()
686 mySourceValue = defaultValue();
687 setString( format( ( myFlags & NotFormat ) ? (QString) "" : format(), type(), mySourceValue ) );
691 QString str = getString();
693 emit paramChanged( str );
697 \brief Clear the control.
699 void QDS_Datum::clear()
703 if ( !getString().isEmpty() )
706 setString( mySourceValue );
710 QString str = getString();
712 emit paramChanged( str );
717 \brief Set datum value from QVariant object.
720 void QDS_Datum::setValue( const QVariant& val )
722 // trying to extract data of correct type from QVariant
723 if ( !dicItem().IsNull() )
728 case DDS_DicItem::Float:
730 double aDblVal = val.toDouble( &isOk );
733 setDoubleValue( aDblVal );
738 case DDS_DicItem::Integer:
739 case DDS_DicItem::List:
741 int anIntVal = val.toInt( &isOk );
744 setIntegerValue( anIntVal );
749 case DDS_DicItem::String:
750 case DDS_DicItem::Unknown:
755 if ( val.isValid() && val.canConvert( QVariant::String ) )
756 setStringValue( val.toString() );
762 \brief Set datum value from string data.
765 void QDS_Datum::setStringValue( const QString& txt )
770 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), txt );
772 myTargetValue = aStr;
775 QString str = getString();
777 emit paramChanged( str );
781 \brief Set datum value from double data.
783 The value is converted from measure units in "SI" units system
784 to the measure units in the active units system.
785 Format the value using datum format internal if it is required.
789 void QDS_Datum::setDoubleValue( const double num )
793 mySourceValue = QString().setNum( num, 'g', 16 );
795 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
796 val = myDicItem->FromSI( val );
798 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
800 myTargetValue = aStr;
803 QString str = getString();
805 emit paramChanged( str );
809 \brief Set datum value from integer data.
811 The value is converted from measure units in "SI" units system
812 to the measure units in the active units system.
813 Format the value using datum format if it is required.
817 void QDS_Datum::setIntegerValue( const int num )
821 mySourceValue = QString().setNum( num );
823 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
824 val = myDicItem->FromSI( val );
826 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
828 myTargetValue = aStr;
831 QString str = getString();
833 emit paramChanged( str );
837 \brief Get 'enabled' state of the specified subwidget.
838 \param element ORed subwidget flags (QDS::DatumFlags)
839 \return \c true if all subwidgets specified by \a element are enabled
842 bool QDS_Datum::isEnabled( const int element ) const
847 if ( element & Label )
848 res = res && labelWidget() && labelWidget()->isEnabled();
849 if ( element & Units )
850 res = res && unitsWidget() && unitsWidget()->isEnabled();
851 if ( element & Control )
852 res = res && controlWidget() && controlWidget()->isEnabled();
857 \brief Enable/disable subwidgets specified by \a element.
859 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
860 or their ORed combinations.
862 \param on new 'enabled' state
863 \param element ORed subwidget flags (QDS::DatumFlags)
866 void QDS_Datum::setEnabled( const bool on, const int element )
870 if ( element & Label && labelWidget() )
871 labelWidget()->setEnabled( on );
872 if ( element & Units && unitsWidget() )
873 unitsWidget()->setEnabled( on );
874 if ( element & Control && controlWidget() )
875 controlWidget()->setEnabled( on );
879 \brief Enable/disable main control subwidget (QDS::Control).
880 \param on new 'enabled' state
882 void QDS_Datum::setEnabled( bool on )
884 setEnabled( on, Control );
888 \brief Show/hide subwidgets specified by \a flags.
890 Possible values of \a flags: QDS::Label, QDS::Control, QDS::Units
891 or their ORed combinations.
893 \param visible new 'visibility' state
894 \param flags ORed subwidget flags (QDS::DatumFlags)
897 void QDS_Datum::setShown( const bool visible, const int flags )
904 if ( flags & flag && widget( flag ) )
905 widget( flag )->setShown( visible );
911 \brief Show subwidgets specified by \a element.
913 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
914 or their ORed combinations.
916 \param element ORed subwidget flags (QDS::DatumFlags)
917 \sa hide(), setShown()
919 void QDS_Datum::show( const int element )
921 setShown( true, element );
925 \brief Hide subwidgets specified by \a element.
927 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
928 or their ORed combinations.
930 \param element ORed subwidget flags (QDS::DatumFlags)
931 \sa show(), setShown()
933 void QDS_Datum::hide( const int element )
935 setShown( false, element );
939 \brief Get subwidget specified by \a element.
941 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units.
943 \param element subwidget
946 QWidget* QDS_Datum::widget( const int element ) const
949 return wrapper( element );
953 \brief Set the input focus to the control widget.
955 void QDS_Datum::setFocus()
959 if ( controlWidget() )
960 controlWidget()->setFocus();
964 \brief Check if input data is valid.
966 If data is invalid and \a msgBox is \c true, the warning message box is shown.
968 \param msgBox if \c true, show warning message box if input is invalid
969 \param extMsg warning message
970 \param extLabel optional name of the variable (if QDS::Label control is not used)
971 \return \c true if input data is valid
973 bool QDS_Datum::isValid( const bool msgBox, const QString& extMsg, const QString& extLabel ) const
977 if ( type() == DDS_DicItem::String && isDoubleFormat( format() ) )
981 if ( !dicItem().IsNull() )
982 req = toQString( dicItem()->GetRequired() );
985 QString aStr = getString();
987 if ( aStr.isEmpty() )
988 aState = !( req == QString( "yes" ) || req == QString( "true" ) || req.toInt() );
990 aState = validate( aStr );
992 if ( msgBox && !aState )
995 if ( !label().isEmpty() )
996 info += tr( "DATA_INCORRECT_VALUE" ).arg( label() );
997 else if ( !extLabel.isEmpty() )
998 info += tr( "DATA_INCORRECT_VALUE" ).arg( extLabel );
1003 case DDS_DicItem::String:
1004 typeStr = tr( "DATA_STRING" );
1006 case DDS_DicItem::Integer:
1007 typeStr = tr( "DATA_INTEGER" );
1009 case DDS_DicItem::Float:
1010 typeStr = tr( "DATA_FLOAT" );
1013 typeStr = tr( "DATA_NON_EMPTY" );
1016 info += ( info.isEmpty() ? (QString) "" : QString( "\n" ) ) +
1017 tr( "DATA_SHOULD_BE_VALUE" ).arg( typeStr );
1019 if ( type() == DDS_DicItem::Float || type() == DDS_DicItem::Integer )
1021 QString aMinValue = minValue();
1022 QString aMaxValue = maxValue();
1023 if ( !aMinValue.isEmpty() && !aMaxValue.isEmpty() )
1024 limit = tr( "DATA_RANGE" ).arg( aMinValue ).arg( aMaxValue );
1025 else if ( !aMinValue.isEmpty() )
1026 limit = tr( "DATA_MIN_LIMIT" ).arg( aMinValue );
1027 else if ( !aMaxValue.isEmpty() )
1028 limit = tr( "DATA_MAX_LIMIT" ).arg( aMaxValue );
1030 if ( !limit.isEmpty() )
1033 info += QString( ".\n" ) + tr( "DATA_INPUT_VALUE" );
1035 if ( !extMsg.isEmpty() )
1036 info += QString( "\n" ) + extMsg;
1039 for ( int i = 0; i < info.length(); i++ )
1040 if ( info.at( i ) == '\n' )
1041 msg += QString( "<br>" );
1043 msg += info.at( i );
1045 info = QString( "<p><nobr>%1</nobr></p>" ).arg( msg );
1047 QMessageBox::critical( controlWidget() ? controlWidget()->topLevelWidget() : 0,
1048 tr( "DATA_ERR_TITLE" ), info, tr( "OK" ) );
1049 if ( controlWidget() )
1050 controlWidget()->setFocus();
1056 \brief Add widgets to the vertical box layout.
1059 void QDS_Datum::addTo( QVBoxLayout* l )
1066 if ( wrapper( Label ) )
1067 l->addWidget( wrapper( Label ) );
1068 if ( wrapper( Control ) )
1069 l->addWidget( wrapper( Control ) );
1070 if ( wrapper( Units ) )
1071 l->addWidget( wrapper( Units ) );
1075 \brief Add widgets to the horizontal box layout.
1078 void QDS_Datum::addTo( QHBoxLayout* l )
1085 if ( wrapper( Label ) )
1086 l->addWidget( wrapper( Label ) );
1087 if ( wrapper( Control ) )
1088 l->addWidget( wrapper( Control ) );
1089 if ( wrapper( Units ) )
1090 l->addWidget( wrapper( Units ) );
1094 \brief Add widgets to the grid layout.
1095 \param theLay layout
1096 \param theRow layout row index
1097 \param theCol layout column index
1098 \param vertical if \c true subwidgets are layouted vertically, otherwise - horizontally
1100 void QDS_Datum::addTo( QGridLayout* theLay, const int theRow, const int theCol, bool vertical )
1109 if ( wrapper( Label ) )
1111 theLay->addWidget( wrapper( Label ), row, col );
1112 vertical ? row++ : col++;
1114 if ( wrapper( Control ) )
1116 theLay->addWidget( wrapper( Control ), row, col );
1117 vertical ? row++ : col++;
1119 if ( wrapper( Units ) )
1120 theLay->addWidget( wrapper( Units ), row, col );
1124 \brief Set the aligment for QDS::Label and/or QDS::Units subwidgets.
1125 \param align alignment type (Qt::Alignment)
1126 \param type ORed subwidget flags
1128 void QDS_Datum::setAlignment( const int align, const int type )
1132 if ( ( type & Label ) && labelWidget() )
1133 labelWidget()->setAlignment( Qt::Alignment(align) );
1134 if ( ( type & Units ) && unitsWidget() )
1135 unitsWidget()->setAlignment( Qt::Alignment(align) );
1139 \brief Event filter.
1141 Perform delayed initialisation. Reimplemented for internal reasons.
1143 \param o event reciever object
1145 \return \c true if event should be filtered
1147 bool QDS_Datum::eventFilter( QObject* o, QEvent* e )
1149 if ( o == parent() )
1151 if ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
1152 ( e->type() == QEvent::ChildAdded && ((QChildEvent*)e)->child() == this ) )
1155 return QObject::eventFilter( o, e );
1159 \brief Called when datum value is changed.
1161 void QDS_Datum::onParamChanged()
1166 \brief Perform delayed initialization.
1168 void QDS_Datum::onInitDatum()
1174 \brief Called when child subwidget is destroued.
1176 Allows avoiding crash of extra calling of the child subwidget destructor.
1178 \param obj object being destroyed
1180 void QDS_Datum::onDestroyed( QObject* obj )
1182 myWrapper.remove( wrapperType( (Wrapper*)obj ) );
1186 \brief Get QDS::Label widget.
1187 \return label widget
1189 QLabel* QDS_Datum::labelWidget() const
1196 \brief Get QDS::Units widget.
1197 \return units widget
1199 QLabel* QDS_Datum::unitsWidget() const
1206 \brief Get QDS::Control widget.
1207 \return control widget
1209 QWidget* QDS_Datum::controlWidget() const
1216 \brief Get the dictionary item from the datum.
1217 \return handle to data dictionary item
1219 Handle(DDS_DicItem) QDS_Datum::dicItem() const
1225 \brief Set the dictionary item to the datum.
1226 \param item handle to data dictionary item
1228 void QDS_Datum::setDicItem( const Handle(DDS_DicItem)& item )
1234 \brief Create QDS::Label widget.
1235 \param parent parent widget
1236 \return label widget
1238 QLabel* QDS_Datum::createLabel( QWidget* parent )
1240 return new QLabel( parent );
1244 \brief Create QDS::Units widget.
1245 \param parent parent widget
1246 \return units widget
1248 QLabel* QDS_Datum::createUnits( QWidget* parent )
1250 return new QLabel( parent );
1254 \fn QWidget* QDS_Datum::createControl( QWidget* parent );
1255 \brief Create QDS::Control widget.
1257 This method should be implemented in the successor classes.
1259 \param parent parent widget
1260 \return control widget
1264 \fn QString QDS_Datum::getString() const;
1265 \brief Get string value from datum.
1267 This method should be implemented in the successor classes.
1269 \return datum string value
1273 \fn void QDS_Datum::setString( const QString& txt );
1274 \brief Set string value to datum.
1276 This method should be implemented in the successor classes.
1278 \param txt new datum string value
1282 \brief Create validator according to the datum type of value.
1283 \param limits if \c true use minimum and maximum value limits
1286 QValidator* QDS_Datum::validator( const bool limits ) const
1288 QValidator* aValidator = 0;
1290 QString fltr = filter();
1292 if ( type() == DDS_DicItem::String )
1295 QString aFormat = canonicalFormat( format(), aFlags );
1298 int pos = aFormat.indexOf( "." );
1301 QString numStr = aFormat.mid( pos + 1, aFormat.length() - pos - 2 );
1303 int numVal = numStr.toInt( &ok );
1308 QDS_StringValidator* aStrVal = new QDS_StringValidator( fltr, aFlags, (QObject*)this );
1309 aStrVal->setLength( len );
1311 aValidator = aStrVal;
1313 else if ( type() == DDS_DicItem::Integer )
1315 QDS_IntegerValidator* aIntVal = new QDS_IntegerValidator( fltr, (QObject*)this );
1319 limit = minValue().toInt( &ok );
1321 aIntVal->setBottom( limit );
1322 limit = maxValue().toInt( &ok );
1324 aIntVal->setTop( limit );
1326 aValidator = aIntVal;
1328 else if ( type() == DDS_DicItem::Float )
1330 QDS_DoubleValidator* aFloatVal = new QDS_DoubleValidator( fltr, (QObject*)this );
1334 limit = minValue().toDouble( &ok );
1336 aFloatVal->setBottom( limit );
1337 limit = maxValue().toDouble( &ok );
1339 aFloatVal->setTop( limit );
1341 aValidator = aFloatVal;
1348 \brief Validate the specified string.
1349 \param txt string to be validated
1350 \return \c true if string contains valid data
1352 bool QDS_Datum::validate( const QString& txt ) const
1354 if ( type() == DDS_DicItem::Unknown ||
1355 ( type() == DDS_DicItem::String && isDoubleFormat( format() ) ) )
1358 QValidator* aValidator = validator( true );
1365 bool res = aValidator->validate( str, pos ) == QValidator::Acceptable;
1373 \brief Initialize datum.
1375 Retrieve information from data dictionary and create subwidgets
1376 using virtual mechanism.
1378 Virtual mechanism doesn't work in the constructor, therefore this method should
1379 be called outside the constructor.
1381 void QDS_Datum::initialize()
1383 if ( wrapper( Label ) )
1384 wrapper( Label )->setWidget( myLabel = createLabel( wrapper( Label ) ) );
1385 if ( wrapper( Control ) )
1386 wrapper( Control )->setWidget( myControl = createControl( wrapper( Control ) ) );
1387 if ( wrapper( Units ) )
1388 wrapper( Units )->setWidget( myUnits = createUnits( wrapper( Units ) ) );
1390 TCollection_AsciiString comp;
1391 Handle(DDS_DicItem) item = dicItem();
1392 if ( !item.IsNull() )
1393 comp = item->GetComponent();
1396 Handle(DDS_Dictionary) dic = DDS_Dictionary::Get();
1397 if ( !dic.IsNull() )
1398 unitSystem = toQString( comp.IsEmpty() ? dic->GetActiveUnitSystem() :
1399 dic->GetActiveUnitSystem( comp ) );
1401 unitSystemChanged( unitSystem );
1403 QWidget* ctrl = controlWidget();
1406 QString lDescr = longDescription();
1407 QString sDescr = shortDescription();
1408 if ( !sDescr.isEmpty() )
1409 ctrl->setToolTip( sDescr );
1410 if ( !lDescr.isEmpty() )
1411 ctrl->setWhatsThis( lDescr );
1414 if ( labelWidget() && ctrl && !( flags() & NotAccel ) )
1415 labelWidget()->setBuddy( ctrl );
1419 \brief Process notification about active units system changing.
1421 Update label and units widgets.
1423 \param unitSystem new active units system
1425 void QDS_Datum::unitSystemChanged( const QString& unitSystem )
1427 QString labText = label();
1428 QString unitText = unitsToText( units() );
1430 if ( flags() & UnitsWithLabel )
1432 if ( labText.isEmpty() )
1434 else if ( !unitText.isEmpty() )
1435 labText = QString( "%1 (%2)" ).arg( labText ).arg( unitText );
1436 unitText = QString();
1439 if ( labelWidget() )
1440 labelWidget()->setText( labText );
1442 if ( unitsWidget() )
1443 unitsWidget()->setText( unitText );
1449 \brief Convert units into text presentation.
1450 \param uni units to be converted
1451 \return text presentation of units (rich-text)
1453 QString QDS_Datum::unitsToText( const QString& uni )
1456 QString aUnits = uni;
1457 while ( ( pos = aUnits.indexOf( "**" ) ) != -1 )
1459 aUnits = aUnits.mid( 0, pos ) + QString( "<tt><font size=+2><sup>" ) +
1460 aUnits.mid( pos + 2, 1 ) + QString( "</sup></font></tt>" ) +
1461 aUnits.mid( pos + 3 );
1467 \brief Convert text presentation into internal units format.
1468 \param txt text presentation of units (rich-text)
1471 QString QDS_Datum::textToUnits( const QString& txt )
1474 QString aUnits = txt;
1475 while ( ( pos = aUnits.indexOf( "<sup>" ) ) != -1 )
1477 aUnits.remove( pos, 5 );
1478 aUnits.insert( pos, "**" );
1480 while ( ( pos = aUnits.indexOf( "</sup>" ) ) != -1 )
1481 aUnits.remove( pos, 6 );
1486 \brief Format the specified integer as dictionary item value.
1487 \param num integer value being formatted
1488 \param id data dictionary ID
1489 \param convert if \c true, perform conversion from "SI" units system
1490 \return formatted value
1492 QString QDS_Datum::format( const int num, const QString& id, const bool convert )
1494 Handle(DDS_DicItem) anItem;
1499 int aType = DDS_DicItem::Unknown;
1500 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1501 if ( !aDict.IsNull() )
1503 anItem = aDict->GetDicItem( toAsciiString( id ) );
1504 if ( !anItem.IsNull() )
1506 aType = anItem->GetType();
1507 aFormat = toQString( anItem->GetFormat( false ) );
1509 aNum = ( int )anItem->FromSI( aNum );
1513 return format( aFormat, aType, aNum );
1517 \brief Format the specified double as dictionary item value.
1518 \param num double value being formatted
1519 \param id data dictionary ID
1520 \param convert if \c true, perform conversion from "SI" units system
1521 \return formatted value
1523 QString QDS_Datum::format( const double num, const QString& id, const bool convert )
1525 Handle(DDS_DicItem) anItem;
1530 int aType = DDS_DicItem::Unknown;
1531 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1532 if ( !aDict.IsNull() )
1534 anItem = aDict->GetDicItem( toAsciiString( id ) );
1535 if ( !anItem.IsNull() )
1537 aType = anItem->GetType();
1538 aFormat = toQString( anItem->GetFormat( false ) );
1540 aNum = anItem->FromSI( aNum );
1544 return format( aFormat, aType, aNum );
1548 \brief Format the specified string as dictionary item value.
1549 \param str string value being formatted
1550 \param id data dictionary ID
1551 \param convert if \c true, perform conversion from "SI" units system
1552 \return formatted value
1554 QString QDS_Datum::format( const QString& str, const QString& id, const bool convert )
1556 Handle(DDS_DicItem) anItem;
1561 int aType = DDS_DicItem::Unknown;
1562 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1563 if ( !aDict.IsNull() )
1565 anItem = aDict->GetDicItem( toAsciiString( id ) );
1566 if ( !anItem.IsNull() )
1568 aType = anItem->GetType();
1569 aFormat = toQString( anItem->GetFormat( false ) );
1571 aStr = QString::number( anItem->FromSI( aStr.toDouble() ), 'f', 16 );
1575 return format( aFormat, aType, aStr );
1579 \brief Format the given value according to the data dictionary item type.
1580 \param aFormat format string
1581 \param aType data dictionary item type
1582 \param aValue integer value being formatted
1583 \return formatted value
1585 QString QDS_Datum::format( const QString& aFormat, const int aType, const int aValue )
1589 if ( !aFormat.isEmpty() )
1593 case DDS_DicItem::Float:
1594 txt = sprintf( aFormat, (double)aValue );
1595 txt = txt.trimmed();
1597 case DDS_DicItem::Integer:
1598 txt = sprintf( aFormat, aValue );
1599 txt = txt.trimmed();
1601 case DDS_DicItem::String:
1603 txt = sprintf( aFormat, aValue );
1608 txt = QString().setNum( aValue );
1614 \brief Format the given value according to the data dictionary item type.
1615 \param aFormat format string
1616 \param aType data dictionary item type
1617 \param aValue double value being formatted
1618 \return formatted value
1620 QString QDS_Datum::format( const QString& aFormat, const int aType, const double aValue )
1624 if ( !aFormat.isEmpty() )
1628 case DDS_DicItem::Float:
1629 txt = QString().sprintf( aFormat.toLatin1().constData(), aValue );
1630 txt = txt.trimmed();
1632 case DDS_DicItem::Integer:
1633 txt = QString().sprintf( aFormat.toLatin1().constData(), (int)aValue );
1634 txt = txt.trimmed();
1636 case DDS_DicItem::String:
1638 txt = QString().sprintf( aFormat.toLatin1().constData(), aValue );
1643 txt = QString().setNum( aValue, 'g', 16 );
1649 \brief Format the given value according to the data dictionary item type.
1650 \param aFormat format string
1651 \param aType data dictionary item type
1652 \param aValue string value being formatted
1653 \return formatted value
1655 QString QDS_Datum::format( const QString& aFormat, const int aType, const QString& aValue )
1657 QString txt = aValue;
1659 if ( aType != DDS_DicItem::String )
1660 txt = txt.trimmed();
1662 if ( aFormat.isEmpty() || txt.isEmpty() )
1667 case DDS_DicItem::Float:
1668 txt = txt.replace( 'd', 'e' ).replace( 'D', 'E' );
1669 txt = sprintf( aFormat, txt.toDouble() );
1670 txt = txt.trimmed();
1672 case DDS_DicItem::Integer:
1673 txt = sprintf( aFormat, txt.toInt() );
1674 txt = txt.trimmed();
1676 case DDS_DicItem::String:
1677 txt = sprintf( aFormat, txt );
1685 \brief Wrapper around the standard sprintf() function.
1687 Process some non standard flags from format string.
1689 \param fmt string format
1691 \return formatted value
1693 QString QDS_Datum::sprintf( const QString& fmt, const int val )
1695 return QString().sprintf( canonicalFormat( fmt ).toLatin1().constData(), val );
1699 \brief Wrapper around the standard sprintf() function.
1702 Process some non standard flags from format string.
1704 \param fmt string format
1706 \return formatted value
1708 QString QDS_Datum::sprintf( const QString& fmt, const double val )
1710 return QString().sprintf( canonicalFormat( fmt ).toLatin1().constData(), val );
1714 \brief Wrapper around the standard sprintf() function.
1717 Process some non standard flags from format string.
1719 \param fmt string format
1721 \return formatted value
1723 QString QDS_Datum::sprintf( const QString& fmt, const QString& val )
1726 QString aFormat = canonicalFormat( fmt, aFlags );
1730 QRegExp rx( "^(%[0-9]*.?[0-9]*s)$" );
1731 if ( aFormat.indexOf( rx ) != -1 )
1733 // QString().sprintf() always expects string in UTF8 encoding, so we cannot use it here
1734 char* buf = new char[txt.length() + 1];
1735 ::sprintf( buf, aFormat.toLatin1().constData(), (const char*)(txt.toLocal8Bit()) );
1736 txt = QString::fromLocal8Bit( buf );
1741 if ( isDoubleFormat( aFormat ) )
1744 double aVal = txt.toDouble( &isOk );
1747 txt = sprintf( aFormat, aVal );
1748 txt = txt.replace( 'e', 'D' );
1752 if ( aFlags.contains( "u", Qt::CaseInsensitive ) )
1753 txt = txt.toUpper();
1754 if ( aFlags.contains( "l", Qt::CaseInsensitive ) )
1755 txt = txt.toLower();
1761 \brief Get the canonical sprintf() format.
1762 \param fmt string format
1763 \return canonical sprintf() format
1765 QString QDS_Datum::canonicalFormat( const QString& fmt )
1768 return canonicalFormat( fmt, flags );
1772 \brief Get the canonical sprintf() format and non standard flags.
1773 \param fmt string format
1774 \param flags format flags
1775 \return canonical sprintf() format
1777 QString QDS_Datum::canonicalFormat( const QString& fmt, QString& flags )
1779 QString newFmt = fmt;
1782 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]$" );
1783 if ( rx.indexIn( newFmt ) >= 0 )
1785 flags = rx.cap( 2 );
1786 newFmt.remove( rx.pos( 2 ), flags.length() );
1792 \brief Get displayable units string for specified data dictionary item.
1793 \param id data dictionary item ID
1794 \return units string
1796 QString QDS_Datum::units( const QString& id )
1799 Handle(DDS_DicItem) anItem;
1801 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1802 if ( !aDict.IsNull() )
1804 anItem = aDict->GetDicItem( toAsciiString( id ) );
1805 if ( !anItem.IsNull() )
1806 anUnit = unitsToText( toQString( anItem->GetUnits() ) );
1812 \brief Get prefix string from format.
1813 \return current implementation returns null string
1815 QString QDS_Datum::prefix() const
1821 \brief Get suffix string from format.
1822 \return current implementation returns null string
1824 QString QDS_Datum::suffix() const
1830 \brief Get minimum value.
1831 \return minimum value
1833 QString QDS_Datum::minValue() const
1835 QString pref = prefix();
1836 QString suff = suffix();
1838 QString aMin = minimumValue().trimmed();
1840 if ( !pref.isEmpty() && aMin.left( pref.length() ) == pref )
1841 aMin = aMin.mid( pref.length() );
1843 if ( !suff.isEmpty() && aMin.right( suff.length() ) == suff )
1844 aMin = aMin.mid( 0, aMin.length() - suff.length() );
1850 \brief Get maximum value.
1851 \return maximum value
1853 QString QDS_Datum::maxValue() const
1855 QString pref = prefix();
1856 QString suff = suffix();
1858 QString aMax = maximumValue().trimmed();
1860 if ( !pref.isEmpty() && aMax.left( pref.length() ) == pref )
1861 aMax = aMax.mid( pref.length() );
1863 if ( !suff.isEmpty() && aMax.right( suff.length() ) == suff )
1864 aMax = aMax.mid( 0, aMax.length() - suff.length() );
1870 \brief Reset the numeric value cache.
1872 void QDS_Datum::invalidateCache()
1874 myTargetValue = QString();
1878 \brief Remove the acceleartor tags '&' from specified label string \a src.
1879 \param src processed string
1880 \return string after removing '&' symbols
1882 QString QDS_Datum::removeAccel( const QString& src )
1886 for ( uint i = 0; i < trg.length(); )
1888 if ( trg.mid( i, 2 ) == QString( "&&" ) )
1890 else if ( trg.at( i ) == '&' )
1899 \brief Check if given format specified doube value.
1900 \param theFormat format string
1901 \return \c true if \a theFormat has specificator for double values
1903 bool QDS_Datum::isDoubleFormat( const QString& theFormat )
1905 if ( theFormat.length() > 0 )
1907 QChar c = theFormat[ (int)( theFormat.length() - 1 ) ];
1908 return c == 'f' || c == 'g' || c == 'e' || c == 'G' || c == 'E';
1915 \brief Get datum flags.
1916 \return datum flags (QDS::DatumFlags)
1918 int QDS_Datum::flags() const
1924 \brief Perform initialization if it needed.
1927 void QDS_Datum::initDatum() const
1929 if ( myInitialised )
1932 QDS_Datum* that = (QDS_Datum*)this;
1933 that->myInitialised = true;
1937 parent()->removeEventFilter( (QObject*)this );
1941 \brief Get wrapper for specified subwidget.
1943 \param wid subwidget
1946 QDS_Datum::Wrapper* QDS_Datum::wrapper( QWidget* wid ) const
1952 for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && !wrap; ++it )
1954 if ( it.value() && it.value()->widget() == wid )
1961 \brief Get wrapper for specified subwidget.
1963 \param id subwidget ID
1966 QDS_Datum::Wrapper* QDS_Datum::wrapper( const int id ) const
1969 if ( myWrapper.contains( id ) )
1970 wrap = myWrapper[id];
1975 \brief Get subwidget type for specified wrapper.
1978 \return subwidget ID
1980 int QDS_Datum::wrapperType( QDS_Datum::Wrapper* wrap ) const
1983 for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && id == -1; ++it )
1985 if ( it.value() == wrap )
1992 \fn void QDS_Datum::paramChanged();
1993 \brief The signal is emitted when the datum value is changed.
1997 void QDS_Datum::paramChanged( QString& txt );
1998 \brief The signal is emitted when the datum value is changed.
1999 \param txt new datum value