libyui-qt  2.47.1.1
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, &pclass(_qt_lineEdit)::textChanged,
82  this, &pclass(this)::changed );
83 
84  if ( passwordMode )
85  {
86  _qt_lineEdit->setEchoMode( QLineEdit::Password );
87 
88  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::capsLockActivated,
89  this, &pclass(this)::displayCapsLockWarning );
90 
91  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::capsLockDeactivated,
92  this, &pclass(this)::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"
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:55
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 isValidText(const QString &text) const
Returns &#39;true&#39; if a given text is valid according to ValidChars.
bool x11Event(XEvent *event)
X11 raw event handler.
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 State validate(QString &input, int &pos) const
Check user input.
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:494
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:97
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:80
void changed(const QString &)
Triggered when the text in the InputField changes.