libyui-qt  2.43.5
/usr/src/RPM/BUILD/libyui-qt-2.43.5/src/YQInputField.cc
00001 /*
00002   Copyright (C) 2000-2012 Novell, Inc
00003   This library is free software; you can redistribute it and/or modify
00004   it under the terms of the GNU Lesser General Public License as
00005   published by the Free Software Foundation; either version 2.1 of the
00006   License, or (at your option) version 3.0 of the License. This library
00007   is distributed in the hope that it will be useful, but WITHOUT ANY
00008   WARRANTY; without even the implied warranty of MERCHANTABILITY or
00009   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00010   License for more details. You should have received a copy of the GNU
00011   Lesser General Public License along with this library; if not, write
00012   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
00013   Floor, Boston, MA 02110-1301 USA
00014 */
00015 
00016 
00017 /*-/
00018 
00019   File:       YQInputField.cc
00020 
00021   Author:     Stefan Hundhammer <sh@suse.de>
00022 
00023   Textdomain "qt"
00024 
00025 /-*/
00026 
00027 
00028 #include <qlineedit.h>
00029 #define YUILogComponent "qt-ui"
00030 #include <yui/YUILog.h>
00031 
00032 using std::max;
00033 
00034 #include "utf8.h"
00035 #include "YQUI.h"
00036 #include <yui/YEvent.h>
00037 #include "QY2CharValidator.h"
00038 #include "YQInputField.h"
00039 #include "YQi18n.h"
00040 #include "YQSignalBlocker.h"
00041 #include "YQWidgetCaption.h"
00042 #include <QVBoxLayout>
00043 
00044 // Include low-level X headers AFTER Qt headers:
00045 // X.h pollutes the global namespace (!!!) with pretty useless #defines
00046 // like "Above", "Below" etc. that clash with some Qt headers.
00047 #include <X11/X.h>              // CapsLock detection
00048 #include <X11/Xlib.h>           // CapsLock detection
00049 #include <X11/keysym.h>         // CapsLock detection
00050 
00051 using std::string;
00052 
00053 
00054 
00055 YQInputField::YQInputField( YWidget *           parent,
00056                             const std::string & label,
00057                             bool                passwordMode )
00058     : QFrame( (QWidget *) parent->widgetRep() )
00059     , YInputField( parent, label, passwordMode )
00060     , _validator(0)
00061     , _displayingCapsLockWarning( false )
00062 {
00063     QVBoxLayout* layout = new QVBoxLayout( this );
00064     setLayout( layout );
00065 
00066     setWidgetRep( this );
00067 
00068     layout->setSpacing( YQWidgetSpacing );
00069     layout->setMargin( YQWidgetMargin );
00070 
00071     _caption = new YQWidgetCaption( this, label );
00072     YUI_CHECK_NEW( _caption );
00073     layout->addWidget( _caption );
00074 
00075     _qt_lineEdit = new YQRawLineEdit( this );
00076     YUI_CHECK_NEW( _qt_lineEdit );
00077     layout->addWidget( _qt_lineEdit );
00078 
00079     _caption->setBuddy( _qt_lineEdit );
00080 
00081     connect( _qt_lineEdit, SIGNAL( textChanged( const QString & ) ),
00082              this,         SLOT  ( changed    ( const QString & ) ) );
00083 
00084     if ( passwordMode )
00085     {
00086         _qt_lineEdit->setEchoMode( QLineEdit::Password );
00087 
00088         connect( _qt_lineEdit,  SIGNAL( capsLockActivated() ),
00089                  this,          SLOT  ( displayCapsLockWarning() ) );
00090 
00091         connect( _qt_lineEdit,  SIGNAL( capsLockDeactivated() ),
00092                  this,          SLOT  ( clearCapsLockWarning() ) );
00093     }
00094 }
00095 
00096 
00097 string YQInputField::value()
00098 {
00099     return toUTF8( _qt_lineEdit->text() );
00100 }
00101 
00102 
00103 void YQInputField::setValue( const std::string & newText )
00104 {
00105     QString text = fromUTF8( newText );
00106 
00107     if ( isValidText( text ) )
00108     {
00109         YQSignalBlocker sigBlocker( _qt_lineEdit );
00110         _qt_lineEdit->setText( text );
00111     }
00112     else
00113     {
00114         yuiError() << this << ": Rejecting invalid value \"" << newText << "\"" << std::endl;
00115     }
00116 }
00117 
00118 
00119 void YQInputField::setEnabled( bool enabled )
00120 {
00121     _qt_lineEdit->setEnabled( enabled );
00122     _caption->setEnabled( enabled );
00123     YWidget::setEnabled( enabled );
00124 }
00125 
00126 
00127 int YQInputField::preferredWidth()
00128 {
00129     int minSize   = shrinkable() ? 30 : 200;
00130     int hintWidth = !_caption->isHidden()
00131         ? _caption->sizeHint().width() + 2 * YQWidgetMargin
00132         : 0;
00133 
00134     return max( minSize, hintWidth );
00135 }
00136 
00137 
00138 int YQInputField::preferredHeight()
00139 {
00140     return sizeHint().height();
00141 }
00142 
00143 
00144 void YQInputField::setSize( int newWidth, int newHeight )
00145 {
00146     resize( newWidth, newHeight );
00147 }
00148 
00149 
00150 void YQInputField::setLabel( const std::string & label )
00151 {
00152     _caption->setText( label );
00153     YInputField::setLabel( label );
00154 }
00155 
00156 
00157 bool YQInputField::isValidText( const QString & txt ) const
00158 {
00159     if ( ! _validator )
00160         return true;
00161 
00162     int pos = 0;
00163     QString text( txt );        // need a non-const QString &
00164 
00165     return _validator->validate( text, pos ) == QValidator::Acceptable;
00166 }
00167 
00168 
00169 void YQInputField::setValidChars( const std::string & newValidChars )
00170 {
00171     if ( _validator )
00172     {
00173         _validator->setValidChars( fromUTF8( newValidChars ) );
00174     }
00175     else
00176     {
00177         _validator = new QY2CharValidator( fromUTF8( newValidChars ), this );
00178         _qt_lineEdit->setValidator( _validator );
00179 
00180         // No need to delete the validator in the destructor - Qt will take
00181         // care of that since it's a QObject with a parent!
00182     }
00183 
00184     if ( ! isValidText( _qt_lineEdit->text() ) )
00185     {
00186         yuiError() << this << ": Old value \"" << _qt_lineEdit->text()
00187                    << "\" invalid according to new ValidChars \"" << newValidChars
00188                    << "\" - deleting"
00189                    << std::endl;
00190 
00191         _qt_lineEdit->setText( "" );
00192     }
00193 
00194     YInputField::setValidChars( newValidChars );
00195 }
00196 
00197 void YQInputField::setInputMaxLength( int len )
00198 {
00199     _qt_lineEdit->setMaxLength( len );
00200     YInputField::setInputMaxLength( len );
00201 }
00202 
00203 bool YQInputField::setKeyboardFocus()
00204 {
00205     _qt_lineEdit->setFocus();
00206     _qt_lineEdit->selectAll();
00207 
00208     return true;
00209 }
00210 
00211 
00212 void YQInputField::changed( const QString & )
00213 {
00214     if ( notify() )
00215         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
00216 }
00217 
00218 
00219 void YQInputField::displayCapsLockWarning()
00220 {
00221     yuiMilestone() << "warning" << std::endl;
00222     if ( _displayingCapsLockWarning )
00223         return;
00224 
00225     if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
00226         return;
00227 
00228     // Translators: This is a very short warning that the CapsLock key
00229     // is active while trying to type in a password field. This warning
00230     // replaces the normal label (caption) of that password field while
00231     // CapsLock is active, so please keep it short. Please don't translate it
00232     // at all if the term "CapsLock" can reasonably expected to be understood
00233     // by the target audience.
00234     //
00235     // In particular, please don't translate this to death in German.
00236     // Simply leave it.
00237 
00238     _caption->setText( _( "CapsLock!" ) );
00239     _displayingCapsLockWarning = true;
00240 }
00241 
00242 
00243 void YQInputField::clearCapsLockWarning()
00244 {
00245     yuiMilestone() << "warning off " << std::endl;
00246     if ( ! _displayingCapsLockWarning )
00247         return;
00248 
00249     if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
00250         return;
00251 
00252     _caption->setText( label() );
00253     _displayingCapsLockWarning = false;
00254 }
00255 
00256 
00257 bool YQRawLineEdit::x11Event( XEvent * event )
00258 {
00259     // Qt (3.x) does not have support for the CapsLock key.
00260     // All other modifiers (Shift, Control, Meta) are propagated via
00261     // Qt's events, but for some reason, CapsLock is not.
00262     //
00263     // So let's examine the raw X11 event here to check for the
00264     // CapsLock status. All events are really handled on the parent class
00265     // (QWidget) level, though. We only peek into the modifier states.
00266 
00267     if ( event )
00268     {
00269         bool oldCapsLockActive = _capsLockActive;
00270 
00271         switch ( event->type )
00272         {
00273             case KeyPress:
00274                 _capsLockActive = (bool) ( event->xkey.state & LockMask );
00275                 break;
00276 
00277             case KeyRelease:
00278 
00279                 _capsLockActive = (bool) ( event->xkey.state & LockMask );
00280 
00281                 if ( _capsLockActive && oldCapsLockActive )
00282                 {
00283                     KeySym key = XLookupKeysym( &(event->xkey), 0 );
00284 
00285                     if ( key == XK_Caps_Lock ||
00286                          key == XK_Shift_Lock  )
00287                     {
00288                         yuiMilestone() << "CapsLock released" << std::endl;
00289                         _capsLockActive = false;
00290                     }
00291                 }
00292 
00293                 if ( _capsLockActive )
00294                     yuiDebug() << "Key event; caps lock: "
00295                                << std::boolalpha << _capsLockActive << std::noboolalpha
00296                                << std::endl;
00297                 break;
00298 
00299             case ButtonPress:
00300             case ButtonRelease:
00301                 _capsLockActive = (bool) ( event->xbutton.state & LockMask );
00302                 break;
00303 
00304             case EnterNotify:
00305                 _capsLockActive = (bool) ( event->xcrossing.state & LockMask );
00306                 break;
00307 
00308             case LeaveNotify:
00309             case FocusOut:
00310                 _capsLockActive = false;
00311                 emit capsLockDeactivated();
00312                 break;
00313 
00314             default:
00315                 break;
00316         }
00317 
00318         if ( oldCapsLockActive != _capsLockActive )
00319         {
00320             yuiMilestone() << "Emitting warning" << std::endl;
00321 
00322             if ( _capsLockActive )
00323                 emit capsLockActivated();
00324             else
00325                 emit capsLockDeactivated();
00326         }
00327     }
00328 
00329     return false; // handle this event at the Qt level
00330 }
00331 
00332 
00333 #include "YQInputField.moc"
 All Classes Functions Variables