Back to index

salome-gui  6.5.0
SalomeApp_DoubleSpinBox.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 // File:      SalomeApp_DoubleSpinBox.cxx
00021 // Author:    Oleg UVAROV
00022 //
00023 #include <PyConsole_Interp.h> // this include must be first (see PyInterp_base.h)!
00024 #include <PyConsole_Console.h>
00025 
00026 #include "SalomeApp_DoubleSpinBox.h"
00027 #include "SalomeApp_Application.h"
00028 #include "SalomeApp_Study.h"
00029 
00030 #include <SUIT_Session.h>
00031 
00032 #include "SALOMEDSClient_ClientFactory.hxx" 
00033 #include CORBA_SERVER_HEADER(SALOMEDS)
00034 
00035 #include <QKeyEvent>
00036 #include <QLineEdit>
00037 #include <QToolTip>
00038 #include <QRegExp>
00039 
00040 #include <string>
00041 
00055 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( QWidget* parent )
00056 : QtxDoubleSpinBox( parent ),
00057   myDefaultValue( 0.0 ),
00058   myIsRangeSet( false ),
00059   myMinimum( 0.0 ),
00060   myMaximum( 99.99 ),
00061   myAcceptNames( true ),
00062   myShowTip( true )
00063 {
00064   connectSignalsAndSlots();
00065 }
00066 
00079 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, double max, double step, QWidget* parent )
00080 : QtxDoubleSpinBox( min, max, step, parent ),
00081   myDefaultValue( 0.0 ),
00082   myIsRangeSet( false ),
00083   myMinimum( min ),
00084   myMaximum( max ),
00085   myAcceptNames( true ),
00086   myShowTip( true )
00087 {
00088   connectSignalsAndSlots();
00089 }
00090 
00105 SalomeApp_DoubleSpinBox::SalomeApp_DoubleSpinBox( double min, 
00106                                                   double max, 
00107                                                   double step, 
00108                                                   int prec, 
00109                                                   int dec, 
00110                                                   QWidget* parent,
00111                                                   bool acceptNames,
00112                                                   bool showTip )
00113 : QtxDoubleSpinBox( min, max, step, prec, dec, parent ),
00114   myDefaultValue( 0.0 ),
00115   myIsRangeSet( false ),
00116   myMinimum( min ),
00117   myMaximum( max ),
00118   myAcceptNames( acceptNames ),
00119   myShowTip( showTip )
00120 {
00121   connectSignalsAndSlots();
00122 }
00123 
00127 SalomeApp_DoubleSpinBox::~SalomeApp_DoubleSpinBox()
00128 {
00129 }
00130 
00140 void SalomeApp_DoubleSpinBox::stepBy( int steps )
00141 {
00142   QString str  = text();
00143   QString pref = prefix();
00144   QString suff = suffix();
00145   
00146   if ( pref.length() && str.startsWith( pref ) )
00147     str = str.right( str.length() - pref.length() );
00148   if ( suff.length() && str.endsWith( suff ) )
00149     str = str.left( str.length() - suff.length() );
00150   
00151   QRegExp varNameMask( "([a-z]|[A-Z]|_).*" );
00152   if ( varNameMask.exactMatch( str ) )
00153     return;
00154 
00155   QtxDoubleSpinBox::stepBy( steps );
00156 }
00157 
00161 void SalomeApp_DoubleSpinBox::connectSignalsAndSlots()
00162 {
00163   connect( this, SIGNAL( editingFinished() ),
00164            this, SLOT( onEditingFinished() ) );
00165 
00166   connect( this, SIGNAL( valueChanged( const QString& ) ),
00167            this, SLOT( onTextChanged( const QString& ) ) );
00168 
00169   connect( lineEdit(), SIGNAL( textChanged( const QString& ) ),
00170            this, SLOT( onTextChanged( const QString& ) ) );
00171 
00172   connect( lineEdit(), SIGNAL( textChanged( const QString& )),
00173            this, SIGNAL( textChanged( const QString& ) ) );
00174 }
00175 
00179 void SalomeApp_DoubleSpinBox::onEditingFinished()
00180 {
00181   if( myTextValue.isNull() )
00182     myTextValue = text();
00183 
00184   setText( myTextValue );
00185 }
00186 
00190 void SalomeApp_DoubleSpinBox::onTextChanged( const QString& text )
00191 {
00192   myTextValue = text;
00193 
00194   double value = 0;
00195   if( isValid( text, value ) == Acceptable )
00196     myCorrectValue = text;
00197 }
00198 
00205 double SalomeApp_DoubleSpinBox::valueFromText( const QString& text ) const
00206 {
00207   double value = 0;
00208   if( isValid( text, value ) == Acceptable )
00209     return value;
00210 
00211   return defaultValue();
00212 }
00213 
00222 QString SalomeApp_DoubleSpinBox::textFromValue( double val ) const
00223 {
00224   return QtxDoubleSpinBox::textFromValue( val );
00225 }
00226 
00233 QValidator::State SalomeApp_DoubleSpinBox::validate( QString& str, int& pos ) const
00234 {
00235   QValidator::State res = QValidator::Invalid;
00236 
00237   // Considering the input text as a variable name
00238   // Applying Python identifier syntax:
00239   // either a string starting with a letter, or a string starting with
00240   // an underscore followed by at least one alphanumeric character
00241   if ( isAcceptNames() ){
00242     QRegExp varNameMask( "(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)" );
00243     if ( varNameMask.exactMatch( str ) )
00244       res = QValidator::Acceptable;
00245   
00246     if ( res == QValidator::Invalid ){
00247       varNameMask.setPattern( "_" );
00248       if ( varNameMask.exactMatch( str ) )  
00249         res = QValidator::Intermediate;
00250     }
00251   }
00252   
00253   // Trying to interpret the current input text as a numeric value
00254   if ( res == QValidator::Invalid )
00255     res = QtxDoubleSpinBox::validate( str, pos );  
00256   
00257   // Show tooltip in case of invalid manual input
00258   if ( isShowTipOnValidate() && lineEdit()->hasFocus() ){
00259     if ( res != QValidator::Acceptable ){ // san: do we need to warn the user in Intermediate state???
00260       SalomeApp_DoubleSpinBox* that = const_cast<SalomeApp_DoubleSpinBox*>( this );
00261       QPoint pos( size().width(), 0. );
00262       QPoint globalPos = mapToGlobal( pos );
00263       QString minVal = textFromValue( minimum() );
00264       QString maxVal = textFromValue( maximum() );
00265       
00266       // Same stuff as in QtxDoubleSpinBox::textFromValue()
00267       int digits = getPrecision();
00268       
00269       // For 'g' format, max. number of digits after the decimal point is getPrecision() - 1
00270       // See also QtxDoubleSpinBox::validate()
00271       if ( digits < 0 )
00272         digits = qAbs( digits ) - 1;
00273       
00274       QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) );
00275       QString msg( templ.arg( minVal ).arg( maxVal ).arg( digits ) );
00276       
00277       // Add extra hints to the message (if any passed through dynamic properties)
00278       QVariant propVal = property( "validity_tune_hint" );
00279       if ( propVal.isValid() ){
00280         QString extraInfo = propVal.toString();
00281         if ( !extraInfo.isEmpty() ){
00282           msg += "\n";
00283           msg += extraInfo;
00284         }
00285       }
00286       
00287       QToolTip::showText( globalPos, 
00288                           msg, 
00289                           that );
00290     }
00291     else
00292       QToolTip::hideText();
00293   }
00294       
00295   return res;
00296 }
00297 
00302 bool SalomeApp_DoubleSpinBox::isValid( QString& msg, bool toCorrect )
00303 {
00304   double value;
00305   State aState = isValid( text(), value );
00306 
00307   if( aState != Acceptable )
00308   {
00309     if( toCorrect )
00310     {
00311       if( aState == Incompatible )
00312         msg += tr( "ERR_INCOMPATIBLE_TYPE" ).arg( text() ) + "\n";
00313       else if( aState == NoVariable )
00314         msg += tr( "ERR_NO_VARIABLE" ).arg( text() ) + "\n";
00315       else if( aState == Invalid )
00316         msg += tr( "ERR_INVALID_VALUE" ) + "\n";
00317 
00318       setText( myCorrectValue );
00319     }
00320     return false;
00321   }
00322 
00323   return true;
00324 }
00325 
00330 void SalomeApp_DoubleSpinBox::setDefaultValue( const double value )
00331 {
00332   myDefaultValue = value;
00333 }
00334 
00340 void SalomeApp_DoubleSpinBox::setRange( const double min, const double max )
00341 {
00342   QtxDoubleSpinBox::setRange( min, max );
00343 
00344   myIsRangeSet = true;
00345   myMinimum = min;
00346   myMaximum = max;
00347 }
00348 
00353 void SalomeApp_DoubleSpinBox::setValue( const double value )
00354 {
00355   QtxDoubleSpinBox::setValue( value );
00356 
00357   myCorrectValue = QtxDoubleSpinBox::textFromValue( value );
00358   myTextValue = myCorrectValue;
00359 }
00360 
00365 void SalomeApp_DoubleSpinBox::setText( const QString& value )
00366 {
00367   lineEdit()->setText(value);
00368 }
00369 
00374 SalomeApp_DoubleSpinBox::State SalomeApp_DoubleSpinBox::isValid( const QString& text, double& value ) const
00375 {
00376   SearchState aSearchState = findVariable( text, value );
00377   if( aSearchState == NotFound )
00378   {
00379     bool ok = false;
00380     value = locale().toDouble( text, &ok );
00381     if ( !ok )
00382       return NoVariable;
00383   }
00384   else if( aSearchState == IncorrectType )
00385     return Incompatible;
00386 
00387   if( !checkRange( value ) )
00388     return Invalid;
00389 
00390   return Acceptable;
00391 }
00392 
00397 double SalomeApp_DoubleSpinBox::defaultValue() const
00398 {
00399   if( myMinimum > myDefaultValue || myMaximum < myDefaultValue )
00400     return myMinimum;
00401 
00402   return myDefaultValue;
00403 }
00404 
00409 bool SalomeApp_DoubleSpinBox::checkRange( const double value ) const
00410 {
00411   if( !myIsRangeSet )
00412     return true;
00413 
00414   return value >= myMinimum && value <= myMaximum;
00415 }
00416 
00421 SalomeApp_DoubleSpinBox::SearchState SalomeApp_DoubleSpinBox::findVariable( const QString& name, double& value ) const
00422 {
00423   value = 0;
00424   if( SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() ) )
00425   {
00426     if( SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
00427     {
00428       _PTR(Study) studyDS = study->studyDS();
00429 
00430       std::string aName = name.toStdString();
00431       if( studyDS->IsVariable( aName ) )
00432       {
00433         if( studyDS->IsReal( aName ) || studyDS->IsInteger( aName ) || studyDS->IsString( aName ) )
00434         {
00435           if( studyDS->IsString( aName ) )
00436             {
00437               PyConsole_Console* pyConsole = app->pythonConsole();
00438               PyConsole_Interp* pyInterp = pyConsole->getInterp();
00439               PyLockWrapper aLock = pyInterp->GetLockWrapper();
00440               std::string command;
00441               command  = "import salome_notebook ; ";
00442               command += "salome_notebook.notebook.setAsReal(\"";
00443               command += aName;
00444               command += "\")";
00445               bool aResult;
00446               aResult = pyInterp->run(command.c_str());
00447               if(aResult)
00448                 {
00449                   return IncorrectType;
00450                 }
00451             }
00452           value = studyDS->GetReal( aName );
00453           return Found;
00454         }
00455         return IncorrectType;
00456       }
00457     }
00458   }
00459   return NotFound;
00460 }
00461 
00465 void SalomeApp_DoubleSpinBox::keyPressEvent( QKeyEvent* e )
00466 {
00467   if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
00468     QWidget::keyPressEvent( e );
00469   else
00470     QtxDoubleSpinBox::keyPressEvent( e );
00471 }
00472 
00476 void SalomeApp_DoubleSpinBox::showEvent( QShowEvent* )
00477 {
00478   setText( myTextValue );
00479 }
00480 
00486 void SalomeApp_DoubleSpinBox::setAcceptNames( const bool flag )
00487 {
00488   myAcceptNames = flag;
00489 }
00490 
00494 bool SalomeApp_DoubleSpinBox::isAcceptNames() const
00495 {
00496   return myAcceptNames;
00497 }
00498 
00504 void SalomeApp_DoubleSpinBox::setShowTipOnValidate( const bool flag )
00505 {
00506   myShowTip = myShowTip;
00507 }
00508 
00512 bool SalomeApp_DoubleSpinBox::isShowTipOnValidate() const
00513 {
00514   return myShowTip;
00515 }