1 // Copyright (C) 2007-2012 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
560 \brief Get the datum value as string.
561 \return datum value converted to string
563 QString QDS_Datum::stringValue() const
567 if ( getString() == myTargetValue )
568 return mySourceValue;
574 \brief Get the datum value as double.
576 The value is converted according to the measure units in the active units system
577 to measure units in "SI" units system.
579 \return datum value converted to double
581 double QDS_Datum::doubleValue() const
586 if ( !myTargetValue.isNull() && myTargetValue == getString() )
587 res = mySourceValue.toDouble();
590 res = getString().toDouble();
591 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
592 res = myDicItem->ToSI( res );
599 \brief Get the datum value as integer.
601 The value is converted according to the measure units in the active units system
602 to measure units in "SI" units system.
604 \return datum value converted to integer
606 int QDS_Datum::integerValue() const
611 if ( !myTargetValue.isNull() && myTargetValue == getString() )
612 res = mySourceValue.toInt();
615 double val = getString().toDouble();
616 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
617 res = (int)myDicItem->ToSI( val );
624 \brief Get the text data from datum.
626 Text consists of label, string value and units.
628 \return datum text data
630 QString QDS_Datum::text() const
634 QString aLabel = label();
635 QString aData = stringValue();
636 QString aUnits = units();
638 QString res = aLabel;
639 if ( !res.isEmpty() && !aData.isEmpty() )
640 res += QString( ": " );
643 if ( !aUnits.isEmpty() )
644 res += QString( " " ) + aUnits;
650 \brief Check if the datum is empty.
651 \return \c false if datum control has value entered
653 bool QDS_Datum::isEmpty() const
655 return stringValue().isEmpty();
659 \brief Reset datum state and set default value as current.
661 void QDS_Datum::reset()
665 mySourceValue = defaultValue();
666 setString( format( ( myFlags & NotFormat ) ? (QString) "" : format(), type(), mySourceValue ) );
670 QString str = getString();
672 emit paramChanged( str );
676 \brief Clear the control.
678 void QDS_Datum::clear()
682 if ( !getString().isEmpty() )
685 setString( mySourceValue );
689 QString str = getString();
691 emit paramChanged( str );
696 \brief Set datum value from QVariant object.
699 void QDS_Datum::setValue( const QVariant& val )
701 if ( val.isValid() && val.canConvert( QVariant::String ) )
702 setStringValue( val.toString() );
708 \brief Set datum value from string data.
711 void QDS_Datum::setStringValue( const QString& txt )
716 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), txt );
718 myTargetValue = aStr;
721 QString str = getString();
723 emit paramChanged( str );
727 \brief Set datum value from double data.
729 The value is converted from measure units in "SI" units system
730 to the measure units in the active units system.
731 Format the value using datum format internal if it is required.
735 void QDS_Datum::setDoubleValue( const double num )
739 mySourceValue = QString().setNum( num, 'g', 16 );
741 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
742 val = myDicItem->FromSI( val );
744 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
746 myTargetValue = aStr;
749 QString str = getString();
751 emit paramChanged( str );
755 \brief Set datum value from integer data.
757 The value is converted from measure units in "SI" units system
758 to the measure units in the active units system.
759 Format the value using datum format if it is required.
763 void QDS_Datum::setIntegerValue( const int num )
767 mySourceValue = QString().setNum( num );
769 if ( !myDicItem.IsNull() && !( flags() & NotConvert ) )
770 val = myDicItem->FromSI( val );
772 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
774 myTargetValue = aStr;
777 QString str = getString();
779 emit paramChanged( str );
783 \brief Get 'enabled' state of the specified subwidget.
784 \param element ORed subwidget flags (QDS::DatumFlags)
785 \return \c true if all subwidgets specified by \a element are enabled
788 bool QDS_Datum::isEnabled( const int element ) const
793 if ( element & Label )
794 res = res && labelWidget() && labelWidget()->isEnabled();
795 if ( element & Units )
796 res = res && unitsWidget() && unitsWidget()->isEnabled();
797 if ( element & Control )
798 res = res && controlWidget() && controlWidget()->isEnabled();
803 \brief Enable/disable subwidgets specified by \a element.
805 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
806 or their ORed combinations.
808 \param on new 'enabled' state
809 \param element ORed subwidget flags (QDS::DatumFlags)
812 void QDS_Datum::setEnabled( const bool on, const int element )
816 if ( element & Label && labelWidget() )
817 labelWidget()->setEnabled( on );
818 if ( element & Units && unitsWidget() )
819 unitsWidget()->setEnabled( on );
820 if ( element & Control && controlWidget() )
821 controlWidget()->setEnabled( on );
825 \brief Enable/disable main control subwidget (QDS::Control).
826 \param on new 'enabled' state
828 void QDS_Datum::setEnabled( bool on )
830 setEnabled( on, Control );
834 \brief Show/hide subwidgets specified by \a flags.
836 Possible values of \a flags: QDS::Label, QDS::Control, QDS::Units
837 or their ORed combinations.
839 \param visible new 'visibility' state
840 \param flags ORed subwidget flags (QDS::DatumFlags)
843 void QDS_Datum::setShown( const bool visible, const int flags )
850 if ( flags & flag && widget( flag ) )
851 widget( flag )->setShown( visible );
857 \brief Show subwidgets specified by \a element.
859 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
860 or their ORed combinations.
862 \param element ORed subwidget flags (QDS::DatumFlags)
863 \sa hide(), setShown()
865 void QDS_Datum::show( const int element )
867 setShown( true, element );
871 \brief Hide subwidgets specified by \a element.
873 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
874 or their ORed combinations.
876 \param element ORed subwidget flags (QDS::DatumFlags)
877 \sa show(), setShown()
879 void QDS_Datum::hide( const int element )
881 setShown( false, element );
885 \brief Get subwidget specified by \a element.
887 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units.
889 \param element subwidget
892 QWidget* QDS_Datum::widget( const int element ) const
895 return wrapper( element );
899 \brief Set the input focus to the control widget.
901 void QDS_Datum::setFocus()
905 if ( controlWidget() )
906 controlWidget()->setFocus();
910 \brief Check if input data is valid.
912 If data is invalid and \a msgBox is \c true, the warning message box is shown.
914 \param msgBox if \c true, show warning message box if input is invalid
915 \param extMsg warning message
916 \param extLabel optional name of the variable (if QDS::Label control is not used)
917 \return \c true if input data is valid
919 bool QDS_Datum::isValid( const bool msgBox, const QString& extMsg, const QString& extLabel ) const
923 if ( type() == DDS_DicItem::String && isDoubleFormat( format() ) )
927 if ( !dicItem().IsNull() )
928 req = toQString( dicItem()->GetRequired() );
931 QString aStr = getString();
933 if ( aStr.isEmpty() )
934 aState = !( req == QString( "yes" ) || req == QString( "true" ) || req.toInt() );
936 aState = validate( aStr );
938 if ( msgBox && !aState )
941 if ( !label().isEmpty() )
942 info += tr( "DATA_INCORRECT_VALUE" ).arg( label() );
943 else if ( !extLabel.isEmpty() )
944 info += tr( "DATA_INCORRECT_VALUE" ).arg( extLabel );
949 case DDS_DicItem::String:
950 typeStr = tr( "DATA_STRING" );
952 case DDS_DicItem::Integer:
953 typeStr = tr( "DATA_INTEGER" );
955 case DDS_DicItem::Float:
956 typeStr = tr( "DATA_FLOAT" );
959 typeStr = tr( "DATA_NON_EMPTY" );
962 info += ( info.isEmpty() ? (QString) "" : QString( "\n" ) ) +
963 tr( "DATA_SHOULD_BE_VALUE" ).arg( typeStr );
965 if ( type() == DDS_DicItem::Float || type() == DDS_DicItem::Integer )
967 QString aMinValue = minValue();
968 QString aMaxValue = maxValue();
969 if ( !aMinValue.isEmpty() && !aMaxValue.isEmpty() )
970 limit = tr( "DATA_RANGE" ).arg( aMinValue ).arg( aMaxValue );
971 else if ( !aMinValue.isEmpty() )
972 limit = tr( "DATA_MIN_LIMIT" ).arg( aMinValue );
973 else if ( !aMaxValue.isEmpty() )
974 limit = tr( "DATA_MAX_LIMIT" ).arg( aMaxValue );
976 if ( !limit.isEmpty() )
979 info += QString( ".\n" ) + tr( "DATA_INPUT_VALUE" );
981 if ( !extMsg.isEmpty() )
982 info += QString( "\n" ) + extMsg;
985 for ( int i = 0; i < info.length(); i++ )
986 if ( info.at( i ) == '\n' )
987 msg += QString( "<br>" );
991 info = QString( "<p><nobr>%1</nobr></p>" ).arg( msg );
993 QMessageBox::critical( controlWidget() ? controlWidget()->topLevelWidget() : 0,
994 tr( "DATA_ERR_TITLE" ), info, tr( "OK" ) );
995 if ( controlWidget() )
996 controlWidget()->setFocus();
1002 \brief Add widgets to the vertical box layout.
1005 void QDS_Datum::addTo( QVBoxLayout* l )
1012 if ( wrapper( Label ) )
1013 l->addWidget( wrapper( Label ) );
1014 if ( wrapper( Control ) )
1015 l->addWidget( wrapper( Control ) );
1016 if ( wrapper( Units ) )
1017 l->addWidget( wrapper( Units ) );
1021 \brief Add widgets to the horizontal box layout.
1024 void QDS_Datum::addTo( QHBoxLayout* l )
1031 if ( wrapper( Label ) )
1032 l->addWidget( wrapper( Label ) );
1033 if ( wrapper( Control ) )
1034 l->addWidget( wrapper( Control ) );
1035 if ( wrapper( Units ) )
1036 l->addWidget( unitsWidget() );
1040 \brief Add widgets to the grid layout.
1041 \param theLay layout
1042 \param theRow layout row index
1043 \param theCol layout column index
1044 \param vertical if \c true subwidgets are layouted vertically, otherwise - horizontally
1046 void QDS_Datum::addTo( QGridLayout* theLay, const int theRow, const int theCol, bool vertical )
1055 if ( wrapper( Label ) )
1057 theLay->addWidget( wrapper( Label ), row, col );
1058 vertical ? row++ : col++;
1060 if ( wrapper( Control ) )
1062 theLay->addWidget( wrapper( Control ), row, col );
1063 vertical ? row++ : col++;
1065 if ( wrapper( Units ) )
1066 theLay->addWidget( wrapper( Units ), row, col );
1070 \brief Set the aligment for QDS::Label and/or QDS::Units subwidgets.
1071 \param align alignment type (Qt::Alignment)
1072 \param type ORed subwidget flags
1074 void QDS_Datum::setAlignment( const int align, const int type )
1078 if ( ( type & Label ) && labelWidget() )
1079 labelWidget()->setAlignment( Qt::Alignment(align) );
1080 if ( ( type & Units ) && unitsWidget() )
1081 unitsWidget()->setAlignment( Qt::Alignment(align) );
1085 \brief Event filter.
1087 Perform delayed initialisation. Reimplemented for internal reasons.
1089 \param o event reciever object
1091 \return \c true if event should be filtered
1093 bool QDS_Datum::eventFilter( QObject* o, QEvent* e )
1095 if ( o == parent() )
1097 if ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
1098 ( e->type() == QEvent::ChildAdded && ((QChildEvent*)e)->child() == this ) )
1101 return QObject::eventFilter( o, e );
1105 \brief Called when datum value is changed.
1107 void QDS_Datum::onParamChanged()
1112 \brief Perform delayed initialization.
1114 void QDS_Datum::onInitDatum()
1120 \brief Called when child subwidget is destroued.
1122 Allows avoiding crash of extra calling of the child subwidget destructor.
1124 \param obj object being destroyed
1126 void QDS_Datum::onDestroyed( QObject* obj )
1128 myWrapper.remove( wrapperType( (Wrapper*)obj ) );
1132 \brief Get QDS::Label widget.
1133 \return label widget
1135 QLabel* QDS_Datum::labelWidget() const
1142 \brief Get QDS::Units widget.
1143 \return units widget
1145 QLabel* QDS_Datum::unitsWidget() const
1152 \brief Get QDS::Control widget.
1153 \return control widget
1155 QWidget* QDS_Datum::controlWidget() const
1162 \brief Get the dictionary item from the datum.
1163 \return handle to data dictionary item
1165 Handle(DDS_DicItem) QDS_Datum::dicItem() const
1171 \brief Set the dictionary item to the datum.
1172 \param item handle to data dictionary item
1174 void QDS_Datum::setDicItem( const Handle(DDS_DicItem)& item )
1180 \brief Create QDS::Label widget.
1181 \param parent parent widget
1182 \return label widget
1184 QLabel* QDS_Datum::createLabel( QWidget* parent )
1186 return new QLabel( parent );
1190 \brief Create QDS::Units widget.
1191 \param parent parent widget
1192 \return units widget
1194 QLabel* QDS_Datum::createUnits( QWidget* parent )
1196 return new QLabel( parent );
1200 \fn QWidget* QDS_Datum::createControl( QWidget* parent );
1201 \brief Create QDS::Control widget.
1203 This method should be implemented in the successor classes.
1205 \param parent parent widget
1206 \return control widget
1210 \fn QString QDS_Datum::getString() const;
1211 \brief Get string value from datum.
1213 This method should be implemented in the successor classes.
1215 \return datum string value
1219 \fn void QDS_Datum::setString( const QString& txt );
1220 \brief Set string value to datum.
1222 This method should be implemented in the successor classes.
1224 \param txt new datum string value
1228 \brief Create validator according to the datum type of value.
1229 \param limits if \c true use minimum and maximum value limits
1232 QValidator* QDS_Datum::validator( const bool limits ) const
1234 QValidator* aValidator = 0;
1236 QString fltr = filter();
1238 if ( type() == DDS_DicItem::String )
1241 QString aFormat = canonicalFormat( format(), aFlags );
1244 int pos = aFormat.indexOf( "." );
1247 QString numStr = aFormat.mid( pos + 1, aFormat.length() - pos - 2 );
1249 int numVal = numStr.toInt( &ok );
1254 QDS_StringValidator* aStrVal = new QDS_StringValidator( fltr, aFlags, (QObject*)this );
1255 aStrVal->setLength( len );
1257 aValidator = aStrVal;
1259 else if ( type() == DDS_DicItem::Integer )
1261 QDS_IntegerValidator* aIntVal = new QDS_IntegerValidator( fltr, (QObject*)this );
1265 limit = minValue().toInt( &ok );
1267 aIntVal->setBottom( limit );
1268 limit = maxValue().toInt( &ok );
1270 aIntVal->setTop( limit );
1272 aValidator = aIntVal;
1274 else if ( type() == DDS_DicItem::Float )
1276 QDS_DoubleValidator* aFloatVal = new QDS_DoubleValidator( fltr, (QObject*)this );
1280 limit = minValue().toDouble( &ok );
1282 aFloatVal->setBottom( limit );
1283 limit = maxValue().toDouble( &ok );
1285 aFloatVal->setTop( limit );
1287 aValidator = aFloatVal;
1294 \brief Validate the specified string.
1295 \param txt string to be validated
1296 \return \c true if string contains valid data
1298 bool QDS_Datum::validate( const QString& txt ) const
1300 if ( type() == DDS_DicItem::Unknown ||
1301 ( type() == DDS_DicItem::String && isDoubleFormat( format() ) ) )
1304 QValidator* aValidator = validator( true );
1311 bool res = aValidator->validate( str, pos ) == QValidator::Acceptable;
1319 \brief Initialize datum.
1321 Retrieve information from data dictionary and create subwidgets
1322 using virtual mechanism.
1324 Virtual mechanism doesn't work in the constructor, therefore this method should
1325 be called outside the constructor.
1327 void QDS_Datum::initialize()
1329 if ( wrapper( Label ) )
1330 wrapper( Label )->setWidget( myLabel = createLabel( wrapper( Label ) ) );
1331 if ( wrapper( Control ) )
1332 wrapper( Control )->setWidget( myControl = createControl( wrapper( Control ) ) );
1333 if ( wrapper( Units ) )
1334 wrapper( Units )->setWidget( myUnits = createUnits( wrapper( Units ) ) );
1336 TCollection_AsciiString comp;
1337 Handle(DDS_DicItem) item = dicItem();
1338 if ( !item.IsNull() )
1339 comp = item->GetComponent();
1342 Handle(DDS_Dictionary) dic = DDS_Dictionary::Get();
1343 if ( !dic.IsNull() )
1344 unitSystem = toQString( comp.IsEmpty() ? dic->GetActiveUnitSystem() :
1345 dic->GetActiveUnitSystem( comp ) );
1347 unitSystemChanged( unitSystem );
1349 QWidget* ctrl = controlWidget();
1352 QString lDescr = longDescription();
1353 QString sDescr = shortDescription();
1354 if ( !sDescr.isEmpty() )
1355 ctrl->setToolTip( sDescr );
1356 if ( !lDescr.isEmpty() )
1357 ctrl->setWhatsThis( lDescr );
1360 if ( labelWidget() && ctrl && !( flags() & NotAccel ) )
1361 labelWidget()->setBuddy( ctrl );
1365 \brief Process notification about active units system changing.
1367 Update label and units widgets.
1369 \param unitSystem new active units system
1371 void QDS_Datum::unitSystemChanged( const QString& unitSystem )
1373 QString labText = label();
1374 QString unitText = unitsToText( units() );
1376 if ( flags() & UnitsWithLabel )
1378 if ( labText.isEmpty() )
1380 else if ( !unitText.isEmpty() )
1381 labText = QString( "%1 (%2)" ).arg( labText ).arg( unitText );
1382 unitText = QString();
1385 if ( labelWidget() )
1386 labelWidget()->setText( labText );
1388 if ( unitsWidget() )
1389 unitsWidget()->setText( unitText );
1395 \brief Convert units into text presentation.
1396 \param uni units to be converted
1397 \return text presentation of units (rich-text)
1399 QString QDS_Datum::unitsToText( const QString& uni )
1402 QString aUnits = uni;
1403 while ( ( pos = aUnits.indexOf( "**" ) ) != -1 )
1405 aUnits = aUnits.mid( 0, pos ) + QString( "<tt><font size=+2><sup>" ) +
1406 aUnits.mid( pos + 2, 1 ) + QString( "</sup></font></tt>" ) +
1407 aUnits.mid( pos + 3 );
1413 \brief Convert text presentation into internal units format.
1414 \param txt text presentation of units (rich-text)
1417 QString QDS_Datum::textToUnits( const QString& txt )
1420 QString aUnits = txt;
1421 while ( ( pos = aUnits.indexOf( "<sup>" ) ) != -1 )
1423 aUnits.remove( pos, 5 );
1424 aUnits.insert( pos, "**" );
1426 while ( ( pos = aUnits.indexOf( "</sup>" ) ) != -1 )
1427 aUnits.remove( pos, 6 );
1432 \brief Format the specified integer as dictionary item value.
1433 \param num integer value being formatted
1434 \param id data dictionary ID
1435 \param convert if \c true, perform conversion from "SI" units system
1436 \return formatted value
1438 QString QDS_Datum::format( const int num, const QString& id, const bool convert )
1440 Handle(DDS_DicItem) anItem;
1445 int aType = DDS_DicItem::Unknown;
1446 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1447 if ( !aDict.IsNull() )
1449 anItem = aDict->GetDicItem( toAsciiString( id ) );
1450 if ( !anItem.IsNull() )
1452 aType = anItem->GetType();
1453 aFormat = toQString( anItem->GetFormat( false ) );
1455 aNum = ( int )anItem->FromSI( aNum );
1459 return format( aFormat, aType, aNum );
1463 \brief Format the specified double as dictionary item value.
1464 \param num double value being formatted
1465 \param id data dictionary ID
1466 \param convert if \c true, perform conversion from "SI" units system
1467 \return formatted value
1469 QString QDS_Datum::format( const double num, const QString& id, const bool convert )
1471 Handle(DDS_DicItem) anItem;
1476 int aType = DDS_DicItem::Unknown;
1477 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1478 if ( !aDict.IsNull() )
1480 anItem = aDict->GetDicItem( toAsciiString( id ) );
1481 if ( !anItem.IsNull() )
1483 aType = anItem->GetType();
1484 aFormat = toQString( anItem->GetFormat( false ) );
1486 aNum = anItem->FromSI( aNum );
1490 return format( aFormat, aType, aNum );
1494 \brief Format the specified string as dictionary item value.
1495 \param str string value being formatted
1496 \param id data dictionary ID
1497 \param convert if \c true, perform conversion from "SI" units system
1498 \return formatted value
1500 QString QDS_Datum::format( const QString& str, const QString& id, const bool convert )
1502 Handle(DDS_DicItem) anItem;
1507 int aType = DDS_DicItem::Unknown;
1508 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1509 if ( !aDict.IsNull() )
1511 anItem = aDict->GetDicItem( toAsciiString( id ) );
1512 if ( !anItem.IsNull() )
1514 aType = anItem->GetType();
1515 aFormat = toQString( anItem->GetFormat( false ) );
1517 aStr = QString::number( anItem->FromSI( aStr.toDouble() ), 'f', 16 );
1521 return format( aFormat, aType, aStr );
1525 \brief Format the given value according to the data dictionary item type.
1526 \param aFormat format string
1527 \param aType data dictionary item type
1528 \param aValue integer value being formatted
1529 \return formatted value
1531 QString QDS_Datum::format( const QString& aFormat, const int aType, const int aValue )
1535 if ( !aFormat.isEmpty() )
1539 case DDS_DicItem::Float:
1540 txt = sprintf( aFormat, (double)aValue );
1541 txt = txt.trimmed();
1543 case DDS_DicItem::Integer:
1544 txt = sprintf( aFormat, aValue );
1545 txt = txt.trimmed();
1547 case DDS_DicItem::String:
1549 txt = sprintf( aFormat, aValue );
1554 txt = QString().setNum( aValue );
1560 \brief Format the given value according to the data dictionary item type.
1561 \param aFormat format string
1562 \param aType data dictionary item type
1563 \param aValue double value being formatted
1564 \return formatted value
1566 QString QDS_Datum::format( const QString& aFormat, const int aType, const double aValue )
1570 if ( !aFormat.isEmpty() )
1574 case DDS_DicItem::Float:
1575 txt = QString().sprintf( aFormat.toLatin1().constData(), aValue );
1576 txt = txt.trimmed();
1578 case DDS_DicItem::Integer:
1579 txt = QString().sprintf( aFormat.toLatin1().constData(), (int)aValue );
1580 txt = txt.trimmed();
1582 case DDS_DicItem::String:
1584 txt = QString().sprintf( aFormat.toLatin1().constData(), aValue );
1589 txt = QString().setNum( aValue, 'g', 16 );
1595 \brief Format the given value according to the data dictionary item type.
1596 \param aFormat format string
1597 \param aType data dictionary item type
1598 \param aValue string value being formatted
1599 \return formatted value
1601 QString QDS_Datum::format( const QString& aFormat, const int aType, const QString& aValue )
1603 QString txt = aValue;
1605 if ( aType != DDS_DicItem::String )
1606 txt = txt.trimmed();
1608 if ( aFormat.isEmpty() || txt.isEmpty() )
1613 case DDS_DicItem::Float:
1614 txt = txt.replace( 'd', 'e' ).replace( 'D', 'E' );
1615 txt = sprintf( aFormat, txt.toDouble() );
1616 txt = txt.trimmed();
1618 case DDS_DicItem::Integer:
1619 txt = sprintf( aFormat, txt.toInt() );
1620 txt = txt.trimmed();
1622 case DDS_DicItem::String:
1623 txt = sprintf( aFormat, txt );
1631 \brief Wrapper around the standard sprintf() function.
1633 Process some non standard flags from format string.
1635 \param fmt string format
1637 \return formatted value
1639 QString QDS_Datum::sprintf( const QString& fmt, const int val )
1641 return QString().sprintf( canonicalFormat( fmt ).toLatin1().constData(), val );
1645 \brief Wrapper around the standard sprintf() function.
1648 Process some non standard flags from format string.
1650 \param fmt string format
1652 \return formatted value
1654 QString QDS_Datum::sprintf( const QString& fmt, const double val )
1656 return QString().sprintf( canonicalFormat( fmt ).toLatin1().constData(), val );
1660 \brief Wrapper around the standard sprintf() function.
1663 Process some non standard flags from format string.
1665 \param fmt string format
1667 \return formatted value
1669 QString QDS_Datum::sprintf( const QString& fmt, const QString& val )
1672 QString aFormat = canonicalFormat( fmt, aFlags );
1676 QRegExp rx( "^(%[0-9]*.?[0-9]*s)$" );
1677 if ( aFormat.indexOf( rx ) != -1 )
1679 // QString().sprintf() always expects string in UTF8 encoding, so we cannot use it here
1680 char* buf = new char[txt.length() + 1];
1681 ::sprintf( buf, aFormat.toLatin1().constData(), (const char*)(txt.toLocal8Bit()) );
1682 txt = QString::fromLocal8Bit( buf );
1687 if ( isDoubleFormat( aFormat ) )
1690 double aVal = txt.toDouble( &isOk );
1693 txt = sprintf( aFormat, aVal );
1694 txt = txt.replace( 'e', 'D' );
1698 if ( aFlags.contains( "u", Qt::CaseInsensitive ) )
1699 txt = txt.toUpper();
1700 if ( aFlags.contains( "l", Qt::CaseInsensitive ) )
1701 txt = txt.toLower();
1707 \brief Get the canonical sprintf() format.
1708 \param fmt string format
1709 \return canonical sprintf() format
1711 QString QDS_Datum::canonicalFormat( const QString& fmt )
1714 return canonicalFormat( fmt, flags );
1718 \brief Get the canonical sprintf() format and non standard flags.
1719 \param fmt string format
1720 \param flags format flags
1721 \return canonical sprintf() format
1723 QString QDS_Datum::canonicalFormat( const QString& fmt, QString& flags )
1725 QString newFmt = fmt;
1728 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]$" );
1729 if ( rx.indexIn( newFmt ) >= 0 )
1731 flags = rx.cap( 2 );
1732 newFmt.remove( rx.pos( 2 ), flags.length() );
1738 \brief Get displayable units string for specified data dictionary item.
1739 \param id data dictionary item ID
1740 \return units string
1742 QString QDS_Datum::units( const QString& id )
1745 Handle(DDS_DicItem) anItem;
1747 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1748 if ( !aDict.IsNull() )
1750 anItem = aDict->GetDicItem( toAsciiString( id ) );
1751 if ( !anItem.IsNull() )
1752 anUnit = unitsToText( toQString( anItem->GetUnits() ) );
1758 \brief Get prefix string from format.
1759 \return current implementation returns null string
1761 QString QDS_Datum::prefix() const
1767 \brief Get suffix string from format.
1768 \return current implementation returns null string
1770 QString QDS_Datum::suffix() const
1776 \brief Get minimum value.
1777 \return minimum value
1779 QString QDS_Datum::minValue() const
1781 QString pref = prefix();
1782 QString suff = suffix();
1784 QString aMin = minimumValue().trimmed();
1786 if ( !pref.isEmpty() && aMin.left( pref.length() ) == pref )
1787 aMin = aMin.mid( pref.length() );
1789 if ( !suff.isEmpty() && aMin.right( suff.length() ) == suff )
1790 aMin = aMin.mid( 0, aMin.length() - suff.length() );
1796 \brief Get maximum value.
1797 \return maximum value
1799 QString QDS_Datum::maxValue() const
1801 QString pref = prefix();
1802 QString suff = suffix();
1804 QString aMax = maximumValue().trimmed();
1806 if ( !pref.isEmpty() && aMax.left( pref.length() ) == pref )
1807 aMax = aMax.mid( pref.length() );
1809 if ( !suff.isEmpty() && aMax.right( suff.length() ) == suff )
1810 aMax = aMax.mid( 0, aMax.length() - suff.length() );
1816 \brief Reset the numeric value cache.
1818 void QDS_Datum::invalidateCache()
1820 myTargetValue = QString();
1824 \brief Remove the acceleartor tags '&' from specified label string \a src.
1825 \param src processed string
1826 \return string after removing '&' symbols
1828 QString QDS_Datum::removeAccel( const QString& src )
1832 for ( uint i = 0; i < trg.length(); )
1834 if ( trg.mid( i, 2 ) == QString( "&&" ) )
1836 else if ( trg.at( i ) == '&' )
1845 \brief Check if given format specified doube value.
1846 \param theFormat format string
1847 \return \c true if \a theFormat has specificator for double values
1849 bool QDS_Datum::isDoubleFormat( const QString& theFormat )
1851 if ( theFormat.length() > 0 )
1853 QChar c = theFormat[ (int)( theFormat.length() - 1 ) ];
1854 return c == 'f' || c == 'g' || c == 'e' || c == 'G' || c == 'E';
1861 \brief Get datum flags.
1862 \return datum flags (QDS::DatumFlags)
1864 int QDS_Datum::flags() const
1870 \brief Perform initialization if it needed.
1873 void QDS_Datum::initDatum() const
1875 if ( myInitialised )
1878 QDS_Datum* that = (QDS_Datum*)this;
1879 that->myInitialised = true;
1883 parent()->removeEventFilter( (QObject*)this );
1887 \brief Get wrapper for specified subwidget.
1889 \param wid subwidget
1892 QDS_Datum::Wrapper* QDS_Datum::wrapper( QWidget* wid ) const
1898 for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && !wrap; ++it )
1900 if ( it.value() && it.value()->widget() == wid )
1907 \brief Get wrapper for specified subwidget.
1909 \param id subwidget ID
1912 QDS_Datum::Wrapper* QDS_Datum::wrapper( const int id ) const
1915 if ( myWrapper.contains( id ) )
1916 wrap = myWrapper[id];
1921 \brief Get subwidget type for specified wrapper.
1924 \return subwidget ID
1926 int QDS_Datum::wrapperType( QDS_Datum::Wrapper* wrap ) const
1929 for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && id == -1; ++it )
1931 if ( it.value() == wrap )
1938 \fn void QDS_Datum::paramChanged();
1939 \brief The signal is emitted when the datum value is changed.
1943 void QDS_Datum::paramChanged( QString& txt );
1944 \brief The signal is emitted when the datum value is changed.
1945 \param txt new datum value