1 // Copyright (C) 2007-2008 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
22 #include "QDS_Datum.h"
28 #include <QMessageBox>
29 #include <QApplication>
31 #include "QDS_Validator.h"
32 #include <DDS_Dictionary.h>
35 \class QDS_Datum::Wrapper
37 \brief Wrapper for sub widgets.
40 class QDS_Datum::Wrapper : public QWidget
43 Wrapper( QWidget* = 0 );
46 QWidget* widget() const;
47 void setWidget( QWidget* );
49 virtual void setGeometry( int x, int y, int w, int h );
50 virtual void setSizePolicy( QSizePolicy );
58 \param parent parent widget
60 QDS_Datum::Wrapper::Wrapper( QWidget* parent )
64 setLayout( new QHBoxLayout() );
65 layout()->setSpacing( 0 );
66 layout()->setMargin( 0 );
67 setFocusPolicy( Qt::StrongFocus );
73 QDS_Datum::Wrapper::~Wrapper()
81 QWidget* QDS_Datum::Wrapper::widget() const
90 void QDS_Datum::Wrapper::setWidget( QWidget* wid )
92 if ( myWid == wid || !wid )
95 wid->setParent( this );
96 QHBoxLayout* hl = qobject_cast<QHBoxLayout*>( layout() );
98 hl->removeWidget( myWid );
102 setTabOrder( this, myWid );
103 setFocusProxy( myWid );
105 myWid->updateGeometry();
110 \brief Set size policy of the widget.
111 \param sp new size policy
113 void QDS_Datum::Wrapper::setSizePolicy( QSizePolicy sp )
115 QWidget::setSizePolicy( sp );
118 widget()->setSizePolicy( sp );
122 \brief Set widget geometry.
123 \param x horizontal position
124 \param y vertical position
125 \param w widget width
126 \param h widget height
128 void QDS_Datum::Wrapper::setGeometry( int x, int y, int w, int h )
130 QWidget::setGeometry( x, y, w, h );
132 if ( widget() && widget()->size() != size() )
133 widget()->setGeometry( 0, 0, width(), height() );
138 \brief Base class for all controls using the data dictionary.
140 Datum is successor of QObject (not QWidget). This object can have up to three
141 sub widgets named as QDS::Label, QDS::Control and QDS::Units.
142 User can prevent creation of any of them by setting corresponding subwidgets IDs
143 in the parameter \a flags of the constructor.
144 QDS::Label widget displays label of datum, QDS::Control widget allows
145 entering the value and QDS::Units widget displays measure units in the active
148 These widgets are constructed under the parent widget of the datum.
149 The sub widgets are layouted in the parent widget in the following order: first widget
150 is QDS::Label, it is followed by QDS::Control, and in the end is QDS::Units.
151 User can add these widgets to layout manually using method addTo().
152 Method widget() can be used to retrieve desired widget and place it into layout.
154 When QGroupBox is used as parent widget for datum object, all subwidgets are
155 arranged automatically by the group box according to the column and orientation
156 properties of the QGroupBox.
160 QGroupBox* box = new QGroupBox( 3, Qt::Horizontal, "datum box" );
161 QDS_Datum* d1 = new QDS_Datum( "datum_1", box, All );
162 QDS_Datum* d2 = new QDS_Datum( "datum_2", box, All );
163 QDS_Datum* d3 = new QDS_Datum( "datum_3", box, All );
166 In this example we create the QGroupBox with 3 horizontal columns.
167 All the created datum widgets will be placed automatically in 3 rows.
168 Datums will be placed from top to bottom one by one and aligned in he grid.
170 Datum value is stored as string. User can get/set this value:
171 - As string : stringValue()/setStringValue().
172 - As integer : integerValue()/setIntegerValue(). Value is converted to/from SI.
173 - As double : doubleValue()/setDoubleValue(). Value is converted to/from SI.
174 - As variant : value()/setValue().
176 User can enable/disable datum subwidgets with setEnabled() method, show/hide them
177 with show()/hide() methods, set input focus to datum with setFocus(), set widgets
178 alignment with setAlignment(), etc.
184 Create datum object with datum identifier \a id and parent widget \a parent.
186 Parameter \a flags defines behaviour of datum and set of created
187 subwidgets. Default value of this parameter is QDS::All.
189 Parameter \a comp specifies the component name which will be used
190 when searching the dictionary item.
192 Datum is self-registered in the global list by QDS::insertDatum().
194 \param id datum identifier
195 \param parent parent widget
196 \param flags datum flags
197 \param comp component
199 QDS_Datum::QDS_Datum( const QString& id, QWidget* parent, const int flags, const QString& comp )
206 myInitialised( false ),
209 if ( myFlags & Label )
210 myWrapper.insert( Label, new Wrapper( parent ) );
211 if ( myFlags & Control )
212 myWrapper.insert( Control, new Wrapper( parent ) );
213 if ( myFlags & Units )
214 myWrapper.insert( Units, new Wrapper( parent ) );
216 for ( QMap<int, Wrapper*>::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it )
217 connect( it.value(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
219 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
220 if ( aDict.IsNull() )
223 TCollection_AsciiString anId = toAsciiString( id );
224 TCollection_AsciiString aComp = toAsciiString( comp );
226 if ( aComp.IsEmpty() )
227 setDicItem( aDict->GetDicItem( anId ) );
229 setDicItem( aDict->GetDicItem( anId, aComp ) );
231 QTimer::singleShot( 0, this, SLOT( onInitDatum() ) );
234 parent->installEventFilter( this );
242 Destroy all subwidget. Datum is unregistered from the global list
243 by QDS::removeDatum().
245 QDS_Datum::~QDS_Datum()
253 for ( QMap<int, Wrapper*>::Iterator it = myWrapper.begin(); it != myWrapper.end(); ++it )
259 \brief Overloaded operator used to retrieve main subwidget named QDS::Control.
260 \return QDS::Control subwidget
262 QDS_Datum::operator QWidget*() const
264 return widget( Control );
268 \brief Get the datum ID.
271 QString QDS_Datum::id() const
279 \brief Get the datum value type.
280 \return datum value type
282 int QDS_Datum::type() const
286 int res = DDS_DicItem::Unknown;
287 if ( !myDicItem.IsNull() )
288 res = myDicItem->GetType();
293 \brief Return state of custom translation.
294 \return true if custom translation is enabled
296 bool QDS_Datum::isCustomTr() const
302 \brief Change state of custom translation.
304 Custom translation means that text labels of datums are translated
305 with help of standard Qt mechanism of internationalization. In this
306 case special records should be placed into *.ts files under context "QDS".
307 For example, if label has name "myLabel", the corresponding translation
312 <source>myLabel</source>
313 <translation>myLabel translation</translation>
317 If custom translation mechanism is deactivated, then labels will be shown
318 with text got from xml data dictionary file
320 By default, the custom translation is deactivated
322 \param on - if it is true, custom translation is activated, otherwise, deactivated
324 void QDS_Datum::enableCustomTr( const bool on )
327 labelWidget()->setText( label() );
331 \brief Get the datum label text.
334 QString QDS_Datum::label() const
339 if ( !myDicItem.IsNull() )
341 labStr = toQString( myDicItem->GetLabel() );
342 if( labStr.isNull() )
343 labStr = toQString( myDicItem->GetId() );
347 QString dest = QApplication::translate( "QDS", labStr.toLatin1().constData() );
351 if ( flags() & NotAccel )
352 labStr = removeAccel( labStr );
357 \brief Get the datum units text.
360 QString QDS_Datum::units() const
365 if ( !myDicItem.IsNull() )
366 unitStr = toQString( myDicItem->GetUnits() );
371 \brief Get the datum filter string.
372 \return filter string
374 QString QDS_Datum::filter() const
379 if ( !myDicItem.IsNull() )
380 fltr = toQString( myDicItem->GetFilter() );
385 \brief Get the datum format string
386 \return format string
388 QString QDS_Datum::format() const
393 if ( !myDicItem.IsNull() )
394 fmtStr = toQString( myDicItem->GetFormat( false ) );
399 \brief Get the datum default value
400 \return default value
402 QString QDS_Datum::defaultValue() const
406 QString pref = prefix();
407 QString suff = suffix();
410 if ( !myDicItem.IsNull() )
411 def = toQString( myDicItem->GetDefaultValue() );
413 QString aDef = def.trimmed();
414 if ( !pref.isEmpty() && aDef.left( pref.length() ) == pref )
415 aDef = aDef.mid( pref.length() );
417 if ( !suff.isEmpty() && aDef.right( suff.length() ) == suff )
418 aDef = aDef.mid( 0, aDef.length() - suff.length() );
424 \brief Get the datum minimum value.
425 \return minimum value
427 QString QDS_Datum::minimumValue() const
432 if ( !myDicItem.IsNull() && myDicItem->HasData( DDS_DicItem::MinValue ) )
433 min = format( format(), type(), myDicItem->GetMinValue() );
438 \brief Get the datum maximum value.
439 \return maximum value
441 QString QDS_Datum::maximumValue() const
446 if ( !myDicItem.IsNull() && myDicItem->HasData( DDS_DicItem::MaxValue ) )
447 max = format( format(), type(), myDicItem->GetMaxValue() );
452 \brief Get the datum long description.
453 \return datum long description
455 QString QDS_Datum::longDescription() const
460 if ( !myDicItem.IsNull() )
461 ldStr = toQString( myDicItem->GetLongDescription() );
466 \brief Get the datum short description.
467 \return datum short description
469 QString QDS_Datum::shortDescription() const
474 if ( !myDicItem.IsNull() )
475 sdStr = toQString( myDicItem->GetLongDescription() );
480 \brief Get the datum options names.
481 \return datum options
483 QStringList QDS_Datum::options() const
486 if ( !dicItem().IsNull() )
488 TColStd_SequenceOfAsciiString lst;
489 dicItem()->GetOptionNames( lst );
490 for ( int i = 1; i <= lst.Length(); i++ )
491 res.append( toQString( lst.Value( i ) ) );
497 \brief Get datum option specified by \a name as QVariant.
498 \return the option value or invalid QVariant if the option does not exist
500 QVariant QDS_Datum::option( const QString& name ) const
503 if ( !dicItem().IsNull() )
504 res = QVariant( toQString( dicItem()->GetOption( toAsciiString( name ) ) ) );
509 \brief Get datum option specified by \a name as string.
510 \return the option value or null QString if the option does not exist
512 QString QDS_Datum::optionString( const QString& name ) const
515 if ( !dicItem().IsNull() )
516 res = toQString( dicItem()->GetOption( toAsciiString( name ) ) );
521 \brief Get datum option specified by \a name as double.
522 \return the option value or 0 if the option does not exist
524 double QDS_Datum::optionDouble( const QString& name ) const
527 QVariant opt = option( name );
528 if ( opt.isValid() && opt.canConvert( QVariant::Double ) )
529 res = opt.toDouble();
534 \brief Get datum option specified by \a name as integer.
535 \return the option value or 0 if the option does not exist
537 int QDS_Datum::optionInteger( const QString& name ) const
540 QVariant opt = option( name );
541 if ( opt.isValid() && opt.canConvert( QVariant::Int ) )
547 \brief Get the datum value as QVariant.
550 QVariant QDS_Datum::value() const
559 \brief Get the datum value as string.
560 \return datum value converted to string
562 QString QDS_Datum::stringValue() const
566 if ( getString() == myTargetValue )
567 return mySourceValue;
573 \brief Get the datum value as double.
575 The value is converted according to the measure units in the active units system
576 to measure units in "SI" units system.
578 \return datum value converted to double
580 double QDS_Datum::doubleValue() const
585 if ( !myTargetValue.isNull() && myTargetValue == getString() )
586 res = mySourceValue.toDouble();
589 res = getString().toDouble();
590 if ( !myDicItem.IsNull() )
591 res = myDicItem->ToSI( res );
598 \brief Get the datum value as integer.
600 The value is converted according to the measure units in the active units system
601 to measure units in "SI" units system.
603 \return datum value converted to integer
605 int QDS_Datum::integerValue() const
610 if ( !myTargetValue.isNull() && myTargetValue == getString() )
611 res = mySourceValue.toInt();
614 double val = getString().toDouble();
615 if ( !myDicItem.IsNull() )
616 res = (int)myDicItem->ToSI( val );
623 \brief Get the text data from datum.
625 Text consists of label, string value and units.
627 \return datum text data
629 QString QDS_Datum::text() const
633 QString aLabel = label();
634 QString aData = stringValue();
635 QString aUnits = units();
637 QString res = aLabel;
638 if ( !res.isEmpty() && !aData.isEmpty() )
639 res += QString( ": " );
642 if ( !aUnits.isEmpty() )
643 res += QString( " " ) + aUnits;
649 \brief Check if the datum is empty.
650 \return \c false if datum control has value entered
652 bool QDS_Datum::isEmpty() const
654 return stringValue().isEmpty();
658 \brief Reset datum state and set default value as current.
660 void QDS_Datum::reset()
664 mySourceValue = defaultValue();
665 setString( format( ( myFlags & NotFormat ) ? (QString) "" : format(), type(), mySourceValue ) );
669 QString str = getString();
671 emit paramChanged( str );
675 \brief Clear the control.
677 void QDS_Datum::clear()
681 if ( !getString().isEmpty() )
684 setString( mySourceValue );
688 QString str = getString();
690 emit paramChanged( str );
695 \brief Set datum value from QVariant object.
698 void QDS_Datum::setValue( const QVariant& val )
700 if ( val.isValid() && val.canConvert( QVariant::String ) )
701 setStringValue( val.toString() );
707 \brief Set datum value from string data.
710 void QDS_Datum::setStringValue( const QString& txt )
715 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), txt );
717 myTargetValue = aStr;
720 QString str = getString();
722 emit paramChanged( str );
726 \brief Set datum value from double data.
728 The value is converted from measure units in "SI" units system
729 to the measure units in the active units system.
730 Format the value using datum format internal if it is required.
734 void QDS_Datum::setDoubleValue( const double num )
738 mySourceValue = QString().setNum( num, 'g', 16 );
740 if ( !myDicItem.IsNull() )
741 val = myDicItem->FromSI( val );
743 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
745 myTargetValue = aStr;
748 QString str = getString();
750 emit paramChanged( str );
754 \brief Set datum value from integer data.
756 The value is converted from measure units in "SI" units system
757 to the measure units in the active units system.
758 Format the value using datum format if it is required.
762 void QDS_Datum::setIntegerValue( const int num )
766 mySourceValue = QString().setNum( num );
768 if ( !myDicItem.IsNull() )
769 val = myDicItem->FromSI( val );
771 QString aStr = format( ( flags() & NotFormat ) ? (QString) "" : format(), type(), val );
773 myTargetValue = aStr;
776 QString str = getString();
778 emit paramChanged( str );
782 \brief Get 'enabled' state of the specified subwidget.
783 \param element ORed subwidget flags (QDS::DatumFlags)
784 \return \c true if all subwidgets specified by \a element are enabled
787 bool QDS_Datum::isEnabled( const int element ) const
792 if ( element & Label )
793 res = res && labelWidget() && labelWidget()->isEnabled();
794 if ( element & Units )
795 res = res && unitsWidget() && unitsWidget()->isEnabled();
796 if ( element & Control )
797 res = res && controlWidget() && controlWidget()->isEnabled();
802 \brief Enable/disable subwidgets specified by \a element.
804 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
805 or their ORed combinations.
807 \param on new 'enabled' state
808 \param element ORed subwidget flags (QDS::DatumFlags)
811 void QDS_Datum::setEnabled( const bool on, const int element )
815 if ( element & Label && labelWidget() )
816 labelWidget()->setEnabled( on );
817 if ( element & Units && unitsWidget() )
818 unitsWidget()->setEnabled( on );
819 if ( element & Control && controlWidget() )
820 controlWidget()->setEnabled( on );
824 \brief Enable/disable main control subwidget (QDS::Control).
825 \param on new 'enabled' state
827 void QDS_Datum::setEnabled( bool on )
829 setEnabled( on, Control );
833 \brief Show/hide subwidgets specified by \a flags.
835 Possible values of \a flags: QDS::Label, QDS::Control, QDS::Units
836 or their ORed combinations.
838 \param visible new 'visibility' state
839 \param flags ORed subwidget flags (QDS::DatumFlags)
842 void QDS_Datum::setShown( const bool visible, const int flags )
849 if ( flags & flag && widget( flag ) )
850 widget( flag )->setShown( visible );
856 \brief Show subwidgets specified by \a element.
858 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
859 or their ORed combinations.
861 \param element ORed subwidget flags (QDS::DatumFlags)
862 \sa hide(), setShown()
864 void QDS_Datum::show( const int element )
866 setShown( true, element );
870 \brief Hide subwidgets specified by \a element.
872 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units
873 or their ORed combinations.
875 \param element ORed subwidget flags (QDS::DatumFlags)
876 \sa show(), setShown()
878 void QDS_Datum::hide( const int element )
880 setShown( false, element );
884 \brief Get subwidget specified by \a element.
886 Possible values of \a element: QDS::Label, QDS::Control, QDS::Units.
888 \param element subwidget
891 QWidget* QDS_Datum::widget( const int element ) const
894 return wrapper( element );
898 \brief Set the input focus to the control widget.
900 void QDS_Datum::setFocus()
904 if ( controlWidget() )
905 controlWidget()->setFocus();
909 \brief Check if input data is valid.
911 If data is invalid and \a msgBox is \c true, the warning message box is shown.
913 \param msgBox if \c true, show warning message box if input is invalid
914 \param extMsg warning message
915 \param extLabel optional name of the variable (if QDS::Label control is not used)
916 \return \c true if input data is valid
918 bool QDS_Datum::isValid( const bool msgBox, const QString& extMsg, const QString& extLabel ) const
922 if ( type() == DDS_DicItem::String && isDoubleFormat( format() ) )
926 if ( !dicItem().IsNull() )
927 req = toQString( dicItem()->GetRequired() );
930 QString aStr = getString();
932 if ( aStr.isEmpty() )
933 aState = !( req == QString( "yes" ) || req == QString( "true" ) || req.toInt() );
935 aState = validate( aStr );
937 if ( msgBox && !aState )
940 if ( !label().isEmpty() )
941 info += tr( "DATA_INCORRECT_VALUE" ).arg( label() );
942 else if ( !extLabel.isEmpty() )
943 info += tr( "DATA_INCORRECT_VALUE" ).arg( extLabel );
948 case DDS_DicItem::String:
949 typeStr = tr( "DATA_STRING" );
951 case DDS_DicItem::Integer:
952 typeStr = tr( "DATA_INTEGER" );
954 case DDS_DicItem::Float:
955 typeStr = tr( "DATA_FLOAT" );
958 typeStr = tr( "DATA_NON_EMPTY" );
961 info += ( info.isEmpty() ? (QString) "" : QString( "\n" ) ) +
962 tr( "DATA_SHOULD_BE_VALUE" ).arg( typeStr );
964 if ( type() == DDS_DicItem::Float || type() == DDS_DicItem::Integer )
966 QString aMinValue = minValue();
967 QString aMaxValue = maxValue();
968 if ( !aMinValue.isEmpty() && !aMaxValue.isEmpty() )
969 limit = tr( "DATA_RANGE" ).arg( aMinValue ).arg( aMaxValue );
970 else if ( !aMinValue.isEmpty() )
971 limit = tr( "DATA_MIN_LIMIT" ).arg( aMinValue );
972 else if ( !aMaxValue.isEmpty() )
973 limit = tr( "DATA_MAX_LIMIT" ).arg( aMaxValue );
975 if ( !limit.isEmpty() )
978 info += QString( ".\n" ) + tr( "DATA_INPUT_VALUE" );
980 if ( !extMsg.isEmpty() )
981 info += QString( "\n" ) + extMsg;
984 for ( int i = 0; i < info.length(); i++ )
985 if ( info.at( i ) == '\n' )
986 msg += QString( "<br>" );
990 info = QString( "<p><nobr>%1</nobr></p>" ).arg( msg );
992 QMessageBox::critical( controlWidget() ? controlWidget()->topLevelWidget() : 0,
993 tr( "DATA_ERR_TITLE" ), info, tr( "OK" ) );
994 if ( controlWidget() )
995 controlWidget()->setFocus();
1001 \brief Add widgets to the vertical box layout.
1004 void QDS_Datum::addTo( QVBoxLayout* l )
1011 if ( wrapper( Label ) )
1012 l->addWidget( wrapper( Label ) );
1013 if ( wrapper( Control ) )
1014 l->addWidget( wrapper( Control ) );
1015 if ( wrapper( Units ) )
1016 l->addWidget( wrapper( Units ) );
1020 \brief Add widgets to the horizontal box layout.
1023 void QDS_Datum::addTo( QHBoxLayout* l )
1030 if ( wrapper( Label ) )
1031 l->addWidget( wrapper( Label ) );
1032 if ( wrapper( Control ) )
1033 l->addWidget( wrapper( Control ) );
1034 if ( wrapper( Units ) )
1035 l->addWidget( unitsWidget() );
1039 \brief Add widgets to the grid layout.
1040 \param theLay layout
1041 \param theRow layout row index
1042 \param theCol layout column index
1043 \param vertical if \c true subwidgets are layouted vertically, otherwise - horizontally
1045 void QDS_Datum::addTo( QGridLayout* theLay, const int theRow, const int theCol, bool vertical )
1054 if ( wrapper( Label ) )
1056 theLay->addWidget( wrapper( Label ), row, col );
1057 vertical ? row++ : col++;
1059 if ( wrapper( Control ) )
1061 theLay->addWidget( wrapper( Control ), row, col );
1062 vertical ? row++ : col++;
1064 if ( wrapper( Units ) )
1065 theLay->addWidget( wrapper( Units ), row, col );
1069 \brief Set the aligment for QDS::Label and/or QDS::Units subwidgets.
1070 \param align alignment type (Qt::Alignment)
1071 \param type ORed subwidget flags
1073 void QDS_Datum::setAlignment( const int align, const int type )
1077 if ( ( type & Label ) && labelWidget() )
1078 labelWidget()->setAlignment( Qt::Alignment(align) );
1079 if ( ( type & Units ) && unitsWidget() )
1080 unitsWidget()->setAlignment( Qt::Alignment(align) );
1084 \brief Event filter.
1086 Perform delayed initialisation. Reimplemented for internal reasons.
1088 \param o event reciever object
1090 \return \c true if event should be filtered
1092 bool QDS_Datum::eventFilter( QObject* o, QEvent* e )
1094 if ( o == parent() )
1096 if ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
1097 ( e->type() == QEvent::ChildAdded && ((QChildEvent*)e)->child() == this ) )
1100 return QObject::eventFilter( o, e );
1104 \brief Called when datum value is changed.
1106 void QDS_Datum::onParamChanged()
1111 \brief Perform delayed initialization.
1113 void QDS_Datum::onInitDatum()
1119 \brief Called when child subwidget is destroued.
1121 Allows avoiding crash of extra calling of the child subwidget destructor.
1123 \param obj object being destroyed
1125 void QDS_Datum::onDestroyed( QObject* obj )
1127 myWrapper.remove( wrapperType( (Wrapper*)obj ) );
1131 \brief Get QDS::Label widget.
1132 \return label widget
1134 QLabel* QDS_Datum::labelWidget() const
1141 \brief Get QDS::Units widget.
1142 \return units widget
1144 QLabel* QDS_Datum::unitsWidget() const
1151 \brief Get QDS::Control widget.
1152 \return control widget
1154 QWidget* QDS_Datum::controlWidget() const
1161 \brief Get the dictionary item from the datum.
1162 \return handle to data dictionary item
1164 Handle(DDS_DicItem) QDS_Datum::dicItem() const
1170 \brief Set the dictionary item to the datum.
1171 \param item handle to data dictionary item
1173 void QDS_Datum::setDicItem( const Handle(DDS_DicItem)& item )
1179 \brief Create QDS::Label widget.
1180 \param parent parent widget
1181 \return label widget
1183 QLabel* QDS_Datum::createLabel( QWidget* parent )
1185 return new QLabel( parent );
1189 \brief Create QDS::Units widget.
1190 \param parent parent widget
1191 \return units widget
1193 QLabel* QDS_Datum::createUnits( QWidget* parent )
1195 return new QLabel( parent );
1199 \fn QWidget* QDS_Datum::createControl( QWidget* parent );
1200 \brief Create QDS::Control widget.
1202 This method should be implemented in the successor classes.
1204 \param parent parent widget
1205 \return control widget
1209 \fn QString QDS_Datum::getString() const;
1210 \brief Get string value from datum.
1212 This method should be implemented in the successor classes.
1214 \return datum string value
1218 \fn void QDS_Datum::setString( const QString& txt );
1219 \brief Set string value to datum.
1221 This method should be implemented in the successor classes.
1223 \param txt new datum string value
1227 \brief Create validator according to the datum type of value.
1228 \param limits if \c true use minimum and maximum value limits
1231 QValidator* QDS_Datum::validator( const bool limits ) const
1233 QValidator* aValidator = 0;
1235 QString fltr = filter();
1237 if ( type() == DDS_DicItem::String )
1240 QString aFormat = canonicalFormat( format(), aFlags );
1243 int pos = aFormat.indexOf( "." );
1246 QString numStr = aFormat.mid( pos + 1, aFormat.length() - pos - 2 );
1248 int numVal = numStr.toInt( &ok );
1253 QDS_StringValidator* aStrVal = new QDS_StringValidator( fltr, aFlags, (QObject*)this );
1254 aStrVal->setLength( len );
1256 aValidator = aStrVal;
1258 else if ( type() == DDS_DicItem::Integer )
1260 QDS_IntegerValidator* aIntVal = new QDS_IntegerValidator( fltr, (QObject*)this );
1264 limit = minValue().toInt( &ok );
1266 aIntVal->setBottom( limit );
1267 limit = maxValue().toInt( &ok );
1269 aIntVal->setTop( limit );
1271 aValidator = aIntVal;
1273 else if ( type() == DDS_DicItem::Float )
1275 QDS_DoubleValidator* aFloatVal = new QDS_DoubleValidator( fltr, (QObject*)this );
1279 limit = minValue().toDouble( &ok );
1281 aFloatVal->setBottom( limit );
1282 limit = maxValue().toDouble( &ok );
1284 aFloatVal->setTop( limit );
1286 aValidator = aFloatVal;
1293 \brief Validate the specified string.
1294 \param txt string to be validated
1295 \return \c true if string contains valid data
1297 bool QDS_Datum::validate( const QString& txt ) const
1299 if ( type() == DDS_DicItem::Unknown ||
1300 type() == DDS_DicItem::String && isDoubleFormat( format() ) )
1303 QValidator* aValidator = validator( true );
1310 bool res = aValidator->validate( str, pos ) == QValidator::Acceptable;
1318 \brief Initialize datum.
1320 Retrieve information from data dictionary and create subwidgets
1321 using virtual mechanism.
1323 Virtual mechanism doesn't work in the constructor, therefore this method should
1324 be called outside the constructor.
1326 void QDS_Datum::initialize()
1328 if ( wrapper( Label ) )
1329 wrapper( Label )->setWidget( myLabel = createLabel( wrapper( Label ) ) );
1330 if ( wrapper( Control ) )
1331 wrapper( Control )->setWidget( myControl = createControl( wrapper( Control ) ) );
1332 if ( wrapper( Units ) )
1333 wrapper( Units )->setWidget( myUnits = createUnits( wrapper( Units ) ) );
1335 TCollection_AsciiString comp;
1336 Handle(DDS_DicItem) item = dicItem();
1337 if ( !item.IsNull() )
1338 comp = item->GetComponent();
1341 Handle(DDS_Dictionary) dic = DDS_Dictionary::Get();
1342 if ( !dic.IsNull() )
1343 unitSystem = toQString( comp.IsEmpty() ? dic->GetActiveUnitSystem() :
1344 dic->GetActiveUnitSystem( comp ) );
1346 unitSystemChanged( unitSystem );
1348 QWidget* ctrl = controlWidget();
1351 QString lDescr = longDescription();
1352 QString sDescr = shortDescription();
1353 if ( !sDescr.isEmpty() )
1354 ctrl->setToolTip( sDescr );
1355 if ( !lDescr.isEmpty() )
1356 ctrl->setWhatsThis( lDescr );
1359 if ( labelWidget() && ctrl && !( flags() & NotAccel ) )
1360 labelWidget()->setBuddy( ctrl );
1364 \brief Process notification about active units system changing.
1366 Update label and units widgets.
1368 \param unitSystem new active units system
1370 void QDS_Datum::unitSystemChanged( const QString& unitSystem )
1372 QString labText = label();
1373 QString unitText = unitsToText( units() );
1375 if ( flags() & UnitsWithLabel )
1377 if ( labText.isEmpty() )
1379 else if ( !unitText.isEmpty() )
1380 labText = QString( "%1 (%2)" ).arg( labText ).arg( unitText );
1381 unitText = QString();
1384 if ( labelWidget() )
1385 labelWidget()->setText( labText );
1387 if ( unitsWidget() )
1388 unitsWidget()->setText( unitText );
1394 \brief Convert units into text presentation.
1395 \param uni units to be converted
1396 \return text presentation of units (rich-text)
1398 QString QDS_Datum::unitsToText( const QString& uni )
1401 QString aUnits = uni;
1402 while ( ( pos = aUnits.indexOf( "**" ) ) != -1 )
1404 aUnits = aUnits.mid( 0, pos ) + QString( "<tt><font size=+2><sup>" ) +
1405 aUnits.mid( pos + 2, 1 ) + QString( "</sup></font></tt>" ) +
1406 aUnits.mid( pos + 3 );
1412 \brief Convert text presentation into internal units format.
1413 \param txt text presentation of units (rich-text)
1416 QString QDS_Datum::textToUnits( const QString& txt )
1419 QString aUnits = txt;
1420 while ( ( pos = aUnits.indexOf( "<sup>" ) ) != -1 )
1422 aUnits.remove( pos, 5 );
1423 aUnits.insert( pos, "**" );
1425 while ( ( pos = aUnits.indexOf( "</sup>" ) ) != -1 )
1426 aUnits.remove( pos, 6 );
1431 \brief Format the specified integer as dictionary item value.
1432 \param num integer value being formatted
1433 \param id data dictionary ID
1434 \param convert if \c true, perform conversion from "SI" units system
1435 \return formatted value
1437 QString QDS_Datum::format( const int num, const QString& id, const bool convert )
1439 Handle(DDS_DicItem) anItem;
1444 int aType = DDS_DicItem::Unknown;
1445 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1446 if ( !aDict.IsNull() )
1448 anItem = aDict->GetDicItem( toAsciiString( id ) );
1449 if ( !anItem.IsNull() )
1451 aType = anItem->GetType();
1452 aFormat = toQString( anItem->GetFormat( false ) );
1454 aNum = ( int )anItem->FromSI( aNum );
1458 return format( aFormat, aType, aNum );
1462 \brief Format the specified double as dictionary item value.
1463 \param num double value being formatted
1464 \param id data dictionary ID
1465 \param convert if \c true, perform conversion from "SI" units system
1466 \return formatted value
1468 QString QDS_Datum::format( const double num, const QString& id, const bool convert )
1470 Handle(DDS_DicItem) anItem;
1475 int aType = DDS_DicItem::Unknown;
1476 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1477 if ( !aDict.IsNull() )
1479 anItem = aDict->GetDicItem( toAsciiString( id ) );
1480 if ( !anItem.IsNull() )
1482 aType = anItem->GetType();
1483 aFormat = toQString( anItem->GetFormat( false ) );
1485 aNum = anItem->FromSI( aNum );
1489 return format( aFormat, aType, aNum );
1493 \brief Format the specified string as dictionary item value.
1494 \param str string value being formatted
1495 \param id data dictionary ID
1496 \param convert if \c true, perform conversion from "SI" units system
1497 \return formatted value
1499 QString QDS_Datum::format( const QString& str, const QString& id, const bool convert )
1501 Handle(DDS_DicItem) anItem;
1506 int aType = DDS_DicItem::Unknown;
1507 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1508 if ( !aDict.IsNull() )
1510 anItem = aDict->GetDicItem( toAsciiString( id ) );
1511 if ( !anItem.IsNull() )
1513 aType = anItem->GetType();
1514 aFormat = toQString( anItem->GetFormat( false ) );
1516 aStr = QString::number( anItem->FromSI( aStr.toDouble() ), 'f', 16 );
1520 return format( aFormat, aType, aStr );
1524 \brief Format the given value according to the data dictionary item type.
1525 \param aFormat format string
1526 \param aType data dictionary item type
1527 \param aValue integer value being formatted
1528 \return formatted value
1530 QString QDS_Datum::format( const QString& aFormat, const int aType, const int aValue )
1534 if ( !aFormat.isEmpty() )
1538 case DDS_DicItem::Float:
1539 txt = sprintf( aFormat, (double)aValue );
1540 txt = txt.trimmed();
1542 case DDS_DicItem::Integer:
1543 txt = sprintf( aFormat, aValue );
1544 txt = txt.trimmed();
1546 case DDS_DicItem::String:
1548 txt = sprintf( aFormat, aValue );
1553 txt = QString().setNum( aValue );
1559 \brief Format the given value according to the data dictionary item type.
1560 \param aFormat format string
1561 \param aType data dictionary item type
1562 \param aValue double value being formatted
1563 \return formatted value
1565 QString QDS_Datum::format( const QString& aFormat, const int aType, const double aValue )
1569 if ( !aFormat.isEmpty() )
1573 case DDS_DicItem::Float:
1574 txt = QString().sprintf( aFormat.toLatin1().constData(), aValue );
1575 txt = txt.trimmed();
1577 case DDS_DicItem::Integer:
1578 txt = QString().sprintf( aFormat.toLatin1().constData(), (int)aValue );
1579 txt = txt.trimmed();
1581 case DDS_DicItem::String:
1583 txt = QString().sprintf( aFormat.toLatin1().constData(), aValue );
1588 txt = QString().setNum( aValue, 'g', 16 );
1594 \brief Format the given value according to the data dictionary item type.
1595 \param aFormat format string
1596 \param aType data dictionary item type
1597 \param aValue string value being formatted
1598 \return formatted value
1600 QString QDS_Datum::format( const QString& aFormat, const int aType, const QString& aValue )
1602 QString txt = aValue;
1604 if ( aType != DDS_DicItem::String )
1605 txt = txt.trimmed();
1607 if ( aFormat.isEmpty() || txt.isEmpty() )
1612 case DDS_DicItem::Float:
1613 txt = txt.replace( 'd', 'e' ).replace( 'D', 'E' );
1614 txt = sprintf( aFormat, txt.toDouble() );
1615 txt = txt.trimmed();
1617 case DDS_DicItem::Integer:
1618 txt = sprintf( aFormat, txt.toInt() );
1619 txt = txt.trimmed();
1621 case DDS_DicItem::String:
1622 txt = sprintf( aFormat, txt );
1630 \brief Wrapper around the standard sprintf() function.
1632 Process some non standard flags from format string.
1634 \param fmt string format
1636 \return formatted value
1638 QString QDS_Datum::sprintf( const QString& fmt, const int val )
1640 return QString().sprintf( canonicalFormat( fmt ).toLatin1().constData(), val );
1644 \brief Wrapper around the standard sprintf() function.
1647 Process some non standard flags from format string.
1649 \param fmt string format
1651 \return formatted value
1653 QString QDS_Datum::sprintf( const QString& fmt, const double val )
1655 return QString().sprintf( canonicalFormat( fmt ).toLatin1().constData(), val );
1659 \brief Wrapper around the standard sprintf() function.
1662 Process some non standard flags from format string.
1664 \param fmt string format
1666 \return formatted value
1668 QString QDS_Datum::sprintf( const QString& fmt, const QString& val )
1671 QString aFormat = canonicalFormat( fmt, aFlags );
1675 QRegExp rx( "^(%[0-9]*.?[0-9]*s)$" );
1676 if ( aFormat.indexOf( rx ) != -1 )
1678 // QString().sprintf() always expects string in UTF8 encoding, so we cannot use it here
1679 char* buf = new char[txt.length() + 1];
1680 ::sprintf( buf, aFormat.toLatin1().constData(), (const char*)(txt.toLocal8Bit()) );
1681 txt = QString::fromLocal8Bit( buf );
1686 if ( isDoubleFormat( aFormat ) )
1689 double aVal = txt.toDouble( &isOk );
1692 txt = sprintf( aFormat, aVal );
1693 txt = txt.replace( 'e', 'D' );
1697 if ( aFlags.contains( "u", Qt::CaseInsensitive ) )
1698 txt = txt.toUpper();
1699 if ( aFlags.contains( "l", Qt::CaseInsensitive ) )
1700 txt = txt.toLower();
1706 \brief Get the canonical sprintf() format.
1707 \param fmt string format
1708 \return canonical sprintf() format
1710 QString QDS_Datum::canonicalFormat( const QString& fmt )
1713 return canonicalFormat( fmt, flags );
1717 \brief Get the canonical sprintf() format and non standard flags.
1718 \param fmt string format
1719 \param flags format flags
1720 \return canonical sprintf() format
1722 QString QDS_Datum::canonicalFormat( const QString& fmt, QString& flags )
1724 QString newFmt = fmt;
1727 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]$" );
1728 if ( rx.indexIn( newFmt ) >= 0 )
1730 flags = rx.cap( 2 );
1731 newFmt.remove( rx.pos( 2 ), flags.length() );
1737 \brief Get displayable units string for specified data dictionary item.
1738 \param id data dictionary item ID
1739 \return units string
1741 QString QDS_Datum::units( const QString& id )
1744 Handle(DDS_DicItem) anItem;
1746 Handle(DDS_Dictionary) aDict = DDS_Dictionary::Get();
1747 if ( !aDict.IsNull() )
1749 anItem = aDict->GetDicItem( toAsciiString( id ) );
1750 if ( !anItem.IsNull() )
1751 anUnit = unitsToText( toQString( anItem->GetUnits() ) );
1757 \brief Get prefix string from format.
1758 \return current implementation returns null string
1760 QString QDS_Datum::prefix() const
1766 \brief Get suffix string from format.
1767 \return current implementation returns null string
1769 QString QDS_Datum::suffix() const
1775 \brief Get minimum value.
1776 \return minimum value
1778 QString QDS_Datum::minValue() const
1780 QString pref = prefix();
1781 QString suff = suffix();
1783 QString aMin = minimumValue().trimmed();
1785 if ( !pref.isEmpty() && aMin.left( pref.length() ) == pref )
1786 aMin = aMin.mid( pref.length() );
1788 if ( !suff.isEmpty() && aMin.right( suff.length() ) == suff )
1789 aMin = aMin.mid( 0, aMin.length() - suff.length() );
1795 \brief Get maximum value.
1796 \return maximum value
1798 QString QDS_Datum::maxValue() const
1800 QString pref = prefix();
1801 QString suff = suffix();
1803 QString aMax = maximumValue().trimmed();
1805 if ( !pref.isEmpty() && aMax.left( pref.length() ) == pref )
1806 aMax = aMax.mid( pref.length() );
1808 if ( !suff.isEmpty() && aMax.right( suff.length() ) == suff )
1809 aMax = aMax.mid( 0, aMax.length() - suff.length() );
1815 \brief Reset the numeric value cache.
1817 void QDS_Datum::invalidateCache()
1819 myTargetValue = QString();
1823 \brief Remove the acceleartor tags '&' from specified label string \a src.
1824 \param src processed string
1825 \return string after removing '&' symbols
1827 QString QDS_Datum::removeAccel( const QString& src )
1831 for ( uint i = 0; i < trg.length(); )
1833 if ( trg.mid( i, 2 ) == QString( "&&" ) )
1835 else if ( trg.at( i ) == '&' )
1844 \brief Check if given format specified doube value.
1845 \param theFormat format string
1846 \return \c true if \a theFormat has specificator for double values
1848 bool QDS_Datum::isDoubleFormat( const QString& theFormat )
1850 if ( theFormat.length() > 0 )
1852 QChar c = theFormat[ (int)( theFormat.length() - 1 ) ];
1853 return c == 'f' || c == 'g' || c == 'e' || c == 'G' || c == 'E';
1860 \brief Get datum flags.
1861 \return datum flags (QDS::DatumFlags)
1863 int QDS_Datum::flags() const
1869 \brief Perform initialization if it needed.
1872 void QDS_Datum::initDatum() const
1874 if ( myInitialised )
1877 QDS_Datum* that = (QDS_Datum*)this;
1878 that->myInitialised = true;
1882 parent()->removeEventFilter( (QObject*)this );
1886 \brief Get wrapper for specified subwidget.
1888 \param wid subwidget
1891 QDS_Datum::Wrapper* QDS_Datum::wrapper( QWidget* wid ) const
1897 for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && !wrap; ++it )
1899 if ( it.value() && it.value()->widget() == wid )
1906 \brief Get wrapper for specified subwidget.
1908 \param id subwidget ID
1911 QDS_Datum::Wrapper* QDS_Datum::wrapper( const int id ) const
1914 if ( myWrapper.contains( id ) )
1915 wrap = myWrapper[id];
1920 \brief Get subwidget type for specified wrapper.
1923 \return subwidget ID
1925 int QDS_Datum::wrapperType( QDS_Datum::Wrapper* wrap ) const
1928 for ( QMap<int, Wrapper*>::ConstIterator it = myWrapper.begin(); it != myWrapper.end() && id == -1; ++it )
1930 if ( it.value() == wrap )
1937 \fn void QDS_Datum::paramChanged();
1938 \brief The signal is emitted when the datum value is changed.
1942 void QDS_Datum::paramChanged( QString& txt );
1943 \brief The signal is emitted when the datum value is changed.
1944 \param txt new datum value