libyui-qt
2.43.5
|
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"