libyui-qt  2.43.5
 All Classes Functions Variables
YQInputField.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YQInputField.cc
20 
21  Author: Stefan Hundhammer <sh@suse.de>
22 
23  Textdomain "qt"
24 
25 /-*/
26 
27 
28 #include <qlineedit.h>
29 #define YUILogComponent "qt-ui"
30 #include <yui/YUILog.h>
31 
32 using std::max;
33 
34 #include "utf8.h"
35 #include "YQUI.h"
36 #include <yui/YEvent.h>
37 #include "QY2CharValidator.h"
38 #include "YQInputField.h"
39 #include "YQi18n.h"
40 #include "YQSignalBlocker.h"
41 #include "YQWidgetCaption.h"
42 #include <QVBoxLayout>
43 
44 // Include low-level X headers AFTER Qt headers:
45 // X.h pollutes the global namespace (!!!) with pretty useless #defines
46 // like "Above", "Below" etc. that clash with some Qt headers.
47 #include <X11/X.h> // CapsLock detection
48 #include <X11/Xlib.h> // CapsLock detection
49 #include <X11/keysym.h> // CapsLock detection
50 
51 using std::string;
52 
53 
54 
55 YQInputField::YQInputField( YWidget * parent,
56  const std::string & label,
57  bool passwordMode )
58  : QFrame( (QWidget *) parent->widgetRep() )
59  , YInputField( parent, label, passwordMode )
60  , _validator(0)
61  , _displayingCapsLockWarning( false )
62 {
63  QVBoxLayout* layout = new QVBoxLayout( this );
64  setLayout( layout );
65 
66  setWidgetRep( this );
67 
68  layout->setSpacing( YQWidgetSpacing );
69  layout->setMargin( YQWidgetMargin );
70 
71  _caption = new YQWidgetCaption( this, label );
72  YUI_CHECK_NEW( _caption );
73  layout->addWidget( _caption );
74 
75  _qt_lineEdit = new YQRawLineEdit( this );
76  YUI_CHECK_NEW( _qt_lineEdit );
77  layout->addWidget( _qt_lineEdit );
78 
79  _caption->setBuddy( _qt_lineEdit );
80 
81  connect( _qt_lineEdit, SIGNAL( textChanged( const QString & ) ),
82  this, SLOT ( changed ( const QString & ) ) );
83 
84  if ( passwordMode )
85  {
86  _qt_lineEdit->setEchoMode( QLineEdit::Password );
87 
88  connect( _qt_lineEdit, SIGNAL( capsLockActivated() ),
89  this, SLOT ( displayCapsLockWarning() ) );
90 
91  connect( _qt_lineEdit, SIGNAL( capsLockDeactivated() ),
92  this, SLOT ( clearCapsLockWarning() ) );
93  }
94 }
95 
96 
98 {
99  return toUTF8( _qt_lineEdit->text() );
100 }
101 
102 
103 void YQInputField::setValue( const std::string & newText )
104 {
105  QString text = fromUTF8( newText );
106 
107  if ( isValidText( text ) )
108  {
109  YQSignalBlocker sigBlocker( _qt_lineEdit );
110  _qt_lineEdit->setText( text );
111  }
112  else
113  {
114  yuiError() << this << ": Rejecting invalid value \"" << newText << "\"" << std::endl;
115  }
116 }
117 
118 
119 void YQInputField::setEnabled( bool enabled )
120 {
121  _qt_lineEdit->setEnabled( enabled );
122  _caption->setEnabled( enabled );
123  YWidget::setEnabled( enabled );
124 }
125 
126 
128 {
129  int minSize = shrinkable() ? 30 : 200;
130  int hintWidth = !_caption->isHidden()
131  ? _caption->sizeHint().width() + 2 * YQWidgetMargin
132  : 0;
133 
134  return max( minSize, hintWidth );
135 }
136 
137 
139 {
140  return sizeHint().height();
141 }
142 
143 
144 void YQInputField::setSize( int newWidth, int newHeight )
145 {
146  resize( newWidth, newHeight );
147 }
148 
149 
150 void YQInputField::setLabel( const std::string & label )
151 {
152  _caption->setText( label );
153  YInputField::setLabel( label );
154 }
155 
156 
157 bool YQInputField::isValidText( const QString & txt ) const
158 {
159  if ( ! _validator )
160  return true;
161 
162  int pos = 0;
163  QString text( txt ); // need a non-const QString &
164 
165  return _validator->validate( text, pos ) == QValidator::Acceptable;
166 }
167 
168 
169 void YQInputField::setValidChars( const std::string & newValidChars )
170 {
171  if ( _validator )
172  {
173  _validator->setValidChars( fromUTF8( newValidChars ) );
174  }
175  else
176  {
177  _validator = new QY2CharValidator( fromUTF8( newValidChars ), this );
178  _qt_lineEdit->setValidator( _validator );
179 
180  // No need to delete the validator in the destructor - Qt will take
181  // care of that since it's a QObject with a parent!
182  }
183 
184  if ( ! isValidText( _qt_lineEdit->text() ) )
185  {
186  yuiError() << this << ": Old value \"" << _qt_lineEdit->text()
187  << "\" invalid according to new ValidChars \"" << newValidChars
188  << "\" - deleting"
189  << std::endl;
190 
191  _qt_lineEdit->setText( "" );
192  }
193 
194  YInputField::setValidChars( newValidChars );
195 }
196 
198 {
199  _qt_lineEdit->setMaxLength( len );
200  YInputField::setInputMaxLength( len );
201 }
202 
204 {
205  _qt_lineEdit->setFocus();
206  _qt_lineEdit->selectAll();
207 
208  return true;
209 }
210 
211 
212 void YQInputField::changed( const QString & )
213 {
214  if ( notify() )
215  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
216 }
217 
218 
220 {
221  yuiMilestone() << "warning" << std::endl;
222  if ( _displayingCapsLockWarning )
223  return;
224 
225  if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
226  return;
227 
228  // Translators: This is a very short warning that the CapsLock key
229  // is active while trying to type in a password field. This warning
230  // replaces the normal label (caption) of that password field while
231  // CapsLock is active, so please keep it short. Please don't translate it
232  // at all if the term "CapsLock" can reasonably expected to be understood
233  // by the target audience.
234  //
235  // In particular, please don't translate this to death in German.
236  // Simply leave it.
237 
238  _caption->setText( _( "CapsLock!" ) );
239  _displayingCapsLockWarning = true;
240 }
241 
242 
244 {
245  yuiMilestone() << "warning off " << std::endl;
246  if ( ! _displayingCapsLockWarning )
247  return;
248 
249  if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
250  return;
251 
252  _caption->setText( label() );
253  _displayingCapsLockWarning = false;
254 }
255 
256 
257 bool YQRawLineEdit::x11Event( XEvent * event )
258 {
259  // Qt (3.x) does not have support for the CapsLock key.
260  // All other modifiers (Shift, Control, Meta) are propagated via
261  // Qt's events, but for some reason, CapsLock is not.
262  //
263  // So let's examine the raw X11 event here to check for the
264  // CapsLock status. All events are really handled on the parent class
265  // (QWidget) level, though. We only peek into the modifier states.
266 
267  if ( event )
268  {
269  bool oldCapsLockActive = _capsLockActive;
270 
271  switch ( event->type )
272  {
273  case KeyPress:
274  _capsLockActive = (bool) ( event->xkey.state & LockMask );
275  break;
276 
277  case KeyRelease:
278 
279  _capsLockActive = (bool) ( event->xkey.state & LockMask );
280 
281  if ( _capsLockActive && oldCapsLockActive )
282  {
283  KeySym key = XLookupKeysym( &(event->xkey), 0 );
284 
285  if ( key == XK_Caps_Lock ||
286  key == XK_Shift_Lock )
287  {
288  yuiMilestone() << "CapsLock released" << std::endl;
289  _capsLockActive = false;
290  }
291  }
292 
293  if ( _capsLockActive )
294  yuiDebug() << "Key event; caps lock: "
295  << std::boolalpha << _capsLockActive << std::noboolalpha
296  << std::endl;
297  break;
298 
299  case ButtonPress:
300  case ButtonRelease:
301  _capsLockActive = (bool) ( event->xbutton.state & LockMask );
302  break;
303 
304  case EnterNotify:
305  _capsLockActive = (bool) ( event->xcrossing.state & LockMask );
306  break;
307 
308  case LeaveNotify:
309  case FocusOut:
310  _capsLockActive = false;
311  emit capsLockDeactivated();
312  break;
313 
314  default:
315  break;
316  }
317 
318  if ( oldCapsLockActive != _capsLockActive )
319  {
320  yuiMilestone() << "Emitting warning" << std::endl;
321 
322  if ( _capsLockActive )
323  emit capsLockActivated();
324  else
325  emit capsLockDeactivated();
326  }
327  }
328 
329  return false; // handle this event at the Qt level
330 }
331 
332 
333 #include "YQInputField.moc"