1 // Copyright (C) 2007-2024 CEA, EDF, 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
24 #ifndef DISABLE_PYCONSOLE
25 #include <PyConsole_Interp.h> // this include must be first (see PyInterp_base.h)!
28 #include "SalomeApp_DoubleSpinBox.h"
29 #include "SalomeApp_Application.h"
30 #include "SalomeApp_Study.h"
32 #include <SUIT_Session.h>
34 #include "SALOMEDSClient_ClientFactory.hxx"
35 #include CORBA_SERVER_HEADER(SALOMEDS)
45 \class SalomeApp_DoubleSpinBox
51 Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
52 a step value of 1.0 and a precision of 2 decimal places.
53 The value is initially set to 0.00.
55 \param parent parent object
57 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( QWidget* parent )
58 : QtxDoubleSpinBox( parent ),
59 myDefaultValue( 0.0 ),
60 myIsRangeSet( false ),
63 myAcceptNames( true ),
66 connectSignalsAndSlots();
72 Constructs a spin box with specified minimum, maximum and step value.
73 The precision is set to 2 decimal places.
74 The value is initially set to the minimum value.
76 \param min spin box minimum possible value
77 \param max spin box maximum possible value
78 \param step spin box increment/decrement value
79 \param parent parent object
81 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, double max, double step, QWidget* parent )
82 : QtxDoubleSpinBox( min, max, step, parent ),
83 myDefaultValue( 0.0 ),
84 myIsRangeSet( false ),
87 myAcceptNames( true ),
90 connectSignalsAndSlots();
96 Constructs a spin box with specified minimum, maximum and step value.
97 The precision is set to 2 decimal places.
98 The value is initially set to the minimum value.
100 \param min spin box minimum possible value
101 \param max spin box maximum possible value
102 \param step spin box increment/decrement value
103 \param parent parent object
104 \param acceptNames if true, enables variable names in the spin box
105 \param showTip if true, makes the widget show a tooltip when invalid text is entered by the user
107 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min,
115 : QtxDoubleSpinBox( min, max, step, prec, dec, parent ),
116 myDefaultValue( 0.0 ),
117 myIsRangeSet( false ),
120 myAcceptNames( acceptNames ),
123 connectSignalsAndSlots();
129 SalomeApp_DoubleSpinBox::~SalomeApp_DoubleSpinBox()
134 \brief Perform \a steps increment/decrement steps.
136 Re-implemented to handle cases when Notebook variable
137 name is specified by the user as the widget text.
138 Otherwise, simply calls the base implementation.
140 \param steps number of increment/decrement steps
142 void SalomeApp_DoubleSpinBox::stepBy( int steps )
144 QString str = text();
145 QString pref = prefix();
146 QString suff = suffix();
148 if ( pref.length() && str.startsWith( pref ) )
149 str = str.right( str.length() - pref.length() );
150 if ( suff.length() && str.endsWith( suff ) )
151 str = str.left( str.length() - suff.length() );
153 QRegExp varNameMask( "([a-z]|[A-Z]|_).*" );
154 if ( varNameMask.exactMatch( str ) )
157 QtxDoubleSpinBox::stepBy( steps );
161 \brief Connect signals and slots.
163 void SalomeApp_DoubleSpinBox::connectSignalsAndSlots()
165 connect( this, SIGNAL( editingFinished() ),
166 this, SLOT( onEditingFinished() ) );
168 connect( this, SIGNAL( valueChanged( const QString& ) ),
169 this, SLOT( onTextChanged( const QString& ) ) );
171 connect( lineEdit(), SIGNAL( textChanged( const QString& ) ),
172 this, SLOT( onTextChanged( const QString& ) ) );
174 connect( lineEdit(), SIGNAL( textChanged( const QString& )),
175 this, SIGNAL( textChanged( const QString& ) ) );
179 \brief This function is called when editing is finished.
181 void SalomeApp_DoubleSpinBox::onEditingFinished()
183 if( myTextValue.isNull() )
184 myTextValue = text();
186 setText( myTextValue );
190 \brief This function is called when value is changed.
192 void SalomeApp_DoubleSpinBox::onTextChanged( const QString& text )
197 if( isValid( text, value ) == Acceptable )
198 myCorrectValue = text;
202 \brief Interpret text entered by the user as a value.
203 \param text text entered by the user
207 double SalomeApp_DoubleSpinBox::valueFromText( const QString& text ) const
210 if( isValid( text, value ) == Acceptable )
213 return defaultValue();
217 \brief This function is used by the spin box whenever it needs to display
220 \param val spin box value
221 \return text representation of the value
224 QString SalomeApp_DoubleSpinBox::textFromValue( double val ) const
226 return QtxDoubleSpinBox::textFromValue( val );
230 \brief This function is used to determine whether input is valid.
231 \param str currently entered value
232 \param pos cursor position in the string
233 \return validating operation result
235 QValidator::State SalomeApp_DoubleSpinBox::validate( QString& str, int& pos ) const
237 QValidator::State res = QValidator::Invalid;
239 // Considering the input text as a variable name
240 // Applying Python identifier syntax:
241 // either a string starting with a letter, or a string starting with
242 // an underscore followed by at least one alphanumeric character
243 if ( isAcceptNames() ){
244 QRegExp varNameMask( "(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)" );
245 if ( varNameMask.exactMatch( str ) )
246 res = QValidator::Acceptable;
248 if ( res == QValidator::Invalid ){
249 varNameMask.setPattern( "_" );
250 if ( varNameMask.exactMatch( str ) )
251 res = QValidator::Intermediate;
255 // Trying to interpret the current input text as a numeric value
256 if ( res == QValidator::Invalid )
257 res = QtxDoubleSpinBox::validate( str, pos );
259 // Show tooltip in case of invalid manual input
260 if ( isShowTipOnValidate() && lineEdit()->hasFocus() ){
261 showValidationToolTip(res);
268 \brief This function is used to determine whether input is valid.
269 \return validating operation result
271 bool SalomeApp_DoubleSpinBox::isValid( QString& msg, bool toCorrect )
274 State aState = isValid( text(), value );
276 if( aState != Acceptable )
280 if( aState == Incompatible )
281 msg += tr( "ERR_INCOMPATIBLE_TYPE" ).arg( text() ) + "\n";
282 else if( aState == NoVariable )
283 msg += tr( "ERR_NO_VARIABLE" ).arg( text() ) + "\n";
284 else if( aState == Invalid )
285 msg += tr( "ERR_INVALID_VALUE" ) + "\n";
287 setText( myCorrectValue );
296 \brief This function is used to set a default value for this spinbox.
297 \param value default value
299 void SalomeApp_DoubleSpinBox::setDefaultValue( const double value )
301 myDefaultValue = value;
305 \brief This function is used to set minimum and maximum values for this spinbox.
306 \param min minimum value
307 \param max maximum value
309 void SalomeApp_DoubleSpinBox::setRange( const double min, const double max )
311 QtxDoubleSpinBox::setRange( min, max );
319 \brief This function is used to set a current value for this spinbox.
320 \param value current value
322 void SalomeApp_DoubleSpinBox::setValue( const double value )
324 QtxDoubleSpinBox::setValue( value );
326 myCorrectValue = QtxDoubleSpinBox::textFromValue( value );
327 myTextValue = myCorrectValue;
331 \brief This function is used to set a text for this spinbox.
332 \param value current value
334 void SalomeApp_DoubleSpinBox::setText( const QString& value )
336 lineEdit()->setText(value);
340 \brief This function is used to determine whether input is valid.
341 \return validating operation result
343 SalomeApp_DoubleSpinBox::State SalomeApp_DoubleSpinBox::isValid( const QString& text, double& value ) const
345 SearchState aSearchState = findVariable( text, value );
346 if( aSearchState == NotFound )
349 value = locale().toDouble( text, &ok );
353 else if( aSearchState == IncorrectType )
356 if( !checkRange( value ) )
363 \brief This function return a default acceptable value (commonly, 0.0).
364 \return default acceptable value
366 double SalomeApp_DoubleSpinBox::defaultValue() const
368 if( myMinimum > myDefaultValue || myMaximum < myDefaultValue )
371 return myDefaultValue;
375 \brief This function is used to check that string value lies within predefined range.
378 bool SalomeApp_DoubleSpinBox::checkRange( const double value ) const
383 return value >= myMinimum && value <= myMaximum;
387 \brief This function is used to determine whether input is a variable name and to get its value.
388 \return status of search operation
390 SalomeApp_DoubleSpinBox::SearchState SalomeApp_DoubleSpinBox::findVariable( const QString& name, double& value ) const
393 if( SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() ) )
395 _PTR(Study) studyDS = SalomeApp_Application::getStudy();
397 std::string aName = name.toStdString();
398 if( studyDS->IsVariable( aName ) )
400 if( studyDS->IsReal( aName ) || studyDS->IsInteger( aName ) || studyDS->IsString( aName ) )
402 if( studyDS->IsString( aName ) )
404 #ifndef DISABLE_PYCONSOLE
405 PyConsole_Interp* pyInterp = app->getPyInterp();
406 PyLockWrapper aLock; // Acquire GIL
408 command = "import salome_notebook ; ";
409 command += "salome_notebook.notebook.setAsReal(\"";
413 aResult = pyInterp->run(command.c_str());
416 return IncorrectType;
420 value = studyDS->GetReal( aName );
423 return IncorrectType;
429 void SalomeApp_DoubleSpinBox::showValidationToolTip(const QValidator::State state) const
431 // san: do we need to warn the user in Intermediate state???
432 if ( state == QValidator::Acceptable )
434 QToolTip::hideText();
438 SalomeApp_DoubleSpinBox* that = const_cast<SalomeApp_DoubleSpinBox*>( this );
439 QPoint pos( size().width(), 0. );
440 QPoint globalPos = mapToGlobal( pos );
441 QString minVal = textFromValue( minimum() );
442 QString maxVal = textFromValue( maximum() );
444 // Same stuff as in QtxDoubleSpinBox::textFromValue()
445 int digits = getPrecision();
447 // For 'g' format, max. number of digits after the decimal point is getPrecision() - 1
448 // See also QtxDoubleSpinBox::validate()
450 digits = qAbs( digits ) - 1;
452 QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) );
453 QString msg( templ.arg( minVal ).arg( maxVal ).arg( digits ) );
455 // Add extra hints to the message (if any passed through dynamic properties)
456 QVariant propVal = property( "validity_tune_hint" );
457 if ( propVal.isValid() ){
458 QString extraInfo = propVal.toString();
459 if ( !extraInfo.isEmpty() ){
465 QToolTip::showText( globalPos,
471 \brief This function is called when the spinbox recieves key press event.
473 void SalomeApp_DoubleSpinBox::keyPressEvent( QKeyEvent* e )
475 if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
476 QWidget::keyPressEvent( e );
478 QtxDoubleSpinBox::keyPressEvent( e );
482 \brief This function is called when the spinbox recieves show event.
484 void SalomeApp_DoubleSpinBox::showEvent( QShowEvent* )
486 setText( myTextValue );
490 \brief Enables or disables variable names in the spin box.
491 By default, variable names are enabled.
492 \param flag If true, variable names are enabled.
494 void SalomeApp_DoubleSpinBox::setAcceptNames( const bool flag )
496 myAcceptNames = flag;
500 \brief Returns true if the spin box accepts variable names.
502 bool SalomeApp_DoubleSpinBox::isAcceptNames() const
504 return myAcceptNames;
508 \brief Enables or disables tooltips in case of invalid or intermediate-state input.
509 Tooltips are enabled by default.
510 \param flag If true, tooltips are enabled.
512 void SalomeApp_DoubleSpinBox::setShowTipOnValidate( const bool flag )
518 \brief Returns true if tooltip should be shown in case of invalid or intermediate-state input.
520 bool SalomeApp_DoubleSpinBox::isShowTipOnValidate() const