1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: SalomeApp_DoubleSpinBox.cxx
21 // Author: Oleg UVAROV
23 #include <PyConsole_Interp.h> // this include must be first (see PyInterp_base.h)!
24 #include <PyConsole_Console.h>
26 #include "SalomeApp_DoubleSpinBox.h"
27 #include "SalomeApp_Application.h"
28 #include "SalomeApp_Study.h"
30 #include <SUIT_Session.h>
32 #include "SALOMEDSClient_ClientFactory.hxx"
33 #include CORBA_SERVER_HEADER(SALOMEDS)
43 \class SalomeApp_DoubleSpinBox
49 Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
50 a step value of 1.0 and a precision of 2 decimal places.
51 The value is initially set to 0.00.
53 \param parent parent object
55 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( QWidget* parent )
56 : QtxDoubleSpinBox( parent ),
57 myDefaultValue( 0.0 ),
58 myIsRangeSet( false ),
61 myAcceptNames( true ),
64 connectSignalsAndSlots();
70 Constructs a spin box with specified minimum, maximum and step value.
71 The precision is set to 2 decimal places.
72 The value is initially set to the minimum value.
74 \param min spin box minimum possible value
75 \param max spin box maximum possible value
76 \param step spin box increment/decrement value
77 \param parent parent object
79 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, double max, double step, QWidget* parent )
80 : QtxDoubleSpinBox( min, max, step, parent ),
81 myDefaultValue( 0.0 ),
82 myIsRangeSet( false ),
85 myAcceptNames( true ),
88 connectSignalsAndSlots();
94 Constructs a spin box with specified minimum, maximum and step value.
95 The precision is set to 2 decimal places.
96 The value is initially set to the minimum value.
98 \param min spin box minimum possible value
99 \param max spin box maximum possible value
100 \param step spin box increment/decrement value
101 \param parent parent object
102 \param acceptNames if true, enables variable names in the spin box
103 \param showTip if true, makes the widget show a tooltip when invalid text is entered by the user
105 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min,
113 : QtxDoubleSpinBox( min, max, step, prec, dec, parent ),
114 myDefaultValue( 0.0 ),
115 myIsRangeSet( false ),
118 myAcceptNames( acceptNames ),
121 connectSignalsAndSlots();
127 SalomeApp_DoubleSpinBox::~SalomeApp_DoubleSpinBox()
132 \brief Perform \a steps increment/decrement steps.
134 Re-implemented to handle cases when Notebook variable
135 name is specified by the user as the widget text.
136 Otherwise, simply calls the base implementation.
138 \param steps number of increment/decrement steps
140 void SalomeApp_DoubleSpinBox::stepBy( int steps )
142 QString str = text();
143 QString pref = prefix();
144 QString suff = suffix();
146 if ( pref.length() && str.startsWith( pref ) )
147 str = str.right( str.length() - pref.length() );
148 if ( suff.length() && str.endsWith( suff ) )
149 str = str.left( str.length() - suff.length() );
151 QRegExp varNameMask( "([a-z]|[A-Z]|_).*" );
152 if ( varNameMask.exactMatch( str ) )
155 QtxDoubleSpinBox::stepBy( steps );
159 \brief Connect signals and slots.
161 void SalomeApp_DoubleSpinBox::connectSignalsAndSlots()
163 connect( this, SIGNAL( editingFinished() ),
164 this, SLOT( onEditingFinished() ) );
166 connect( this, SIGNAL( valueChanged( const QString& ) ),
167 this, SLOT( onTextChanged( const QString& ) ) );
169 connect( lineEdit(), SIGNAL( textChanged( const QString& ) ),
170 this, SLOT( onTextChanged( const QString& ) ) );
172 connect( lineEdit(), SIGNAL( textChanged( const QString& )),
173 this, SIGNAL( textChanged( const QString& ) ) );
177 \brief This function is called when editing is finished.
179 void SalomeApp_DoubleSpinBox::onEditingFinished()
181 if( myTextValue.isNull() )
182 myTextValue = text();
184 setText( myTextValue );
188 \brief This function is called when value is changed.
190 void SalomeApp_DoubleSpinBox::onTextChanged( const QString& text )
195 if( isValid( text, value ) == Acceptable )
196 myCorrectValue = text;
200 \brief Interpret text entered by the user as a value.
201 \param text text entered by the user
205 double SalomeApp_DoubleSpinBox::valueFromText( const QString& text ) const
208 if( isValid( text, value ) == Acceptable )
211 return defaultValue();
215 \brief This function is used by the spin box whenever it needs to display
218 \param val spin box value
219 \return text representation of the value
222 QString SalomeApp_DoubleSpinBox::textFromValue( double val ) const
224 return QtxDoubleSpinBox::textFromValue( val );
228 \brief This function is used to determine whether input is valid.
229 \param str currently entered value
230 \param pos cursor position in the string
231 \return validating operation result
233 QValidator::State SalomeApp_DoubleSpinBox::validate( QString& str, int& pos ) const
235 QValidator::State res = QValidator::Invalid;
237 // Considering the input text as a variable name
238 // Applying Python identifier syntax:
239 // either a string starting with a letter, or a string starting with
240 // an underscore followed by at least one alphanumeric character
241 if ( isAcceptNames() ){
242 QRegExp varNameMask( "(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)" );
243 if ( varNameMask.exactMatch( str ) )
244 res = QValidator::Acceptable;
246 if ( res == QValidator::Invalid ){
247 varNameMask.setPattern( "_" );
248 if ( varNameMask.exactMatch( str ) )
249 res = QValidator::Intermediate;
253 // Trying to interpret the current input text as a numeric value
254 if ( res == QValidator::Invalid )
255 res = QtxDoubleSpinBox::validate( str, pos );
257 // Show tooltip in case of invalid manual input
258 if ( isShowTipOnValidate() && lineEdit()->hasFocus() ){
259 if ( res != QValidator::Acceptable ){ // san: do we need to warn the user in Intermediate state???
260 SalomeApp_DoubleSpinBox* that = const_cast<SalomeApp_DoubleSpinBox*>( this );
261 QPoint pos( size().width(), 0. );
262 QPoint globalPos = mapToGlobal( pos );
263 QString minVal = textFromValue( minimum() );
264 QString maxVal = textFromValue( maximum() );
266 // Same stuff as in QtxDoubleSpinBox::textFromValue()
267 int digits = getPrecision();
269 // For 'g' format, max. number of digits after the decimal point is getPrecision() - 1
270 // See also QtxDoubleSpinBox::validate()
272 digits = qAbs( digits ) - 1;
274 QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) );
275 QString msg( templ.arg( minVal ).arg( maxVal ).arg( digits ) );
277 // Add extra hints to the message (if any passed through dynamic properties)
278 QVariant propVal = property( "validity_tune_hint" );
279 if ( propVal.isValid() ){
280 QString extraInfo = propVal.toString();
281 if ( !extraInfo.isEmpty() ){
287 QToolTip::showText( globalPos,
292 QToolTip::hideText();
299 \brief This function is used to determine whether input is valid.
300 \return validating operation result
302 bool SalomeApp_DoubleSpinBox::isValid( QString& msg, bool toCorrect )
305 State aState = isValid( text(), value );
307 if( aState != Acceptable )
311 if( aState == Incompatible )
312 msg += tr( "ERR_INCOMPATIBLE_TYPE" ).arg( text() ) + "\n";
313 else if( aState == NoVariable )
314 msg += tr( "ERR_NO_VARIABLE" ).arg( text() ) + "\n";
315 else if( aState == Invalid )
316 msg += tr( "ERR_INVALID_VALUE" ) + "\n";
318 setText( myCorrectValue );
327 \brief This function is used to set a default value for this spinbox.
328 \param value default value
330 void SalomeApp_DoubleSpinBox::setDefaultValue( const double value )
332 myDefaultValue = value;
336 \brief This function is used to set minimum and maximum values for this spinbox.
337 \param min minimum value
338 \param max maximum value
340 void SalomeApp_DoubleSpinBox::setRange( const double min, const double max )
342 QtxDoubleSpinBox::setRange( min, max );
350 \brief This function is used to set a current value for this spinbox.
351 \param value current value
353 void SalomeApp_DoubleSpinBox::setValue( const double value )
355 QtxDoubleSpinBox::setValue( value );
357 myCorrectValue = QtxDoubleSpinBox::textFromValue( value );
358 myTextValue = myCorrectValue;
362 \brief This function is used to set a text for this spinbox.
363 \param value current value
365 void SalomeApp_DoubleSpinBox::setText( const QString& value )
367 lineEdit()->setText(value);
371 \brief This function is used to determine whether input is valid.
372 \return validating operation result
374 SalomeApp_DoubleSpinBox::State SalomeApp_DoubleSpinBox::isValid( const QString& text, double& value ) const
376 SearchState aSearchState = findVariable( text, value );
377 if( aSearchState == NotFound )
380 value = locale().toDouble( text, &ok );
384 else if( aSearchState == IncorrectType )
387 if( !checkRange( value ) )
394 \brief This function return a default acceptable value (commonly, 0.0).
395 \return default acceptable value
397 double SalomeApp_DoubleSpinBox::defaultValue() const
399 if( myMinimum > myDefaultValue || myMaximum < myDefaultValue )
402 return myDefaultValue;
406 \brief This function is used to check that string value lies within predefined range.
409 bool SalomeApp_DoubleSpinBox::checkRange( const double value ) const
414 return value >= myMinimum && value <= myMaximum;
418 \brief This function is used to determine whether input is a variable name and to get its value.
419 \return status of search operation
421 SalomeApp_DoubleSpinBox::SearchState SalomeApp_DoubleSpinBox::findVariable( const QString& name, double& value ) const
424 if( SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() ) )
426 if( SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
428 _PTR(Study) studyDS = study->studyDS();
430 std::string aName = name.toStdString();
431 if( studyDS->IsVariable( aName ) )
433 if( studyDS->IsReal( aName ) || studyDS->IsInteger( aName ) || studyDS->IsString( aName ) )
435 if( studyDS->IsString( aName ) )
437 PyConsole_Console* pyConsole = app->pythonConsole();
438 PyConsole_Interp* pyInterp = pyConsole->getInterp();
439 PyLockWrapper aLock = pyInterp->GetLockWrapper();
441 command = "import salome_notebook ; ";
442 command += "salome_notebook.notebook.setAsReal(\"";
446 aResult = pyInterp->run(command.c_str());
449 return IncorrectType;
452 value = studyDS->GetReal( aName );
455 return IncorrectType;
463 \brief This function is called when the spinbox recieves key press event.
465 void SalomeApp_DoubleSpinBox::keyPressEvent( QKeyEvent* e )
467 if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
468 QWidget::keyPressEvent( e );
470 QtxDoubleSpinBox::keyPressEvent( e );
474 \brief This function is called when the spinbox recieves show event.
476 void SalomeApp_DoubleSpinBox::showEvent( QShowEvent* )
478 setText( myTextValue );
482 \brief Enables or disables variable names in the spin box.
483 By default, variable names are enabled.
484 \param flag If true, variable names are enabled.
486 void SalomeApp_DoubleSpinBox::setAcceptNames( const bool flag )
488 myAcceptNames = flag;
492 \brief Returns true if the spin box accepts variable names.
494 bool SalomeApp_DoubleSpinBox::isAcceptNames() const
496 return myAcceptNames;
500 \brief Enables or disables tooltips in case of invalid or intermediate-state input.
501 Tooltips are enabled by default.
502 \param flag If true, tooltips are enabled.
504 void SalomeApp_DoubleSpinBox::setShowTipOnValidate( const bool flag )
506 myShowTip = myShowTip;
510 \brief Returns true if tooltip should be shown in case of invalid or intermediate-state input.
512 bool SalomeApp_DoubleSpinBox::isShowTipOnValidate() const