libyui-qt  2.52.2
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 #include "utf8.h"
33 #include "YQUI.h"
34 #include <yui/YEvent.h>
35 #include "QY2CharValidator.h"
36 #include "YQInputField.h"
37 #include "YQi18n.h"
38 #include "YQSignalBlocker.h"
39 #include "YQWidgetCaption.h"
40 #include <QVBoxLayout>
41 
42 // Include low-level X headers AFTER Qt headers:
43 // X.h pollutes the global namespace (!!!) with pretty useless #defines
44 // like "Above", "Below" etc. that clash with some Qt headers.
45 #include <X11/X.h> // CapsLock detection
46 #include <X11/Xlib.h> // CapsLock detection
47 #include <X11/keysym.h> // CapsLock detection
48 
49 using std::string;
50 
51 
52 
53 YQInputField::YQInputField( YWidget * parent,
54  const string & label,
55  bool passwordMode )
56  : QFrame( (QWidget *) parent->widgetRep() )
57  , YInputField( parent, label, passwordMode )
58  , _validator(0)
59  , _displayingCapsLockWarning( false )
60 {
61  QVBoxLayout* layout = new QVBoxLayout( this );
62  setLayout( layout );
63 
64  setWidgetRep( this );
65 
66  layout->setSpacing( YQWidgetSpacing );
67  layout->setMargin( YQWidgetMargin );
68 
69  _caption = new YQWidgetCaption( this, label );
70  YUI_CHECK_NEW( _caption );
71  layout->addWidget( _caption );
72 
73  _qt_lineEdit = new YQRawLineEdit( this );
74  YUI_CHECK_NEW( _qt_lineEdit );
75  layout->addWidget( _qt_lineEdit );
76 
77  _caption->setBuddy( _qt_lineEdit );
78 
79  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::textChanged,
80  this, &pclass(this)::changed );
81 
82  if ( passwordMode )
83  {
84  _qt_lineEdit->setEchoMode( QLineEdit::Password );
85 
86  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::capsLockActivated,
87  this, &pclass(this)::displayCapsLockWarning );
88 
89  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::capsLockDeactivated,
90  this, &pclass(this)::clearCapsLockWarning );
91  }
92 }
93 
94 
96 {
97  return toUTF8( _qt_lineEdit->text() );
98 }
99 
100 
101 void YQInputField::setValue( const string & newText )
102 {
103  QString text = fromUTF8( newText );
104 
105  if ( isValidText( text ) )
106  {
107  YQSignalBlocker sigBlocker( _qt_lineEdit );
108  _qt_lineEdit->setText( text );
109  }
110  else
111  {
112  yuiError() << this << ": Rejecting invalid value \"" << newText << "\"" << endl;
113  }
114 }
115 
116 
117 void YQInputField::setEnabled( bool enabled )
118 {
119  _qt_lineEdit->setEnabled( enabled );
120  _caption->setEnabled( enabled );
121  YWidget::setEnabled( enabled );
122 }
123 
124 
126 {
127  int minSize = shrinkable() ? 30 : 200;
128  int hintWidth = !_caption->isHidden()
129  ? _caption->sizeHint().width() + 2 * YQWidgetMargin
130  : 0;
131 
132  return std::max( minSize, hintWidth );
133 }
134 
135 
137 {
138  return sizeHint().height();
139 }
140 
141 
142 void YQInputField::setSize( int newWidth, int newHeight )
143 {
144  resize( newWidth, newHeight );
145 }
146 
147 
148 void YQInputField::setLabel( const string & label )
149 {
150  _caption->setText( label );
151  YInputField::setLabel( label );
152 }
153 
154 
155 bool YQInputField::isValidText( const QString & txt ) const
156 {
157  if ( ! _validator )
158  return true;
159 
160  int pos = 0;
161  QString text( txt ); // need a non-const QString &
162 
163  return _validator->validate( text, pos ) == QValidator::Acceptable;
164 }
165 
166 
167 void YQInputField::setValidChars( const string & newValidChars )
168 {
169  if ( _validator )
170  {
171  _validator->setValidChars( fromUTF8( newValidChars ) );
172  }
173  else
174  {
175  _validator = new QY2CharValidator( fromUTF8( newValidChars ), this );
176  _qt_lineEdit->setValidator( _validator );
177 
178  // No need to delete the validator in the destructor - Qt will take
179  // care of that since it's a QObject with a parent!
180  }
181 
182  if ( ! isValidText( _qt_lineEdit->text() ) )
183  {
184  yuiError() << this << ": Old value \"" << _qt_lineEdit->text()
185  << "\" invalid according to new ValidChars \"" << newValidChars
186  << "\" - deleting"
187  << endl;
188 
189  _qt_lineEdit->setText( "" );
190  }
191 
192  YInputField::setValidChars( newValidChars );
193 }
194 
196 {
197  _qt_lineEdit->setMaxLength( len );
198  YInputField::setInputMaxLength( len );
199 }
200 
202 {
203  _qt_lineEdit->setFocus();
204  _qt_lineEdit->selectAll();
205 
206  return true;
207 }
208 
209 
210 void YQInputField::changed( const QString & )
211 {
212  if ( notify() )
213  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
214 }
215 
216 
218 {
219  yuiMilestone() << "warning" << endl;
220  if ( _displayingCapsLockWarning )
221  return;
222 
223  if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
224  return;
225 
226  // Translators: This is a very short warning that the CapsLock key
227  // is active while trying to type in a password field. This warning
228  // replaces the normal label (caption) of that password field while
229  // CapsLock is active, so please keep it short. Please don't translate it
230  // at all if the term "CapsLock" can reasonably expected to be understood
231  // by the target audience.
232  //
233  // In particular, please don't translate this to death in German.
234  // Simply leave it.
235 
236  _caption->setText( _( "CapsLock!" ) );
237  _displayingCapsLockWarning = true;
238 }
239 
240 
242 {
243  yuiMilestone() << "warning off " << endl;
244  if ( ! _displayingCapsLockWarning )
245  return;
246 
247  if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
248  return;
249 
250  _caption->setText( label() );
251  _displayingCapsLockWarning = false;
252 }
253 
254 
255 bool YQRawLineEdit::x11Event( XEvent * event )
256 {
257  // Qt (3.x) does not have support for the CapsLock key.
258  // All other modifiers (Shift, Control, Meta) are propagated via
259  // Qt's events, but for some reason, CapsLock is not.
260  //
261  // So let's examine the raw X11 event here to check for the
262  // CapsLock status. All events are really handled on the parent class
263  // (QWidget) level, though. We only peek into the modifier states.
264 
265  if ( event )
266  {
267  bool oldCapsLockActive = _capsLockActive;
268 
269  switch ( event->type )
270  {
271  case KeyPress:
272  _capsLockActive = (bool) ( event->xkey.state & LockMask );
273  break;
274 
275  case KeyRelease:
276 
277  _capsLockActive = (bool) ( event->xkey.state & LockMask );
278 
279  if ( _capsLockActive && oldCapsLockActive )
280  {
281  KeySym key = XLookupKeysym( &(event->xkey), 0 );
282 
283  if ( key == XK_Caps_Lock ||
284  key == XK_Shift_Lock )
285  {
286  yuiMilestone() << "CapsLock released" << endl;
287  _capsLockActive = false;
288  }
289  }
290 
291  if ( _capsLockActive )
292  yuiDebug() << "Key event; caps lock: "
293  << std::boolalpha << _capsLockActive << std::noboolalpha
294  << endl;
295  break;
296 
297  case ButtonPress:
298  case ButtonRelease:
299  _capsLockActive = (bool) ( event->xbutton.state & LockMask );
300  break;
301 
302  case EnterNotify:
303  _capsLockActive = (bool) ( event->xcrossing.state & LockMask );
304  break;
305 
306  case LeaveNotify:
307  case FocusOut:
308  _capsLockActive = false;
309  emit capsLockDeactivated();
310  break;
311 
312  default:
313  break;
314  }
315 
316  if ( oldCapsLockActive != _capsLockActive )
317  {
318  yuiMilestone() << "Emitting warning" << endl;
319 
320  if ( _capsLockActive )
321  emit capsLockActivated();
322  else
323  emit capsLockDeactivated();
324  }
325  }
326 
327  return false; // handle this event at the Qt level
328 }
Helper class to block Qt signals for QWidgets or QObjects as long as this object exists.
virtual void setEnabled(bool enabled)
Set enabled/disabled state.
virtual void setValue(const std::string &text)
Set the current value (the text entered by the user or set from the outside) of this input field...
YQInputField(YWidget *parent, const std::string &label, bool passwordMode=false)
Constructor.
Definition: YQInputField.cc:53
virtual void setText(const std::string &newText)
Change the text and handle visibility: If the new text is empty, hide this widget.
Helper class that can obtain the CapsLock status, too.
Definition: YQInputField.h:167
bool x11Event(XEvent *event)
X11 raw event handler.
bool isValidText(const QString &text) const
Returns &#39;true&#39; if a given text is valid according to ValidChars.
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
virtual void setInputMaxLength(int numberOfChars)
Specify the amount of characters which can be inserted.
virtual void setLabel(const std::string &label)
Set the label (the caption above the input field).
virtual int preferredWidth()
Preferred width of the widget.
virtual bool setKeyboardFocus()
Accept the keyboard focus.
virtual void setValidChars(const std::string &validChars)
Set the valid input characters.
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
Definition: YQUI.cc:480
void displayCapsLockWarning()
Display a warning that CapsLock is active: Replace the label with "CapsLock!".
virtual int preferredHeight()
Preferred height of the widget.
void setValidChars(const QString &newValidChars)
Set the valid input characters.
Helper class for captions (labels) above a widget: Takes care of hiding itself when its text is empty...
void clearCapsLockWarning()
Clear the CapsLock warning: Restore old label.
virtual std::string value()
Get the current value (the text entered by the user or set from the outside) of this input field...
Definition: YQInputField.cc:95
virtual State validate(QString &input, int &pos) const
Check user input.
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83
void changed(const QString &)
Triggered when the text in the InputField changes.