1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
11 \----------------------------------------------------------------------/
15 Author: Stefan Hundhammer <sh@suse.de>
17 textdomain "packages-qt"
22 #include <qlineedit.h>
23 #define y2log_component "qt-ui"
24 #include <ycp/y2log.h>
31 #include "QY2CharValidator.h"
32 #include "YQInputField.h"
34 #include "YQSignalBlocker.h"
35 #include "YQWidgetCaption.h"
36 #include <QVBoxLayout>
38 // Include low-level X headers AFTER Qt headers:
39 // X.h pollutes the global namespace (!!!) with pretty useless #defines
40 // like "Above", "Below" etc. that clash with some Qt headers.
41 #include <X11/X.h> // CapsLock detection
42 #include <X11/Xlib.h> // CapsLock detection
43 #include <X11/keysym.h> // CapsLock detection
49 YQInputField::YQInputField( YWidget * parent,
52 : QFrame( (QWidget *) parent->widgetRep() )
53 , YInputField( parent, label, passwordMode )
55 , _displayingCapsLockWarning( false )
57 QVBoxLayout* layout = new QVBoxLayout( this );
62 layout->setSpacing( YQWidgetSpacing );
63 layout->setMargin( YQWidgetMargin );
65 _caption = new YQWidgetCaption( this, label );
66 YUI_CHECK_NEW( _caption );
67 layout->addWidget( _caption );
69 _qt_lineEdit = new YQRawLineEdit( this );
70 YUI_CHECK_NEW( _qt_lineEdit );
71 layout->addWidget( _qt_lineEdit );
73 _caption->setBuddy( _qt_lineEdit );
75 connect( _qt_lineEdit, SIGNAL( textChanged( const QString & ) ),
76 this, SLOT ( changed ( const QString & ) ) );
80 _qt_lineEdit->setEchoMode( QLineEdit::Password );
82 connect( _qt_lineEdit, SIGNAL( capsLockActivated() ),
83 this, SLOT ( displayCapsLockWarning() ) );
85 connect( _qt_lineEdit, SIGNAL( capsLockDeactivated() ),
86 this, SLOT ( clearCapsLockWarning() ) );
91 string YQInputField::value()
93 return toUTF8( _qt_lineEdit->text() );
97 void YQInputField::setValue( const string & newText )
99 QString text = fromUTF8( newText );
101 if ( isValidText( text ) )
103 YQSignalBlocker sigBlocker( _qt_lineEdit );
104 _qt_lineEdit->setText( text );
108 y2error( "%s \"%s\": Rejecting invalid value \"%s\"",
109 widgetClass(), debugLabel().c_str(), newText.c_str() );
114 void YQInputField::setEnabled( bool enabled )
116 _qt_lineEdit->setEnabled( enabled );
117 _caption->setEnabled( enabled );
118 YWidget::setEnabled( enabled );
122 int YQInputField::preferredWidth()
124 int minSize = shrinkable() ? 30 : 200;
125 int hintWidth = _caption->isShown()
126 ? _caption->sizeHint().width() + 2 * YQWidgetMargin
129 return max( minSize, hintWidth );
133 int YQInputField::preferredHeight()
135 return sizeHint().height();
139 void YQInputField::setSize( int newWidth, int newHeight )
141 resize( newWidth, newHeight );
145 void YQInputField::setLabel( const string & label )
147 _caption->setText( label );
148 YInputField::setLabel( label );
152 bool YQInputField::isValidText( const QString & txt ) const
158 QString text( txt ); // need a non-const QString &
160 return _validator->validate( text, pos ) == QValidator::Acceptable;
164 void YQInputField::setValidChars( const string & newValidChars )
168 _validator->setValidChars( fromUTF8( newValidChars ) );
172 _validator = new QY2CharValidator( fromUTF8( newValidChars ), this );
173 _qt_lineEdit->setValidator( _validator );
175 // No need to delete the validator in the destructor - Qt will take
176 // care of that since it's a QObject with a parent!
179 if ( ! isValidText( _qt_lineEdit->text() ) )
181 y2error( "Old value \"%s\" of %s \"%s\" invalid according to ValidChars \"%s\" - deleting",
182 (const char *) _qt_lineEdit->text(),
183 widgetClass(), debugLabel().c_str(),
184 newValidChars.c_str() );
185 _qt_lineEdit->setText( "" );
188 YInputField::setValidChars( newValidChars );
191 void YQInputField::setInputMaxLength( int len )
193 _qt_lineEdit->setMaxLength( len );
194 YInputField::setInputMaxLength( len );
197 bool YQInputField::setKeyboardFocus()
199 _qt_lineEdit->setFocus();
200 _qt_lineEdit->selectAll();
206 void YQInputField::changed( const QString & )
209 YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
213 void YQInputField::displayCapsLockWarning()
215 y2milestone( "warning" );
216 if ( _displayingCapsLockWarning )
219 if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
222 // Translators: This is a very short warning that the CapsLock key
223 // is active while trying to type in a password field. This warning
224 // replaces the normal label (caption) of that password field while
225 // CapsLock is active, so please keep it short. Please don't translate it
226 // at all if the term "CapsLock" can reasonably expected to be understood
227 // by the target audience.
229 // In particular, please don't translate this to death in German.
232 _caption->setText( _( "CapsLock!" ) );
233 _displayingCapsLockWarning = true;
237 void YQInputField::clearCapsLockWarning()
239 y2milestone( "warning off " );
240 if ( ! _displayingCapsLockWarning )
243 if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
246 _caption->setText( label() );
247 _displayingCapsLockWarning = false;
251 bool YQRawLineEdit::x11Event( XEvent * event )
253 // Qt (3.x) does not have support for the CapsLock key.
254 // All other modifiers (Shift, Control, Meta) are propagated via
255 // Qt's events, but for some reason, CapsLock is not.
257 // So let's examine the raw X11 event here to check for the
258 // CapsLock status. All events are really handled on the parent class
259 // (QWidget) level, though. We only peek into the modifier states.
263 bool oldCapsLockActive = _capsLockActive;
265 switch ( event->type )
268 _capsLockActive = (bool) ( event->xkey.state & LockMask );
273 _capsLockActive = (bool) ( event->xkey.state & LockMask );
275 if ( _capsLockActive && oldCapsLockActive )
277 KeySym key = XLookupKeysym( &(event->xkey), 0 );
279 if ( key == XK_Caps_Lock ||
280 key == XK_Shift_Lock )
282 y2milestone( "CapsLock released" );
283 _capsLockActive = false;
287 y2debug( "Key event; caps lock: %s", _capsLockActive ? "on" : "off" );
292 _capsLockActive = (bool) ( event->xbutton.state & LockMask );
296 _capsLockActive = (bool) ( event->xcrossing.state & LockMask );
301 _capsLockActive = false;
302 emit capsLockDeactivated();
309 if ( oldCapsLockActive != _capsLockActive )
311 y2milestone( "Emitting warning" );
313 if ( _capsLockActive )
314 emit capsLockActivated();
316 emit capsLockDeactivated();
320 return false; // handle this event at the Qt level
324 #include "YQInputField.moc"