[svn] pinentry - r191 - trunk/qt4

svn author marcus cvs at cvs.gnupg.org
Thu Feb 19 17:18:41 CET 2009


Author: marcus
Date: 2009-02-19 17:18:41 +0100 (Thu, 19 Feb 2009)
New Revision: 191

Added:
   trunk/qt4/pinentrydialog.moc
   trunk/qt4/qsecurelineedit.cpp
   trunk/qt4/qsecurelineedit.h
   trunk/qt4/qsecurelineedit.moc
   trunk/qt4/qsecurelineedit_p.h
   trunk/qt4/secstring.cpp
   trunk/qt4/secstring.h
Modified:
   trunk/qt4/Makefile.am
   trunk/qt4/main.cpp
   trunk/qt4/pinentrydialog.cpp
   trunk/qt4/pinentrydialog.h
Log:
2009-02-19  Marcus Brinkmann  <marcus at g10code.de>

	* qt4/Makefile.am, qt4/main.cpp, qt4/pinentrydialog.cpp,
	qt4/pinentrydialog.h: Changes to use secure memory.
	* qt4/pinentrydialog.moc, qt4/qsecurelineedit.moc: New files.
	* qt4/qsecurelineedit.cpp, qt4/qsecurelineedit.h,
	qt4/qsecurelineedit_p.h, qt4/secstring.h, qt4/secstring.cpp: New
	files.
	Submitted by Marc Mutz <marc at kdab.net>.


[The diff below has been truncated]

Modified: trunk/qt4/Makefile.am
===================================================================
--- trunk/qt4/Makefile.am	2008-12-08 16:45:52 UTC (rev 190)
+++ trunk/qt4/Makefile.am	2009-02-19 16:18:41 UTC (rev 191)
@@ -31,7 +31,7 @@
 endif
 
 
-AM_CPPFLAGS = -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem \
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem \
 	$(ncurses_include) -I$(top_srcdir)/pinentry
 AM_CXXFLAGS = $(QT4_CORE_CFLAGS) $(QT4_GUI_CFLAGS)
 pinentry_qt4_LDADD = $(QT4_CORE_LIBS) $(QT4_GUI_LIBS) $(libcurses) \
@@ -39,11 +39,4 @@
 	$(top_builddir)/secmem/libsecmem.a $(LIBCAP)
 
 pinentry_qt4_SOURCES = pinentrydialog.h pinentrydialog.cpp \
-	main.cpp 
-nodist_pinentry_qt4_SOURCES = pinentrydialog.moc
-BUILT_SOURCES = pinentrydialog.moc
-
-CLEANFILES = $(nodist_pinentry_qt4_SOURCES)
-
-%.moc: $(srcdir)/%.h
-	$(MOC) $< -o $@
+	main.cpp secstring.h secstring.cpp qsecurelineedit.h qsecurelineedit.cpp

Modified: trunk/qt4/main.cpp
===================================================================
--- trunk/qt4/main.cpp	2008-12-08 16:45:52 UTC (rev 190)
+++ trunk/qt4/main.cpp	2009-02-19 16:18:41 UTC (rev 191)
@@ -1,12 +1,13 @@
 /* 
    main.cpp - A (not yet) secure Qt 4 dialog for PIN entry.
 
-   Copyright (C) 2002 Klarälvdalens Datakonsult AB
+   Copyright (C) 2002, 2008 Klarälvdalens Datakonsult AB (KDAB)
    Copyright (C) 2003 g10 Code GmbH
    Copyright 2007 Ingo Klöcker
 
    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>.
    Modified by Marcus Brinkmann <marcus at g10code.de>.
+   Modified by Marc Mutz <marc at kdab.com>
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -24,25 +25,17 @@
 */
 
 
-#include <stdlib.h>
-#include <errno.h>
+#include "pinentrydialog.h"
+#include "pinentry.h"
 
 #include <qapplication.h>
 #include <QString>
 #include <qwidget.h>
 #include <qmessagebox.h>
-// #include "secqstring.h"
 
-#include "pinentrydialog.h"
-
-#include "pinentry.h"
-
-extern "C"
-{
-#include "memory.h"
-}
-
 #include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
 
 #ifdef FALLBACK_CURSES
 #include <pinentry-curses.h>
@@ -52,7 +45,7 @@
 class ForeignWidget : public QWidget
 {
 public:
-  ForeignWidget( WId wid ) : QWidget( 0 )
+  explicit ForeignWidget( WId wid ) : QWidget( 0 )
   {
     QWidget::destroy();
     create( wid, false, false );
@@ -82,9 +75,7 @@
       pinentry.setPrompt (QString::fromUtf8 (pe->prompt));
       pinentry.setDescription (QString::fromUtf8 (pe->description));
       /* If we reuse the same dialog window.  */
-#if 0
-      pinentry.setText (SecQString::null);
-#endif
+      pinentry.setPin (secqstring());
 
       if (pe->ok)
 	pinentry.setOkText (QString::fromUtf8 (pe->ok));
@@ -97,8 +88,8 @@
       if (!ret)
 	return -1;
 
-      QByteArray pinUtf8 = pinentry.text().toUtf8();
-      char *pin = pinUtf8.data();
+      const secstring pinUtf8 = toUtf8( pinentry.pin() );
+      const char *pin = pinUtf8.data();
       if (!pin)
 	return -1;
 
@@ -109,11 +100,9 @@
 	  if (pe->pin)
 	    {
 	      strcpy (pe->pin, pin);
-	      // ::secmem_free (pin);
 	      return len;
 	    }
 	}
-      // ::secmem_free (pin);
       return -1;
     }
   else

Modified: trunk/qt4/pinentrydialog.cpp
===================================================================
--- trunk/qt4/pinentrydialog.cpp	2008-12-08 16:45:52 UTC (rev 190)
+++ trunk/qt4/pinentrydialog.cpp	2009-02-19 16:18:41 UTC (rev 191)
@@ -1,7 +1,7 @@
 /* 
    pinentrydialog.cpp - A (not yet) secure Qt 4 dialog for PIN entry.
 
-   Copyright (C) 2002 Klarälvdalens Datakonsult AB
+   Copyright (C) 2002, 2008 Klarälvdalens Datakonsult AB (KDAB)
    Copyright 2007 Ingo Klöcker
 
    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>.
@@ -21,6 +21,10 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
 
+#include "pinentrydialog.h"
+
+#include "qsecurelineedit.h"
+
 #include <QVBoxLayout>
 #include <QHBoxLayout>
 #include <QPushButton>
@@ -28,14 +32,6 @@
 #include <QLabel>
 #include <QMessageBox>
 
-#ifdef WITH_SECURE_QSTRING
-#include "secqlineedit.h"
-#else
-#include <QLineEdit>
-#endif
-
-#include "pinentrydialog.h"
-
 PinEntryDialog::PinEntryDialog( QWidget* parent, const char* name, bool modal )
   : QDialog( parent ), _grabbed( false )
 {
@@ -65,9 +61,8 @@
   top->addLayout( l );
   _prompt = new QLabel( this );
   l->addWidget( _prompt );
-  _edit = new SecQLineEdit( this );
+  _edit = new QSecureLineEdit( this );
   _edit->setMaxLength( 256 );
-  _edit->setEchoMode( SecQLineEdit::Password );
   l->addWidget( _edit );
 
   l = new QHBoxLayout();
@@ -95,15 +90,15 @@
   _edit->setFocus();
 }
 
-void PinEntryDialog::paintEvent( QPaintEvent* ev )
+void PinEntryDialog::showEvent( QShowEvent* ev )
 {
   // Grab keyboard when widget is mapped to screen
   // It might be a little weird to do it here, but it works!
+  QDialog::showEvent( ev );
   if( !_grabbed ) {
     _edit->grabKeyboard();
     _grabbed = true;
   }
-  QDialog::paintEvent( ev );
 }
 
 void PinEntryDialog::hideEvent( QHideEvent* ev )
@@ -145,14 +140,14 @@
   return _error->text();
 }
 
-void PinEntryDialog::setText( const SecQString& txt ) 
+void PinEntryDialog::setPin( const secqstring & txt ) 
 {
-  _edit->setText( txt );
+    _edit->setText( txt );
 }
 
-SecQString PinEntryDialog::text() const 
+secqstring PinEntryDialog::pin() const 
 {
-  return _edit->text();
+    return _edit->text();
 }
 
 void PinEntryDialog::setPrompt( const QString& txt ) 

Modified: trunk/qt4/pinentrydialog.h
===================================================================
--- trunk/qt4/pinentrydialog.h	2008-12-08 16:45:52 UTC (rev 190)
+++ trunk/qt4/pinentrydialog.h	2009-02-19 16:18:41 UTC (rev 191)
@@ -1,7 +1,7 @@
 /* 
    pinentrydialog.h - A (not yet) secure Qt 4 dialog for PIN entry.
 
-   Copyright (C) 2002 Klarälvdalens Datakonsult AB
+   Copyright (C) 2002, 2008 Klarälvdalens Datakonsult AB (KDAB)
    Copyright 2007 Ingo Klöcker
 
    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>.
@@ -26,28 +26,25 @@
 
 #include <QDialog>
 
+#include "secstring.h"
+
 class QLabel;
 class QPushButton;
-#ifdef WITH_SECURE_QSTRING
-class SecQLineEdit;
-class SecQString;
-#else
-class QLineEdit;
+class QSecureLineEdit;
 class QString;
-#define SecQLineEdit QLineEdit
-#define SecQString QString
-#endif
 
+
+
 class PinEntryDialog : public QDialog {
   Q_OBJECT
 
   Q_PROPERTY( QString description READ description WRITE setDescription )
   Q_PROPERTY( QString error READ error WRITE setError )
-    //  Q_PROPERTY( SecQString text READ text WRITE setText )
+  Q_PROPERTY( secqstring pin READ pin WRITE setPin )
   Q_PROPERTY( QString prompt READ prompt WRITE setPrompt )
 public:
   friend class PinEntryController; // TODO: remove when assuan lets me use Qt eventloop.
-  PinEntryDialog( QWidget* parent = 0, const char* name = 0, bool modal = false );
+  explicit PinEntryDialog( QWidget* parent = 0, const char* name = 0, bool modal = false );
 
   void setDescription( const QString& );
   QString description() const;
@@ -55,8 +52,8 @@
   void setError( const QString& );
   QString error() const;
 
-  void setText( const SecQString& );
-  SecQString text() const;
+  void setPin( const secqstring & );
+  secqstring pin() const;
 
   void setPrompt( const QString& );
   QString prompt() const;
@@ -69,16 +66,16 @@
   void rejected();
 
 protected:
-  virtual void keyPressEvent( QKeyEvent *e );
-  virtual void hideEvent( QHideEvent* );
-  virtual void paintEvent( QPaintEvent* );
+  /* reimp */ void keyPressEvent( QKeyEvent *e );
+  /* reimp */ void hideEvent( QHideEvent* );
+  /* reimp */ void showEvent( QShowEvent* );
 
 private:
   QLabel*    _icon;
   QLabel*    _desc;
   QLabel*    _error;
   QLabel*    _prompt;
-  SecQLineEdit* _edit;
+  QSecureLineEdit* _edit;
   QPushButton* _ok;
   QPushButton* _cancel;  
   bool       _grabbed;

Added: trunk/qt4/pinentrydialog.moc
===================================================================
--- trunk/qt4/pinentrydialog.moc	                        (rev 0)
+++ trunk/qt4/pinentrydialog.moc	2009-02-19 16:18:41 UTC (rev 191)
@@ -0,0 +1,126 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'pinentrydialog.h'
+**
+** Created: Mon Oct 20 09:30:12 2008
+**      by: The Qt Meta Object Compiler version 59 (Qt 4.4.1)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "pinentrydialog.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'pinentrydialog.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 59
+#error "This file was generated using the moc from 4.4.1. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_PinEntryDialog[] = {
+
+ // content:
+       1,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       2,   10, // methods
+       4,   20, // properties
+       0,    0, // enums/sets
+
+ // signals: signature, parameters, type, tag, flags
+      16,   15,   15,   15, 0x05,
+      27,   15,   15,   15, 0x05,
+
+ // properties: name, type, flags
+      46,   38, 0x0a095103,
+      58,   38, 0x0a095103,
+      75,   64, 0x0009510b,
+      79,   38, 0x0a095103,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_PinEntryDialog[] = {
+    "PinEntryDialog\0\0accepted()\0rejected()\0"
+    "QString\0description\0error\0secqstring\0"
+    "pin\0prompt\0"
+};
+
+const QMetaObject PinEntryDialog::staticMetaObject = {
+    { &QDialog::staticMetaObject, qt_meta_stringdata_PinEntryDialog,
+      qt_meta_data_PinEntryDialog, 0 }
+};
+
+const QMetaObject *PinEntryDialog::metaObject() const
+{
+    return &staticMetaObject;
+}
+
+void *PinEntryDialog::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_PinEntryDialog))
+        return static_cast<void*>(const_cast< PinEntryDialog*>(this));
+    return QDialog::qt_metacast(_clname);
+}
+
+int PinEntryDialog::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QDialog::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: accepted(); break;
+        case 1: rejected(); break;
+        }
+        _id -= 2;
+    }
+#ifndef QT_NO_PROPERTIES
+      else if (_c == QMetaObject::ReadProperty) {
+        void *_v = _a[0];
+        switch (_id) {
+        case 0: *reinterpret_cast< QString*>(_v) = description(); break;
+        case 1: *reinterpret_cast< QString*>(_v) = error(); break;
+        case 2: *reinterpret_cast< secqstring*>(_v) = pin(); break;
+        case 3: *reinterpret_cast< QString*>(_v) = prompt(); break;
+        }
+        _id -= 4;
+    } else if (_c == QMetaObject::WriteProperty) {
+        void *_v = _a[0];
+        switch (_id) {
+        case 0: setDescription(*reinterpret_cast< QString*>(_v)); break;
+        case 1: setError(*reinterpret_cast< QString*>(_v)); break;
+        case 2: setPin(*reinterpret_cast< secqstring*>(_v)); break;
+        case 3: setPrompt(*reinterpret_cast< QString*>(_v)); break;
+        }
+        _id -= 4;
+    } else if (_c == QMetaObject::ResetProperty) {
+        _id -= 4;
+    } else if (_c == QMetaObject::QueryPropertyDesignable) {
+        _id -= 4;
+    } else if (_c == QMetaObject::QueryPropertyScriptable) {
+        _id -= 4;
+    } else if (_c == QMetaObject::QueryPropertyStored) {
+        _id -= 4;
+    } else if (_c == QMetaObject::QueryPropertyEditable) {
+        _id -= 4;
+    } else if (_c == QMetaObject::QueryPropertyUser) {
+        _id -= 4;
+    }
+#endif // QT_NO_PROPERTIES
+    return _id;
+}
+
+// SIGNAL 0
+void PinEntryDialog::accepted()
+{
+    QMetaObject::activate(this, &staticMetaObject, 0, 0);
+}
+
+// SIGNAL 1
+void PinEntryDialog::rejected()
+{
+    QMetaObject::activate(this, &staticMetaObject, 1, 0);
+}
+QT_END_MOC_NAMESPACE

Added: trunk/qt4/qsecurelineedit.cpp
===================================================================
--- trunk/qt4/qsecurelineedit.cpp	                        (rev 0)
+++ trunk/qt4/qsecurelineedit.cpp	2009-02-19 16:18:41 UTC (rev 191)
@@ -0,0 +1,3591 @@
+/* 
+   qsecurelineedit.cpp - QLineEdit that uses secmem
+
+   Copyright (C) 2008 Klarälvdalens Datakonsult AB (KDAB)
+
+   Written by Marc Mutz <marc at kdab.com>.
+   
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+// the following code has been ported from QString to secqstring.
+// The licence of the original code:
+
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** Licensees holding a valid Qt License Agreement may use this file in
+** accordance with the rights, responsibilities and obligations
+** contained therein.  Please consult your licensing agreement or
+** contact sales at trolltech.com if any conditions of this licensing
+** agreement are not clear to you.
+**
+** Further information about Qt licensing is available at:
+** http://www.trolltech.com/products/qt/licensing.html or by
+** contacting info at trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "qlineedit.h" // added to pick up qt defines
+
+#ifndef QT_NO_LINEEDIT
+#include "qaction.h"
+#include "qapplication.h"
+#include "qclipboard.h"
+#include "qdrag.h"
+#include "qdrawutil.h"
+#include "qevent.h"
+#include "qfontmetrics.h"
+#include "qmenu.h"
+#include "qpainter.h"
+#include "qpixmap.h"
+#include "qpointer.h"
+#include "qstringlist.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qtimer.h"
+#include "qvalidator.h"
+#include "qvariant.h"
+#include "qvector.h"
+#include "qwhatsthis.h"
+#include "qdebug.h"
+#include "qtextedit.h"
+//#include <private/qtextedit_p.h>
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qlist.h"
+#endif
+#include "qabstractitemview.h"
+#ifdef QT_NO_STYLE_STYLESHEET
+#include "private/qstylesheetstyle_p.h"
+#endif
+
+#ifndef QT_NO_SHORTCUT
+#include "qkeysequence.h"
+#define ACCEL_KEY(k) QLatin1String("\t") + QString(QKeySequence(k))
+#else
+#define ACCEL_KEY(k) QString()
+#endif
+
+#include <limits.h>
+
+// these go last so they don't contaminate other Qt headers
+#include "qsecurelineedit_p.h"
+#include "qsecurelineedit.h"
+
+#define verticalMargin 1
+#define horizontalMargin 2
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_MAC
+extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
+#endif
+
+/*!
+    Initialize \a option with the values from this QSecureLineEdit. This method
+    is useful for subclasses when they need a QStyleOptionFrame or QStyleOptionFrameV2, but don't want
+    to fill in all the information themselves. This function will check the version
+    of the QStyleOptionFrame and fill in the additional values for a
+    QStyleOptionFrameV2.
+
+    \sa QStyleOption::initFrom()
+*/
+void QSecureLineEdit::initStyleOption(QStyleOptionFrame *option) const
+{
+    if (!option)
+        return;
+
+    Q_D(const QSecureLineEdit);
+    option->initFrom(this);
+    option->rect = contentsRect();
+    option->lineWidth = d->frame ? style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this)
+                                 : 0;
+    option->midLineWidth = 0;
+    option->state |= QStyle::State_Sunken;
+    if (d->readOnly)
+        option->state |= QStyle::State_ReadOnly;
+#ifdef QT_KEYPAD_NAVIGATION
+    if (hasEditFocus())
+        option->state |= QStyle::State_HasEditFocus;
+#endif
+    if (QStyleOptionFrameV2 *optionV2 = qstyleoption_cast<QStyleOptionFrameV2 *>(option))
+        optionV2->features = QStyleOptionFrameV2::None;
+}
+
+/*!
+    \class QSecureLineEdit
+    \brief The QSecureLineEdit widget is a one-line text editor.
+
+    \ingroup basicwidgets
+    \mainclass
+
+    A line edit allows the user to enter and edit a single line of
+    plain text with a useful collection of editing functions,
+    including undo and redo, cut and paste, and drag and drop.
+
+    By changing the echoMode() of a line edit, it can also be used as
+    a "write-only" field, for inputs such as passwords.
+
+    The length of the text can be constrained to maxLength(). The text
+    can be arbitrarily constrained using a validator() or an
+    inputMask(), or both.
+
+    A related class is QTextEdit which allows multi-line, rich text
+    editing.
+
+    You can change the text with setText() or insert(). The text is
+    retrieved with text(); the displayed text (which may be different,
+    see \l{EchoMode}) is retrieved with displayText(). Text can be
+    selected with setSelection() or selectAll(), and the selection can
+    be cut(), copy()ied and paste()d. The text can be aligned with
+    setAlignment().
+
+    When the text changes the textChanged() signal is emitted; when
+    the text changes other than by calling setText() the textEdited()
+    signal is emitted; when the cursor is moved the
+    cursorPositionChanged() signal is emitted; and when the Return or
+    Enter key is pressed the returnPressed() signal is emitted.
+
+    When editing is finished, either because the line edit lost focus
+    or Return/Enter is pressed the editingFinished() signal is
+    emitted.
+
+    Note that if there is a validator set on the line edit, the
+    returnPressed()/editingFinished() signals will only be emitted if
+    the validator returns QValidator::Acceptable.
+
+    By default, QSecureLineEdits have a frame as specified by the Windows
+    and Motif style guides; you can turn it off by calling
+    setFrame(false).
+
+    The default key bindings are described below. The line edit also
+    provides a context menu (usually invoked by a right mouse click)
+    that presents some of these editing options.
+    \target desc
+    \table
+    \header \i Keypress \i Action
+    \row \i Left Arrow \i Moves the cursor one character to the left.
+    \row \i Shift+Left Arrow \i Moves and selects text one character to the left.
+    \row \i Right Arrow \i Moves the cursor one character to the right.
+    \row \i Shift+Right Arrow \i Moves and selects text one character to the right.
+    \row \i Home \i Moves the cursor to the beginning of the line.
+    \row \i End \i Moves the cursor to the end of the line.
+    \row \i Backspace \i Deletes the character to the left of the cursor.
+    \row \i Ctrl+Backspace \i Deletes the word to the left of the cursor.
+    \row \i Delete \i Deletes the character to the right of the cursor.
+    \row \i Ctrl+Delete \i Deletes the word to the right of the cursor.
+    \row \i Ctrl+A \i Select all.
+    \row \i Ctrl+C \i Copies the selected text to the clipboard.
+    \row \i Ctrl+Insert \i Copies the selected text to the clipboard.
+    \row \i Ctrl+K \i Deletes to the end of the line.
+    \row \i Ctrl+V \i Pastes the clipboard text into line edit.
+    \row \i Shift+Insert \i Pastes the clipboard text into line edit.
+    \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard.
+    \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard.
+    \row \i Ctrl+Z \i Undoes the last operation.
+    \row \i Ctrl+Y \i Redoes the last undone operation.
+    \endtable
+
+    Any other key sequence that represents a valid character, will
+    cause the character to be inserted into the line edit.
+
+    \table 100%
+    \row \o \inlineimage macintosh-lineedit.png Screenshot of a Macintosh style line edit
+         \o A line edit shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
+    \row \o \inlineimage windows-lineedit.png Screenshot of a Windows XP style line edit
+         \o A line edit shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
+    \row \o \inlineimage plastique-lineedit.png Screenshot of a Plastique style line edit
+         \o A line edit shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
+    \endtable
+
+    \sa QTextEdit, QLabel, QComboBox, {fowler}{GUI Design Handbook: Field, Entry}, {Line Edits Example}
+*/
+
+
+/*!
+    \fn void QSecureLineEdit::textChanged(const QString &text)
+
+    This signal is emitted whenever the text changes. The \a text
+    argument is the new text.
+
+    Unlike textEdited(), this signal is also emitted when the text is
+    changed programmatically, for example, by calling setText().
+*/
+
+/*!
+    \fn void QSecureLineEdit::textEdited(const QString &text)
+
+    This signal is emitted whenever the text is edited. The \a text
+    argument is the next text.
+
+    Unlike textChanged(), this signal is not emitted when the text is
+    changed programmatically, for example, by calling setText().
+*/
+
+/*!
+    \fn void QSecureLineEdit::cursorPositionChanged(int old, int new)
+
+    This signal is emitted whenever the cursor moves. The previous
+    position is given by \a old, and the new position by \a new.
+
+    \sa setCursorPosition(), cursorPosition()
+*/
+
+/*!
+    \fn void QSecureLineEdit::selectionChanged()
+
+    This signal is emitted whenever the selection changes.
+
+    \sa hasSelectedText(), selectedText()
+*/
+
+/*!
+    Constructs a line edit with no text.
+
+    The maximum text length is set to 32767 characters.
+
+    The \a parent argument is sent to the QWidget constructor.
+
+    \sa setText(), setMaxLength()
+*/
+QSecureLineEdit::QSecureLineEdit(QWidget* parent)
+    : QWidget(parent,0), m_d(new QSecureLineEditPrivate(this))
+{
+    Q_D(QSecureLineEdit);
+    d->init(secqstring());
+}
+
+/*!
+    Constructs a line edit containing the text \a contents.
+
+    The cursor position is set to the end of the line and the maximum
+    text length to 32767 characters.
+
+    The \a parent and argument is sent to the QWidget
+    constructor.
+
+    \sa text(), setMaxLength()
+*/
+QSecureLineEdit::QSecureLineEdit(const secqstring& contents, QWidget* parent)
+    : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
+{
+    Q_D(QSecureLineEdit);
+    d->init(contents);
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+    Constructs a line edit with no text.
+
+    The maximum text length is set to 32767 characters.
+
+    The \a parent and \a name arguments are sent to the QWidget constructor.
+
+    \sa setText(), setMaxLength()
+*/
+QSecureLineEdit::QSecureLineEdit(QWidget* parent, const char* name)
+    : QWidget(parent,0), m_d(new QSecureLineEditPrivate(this))
+{
+    Q_D(QSecureLineEdit);
+    setObjectName(QString::fromAscii(name));
+    d->init(secqstring());
+}
+
+/*!
+    Constructs a line edit containing the text \a contents.
+
+    The cursor position is set to the end of the line and the maximum
+    text length to 32767 characters.
+
+    The \a parent and \a name arguments are sent to the QWidget
+    constructor.
+
+    \sa text(), setMaxLength()
+*/
+
+QSecureLineEdit::QSecureLineEdit(const secqstring& contents, QWidget* parent, const char* name)
+    : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
+{
+    Q_D(QSecureLineEdit);
+    setObjectName(QString::fromAscii(name));
+    d->init(contents);
+}
+
+/*!
+    Constructs a line edit with an input \a inputMask and the text \a
+    contents.
+
+    The cursor position is set to the end of the line and the maximum
+    text length is set to the length of the mask (the number of mask
+    characters and separators).
+
+    The \a parent and \a name arguments are sent to the QWidget
+    constructor.
+
+    \sa setMask() text()
+*/
+QSecureLineEdit::QSecureLineEdit(const QString& contents, const QString &inputMask, QWidget* parent, const char* name)
+    : QWidget(parent, 0), m_d(new QSecureLineEditPrivate(this))
+{
+    Q_D(QSecureLineEdit);
+    setObjectName(QString::fromAscii(name));
+    d->parseInputMask(inputMask);
+    if (d->maskData) {
+        QString ms = d->maskString(0, contents);
+        d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length()));
+        d->cursor = d->nextMaskBlank(ms.length());
+    } else {
+        d->init(contents);
+    }
+}
+#endif
+
+/*!
+    Destroys the line edit.
+*/
+
+QSecureLineEdit::~QSecureLineEdit()
+{
+    delete m_d;
+}
+
+
+/*!
+    \property QSecureLineEdit::text
+    \brief the line edit's text
+
+    Setting this property clears the selection, clears the undo/redo
+    history, moves the cursor to the end of the line and resets the
+    \l modified property to false. The text is not validated when
+    inserted with setText().
+
+    The text is truncated to maxLength() length.
+
+    \sa insert(), clear()
+*/
+secqstring QSecureLineEdit::text() const
+{
+    Q_D(const QSecureLineEdit);
+    secqstring res = d->text;
+    if (d->maskData)
+        res = d->stripString(d->text);
+    return res;//(res.isNull() ? QString::fromLatin1("") : res);
+}
+
+void QSecureLineEdit::setText(const secqstring& text)
+{
+    Q_D(QSecureLineEdit);
+    d->setText(text, -1, false);
+#ifdef QT_KEYPAD_NAVIGATION
+    d->origText = d->text;
+#endif
+}
+
+
+/*!
+    \property QSecureLineEdit::displayText
+    \brief the displayed text
+
+    If \l echoMode is \l Normal this returns the same as text(); if
+    \l EchoMode is \l Password or \l PasswordEchoOnEdit it returns a string of asterisks
+    text().length() characters long, e.g. "******"; if \l EchoMode is
+    \l NoEcho returns an empty string, "".
+
+    \sa setEchoMode() text() EchoMode
+*/
+
+secqstring QSecureLineEdit::displayText() const
+{
+    Q_D(const QSecureLineEdit);
+    if (d->echoMode == NoEcho)
+        return secqstring();
+    secqstring res = d->text;
+
+    if (d->echoMode == Password || d->echoMode == PasswordEchoOnEdit) {
+        QStyleOptionFrameV2 opt;
+        initStyleOption(&opt);
+        return secqstring( res.size(), style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this) );
+        //res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
+    }
+    return res;//(res.isNull() ? QString::fromLatin1("") : res);
+}
+
+
+/*!
+    \property QSecureLineEdit::maxLength
+    \brief the maximum permitted length of the text
+
+    If the text is too long, it is truncated at the limit.
+
+    If truncation occurs any selected text will be unselected, the
+    cursor position is set to 0 and the first part of the string is
+    shown.
+
+    If the line edit has an input mask, the mask defines the maximum
+    string length.
+
+    \sa inputMask
+*/
+
+int QSecureLineEdit::maxLength() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->maxLength;
+}
+
+void QSecureLineEdit::setMaxLength(int maxLength)
+{
+    Q_D(QSecureLineEdit);
+    if (d->maskData)
+        return;
+    d->maxLength = maxLength;
+    setText(d->text);
+}
+
+
+
+/*!
+    \property QSecureLineEdit::frame
+    \brief whether the line edit draws itself with a frame
+
+    If enabled (the default) the line edit draws itself inside a
+    frame, otherwise the line edit draws itself without any frame.
+*/
+bool QSecureLineEdit::hasFrame() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->frame;
+}
+
+
+void QSecureLineEdit::setFrame(bool enable)
+{
+    Q_D(QSecureLineEdit);
+    d->frame = enable;
+    update();
+    updateGeometry();
+}
+
+
+/*!
+    \enum QSecureLineEdit::EchoMode
+
+    This enum type describes how a line edit should display its
+    contents.
+
+    \value Normal   Display characters as they are entered. This is the
+                    default.
+    \value NoEcho   Do not display anything. This may be appropriate
+                    for passwords where even the length of the
+                    password should be kept secret.
+    \value Password  Display asterisks instead of the characters
+                    actually entered.
+    \value PasswordEchoOnEdit Display characters as they are entered
+                    while editing otherwise display asterisks.
+
+    \sa setEchoMode() echoMode()
+*/
+
+
+/*!
+    \property QSecureLineEdit::echoMode
+    \brief the line edit's echo mode
+
+    The initial setting is \l Normal, but QSecureLineEdit also supports \l
+    NoEcho, \l Password and \l PasswordEchoOnEdit modes.
+
+    The widget's display and the ability to copy or drag the text is
+    affected by this setting.
+
+    \sa EchoMode displayText()
+*/
+
+QSecureLineEdit::EchoMode QSecureLineEdit::echoMode() const
+{
+    Q_D(const QSecureLineEdit);
+    return (EchoMode) d->echoMode;
+}
+
+void QSecureLineEdit::setEchoMode(EchoMode mode)
+{
+    Q_D(QSecureLineEdit);
+    if(mode == (EchoMode)d->echoMode)
+        return;
+    setAttribute(Qt::WA_InputMethodEnabled, mode == Normal || mode == PasswordEchoOnEdit);
+    d->echoMode = mode;
+    d->updateTextLayout();
+    update();
+#ifdef Q_WS_MAC
+    if (hasFocus())
+        qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
+#endif
+}
+
+
+#ifndef QT_NO_VALIDATOR
+/*!
+    Returns a pointer to the current input validator, or 0 if no
+    validator has been set.
+
+    \sa setValidator()
+*/
+
+const QValidator * QSecureLineEdit::validator() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->validator;
+}
+
+/*!
+    Sets this line edit to only accept input that the validator, \a v,
+    will accept. This allows you to place any arbitrary constraints on
+    the text which may be entered.
+
+    If \a v == 0, setValidator() removes the current input validator.
+    The initial setting is to have no input validator (i.e. any input
+    is accepted up to maxLength()).
+
+    \sa validator() QIntValidator QDoubleValidator QRegExpValidator
+*/
+
+void QSecureLineEdit::setValidator(const QValidator *v)
+{
+    Q_D(QSecureLineEdit);
+    d->validator = const_cast<QValidator*>(v);
+}
+#endif // QT_NO_VALIDATOR
+
+#ifndef QT_NO_COMPLETER
+/*!
+    \since 4.2
+
+    Sets this line edit to provide auto completions from the completer, \a c.
+    The completion mode is set using QCompleter::setCompletionMode().
+
+    To use a QCompleter with a QValidator or QSecureLineEdit::inputMask, you need to
+    ensure that the model provided to QCompleter contains valid entries. You can
+    use the QSortFilterProxyModel to ensure that the QCompleter's model contains
+    only valid entries.
+
+    If \a c == 0, setCompleter() removes the current completer, effectively
+    disabling auto completion.
+
+    \sa QCompleter
+*/
+void QSecureLineEdit::setCompleter(QCompleter *c)
+{
+    Q_D(QSecureLineEdit);
+    if (c == d->completer)
+        return;
+    if (d->completer) {
+        disconnect(d->completer, 0, this, 0);
+        d->completer->setWidget(0);
+        if (d->completer->parent() == this)
+            delete d->completer;
+    }
+    d->completer = c;
+    if (!c)
+        return;
+    if (c->widget() == 0)
+        c->setWidget(this);
+    if (hasFocus()) {
+        QObject::connect(d->completer, SIGNAL(activated(QString)),
+                         this, SLOT(setText(QString)));
+        QObject::connect(d->completer, SIGNAL(highlighted(QString)),
+                         this, SLOT(_q_completionHighlighted(QString)));
+    }
+}
+
+/*!
+    \since 4.2
+
+    Returns the current QCompleter that provides completions.
+*/
+QCompleter *QSecureLineEdit::completer() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->completer;
+}
+
+// looks for an enabled item iterating forward(dir=1)/backward(dir=-1) from the
+// current row based. dir=0 indicates a new completion prefix was set.
+bool QSecureLineEditPrivate::advanceToEnabledItem(int dir)
+{
+    int start = completer->currentRow();
+    if (start == -1)
+        return false;
+    int i = start + dir;
+    if (dir == 0) dir = 1;
+    do {
+        if (!completer->setCurrentRow(i)) {
+            if (!completer->wrapAround())
+                break;
+            i = i > 0 ? 0 : completer->completionCount() - 1;
+        } else {
+            QModelIndex currentIndex = completer->currentIndex();
+            if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
+                return true;
+            i += dir;
+        }
+    } while (i != start);
+
+    completer->setCurrentRow(start); // restore
+    return false;
+}
+
+void QSecureLineEditPrivate::complete(int key)
+{
+    if (!completer || readOnly || echoMode != QSecureLineEdit::Normal)
+        return;
+
+    if (completer->completionMode() == QCompleter::InlineCompletion) {
+        if (key == Qt::Key_Backspace)
+            return;
+        int n = 0;
+        if (key == Qt::Key_Up || key == Qt::Key_Down) {
+            if (selend != 0 && selend != text.length())
+                return;
+            QString prefix = hasSelectedText() ? text.left(selstart) : text;
+            if (text.compare(completer->currentCompletion(), completer->caseSensitivity()) != 0
+                || prefix.compare(completer->completionPrefix(), completer->caseSensitivity()) != 0) {
+                completer->setCompletionPrefix(prefix);
+            } else {
+                n = (key == Qt::Key_Up) ? -1 : +1;
+            }
+        } else {
+            completer->setCompletionPrefix(text);
+        }
+        if (!advanceToEnabledItem(n))
+            return;
+    } else {
+#ifndef QT_KEYPAD_NAVIGATION
+        if (text.isEmpty()) {
+            completer->popup()->hide();
+            return;
+        }
+#endif
+        completer->setCompletionPrefix(text);
+    }
+
+    completer->complete();
+}
+
+void QSecureLineEditPrivate::_q_completionHighlighted(QString newText)
+{
+    Q_Q(QSecureLineEdit);
+    if (completer->completionMode() != QCompleter::InlineCompletion)
+        q->setText(newText);
+    else {
+        int c = cursor;
+        q->setText(text.left(c) + newText.mid(c));
+        q->setSelection(text.length(), c - newText.length());
+    }
+}
+#endif // QT_NO_COMPLETER
+
+/*!
+    Returns a recommended size for the widget.
+
+    The width returned, in pixels, is usually enough for about 15 to
+    20 characters.
+*/
+
+QSize QSecureLineEdit::sizeHint() const
+{
+    Q_D(const QSecureLineEdit);
+    ensurePolished();
+    QFontMetrics fm(font());
+    int leftmargin, topmargin, rightmargin, bottommargin;
+    getContentsMargins( &leftmargin, &topmargin, &rightmargin, &bottommargin );
+    int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin
+            + topmargin + bottommargin;
+    int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin
+            + leftmargin + rightmargin; // "some"
+    QStyleOptionFrameV2 opt;
+    initStyleOption(&opt);
+    return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
+                                      expandedTo(QApplication::globalStrut()), this));
+}
+
+
+/*!
+    Returns a minimum size for the line edit.
+
+    The width returned is enough for at least one character.
+*/
+
+QSize QSecureLineEdit::minimumSizeHint() const
+{
+    Q_D(const QSecureLineEdit);
+    ensurePolished();
+    QFontMetrics fm = fontMetrics();
+    int leftmargin, topmargin, rightmargin, bottommargin;
+    getContentsMargins( &leftmargin, &topmargin, &rightmargin, &bottommargin );
+    int h = fm.height() + qMax(2*verticalMargin, fm.leading())
+            + topmargin + bottommargin;
+    int w = fm.maxWidth() + leftmargin + rightmargin;
+    QStyleOptionFrameV2 opt;
+    initStyleOption(&opt);
+    return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
+                                      expandedTo(QApplication::globalStrut()), this));
+}
+
+
+/*!
+    \property QSecureLineEdit::cursorPosition
+    \brief the current cursor position for this line edit
+
+    Setting the cursor position causes a repaint when appropriate.
+*/
+
+int QSecureLineEdit::cursorPosition() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->cursor;
+}
+
+void QSecureLineEdit::setCursorPosition(int pos)
+{
+    Q_D(QSecureLineEdit);
+    if (pos < 0)
+        pos = 0;
+
+    if (pos <= d->text.length())
+        d->moveCursor(pos);
+}
+
+/*!
+    Returns the cursor position under the point \a pos.
+*/
+// ### What should this do if the point is outside of contentsRect? Currently returns 0.
+int QSecureLineEdit::cursorPositionAt(const QPoint &pos)
+{
+    Q_D(QSecureLineEdit);
+    return d->xToPos(pos.x());
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \obsolete
+
+    Use setText(), setCursorPosition() and setSelection() instead.
+*/
+bool QSecureLineEdit::validateAndSet(const QString &newText, int newPos,
+                                 int newMarkAnchor, int newMarkDrag)
+{
+    Q_D(QSecureLineEdit);
+    int priorState = d->undoState;
+    d->selstart = 0;
+    d->selend = d->text.length();
+    d->removeSelectedText();
+    d->insert(newText);
+    d->finishChange(priorState);
+    if (d->undoState > priorState) {
+        d->cursor = newPos;
+        d->selstart = qMin(newMarkAnchor, newMarkDrag);
+        d->selend = qMax(newMarkAnchor, newMarkDrag);
+        update();
+        d->emitCursorPositionChanged();
+        return true;
+    }
+    return false;
+}
+#endif //QT3_SUPPORT
+
+/*!
+    \property QSecureLineEdit::alignment
+    \brief the alignment of the line edit
+
+    Both horizontal and vertical alignment is allowed here, Qt::AlignJustify
+    will map to Qt::AlignLeft.
+
+    \sa Qt::Alignment
+*/
+
+Qt::Alignment QSecureLineEdit::alignment() const
+{
+    Q_D(const QSecureLineEdit);
+    return QFlag(d->alignment);
+}
+
+void QSecureLineEdit::setAlignment(Qt::Alignment alignment)
+{
+    Q_D(QSecureLineEdit);
+    d->alignment = alignment;
+    update();
+}
+
+
+/*!
+    Moves the cursor forward \a steps characters. If \a mark is true
+    each character moved over is added to the selection; if \a mark is
+    false the selection is cleared.
+
+    \sa cursorBackward()
+*/
+
+void QSecureLineEdit::cursorForward(bool mark, int steps)
+{
+    Q_D(QSecureLineEdit);
+    int cursor = d->cursor;
+    if (steps > 0) {
+        while(steps--)
+            cursor = d->textLayout.nextCursorPosition(cursor);
+    } else if (steps < 0) {
+        while (steps++)
+            cursor = d->textLayout.previousCursorPosition(cursor);
+    }
+    d->moveCursor(cursor, mark);
+}
+
+
+/*!
+    Moves the cursor back \a steps characters. If \a mark is true each
+    character moved over is added to the selection; if \a mark is
+    false the selection is cleared.
+
+    \sa cursorForward()
+*/
+void QSecureLineEdit::cursorBackward(bool mark, int steps)
+{
+    cursorForward(mark, -steps);
+}
+
+/*!
+    Moves the cursor one word forward. If \a mark is true, the word is
+    also selected.
+
+    \sa cursorWordBackward()
+*/
+void QSecureLineEdit::cursorWordForward(bool mark)
+{
+    Q_D(QSecureLineEdit);
+    d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
+}
+
+/*!
+    Moves the cursor one word backward. If \a mark is true, the word
+    is also selected.
+
+    \sa cursorWordForward()
+*/
+
+void QSecureLineEdit::cursorWordBackward(bool mark)
+{
+    Q_D(QSecureLineEdit);
+    d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
+}
+
+
+/*!
+    If no text is selected, deletes the character to the left of the
+    text cursor and moves the cursor one position to the left. If any
+    text is selected, the cursor is moved to the beginning of the
+    selected text and the selected text is deleted.
+
+    \sa del()
+*/
+void QSecureLineEdit::backspace()
+{
+    Q_D(QSecureLineEdit);
+    int priorState = d->undoState;
+    if (d->hasSelectedText()) {
+        d->removeSelectedText();
+    } else if (d->cursor) {
+            --d->cursor;
+            if (d->maskData)
+                d->cursor = d->prevMaskBlank(d->cursor);
+            QChar uc = d->text.at(d->cursor);
+            if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
+                // second half of a surrogate, check if we have the first half as well,
+                // if yes delete both at once
+                uc = d->text.at(d->cursor - 1);
+                if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
+                    d->del(true);
+                    --d->cursor;
+                }
+            }
+            d->del(true);
+    }
+    d->finishChange(priorState);
+}
+
+/*!
+    If no text is selected, deletes the character to the right of the
+    text cursor. If any text is selected, the cursor is moved to the
+    beginning of the selected text and the selected text is deleted.
+
+    \sa backspace()
+*/
+
+void QSecureLineEdit::del()
+{
+    Q_D(QSecureLineEdit);
+    int priorState = d->undoState;
+    if (d->hasSelectedText()) {
+        d->removeSelectedText();
+    } else {
+        int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor;
+        while (n--)
+            d->del();
+    }
+    d->finishChange(priorState);
+}
+
+/*!
+    Moves the text cursor to the beginning of the line unless it is
+    already there. If \a mark is true, text is selected towards the
+    first position; otherwise, any selected text is unselected if the
+    cursor is moved.
+
+    \sa end()
+*/
+
+void QSecureLineEdit::home(bool mark)
+{
+    Q_D(QSecureLineEdit);
+    d->moveCursor(0, mark);
+}
+
+/*!
+    Moves the text cursor to the end of the line unless it is already
+    there. If \a mark is true, text is selected towards the last
+    position; otherwise, any selected text is unselected if the cursor
+    is moved.
+
+    \sa home()
+*/
+
+void QSecureLineEdit::end(bool mark)
+{
+    Q_D(QSecureLineEdit);
+    d->moveCursor(d->text.length(), mark);
+}
+
+
+/*!
+    \property QSecureLineEdit::modified
+    \brief whether the line edit's contents has been modified by the user
+
+    The modified flag is never read by QSecureLineEdit; it has a default value
+    of false and is changed to true whenever the user changes the line
+    edit's contents.
+
+    This is useful for things that need to provide a default value but
+    do not start out knowing what the default should be (perhaps it
+    depends on other fields on the form). Start the line edit without
+    the best default, and when the default is known, if modified()
+    returns false (the user hasn't entered any text), insert the
+    default value.
+
+    Calling setText() resets the modified flag to false.
+*/
+
+bool QSecureLineEdit::isModified() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->modifiedState != d->undoState;
+}
+
+void QSecureLineEdit::setModified(bool modified)
+{
+    Q_D(QSecureLineEdit);
+    if (modified)
+        d->modifiedState = -1;
+    else
+        d->modifiedState = d->undoState;
+}
+
+
+/*!\fn QSecureLineEdit::clearModified()
+
+Use setModified(false) instead.
+
+    \sa isModified()
+*/
+
+
+/*!
+    \property QSecureLineEdit::hasSelectedText
+    \brief whether there is any text selected
+
+    hasSelectedText() returns true if some or all of the text has been
+    selected by the user; otherwise returns false.
+
+    \sa selectedText()
+*/
+
+
+bool QSecureLineEdit::hasSelectedText() const
+{
+    Q_D(const QSecureLineEdit);
+    return d->hasSelectedText();
+}
+
+/*!
+    \property QSecureLineEdit::selectedText
+    \brief the selected text
+
+    If there is no selected text this property's value is
+    an empty string.
+
+    \sa hasSelectedText()
+*/
+
+secqstring QSecureLineEdit::selectedText() const
+{
+    Q_D(const QSecureLineEdit);
+    if (d->hasSelectedText())
+        return d->text.substr(d->selstart, d->selend - d->selstart);
+    return secqstring();
+}
+
+/*!
+    selectionStart() returns the index of the first selected character in the
+    line edit or -1 if no text is selected.
+
+    \sa selectedText()
+*/
+
+int QSecureLineEdit::selectionStart() const




More information about the Gnupg-commits mailing list