gtk+-2: Make current focus visible again.
[pinentry.git] / qt4 / qsecurelineedit.cpp
1 /*
2    qsecurelineedit.cpp - QLineEdit that uses secmem
3
4    Copyright (C) 2008 Klarälvdalens Datakonsult AB (KDAB)
5
6    Written by Marc Mutz <marc@kdab.com>.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2 of the
11    License, or (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 // the following code has been ported from QString to secqstring.
24 // The licence of the original code:
25
26 /****************************************************************************
27 **
28 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
29 **
30 ** This file is part of the QtGui module of the Qt Toolkit.
31 **
32 ** Licensees holding a valid Qt License Agreement may use this file in
33 ** accordance with the rights, responsibilities and obligations
34 ** contained therein.  Please consult your licensing agreement or
35 ** contact sales@trolltech.com if any conditions of this licensing
36 ** agreement are not clear to you.
37 **
38 ** Further information about Qt licensing is available at:
39 ** http://www.trolltech.com/products/qt/licensing.html or by
40 ** contacting info@trolltech.com.
41 **
42 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
43 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
44 **
45 ****************************************************************************/
46
47 #include "qlineedit.h" // added to pick up qt defines
48
49 #ifndef QT_NO_LINEEDIT
50 #include "qaction.h"
51 #include "qapplication.h"
52 #include "qclipboard.h"
53 #include "qdrag.h"
54 #include "qdrawutil.h"
55 #include "qevent.h"
56 #include "qfontmetrics.h"
57 #include "qmenu.h"
58 #include "qpainter.h"
59 #include "qpixmap.h"
60 #include "qpointer.h"
61 #include "qstringlist.h"
62 #include "qstyle.h"
63 #include "qstyleoption.h"
64 #include "qtimer.h"
65 #include "qvalidator.h"
66 #include "qvariant.h"
67 #include "qvector.h"
68 #include "qwhatsthis.h"
69 #include "qdebug.h"
70 #include "qtextedit.h"
71 //#include <private/qtextedit_p.h>
72 #ifndef QT_NO_ACCESSIBILITY
73 #include "qaccessible.h"
74 #endif
75 #ifndef QT_NO_IM
76 #include "qinputcontext.h"
77 #include "qlist.h"
78 #endif
79 #include "qabstractitemview.h"
80 #ifdef QT_NO_STYLE_STYLESHEET
81 #include "private/qstylesheetstyle_p.h"
82 #endif
83
84 #ifndef QT_NO_SHORTCUT
85 #include "qkeysequence.h"
86 #define ACCEL_KEY(k) QLatin1String("\t") + QString(QKeySequence(k))
87 #else
88 #define ACCEL_KEY(k) QString()
89 #endif
90
91 #include <limits.h>
92
93 // these go last so they don't contaminate other Qt headers
94 #include "qsecurelineedit_p.h"
95 #include "qsecurelineedit.h"
96
97 #define verticalMargin 1
98 #define horizontalMargin 2
99
100 QT_BEGIN_NAMESPACE
101
102 #ifdef Q_WS_MAC
103 extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
104 #endif
105
106 /*!
107     Initialize \a option with the values from this QSecureLineEdit. This method
108     is useful for subclasses when they need a QStyleOptionFrame or QStyleOptionFrameV2, but don't want
109     to fill in all the information themselves. This function will check the version
110     of the QStyleOptionFrame and fill in the additional values for a
111     QStyleOptionFrameV2.
112
113     \sa QStyleOption::initFrom()
114 */
115 void QSecureLineEdit::initStyleOption(QStyleOptionFrame *option) const
116 {
117     if (!option)
118         return;
119
120     Q_D(const QSecureLineEdit);
121     option->initFrom(this);
122     option->rect = contentsRect();
123     option->lineWidth = d->frame ? style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this)
124                                  : 0;
125     option->midLineWidth = 0;
126     option->state |= QStyle::State_Sunken;
127     if (d->readOnly)
128         option->state |= QStyle::State_ReadOnly;
129 #ifdef QT_KEYPAD_NAVIGATION
130     if (hasEditFocus())
131         option->state |= QStyle::State_HasEditFocus;
132 #endif
133     if (QStyleOptionFrameV2 *optionV2 = qstyleoption_cast<QStyleOptionFrameV2 *>(option))
134         optionV2->features = QStyleOptionFrameV2::None;
135 }
136
137 /*!
138     \class QSecureLineEdit
139     \brief The QSecureLineEdit widget is a one-line text editor.
140
141     \ingroup basicwidgets
142     \mainclass
143
144     A line edit allows the user to enter and edit a single line of
145     plain text with a useful collection of editing functions,
146     including undo and redo, cut and paste, and drag and drop.
147
148     By changing the echoMode() of a line edit, it can also be used as
149     a "write-only" field, for inputs such as passwords.
150
151     The length of the text can be constrained to maxLength(). The text
152     can be arbitrarily constrained using a validator() or an
153     inputMask(), or both.
154
155     A related class is QTextEdit which allows multi-line, rich text
156     editing.
157
158     You can change the text with setText() or insert(). The text is
159     retrieved with text(); the displayed text (which may be different,
160     see \l{EchoMode}) is retrieved with displayText(). Text can be
161     selected with setSelection() or selectAll(), and the selection can
162     be cut(), copy()ied and paste()d. The text can be aligned with
163     setAlignment().
164
165     When the text changes the textChanged() signal is emitted; when
166     the text changes other than by calling setText() the textEdited()
167     signal is emitted; when the cursor is moved the
168     cursorPositionChanged() signal is emitted; and when the Return or
169     Enter key is pressed the returnPressed() signal is emitted.
170
171     When editing is finished, either because the line edit lost focus
172     or Return/Enter is pressed the editingFinished() signal is
173     emitted.
174
175     Note that if there is a validator set on the line edit, the
176     returnPressed()/editingFinished() signals will only be emitted if
177     the validator returns QValidator::Acceptable.
178
179     By default, QSecureLineEdits have a frame as specified by the Windows
180     and Motif style guides; you can turn it off by calling
181     setFrame(false).
182
183     The default key bindings are described below. The line edit also
184     provides a context menu (usually invoked by a right mouse click)
185     that presents some of these editing options.
186     \target desc
187     \table
188     \header \i Keypress \i Action
189     \row \i Left Arrow \i Moves the cursor one character to the left.
190     \row \i Shift+Left Arrow \i Moves and selects text one character to the left.
191     \row \i Right Arrow \i Moves the cursor one character to the right.
192     \row \i Shift+Right Arrow \i Moves and selects text one character to the right.
193     \row \i Home \i Moves the cursor to the beginning of the line.
194     \row \i End \i Moves the cursor to the end of the line.
195     \row \i Backspace \i Deletes the character to the left of the cursor.
196     \row \i Ctrl+Backspace \i Deletes the word to the left of the cursor.
197     \row \i Delete \i Deletes the character to the right of the cursor.
198     \row \i Ctrl+Delete \i Deletes the word to the right of the cursor.
199     \row \i Ctrl+A \i Select all.
200     \row \i Ctrl+C \i Copies the selected text to the clipboard.
201     \row \i Ctrl+Insert \i Copies the selected text to the clipboard.
202     \row \i Ctrl+K \i Deletes to the end of the line.
203     \row \i Ctrl+V \i Pastes the clipboard text into line edit.
204     \row \i Shift+Insert \i Pastes the clipboard text into line edit.
205     \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard.
206     \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard.
207     \row \i Ctrl+Z \i Undoes the last operation.
208     \row \i Ctrl+Y \i Redoes the last undone operation.
209     \endtable
210
211     Any other key sequence that represents a valid character, will
212     cause the character to be inserted into the line edit.
213
214     \table 100%
215     \row \o \inlineimage macintosh-lineedit.png Screenshot of a Macintosh style line edit
216          \o A line edit shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
217     \row \o \inlineimage windows-lineedit.png Screenshot of a Windows XP style line edit
218          \o A line edit shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
219     \row \o \inlineimage plastique-lineedit.png Screenshot of a Plastique style line edit
220          \o A line edit shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
221     \endtable
222
223     \sa QTextEdit, QLabel, QComboBox, {fowler}{GUI Design Handbook: Field, Entry}, {Line Edits Example}
224 */
225
226
227 /*!
228     \fn void QSecureLineEdit::textChanged(const QString &text)
229
230     This signal is emitted whenever the text changes. The \a text
231     argument is the new text.
232
233     Unlike textEdited(), this signal is also emitted when the text is
234     changed programmatically, for example, by calling setText().
235 */
236
237 /*!
238     \fn void QSecureLineEdit::textEdited(const QString &text)
239
240     This signal is emitted whenever the text is edited. The \a text
241     argument is the next text.
242
243     Unlike textChanged(), this signal is not emitted when the text is
244     changed programmatically, for example, by calling setText().
245 */
246
247 /*!
248     \fn void QSecureLineEdit::cursorPositionChanged(int old, int new)
249
250     This signal is emitted whenever the cursor moves. The previous
251     position is given by \a old, and the new position by \a new.
252
253     \sa setCursorPosition(), cursorPosition()
254 */
255
256 /*!
257     \fn void QSecureLineEdit::selectionChanged()
258
259     This signal is emitted whenever the selection changes.
260
261     \sa hasSelectedText(), selectedText()
262 */
263
264 /*!
265     Constructs a line edit with no text.
266
267     The maximum text length is set to 32767 characters.
268
269     The \a parent argument is sent to the QWidget constructor.
270
271     \sa setText(), setMaxLength()
272 */
273 QSecureLineEdit::QSecureLineEdit(QWidget* parent)
274     : QWidget(parent,0), m_d(new QSecureLineEditPrivate(this))
275 {
276     Q_D(QSecureLineEdit);
277     d->init(secqstring());
278 }
279
280 /*!
281     Constructs a line edit containing the text \a contents.
282
283     The cursor position is set to the end of the line and the maximum
284     text length to 32767 characters.
285
286     The \a parent and argument is sent to the QWidget
287     constructor.
288
289     \sa text(), setMaxLength()
290 */
291 QSecureLineEdit::QSecureLineEdit(const secqstring& contents, QWidget* parent)
292     : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
293 {
294     Q_D(QSecureLineEdit);
295     d->init(contents);
296 }
297
298
299 #ifdef QT3_SUPPORT
300 /*!
301     Constructs a line edit with no text.
302
303     The maximum text length is set to 32767 characters.
304
305     The \a parent and \a name arguments are sent to the QWidget constructor.
306
307     \sa setText(), setMaxLength()
308 */
309 QSecureLineEdit::QSecureLineEdit(QWidget* parent, const char* name)
310     : QWidget(parent,0), m_d(new QSecureLineEditPrivate(this))
311 {
312     Q_D(QSecureLineEdit);
313     setObjectName(QString::fromAscii(name));
314     d->init(secqstring());
315 }
316
317 /*!
318     Constructs a line edit containing the text \a contents.
319
320     The cursor position is set to the end of the line and the maximum
321     text length to 32767 characters.
322
323     The \a parent and \a name arguments are sent to the QWidget
324     constructor.
325
326     \sa text(), setMaxLength()
327 */
328
329 QSecureLineEdit::QSecureLineEdit(const secqstring& contents, QWidget* parent, const char* name)
330     : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
331 {
332     Q_D(QSecureLineEdit);
333     setObjectName(QString::fromAscii(name));
334     d->init(contents);
335 }
336
337 /*!
338     Constructs a line edit with an input \a inputMask and the text \a
339     contents.
340
341     The cursor position is set to the end of the line and the maximum
342     text length is set to the length of the mask (the number of mask
343     characters and separators).
344
345     The \a parent and \a name arguments are sent to the QWidget
346     constructor.
347
348     \sa setMask() text()
349 */
350 QSecureLineEdit::QSecureLineEdit(const QString& contents, const QString &inputMask, QWidget* parent, const char* name)
351     : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
352 {
353     Q_D(QSecureLineEdit);
354     setObjectName(QString::fromAscii(name));
355     d->parseInputMask(inputMask);
356     if (d->maskData) {
357         QString ms = d->maskString(0, contents);
358         d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length()));
359         d->cursor = d->nextMaskBlank(ms.length());
360     } else {
361         d->init(contents);
362     }
363 }
364 #endif
365
366 /*!
367     Destroys the line edit.
368 */
369
370 QSecureLineEdit::~QSecureLineEdit()
371 {
372     delete m_d;
373 }
374
375
376 /*!
377     \property QSecureLineEdit::text
378     \brief the line edit's text
379
380     Setting this property clears the selection, clears the undo/redo
381     history, moves the cursor to the end of the line and resets the
382     \l modified property to false. The text is not validated when
383     inserted with setText().
384
385     The text is truncated to maxLength() length.
386
387     \sa insert(), clear()
388 */
389 secqstring QSecureLineEdit::text() const
390 {
391     Q_D(const QSecureLineEdit);
392     secqstring res = d->text;
393     if (d->maskData)
394         res = d->stripString(d->text);
395     return res;//(res.isNull() ? QString::fromLatin1("") : res);
396 }
397
398 void QSecureLineEdit::setText(const secqstring& text)
399 {
400     Q_D(QSecureLineEdit);
401     d->setText(text, -1, false);
402 #ifdef QT_KEYPAD_NAVIGATION
403     d->origText = d->text;
404 #endif
405 }
406
407
408 /*!
409     \property QSecureLineEdit::displayText
410     \brief the displayed text
411
412     If \l echoMode is \l Normal this returns the same as text(); if
413     \l EchoMode is \l Password or \l PasswordEchoOnEdit it returns a string of asterisks
414     text().length() characters long, e.g. "******"; if \l EchoMode is
415     \l NoEcho returns an empty string, "".
416
417     \sa setEchoMode() text() EchoMode
418 */
419
420 secqstring QSecureLineEdit::displayText() const
421 {
422     Q_D(const QSecureLineEdit);
423     if (d->echoMode == NoEcho)
424         return secqstring();
425     secqstring res = d->text;
426
427     if (d->echoMode == Password || d->echoMode == PasswordEchoOnEdit) {
428         QStyleOptionFrameV2 opt;
429         initStyleOption(&opt);
430         return secqstring( res.size(), style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this) );
431         //res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
432     }
433     return res;//(res.isNull() ? QString::fromLatin1("") : res);
434 }
435
436
437 /*!
438     \property QSecureLineEdit::maxLength
439     \brief the maximum permitted length of the text
440
441     If the text is too long, it is truncated at the limit.
442
443     If truncation occurs any selected text will be unselected, the
444     cursor position is set to 0 and the first part of the string is
445     shown.
446
447     If the line edit has an input mask, the mask defines the maximum
448     string length.
449
450     \sa inputMask
451 */
452
453 int QSecureLineEdit::maxLength() const
454 {
455     Q_D(const QSecureLineEdit);
456     return d->maxLength;
457 }
458
459 void QSecureLineEdit::setMaxLength(int maxLength)
460 {
461     Q_D(QSecureLineEdit);
462     if (d->maskData)
463         return;
464     d->maxLength = maxLength;
465     setText(d->text);
466 }
467
468
469
470 /*!
471     \property QSecureLineEdit::frame
472     \brief whether the line edit draws itself with a frame
473
474     If enabled (the default) the line edit draws itself inside a
475     frame, otherwise the line edit draws itself without any frame.
476 */
477 bool QSecureLineEdit::hasFrame() const
478 {
479     Q_D(const QSecureLineEdit);
480     return d->frame;
481 }
482
483
484 void QSecureLineEdit::setFrame(bool enable)
485 {
486     Q_D(QSecureLineEdit);
487     d->frame = enable;
488     update();
489     updateGeometry();
490 }
491
492
493 /*!
494     \enum QSecureLineEdit::EchoMode
495
496     This enum type describes how a line edit should display its
497     contents.
498
499     \value Normal   Display characters as they are entered. This is the
500                     default.
501     \value NoEcho   Do not display anything. This may be appropriate
502                     for passwords where even the length of the
503                     password should be kept secret.
504     \value Password  Display asterisks instead of the characters
505                     actually entered.
506     \value PasswordEchoOnEdit Display characters as they are entered
507                     while editing otherwise display asterisks.
508
509     \sa setEchoMode() echoMode()
510 */
511
512
513 /*!
514     \property QSecureLineEdit::echoMode
515     \brief the line edit's echo mode
516
517     The initial setting is \l Normal, but QSecureLineEdit also supports \l
518     NoEcho, \l Password and \l PasswordEchoOnEdit modes.
519
520     The widget's display and the ability to copy or drag the text is
521     affected by this setting.
522
523     \sa EchoMode displayText()
524 */
525
526 QSecureLineEdit::EchoMode QSecureLineEdit::echoMode() const
527 {
528     Q_D(const QSecureLineEdit);
529     return (EchoMode) d->echoMode;
530 }
531
532 void QSecureLineEdit::setEchoMode(EchoMode mode)
533 {
534     Q_D(QSecureLineEdit);
535     if(mode == (EchoMode)d->echoMode)
536         return;
537     setAttribute(Qt::WA_InputMethodEnabled, mode == Normal || mode == PasswordEchoOnEdit);
538     d->echoMode = mode;
539     d->updateTextLayout();
540     update();
541 #ifdef Q_WS_MAC
542     if (hasFocus())
543         qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
544 #endif
545 }
546
547
548 #ifndef QT_NO_VALIDATOR
549 /*!
550     Returns a pointer to the current input validator, or 0 if no
551     validator has been set.
552
553     \sa setValidator()
554 */
555
556 const QValidator * QSecureLineEdit::validator() const
557 {
558     Q_D(const QSecureLineEdit);
559     return d->validator;
560 }
561
562 /*!
563     Sets this line edit to only accept input that the validator, \a v,
564     will accept. This allows you to place any arbitrary constraints on
565     the text which may be entered.
566
567     If \a v == 0, setValidator() removes the current input validator.
568     The initial setting is to have no input validator (i.e. any input
569     is accepted up to maxLength()).
570
571     \sa validator() QIntValidator QDoubleValidator QRegExpValidator
572 */
573
574 void QSecureLineEdit::setValidator(const QValidator *v)
575 {
576     Q_D(QSecureLineEdit);
577     d->validator = const_cast<QValidator*>(v);
578 }
579 #endif // QT_NO_VALIDATOR
580
581 #ifndef QT_NO_COMPLETER
582 /*!
583     \since 4.2
584
585     Sets this line edit to provide auto completions from the completer, \a c.
586     The completion mode is set using QCompleter::setCompletionMode().
587
588     To use a QCompleter with a QValidator or QSecureLineEdit::inputMask, you need to
589     ensure that the model provided to QCompleter contains valid entries. You can
590     use the QSortFilterProxyModel to ensure that the QCompleter's model contains
591     only valid entries.
592
593     If \a c == 0, setCompleter() removes the current completer, effectively
594     disabling auto completion.
595
596     \sa QCompleter
597 */
598 void QSecureLineEdit::setCompleter(QCompleter *c)
599 {
600     Q_D(QSecureLineEdit);
601     if (c == d->completer)
602         return;
603     if (d->completer) {
604         disconnect(d->completer, 0, this, 0);
605         d->completer->setWidget(0);
606         if (d->completer->parent() == this)
607             delete d->completer;
608     }
609     d->completer = c;
610     if (!c)
611         return;
612     if (c->widget() == 0)
613         c->setWidget(this);
614     if (hasFocus()) {
615         QObject::connect(d->completer, SIGNAL(activated(QString)),
616                          this, SLOT(setText(QString)));
617         QObject::connect(d->completer, SIGNAL(highlighted(QString)),
618                          this, SLOT(_q_completionHighlighted(QString)));
619     }
620 }
621
622 /*!
623     \since 4.2
624
625     Returns the current QCompleter that provides completions.
626 */
627 QCompleter *QSecureLineEdit::completer() const
628 {
629     Q_D(const QSecureLineEdit);
630     return d->completer;
631 }
632
633 // looks for an enabled item iterating forward(dir=1)/backward(dir=-1) from the
634 // current row based. dir=0 indicates a new completion prefix was set.
635 bool QSecureLineEditPrivate::advanceToEnabledItem(int dir)
636 {
637     int start = completer->currentRow();
638     if (start == -1)
639         return false;
640     int i = start + dir;
641     if (dir == 0) dir = 1;
642     do {
643         if (!completer->setCurrentRow(i)) {
644             if (!completer->wrapAround())
645                 break;
646             i = i > 0 ? 0 : completer->completionCount() - 1;
647         } else {
648             QModelIndex currentIndex = completer->currentIndex();
649             if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
650                 return true;
651             i += dir;
652         }
653     } while (i != start);
654
655     completer->setCurrentRow(start); // restore
656     return false;
657 }
658
659 void QSecureLineEditPrivate::complete(int key)
660 {
661     if (!completer || readOnly || echoMode != QSecureLineEdit::Normal)
662         return;
663
664     if (completer->completionMode() == QCompleter::InlineCompletion) {
665         if (key == Qt::Key_Backspace)
666             return;
667         int n = 0;
668         if (key == Qt::Key_Up || key == Qt::Key_Down) {
669             if (selend != 0 && selend != text.length())
670                 return;
671             QString prefix = hasSelectedText() ? text.left(selstart) : text;
672             if (text.compare(completer->currentCompletion(), completer->caseSensitivity()) != 0
673                 || prefix.compare(completer->completionPrefix(), completer->caseSensitivity()) != 0) {
674                 completer->setCompletionPrefix(prefix);
675             } else {
676                 n = (key == Qt::Key_Up) ? -1 : +1;
677             }
678         } else {
679             completer->setCompletionPrefix(text);
680         }
681         if (!advanceToEnabledItem(n))
682             return;
683     } else {
684 #ifndef QT_KEYPAD_NAVIGATION
685         if (text.isEmpty()) {
686             completer->popup()->hide();
687             return;
688         }
689 #endif
690         completer->setCompletionPrefix(text);
691     }
692
693     completer->complete();
694 }
695
696 void QSecureLineEditPrivate::_q_completionHighlighted(QString newText)
697 {
698     Q_Q(QSecureLineEdit);
699     if (completer->completionMode() != QCompleter::InlineCompletion)
700         q->setText(newText);
701     else {
702         int c = cursor;
703         q->setText(text.left(c) + newText.mid(c));
704         q->setSelection(text.length(), c - newText.length());
705     }
706 }
707 #endif // QT_NO_COMPLETER
708
709 /*!
710     Returns a recommended size for the widget.
711
712     The width returned, in pixels, is usually enough for about 15 to
713     20 characters.
714 */
715
716 QSize QSecureLineEdit::sizeHint() const
717 {
718     Q_D(const QSecureLineEdit);
719     ensurePolished();
720     QFontMetrics fm(font());
721     int leftmargin, topmargin, rightmargin, bottommargin;
722     getContentsMargins( &leftmargin, &topmargin, &rightmargin, &bottommargin );
723     int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin
724             + topmargin + bottommargin;
725     int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin
726             + leftmargin + rightmargin; // "some"
727     QStyleOptionFrameV2 opt;
728     initStyleOption(&opt);
729     return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
730                                       expandedTo(QApplication::globalStrut()), this));
731 }
732
733
734 /*!
735     Returns a minimum size for the line edit.
736
737     The width returned is enough for at least one character.
738 */
739
740 QSize QSecureLineEdit::minimumSizeHint() const
741 {
742     Q_D(const QSecureLineEdit);
743     ensurePolished();
744     QFontMetrics fm = fontMetrics();
745     int leftmargin, topmargin, rightmargin, bottommargin;
746     getContentsMargins( &leftmargin, &topmargin, &rightmargin, &bottommargin );
747     int h = fm.height() + qMax(2*verticalMargin, fm.leading())
748             + topmargin + bottommargin;
749     int w = fm.maxWidth() + leftmargin + rightmargin;
750     QStyleOptionFrameV2 opt;
751     initStyleOption(&opt);
752     return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
753                                       expandedTo(QApplication::globalStrut()), this));
754 }
755
756
757 /*!
758     \property QSecureLineEdit::cursorPosition
759     \brief the current cursor position for this line edit
760
761     Setting the cursor position causes a repaint when appropriate.
762 */
763
764 int QSecureLineEdit::cursorPosition() const
765 {
766     Q_D(const QSecureLineEdit);
767     return d->cursor;
768 }
769
770 void QSecureLineEdit::setCursorPosition(int pos)
771 {
772     Q_D(QSecureLineEdit);
773     if (pos < 0)
774         pos = 0;
775
776     if (pos <= d->text.length())
777         d->moveCursor(pos);
778 }
779
780 /*!
781     Returns the cursor position under the point \a pos.
782 */
783 // ### What should this do if the point is outside of contentsRect? Currently returns 0.
784 int QSecureLineEdit::cursorPositionAt(const QPoint &pos)
785 {
786     Q_D(QSecureLineEdit);
787     return d->xToPos(pos.x());
788 }
789
790
791 #ifdef QT3_SUPPORT
792 /*! \obsolete
793
794     Use setText(), setCursorPosition() and setSelection() instead.
795 */
796 bool QSecureLineEdit::validateAndSet(const QString &newText, int newPos,
797                                  int newMarkAnchor, int newMarkDrag)
798 {
799     Q_D(QSecureLineEdit);
800     int priorState = d->undoState;
801     d->selstart = 0;
802     d->selend = d->text.length();
803     d->removeSelectedText();
804     d->insert(newText);
805     d->finishChange(priorState);
806     if (d->undoState > priorState) {
807         d->cursor = newPos;
808         d->selstart = qMin(newMarkAnchor, newMarkDrag);
809         d->selend = qMax(newMarkAnchor, newMarkDrag);
810         update();
811         d->emitCursorPositionChanged();
812         return true;
813     }
814     return false;
815 }
816 #endif //QT3_SUPPORT
817
818 /*!
819     \property QSecureLineEdit::alignment
820     \brief the alignment of the line edit
821
822     Both horizontal and vertical alignment is allowed here, Qt::AlignJustify
823     will map to Qt::AlignLeft.
824
825     \sa Qt::Alignment
826 */
827
828 Qt::Alignment QSecureLineEdit::alignment() const
829 {
830     Q_D(const QSecureLineEdit);
831     return QFlag(d->alignment);
832 }
833
834 void QSecureLineEdit::setAlignment(Qt::Alignment alignment)
835 {
836     Q_D(QSecureLineEdit);
837     d->alignment = alignment;
838     update();
839 }
840
841
842 /*!
843     Moves the cursor forward \a steps characters. If \a mark is true
844     each character moved over is added to the selection; if \a mark is
845     false the selection is cleared.
846
847     \sa cursorBackward()
848 */
849
850 void QSecureLineEdit::cursorForward(bool mark, int steps)
851 {
852     Q_D(QSecureLineEdit);
853     int cursor = d->cursor;
854     if (steps > 0) {
855         while(steps--)
856             cursor = d->textLayout.nextCursorPosition(cursor);
857     } else if (steps < 0) {
858         while (steps++)
859             cursor = d->textLayout.previousCursorPosition(cursor);
860     }
861     d->moveCursor(cursor, mark);
862 }
863
864
865 /*!
866     Moves the cursor back \a steps characters. If \a mark is true each
867     character moved over is added to the selection; if \a mark is
868     false the selection is cleared.
869
870     \sa cursorForward()
871 */
872 void QSecureLineEdit::cursorBackward(bool mark, int steps)
873 {
874     cursorForward(mark, -steps);
875 }
876
877 /*!
878     Moves the cursor one word forward. If \a mark is true, the word is
879     also selected.
880
881     \sa cursorWordBackward()
882 */
883 void QSecureLineEdit::cursorWordForward(bool mark)
884 {
885     Q_D(QSecureLineEdit);
886     d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
887 }
888
889 /*!
890     Moves the cursor one word backward. If \a mark is true, the word
891     is also selected.
892
893     \sa cursorWordForward()
894 */
895
896 void QSecureLineEdit::cursorWordBackward(bool mark)
897 {
898     Q_D(QSecureLineEdit);
899     d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
900 }
901
902
903 /*!
904     If no text is selected, deletes the character to the left of the
905     text cursor and moves the cursor one position to the left. If any
906     text is selected, the cursor is moved to the beginning of the
907     selected text and the selected text is deleted.
908
909     \sa del()
910 */
911 void QSecureLineEdit::backspace()
912 {
913     Q_D(QSecureLineEdit);
914     int priorState = d->undoState;
915     if (d->hasSelectedText()) {
916         d->removeSelectedText();
917     } else if (d->cursor) {
918             --d->cursor;
919             if (d->maskData)
920                 d->cursor = d->prevMaskBlank(d->cursor);
921             QChar uc = d->text.at(d->cursor);
922             if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
923                 // second half of a surrogate, check if we have the first half as well,
924                 // if yes delete both at once
925                 uc = d->text.at(d->cursor - 1);
926                 if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
927                     d->del(true);
928                     --d->cursor;
929                 }
930             }
931             d->del(true);
932     }
933     d->finishChange(priorState);
934 }
935
936 /*!
937     If no text is selected, deletes the character to the right of the
938     text cursor. If any text is selected, the cursor is moved to the
939     beginning of the selected text and the selected text is deleted.
940
941     \sa backspace()
942 */
943
944 void QSecureLineEdit::del()
945 {
946     Q_D(QSecureLineEdit);
947     int priorState = d->undoState;
948     if (d->hasSelectedText()) {
949         d->removeSelectedText();
950     } else {
951         int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor;
952         while (n--)
953             d->del();
954     }
955     d->finishChange(priorState);
956 }
957
958 /*!
959     Moves the text cursor to the beginning of the line unless it is
960     already there. If \a mark is true, text is selected towards the
961     first position; otherwise, any selected text is unselected if the
962     cursor is moved.
963
964     \sa end()
965 */
966
967 void QSecureLineEdit::home(bool mark)
968 {
969     Q_D(QSecureLineEdit);
970     d->moveCursor(0, mark);
971 }
972
973 /*!
974     Moves the text cursor to the end of the line unless it is already
975     there. If \a mark is true, text is selected towards the last
976     position; otherwise, any selected text is unselected if the cursor
977     is moved.
978
979     \sa home()
980 */
981
982 void QSecureLineEdit::end(bool mark)
983 {
984     Q_D(QSecureLineEdit);
985     d->moveCursor(d->text.length(), mark);
986 }
987
988
989 /*!
990     \property QSecureLineEdit::modified
991     \brief whether the line edit's contents has been modified by the user
992
993     The modified flag is never read by QSecureLineEdit; it has a default value
994     of false and is changed to true whenever the user changes the line
995     edit's contents.
996
997     This is useful for things that need to provide a default value but
998     do not start out knowing what the default should be (perhaps it
999     depends on other fields on the form). Start the line edit without
1000     the best default, and when the default is known, if modified()
1001     returns false (the user hasn't entered any text), insert the
1002     default value.
1003
1004     Calling setText() resets the modified flag to false.
1005 */
1006
1007 bool QSecureLineEdit::isModified() const
1008 {
1009     Q_D(const QSecureLineEdit);
1010     return d->modifiedState != d->undoState;
1011 }
1012
1013 void QSecureLineEdit::setModified(bool modified)
1014 {
1015     Q_D(QSecureLineEdit);
1016     if (modified)
1017         d->modifiedState = -1;
1018     else
1019         d->modifiedState = d->undoState;
1020 }
1021
1022
1023 /*!\fn QSecureLineEdit::clearModified()
1024
1025 Use setModified(false) instead.
1026
1027     \sa isModified()
1028 */
1029
1030
1031 /*!
1032     \property QSecureLineEdit::hasSelectedText
1033     \brief whether there is any text selected
1034
1035     hasSelectedText() returns true if some or all of the text has been
1036     selected by the user; otherwise returns false.
1037
1038     \sa selectedText()
1039 */
1040
1041
1042 bool QSecureLineEdit::hasSelectedText() const
1043 {
1044     Q_D(const QSecureLineEdit);
1045     return d->hasSelectedText();
1046 }
1047
1048 /*!
1049     \property QSecureLineEdit::selectedText
1050     \brief the selected text
1051
1052     If there is no selected text this property's value is
1053     an empty string.
1054
1055     \sa hasSelectedText()
1056 */
1057
1058 secqstring QSecureLineEdit::selectedText() const
1059 {
1060     Q_D(const QSecureLineEdit);
1061     if (d->hasSelectedText())
1062         return d->text.substr(d->selstart, d->selend - d->selstart);
1063     return secqstring();
1064 }
1065
1066 /*!
1067     selectionStart() returns the index of the first selected character in the
1068     line edit or -1 if no text is selected.
1069
1070     \sa selectedText()
1071 */
1072
1073 int QSecureLineEdit::selectionStart() const
1074 {
1075     Q_D(const QSecureLineEdit);
1076     return d->hasSelectedText() ? d->selstart : -1;
1077 }
1078
1079
1080 #ifdef QT3_SUPPORT
1081
1082 /*!
1083     \fn void QSecureLineEdit::lostFocus()
1084
1085     This signal is emitted when the line edit has lost focus.
1086
1087     Use editingFinished() instead
1088     \sa editingFinished(), returnPressed()
1089 */
1090
1091 /*!
1092     Use isModified() instead.
1093 */
1094 bool QSecureLineEdit::edited() const { return isModified(); }
1095 /*!
1096     Use setModified()  or setText().
1097 */
1098 void QSecureLineEdit::setEdited(bool on) { setModified(on); }
1099
1100 /*!
1101     There exists no equivalent functionality in Qt 4.
1102 */
1103 int QSecureLineEdit::characterAt(int xpos, QChar *chr) const
1104 {
1105     Q_D(const QSecureLineEdit);
1106     int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin);
1107     if (chr && pos < (int) d->text.length())
1108         *chr = d->text.at(pos);
1109     return pos;
1110
1111 }
1112
1113 /*!
1114     Use selectedText() and selectionStart() instead.
1115 */
1116 bool QSecureLineEdit::getSelection(int *start, int *end)
1117 {
1118     Q_D(QSecureLineEdit);
1119     if (d->hasSelectedText() && start && end) {
1120         *start = d->selstart;
1121         *end = d->selend;
1122         return true;
1123     }
1124     return false;
1125 }
1126 #endif
1127
1128
1129 /*!
1130     Selects text from position \a start and for \a length characters.
1131     Negative lengths are allowed.
1132
1133     \sa deselect() selectAll() selectedText()
1134 */
1135
1136 void QSecureLineEdit::setSelection(int start, int length)
1137 {
1138     Q_D(QSecureLineEdit);
1139     if (start < 0 || start > (int)d->text.length()) {
1140         qWarning("QSecureLineEdit::setSelection: Invalid start position (%d)", start);
1141         return;
1142     } else {
1143         if (length > 0) {
1144             d->selstart = start;
1145             d->selend = qMin(start + length, (int)d->text.length());
1146             d->cursor = d->selend;
1147         } else {
1148             d->selstart = qMax(start + length, 0);
1149             d->selend = start;
1150             d->cursor = d->selstart;
1151         }
1152     }
1153
1154     if (d->hasSelectedText()){
1155         QStyleOptionFrameV2 opt;
1156         initStyleOption(&opt);
1157         if (!style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
1158             d->setCursorVisible(false);
1159     }
1160
1161     update();
1162     d->emitCursorPositionChanged();
1163 }
1164
1165
1166 /*!
1167     \property QSecureLineEdit::undoAvailable
1168     \brief whether undo is available
1169 */
1170
1171 bool QSecureLineEdit::isUndoAvailable() const
1172 {
1173     Q_D(const QSecureLineEdit);
1174     return d->isUndoAvailable();
1175 }
1176
1177 /*!
1178     \property QSecureLineEdit::redoAvailable
1179     \brief whether redo is available
1180 */
1181
1182 bool QSecureLineEdit::isRedoAvailable() const
1183 {
1184     Q_D(const QSecureLineEdit);
1185     return d->isRedoAvailable();
1186 }
1187
1188 /*!
1189     \property QSecureLineEdit::dragEnabled
1190     \brief whether the lineedit starts a drag if the user presses and
1191     moves the mouse on some selected text
1192
1193     Dragging is disabled by default.
1194 */
1195
1196 bool QSecureLineEdit::dragEnabled() const
1197 {
1198     Q_D(const QSecureLineEdit);
1199     return d->dragEnabled;
1200 }
1201
1202 void QSecureLineEdit::setDragEnabled(bool b)
1203 {
1204     Q_D(QSecureLineEdit);
1205     d->dragEnabled = b;
1206 }
1207
1208
1209 /*!
1210     \property QSecureLineEdit::acceptableInput
1211     \brief whether the input satisfies the inputMask and the
1212     validator.
1213
1214     \sa setInputMask(), setValidator()
1215 */
1216 bool QSecureLineEdit::hasAcceptableInput() const
1217 {
1218     Q_D(const QSecureLineEdit);
1219     return d->hasAcceptableInput(d->text);
1220 }
1221
1222 /*!
1223     \property QSecureLineEdit::inputMask
1224     \brief The validation input mask
1225
1226     If no mask is set, inputMask() returns an empty string.
1227
1228     Sets the QSecureLineEdit's validation mask. Validators can be used
1229     instead of, or in conjunction with masks; see setValidator().
1230
1231     Unset the mask and return to normal QSecureLineEdit operation by passing
1232     an empty string ("") or just calling setInputMask() with no
1233     arguments.
1234
1235     The table below shows the characters that can be used in an input mask.
1236     A space character, the default character for a blank, is needed for cases
1237     where a character is \e{permitted but not required}.
1238
1239     \table
1240     \header \i Character \i Meaning
1241     \row \i \c A \i ASCII alphabetic character required. A-Z, a-z.
1242     \row \i \c a \i ASCII alphabetic character permitted but not required.
1243     \row \i \c N \i ASCII alphanumeric character required. A-Z, a-z, 0-9.
1244     \row \i \c n \i ASCII alphanumeric character permitted but not required.
1245     \row \i \c X \i Any character required.
1246     \row \i \c x \i Any character permitted but not required.
1247     \row \i \c 9 \i ASCII digit required. 0-9.
1248     \row \i \c 0 \i ASCII digit permitted but not required.
1249     \row \i \c D \i ASCII digit required. 1-9.
1250     \row \i \c d \i ASCII digit permitted but not required (1-9).
1251     \row \i \c # \i ASCII digit or plus/minus sign permitted but not required.
1252     \row \i \c H \i Hexadecimal character required. A-F, a-f, 0-9.
1253     \row \i \c h \i Hexadecimal character permitted but not required.
1254     \row \i \c B \i Binary character required. 0-1.
1255     \row \i \c b \i Binary character permitted but not required.
1256     \row \i \c > \i All following alphabetic characters are uppercased.
1257     \row \i \c < \i All following alphabetic characters are lowercased.
1258     \row \i \c ! \i Switch off case conversion.
1259     \row \i \tt{\\} \i Use \tt{\\} to escape the special
1260                            characters listed above to use them as
1261                            separators.
1262     \endtable
1263
1264     The mask consists of a string of mask characters and separators,
1265     optionally followed by a semicolon and the character used for
1266     blanks. The blank characters are always removed from the text
1267     after editing.
1268
1269     Examples:
1270     \table
1271     \header \i Mask \i Notes
1272     \row \i \c 000.000.000.000;_ \i IP address; blanks are \c{_}.
1273     \row \i \c HH:HH:HH:HH:HH:HH;_ \i MAC address
1274     \row \i \c 0000-00-00 \i ISO Date; blanks are \c space
1275     \row \i \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \i License number;
1276     blanks are \c - and all (alphabetic) characters are converted to
1277     uppercase.
1278     \endtable
1279
1280     To get range control (e.g. for an IP address) use masks together
1281     with \link setValidator() validators\endlink.
1282
1283     \sa maxLength
1284 */
1285 QString QSecureLineEdit::inputMask() const
1286 {
1287     Q_D(const QSecureLineEdit);
1288     return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString());
1289 }
1290
1291 void QSecureLineEdit::setInputMask(const QString &inputMask)
1292 {
1293     Q_D(QSecureLineEdit);
1294     d->parseInputMask(inputMask);
1295     if (d->maskData)
1296         d->moveCursor(d->nextMaskBlank(0));
1297 }
1298
1299 /*!
1300     Selects all the text (i.e. highlights it) and moves the cursor to
1301     the end. This is useful when a default value has been inserted
1302     because if the user types before clicking on the widget, the
1303     selected text will be deleted.
1304
1305     \sa setSelection() deselect()
1306 */
1307
1308 void QSecureLineEdit::selectAll()
1309 {
1310     Q_D(QSecureLineEdit);
1311     d->selstart = d->selend = d->cursor = 0;
1312     d->moveCursor(d->text.length(), true);
1313 }
1314
1315 /*!
1316     Deselects any selected text.
1317
1318     \sa setSelection() selectAll()
1319 */
1320
1321 void QSecureLineEdit::deselect()
1322 {
1323     Q_D(QSecureLineEdit);
1324     d->deselect();
1325     d->finishChange();
1326 }
1327
1328
1329 /*!
1330     Deletes any selected text, inserts \a newText, and validates the
1331     result. If it is valid, it sets it as the new contents of the line
1332     edit.
1333
1334     \sa setText(), clear()
1335 */
1336 void QSecureLineEdit::insert(const secqstring &newText)
1337 {
1338 //     q->resetInputContext(); //#### FIX ME IN QT
1339     Q_D(QSecureLineEdit);
1340     int priorState = d->undoState;
1341     d->removeSelectedText();
1342     d->insert(newText);
1343     d->finishChange(priorState);
1344 }
1345
1346 /*!
1347     Clears the contents of the line edit.
1348
1349     \sa setText(), insert()
1350 */
1351 void QSecureLineEdit::clear()
1352 {
1353     Q_D(QSecureLineEdit);
1354     int priorState = d->undoState;
1355     resetInputContext();
1356     d->selstart = 0;
1357     d->selend = d->text.length();
1358     d->removeSelectedText();
1359     d->separate();
1360     d->finishChange(priorState, /*update*/false, /*edited*/false);
1361 }
1362
1363 /*!
1364     Undoes the last operation if undo is \link
1365     QSecureLineEdit::undoAvailable available\endlink. Deselects any current
1366     selection, and updates the selection start to the current cursor
1367     position.
1368 */
1369 void QSecureLineEdit::undo()
1370 {
1371     Q_D(QSecureLineEdit);
1372     resetInputContext();
1373     d->undo();
1374     d->finishChange(-1, true);
1375 }
1376
1377 /*!
1378     Redoes the last operation if redo is \link
1379     QSecureLineEdit::redoAvailable available\endlink.
1380 */
1381 void QSecureLineEdit::redo()
1382 {
1383     Q_D(QSecureLineEdit);
1384     resetInputContext();
1385     d->redo();
1386     d->finishChange();
1387 }
1388
1389
1390 /*!
1391     \property QSecureLineEdit::readOnly
1392     \brief whether the line edit is read only.
1393
1394     In read-only mode, the user can still copy the text to the
1395     clipboard, or drag and drop the text (if echoMode() is \l Normal),
1396     but cannot edit it.
1397
1398     QSecureLineEdit does not show a cursor in read-only mode.
1399
1400     \sa setEnabled()
1401 */
1402
1403 bool QSecureLineEdit::isReadOnly() const
1404 {
1405     Q_D(const QSecureLineEdit);
1406     return d->readOnly;
1407 }
1408
1409 void QSecureLineEdit::setReadOnly(bool enable)
1410 {
1411     Q_D(QSecureLineEdit);
1412     if (d->readOnly != enable) {
1413         d->readOnly = enable;
1414         setAttribute(Qt::WA_MacShowFocusRect, !d->readOnly);
1415 #ifndef QT_NO_CURSOR
1416         setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor);
1417 #endif
1418         update();
1419     }
1420 }
1421
1422
1423 #ifndef QT_NO_CLIPBOARD
1424 /*!
1425     Copies the selected text to the clipboard and deletes it, if there
1426     is any, and if echoMode() is \l Normal.
1427
1428     If the current validator disallows deleting the selected text,
1429     cut() will copy without deleting.
1430
1431     \sa copy() paste() setValidator()
1432 */
1433
1434 void QSecureLineEdit::cut()
1435 {
1436     if (hasSelectedText()) {
1437         copy();
1438         del();
1439     }
1440 }
1441
1442
1443 /*!
1444     Copies the selected text to the clipboard, if there is any, and if
1445     echoMode() is \l Normal.
1446
1447     \sa cut() paste()
1448 */
1449
1450 void QSecureLineEdit::copy() const
1451 {
1452     Q_D(const QSecureLineEdit);
1453     d->copy();
1454 }
1455
1456 /*!
1457     Inserts the clipboard's text at the cursor position, deleting any
1458     selected text, providing the line edit is not \link
1459     QSecureLineEdit::readOnly read-only\endlink.
1460
1461     If the end result would not be acceptable to the current
1462     \link setValidator() validator\endlink, nothing happens.
1463
1464     \sa copy() cut()
1465 */
1466
1467 void QSecureLineEdit::paste()
1468 {
1469     if(echoMode() == PasswordEchoOnEdit)
1470     {
1471         Q_D(QSecureLineEdit);
1472         setEchoMode(Normal);
1473         clear();
1474         d->resumePassword = true;
1475     }
1476     insert(QApplication::clipboard()->text(QClipboard::Clipboard));
1477 }
1478
1479 void QSecureLineEditPrivate::copy(bool clipboard) const
1480 {
1481     Q_Q(const QSecureLineEdit);
1482     QString t = q->selectedText();
1483     if (!t.isEmpty() && echoMode == QSecureLineEdit::Normal) {
1484         q->disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), q, 0);
1485         QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection);
1486         q->connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
1487                    q, SLOT(_q_clipboardChanged()));
1488     }
1489 }
1490
1491 #endif // !QT_NO_CLIPBOARD
1492
1493 /*! \reimp
1494 */
1495 bool QSecureLineEdit::event(QEvent * e)
1496 {
1497     Q_D(QSecureLineEdit);
1498     if (e->type() == QEvent::ShortcutOverride && !d->readOnly) {
1499         QKeyEvent* ke = (QKeyEvent*) e;
1500         if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
1501             || ke->modifiers() == Qt::KeypadModifier) {
1502             if (ke->key() < Qt::Key_Escape) {
1503                 ke->accept();
1504             } else {
1505                 switch (ke->key()) {
1506                 case Qt::Key_Delete:
1507                 case Qt::Key_Home:
1508                 case Qt::Key_End:
1509                 case Qt::Key_Backspace:
1510                 case Qt::Key_Left:
1511                 case Qt::Key_Right:
1512                     ke->accept();
1513                 default:
1514                     break;
1515                 }
1516             }
1517         } else if (ke->modifiers() & Qt::ControlModifier) {
1518             switch (ke->key()) {
1519 // Those are too frequently used for application functionality
1520 /*            case Qt::Key_A:
1521             case Qt::Key_B:
1522             case Qt::Key_D:
1523             case Qt::Key_E:
1524             case Qt::Key_F:
1525             case Qt::Key_H:
1526             case Qt::Key_K:
1527 */
1528             case Qt::Key_C:
1529             case Qt::Key_V:
1530             case Qt::Key_X:
1531             case Qt::Key_Y:
1532             case Qt::Key_Z:
1533             case Qt::Key_Left:
1534             case Qt::Key_Right:
1535 #if !defined(Q_WS_MAC)
1536             case Qt::Key_Insert:
1537             case Qt::Key_Delete:
1538 #endif
1539                 ke->accept();
1540             default:
1541                 break;
1542             }
1543         }
1544     } else if (e->type() == QEvent::Timer) {
1545         // should be timerEvent, is here for binary compatibility
1546         int timerId = ((QTimerEvent*)e)->timerId();
1547         if (timerId == d->cursorTimer) {
1548             QStyleOptionFrameV2 opt;
1549             initStyleOption(&opt);
1550             if(!hasSelectedText()
1551                || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
1552                 d->setCursorVisible(!d->cursorVisible);
1553 #ifndef QT_NO_DRAGANDDROP
1554         } else if (timerId == d->dndTimer.timerId()) {
1555             d->drag();
1556 #endif
1557         }
1558         else if (timerId == d->tripleClickTimer.timerId())
1559             d->tripleClickTimer.stop();
1560 #ifdef QT_KEYPAD_NAVIGATION
1561         else if (timerId == d->deleteAllTimer.timerId()) {
1562             d->deleteAllTimer.stop();
1563             clear();
1564         }
1565 #endif
1566     } else if (e->type() == QEvent::ContextMenu) {
1567 #ifndef QT_NO_IM
1568         if (d->composeMode())
1569             return true;
1570 #endif
1571         d->separate();
1572     } else if (e->type() == QEvent::WindowActivate) {
1573         QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate()));
1574     }
1575 #ifdef QT_KEYPAD_NAVIGATION
1576     if (QApplication::keypadNavigationEnabled()) {
1577         if ((e->type() == QEvent::KeyPress) || (e->type() == QEvent::KeyRelease)) {
1578             QKeyEvent *ke = (QKeyEvent *)e;
1579             if (ke->key() == Qt::Key_Back) {
1580                 if (ke->isAutoRepeat()) {
1581                     // Swallow it. We don't want back keys running amok.
1582                     ke->accept();
1583                     return true;
1584                 }
1585                 if ((e->type() == QEvent::KeyRelease)
1586                     && !isReadOnly()
1587                     && d->deleteAllTimer.isActive()) {
1588                     d->deleteAllTimer.stop();
1589                     backspace();
1590                     ke->accept();
1591                     return true;
1592                 }
1593             }
1594         } else if (e->type() == QEvent::EnterEditFocus) {
1595             end(false);
1596             if (!d->cursorTimer) {
1597                 int cft = QApplication::cursorFlashTime();
1598                 d->cursorTimer = cft ? startTimer(cft/2) : -1;
1599             }
1600         } else if (e->type() == QEvent::LeaveEditFocus) {
1601             d->setCursorVisible(false);
1602             if (d->cursorTimer > 0)
1603                 killTimer(d->cursorTimer);
1604             d->cursorTimer = 0;
1605
1606             if (!d->emitingEditingFinished) {
1607                 if (hasAcceptableInput() || d->fixup()) {
1608                     d->emitingEditingFinished = true;
1609                     emit editingFinished();
1610                     d->emitingEditingFinished = false;
1611                 }
1612             }
1613         }
1614     }
1615 #endif
1616     return QWidget::event(e);
1617 }
1618
1619 /*! \reimp
1620 */
1621 void QSecureLineEdit::mousePressEvent(QMouseEvent* e)
1622 {
1623     Q_D(QSecureLineEdit);
1624     if (d->sendMouseEventToInputContext(e))
1625         return;
1626     if (e->button() == Qt::RightButton)
1627         return;
1628 #ifdef QT_KEYPAD_NAVIGATION
1629     if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1630         setEditFocus(true);
1631         // Get the completion list to pop up.
1632         if (d->completer)
1633             d->completer->complete();
1634     }
1635 #endif
1636     if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
1637          QApplication::startDragDistance()) {
1638         selectAll();
1639         return;
1640     }
1641     bool mark = e->modifiers() & Qt::ShiftModifier;
1642     int cursor = d->xToPos(e->pos().x());
1643 #ifndef QT_NO_DRAGANDDROP
1644     if (!mark && d->dragEnabled && d->echoMode == Normal &&
1645          e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) {
1646         d->cursor = cursor;
1647         update();
1648         d->dndPos = e->pos();
1649         if (!d->dndTimer.isActive())
1650             d->dndTimer.start(QApplication::startDragTime(), this);
1651         d->emitCursorPositionChanged();
1652     } else
1653 #endif
1654     {
1655         d->moveCursor(cursor, mark);
1656     }
1657 }
1658
1659 /*! \reimp
1660 */
1661 void QSecureLineEdit::mouseMoveEvent(QMouseEvent * e)
1662 {
1663     Q_D(QSecureLineEdit);
1664     if (d->sendMouseEventToInputContext(e))
1665         return;
1666
1667     if (e->buttons() & Qt::LeftButton) {
1668 #ifndef QT_NO_DRAGANDDROP
1669         if (d->dndTimer.isActive()) {
1670             if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
1671                 d->drag();
1672         } else
1673 #endif
1674         {
1675             d->moveCursor(d->xToPos(e->pos().x()), true);
1676         }
1677     }
1678 }
1679
1680 /*! \reimp
1681 */
1682 void QSecureLineEdit::mouseReleaseEvent(QMouseEvent* e)
1683 {
1684     Q_D(QSecureLineEdit);
1685     if (d->sendMouseEventToInputContext(e))
1686         return;
1687 #ifndef QT_NO_DRAGANDDROP
1688     if (e->button() == Qt::LeftButton) {
1689         if (d->dndTimer.isActive()) {
1690             d->dndTimer.stop();
1691             deselect();
1692             return;
1693         }
1694     }
1695 #endif
1696 #ifndef QT_NO_CLIPBOARD
1697     if (QApplication::clipboard()->supportsSelection()) {
1698         if (e->button() == Qt::LeftButton) {
1699             d->copy(false);
1700         } else if (!d->readOnly && e->button() == Qt::MidButton) {
1701             d->deselect();
1702             insert(QApplication::clipboard()->text(QClipboard::Selection));
1703         }
1704     }
1705 #endif
1706 }
1707
1708 /*! \reimp
1709 */
1710 void QSecureLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
1711 {
1712     Q_D(QSecureLineEdit);
1713     if (d->sendMouseEventToInputContext(e))
1714         return;
1715     if (e->button() == Qt::LeftButton) {
1716         deselect();
1717         d->cursor = d->xToPos(e->pos().x());
1718         d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords);
1719         // ## text layout should support end of words.
1720         int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords);
1721         while (end > d->cursor && d->text[end-1].isSpace())
1722             --end;
1723         d->moveCursor(end, true);
1724         d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
1725         d->tripleClick = e->pos();
1726     }
1727 }
1728
1729 /*!
1730     \fn void  QSecureLineEdit::returnPressed()
1731
1732     This signal is emitted when the Return or Enter key is pressed.
1733     Note that if there is a validator() or inputMask() set on the line
1734     edit, the returnPressed() signal will only be emitted if the input
1735     follows the inputMask() and the validator() returns
1736     QValidator::Acceptable.
1737 */
1738
1739 /*!
1740     \fn void  QSecureLineEdit::editingFinished()
1741
1742     This signal is emitted when the Return or Enter key is pressed or
1743     the line edit loses focus. Note that if there is a validator() or
1744     inputMask() set on the line edit and enter/return is pressed, the
1745     editingFinished() signal will only be emitted if the input follows
1746     the inputMask() and the validator() returns QValidator::Acceptable.
1747 */
1748
1749 /*!
1750     Converts the given key press \a event into a line edit action.
1751
1752     If Return or Enter is pressed and the current text is valid (or
1753     can be \link QValidator::fixup() made valid\endlink by the
1754     validator), the signal returnPressed() is emitted.
1755
1756     The default key bindings are listed in the class's detailed
1757     description.
1758 */
1759
1760 void QSecureLineEdit::keyPressEvent(QKeyEvent *event)
1761 {
1762     Q_D(QSecureLineEdit);
1763
1764 #ifndef QT_NO_COMPLETER
1765     if (d->completer
1766         && d->completer->popup()
1767         && d->completer->popup()->isVisible()) {
1768         // The following keys are forwarded by the completer to the widget
1769         // Ignoring the events lets the completer provide suitable default behavior
1770        switch (event->key()) {
1771        case Qt::Key_Escape:
1772             event->ignore();
1773             return;
1774        case Qt::Key_Enter:
1775        case Qt::Key_Return:
1776        case Qt::Key_F4:
1777 #ifdef QT_KEYPAD_NAVIGATION
1778        case Qt::Key_Select:
1779            if (!QApplication::keypadNavigationEnabled())
1780                break;
1781 #endif
1782            d->completer->popup()->hide(); // just hide. will end up propagating to parent
1783        default:
1784            break; // normal key processing
1785        }
1786     }
1787 #endif // QT_NO_COMPLETER
1788
1789 #ifdef QT_KEYPAD_NAVIGATION
1790     bool select = false;
1791     switch (event->key()) {
1792         case Qt::Key_Select:
1793             if (QApplication::keypadNavigationEnabled()) {
1794                 if (hasEditFocus()) {
1795                     setEditFocus(false);
1796                     if (d->completer && d->completer->popup()->isVisible())
1797                         d->completer->popup()->hide();
1798                     select = true;
1799                 }
1800             }
1801             break;
1802         case Qt::Key_Back:
1803         case Qt::Key_No:
1804             if (!QApplication::keypadNavigationEnabled() || !hasEditFocus()) {
1805                 event->ignore();
1806                 return;
1807             }
1808             break;
1809         default:
1810             if (QApplication::keypadNavigationEnabled()) {
1811                 if (!hasEditFocus() && !(event->modifiers() & Qt::ControlModifier)) {
1812                     if (!event->text().isEmpty() && event->text().at(0).isPrint()
1813                         && !isReadOnly())
1814                     {
1815                         setEditFocus(true);
1816                         clear();
1817                     } else {
1818                         event->ignore();
1819                         return;
1820                     }
1821                 }
1822             }
1823     }
1824
1825
1826
1827     if (QApplication::keypadNavigationEnabled() && !select && !hasEditFocus()) {
1828         setEditFocus(true);
1829         if (event->key() == Qt::Key_Select)
1830             return; // Just start. No action.
1831     }
1832 #endif
1833
1834
1835     if(echoMode() == PasswordEchoOnEdit &&
1836        !isReadOnly() &&
1837        !event->text().isEmpty() &&
1838 #ifdef QT_KEYPAD_NAVIGATION
1839        event->key() != Qt::Key_Select &&
1840        event->key() != Qt::Key_Up &&
1841        event->key() != Qt::Key_Down &&
1842        event->key() != Qt::Key_Back &&
1843 #endif
1844        !(event->modifiers() & Qt::ControlModifier))
1845     {
1846         setEchoMode(Normal);
1847         clear();
1848         d->resumePassword = true;
1849     }
1850
1851     d->setCursorVisible(true);
1852     if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
1853         if (hasAcceptableInput() || d->fixup()) {
1854             emit returnPressed();
1855             d->emitingEditingFinished = true;
1856             emit editingFinished();
1857             d->emitingEditingFinished = false;
1858         }
1859         event->ignore();
1860         return;
1861     }
1862     bool unknown = false;
1863
1864     if (false) {
1865     }
1866 #ifndef QT_NO_SHORTCUT
1867     else if (event == QKeySequence::Undo) {
1868         if (!d->readOnly)
1869             undo();
1870     }
1871     else if (event == QKeySequence::Redo) {
1872         if (!d->readOnly)
1873             redo();
1874     }
1875     else if (event == QKeySequence::SelectAll) {
1876         selectAll();
1877     }
1878 #ifndef QT_NO_CLIPBOARD
1879     else if (event == QKeySequence::Copy) {
1880         copy();
1881     }
1882     else if (event == QKeySequence::Paste) {
1883         if (!d->readOnly)
1884             paste();
1885     }
1886     else if (event == QKeySequence::Cut) {
1887         if (!d->readOnly) {
1888             cut();
1889         }
1890     }
1891     else if (event == QKeySequence::DeleteEndOfLine) {
1892         if (!d->readOnly) {
1893             setSelection(d->cursor, d->text.size());
1894             copy();
1895             del();
1896         }
1897     }
1898 #endif //QT_NO_CLIPBOARD
1899     else if (event == QKeySequence::MoveToStartOfLine) {
1900         home(0);
1901     }
1902     else if (event == QKeySequence::MoveToEndOfLine) {
1903         end(0);
1904     }
1905     else if (event == QKeySequence::SelectStartOfLine) {
1906         home(1);
1907     }
1908     else if (event == QKeySequence::SelectEndOfLine) {
1909         end(1);
1910     }
1911     else if (event == QKeySequence::MoveToNextChar) {
1912 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
1913         if (d->hasSelectedText()) {
1914 #else
1915         if (d->hasSelectedText() && d->completer
1916             && d->completer->completionMode() == QCompleter::InlineCompletion) {
1917 #endif
1918             d->moveCursor(d->selend, false);
1919         } else {
1920             cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1921         }
1922     }
1923     else if (event == QKeySequence::SelectNextChar) {
1924         cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1925     }
1926     else if (event == QKeySequence::MoveToPreviousChar) {
1927 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
1928         if (d->hasSelectedText()) {
1929 #else
1930         if (d->hasSelectedText() && d->completer
1931             && d->completer->completionMode() == QCompleter::InlineCompletion) {
1932 #endif
1933             d->moveCursor(d->selstart, false);
1934         } else {
1935             cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1936         }
1937     }
1938     else if (event == QKeySequence::SelectPreviousChar) {
1939         cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1940     }
1941     else if (event == QKeySequence::MoveToNextWord) {
1942         if (echoMode() == Normal)
1943             layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
1944         else
1945             layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
1946     }
1947     else if (event == QKeySequence::MoveToPreviousWord) {
1948         if (echoMode() == Normal)
1949             layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
1950         else if (!d->readOnly) {
1951             layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
1952         }
1953     }
1954     else if (event == QKeySequence::SelectNextWord) {
1955         if (echoMode() == Normal)
1956             layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
1957         else
1958             layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
1959     }
1960     else if (event == QKeySequence::SelectPreviousWord) {
1961         if (echoMode() == Normal)
1962             layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
1963         else
1964             layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
1965     }
1966     else if (event == QKeySequence::Delete) {
1967         if (!d->readOnly)
1968             del();
1969     }
1970     else if (event == QKeySequence::DeleteEndOfWord) {
1971         if (!d->readOnly) {
1972             cursorWordForward(true);
1973             del();
1974         }
1975     }
1976     else if (event == QKeySequence::DeleteStartOfWord) {
1977         if (!d->readOnly) {
1978             cursorWordBackward(true);
1979             del();
1980         }
1981     }
1982 #endif // QT_NO_SHORTCUT
1983     else {
1984 #ifdef Q_WS_MAC
1985         if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
1986             Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
1987             if (myModifiers & Qt::ShiftModifier) {
1988                 if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
1989                         || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
1990                         || myModifiers == Qt::ShiftModifier) {
1991
1992                     event->key() == Qt::Key_Up ? home(1) : end(1);
1993                 }
1994             } else {
1995                 if ((myModifiers == Qt::ControlModifier
1996                      || myModifiers == Qt::AltModifier
1997                      || myModifiers == Qt::NoModifier)) {
1998                     event->key() == Qt::Key_Up ? home(0) : end(0);
1999                 }
2000             }
2001         }
2002 #endif
2003         if (event->modifiers() & Qt::ControlModifier) {
2004             switch (event->key()) {
2005             case Qt::Key_Backspace:
2006                 if (!d->readOnly) {
2007                     cursorWordBackward(true);
2008                     del();
2009                 }
2010                 break;
2011 #ifndef QT_NO_COMPLETER
2012             case Qt::Key_Up:
2013             case Qt::Key_Down:
2014                 d->complete(event->key());
2015                 break;
2016 #endif
2017 #if defined(Q_WS_X11)
2018             case Qt::Key_E:
2019                 end(0);
2020                 break;
2021
2022             case Qt::Key_U:
2023                 if (!d->readOnly) {
2024                     setSelection(0, d->text.size());
2025 #ifndef QT_NO_CLIPBOARD
2026                     copy();
2027 #endif
2028                     del();
2029                 }
2030             break;
2031 #endif
2032             default:
2033                 unknown = true;
2034             }
2035         } else { // ### check for *no* modifier
2036             switch (event->key()) {
2037             case Qt::Key_Backspace:
2038                 if (!d->readOnly) {
2039                     backspace();
2040 #ifndef QT_NO_COMPLETER
2041                     d->complete(Qt::Key_Backspace);
2042 #endif
2043                 }
2044                 break;
2045 #ifdef QT_KEYPAD_NAVIGATION
2046             case Qt::Key_Back:
2047                 if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
2048                     && !isReadOnly()) {
2049                     if (text().length() == 0) {
2050                         setText(d->origText);
2051
2052                         if (d->resumePassword)
2053                         {
2054                             setEchoMode(PasswordEchoOnEdit);
2055                             d->resumePassword = false;
2056                         }
2057
2058                         setEditFocus(false);
2059                     } else if (!d->deleteAllTimer.isActive()) {
2060                         d->deleteAllTimer.start(750, this);
2061                     }
2062                 } else {
2063                     unknown = true;
2064                 }
2065                 break;
2066 #endif
2067
2068             default:
2069                 unknown = true;
2070             }
2071         }
2072     }
2073
2074     if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
2075         setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
2076         d->updateTextLayout();
2077         update();
2078         unknown = false;
2079     }
2080
2081     if (unknown && !d->readOnly) {
2082         QString t = event->text();
2083         if (!t.isEmpty() && t.at(0).isPrint()) {
2084             insert( secqstring( t.begin(), t.end() ) );
2085             // PENDING(marc) wipe 't' here?
2086             // wipe( const_cast<QChar*>( t.constData() ), t.length() );
2087 #ifndef QT_NO_COMPLETER
2088             d->complete(event->key());
2089 #endif
2090             event->accept();
2091             return;
2092         }
2093     }
2094
2095     if (unknown)
2096         event->ignore();
2097     else
2098         event->accept();
2099 }
2100
2101 /*!
2102   \since 4.4
2103
2104   Returns a rectangle that includes the lineedit cursor.
2105 */
2106 QRect QSecureLineEdit::cursorRect() const
2107 {
2108     Q_D(const QSecureLineEdit);
2109     return d->cursorRect();
2110 }
2111
2112 /*!
2113   This function is not intended as polymorphic usage. Just a shared code
2114   fragment that calls QInputContext::mouseHandler for this
2115   class.
2116 */
2117 bool QSecureLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
2118 {
2119 #if !defined QT_NO_IM
2120     Q_Q(QSecureLineEdit);
2121     if ( composeMode() ) {
2122         int tmp_cursor = xToPos(e->pos().x());
2123         int mousePos = tmp_cursor - cursor;
2124         if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) {
2125             mousePos = -1;
2126             // don't send move events outside the preedit area
2127             if ( e->type() == QEvent::MouseMove )
2128                 return true;
2129         }
2130
2131         QInputContext *qic = q->inputContext();
2132         if ( qic )
2133             // may be causing reset() in some input methods
2134             qic->mouseHandler(mousePos, e);
2135         if (!textLayout.preeditAreaText().isEmpty())
2136             return true;
2137     }
2138 #else
2139     Q_UNUSED(e);
2140 #endif
2141
2142     return false;
2143 }
2144
2145 /*! \reimp
2146  */
2147 void QSecureLineEdit::inputMethodEvent(QInputMethodEvent *e)
2148 {
2149     Q_D(QSecureLineEdit);
2150     if (d->readOnly) {
2151         e->ignore();
2152         return;
2153     }
2154
2155
2156     if(echoMode() == PasswordEchoOnEdit)
2157     {
2158         setEchoMode(Normal);
2159         clear();
2160         d->resumePassword = true;
2161     }
2162
2163
2164 #ifdef QT_KEYPAD_NAVIGATION
2165     // Focus in if currently in navigation focus on the widget
2166     // Only focus in on preedits, to allow input methods to
2167     // commit text as they focus out without interfering with focus
2168     if (QApplication::keypadNavigationEnabled() &&
2169             hasFocus() && !hasEditFocus()
2170             && !e->preeditString().isEmpty()) {
2171         setEditFocus(true);
2172         selectAll();        // so text is replaced rather than appended to
2173     }
2174 #endif
2175
2176     int priorState = d->undoState;
2177     d->removeSelectedText();
2178
2179     int c = d->cursor; // cursor position after insertion of commit string
2180     if (e->replacementStart() <= 0)
2181         c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength());
2182
2183     d->cursor += e->replacementStart();
2184
2185     // insert commit string
2186     if (e->replacementLength()) {
2187         d->selstart = d->cursor;
2188         d->selend = d->selstart + e->replacementLength();
2189         d->removeSelectedText();
2190     }
2191     const QString commitString = e->commitString();
2192     if (!commitString.isEmpty())
2193         d->insert(secqstring(commitString.begin(), commitString.end()));
2194
2195     d->cursor = c;
2196
2197     d->textLayout.setPreeditArea(d->cursor, e->preeditString());
2198     d->preeditCursor = e->preeditString().length();
2199     d->hideCursor = false;
2200     QList<QTextLayout::FormatRange> formats;
2201     for (int i = 0; i < e->attributes().size(); ++i) {
2202         const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2203         if (a.type == QInputMethodEvent::Cursor) {
2204             d->preeditCursor = a.start;
2205             d->hideCursor = !a.length;
2206         } else if (a.type == QInputMethodEvent::TextFormat) {
2207             QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
2208             if (f.isValid()) {
2209                 QTextLayout::FormatRange o;
2210                 o.start = a.start + d->cursor;
2211                 o.length = a.length;
2212                 o.format = f;
2213                 formats.append(o);
2214             }
2215         }
2216     }
2217     d->textLayout.setAdditionalFormats(formats);
2218     d->updateTextLayout();
2219     update();
2220     if (!e->commitString().isEmpty())
2221         d->emitCursorPositionChanged();
2222     d->finishChange(priorState);
2223 #ifndef QT_NO_COMPLETER
2224     if (!e->commitString().isEmpty())
2225         d->complete(Qt::Key_unknown);
2226 #endif
2227 }
2228
2229 /*!\reimp
2230 */
2231 QVariant QSecureLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
2232 {
2233     Q_D(const QSecureLineEdit);
2234     switch(property) {
2235     case Qt::ImMicroFocus:
2236         return d->cursorRect();
2237     case Qt::ImFont:
2238         return font();
2239     case Qt::ImCursorPosition:
2240         return QVariant(d->cursor);
2241 #ifdef TEMPORARILY_REMOVED // PENDING(marc) insecure
2242     case Qt::ImSurroundingText:
2243         return QVariant(d->text);
2244     case Qt::ImCurrentSelection:
2245         return QVariant(selectedText());
2246 #endif
2247     default:
2248         return QVariant();
2249     }
2250 }
2251
2252 /*!\reimp
2253 */
2254
2255 void QSecureLineEdit::focusInEvent(QFocusEvent *e)
2256 {
2257     Q_D(QSecureLineEdit);
2258     if (e->reason() == Qt::TabFocusReason ||
2259          e->reason() == Qt::BacktabFocusReason  ||
2260          e->reason() == Qt::ShortcutFocusReason) {
2261         if (d->maskData)
2262             d->moveCursor(d->nextMaskBlank(0));
2263         else if (!d->hasSelectedText())
2264             selectAll();
2265     }
2266 #ifdef QT_KEYPAD_NAVIGATION
2267     if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason))
2268 #endif
2269     if (!d->cursorTimer) {
2270         int cft = QApplication::cursorFlashTime();
2271         d->cursorTimer = cft ? startTimer(cft/2) : -1;
2272     }
2273     QStyleOptionFrameV2 opt;
2274     initStyleOption(&opt);
2275     if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty())
2276        || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
2277         d->setCursorVisible(true);
2278 #ifdef Q_WS_MAC
2279     if (d->echoMode == Password || d->echoMode == NoEcho)
2280         qt_mac_secure_keyboard(true);
2281 #endif
2282 #ifdef QT_KEYPAD_NAVIGATION
2283     d->origText = d->text;
2284 #endif
2285 #ifndef QT_NO_COMPLETER
2286     if (d->completer) {
2287         d->completer->setWidget(this);
2288         QObject::connect(d->completer, SIGNAL(activated(QString)),
2289                          this, SLOT(setText(QString)));
2290         QObject::connect(d->completer, SIGNAL(highlighted(QString)),
2291                          this, SLOT(_q_completionHighlighted(QString)));
2292     }
2293 #endif
2294     update();
2295 }
2296
2297 /*!\reimp
2298 */
2299
2300 void QSecureLineEdit::focusOutEvent(QFocusEvent *e)
2301 {
2302     Q_D(QSecureLineEdit);
2303
2304
2305     if(d->resumePassword){
2306         setEchoMode(PasswordEchoOnEdit);
2307         d->resumePassword = false;
2308     }
2309
2310
2311     Qt::FocusReason reason = e->reason();
2312     if (reason != Qt::ActiveWindowFocusReason &&
2313         reason != Qt::PopupFocusReason)
2314         deselect();
2315
2316     d->setCursorVisible(false);
2317     if (d->cursorTimer > 0)
2318         killTimer(d->cursorTimer);
2319     d->cursorTimer = 0;
2320
2321 #ifdef QT_KEYPAD_NAVIGATION
2322     // editingFinished() is already emitted on LeaveEditFocus
2323     if (!QApplication::keypadNavigationEnabled())
2324 #endif
2325     if (reason != Qt::PopupFocusReason
2326         || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) {
2327         if (!d->emitingEditingFinished) {
2328             if (hasAcceptableInput() || d->fixup()) {
2329                 d->emitingEditingFinished = true;
2330                 emit editingFinished();
2331                 d->emitingEditingFinished = false;
2332             }
2333         }
2334 #ifdef QT3_SUPPORT
2335         emit lostFocus();
2336 #endif
2337     }
2338 #ifdef Q_WS_MAC
2339     if (d->echoMode == Password || d->echoMode == NoEcho)
2340         qt_mac_secure_keyboard(false);
2341 #endif
2342 #ifdef QT_KEYPAD_NAVIGATION
2343     d->origText = QString();
2344 #endif
2345 #ifndef QT_NO_COMPLETER
2346     if (d->completer) {
2347         QObject::disconnect(d->completer, 0, this, 0);
2348     }
2349 #endif
2350     update();
2351 }
2352
2353 /*!\reimp
2354 */
2355 void QSecureLineEdit::paintEvent(QPaintEvent *)
2356 {
2357     Q_D(QSecureLineEdit);
2358     QPainter p(this);
2359
2360     QRect r = rect();
2361     QPalette pal = palette();
2362
2363     QStyleOptionFrameV2 panel;
2364     initStyleOption(&panel);
2365     style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this);
2366     r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
2367     p.setClipRect(r);
2368
2369     QFontMetrics fm = fontMetrics();
2370     Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment));
2371     switch (va & Qt::AlignVertical_Mask) {
2372      case Qt::AlignBottom:
2373          d->vscroll = r.y() + r.height() - fm.height() - verticalMargin;
2374          break;
2375      case Qt::AlignTop:
2376          d->vscroll = r.y() + verticalMargin;
2377          break;
2378      default:
2379          //center
2380          d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2;
2381          break;
2382     }
2383     QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height());
2384     QTextLine line = d->textLayout.lineAt(0);
2385
2386     int cursor = d->cursor;
2387     if (d->preeditCursor != -1)
2388         cursor += d->preeditCursor;
2389     // locate cursor position
2390     int cix = qRound(line.cursorToX(cursor));
2391
2392     // horizontal scrolling
2393     int minLB = qMax(0, -fm.minLeftBearing());
2394     int minRB = qMax(0, -fm.minRightBearing());
2395
2396
2397     int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
2398     if ((minLB + widthUsed) <=  lineRect.width()) {
2399         switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
2400         case Qt::AlignRight:
2401             d->hscroll = widthUsed - lineRect.width() + 1;
2402             break;
2403         case Qt::AlignHCenter:
2404             d->hscroll = (widthUsed - lineRect.width()) / 2;
2405             break;
2406         default:
2407             // Left
2408             d->hscroll = 0;
2409             break;
2410         }
2411         d->hscroll -= minLB;
2412     } else if (cix - d->hscroll >= lineRect.width()) {
2413         d->hscroll = cix - lineRect.width() + 1;
2414     } else if (cix - d->hscroll < 0) {
2415         d->hscroll = cix;
2416     } else if (widthUsed - d->hscroll < lineRect.width()) {
2417         d->hscroll = widthUsed - lineRect.width() + 1;
2418     }
2419     // the y offset is there to keep the baseline constant in case we have script changes in the text.
2420     QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent - fm.ascent());
2421
2422     // draw text, selections and cursors
2423 #ifndef QT_NO_STYLE_STYLESHEET
2424     if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) {
2425         cssStyle->focusPalette(this, &panel, &pal);
2426     }
2427 #endif
2428     p.setPen(pal.text().color());
2429
2430     QVector<QTextLayout::FormatRange> selections;
2431 #ifdef QT_KEYPAD_NAVIGATION
2432     if (!QApplication::keypadNavigationEnabled() || hasEditFocus())
2433 #endif
2434     if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) {
2435         QTextLayout::FormatRange o;
2436         if (d->selstart < d->selend) {
2437             o.start = d->selstart;
2438             o.length = d->selend - d->selstart;
2439             o.format.setBackground(pal.brush(QPalette::Highlight));
2440             o.format.setForeground(pal.brush(QPalette::HighlightedText));
2441         } else {
2442             // mask selection
2443             o.start = d->cursor;
2444             o.length = 1;
2445             o.format.setBackground(pal.brush(QPalette::Text));
2446             o.format.setForeground(pal.brush(QPalette::Window));
2447         }
2448         selections.append(o);
2449     }
2450
2451     // Asian users see an IM selection text as cursor on candidate
2452     // selection phase of input method, so the ordinary cursor should be
2453     // invisible if we have a preedit string.
2454     d->textLayout.draw(&p, topLeft, selections, r);
2455     if (d->cursorVisible && !d->readOnly && !d->hideCursor)
2456         d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth));
2457 }
2458
2459
2460 #ifndef QT_NO_DRAGANDDROP
2461 /*!\reimp
2462 */
2463 void QSecureLineEdit::dragMoveEvent(QDragMoveEvent *e)
2464 {
2465     Q_D(QSecureLineEdit);
2466     if (!d->readOnly && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
2467         e->acceptProposedAction();
2468         d->cursor = d->xToPos(e->pos().x());
2469         d->cursorVisible = true;
2470         update();
2471         d->emitCursorPositionChanged();
2472     }
2473 }
2474
2475 /*!\reimp */
2476 void QSecureLineEdit::dragEnterEvent(QDragEnterEvent * e)
2477 {
2478     QSecureLineEdit::dragMoveEvent(e);
2479 }
2480
2481 /*!\reimp */
2482 void QSecureLineEdit::dragLeaveEvent(QDragLeaveEvent *)
2483 {
2484     Q_D(QSecureLineEdit);
2485     if (d->cursorVisible) {
2486         d->cursorVisible = false;
2487         update();
2488     }
2489 }
2490
2491 /*!\reimp */
2492 void QSecureLineEdit::dropEvent(QDropEvent* e)
2493 {
2494     Q_D(QSecureLineEdit);
2495     QString str = e->mimeData()->text();
2496
2497     if (!str.isNull() && !d->readOnly) {
2498         if (e->source() == this && e->dropAction() == Qt::CopyAction)
2499             deselect();
2500         d->cursor =d->xToPos(e->pos().x());
2501         int selStart = d->cursor;
2502         int oldSelStart = d->selstart;
2503         int oldSelEnd = d->selend;
2504         d->cursorVisible = false;
2505         e->acceptProposedAction();
2506         insert(str);
2507         if (e->source() == this) {
2508             if (e->dropAction() == Qt::MoveAction) {
2509                 if (selStart > oldSelStart && selStart <= oldSelEnd)
2510                     setSelection(oldSelStart, str.length());
2511                 else if (selStart > oldSelEnd)
2512                     setSelection(selStart - str.length(), str.length());
2513                 else
2514                     setSelection(selStart, str.length());
2515             } else {
2516                 setSelection(selStart, str.length());
2517             }
2518         }
2519     } else {
2520         e->ignore();
2521         update();
2522     }
2523 }
2524
2525 void QSecureLineEditPrivate::drag()
2526 {
2527     Q_Q(QSecureLineEdit);
2528     dndTimer.stop();
2529     QMimeData *data = new QMimeData;
2530     data->setText(q->selectedText());
2531     QDrag *drag = new QDrag(q);
2532     drag->setMimeData(data);
2533     Qt::DropAction action = drag->start();
2534     if (action == Qt::MoveAction && !readOnly && drag->target() != q) {
2535         int priorState = undoState;
2536         removeSelectedText();
2537         finishChange(priorState);
2538     }
2539 }
2540
2541 #endif // QT_NO_DRAGANDDROP
2542
2543 #ifndef QT_NO_CONTEXTMENU
2544 /*!
2545     Shows the standard context menu created with
2546     createStandardContextMenu().
2547
2548     If you do not want the line edit to have a context menu, you can set
2549     its \l contextMenuPolicy to Qt::NoContextMenu. If you want to
2550     customize the context menu, reimplement this function. If you want
2551     to extend the standard context menu, reimplement this function, call
2552     createStandardContextMenu() and extend the menu returned.
2553
2554     \snippet doc/src/snippets/code/src.gui.widgets.qsecurelineedit.cpp 0
2555
2556     The \a event parameter is used to obtain the position where
2557     the mouse cursor was when the event was generated.
2558
2559     \sa setContextMenuPolicy()
2560 */
2561 void QSecureLineEdit::contextMenuEvent(QContextMenuEvent *event)
2562 {
2563     QPointer<QMenu> menu = createStandardContextMenu();
2564     menu->exec(event->globalPos());
2565     delete menu;
2566 }
2567
2568 #if defined(Q_WS_WIN)
2569     extern bool qt_use_rtl_extensions;
2570 #endif
2571
2572 /*!  This function creates the standard context menu which is shown
2573         when the user clicks on the line edit with the right mouse
2574         button. It is called from the default contextMenuEvent() handler.
2575         The popup menu's ownership is transferred to the caller.
2576 */
2577
2578 QMenu *QSecureLineEdit::createStandardContextMenu()
2579 {
2580     Q_D(QSecureLineEdit);
2581     if (!d->actions[QSecureLineEditPrivate::UndoAct]) {
2582         d->actions[QSecureLineEditPrivate::UndoAct] = new QAction(QSecureLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo), this);
2583         QObject::connect(d->actions[QSecureLineEditPrivate::UndoAct], SIGNAL(triggered()), this, SLOT(undo()));
2584         d->actions[QSecureLineEditPrivate::RedoAct] = new QAction(QSecureLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo), this);
2585         QObject::connect(d->actions[QSecureLineEditPrivate::RedoAct], SIGNAL(triggered()), this, SLOT(redo()));
2586         //popup->insertSeparator();
2587 #ifndef QT_NO_CLIPBOARD
2588         d->actions[QSecureLineEditPrivate::CutAct] = new QAction(QSecureLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut), this);
2589         QObject::connect(d->actions[QSecureLineEditPrivate::CutAct], SIGNAL(triggered()), this, SLOT(cut()));
2590         d->actions[QSecureLineEditPrivate::CopyAct] = new QAction(QSecureLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy), this);
2591         QObject::connect(d->actions[QSecureLineEditPrivate::CopyAct], SIGNAL(triggered()), this, SLOT(copy()));
2592         d->actions[QSecureLineEditPrivate::PasteAct] = new QAction(QSecureLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste), this);
2593         QObject::connect(d->actions[QSecureLineEditPrivate::PasteAct], SIGNAL(triggered()), this, SLOT(paste()));
2594 #endif
2595         d->actions[QSecureLineEditPrivate::ClearAct] = new QAction(QSecureLineEdit::tr("Delete"), this);
2596         QObject::connect(d->actions[QSecureLineEditPrivate::ClearAct], SIGNAL(triggered()), this, SLOT(_q_deleteSelected()));
2597         //popup->insertSeparator();
2598         d->actions[QSecureLineEditPrivate::SelectAllAct] = new QAction(QSecureLineEdit::tr("Select All")
2599                                                                  + ACCEL_KEY(QKeySequence::SelectAll)
2600                                                                  , this);
2601         QObject::connect(d->actions[QSecureLineEditPrivate::SelectAllAct], SIGNAL(triggered()), this, SLOT(selectAll()));
2602     }
2603     d->actions[QSecureLineEditPrivate::UndoAct]->setEnabled(d->isUndoAvailable());
2604     d->actions[QSecureLineEditPrivate::RedoAct]->setEnabled(d->isRedoAvailable());
2605 #ifndef QT_NO_CLIPBOARD
2606     d->actions[QSecureLineEditPrivate::CutAct]->setEnabled(!d->readOnly && d->hasSelectedText());
2607     d->actions[QSecureLineEditPrivate::CopyAct]->setEnabled(d->hasSelectedText());
2608     d->actions[QSecureLineEditPrivate::PasteAct]->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty());
2609 #else
2610     d->actions[QSecureLineEditPrivate::CutAct]->setEnabled(false);
2611     d->actions[QSecureLineEditPrivate::CopyAct]->setEnabled(false);
2612     d->actions[QSecureLineEditPrivate::PasteAct]->setEnabled(false);
2613 #endif
2614     d->actions[QSecureLineEditPrivate::ClearAct]->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText());
2615     d->actions[QSecureLineEditPrivate::SelectAllAct]->setEnabled(!d->text.isEmpty() && !d->allSelected());
2616
2617     QMenu *popup = new QMenu(this);
2618     popup->setObjectName(QLatin1String("qt_edit_menu"));
2619     popup->addAction(d->actions[QSecureLineEditPrivate::UndoAct]);
2620     popup->addAction(d->actions[QSecureLineEditPrivate::RedoAct]);
2621     popup->addSeparator();
2622     popup->addAction(d->actions[QSecureLineEditPrivate::CutAct]);
2623     popup->addAction(d->actions[QSecureLineEditPrivate::CopyAct]);
2624     popup->addAction(d->actions[QSecureLineEditPrivate::PasteAct]);
2625     popup->addAction(d->actions[QSecureLineEditPrivate::ClearAct]);
2626     popup->addSeparator();
2627     popup->addAction(d->actions[QSecureLineEditPrivate::SelectAllAct]);
2628 #if !defined(QT_NO_IM)
2629     QInputContext *qic = inputContext();
2630     if (qic) {
2631         QList<QAction *> imActions = qic->actions();
2632         for (int i = 0; i < imActions.size(); ++i)
2633             popup->addAction(imActions.at(i));
2634     }
2635 #endif
2636
2637 #if defined(Q_WS_WIN)
2638     if (!d->readOnly && qt_use_rtl_extensions) {
2639 #else
2640     if (!d->readOnly) {
2641 #endif
2642         popup->addSeparator();
2643         QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup);
2644         popup->addMenu(ctrlCharacterMenu);
2645     }
2646     return popup;
2647 }
2648 #endif // QT_NO_CONTEXTMENU
2649
2650 /*! \reimp */
2651 void QSecureLineEdit::changeEvent(QEvent *ev)
2652 {
2653     Q_D(QSecureLineEdit);
2654     if(ev->type() == QEvent::ActivationChange) {
2655         if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
2656             update();
2657     } else if (ev->type() == QEvent::FontChange || ev->type() == QEvent::StyleChange) {
2658         d->updateTextLayout();
2659     }
2660     QWidget::changeEvent(ev);
2661 }
2662
2663 void QSecureLineEditPrivate::_q_clipboardChanged()
2664 {
2665 }
2666
2667 void QSecureLineEditPrivate::_q_handleWindowActivate()
2668 {
2669     Q_Q(QSecureLineEdit);
2670     if (!q->hasFocus() && q->hasSelectedText())
2671         q->deselect();
2672 }
2673
2674 void QSecureLineEditPrivate::_q_deleteSelected()
2675 {
2676     Q_Q(QSecureLineEdit);
2677     if (!hasSelectedText())
2678         return;
2679
2680     int priorState = undoState;
2681     q->resetInputContext();
2682     removeSelectedText();
2683     separate();
2684     finishChange(priorState);
2685 }
2686 void QSecureLineEditPrivate::init(const secqstring& txt)
2687 {
2688     Q_Q(QSecureLineEdit);
2689 #ifndef QT_NO_CURSOR
2690     q->setCursor(Qt::IBeamCursor);
2691 #endif
2692     q->setFocusPolicy(Qt::StrongFocus);
2693     q->setAttribute(Qt::WA_InputMethodEnabled);
2694     //   Specifies that this widget can use more, but is able to survive on
2695     //   less, horizontal space; and is fixed vertically.
2696     q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
2697     q->setBackgroundRole(QPalette::Base);
2698     q->setAttribute(Qt::WA_KeyCompression);
2699     q->setMouseTracking(true);
2700     q->setAcceptDrops(true);
2701     text = txt;
2702     updateTextLayout();
2703     cursor = text.size();
2704
2705     q->setAttribute(Qt::WA_MacShowFocusRect);
2706 }
2707
2708 void QSecureLineEditPrivate::updateTextLayout()
2709 {
2710     // replace certain non-printable characters with spaces (to avoid
2711     // drawing boxes when using fonts that don't have glyphs for such
2712     // characters)
2713     Q_Q(QSecureLineEdit);
2714     secqstring str = q->displayText();
2715     QChar* uc = str.empty() ? 0 : &str[0] ;
2716     for (int i = 0; i < (int)str.size(); ++i) {
2717         if ((uc[i] < 0x20 && uc[i] != 0x09)
2718             || uc[i] == QChar::LineSeparator
2719             || uc[i] == QChar::ParagraphSeparator
2720             || uc[i] == QChar::ObjectReplacementCharacter)
2721             uc[i] = QChar(0x0020);
2722     }
2723     textLayout.setFont(q->font());
2724     // PENDING(marc) insecure (only when not in password mode)
2725     textLayout.setText( QString( str.data(), str.size() ) );
2726     QTextOption option;
2727     option.setTextDirection(q->layoutDirection());
2728     option.setFlags(QTextOption::IncludeTrailingSpaces);
2729     textLayout.setTextOption(option);
2730
2731     textLayout.beginLayout();
2732     QTextLine l = textLayout.createLine();
2733     textLayout.endLayout();
2734     ascent = qRound(l.ascent());
2735 }
2736
2737 int QSecureLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
2738 {
2739     QRect cr = adjustedContentsRect();
2740     x-= cr.x() - hscroll + horizontalMargin;
2741     QTextLine l = textLayout.lineAt(0);
2742     return l.xToCursor(x, betweenOrOn);
2743 }
2744
2745 QRect QSecureLineEditPrivate::cursorRect() const
2746 {
2747     Q_Q(const QSecureLineEdit);
2748     QRect cr = adjustedContentsRect();
2749     int cix = cr.x() - hscroll + horizontalMargin;
2750     QTextLine l = textLayout.lineAt(0);
2751     int c = cursor;
2752     if (preeditCursor != -1)
2753         c += preeditCursor;
2754     cix += qRound(l.cursorToX(c));
2755     int ch = qMin(cr.height(), q->fontMetrics().height() + 1);
2756     int w = q->style()->pixelMetric(QStyle::PM_TextCursorWidth);
2757     return QRect(cix-5, vscroll, w + 9, ch);
2758 }
2759
2760 QRect QSecureLineEditPrivate::adjustedContentsRect() const
2761 {
2762     Q_Q(const QSecureLineEdit);
2763     QStyleOptionFrameV2 opt;
2764     q->initStyleOption(&opt);
2765     return q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
2766 }
2767
2768 bool QSecureLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable
2769 {
2770 #ifndef QT_NO_VALIDATOR
2771     if (validator) {
2772         QString textCopy = text;
2773         int cursorCopy = cursor;
2774         validator->fixup(textCopy);
2775         if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
2776             if (textCopy != text || cursorCopy != cursor)
2777                 setText(textCopy, cursorCopy);
2778             return true;
2779         }
2780     }
2781 #endif
2782     return false;
2783 }
2784
2785
2786 void QSecureLineEditPrivate::moveCursor(int pos, bool mark)
2787 {
2788     Q_Q(QSecureLineEdit);
2789     if (pos != cursor) {
2790         separate();
2791         if (maskData)
2792             pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
2793     }
2794     bool fullUpdate = mark || hasSelectedText();
2795     if (mark) {
2796         int anchor;
2797         if (selend > selstart && cursor == selstart)
2798             anchor = selend;
2799         else if (selend > selstart && cursor == selend)
2800             anchor = selstart;
2801         else
2802             anchor = cursor;
2803         selstart = qMin(anchor, pos);
2804         selend = qMax(anchor, pos);
2805         updateTextLayout();
2806     } else {
2807         deselect();
2808     }
2809     if (fullUpdate) {
2810         cursor = pos;
2811         q->update();
2812     } else {
2813         setCursorVisible(false);
2814         cursor = pos;
2815         setCursorVisible(true);
2816         if (!adjustedContentsRect().contains(cursorRect()))
2817             q->update();
2818     }
2819     QStyleOptionFrameV2 opt;
2820     q->initStyleOption(&opt);
2821     if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q))
2822         setCursorVisible(false);
2823     if (mark || selDirty) {
2824         selDirty = false;
2825         emit q->selectionChanged();
2826     }
2827     emitCursorPositionChanged();
2828 }
2829
2830 void QSecureLineEditPrivate::finishChange(int validateFromState, bool update, bool edited)
2831 {
2832     Q_Q(QSecureLineEdit);
2833     bool lineDirty = selDirty;
2834     if (textDirty) {
2835         // do validation
2836         bool wasValidInput = validInput;
2837         validInput = true;
2838 #ifndef QT_NO_VALIDATOR
2839         if (validator) {
2840             validInput = false;
2841             QString textCopy = text;
2842             int cursorCopy = cursor;
2843             validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
2844             if (validInput) {
2845                 if (text != textCopy) {
2846                     setText(textCopy, cursorCopy);
2847                     return;
2848                 }
2849                 cursor = cursorCopy;
2850             }
2851         }
2852 #endif
2853         if (validateFromState >= 0 && wasValidInput && !validInput) {
2854             undo(validateFromState);
2855             history.resize(undoState);
2856             if (modifiedState > undoState)
2857                 modifiedState = -1;
2858             validInput = true;
2859             textDirty = false;
2860         }
2861         updateTextLayout();
2862         lineDirty |= textDirty;
2863         if (textDirty) {
2864             textDirty = false;
2865             secqstring actualText = maskData ? stripString(text) : text;
2866             if (edited)
2867                 emit q->textEdited(actualText);
2868             q->updateMicroFocus();
2869             emit q->textChanged(actualText);
2870 #ifndef QT_NO_COMPLETER
2871             if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion)
2872                 complete(-1); // update the popup on cut/paste/del
2873 #endif
2874         }
2875 #ifndef QT_NO_ACCESSIBILITY
2876         QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
2877 #endif
2878     }
2879     if (selDirty) {
2880         selDirty = false;
2881         emit q->selectionChanged();
2882     }
2883     if (lineDirty || update)
2884         q->update();
2885     emitCursorPositionChanged();
2886 }
2887
2888 void QSecureLineEditPrivate::emitCursorPositionChanged()
2889 {
2890     Q_Q(QSecureLineEdit);
2891     if (cursor != lastCursorPos) {
2892         const int oldLast = lastCursorPos;
2893         lastCursorPos = cursor;
2894         emit q->cursorPositionChanged(oldLast, cursor);
2895     }
2896 }
2897
2898 void QSecureLineEditPrivate::setText(const secqstring& txt, int pos, bool edited)
2899 {
2900     Q_Q(QSecureLineEdit);
2901     q->resetInputContext();
2902     deselect();
2903     secqstring oldText = text;
2904     if (maskData) {
2905         text = maskString(0, txt, true);
2906         text += clearString(text.size(), maxLength - text.size());
2907     } else {
2908         text = txt.empty() ? txt : txt.substr(0, maxLength);
2909     }
2910     history.clear();
2911     modifiedState =  undoState = 0;
2912     cursor = (pos < 0 || pos > text.size()) ? text.size() : pos;
2913     textDirty = (oldText != text);
2914     finishChange(-1, true, edited);
2915 }
2916
2917
2918 void QSecureLineEditPrivate::setCursorVisible(bool visible)
2919 {
2920     Q_Q(QSecureLineEdit);
2921     if ((bool)cursorVisible == visible)
2922         return;
2923     if (cursorTimer)
2924         cursorVisible = visible;
2925     QRect r = cursorRect();
2926     if (maskData)
2927         q->update();
2928     else
2929         q->update(r);
2930 }
2931
2932 void QSecureLineEditPrivate::addCommand(const Command& cmd)
2933 {
2934     if (separator && undoState && history[undoState-1].type != Separator) {
2935         history.resize(undoState + 2);
2936         history[undoState++] = Command(Separator, cursor, 0, selstart, selend);
2937     } else {
2938         history.resize(undoState + 1);
2939     }
2940     separator = false;
2941     history[undoState++] = cmd;
2942 }
2943
2944 void QSecureLineEditPrivate::insert(const secqstring& s)
2945 {
2946     if (hasSelectedText())
2947         addCommand(Command(SetSelection, cursor, 0, selstart, selend));
2948     if (maskData) {
2949         secqstring ms = maskString(cursor, s);
2950         for (int i = 0; i < (int) ms.length(); ++i) {
2951             addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i), -1, -1));
2952             addCommand(Command(Insert, cursor+i, ms.at(i), -1, -1));
2953         }
2954         text.replace(cursor, ms.length(), secqstring( ms.begin(), ms.end() ) );
2955         cursor += ms.length();
2956         cursor = nextMaskBlank(cursor);
2957     } else {
2958         int remaining = maxLength - text.size();
2959         text.insert(cursor, s.substr(0,remaining));
2960         for (int i = 0; i < (int) s.substr(0,remaining).size(); ++i)
2961             addCommand(Command(Insert, cursor++, s[i], -1, -1));
2962     }
2963     textDirty = true;
2964 }
2965
2966 void QSecureLineEditPrivate::del(bool wasBackspace)
2967 {
2968     if (cursor < (int) text.size()) {
2969         if (hasSelectedText())
2970             addCommand(Command(SetSelection, cursor, 0, selstart, selend));
2971         addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text[cursor], -1, -1));
2972         if (maskData) {
2973             text.replace(cursor, 1, clearString(cursor, 1));
2974             addCommand(Command(Insert, cursor, text[cursor], -1, -1));
2975         } else {
2976             text.erase(cursor, 1);
2977         }
2978         textDirty = true;
2979     }
2980 }
2981
2982 void QSecureLineEditPrivate::removeSelectedText()
2983 {
2984     if (selstart < selend && selend <= (int) text.size()) {
2985         separate();
2986         int i ;
2987         addCommand(Command(SetSelection, cursor, 0, selstart, selend));
2988         if (selstart <= cursor && cursor < selend) {
2989             // cursor is within the selection. Split up the commands
2990             // to be able to restore the correct cursor position
2991             for (i = cursor; i >= selstart; --i)
2992                 addCommand (Command(DeleteSelection, i, text[i], -1, 1));
2993             for (i = selend - 1; i > cursor; --i)
2994                 addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text[i], -1, -1));
2995         } else {
2996             for (i = selend-1; i >= selstart; --i)
2997                 addCommand (Command(RemoveSelection, i, text[i], -1, -1));
2998         }
2999         if (maskData) {
3000             text.replace(selstart, selend - selstart,  clearString(selstart, selend - selstart));
3001             for (int i = 0; i < selend - selstart; ++i)
3002                 addCommand(Command(Insert, selstart + i, text[selstart + i], -1, -1));
3003         } else {
3004             text.erase(selstart, selend - selstart);
3005         }
3006         if (cursor > selstart)
3007             cursor -= qMin(cursor, selend) - selstart;
3008         deselect();
3009         textDirty = true;
3010
3011         // adjust hscroll to avoid gap
3012         const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing());
3013         updateTextLayout();
3014         const QTextLine line = textLayout.lineAt(0);
3015         const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
3016         hscroll = qMin(hscroll, widthUsed);
3017     }
3018 }
3019
3020 void QSecureLineEditPrivate::parseInputMask(const QString &maskFields)
3021 {
3022     int delimiter = maskFields.indexOf(QLatin1Char(';'));
3023     if (maskFields.isEmpty() || delimiter == 0) {
3024         if (maskData) {
3025             delete [] maskData;
3026             maskData = 0;
3027             maxLength = 32767;
3028             setText(secqstring());
3029         }
3030         return;
3031     }
3032
3033     if (delimiter == -1) {
3034         blank = QLatin1Char(' ');
3035         inputMask = maskFields;
3036     } else {
3037         inputMask = maskFields.left(delimiter);
3038         blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
3039     }
3040
3041     // calculate maxLength / maskData length
3042     maxLength = 0;
3043     QChar c = 0;
3044     for (int i=0; i<inputMask.length(); i++) {
3045         c = inputMask.at(i);
3046         if (i > 0 && inputMask.at(i-1) == QLatin1Char('\\')) {
3047             maxLength++;
3048             continue;
3049         }
3050         if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
3051              c != QLatin1Char('<') && c != QLatin1Char('>') &&
3052              c != QLatin1Char('{') && c != QLatin1Char('}') &&
3053              c != QLatin1Char('[') && c != QLatin1Char(']'))
3054             maxLength++;
3055     }
3056
3057     delete [] maskData;
3058     maskData = new MaskInputData[maxLength];
3059
3060     MaskInputData::Casemode m = MaskInputData::NoCaseMode;
3061     c = 0;
3062     bool s;
3063     bool escape = false;
3064     int index = 0;
3065     for (int i = 0; i < inputMask.length(); i++) {
3066         c = inputMask.at(i);
3067         if (escape) {
3068             s = true;
3069             maskData[index].maskChar = c;
3070             maskData[index].separator = s;
3071             maskData[index].caseMode = m;
3072             index++;
3073             escape = false;
3074         } else if (c == QLatin1Char('<')) {
3075                 m = MaskInputData::Lower;
3076         } else if (c == QLatin1Char('>')) {
3077             m = MaskInputData::Upper;
3078         } else if (c == QLatin1Char('!')) {
3079             m = MaskInputData::NoCaseMode;
3080         } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
3081             switch (c.unicode()) {
3082             case 'A':
3083             case 'a':
3084             case 'N':
3085             case 'n':
3086             case 'X':
3087             case 'x':
3088             case '9':
3089             case '0':
3090             case 'D':
3091             case 'd':
3092             case '#':
3093             case 'H':
3094             case 'h':
3095             case 'B':
3096             case 'b':
3097                 s = false;
3098                 break;
3099             case '\\':
3100                 escape = true;
3101             default:
3102                 s = true;
3103                 break;
3104             }
3105
3106             if (!escape) {
3107                 maskData[index].maskChar = c;
3108                 maskData[index].separator = s;
3109                 maskData[index].caseMode = m;
3110                 index++;
3111             }
3112         }
3113     }
3114     setText(text);
3115 }
3116
3117
3118 /* checks if the key is valid compared to the inputMask */
3119 bool QSecureLineEditPrivate::isValidInput(QChar key, QChar mask) const
3120 {
3121     switch (mask.unicode()) {
3122     case 'A':
3123         if (key.isLetter())
3124             return true;
3125         break;
3126     case 'a':
3127         if (key.isLetter() || key == blank)
3128             return true;
3129         break;
3130     case 'N':
3131         if (key.isLetterOrNumber())
3132             return true;
3133         break;
3134     case 'n':
3135         if (key.isLetterOrNumber() || key == blank)
3136             return true;
3137         break;
3138     case 'X':
3139         if (key.isPrint())
3140             return true;
3141         break;
3142     case 'x':
3143         if (key.isPrint() || key == blank)
3144             return true;
3145         break;
3146     case '9':
3147         if (key.isNumber())
3148             return true;
3149         break;
3150     case '0':
3151         if (key.isNumber() || key == blank)
3152             return true;
3153         break;
3154     case 'D':
3155         if (key.isNumber() && key.digitValue() > 0)
3156             return true;
3157         break;
3158     case 'd':
3159         if ((key.isNumber() && key.digitValue() > 0) || key == blank)
3160             return true;
3161         break;
3162     case '#':
3163         if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank)
3164             return true;
3165         break;
3166     case 'B':
3167         if (key == QLatin1Char('0') || key == QLatin1Char('1'))
3168             return true;
3169         break;
3170     case 'b':
3171         if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank)
3172             return true;
3173         break;
3174     case 'H':
3175         if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
3176             return true;
3177         break;
3178     case 'h':
3179         if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank)
3180             return true;
3181         break;
3182     default:
3183         break;
3184     }
3185     return false;
3186 }
3187
3188 bool QSecureLineEditPrivate::hasAcceptableInput(const secqstring &str) const
3189 {
3190 #ifndef QT_NO_VALIDATOR
3191     QString textCopy = str;
3192     int cursorCopy = cursor;
3193     if (validator && validator->validate(textCopy, cursorCopy)
3194         != QValidator::Acceptable)
3195         return false;
3196 #endif
3197
3198     if (!maskData)
3199         return true;
3200
3201     if (str.length() != maxLength)
3202         return false;
3203
3204     for (int i=0; i < maxLength; ++i) {
3205         if (maskData[i].separator) {
3206             if (str[i] != maskData[i].maskChar)
3207                 return false;
3208         } else {
3209             if (!isValidInput(str[i], maskData[i].maskChar))
3210                 return false;
3211         }
3212     }
3213     return true;
3214 }
3215
3216 /*
3217   Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
3218   specifies from where characters should be gotten when a separator is met in \a str - true means
3219   that blanks will be used, false that previous input is used.
3220   Calling this when no inputMask is set is undefined.
3221 */
3222 secqstring QSecureLineEditPrivate::maskString(uint pos, const secqstring &str, bool clear) const
3223 {
3224     if (pos >= (uint)maxLength)
3225         return secqstring();
3226
3227     secqstring fill;
3228     fill = clear ? clearString(0, maxLength) : text;
3229
3230     int strIndex = 0;
3231     secqstring s;
3232     int i = pos;
3233     while (i < maxLength) {
3234         if (strIndex < str.length()) {
3235             if (maskData[i].separator) {
3236                 s += maskData[i].maskChar;
3237                 if (str[(int)strIndex] == maskData[i].maskChar)
3238                     strIndex++;
3239                 ++i;
3240             } else {
3241                 if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) {
3242                     switch (maskData[i].caseMode) {
3243                     case MaskInputData::Upper:
3244                         s += str[(int)strIndex].toUpper();
3245                         break;
3246                     case MaskInputData::Lower:
3247                         s += str[(int)strIndex].toLower();
3248                         break;
3249                     default:
3250                         s += str[(int)strIndex];
3251                     }
3252                     ++i;
3253                 } else {
3254                     // search for separator first
3255                     int n = findInMask(i, true, true, str[(int)strIndex]);
3256                     if (n != -1) {
3257                         if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) {
3258                             s += fill.substr(i, n-i+1);
3259                             i = n + 1; // update i to find + 1
3260                         }
3261                     } else {
3262                         // search for valid blank if not
3263                         n = findInMask(i, true, false, str[(int)strIndex]);
3264                         if (n != -1) {
3265                             s += fill.substr(i, n-i);
3266                             switch (maskData[n].caseMode) {
3267                             case MaskInputData::Upper:
3268                                 s += str[(int)strIndex].toUpper();
3269                                 break;
3270                             case MaskInputData::Lower:
3271                                 s += str[(int)strIndex].toLower();
3272                                 break;
3273                             default:
3274                                 s += str[(int)strIndex];
3275                             }
3276                             i = n + 1; // updates i to find + 1
3277                         }
3278                     }
3279                 }
3280                 strIndex++;
3281             }
3282         } else
3283             break;
3284     }
3285
3286     return s;
3287 }
3288
3289
3290
3291 /*
3292   Returns a "cleared" string with only separators and blank chars.
3293   Calling this when no inputMask is set is undefined.
3294 */
3295 secqstring QSecureLineEditPrivate::clearString(uint pos, uint len) const
3296 {
3297     if (pos >= (uint)maxLength)
3298         return secqstring();
3299
3300     secqstring s;
3301     int end = qMin((uint)maxLength, pos + len);
3302     for (int i=pos; i<end; i++)
3303         if (maskData[i].separator)
3304             s += maskData[i].maskChar;
3305         else
3306             s += blank;
3307
3308     return s;
3309 }
3310
3311 /*
3312   Strips blank parts of the input in a QSecureLineEdit when an inputMask is set,
3313   separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
3314 */
3315 secqstring QSecureLineEditPrivate::stripString(const secqstring &str) const
3316 {
3317     if (!maskData)
3318         return str;
3319
3320     secqstring s;
3321     int end = qMin(maxLength, (int)str.size());
3322     for (int i=0; i < end; i++)
3323         if (maskData[i].separator)
3324             s += maskData[i].maskChar;
3325         else
3326             if (str[i] != blank)
3327                 s += str[i];
3328
3329     return s;
3330 }
3331
3332 /* searches forward/backward in maskData for either a separator or a blank */
3333 int QSecureLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
3334 {
3335     if (pos >= maxLength || pos < 0)
3336         return -1;
3337
3338     int end = forward ? maxLength : -1;
3339     int step = forward ? 1 : -1;
3340     int i = pos;
3341
3342     while (i != end) {
3343         if (findSeparator) {
3344             if (maskData[i].separator && maskData[i].maskChar == searchChar)
3345                 return i;
3346         } else {
3347             if (!maskData[i].separator) {
3348                 if (searchChar.isNull())
3349                     return i;
3350                 else if (isValidInput(searchChar, maskData[i].maskChar))
3351                     return i;
3352             }
3353         }
3354         i += step;
3355     }
3356     return -1;
3357 }
3358
3359 void QSecureLineEditPrivate::undo(int until)
3360 {
3361     if (!isUndoAvailable())
3362         return;
3363     deselect();
3364     while (undoState && undoState > until) {
3365         Command& cmd = history[--undoState];
3366         switch (cmd.type) {
3367         case Insert:
3368             text.erase(cmd.pos, 1);
3369             cursor = cmd.pos;
3370             break;
3371         case SetSelection:
3372             selstart = cmd.selStart;
3373             selend = cmd.selEnd;
3374             cursor = cmd.pos;
3375             break;
3376         case Remove:
3377         case RemoveSelection:
3378             text.insert(cmd.pos, &cmd.uc, 1);
3379             cursor = cmd.pos + 1;
3380             break;
3381         case Delete:
3382         case DeleteSelection:
3383             text.insert(cmd.pos, &cmd.uc, 1);
3384             cursor = cmd.pos;
3385             break;
3386         case Separator:
3387             continue;
3388         }
3389         if (until < 0 && undoState) {
3390             Command& next = history[undoState-1];
3391             if (next.type != cmd.type && next.type < RemoveSelection
3392                  && (cmd.type < RemoveSelection || next.type == Separator))
3393                 break;
3394         }
3395     }
3396     textDirty = true;
3397     emitCursorPositionChanged();
3398 }
3399
3400 void QSecureLineEditPrivate::redo() {
3401     if (!isRedoAvailable())
3402         return;
3403     deselect();
3404     while (undoState < (int)history.size()) {
3405         Command& cmd = history[undoState++];
3406         switch (cmd.type) {
3407         case Insert:
3408             text.insert(cmd.pos, &cmd.uc, 1);
3409             cursor = cmd.pos + 1;
3410             break;
3411         case SetSelection:
3412             selstart = cmd.selStart;
3413             selend = cmd.selEnd;
3414             cursor = cmd.pos;
3415             break;
3416         case Remove:
3417         case Delete:
3418         case RemoveSelection:
3419         case DeleteSelection:
3420             text.erase(cmd.pos, 1);
3421             cursor = cmd.pos;
3422             break;
3423         case Separator:
3424             selstart = cmd.selStart;
3425             selend = cmd.selEnd;
3426             cursor = cmd.pos;
3427             break;
3428         }
3429         if (undoState < (int)history.size()) {
3430             Command& next = history[undoState];
3431             if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
3432                  && (next.type < RemoveSelection || cmd.type == Separator))
3433                 break;
3434         }
3435     }
3436     textDirty = true;
3437     emitCursorPositionChanged();
3438 }
3439
3440 /*!
3441     \fn void QSecureLineEdit::repaintArea(int a, int b)
3442
3443     Use update() instead.
3444 */
3445
3446 /*!
3447     \fn void QSecureLineEdit::cursorLeft(bool mark, int steps)
3448
3449     Use cursorForward() with a negative number of steps instead. For
3450     example, cursorForward(mark, -steps).
3451 */
3452
3453 /*!
3454     \fn void QSecureLineEdit::cursorRight(bool mark, int steps)
3455
3456     Use cursorForward() instead.
3457 */
3458
3459 /*!
3460     \fn bool QSecureLineEdit::frame() const
3461
3462     Use hasFrame() instead.
3463 */
3464
3465 /*!
3466     \fn void QSecureLineEdit::clearValidator()
3467
3468     Use setValidator(0) instead.
3469 */
3470
3471 /*!
3472     \fn bool QSecureLineEdit::hasMarkedText() const
3473
3474     Use hasSelectedText() instead.
3475 */
3476
3477 /*!
3478     \fn QString QSecureLineEdit::markedText() const
3479
3480     Use selectedText() instead.
3481 */
3482
3483 /*!
3484     \fn void QSecureLineEdit::setFrameRect(QRect)
3485     \internal
3486 */
3487
3488 /*!
3489     \fn QRect QSecureLineEdit::frameRect() const
3490     \internal
3491 */
3492 /*!
3493     \enum QSecureLineEdit::DummyFrame
3494     \internal
3495
3496     \value Box
3497     \value Sunken
3498     \value Plain
3499     \value Raised
3500     \value MShadow
3501     \value NoFrame
3502     \value Panel
3503     \value StyledPanel
3504     \value HLine
3505     \value VLine
3506     \value GroupBoxPanel
3507     \value WinPanel
3508     \value ToolBarPanel
3509     \value MenuBarPanel
3510     \value PopupPanel
3511     \value LineEditPanel
3512     \value TabWidgetPanel
3513     \value MShape
3514 */
3515
3516 /*!
3517     \fn void QSecureLineEdit::setFrameShadow(DummyFrame)
3518     \internal
3519 */
3520
3521 /*!
3522     \fn DummyFrame QSecureLineEdit::frameShadow() const
3523     \internal
3524 */
3525
3526 /*!
3527     \fn void QSecureLineEdit::setFrameShape(DummyFrame)
3528     \internal
3529 */
3530
3531 /*!
3532     \fn DummyFrame QSecureLineEdit::frameShape() const
3533     \internal
3534 */
3535
3536 /*!
3537     \fn void QSecureLineEdit::setFrameStyle(int)
3538     \internal
3539 */
3540
3541 /*!
3542     \fn int QSecureLineEdit::frameStyle() const
3543     \internal
3544 */
3545
3546 /*!
3547     \fn int QSecureLineEdit::frameWidth() const
3548     \internal
3549 */
3550
3551 /*!
3552     \fn void QSecureLineEdit::setLineWidth(int)
3553     \internal
3554 */
3555
3556 /*!
3557     \fn int QSecureLineEdit::lineWidth() const
3558     \internal
3559 */
3560
3561 /*!
3562     \fn void QSecureLineEdit::setMargin(int margin)
3563     Sets the width of the margin around the contents of the widget to \a margin.
3564
3565     Use QWidget::setContentsMargins() instead.
3566     \sa margin(), QWidget::setContentsMargins()
3567 */
3568
3569 /*!
3570     \fn int QSecureLineEdit::margin() const
3571     Returns the with of the the margin around the contents of the widget.
3572
3573     Use QWidget::getContentsMargins() instead.
3574     \sa setMargin(), QWidget::getContentsMargins()
3575 */
3576
3577 /*!
3578     \fn void QSecureLineEdit::setMidLineWidth(int)
3579     \internal
3580 */
3581
3582 /*!
3583     \fn int QSecureLineEdit::midLineWidth() const
3584     \internal
3585 */
3586
3587 QT_END_NAMESPACE
3588
3589 #include "qsecurelineedit.moc"
3590
3591 #endif // QT_NO_LINEEDIT