2 qsecurelineedit.cpp - QLineEdit that uses secmem
4 Copyright (C) 2008 Klarälvdalens Datakonsult AB (KDAB)
6 Written by Marc Mutz <marc@kdab.com>.
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.
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.
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.
23 // the following code has been ported from QString to secqstring.
24 // The licence of the original code:
26 /****************************************************************************
28 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
30 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
45 ****************************************************************************/
47 #include "qlineedit.h" // added to pick up qt defines
49 #ifndef QT_NO_LINEEDIT
51 #include "qapplication.h"
52 #include "qclipboard.h"
54 #include "qdrawutil.h"
56 #include "qfontmetrics.h"
61 #include "qstringlist.h"
63 #include "qstyleoption.h"
65 #include "qvalidator.h"
68 #include "qwhatsthis.h"
70 #include "qtextedit.h"
71 //#include <private/qtextedit_p.h>
72 #ifndef QT_NO_ACCESSIBILITY
73 #include "qaccessible.h"
76 #include "qinputcontext.h"
79 #include "qabstractitemview.h"
80 #ifdef QT_NO_STYLE_STYLESHEET
81 #include "private/qstylesheetstyle_p.h"
84 #ifndef QT_NO_SHORTCUT
85 #include "qkeysequence.h"
86 #define ACCEL_KEY(k) QLatin1String("\t") + QString(QKeySequence(k))
88 #define ACCEL_KEY(k) QString()
93 // these go last so they don't contaminate other Qt headers
94 #include "qsecurelineedit_p.h"
95 #include "qsecurelineedit.h"
97 #define verticalMargin 1
98 #define horizontalMargin 2
103 extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
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
113 \sa QStyleOption::initFrom()
115 void QSecureLineEdit::initStyleOption(QStyleOptionFrame *option) const
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)
125 option->midLineWidth = 0;
126 option->state |= QStyle::State_Sunken;
128 option->state |= QStyle::State_ReadOnly;
129 #ifdef QT_KEYPAD_NAVIGATION
131 option->state |= QStyle::State_HasEditFocus;
133 if (QStyleOptionFrameV2 *optionV2 = qstyleoption_cast<QStyleOptionFrameV2 *>(option))
134 optionV2->features = QStyleOptionFrameV2::None;
138 \class QSecureLineEdit
139 \brief The QSecureLineEdit widget is a one-line text editor.
141 \ingroup basicwidgets
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.
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.
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.
155 A related class is QTextEdit which allows multi-line, rich text
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
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.
171 When editing is finished, either because the line edit lost focus
172 or Return/Enter is pressed the editingFinished() signal is
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.
179 By default, QSecureLineEdits have a frame as specified by the Windows
180 and Motif style guides; you can turn it off by calling
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.
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.
211 Any other key sequence that represents a valid character, will
212 cause the character to be inserted into the line edit.
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}.
223 \sa QTextEdit, QLabel, QComboBox, {fowler}{GUI Design Handbook: Field, Entry}, {Line Edits Example}
228 \fn void QSecureLineEdit::textChanged(const QString &text)
230 This signal is emitted whenever the text changes. The \a text
231 argument is the new text.
233 Unlike textEdited(), this signal is also emitted when the text is
234 changed programmatically, for example, by calling setText().
238 \fn void QSecureLineEdit::textEdited(const QString &text)
240 This signal is emitted whenever the text is edited. The \a text
241 argument is the next text.
243 Unlike textChanged(), this signal is not emitted when the text is
244 changed programmatically, for example, by calling setText().
248 \fn void QSecureLineEdit::cursorPositionChanged(int old, int new)
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.
253 \sa setCursorPosition(), cursorPosition()
257 \fn void QSecureLineEdit::selectionChanged()
259 This signal is emitted whenever the selection changes.
261 \sa hasSelectedText(), selectedText()
265 Constructs a line edit with no text.
267 The maximum text length is set to 32767 characters.
269 The \a parent argument is sent to the QWidget constructor.
271 \sa setText(), setMaxLength()
273 QSecureLineEdit::QSecureLineEdit(QWidget* parent)
274 : QWidget(parent,0), m_d(new QSecureLineEditPrivate(this))
276 Q_D(QSecureLineEdit);
277 d->init(secqstring());
281 Constructs a line edit containing the text \a contents.
283 The cursor position is set to the end of the line and the maximum
284 text length to 32767 characters.
286 The \a parent and argument is sent to the QWidget
289 \sa text(), setMaxLength()
291 QSecureLineEdit::QSecureLineEdit(const secqstring& contents, QWidget* parent)
292 : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
294 Q_D(QSecureLineEdit);
301 Constructs a line edit with no text.
303 The maximum text length is set to 32767 characters.
305 The \a parent and \a name arguments are sent to the QWidget constructor.
307 \sa setText(), setMaxLength()
309 QSecureLineEdit::QSecureLineEdit(QWidget* parent, const char* name)
310 : QWidget(parent,0), m_d(new QSecureLineEditPrivate(this))
312 Q_D(QSecureLineEdit);
313 setObjectName(QString::fromAscii(name));
314 d->init(secqstring());
318 Constructs a line edit containing the text \a contents.
320 The cursor position is set to the end of the line and the maximum
321 text length to 32767 characters.
323 The \a parent and \a name arguments are sent to the QWidget
326 \sa text(), setMaxLength()
329 QSecureLineEdit::QSecureLineEdit(const secqstring& contents, QWidget* parent, const char* name)
330 : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
332 Q_D(QSecureLineEdit);
333 setObjectName(QString::fromAscii(name));
338 Constructs a line edit with an input \a inputMask and the text \a
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).
345 The \a parent and \a name arguments are sent to the QWidget
350 QSecureLineEdit::QSecureLineEdit(const QString& contents, const QString &inputMask, QWidget* parent, const char* name)
351 : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
353 Q_D(QSecureLineEdit);
354 setObjectName(QString::fromAscii(name));
355 d->parseInputMask(inputMask);
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());
367 Destroys the line edit.
370 QSecureLineEdit::~QSecureLineEdit()
377 \property QSecureLineEdit::text
378 \brief the line edit's text
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().
385 The text is truncated to maxLength() length.
387 \sa insert(), clear()
389 secqstring QSecureLineEdit::text() const
391 Q_D(const QSecureLineEdit);
392 secqstring res = d->text;
394 res = d->stripString(d->text);
395 return res;//(res.isNull() ? QString::fromLatin1("") : res);
398 void QSecureLineEdit::setText(const secqstring& text)
400 Q_D(QSecureLineEdit);
401 d->setText(text, -1, false);
402 #ifdef QT_KEYPAD_NAVIGATION
403 d->origText = d->text;
409 \property QSecureLineEdit::displayText
410 \brief the displayed text
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, "".
417 \sa setEchoMode() text() EchoMode
420 secqstring QSecureLineEdit::displayText() const
422 Q_D(const QSecureLineEdit);
423 if (d->echoMode == NoEcho)
425 secqstring res = d->text;
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));
433 return res;//(res.isNull() ? QString::fromLatin1("") : res);
438 \property QSecureLineEdit::maxLength
439 \brief the maximum permitted length of the text
441 If the text is too long, it is truncated at the limit.
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
447 If the line edit has an input mask, the mask defines the maximum
453 int QSecureLineEdit::maxLength() const
455 Q_D(const QSecureLineEdit);
459 void QSecureLineEdit::setMaxLength(int maxLength)
461 Q_D(QSecureLineEdit);
464 d->maxLength = maxLength;
471 \property QSecureLineEdit::frame
472 \brief whether the line edit draws itself with a frame
474 If enabled (the default) the line edit draws itself inside a
475 frame, otherwise the line edit draws itself without any frame.
477 bool QSecureLineEdit::hasFrame() const
479 Q_D(const QSecureLineEdit);
484 void QSecureLineEdit::setFrame(bool enable)
486 Q_D(QSecureLineEdit);
494 \enum QSecureLineEdit::EchoMode
496 This enum type describes how a line edit should display its
499 \value Normal Display characters as they are entered. This is the
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
506 \value PasswordEchoOnEdit Display characters as they are entered
507 while editing otherwise display asterisks.
509 \sa setEchoMode() echoMode()
514 \property QSecureLineEdit::echoMode
515 \brief the line edit's echo mode
517 The initial setting is \l Normal, but QSecureLineEdit also supports \l
518 NoEcho, \l Password and \l PasswordEchoOnEdit modes.
520 The widget's display and the ability to copy or drag the text is
521 affected by this setting.
523 \sa EchoMode displayText()
526 QSecureLineEdit::EchoMode QSecureLineEdit::echoMode() const
528 Q_D(const QSecureLineEdit);
529 return (EchoMode) d->echoMode;
532 void QSecureLineEdit::setEchoMode(EchoMode mode)
534 Q_D(QSecureLineEdit);
535 if(mode == (EchoMode)d->echoMode)
537 setAttribute(Qt::WA_InputMethodEnabled, mode == Normal || mode == PasswordEchoOnEdit);
539 d->updateTextLayout();
543 qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
548 #ifndef QT_NO_VALIDATOR
550 Returns a pointer to the current input validator, or 0 if no
551 validator has been set.
556 const QValidator * QSecureLineEdit::validator() const
558 Q_D(const QSecureLineEdit);
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.
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()).
571 \sa validator() QIntValidator QDoubleValidator QRegExpValidator
574 void QSecureLineEdit::setValidator(const QValidator *v)
576 Q_D(QSecureLineEdit);
577 d->validator = const_cast<QValidator*>(v);
579 #endif // QT_NO_VALIDATOR
581 #ifndef QT_NO_COMPLETER
585 Sets this line edit to provide auto completions from the completer, \a c.
586 The completion mode is set using QCompleter::setCompletionMode().
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
593 If \a c == 0, setCompleter() removes the current completer, effectively
594 disabling auto completion.
598 void QSecureLineEdit::setCompleter(QCompleter *c)
600 Q_D(QSecureLineEdit);
601 if (c == d->completer)
604 disconnect(d->completer, 0, this, 0);
605 d->completer->setWidget(0);
606 if (d->completer->parent() == this)
612 if (c->widget() == 0)
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)));
625 Returns the current QCompleter that provides completions.
627 QCompleter *QSecureLineEdit::completer() const
629 Q_D(const QSecureLineEdit);
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)
637 int start = completer->currentRow();
641 if (dir == 0) dir = 1;
643 if (!completer->setCurrentRow(i)) {
644 if (!completer->wrapAround())
646 i = i > 0 ? 0 : completer->completionCount() - 1;
648 QModelIndex currentIndex = completer->currentIndex();
649 if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
653 } while (i != start);
655 completer->setCurrentRow(start); // restore
659 void QSecureLineEditPrivate::complete(int key)
661 if (!completer || readOnly || echoMode != QSecureLineEdit::Normal)
664 if (completer->completionMode() == QCompleter::InlineCompletion) {
665 if (key == Qt::Key_Backspace)
668 if (key == Qt::Key_Up || key == Qt::Key_Down) {
669 if (selend != 0 && selend != text.length())
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);
676 n = (key == Qt::Key_Up) ? -1 : +1;
679 completer->setCompletionPrefix(text);
681 if (!advanceToEnabledItem(n))
684 #ifndef QT_KEYPAD_NAVIGATION
685 if (text.isEmpty()) {
686 completer->popup()->hide();
690 completer->setCompletionPrefix(text);
693 completer->complete();
696 void QSecureLineEditPrivate::_q_completionHighlighted(QString newText)
698 Q_Q(QSecureLineEdit);
699 if (completer->completionMode() != QCompleter::InlineCompletion)
703 q->setText(text.left(c) + newText.mid(c));
704 q->setSelection(text.length(), c - newText.length());
707 #endif // QT_NO_COMPLETER
710 Returns a recommended size for the widget.
712 The width returned, in pixels, is usually enough for about 15 to
716 QSize QSecureLineEdit::sizeHint() const
718 Q_D(const QSecureLineEdit);
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));
735 Returns a minimum size for the line edit.
737 The width returned is enough for at least one character.
740 QSize QSecureLineEdit::minimumSizeHint() const
742 Q_D(const QSecureLineEdit);
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));
758 \property QSecureLineEdit::cursorPosition
759 \brief the current cursor position for this line edit
761 Setting the cursor position causes a repaint when appropriate.
764 int QSecureLineEdit::cursorPosition() const
766 Q_D(const QSecureLineEdit);
770 void QSecureLineEdit::setCursorPosition(int pos)
772 Q_D(QSecureLineEdit);
776 if (pos <= d->text.length())
781 Returns the cursor position under the point \a pos.
783 // ### What should this do if the point is outside of contentsRect? Currently returns 0.
784 int QSecureLineEdit::cursorPositionAt(const QPoint &pos)
786 Q_D(QSecureLineEdit);
787 return d->xToPos(pos.x());
794 Use setText(), setCursorPosition() and setSelection() instead.
796 bool QSecureLineEdit::validateAndSet(const QString &newText, int newPos,
797 int newMarkAnchor, int newMarkDrag)
799 Q_D(QSecureLineEdit);
800 int priorState = d->undoState;
802 d->selend = d->text.length();
803 d->removeSelectedText();
805 d->finishChange(priorState);
806 if (d->undoState > priorState) {
808 d->selstart = qMin(newMarkAnchor, newMarkDrag);
809 d->selend = qMax(newMarkAnchor, newMarkDrag);
811 d->emitCursorPositionChanged();
819 \property QSecureLineEdit::alignment
820 \brief the alignment of the line edit
822 Both horizontal and vertical alignment is allowed here, Qt::AlignJustify
823 will map to Qt::AlignLeft.
828 Qt::Alignment QSecureLineEdit::alignment() const
830 Q_D(const QSecureLineEdit);
831 return QFlag(d->alignment);
834 void QSecureLineEdit::setAlignment(Qt::Alignment alignment)
836 Q_D(QSecureLineEdit);
837 d->alignment = alignment;
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.
850 void QSecureLineEdit::cursorForward(bool mark, int steps)
852 Q_D(QSecureLineEdit);
853 int cursor = d->cursor;
856 cursor = d->textLayout.nextCursorPosition(cursor);
857 } else if (steps < 0) {
859 cursor = d->textLayout.previousCursorPosition(cursor);
861 d->moveCursor(cursor, mark);
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.
872 void QSecureLineEdit::cursorBackward(bool mark, int steps)
874 cursorForward(mark, -steps);
878 Moves the cursor one word forward. If \a mark is true, the word is
881 \sa cursorWordBackward()
883 void QSecureLineEdit::cursorWordForward(bool mark)
885 Q_D(QSecureLineEdit);
886 d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
890 Moves the cursor one word backward. If \a mark is true, the word
893 \sa cursorWordForward()
896 void QSecureLineEdit::cursorWordBackward(bool mark)
898 Q_D(QSecureLineEdit);
899 d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
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.
911 void QSecureLineEdit::backspace()
913 Q_D(QSecureLineEdit);
914 int priorState = d->undoState;
915 if (d->hasSelectedText()) {
916 d->removeSelectedText();
917 } else if (d->cursor) {
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) {
933 d->finishChange(priorState);
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.
944 void QSecureLineEdit::del()
946 Q_D(QSecureLineEdit);
947 int priorState = d->undoState;
948 if (d->hasSelectedText()) {
949 d->removeSelectedText();
951 int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor;
955 d->finishChange(priorState);
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
967 void QSecureLineEdit::home(bool mark)
969 Q_D(QSecureLineEdit);
970 d->moveCursor(0, mark);
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
982 void QSecureLineEdit::end(bool mark)
984 Q_D(QSecureLineEdit);
985 d->moveCursor(d->text.length(), mark);
990 \property QSecureLineEdit::modified
991 \brief whether the line edit's contents has been modified by the user
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
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
1004 Calling setText() resets the modified flag to false.
1007 bool QSecureLineEdit::isModified() const
1009 Q_D(const QSecureLineEdit);
1010 return d->modifiedState != d->undoState;
1013 void QSecureLineEdit::setModified(bool modified)
1015 Q_D(QSecureLineEdit);
1017 d->modifiedState = -1;
1019 d->modifiedState = d->undoState;
1023 /*!\fn QSecureLineEdit::clearModified()
1025 Use setModified(false) instead.
1032 \property QSecureLineEdit::hasSelectedText
1033 \brief whether there is any text selected
1035 hasSelectedText() returns true if some or all of the text has been
1036 selected by the user; otherwise returns false.
1042 bool QSecureLineEdit::hasSelectedText() const
1044 Q_D(const QSecureLineEdit);
1045 return d->hasSelectedText();
1049 \property QSecureLineEdit::selectedText
1050 \brief the selected text
1052 If there is no selected text this property's value is
1055 \sa hasSelectedText()
1058 secqstring QSecureLineEdit::selectedText() const
1060 Q_D(const QSecureLineEdit);
1061 if (d->hasSelectedText())
1062 return d->text.substr(d->selstart, d->selend - d->selstart);
1063 return secqstring();
1067 selectionStart() returns the index of the first selected character in the
1068 line edit or -1 if no text is selected.
1073 int QSecureLineEdit::selectionStart() const
1075 Q_D(const QSecureLineEdit);
1076 return d->hasSelectedText() ? d->selstart : -1;
1083 \fn void QSecureLineEdit::lostFocus()
1085 This signal is emitted when the line edit has lost focus.
1087 Use editingFinished() instead
1088 \sa editingFinished(), returnPressed()
1092 Use isModified() instead.
1094 bool QSecureLineEdit::edited() const { return isModified(); }
1096 Use setModified() or setText().
1098 void QSecureLineEdit::setEdited(bool on) { setModified(on); }
1101 There exists no equivalent functionality in Qt 4.
1103 int QSecureLineEdit::characterAt(int xpos, QChar *chr) const
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);
1114 Use selectedText() and selectionStart() instead.
1116 bool QSecureLineEdit::getSelection(int *start, int *end)
1118 Q_D(QSecureLineEdit);
1119 if (d->hasSelectedText() && start && end) {
1120 *start = d->selstart;
1130 Selects text from position \a start and for \a length characters.
1131 Negative lengths are allowed.
1133 \sa deselect() selectAll() selectedText()
1136 void QSecureLineEdit::setSelection(int start, int length)
1138 Q_D(QSecureLineEdit);
1139 if (start < 0 || start > (int)d->text.length()) {
1140 qWarning("QSecureLineEdit::setSelection: Invalid start position (%d)", start);
1144 d->selstart = start;
1145 d->selend = qMin(start + length, (int)d->text.length());
1146 d->cursor = d->selend;
1148 d->selstart = qMax(start + length, 0);
1150 d->cursor = d->selstart;
1154 if (d->hasSelectedText()){
1155 QStyleOptionFrameV2 opt;
1156 initStyleOption(&opt);
1157 if (!style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
1158 d->setCursorVisible(false);
1162 d->emitCursorPositionChanged();
1167 \property QSecureLineEdit::undoAvailable
1168 \brief whether undo is available
1171 bool QSecureLineEdit::isUndoAvailable() const
1173 Q_D(const QSecureLineEdit);
1174 return d->isUndoAvailable();
1178 \property QSecureLineEdit::redoAvailable
1179 \brief whether redo is available
1182 bool QSecureLineEdit::isRedoAvailable() const
1184 Q_D(const QSecureLineEdit);
1185 return d->isRedoAvailable();
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
1193 Dragging is disabled by default.
1196 bool QSecureLineEdit::dragEnabled() const
1198 Q_D(const QSecureLineEdit);
1199 return d->dragEnabled;
1202 void QSecureLineEdit::setDragEnabled(bool b)
1204 Q_D(QSecureLineEdit);
1210 \property QSecureLineEdit::acceptableInput
1211 \brief whether the input satisfies the inputMask and the
1214 \sa setInputMask(), setValidator()
1216 bool QSecureLineEdit::hasAcceptableInput() const
1218 Q_D(const QSecureLineEdit);
1219 return d->hasAcceptableInput(d->text);
1223 \property QSecureLineEdit::inputMask
1224 \brief The validation input mask
1226 If no mask is set, inputMask() returns an empty string.
1228 Sets the QSecureLineEdit's validation mask. Validators can be used
1229 instead of, or in conjunction with masks; see setValidator().
1231 Unset the mask and return to normal QSecureLineEdit operation by passing
1232 an empty string ("") or just calling setInputMask() with no
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}.
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
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
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
1280 To get range control (e.g. for an IP address) use masks together
1281 with \link setValidator() validators\endlink.
1285 QString QSecureLineEdit::inputMask() const
1287 Q_D(const QSecureLineEdit);
1288 return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString());
1291 void QSecureLineEdit::setInputMask(const QString &inputMask)
1293 Q_D(QSecureLineEdit);
1294 d->parseInputMask(inputMask);
1296 d->moveCursor(d->nextMaskBlank(0));
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.
1305 \sa setSelection() deselect()
1308 void QSecureLineEdit::selectAll()
1310 Q_D(QSecureLineEdit);
1311 d->selstart = d->selend = d->cursor = 0;
1312 d->moveCursor(d->text.length(), true);
1316 Deselects any selected text.
1318 \sa setSelection() selectAll()
1321 void QSecureLineEdit::deselect()
1323 Q_D(QSecureLineEdit);
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
1334 \sa setText(), clear()
1336 void QSecureLineEdit::insert(const secqstring &newText)
1338 // q->resetInputContext(); //#### FIX ME IN QT
1339 Q_D(QSecureLineEdit);
1340 int priorState = d->undoState;
1341 d->removeSelectedText();
1343 d->finishChange(priorState);
1347 Clears the contents of the line edit.
1349 \sa setText(), insert()
1351 void QSecureLineEdit::clear()
1353 Q_D(QSecureLineEdit);
1354 int priorState = d->undoState;
1355 resetInputContext();
1357 d->selend = d->text.length();
1358 d->removeSelectedText();
1360 d->finishChange(priorState, /*update*/false, /*edited*/false);
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
1369 void QSecureLineEdit::undo()
1371 Q_D(QSecureLineEdit);
1372 resetInputContext();
1374 d->finishChange(-1, true);
1378 Redoes the last operation if redo is \link
1379 QSecureLineEdit::redoAvailable available\endlink.
1381 void QSecureLineEdit::redo()
1383 Q_D(QSecureLineEdit);
1384 resetInputContext();
1391 \property QSecureLineEdit::readOnly
1392 \brief whether the line edit is read only.
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),
1398 QSecureLineEdit does not show a cursor in read-only mode.
1403 bool QSecureLineEdit::isReadOnly() const
1405 Q_D(const QSecureLineEdit);
1409 void QSecureLineEdit::setReadOnly(bool enable)
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);
1423 #ifndef QT_NO_CLIPBOARD
1425 Copies the selected text to the clipboard and deletes it, if there
1426 is any, and if echoMode() is \l Normal.
1428 If the current validator disallows deleting the selected text,
1429 cut() will copy without deleting.
1431 \sa copy() paste() setValidator()
1434 void QSecureLineEdit::cut()
1436 if (hasSelectedText()) {
1444 Copies the selected text to the clipboard, if there is any, and if
1445 echoMode() is \l Normal.
1450 void QSecureLineEdit::copy() const
1452 Q_D(const QSecureLineEdit);
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.
1461 If the end result would not be acceptable to the current
1462 \link setValidator() validator\endlink, nothing happens.
1467 void QSecureLineEdit::paste()
1469 if(echoMode() == PasswordEchoOnEdit)
1471 Q_D(QSecureLineEdit);
1472 setEchoMode(Normal);
1474 d->resumePassword = true;
1476 insert(QApplication::clipboard()->text(QClipboard::Clipboard));
1479 void QSecureLineEditPrivate::copy(bool clipboard) const
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()));
1491 #endif // !QT_NO_CLIPBOARD
1495 bool QSecureLineEdit::event(QEvent * e)
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) {
1505 switch (ke->key()) {
1506 case Qt::Key_Delete:
1509 case Qt::Key_Backspace:
1517 } else if (ke->modifiers() & Qt::ControlModifier) {
1518 switch (ke->key()) {
1519 // Those are too frequently used for application functionality
1535 #if !defined(Q_WS_MAC)
1536 case Qt::Key_Insert:
1537 case Qt::Key_Delete:
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()) {
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();
1566 } else if (e->type() == QEvent::ContextMenu) {
1568 if (d->composeMode())
1572 } else if (e->type() == QEvent::WindowActivate) {
1573 QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate()));
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.
1585 if ((e->type() == QEvent::KeyRelease)
1587 && d->deleteAllTimer.isActive()) {
1588 d->deleteAllTimer.stop();
1594 } else if (e->type() == QEvent::EnterEditFocus) {
1596 if (!d->cursorTimer) {
1597 int cft = QApplication::cursorFlashTime();
1598 d->cursorTimer = cft ? startTimer(cft/2) : -1;
1600 } else if (e->type() == QEvent::LeaveEditFocus) {
1601 d->setCursorVisible(false);
1602 if (d->cursorTimer > 0)
1603 killTimer(d->cursorTimer);
1606 if (!d->emitingEditingFinished) {
1607 if (hasAcceptableInput() || d->fixup()) {
1608 d->emitingEditingFinished = true;
1609 emit editingFinished();
1610 d->emitingEditingFinished = false;
1616 return QWidget::event(e);
1621 void QSecureLineEdit::mousePressEvent(QMouseEvent* e)
1623 Q_D(QSecureLineEdit);
1624 if (d->sendMouseEventToInputContext(e))
1626 if (e->button() == Qt::RightButton)
1628 #ifdef QT_KEYPAD_NAVIGATION
1629 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1631 // Get the completion list to pop up.
1633 d->completer->complete();
1636 if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
1637 QApplication::startDragDistance()) {
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())) {
1648 d->dndPos = e->pos();
1649 if (!d->dndTimer.isActive())
1650 d->dndTimer.start(QApplication::startDragTime(), this);
1651 d->emitCursorPositionChanged();
1655 d->moveCursor(cursor, mark);
1661 void QSecureLineEdit::mouseMoveEvent(QMouseEvent * e)
1663 Q_D(QSecureLineEdit);
1664 if (d->sendMouseEventToInputContext(e))
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())
1675 d->moveCursor(d->xToPos(e->pos().x()), true);
1682 void QSecureLineEdit::mouseReleaseEvent(QMouseEvent* e)
1684 Q_D(QSecureLineEdit);
1685 if (d->sendMouseEventToInputContext(e))
1687 #ifndef QT_NO_DRAGANDDROP
1688 if (e->button() == Qt::LeftButton) {
1689 if (d->dndTimer.isActive()) {
1696 #ifndef QT_NO_CLIPBOARD
1697 if (QApplication::clipboard()->supportsSelection()) {
1698 if (e->button() == Qt::LeftButton) {
1700 } else if (!d->readOnly && e->button() == Qt::MidButton) {
1702 insert(QApplication::clipboard()->text(QClipboard::Selection));
1710 void QSecureLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
1712 Q_D(QSecureLineEdit);
1713 if (d->sendMouseEventToInputContext(e))
1715 if (e->button() == Qt::LeftButton) {
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())
1723 d->moveCursor(end, true);
1724 d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
1725 d->tripleClick = e->pos();
1730 \fn void QSecureLineEdit::returnPressed()
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.
1740 \fn void QSecureLineEdit::editingFinished()
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.
1750 Converts the given key press \a event into a line edit action.
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.
1756 The default key bindings are listed in the class's detailed
1760 void QSecureLineEdit::keyPressEvent(QKeyEvent *event)
1762 Q_D(QSecureLineEdit);
1764 #ifndef QT_NO_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:
1775 case Qt::Key_Return:
1777 #ifdef QT_KEYPAD_NAVIGATION
1778 case Qt::Key_Select:
1779 if (!QApplication::keypadNavigationEnabled())
1782 d->completer->popup()->hide(); // just hide. will end up propagating to parent
1784 break; // normal key processing
1787 #endif // QT_NO_COMPLETER
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();
1804 if (!QApplication::keypadNavigationEnabled() || !hasEditFocus()) {
1810 if (QApplication::keypadNavigationEnabled()) {
1811 if (!hasEditFocus() && !(event->modifiers() & Qt::ControlModifier)) {
1812 if (!event->text().isEmpty() && event->text().at(0).isPrint()
1827 if (QApplication::keypadNavigationEnabled() && !select && !hasEditFocus()) {
1829 if (event->key() == Qt::Key_Select)
1830 return; // Just start. No action.
1835 if(echoMode() == PasswordEchoOnEdit &&
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 &&
1844 !(event->modifiers() & Qt::ControlModifier))
1846 setEchoMode(Normal);
1848 d->resumePassword = true;
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;
1862 bool unknown = false;
1866 #ifndef QT_NO_SHORTCUT
1867 else if (event == QKeySequence::Undo) {
1871 else if (event == QKeySequence::Redo) {
1875 else if (event == QKeySequence::SelectAll) {
1878 #ifndef QT_NO_CLIPBOARD
1879 else if (event == QKeySequence::Copy) {
1882 else if (event == QKeySequence::Paste) {
1886 else if (event == QKeySequence::Cut) {
1891 else if (event == QKeySequence::DeleteEndOfLine) {
1893 setSelection(d->cursor, d->text.size());
1898 #endif //QT_NO_CLIPBOARD
1899 else if (event == QKeySequence::MoveToStartOfLine) {
1902 else if (event == QKeySequence::MoveToEndOfLine) {
1905 else if (event == QKeySequence::SelectStartOfLine) {
1908 else if (event == QKeySequence::SelectEndOfLine) {
1911 else if (event == QKeySequence::MoveToNextChar) {
1912 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
1913 if (d->hasSelectedText()) {
1915 if (d->hasSelectedText() && d->completer
1916 && d->completer->completionMode() == QCompleter::InlineCompletion) {
1918 d->moveCursor(d->selend, false);
1920 cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1923 else if (event == QKeySequence::SelectNextChar) {
1924 cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1926 else if (event == QKeySequence::MoveToPreviousChar) {
1927 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
1928 if (d->hasSelectedText()) {
1930 if (d->hasSelectedText() && d->completer
1931 && d->completer->completionMode() == QCompleter::InlineCompletion) {
1933 d->moveCursor(d->selstart, false);
1935 cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1938 else if (event == QKeySequence::SelectPreviousChar) {
1939 cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
1941 else if (event == QKeySequence::MoveToNextWord) {
1942 if (echoMode() == Normal)
1943 layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
1945 layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
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);
1954 else if (event == QKeySequence::SelectNextWord) {
1955 if (echoMode() == Normal)
1956 layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
1958 layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
1960 else if (event == QKeySequence::SelectPreviousWord) {
1961 if (echoMode() == Normal)
1962 layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
1964 layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
1966 else if (event == QKeySequence::Delete) {
1970 else if (event == QKeySequence::DeleteEndOfWord) {
1972 cursorWordForward(true);
1976 else if (event == QKeySequence::DeleteStartOfWord) {
1978 cursorWordBackward(true);
1982 #endif // QT_NO_SHORTCUT
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) {
1992 event->key() == Qt::Key_Up ? home(1) : end(1);
1995 if ((myModifiers == Qt::ControlModifier
1996 || myModifiers == Qt::AltModifier
1997 || myModifiers == Qt::NoModifier)) {
1998 event->key() == Qt::Key_Up ? home(0) : end(0);
2003 if (event->modifiers() & Qt::ControlModifier) {
2004 switch (event->key()) {
2005 case Qt::Key_Backspace:
2007 cursorWordBackward(true);
2011 #ifndef QT_NO_COMPLETER
2014 d->complete(event->key());
2017 #if defined(Q_WS_X11)
2024 setSelection(0, d->text.size());
2025 #ifndef QT_NO_CLIPBOARD
2035 } else { // ### check for *no* modifier
2036 switch (event->key()) {
2037 case Qt::Key_Backspace:
2040 #ifndef QT_NO_COMPLETER
2041 d->complete(Qt::Key_Backspace);
2045 #ifdef QT_KEYPAD_NAVIGATION
2047 if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
2049 if (text().length() == 0) {
2050 setText(d->origText);
2052 if (d->resumePassword)
2054 setEchoMode(PasswordEchoOnEdit);
2055 d->resumePassword = false;
2058 setEditFocus(false);
2059 } else if (!d->deleteAllTimer.isActive()) {
2060 d->deleteAllTimer.start(750, this);
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();
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());
2104 Returns a rectangle that includes the lineedit cursor.
2106 QRect QSecureLineEdit::cursorRect() const
2108 Q_D(const QSecureLineEdit);
2109 return d->cursorRect();
2113 This function is not intended as polymorphic usage. Just a shared code
2114 fragment that calls QInputContext::mouseHandler for this
2117 bool QSecureLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
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() ) {
2126 // don't send move events outside the preedit area
2127 if ( e->type() == QEvent::MouseMove )
2131 QInputContext *qic = q->inputContext();
2133 // may be causing reset() in some input methods
2134 qic->mouseHandler(mousePos, e);
2135 if (!textLayout.preeditAreaText().isEmpty())
2147 void QSecureLineEdit::inputMethodEvent(QInputMethodEvent *e)
2149 Q_D(QSecureLineEdit);
2156 if(echoMode() == PasswordEchoOnEdit)
2158 setEchoMode(Normal);
2160 d->resumePassword = true;
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()) {
2172 selectAll(); // so text is replaced rather than appended to
2176 int priorState = d->undoState;
2177 d->removeSelectedText();
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());
2183 d->cursor += e->replacementStart();
2185 // insert commit string
2186 if (e->replacementLength()) {
2187 d->selstart = d->cursor;
2188 d->selend = d->selstart + e->replacementLength();
2189 d->removeSelectedText();
2191 const QString commitString = e->commitString();
2192 if (!commitString.isEmpty())
2193 d->insert(secqstring(commitString.begin(), commitString.end()));
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();
2209 QTextLayout::FormatRange o;
2210 o.start = a.start + d->cursor;
2211 o.length = a.length;
2217 d->textLayout.setAdditionalFormats(formats);
2218 d->updateTextLayout();
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);
2231 QVariant QSecureLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
2233 Q_D(const QSecureLineEdit);
2235 case Qt::ImMicroFocus:
2236 return d->cursorRect();
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());
2255 void QSecureLineEdit::focusInEvent(QFocusEvent *e)
2257 Q_D(QSecureLineEdit);
2258 if (e->reason() == Qt::TabFocusReason ||
2259 e->reason() == Qt::BacktabFocusReason ||
2260 e->reason() == Qt::ShortcutFocusReason) {
2262 d->moveCursor(d->nextMaskBlank(0));
2263 else if (!d->hasSelectedText())
2266 #ifdef QT_KEYPAD_NAVIGATION
2267 if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason))
2269 if (!d->cursorTimer) {
2270 int cft = QApplication::cursorFlashTime();
2271 d->cursorTimer = cft ? startTimer(cft/2) : -1;
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);
2279 if (d->echoMode == Password || d->echoMode == NoEcho)
2280 qt_mac_secure_keyboard(true);
2282 #ifdef QT_KEYPAD_NAVIGATION
2283 d->origText = d->text;
2285 #ifndef QT_NO_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)));
2300 void QSecureLineEdit::focusOutEvent(QFocusEvent *e)
2302 Q_D(QSecureLineEdit);
2305 if(d->resumePassword){
2306 setEchoMode(PasswordEchoOnEdit);
2307 d->resumePassword = false;
2311 Qt::FocusReason reason = e->reason();
2312 if (reason != Qt::ActiveWindowFocusReason &&
2313 reason != Qt::PopupFocusReason)
2316 d->setCursorVisible(false);
2317 if (d->cursorTimer > 0)
2318 killTimer(d->cursorTimer);
2321 #ifdef QT_KEYPAD_NAVIGATION
2322 // editingFinished() is already emitted on LeaveEditFocus
2323 if (!QApplication::keypadNavigationEnabled())
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;
2339 if (d->echoMode == Password || d->echoMode == NoEcho)
2340 qt_mac_secure_keyboard(false);
2342 #ifdef QT_KEYPAD_NAVIGATION
2343 d->origText = QString();
2345 #ifndef QT_NO_COMPLETER
2347 QObject::disconnect(d->completer, 0, this, 0);
2355 void QSecureLineEdit::paintEvent(QPaintEvent *)
2357 Q_D(QSecureLineEdit);
2361 QPalette pal = palette();
2363 QStyleOptionFrameV2 panel;
2364 initStyleOption(&panel);
2365 style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this);
2366 r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
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;
2376 d->vscroll = r.y() + verticalMargin;
2380 d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2;
2383 QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height());
2384 QTextLine line = d->textLayout.lineAt(0);
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));
2392 // horizontal scrolling
2393 int minLB = qMax(0, -fm.minLeftBearing());
2394 int minRB = qMax(0, -fm.minRightBearing());
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;
2403 case Qt::AlignHCenter:
2404 d->hscroll = (widthUsed - lineRect.width()) / 2;
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) {
2416 } else if (widthUsed - d->hscroll < lineRect.width()) {
2417 d->hscroll = widthUsed - lineRect.width() + 1;
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());
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);
2428 p.setPen(pal.text().color());
2430 QVector<QTextLayout::FormatRange> selections;
2431 #ifdef QT_KEYPAD_NAVIGATION
2432 if (!QApplication::keypadNavigationEnabled() || hasEditFocus())
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));
2443 o.start = d->cursor;
2445 o.format.setBackground(pal.brush(QPalette::Text));
2446 o.format.setForeground(pal.brush(QPalette::Window));
2448 selections.append(o);
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));
2460 #ifndef QT_NO_DRAGANDDROP
2463 void QSecureLineEdit::dragMoveEvent(QDragMoveEvent *e)
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;
2471 d->emitCursorPositionChanged();
2476 void QSecureLineEdit::dragEnterEvent(QDragEnterEvent * e)
2478 QSecureLineEdit::dragMoveEvent(e);
2482 void QSecureLineEdit::dragLeaveEvent(QDragLeaveEvent *)
2484 Q_D(QSecureLineEdit);
2485 if (d->cursorVisible) {
2486 d->cursorVisible = false;
2492 void QSecureLineEdit::dropEvent(QDropEvent* e)
2494 Q_D(QSecureLineEdit);
2495 QString str = e->mimeData()->text();
2497 if (!str.isNull() && !d->readOnly) {
2498 if (e->source() == this && e->dropAction() == Qt::CopyAction)
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();
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());
2514 setSelection(selStart, str.length());
2516 setSelection(selStart, str.length());
2525 void QSecureLineEditPrivate::drag()
2527 Q_Q(QSecureLineEdit);
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);
2541 #endif // QT_NO_DRAGANDDROP
2543 #ifndef QT_NO_CONTEXTMENU
2545 Shows the standard context menu created with
2546 createStandardContextMenu().
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.
2554 \snippet doc/src/snippets/code/src.gui.widgets.qsecurelineedit.cpp 0
2556 The \a event parameter is used to obtain the position where
2557 the mouse cursor was when the event was generated.
2559 \sa setContextMenuPolicy()
2561 void QSecureLineEdit::contextMenuEvent(QContextMenuEvent *event)
2563 QPointer<QMenu> menu = createStandardContextMenu();
2564 menu->exec(event->globalPos());
2568 #if defined(Q_WS_WIN)
2569 extern bool qt_use_rtl_extensions;
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.
2578 QMenu *QSecureLineEdit::createStandardContextMenu()
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()));
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)
2601 QObject::connect(d->actions[QSecureLineEditPrivate::SelectAllAct], SIGNAL(triggered()), this, SLOT(selectAll()));
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());
2610 d->actions[QSecureLineEditPrivate::CutAct]->setEnabled(false);
2611 d->actions[QSecureLineEditPrivate::CopyAct]->setEnabled(false);
2612 d->actions[QSecureLineEditPrivate::PasteAct]->setEnabled(false);
2614 d->actions[QSecureLineEditPrivate::ClearAct]->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText());
2615 d->actions[QSecureLineEditPrivate::SelectAllAct]->setEnabled(!d->text.isEmpty() && !d->allSelected());
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();
2631 QList<QAction *> imActions = qic->actions();
2632 for (int i = 0; i < imActions.size(); ++i)
2633 popup->addAction(imActions.at(i));
2637 #if defined(Q_WS_WIN)
2638 if (!d->readOnly && qt_use_rtl_extensions) {
2642 popup->addSeparator();
2643 QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup);
2644 popup->addMenu(ctrlCharacterMenu);
2648 #endif // QT_NO_CONTEXTMENU
2651 void QSecureLineEdit::changeEvent(QEvent *ev)
2653 Q_D(QSecureLineEdit);
2654 if(ev->type() == QEvent::ActivationChange) {
2655 if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
2657 } else if (ev->type() == QEvent::FontChange || ev->type() == QEvent::StyleChange) {
2658 d->updateTextLayout();
2660 QWidget::changeEvent(ev);
2663 void QSecureLineEditPrivate::_q_clipboardChanged()
2667 void QSecureLineEditPrivate::_q_handleWindowActivate()
2669 Q_Q(QSecureLineEdit);
2670 if (!q->hasFocus() && q->hasSelectedText())
2674 void QSecureLineEditPrivate::_q_deleteSelected()
2676 Q_Q(QSecureLineEdit);
2677 if (!hasSelectedText())
2680 int priorState = undoState;
2681 q->resetInputContext();
2682 removeSelectedText();
2684 finishChange(priorState);
2686 void QSecureLineEditPrivate::init(const secqstring& txt)
2688 Q_Q(QSecureLineEdit);
2689 #ifndef QT_NO_CURSOR
2690 q->setCursor(Qt::IBeamCursor);
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);
2703 cursor = text.size();
2705 q->setAttribute(Qt::WA_MacShowFocusRect);
2708 void QSecureLineEditPrivate::updateTextLayout()
2710 // replace certain non-printable characters with spaces (to avoid
2711 // drawing boxes when using fonts that don't have glyphs for such
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);
2723 textLayout.setFont(q->font());
2724 // PENDING(marc) insecure (only when not in password mode)
2725 textLayout.setText( QString( str.data(), str.size() ) );
2727 option.setTextDirection(q->layoutDirection());
2728 option.setFlags(QTextOption::IncludeTrailingSpaces);
2729 textLayout.setTextOption(option);
2731 textLayout.beginLayout();
2732 QTextLine l = textLayout.createLine();
2733 textLayout.endLayout();
2734 ascent = qRound(l.ascent());
2737 int QSecureLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
2739 QRect cr = adjustedContentsRect();
2740 x-= cr.x() - hscroll + horizontalMargin;
2741 QTextLine l = textLayout.lineAt(0);
2742 return l.xToCursor(x, betweenOrOn);
2745 QRect QSecureLineEditPrivate::cursorRect() const
2747 Q_Q(const QSecureLineEdit);
2748 QRect cr = adjustedContentsRect();
2749 int cix = cr.x() - hscroll + horizontalMargin;
2750 QTextLine l = textLayout.lineAt(0);
2752 if (preeditCursor != -1)
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);
2760 QRect QSecureLineEditPrivate::adjustedContentsRect() const
2762 Q_Q(const QSecureLineEdit);
2763 QStyleOptionFrameV2 opt;
2764 q->initStyleOption(&opt);
2765 return q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
2768 bool QSecureLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable
2770 #ifndef QT_NO_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);
2786 void QSecureLineEditPrivate::moveCursor(int pos, bool mark)
2788 Q_Q(QSecureLineEdit);
2789 if (pos != cursor) {
2792 pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
2794 bool fullUpdate = mark || hasSelectedText();
2797 if (selend > selstart && cursor == selstart)
2799 else if (selend > selstart && cursor == selend)
2803 selstart = qMin(anchor, pos);
2804 selend = qMax(anchor, pos);
2813 setCursorVisible(false);
2815 setCursorVisible(true);
2816 if (!adjustedContentsRect().contains(cursorRect()))
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) {
2825 emit q->selectionChanged();
2827 emitCursorPositionChanged();
2830 void QSecureLineEditPrivate::finishChange(int validateFromState, bool update, bool edited)
2832 Q_Q(QSecureLineEdit);
2833 bool lineDirty = selDirty;
2836 bool wasValidInput = validInput;
2838 #ifndef QT_NO_VALIDATOR
2841 QString textCopy = text;
2842 int cursorCopy = cursor;
2843 validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
2845 if (text != textCopy) {
2846 setText(textCopy, cursorCopy);
2849 cursor = cursorCopy;
2853 if (validateFromState >= 0 && wasValidInput && !validInput) {
2854 undo(validateFromState);
2855 history.resize(undoState);
2856 if (modifiedState > undoState)
2862 lineDirty |= textDirty;
2865 secqstring actualText = maskData ? stripString(text) : text;
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
2875 #ifndef QT_NO_ACCESSIBILITY
2876 QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
2881 emit q->selectionChanged();
2883 if (lineDirty || update)
2885 emitCursorPositionChanged();
2888 void QSecureLineEditPrivate::emitCursorPositionChanged()
2890 Q_Q(QSecureLineEdit);
2891 if (cursor != lastCursorPos) {
2892 const int oldLast = lastCursorPos;
2893 lastCursorPos = cursor;
2894 emit q->cursorPositionChanged(oldLast, cursor);
2898 void QSecureLineEditPrivate::setText(const secqstring& txt, int pos, bool edited)
2900 Q_Q(QSecureLineEdit);
2901 q->resetInputContext();
2903 secqstring oldText = text;
2905 text = maskString(0, txt, true);
2906 text += clearString(text.size(), maxLength - text.size());
2908 text = txt.empty() ? txt : txt.substr(0, maxLength);
2911 modifiedState = undoState = 0;
2912 cursor = (pos < 0 || pos > text.size()) ? text.size() : pos;
2913 textDirty = (oldText != text);
2914 finishChange(-1, true, edited);
2918 void QSecureLineEditPrivate::setCursorVisible(bool visible)
2920 Q_Q(QSecureLineEdit);
2921 if ((bool)cursorVisible == visible)
2924 cursorVisible = visible;
2925 QRect r = cursorRect();
2932 void QSecureLineEditPrivate::addCommand(const Command& cmd)
2934 if (separator && undoState && history[undoState-1].type != Separator) {
2935 history.resize(undoState + 2);
2936 history[undoState++] = Command(Separator, cursor, 0, selstart, selend);
2938 history.resize(undoState + 1);
2941 history[undoState++] = cmd;
2944 void QSecureLineEditPrivate::insert(const secqstring& s)
2946 if (hasSelectedText())
2947 addCommand(Command(SetSelection, cursor, 0, selstart, selend));
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));
2954 text.replace(cursor, ms.length(), secqstring( ms.begin(), ms.end() ) );
2955 cursor += ms.length();
2956 cursor = nextMaskBlank(cursor);
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));
2966 void QSecureLineEditPrivate::del(bool wasBackspace)
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));
2973 text.replace(cursor, 1, clearString(cursor, 1));
2974 addCommand(Command(Insert, cursor, text[cursor], -1, -1));
2976 text.erase(cursor, 1);
2982 void QSecureLineEditPrivate::removeSelectedText()
2984 if (selstart < selend && selend <= (int) text.size()) {
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));
2996 for (i = selend-1; i >= selstart; --i)
2997 addCommand (Command(RemoveSelection, i, text[i], -1, -1));
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));
3004 text.erase(selstart, selend - selstart);
3006 if (cursor > selstart)
3007 cursor -= qMin(cursor, selend) - selstart;
3011 // adjust hscroll to avoid gap
3012 const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing());
3014 const QTextLine line = textLayout.lineAt(0);
3015 const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
3016 hscroll = qMin(hscroll, widthUsed);
3020 void QSecureLineEditPrivate::parseInputMask(const QString &maskFields)
3022 int delimiter = maskFields.indexOf(QLatin1Char(';'));
3023 if (maskFields.isEmpty() || delimiter == 0) {
3028 setText(secqstring());
3033 if (delimiter == -1) {
3034 blank = QLatin1Char(' ');
3035 inputMask = maskFields;
3037 inputMask = maskFields.left(delimiter);
3038 blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
3041 // calculate maxLength / maskData length
3044 for (int i=0; i<inputMask.length(); i++) {
3045 c = inputMask.at(i);
3046 if (i > 0 && inputMask.at(i-1) == QLatin1Char('\\')) {
3050 if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
3051 c != QLatin1Char('<') && c != QLatin1Char('>') &&
3052 c != QLatin1Char('{') && c != QLatin1Char('}') &&
3053 c != QLatin1Char('[') && c != QLatin1Char(']'))
3058 maskData = new MaskInputData[maxLength];
3060 MaskInputData::Casemode m = MaskInputData::NoCaseMode;
3063 bool escape = false;
3065 for (int i = 0; i < inputMask.length(); i++) {
3066 c = inputMask.at(i);
3069 maskData[index].maskChar = c;
3070 maskData[index].separator = s;
3071 maskData[index].caseMode = m;
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()) {
3107 maskData[index].maskChar = c;
3108 maskData[index].separator = s;
3109 maskData[index].caseMode = m;
3118 /* checks if the key is valid compared to the inputMask */
3119 bool QSecureLineEditPrivate::isValidInput(QChar key, QChar mask) const
3121 switch (mask.unicode()) {
3127 if (key.isLetter() || key == blank)
3131 if (key.isLetterOrNumber())
3135 if (key.isLetterOrNumber() || key == blank)
3143 if (key.isPrint() || key == blank)
3151 if (key.isNumber() || key == blank)
3155 if (key.isNumber() && key.digitValue() > 0)
3159 if ((key.isNumber() && key.digitValue() > 0) || key == blank)
3163 if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank)
3167 if (key == QLatin1Char('0') || key == QLatin1Char('1'))
3171 if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank)
3175 if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
3179 if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank)
3188 bool QSecureLineEditPrivate::hasAcceptableInput(const secqstring &str) const
3190 #ifndef QT_NO_VALIDATOR
3191 QString textCopy = str;
3192 int cursorCopy = cursor;
3193 if (validator && validator->validate(textCopy, cursorCopy)
3194 != QValidator::Acceptable)
3201 if (str.length() != maxLength)
3204 for (int i=0; i < maxLength; ++i) {
3205 if (maskData[i].separator) {
3206 if (str[i] != maskData[i].maskChar)
3209 if (!isValidInput(str[i], maskData[i].maskChar))
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.
3222 secqstring QSecureLineEditPrivate::maskString(uint pos, const secqstring &str, bool clear) const
3224 if (pos >= (uint)maxLength)
3225 return secqstring();
3228 fill = clear ? clearString(0, maxLength) : text;
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)
3241 if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) {
3242 switch (maskData[i].caseMode) {
3243 case MaskInputData::Upper:
3244 s += str[(int)strIndex].toUpper();
3246 case MaskInputData::Lower:
3247 s += str[(int)strIndex].toLower();
3250 s += str[(int)strIndex];
3254 // search for separator first
3255 int n = findInMask(i, true, true, str[(int)strIndex]);
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
3262 // search for valid blank if not
3263 n = findInMask(i, true, false, str[(int)strIndex]);
3265 s += fill.substr(i, n-i);
3266 switch (maskData[n].caseMode) {
3267 case MaskInputData::Upper:
3268 s += str[(int)strIndex].toUpper();
3270 case MaskInputData::Lower:
3271 s += str[(int)strIndex].toLower();
3274 s += str[(int)strIndex];
3276 i = n + 1; // updates i to find + 1
3292 Returns a "cleared" string with only separators and blank chars.
3293 Calling this when no inputMask is set is undefined.
3295 secqstring QSecureLineEditPrivate::clearString(uint pos, uint len) const
3297 if (pos >= (uint)maxLength)
3298 return secqstring();
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;
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".
3315 secqstring QSecureLineEditPrivate::stripString(const secqstring &str) const
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;
3326 if (str[i] != blank)
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
3335 if (pos >= maxLength || pos < 0)
3338 int end = forward ? maxLength : -1;
3339 int step = forward ? 1 : -1;
3343 if (findSeparator) {
3344 if (maskData[i].separator && maskData[i].maskChar == searchChar)
3347 if (!maskData[i].separator) {
3348 if (searchChar.isNull())
3350 else if (isValidInput(searchChar, maskData[i].maskChar))
3359 void QSecureLineEditPrivate::undo(int until)
3361 if (!isUndoAvailable())
3364 while (undoState && undoState > until) {
3365 Command& cmd = history[--undoState];
3368 text.erase(cmd.pos, 1);
3372 selstart = cmd.selStart;
3373 selend = cmd.selEnd;
3377 case RemoveSelection:
3378 text.insert(cmd.pos, &cmd.uc, 1);
3379 cursor = cmd.pos + 1;
3382 case DeleteSelection:
3383 text.insert(cmd.pos, &cmd.uc, 1);
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))
3397 emitCursorPositionChanged();
3400 void QSecureLineEditPrivate::redo() {
3401 if (!isRedoAvailable())
3404 while (undoState < (int)history.size()) {
3405 Command& cmd = history[undoState++];
3408 text.insert(cmd.pos, &cmd.uc, 1);
3409 cursor = cmd.pos + 1;
3412 selstart = cmd.selStart;
3413 selend = cmd.selEnd;
3418 case RemoveSelection:
3419 case DeleteSelection:
3420 text.erase(cmd.pos, 1);
3424 selstart = cmd.selStart;
3425 selend = cmd.selEnd;
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))
3437 emitCursorPositionChanged();
3441 \fn void QSecureLineEdit::repaintArea(int a, int b)
3443 Use update() instead.
3447 \fn void QSecureLineEdit::cursorLeft(bool mark, int steps)
3449 Use cursorForward() with a negative number of steps instead. For
3450 example, cursorForward(mark, -steps).
3454 \fn void QSecureLineEdit::cursorRight(bool mark, int steps)
3456 Use cursorForward() instead.
3460 \fn bool QSecureLineEdit::frame() const
3462 Use hasFrame() instead.
3466 \fn void QSecureLineEdit::clearValidator()
3468 Use setValidator(0) instead.
3472 \fn bool QSecureLineEdit::hasMarkedText() const
3474 Use hasSelectedText() instead.
3478 \fn QString QSecureLineEdit::markedText() const
3480 Use selectedText() instead.
3484 \fn void QSecureLineEdit::setFrameRect(QRect)
3489 \fn QRect QSecureLineEdit::frameRect() const
3493 \enum QSecureLineEdit::DummyFrame
3506 \value GroupBoxPanel
3511 \value LineEditPanel
3512 \value TabWidgetPanel
3517 \fn void QSecureLineEdit::setFrameShadow(DummyFrame)
3522 \fn DummyFrame QSecureLineEdit::frameShadow() const
3527 \fn void QSecureLineEdit::setFrameShape(DummyFrame)
3532 \fn DummyFrame QSecureLineEdit::frameShape() const
3537 \fn void QSecureLineEdit::setFrameStyle(int)
3542 \fn int QSecureLineEdit::frameStyle() const
3547 \fn int QSecureLineEdit::frameWidth() const
3552 \fn void QSecureLineEdit::setLineWidth(int)
3557 \fn int QSecureLineEdit::lineWidth() const
3562 \fn void QSecureLineEdit::setMargin(int margin)
3563 Sets the width of the margin around the contents of the widget to \a margin.
3565 Use QWidget::setContentsMargins() instead.
3566 \sa margin(), QWidget::setContentsMargins()
3570 \fn int QSecureLineEdit::margin() const
3571 Returns the with of the the margin around the contents of the widget.
3573 Use QWidget::getContentsMargins() instead.
3574 \sa setMargin(), QWidget::getContentsMargins()
3578 \fn void QSecureLineEdit::setMidLineWidth(int)
3583 \fn int QSecureLineEdit::midLineWidth() const
3589 #include "qsecurelineedit.moc"
3591 #endif // QT_NO_LINEEDIT