Back to index

salome-gui  6.5.0
SalomeApp_IntSpinBox.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_IntSpinBox.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_IntSpinBox.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 
00054 SalomeApp_IntSpinBox::SalomeApp_IntSpinBox( QWidget* parent )
00055 : QtxIntSpinBox( parent ),
00056   myDefaultValue( 0 ),
00057   myAcceptNames( true ),
00058   myShowTip( true )
00059 {
00060   connectSignalsAndSlots();
00061 }
00062 
00076 SalomeApp_IntSpinBox::SalomeApp_IntSpinBox( int min, 
00077                                             int max, 
00078                                             int step, 
00079                                             QWidget* parent,
00080                                             bool acceptNames,
00081                                             bool showTip )
00082 : QtxIntSpinBox( min, max, step, parent ),
00083   myDefaultValue( 0 ),
00084   myAcceptNames( acceptNames ),
00085   myShowTip( showTip )
00086 {
00087   connectSignalsAndSlots();
00088 }
00089 
00093 SalomeApp_IntSpinBox::~SalomeApp_IntSpinBox()
00094 {
00095 }
00096 
00097 
00107 void SalomeApp_IntSpinBox::stepBy( int steps )
00108 {
00109   QString str  = text();
00110   QString pref = prefix();
00111   QString suff = suffix();
00112   
00113   if ( pref.length() && str.startsWith( pref ) )
00114     str = str.right( str.length() - pref.length() );
00115   if ( suff.length() && str.endsWith( suff ) )
00116     str = str.left( str.length() - suff.length() );
00117   
00118   QRegExp varNameMask( "([a-z]|[A-Z]|_).*" );
00119   if ( varNameMask.exactMatch( str ) )
00120     return;
00121 
00122   QtxIntSpinBox::stepBy( steps );
00123 }
00124 
00128 void SalomeApp_IntSpinBox::connectSignalsAndSlots()
00129 {
00130   connect( this, SIGNAL( editingFinished() ),
00131            this, SLOT( onEditingFinished() ) );
00132 
00133   connect( this, SIGNAL( valueChanged( const QString& ) ),
00134            this, SLOT( onTextChanged( const QString& ) ) );
00135 
00136   connect( lineEdit(), SIGNAL( textChanged( const QString& ) ),
00137            this, SLOT( onTextChanged( const QString& ) ) );
00138 
00139   connect( lineEdit(), SIGNAL( textChanged( const QString& )),
00140            this, SIGNAL( textChanged( const QString& ) ) );
00141 }
00142 
00146 void SalomeApp_IntSpinBox::onEditingFinished()
00147 {
00148   if( myTextValue.isNull() )
00149     myTextValue = text();
00150 
00151   setText( myTextValue );
00152 }
00153 
00157 void SalomeApp_IntSpinBox::onTextChanged( const QString& text )
00158 {
00159   myTextValue = text;
00160 
00161   int value = 0;
00162   if( isValid( text, value ) == Acceptable )
00163     myCorrectValue = text;
00164 }
00165 
00172 int SalomeApp_IntSpinBox::valueFromText( const QString& text ) const
00173 {
00174   int value = 0;
00175   if( isValid( text, value ) == Acceptable )
00176     return value;
00177 
00178   return defaultValue();
00179 }
00180 
00189 QString SalomeApp_IntSpinBox::textFromValue( int val ) const
00190 {
00191   return QtxIntSpinBox::textFromValue( val );
00192 }
00193 
00200 QValidator::State SalomeApp_IntSpinBox::validate( QString& str, int& pos ) const
00201 {
00202   //return QValidator::Acceptable;
00203   QValidator::State res = QValidator::Invalid;
00204 
00205   // Considering the input text as a variable name
00206   // Applying Python identifier syntax:
00207   // either a string starting with a letter, or a string starting with
00208   // an underscore followed by at least one alphanumeric character
00209   if ( isAcceptNames() ){
00210     QRegExp varNameMask( "(([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*)|(_([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|_)*)" );
00211     if ( varNameMask.exactMatch( str ) )
00212       res = QValidator::Acceptable;
00213   
00214     if ( res == QValidator::Invalid ){
00215       varNameMask.setPattern( "_" );
00216       if ( varNameMask.exactMatch( str ) )  
00217         res = QValidator::Intermediate;
00218     }
00219   }
00220   
00221   // Trying to interpret the current input text as a numeric value
00222   if ( res == QValidator::Invalid )
00223     res = QtxIntSpinBox::validate( str, pos );  
00224   
00225   // Show tooltip in case of invalid manual input
00226   if ( isShowTipOnValidate() && lineEdit()->hasFocus() ){
00227     if ( res != QValidator::Acceptable ){ // san: do we need to warn the user in Intermediate state???
00228       SalomeApp_IntSpinBox* that = const_cast<SalomeApp_IntSpinBox*>( this );
00229       QPoint pos( size().width(), 0. );
00230       QPoint globalPos = mapToGlobal( pos );
00231       QString minVal = textFromValue( minimum() );
00232       QString maxVal = textFromValue( maximum() );
00233       
00234       QString templ( isAcceptNames() ? tr( "VALID_RANGE_VAR_MSG" ) : tr( "VALID_RANGE_NOVAR_MSG" ) );      
00235       QString msg( templ.arg( minVal ).arg( maxVal ) );
00236       
00237       // Add extra hints to the message (if any passed through dynamic properties)
00238       QVariant propVal = property( "validity_tune_hint" );
00239       if ( propVal.isValid() ){
00240         QString extraInfo = propVal.toString();
00241         if ( !extraInfo.isEmpty() ){
00242           msg += "\n";
00243           msg += extraInfo;
00244         }
00245       }
00246   
00247       QToolTip::showText( globalPos, 
00248                           msg, 
00249                           that );
00250     }
00251     else
00252       QToolTip::hideText();
00253   }
00254       
00255   return res;
00256 }
00257 
00262 bool SalomeApp_IntSpinBox::isValid( QString& msg, bool toCorrect )
00263 {
00264   int value;
00265   State aState = isValid( text(), value );
00266 
00267   if( aState != Acceptable )
00268   {
00269     if( toCorrect )
00270     {
00271       if( aState == Incompatible )
00272         msg += tr( "ERR_INCOMPATIBLE_TYPE" ).arg( text() ) + "\n";
00273       else if( aState == NoVariable )
00274         msg += tr( "ERR_NO_VARIABLE" ).arg( text() ) + "\n";
00275       else if( aState == Invalid )
00276         msg += tr( "ERR_INVALID_VALUE" ) + "\n";
00277 
00278       setText( myCorrectValue );
00279     }
00280     return false;
00281   }
00282 
00283   return true;
00284 }
00285 
00290 void SalomeApp_IntSpinBox::setDefaultValue( const int value )
00291 {
00292   myDefaultValue = value;
00293 }
00294 
00299 void SalomeApp_IntSpinBox::setValue( const int value )
00300 {
00301   QtxIntSpinBox::setValue( value );
00302 
00303   myCorrectValue = QString::number( value );
00304   myTextValue = myCorrectValue;
00305 }
00306 
00311 void SalomeApp_IntSpinBox::setText( const QString& value )
00312 {
00313   lineEdit()->setText(value);
00314 }
00315 
00320 SalomeApp_IntSpinBox::State SalomeApp_IntSpinBox::isValid( const QString& text, int& value ) const
00321 {
00322   SearchState aSearchState = findVariable( text, value );
00323   if( aSearchState == NotFound )
00324   {
00325     bool ok = false;
00326     value = text.toInt( &ok );
00327     if( !ok )
00328     {
00329       text.toDouble( &ok );
00330       if( ok )
00331         return Invalid;
00332       return NoVariable;
00333     }
00334   }
00335   else if( aSearchState == IncorrectType )
00336     return Incompatible;
00337 
00338   if( !checkRange( value ) )
00339     return Invalid;
00340 
00341   return Acceptable;
00342 }
00343 
00348 int SalomeApp_IntSpinBox::defaultValue() const
00349 {
00350   if( minimum() > myDefaultValue || maximum() < myDefaultValue )
00351     return minimum();
00352 
00353   return myDefaultValue;
00354 }
00355 
00360 bool SalomeApp_IntSpinBox::checkRange( const int value ) const
00361 {
00362   return value >= minimum() && value <= maximum();
00363 }
00364 
00369 SalomeApp_IntSpinBox::SearchState SalomeApp_IntSpinBox::findVariable( const QString& name, int& value ) const
00370 {
00371   value = 0;
00372   if( SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() ) )
00373   {
00374     if( SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
00375     {
00376       _PTR(Study) studyDS = study->studyDS();
00377 
00378       std::string aName = name.toStdString();
00379       if( studyDS->IsVariable( aName ) )
00380       {
00381         if( studyDS->IsInteger( aName ) || studyDS->IsString( aName ) )
00382         {
00383           if( studyDS->IsString( aName ) )
00384             {
00385               PyConsole_Console* pyConsole = app->pythonConsole();
00386               PyConsole_Interp* pyInterp = pyConsole->getInterp();
00387               PyLockWrapper aLock = pyInterp->GetLockWrapper();
00388               std::string command;
00389               command  = "import salome_notebook ; ";
00390               command += "salome_notebook.notebook.setAsInteger(\"";
00391               command += aName;
00392               command += "\")";
00393               bool aResult;
00394               aResult = pyInterp->run(command.c_str());
00395               if(aResult)
00396                 {
00397                   return IncorrectType;
00398                 }
00399             }
00400           value = studyDS->GetInteger( aName );
00401           return Found;
00402         }
00403         return IncorrectType;
00404       }
00405     }
00406   }
00407   return NotFound;
00408 }
00409 
00413 void SalomeApp_IntSpinBox::keyPressEvent( QKeyEvent* e )
00414 {
00415   if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
00416     QWidget::keyPressEvent( e );
00417   else
00418     QtxIntSpinBox::keyPressEvent( e );
00419 }
00420 
00424 void SalomeApp_IntSpinBox::showEvent( QShowEvent* )
00425 {
00426   setText( myTextValue );
00427 }
00428 
00434 void SalomeApp_IntSpinBox::setAcceptNames( const bool flag )
00435 {
00436   myAcceptNames = flag;
00437 }
00438 
00442 bool SalomeApp_IntSpinBox::isAcceptNames() const
00443 {
00444   return myAcceptNames;
00445 }
00446 
00452 void SalomeApp_IntSpinBox::setShowTipOnValidate( const bool flag )
00453 {
00454   myShowTip = myShowTip;
00455 }
00456 
00460 bool SalomeApp_IntSpinBox::isShowTipOnValidate() const
00461 {
00462   return myShowTip;
00463 }