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 if ( res != QValidator::Acceptable ){ // san: do we need to warn the user in Intermediate state???
262 SalomeApp_DoubleSpinBox* that = const_cast<SalomeApp_DoubleSpinBox*>( this );
263 QPoint pos( size().width(), 0. );
264 QPoint globalPos = mapToGlobal( pos );
265 QString minVal = textFromValue( minimum() );
266 QString maxVal = textFromValue( maximum() );
268 // Same stuff as in QtxDoubleSpinBox::textFromValue()
269 int digits = getPrecision();
271 // For 'g' format, max. number of digits after the decimal point is getPrecision() - 1
272 // See also QtxDoubleSpinBox::validate()
274 digits = qAbs( digits ) - 1;
276 QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) );
277 QString msg( templ.arg( minVal ).arg( maxVal ).arg( digits ) );
279 // Add extra hints to the message (if any passed through dynamic properties)
280 QVariant propVal = property( "validity_tune_hint" );
281 if ( propVal.isValid() ){
282 QString extraInfo = propVal.toString();
283 if ( !extraInfo.isEmpty() ){
289 QToolTip::showText( globalPos,
294 QToolTip::hideText();
301 \brief This function is used to determine whether input is valid.
302 \return validating operation result
304 bool SalomeApp_DoubleSpinBox::isValid( QString& msg, bool toCorrect )
307 State aState = isValid( text(), value );
309 if( aState != Acceptable )
313 if( aState == Incompatible )
314 msg += tr( "ERR_INCOMPATIBLE_TYPE" ).arg( text() ) + "\n";
315 else if( aState == NoVariable )
316 msg += tr( "ERR_NO_VARIABLE" ).arg( text() ) + "\n";
317 else if( aState == Invalid )
318 msg += tr( "ERR_INVALID_VALUE" ) + "\n";
320 setText( myCorrectValue );
329 \brief This function is used to set a default value for this spinbox.
330 \param value default value
332 void SalomeApp_DoubleSpinBox::setDefaultValue( const double value )
334 myDefaultValue = value;
338 \brief This function is used to set minimum and maximum values for this spinbox.
339 \param min minimum value
340 \param max maximum value
342 void SalomeApp_DoubleSpinBox::setRange( const double min, const double max )
344 QtxDoubleSpinBox::setRange( min, max );
352 \brief This function is used to set a current value for this spinbox.
353 \param value current value
355 void SalomeApp_DoubleSpinBox::setValue( const double value )
357 QtxDoubleSpinBox::setValue( value );
359 myCorrectValue = QtxDoubleSpinBox::textFromValue( value );
360 myTextValue = myCorrectValue;
364 \brief This function is used to set a text for this spinbox.
365 \param value current value
367 void SalomeApp_DoubleSpinBox::setText( const QString& value )
369 lineEdit()->setText(value);
373 \brief This function is used to determine whether input is valid.
374 \return validating operation result
376 SalomeApp_DoubleSpinBox::State SalomeApp_DoubleSpinBox::isValid( const QString& text, double& value ) const
378 SearchState aSearchState = findVariable( text, value );
379 if( aSearchState == NotFound )
382 value = locale().toDouble( text, &ok );
386 else if( aSearchState == IncorrectType )
389 if( !checkRange( value ) )
396 \brief This function return a default acceptable value (commonly, 0.0).
397 \return default acceptable value
399 double SalomeApp_DoubleSpinBox::defaultValue() const
401 if( myMinimum > myDefaultValue || myMaximum < myDefaultValue )
404 return myDefaultValue;
408 \brief This function is used to check that string value lies within predefined range.
411 bool SalomeApp_DoubleSpinBox::checkRange( const double value ) const
416 return value >= myMinimum && value <= myMaximum;
420 \brief This function is used to determine whether input is a variable name and to get its value.
421 \return status of search operation
423 SalomeApp_DoubleSpinBox::SearchState SalomeApp_DoubleSpinBox::findVariable( const QString& name, double& value ) const
426 if( SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() ) )
428 _PTR(Study) studyDS = SalomeApp_Application::getStudy();
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 #ifndef DISABLE_PYCONSOLE
438 PyConsole_Interp* pyInterp = app->getPyInterp();
439 PyLockWrapper aLock; // Acquire GIL
441 command = "import salome_notebook ; ";
442 command += "salome_notebook.notebook.setAsReal(\"";
446 aResult = pyInterp->run(command.c_str());
449 return IncorrectType;
453 value = studyDS->GetReal( aName );
456 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 )
510 \brief Returns true if tooltip should be shown in case of invalid or intermediate-state input.
512 bool SalomeApp_DoubleSpinBox::isShowTipOnValidate() const