libyui-qt  2.52.4
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 using std::endl;
51 
52 
53 
54 YQInputField::YQInputField( YWidget * parent,
55  const string & label,
56  bool passwordMode )
57  : QFrame( (QWidget *) parent->widgetRep() )
58  , YInputField( parent, label, passwordMode )
59  , _validator(0)
60  , _displayingCapsLockWarning( false )
61 {
62  QVBoxLayout* layout = new QVBoxLayout( this );
63  setLayout( layout );
64 
65  setWidgetRep( this );
66 
67  layout->setSpacing( YQWidgetSpacing );
68  layout->setMargin( YQWidgetMargin );
69 
70  _caption = new YQWidgetCaption( this, label );
71  YUI_CHECK_NEW( _caption );
72  layout->addWidget( _caption );
73 
74  _qt_lineEdit = new YQRawLineEdit( this );
75  YUI_CHECK_NEW( _qt_lineEdit );
76  layout->addWidget( _qt_lineEdit );
77 
78  _caption->setBuddy( _qt_lineEdit );
79 
80  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::textChanged,
81  this, &pclass(this)::changed );
82 
83  if ( passwordMode )
84  {
85  _qt_lineEdit->setEchoMode( QLineEdit::Password );
86 
87  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::capsLockActivated,
88  this, &pclass(this)::displayCapsLockWarning );
89 
90  connect( _qt_lineEdit, &pclass(_qt_lineEdit)::capsLockDeactivated,
91  this, &pclass(this)::clearCapsLockWarning );
92  }
93 }
94 
95 
97 {
98  return toUTF8( _qt_lineEdit->text() );
99 }
100 
101 
102 void YQInputField::setValue( const string & newText )
103 {
104  QString text = fromUTF8( newText );
105 
106  if ( isValidText( text ) )
107  {
108  YQSignalBlocker sigBlocker( _qt_lineEdit );
109  _qt_lineEdit->setText( text );
110  }
111  else
112  {
113  yuiError() << this << ": Rejecting invalid value \"" << newText << "\"" << endl;
114  }
115 }
116 
117 
118 void YQInputField::setEnabled( bool enabled )
119 {
120  _qt_lineEdit->setEnabled( enabled );
121  _caption->setEnabled( enabled );
122  YWidget::setEnabled( enabled );
123 }
124 
125 
127 {
128  int minSize = shrinkable() ? 30 : 200;
129  int hintWidth = !_caption->isHidden()
130  ? _caption->sizeHint().width() + 2 * YQWidgetMargin
131  : 0;
132 
133  return std::max( minSize, hintWidth );
134 }
135 
136 
138 {
139  return sizeHint().height();
140 }
141 
142 
143 void YQInputField::setSize( int newWidth, int newHeight )
144 {
145  resize( newWidth, newHeight );
146 }
147 
148 
149 void YQInputField::setLabel( const string & label )
150 {
151  _caption->setText( label );
152  YInputField::setLabel( label );
153 }
154 
155 
156 bool YQInputField::isValidText( const QString & txt ) const
157 {
158  if ( ! _validator )
159  return true;
160 
161  int pos = 0;
162  QString text( txt ); // need a non-const QString &
163 
164  return _validator->validate( text, pos ) == QValidator::Acceptable;
165 }
166 
167 
168 void YQInputField::setValidChars( const string & newValidChars )
169 {
170  if ( _validator )
171  {
172  _validator->setValidChars( fromUTF8( newValidChars ) );
173  }
174  else
175  {
176  _validator = new QY2CharValidator( fromUTF8( newValidChars ), this );
177  _qt_lineEdit->setValidator( _validator );
178 
179  // No need to delete the validator in the destructor - Qt will take
180  // care of that since it's a QObject with a parent!
181  }
182 
183  if ( ! isValidText( _qt_lineEdit->text() ) )
184  {
185  yuiError() << this << ": Old value \"" << _qt_lineEdit->text()
186  << "\" invalid according to new ValidChars \"" << newValidChars
187  << "\" - deleting"
188  << endl;
189 
190  _qt_lineEdit->setText( "" );
191  }
192 
193  YInputField::setValidChars( newValidChars );
194 }
195 
197 {
198  _qt_lineEdit->setMaxLength( len );
199  YInputField::setInputMaxLength( len );
200 }
201 
203 {
204  _qt_lineEdit->setFocus();
205  _qt_lineEdit->selectAll();
206 
207  return true;
208 }
209 
210 
211 void YQInputField::changed( const QString & )
212 {
213  if ( notify() )
214  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
215 }
216 
217 
219 {
220  yuiMilestone() << "warning" << endl;
221  if ( _displayingCapsLockWarning )
222  return;
223 
224  if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
225  return;
226 
227  // Translators: This is a very short warning that the CapsLock key
228  // is active while trying to type in a password field. This warning
229  // replaces the normal label (caption) of that password field while
230  // CapsLock is active, so please keep it short. Please don't translate it
231  // at all if the term "CapsLock" can reasonably expected to be understood
232  // by the target audience.
233  //
234  // In particular, please don't translate this to death in German.
235  // Simply leave it.
236 
237  _caption->setText( _( "CapsLock!" ) );
238  _displayingCapsLockWarning = true;
239 }
240 
241 
243 {
244  yuiMilestone() << "warning off " << endl;
245  if ( ! _displayingCapsLockWarning )
246  return;
247 
248  if ( _qt_lineEdit->echoMode() == QLineEdit::Normal )
249  return;
250 
251  _caption->setText( label() );
252  _displayingCapsLockWarning = false;
253 }
254 
255 
256 bool YQRawLineEdit::x11Event( XEvent * event )
257 {
258  // Qt (3.x) does not have support for the CapsLock key.
259  // All other modifiers (Shift, Control, Meta) are propagated via
260  // Qt's events, but for some reason, CapsLock is not.
261  //
262  // So let's examine the raw X11 event here to check for the
263  // CapsLock status. All events are really handled on the parent class
264  // (QWidget) level, though. We only peek into the modifier states.
265 
266  if ( event )
267  {
268  bool oldCapsLockActive = _capsLockActive;
269 
270  switch ( event->type )
271  {
272  case KeyPress:
273  _capsLockActive = (bool) ( event->xkey.state & LockMask );
274  break;
275 
276  case KeyRelease:
277 
278  _capsLockActive = (bool) ( event->xkey.state & LockMask );
279 
280  if ( _capsLockActive && oldCapsLockActive )
281  {
282  KeySym key = XLookupKeysym( &(event->xkey), 0 );
283 
284  if ( key == XK_Caps_Lock ||
285  key == XK_Shift_Lock )
286  {
287  yuiMilestone() << "CapsLock released" << endl;
288  _capsLockActive = false;
289  }
290  }
291 
292  if ( _capsLockActive )
293  yuiDebug() << "Key event; caps lock: "
294  << std::boolalpha << _capsLockActive << std::noboolalpha
295  << endl;
296  break;
297 
298  case ButtonPress:
299  case ButtonRelease:
300  _capsLockActive = (bool) ( event->xbutton.state & LockMask );
301  break;
302 
303  case EnterNotify:
304  _capsLockActive = (bool) ( event->xcrossing.state & LockMask );
305  break;
306 
307  case LeaveNotify:
308  case FocusOut:
309  _capsLockActive = false;
310  emit capsLockDeactivated();
311  break;
312 
313  default:
314  break;
315  }
316 
317  if ( oldCapsLockActive != _capsLockActive )
318  {
319  yuiMilestone() << "Emitting warning" << endl;
320 
321  if ( _capsLockActive )
322  emit capsLockActivated();
323  else
324  emit capsLockDeactivated();
325  }
326  }
327 
328  return false; // handle this event at the Qt level
329 }
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:54
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:96
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.