summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-07-30 07:08:43 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-07-30 07:08:43 (GMT)
commitf5acc7b83f79c0bce554a6e4fe2d9e6ebb4b582b (patch)
tree865471e5d53175f66e5a8e13926285c289ca1437 /src/gui
parent0eaa3466077839b0cef2ad6c326d80f398eccae7 (diff)
parentc1a90a535206e0a146e13c60d981a855178e69ca (diff)
downloadQt-f5acc7b83f79c0bce554a6e4fe2d9e6ebb4b582b.zip
Qt-f5acc7b83f79c0bce554a6e4fe2d9e6ebb4b582b.tar.gz
Qt-f5acc7b83f79c0bce554a6e4fe2d9e6ebb4b582b.tar.bz2
Merge branch 'master' of git://git-nokia.trolltech.com.au/qtsoftware/qt/qt
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp7
-rw-r--r--src/gui/embedded/embedded.pri19
-rw-r--r--src/gui/embedded/qkbddriverfactory_qws.cpp8
-rw-r--r--src/gui/embedded/qkbdqnx_qws.cpp231
-rw-r--r--src/gui/embedded/qkbdqnx_qws.h76
-rw-r--r--src/gui/embedded/qlock.cpp70
-rw-r--r--src/gui/embedded/qmousedriverfactory_qws.cpp8
-rw-r--r--src/gui/embedded/qmousepc_qws.cpp2
-rw-r--r--src/gui/embedded/qmouseqnx_qws.cpp190
-rw-r--r--src/gui/embedded/qmouseqnx_qws.h79
-rw-r--r--src/gui/embedded/qscreendriverfactory_qws.cpp8
-rw-r--r--src/gui/embedded/qscreenqnx_qws.cpp447
-rw-r--r--src/gui/embedded/qscreenqnx_qws.h82
-rw-r--r--src/gui/embedded/qwindowsystem_qws.cpp37
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp10
-rw-r--r--src/gui/graphicsview/qgraphicstransform.h6
-rw-r--r--src/gui/inputmethod/qinputcontextplugin.h2
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp1
-rw-r--r--src/gui/kernel/qapplication.cpp1
-rw-r--r--src/gui/kernel/qapplication_qws.cpp17
-rw-r--r--src/gui/kernel/qboxlayout.cpp6
-rw-r--r--src/gui/kernel/qgridlayout.cpp2
-rw-r--r--src/gui/kernel/qlayout.cpp4
-rw-r--r--src/gui/kernel/qt_x11_p.h12
-rw-r--r--src/gui/kernel/qwidget.cpp6
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp1
-rw-r--r--src/gui/painting/qbackingstore.cpp3
-rw-r--r--src/gui/painting/qbrush.h9
-rw-r--r--src/gui/painting/qdatabuffer_p.h17
-rw-r--r--src/gui/painting/qgrayraster.c4
-rw-r--r--src/gui/painting/qoutlinemapper.cpp59
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp89
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/painting/qpaintengineex.cpp68
-rw-r--r--src/gui/painting/qpainterpath.cpp2
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h4
-rw-r--r--src/gui/painting/qtransform.h4
-rw-r--r--src/gui/painting/qvectorpath_p.h2
-rw-r--r--src/gui/text/qcssparser_p.h5
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp6
-rw-r--r--src/gui/text/qfontengine_qpf.cpp52
-rw-r--r--src/gui/text/qfontengine_qws.cpp2
-rw-r--r--src/gui/text/qtextdocument_p.cpp45
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp4
-rw-r--r--src/gui/util/qdesktopservices_x11.cpp4
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp1749
-rw-r--r--src/gui/widgets/qlinecontrol_p.h741
-rw-r--r--src/gui/widgets/qlineedit.cpp1869
-rw-r--r--src/gui/widgets/qlineedit.h2
-rw-r--r--src/gui/widgets/qlineedit_p.cpp253
-rw-r--r--src/gui/widgets/qlineedit_p.h175
-rw-r--r--src/gui/widgets/qvalidator.h4
-rw-r--r--src/gui/widgets/widgets.pri3
54 files changed, 4467 insertions, 2044 deletions
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index 887eb71..467822c 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -44,8 +44,11 @@
#include <qfsfileengine.h>
#include <qdiriterator.h>
#ifndef Q_OS_WIN
-#include <unistd.h>
-#include <sys/types.h>
+# include <unistd.h>
+# include <sys/types.h>
+#endif
+#if defined(Q_OS_VXWORKS)
+# include "qplatformdefs.h"
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/gui/embedded/embedded.pri b/src/gui/embedded/embedded.pri
index 53a2512..e8eb959 100644
--- a/src/gui/embedded/embedded.pri
+++ b/src/gui/embedded/embedded.pri
@@ -114,11 +114,18 @@ embedded {
SOURCES += embedded/qscreenlinuxfb_qws.cpp
}
+ contains( gfx-drivers, qnx ) {
+ HEADERS += embedded/qscreenqnx_qws.h
+ SOURCES += embedded/qscreenqnx_qws.cpp
+ LIBS += -lgf
+ }
+
contains( gfx-drivers, qvfb ) {
HEADERS += embedded/qscreenvfb_qws.h
SOURCES += embedded/qscreenvfb_qws.cpp
}
+
contains( gfx-drivers, vnc ) {
VNCDIR = $$QT_SOURCE_TREE/src/plugins/gfxdrivers/vnc
INCLUDEPATH += $$VNCDIR
@@ -158,6 +165,11 @@ embedded {
SOURCES +=embedded/qkbdum_qws.cpp
}
+ contains( kbd-drivers, qnx ) {
+ HEADERS += embedded/qkbdqnx_qws.h
+ SOURCES += embedded/qkbdqnx_qws.cpp
+ }
+
#
# Mouse drivers
#
@@ -185,5 +197,10 @@ embedded {
contains( mouse-drivers, linuxinput ) {
HEADERS +=embedded/qmouselinuxinput_qws.h
SOURCES +=embedded/qmouselinuxinput_qws.cpp
- }
+ }
+
+ contains( mouse-drivers, qnx ) {
+ HEADERS += embedded/qmouseqnx_qws.h
+ SOURCES += embedded/qmouseqnx_qws.cpp
+ }
}
diff --git a/src/gui/embedded/qkbddriverfactory_qws.cpp b/src/gui/embedded/qkbddriverfactory_qws.cpp
index b77eb72..fb10030 100644
--- a/src/gui/embedded/qkbddriverfactory_qws.cpp
+++ b/src/gui/embedded/qkbddriverfactory_qws.cpp
@@ -48,6 +48,7 @@
#include "qkbdlinuxinput_qws.h"
#include "qkbdum_qws.h"
#include "qkbdvfb_qws.h"
+#include "qkbdqnx_qws.h"
#include <stdlib.h>
#include "private/qfactoryloader_p.h"
#include "qkbddriverplugin_qws.h"
@@ -101,6 +102,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QWSKeyboardHandler *QKbdDriverFactory::create(const QString& key, const QString& device)
{
QString driver = key.toLower();
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_KBD_QNX)
+ if (driver == QLatin1String("qnx") || driver.isEmpty())
+ return new QWSQnxKeyboardHandler(device);
+#endif
#ifndef QT_NO_QWS_KEYBOARD
# ifndef QT_NO_QWS_KBD_TTY
if (driver == QLatin1String("tty") || driver.isEmpty())
@@ -143,6 +148,9 @@ QStringList QKbdDriverFactory::keys()
{
QStringList list;
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_KBD_QNX)
+ list << QLatin1String("QNX");
+#endif
#ifndef QT_NO_QWS_KBD_TTY
list << QLatin1String("TTY");
#endif
diff --git a/src/gui/embedded/qkbdqnx_qws.cpp b/src/gui/embedded/qkbdqnx_qws.cpp
new file mode 100644
index 0000000..06163c7
--- /dev/null
+++ b/src/gui/embedded/qkbdqnx_qws.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdqnx_qws.h"
+#include "QtCore/qsocketnotifier.h"
+#include "QtCore/qdebug.h"
+
+#include <sys/dcmd_input.h>
+#include <photon/keycodes.h>
+
+#include "qplatformdefs.h"
+#include <errno.h>
+
+/*!
+ \class QWSQnxKeyboardHandler
+ \preliminary
+ \ingroup qws
+ \since 4.6
+ \internal
+
+ \brief The QWSQnxKeyboardHandler class implements a keyboard driver
+ for the QNX \c{devi-hid} input manager.
+
+ To be able to compile this mouse handler, \l{Qt for Embedded Linux}
+ must be configured with the \c -qt-kbd-qnx option, see the
+ \l{Qt for Embedded Linux Character Input} documentation for details.
+
+ In order to use this keyboard handler, the \c{devi-hid} input manager
+ must be set up and run with the resource manager interface (option \c{-r}).
+ Also, Photon must not be running.
+
+ Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
+ Note that after running \c{devi-hid}, you will not be able to use the local
+ shell anymore. It is suggested to run the command in a shell scrip, that launches
+ a Qt application after invocation of \c{devi-hid}.
+
+ To make \l{Qt for Embedded Linux} explicitly choose the qnx keyboard
+ handler, set the QWS_KEYBOARD environment variable to \c{qnx}. By default,
+ the first keyboard device (\c{/dev/devi/keyboard0}) is used. To override, pass a device
+ name as the first and only parameter, for example
+ \c{QWS_KEYBOARD=qnx:/dev/devi/keyboard1; export QWS_KEYBOARD}.
+
+ \sa {Qt for Embedded Linux Character Input}, {Qt for Embedded Linux}
+*/
+
+/*!
+ Constructs a keyboard handler for the specified \a device, defaulting to
+ \c{/dev/devi/keyboard0}.
+
+ Note that you should never instanciate this class, instead let QKbdDriverFactory
+ handle the keyboard handlers.
+
+ \sa QKbdDriverFactory
+ */
+QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device)
+{
+ // open the keyboard device
+ keyboardFD = QT_OPEN(device.isEmpty() ? "/dev/devi/keyboard0" : device.toLatin1().constData(),
+ QT_OPEN_RDONLY);
+ if (keyboardFD == -1) {
+ qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device");
+ return;
+ }
+
+ // create a socket notifier so we'll wake up whenever keyboard input is detected.
+ QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated()));
+
+ qDebug() << "QWSQnxKeyboardHandler: connected.";
+
+}
+
+/*!
+ Destroys this keyboard handler and closes the connection to the keyboard device.
+ */
+QWSQnxKeyboardHandler::~QWSQnxKeyboardHandler()
+{
+ QT_CLOSE(keyboardFD);
+}
+
+/*! \internal
+ Translates the QNX keyboard events to Qt keyboard events
+ */
+void QWSQnxKeyboardHandler::socketActivated()
+{
+ _keyboard_packet packet;
+
+ // read one keyboard event
+ int bytesRead = QT_READ(keyboardFD, &packet, sizeof(_keyboard_packet));
+ if (bytesRead == -1) {
+ qErrnoWarning(errno, "QWSQnxKeyboardHandler::socketActivated(): Unable to read data.");
+ return;
+ }
+
+ // the bytes read must be the size of a keyboard packet
+ Q_ASSERT(bytesRead == sizeof(_keyboard_packet));
+
+#if 0
+ qDebug() << "keyboard got scancode"
+ << hex << packet.data.modifiers
+ << packet.data.flags
+ << packet.data.key_cap
+ << packet.data.key_sym
+ << packet.data.key_scan;
+#endif
+
+ // QNX is nice enough to translate the raw keyboard data into a QNX data structure
+ // Now we just have to translate it into a format Qt understands.
+
+ // figure out whether it's a press
+ bool isPress = packet.data.key_cap & KEY_DOWN;
+ // figure out wheter the key is still pressed and the key event is repeated
+ bool isRepeat = packet.data.key_cap & KEY_REPEAT;
+
+ Qt::Key key = Qt::Key_unknown;
+ int unicode = 0xffff;
+
+ // TODO - this switch is not complete!
+ switch (packet.data.key_scan) {
+ case KEYCODE_SPACE: key = Qt::Key_Space; unicode = 0x20; break;
+ case KEYCODE_F1: key = Qt::Key_F1; break;
+ case KEYCODE_F2: key = Qt::Key_F2; break;
+ case KEYCODE_F3: key = Qt::Key_F3; break;
+ case KEYCODE_F4: key = Qt::Key_F4; break;
+ case KEYCODE_F5: key = Qt::Key_F5; break;
+ case KEYCODE_F6: key = Qt::Key_F6; break;
+ case KEYCODE_F7: key = Qt::Key_F7; break;
+ case KEYCODE_F8: key = Qt::Key_F8; break;
+ case KEYCODE_F9: key = Qt::Key_F9; break;
+ case KEYCODE_F10: key = Qt::Key_F10; break;
+ case KEYCODE_F11: key = Qt::Key_F11; break;
+ case KEYCODE_F12: key = Qt::Key_F12; break;
+ case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; break;
+ case KEYCODE_TAB: key = Qt::Key_Tab; break;
+ case KEYCODE_RETURN: key = Qt::Key_Return; break;
+ case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break;
+ case KEYCODE_UP:
+ case KEYCODE_KP_UP:
+ key = Qt::Key_Up; break;
+ case KEYCODE_DOWN:
+ case KEYCODE_KP_DOWN:
+ key = Qt::Key_Down; break;
+ case KEYCODE_LEFT:
+ case KEYCODE_KP_LEFT:
+ key = Qt::Key_Left; break;
+ case KEYCODE_RIGHT:
+ case KEYCODE_KP_RIGHT:
+ key = Qt::Key_Right; break;
+ case KEYCODE_HOME:
+ case KEYCODE_KP_HOME:
+ key = Qt::Key_Home; break;
+ case KEYCODE_END:
+ case KEYCODE_KP_END:
+ key = Qt::Key_End; break;
+ case KEYCODE_PG_UP:
+ case KEYCODE_KP_PG_UP:
+ key = Qt::Key_PageUp; break;
+ case KEYCODE_PG_DOWN:
+ case KEYCODE_KP_PG_DOWN:
+ key = Qt::Key_PageDown; break;
+ case KEYCODE_INSERT:
+ case KEYCODE_KP_INSERT:
+ key = Qt::Key_Insert; break;
+ case KEYCODE_DELETE:
+ case KEYCODE_KP_DELETE:
+ key = Qt::Key_Delete; break;
+ case KEYCODE_ESCAPE:
+ key = Qt::Key_Escape; break;
+ default: // none of the above, try the key_scan directly
+ unicode = packet.data.key_scan;
+ break;
+ }
+
+ // figure out the modifiers that are currently pressed
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+ if (packet.data.flags & KEYMOD_SHIFT)
+ modifiers |= Qt::ShiftModifier;
+ if (packet.data.flags & KEYMOD_CTRL)
+ modifiers |= Qt::ControlModifier;
+ if (packet.data.flags & KEYMOD_ALT)
+ modifiers |= Qt::AltModifier;
+
+ // if the unicode value is not ascii, we ignore it.
+ // TODO - do a complete mapping between all QNX scan codes and Qt codes
+ if (unicode != 0xffff && !isascii(unicode))
+ return; // unprintable character
+
+ // call processKeyEvent. This is where all the magic happens to insert a
+ // key event into Qt's event loop.
+ // Note that for repeated key events, isPress must be true
+ // (on QNX, isPress is not set when the key event is repeated).
+ processKeyEvent(unicode, key, modifiers, isPress || isRepeat, isRepeat);
+}
diff --git a/src/gui/embedded/qkbdqnx_qws.h b/src/gui/embedded/qkbdqnx_qws.h
new file mode 100644
index 0000000..c046c8d
--- /dev/null
+++ b/src/gui/embedded/qkbdqnx_qws.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDQNX_QWS_H
+#define QKBDQNX_QWS_H
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_QNX)
+
+class Q_GUI_EXPORT QWSQnxKeyboardHandler : public QObject, public QWSKeyboardHandler
+{
+ Q_OBJECT
+public:
+ QWSQnxKeyboardHandler(const QString &device);
+ ~QWSQnxKeyboardHandler();
+
+private Q_SLOTS:
+ void socketActivated();
+
+private:
+ int keyboardFD;
+};
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDQNX_QWS_H
diff --git a/src/gui/embedded/qlock.cpp b/src/gui/embedded/qlock.cpp
index 305832c..9592a4d 100644
--- a/src/gui/embedded/qlock.cpp
+++ b/src/gui/embedded/qlock.cpp
@@ -41,9 +41,46 @@
#include "qlock_p.h"
-#ifndef QT_NO_QWS_MULTIPROCESS
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_NO_QWS_MULTIPROCESS
+
+/* no multiprocess - use a dummy */
+
+QLock::QLock(const QString & /*filename*/, char /*id*/, bool /*create*/)
+ : type(Read), data(0)
+{
+}
+
+QLock::~QLock()
+{
+}
+
+bool QLock::isValid() const
+{
+ return true;
+}
+
+void QLock::lock(Type t)
+{
+ data = (QLockData *)-1;
+ type = t;
+}
+
+void QLock::unlock()
+{
+ data = 0;
+}
+
+bool QLock::locked() const
+{
+ return data;
+}
+
+#else // QT_NO_QWS_MULTIPROCESS
#include "qwssignalhandler_p.h"
+
#include <unistd.h>
#include <sys/types.h>
#if defined(Q_OS_DARWIN)
@@ -71,16 +108,10 @@ union semun {
#include <qdebug.h>
#include <signal.h>
-#endif // QT_NO_QWS_MULTIPROCESS
-
#include <private/qcore_unix_p.h> // overrides QT_OPEN
#define MAX_LOCKS 200 // maximum simultaneous read locks
-QT_BEGIN_NAMESPACE
-
-
-#ifndef QT_NO_QWS_MULTIPROCESS
class QLockData
{
public:
@@ -91,7 +122,6 @@ public:
int count;
bool owned;
};
-#endif // QT_NO_QWS_MULTIPROCESS
/*!
\class QLock
@@ -126,11 +156,6 @@ public:
QLock::QLock(const QString &filename, char id, bool create)
{
-#ifdef QT_NO_QWS_MULTIPROCESS
- Q_UNUSED(filename);
- Q_UNUSED(id);
- Q_UNUSED(create);
-#else
data = new QLockData;
data->count = 0;
#ifdef Q_NO_SEMAPHORE
@@ -163,7 +188,6 @@ QLock::QLock(const QString &filename, char id, bool create)
qPrintable(filename), id);
qDebug() << "Error" << eno << strerror(eno);
}
-#endif
}
/*!
@@ -174,7 +198,6 @@ QLock::QLock(const QString &filename, char id, bool create)
QLock::~QLock()
{
-#ifndef QT_NO_QWS_MULTIPROCESS
if (locked())
unlock();
#ifdef Q_NO_SEMAPHORE
@@ -188,7 +211,6 @@ QLock::~QLock()
QWSSignalHandler::instance()->removeSemaphore(data->id);
#endif
delete data;
-#endif
}
/*!
@@ -200,11 +222,7 @@ QLock::~QLock()
bool QLock::isValid() const
{
-#ifndef QT_NO_QWS_MULTIPROCESS
return (data->id != -1);
-#else
- return true;
-#endif
}
/*!
@@ -221,9 +239,6 @@ bool QLock::isValid() const
void QLock::lock(Type t)
{
-#ifdef QT_NO_QWS_MULTIPROCESS
- Q_UNUSED(t);
-#else
if (!data->count) {
#ifdef Q_NO_SEMAPHORE
int op = LOCK_SH;
@@ -256,7 +271,6 @@ void QLock::lock(Type t)
#endif
}
data->count++;
-#endif
}
/*!
@@ -269,7 +283,6 @@ void QLock::lock(Type t)
void QLock::unlock()
{
-#ifndef QT_NO_QWS_MULTIPROCESS
if(data->count) {
data->count--;
if(!data->count) {
@@ -298,7 +311,6 @@ void QLock::unlock()
} else {
qDebug("Unlock without corresponding lock");
}
-#endif
}
/*!
@@ -310,11 +322,9 @@ void QLock::unlock()
bool QLock::locked() const
{
-#ifndef QT_NO_QWS_MULTIPROCESS
return (data->count > 0);
-#else
- return false;
-#endif
}
+#endif // QT_NO_QWS_MULTIPROCESS
+
QT_END_NAMESPACE
diff --git a/src/gui/embedded/qmousedriverfactory_qws.cpp b/src/gui/embedded/qmousedriverfactory_qws.cpp
index 46898ae..6d71750 100644
--- a/src/gui/embedded/qmousedriverfactory_qws.cpp
+++ b/src/gui/embedded/qmousedriverfactory_qws.cpp
@@ -47,6 +47,7 @@
#include "qmouselinuxinput_qws.h"
#include "qmousevfb_qws.h"
#include "qmousetslib_qws.h"
+#include "qmouseqnx_qws.h"
#include <stdlib.h>
#include "private/qfactoryloader_p.h"
#include "qmousedriverplugin_qws.h"
@@ -102,6 +103,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QWSMouseHandler *QMouseDriverFactory::create(const QString& key, const QString &device)
{
QString driver = key.toLower();
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_MOUSE_QNX)
+ if (driver == QLatin1String("qnx") || driver.isEmpty())
+ return new QQnxMouseHandler(key, device);
+#endif
#ifndef QT_NO_QWS_MOUSE_LINUXTP
if (driver == QLatin1String("linuxtp") || driver.isEmpty())
return new QWSLinuxTPMouseHandler(key, device);
@@ -149,6 +154,9 @@ QStringList QMouseDriverFactory::keys()
{
QStringList list;
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_MOUSE_QNX)
+ list << QLatin1String("QNX");
+#endif
#ifndef QT_NO_QWS_MOUSE_LINUXTP
list << QLatin1String("LinuxTP");
#endif
diff --git a/src/gui/embedded/qmousepc_qws.cpp b/src/gui/embedded/qmousepc_qws.cpp
index 317bb8a..2d62772 100644
--- a/src/gui/embedded/qmousepc_qws.cpp
+++ b/src/gui/embedded/qmousepc_qws.cpp
@@ -332,7 +332,7 @@ protected:
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = f | CREAD | CLOCAL | HUPCL;
-#if !defined(Q_OS_DARWIN) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_INTEGRITY)
+#ifdef Q_OS_LINUX
tty.c_line = 0;
#endif
tty.c_cc[VTIME] = 0;
diff --git a/src/gui/embedded/qmouseqnx_qws.cpp b/src/gui/embedded/qmouseqnx_qws.cpp
new file mode 100644
index 0000000..98f8f06
--- /dev/null
+++ b/src/gui/embedded/qmouseqnx_qws.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmouseqnx_qws.h"
+
+#include "qsocketnotifier.h"
+#include "qdebug.h"
+
+#include <sys/dcmd_input.h>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQnxMouseHandler
+ \preliminary
+ \ingroup qws
+ \internal
+ \since 4.6
+
+ \brief The QQnxMouseHandler class implements a mouse driver
+ for the QNX \c{devi-hid} input manager.
+
+ To be able to compile this mouse handler, \l{Qt for Embedded Linux}
+ must be configured with the \c -qt-mouse-qnx option, see the
+ \l{Qt for Embedded Linux Pointer Handling}{Pointer Handling} documentation for details.
+
+ In order to use this mouse handler, the \c{devi-hid} input manager
+ must be set up and run with the resource manager interface (option \c{-r}).
+ Also, Photon must not be running.
+
+ Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
+ Note that after running \c{devi-hid}, you will not be able to use the local
+ shell anymore. It is suggested to run the command in a shell scrip, that launches
+ a Qt application after invocation of \c{devi-hid}.
+
+ To make \l{Qt for Embedded Linux} explicitly choose the qnx mouse
+ handler, set the QWS_MOUSE_PROTO environment variable to \c{qnx}. By default,
+ the first mouse device (\c{/dev/devi/mouse0}) is used. To override, pass a device
+ name as the first and only parameter, for example
+ \c{QWS_MOUSE_PROTO=qnx:/dev/devi/mouse1; export QWS_MOUSE_PROTO}.
+
+ \sa {Qt for Embedded Linux Pointer Handling}{Pointer Handling}, {Qt for Embedded Linux}
+*/
+
+/*!
+ Constructs a mouse handler for the specified \a device, defaulting to \c{/dev/devi/mouse0}.
+ The \a driver parameter must be \c{"qnx"}.
+
+ Note that you should never instanciate this class, instead let QMouseDriverFactory
+ handle the mouse handlers.
+
+ \sa QMouseDriverFactory
+ */
+QQnxMouseHandler::QQnxMouseHandler(const QString & /*driver*/, const QString &device)
+{
+ // open the mouse device with O_NONBLOCK so reading won't block when there's no data
+ mouseFD = QT_OPEN(device.isEmpty() ? "/dev/devi/mouse0" : device.toLatin1().constData(),
+ QT_OPEN_RDONLY | O_NONBLOCK);
+ if (mouseFD == -1) {
+ qErrnoWarning(errno, "QQnxMouseHandler: Unable to open mouse device");
+ return;
+ }
+
+ // register a socket notifier on the file descriptor so we'll wake up whenever
+ // there's a mouse move waiting for us.
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)), SLOT(socketActivated()));
+
+ qDebug() << "QQnxMouseHandler: connected.";
+}
+
+/*!
+ Destroys this mouse handler and closes the connection to the mouse device.
+ */
+QQnxMouseHandler::~QQnxMouseHandler()
+{
+ QT_CLOSE(mouseFD);
+}
+
+/*! \reimp */
+void QQnxMouseHandler::resume()
+{
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(true);
+}
+
+/*! \reimp */
+void QQnxMouseHandler::suspend()
+{
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(false);
+}
+
+/*! \internal
+
+ This function is called whenever there is activity on the mouse device.
+ By default, it reads up to 10 mouse move packets and calls mouseChanged()
+ for each of them.
+*/
+void QQnxMouseHandler::socketActivated()
+{
+ // _mouse_packet is a QNX structure. devi-hid is nice enough to translate
+ // the raw byte data from mouse devices into generic format for us.
+ _mouse_packet packet;
+
+ int iteration = 0;
+
+ // read mouse events in batches of 10. Since we're getting quite a lot
+ // of mouse events, it's better to do them in batches than to return to the
+ // event loop every time.
+ do {
+ int bytesRead = QT_READ(mouseFD, &packet, sizeof(packet));
+ if (bytesRead == -1) {
+ // EAGAIN means that there are no more mouse events to read
+ if (errno != EAGAIN)
+ qErrnoWarning(errno, "QQnxMouseHandler: Unable to read from socket");
+ return;
+ }
+
+ // bytes read should always be equal to the size of a packet.
+ Q_ASSERT(bytesRead == sizeof(packet));
+
+ // translate the coordinates from the QNX data structure to Qt coordinates
+ // note the swapped y axis
+ QPoint pos = mousePos;
+ pos += QPoint(packet.dx, -packet.dy);
+
+ // QNX only tells us relative mouse movements, not absolute ones, so limit the
+ // cursor position manually to the screen
+ limitToScreen(pos);
+
+ // translate the QNX mouse button bitmask to Qt buttons
+ int buttons = Qt::NoButton;
+
+ if (packet.hdr.buttons & _POINTER_BUTTON_LEFT)
+ buttons |= Qt::LeftButton;
+ if (packet.hdr.buttons & _POINTER_BUTTON_MIDDLE)
+ buttons |= Qt::MidButton;
+ if (packet.hdr.buttons & _POINTER_BUTTON_RIGHT)
+ buttons |= Qt::RightButton;
+
+ // call mouseChanged() - this does all the magic to actually move the on-screen
+ // mouse cursor.
+ mouseChanged(pos, buttons, 0);
+ } while (++iteration < 11);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/embedded/qmouseqnx_qws.h b/src/gui/embedded/qmouseqnx_qws.h
new file mode 100644
index 0000000..a61562e
--- /dev/null
+++ b/src/gui/embedded/qmouseqnx_qws.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSE_QNX_H
+#define QMOUSE_QNX_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QSocketNotifier;
+
+class Q_GUI_EXPORT QQnxMouseHandler : public QObject, public QWSMouseHandler
+{
+ Q_OBJECT
+public:
+ explicit QQnxMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+ ~QQnxMouseHandler();
+
+ void resume();
+ void suspend();
+
+private Q_SLOTS:
+ void socketActivated();
+
+private:
+ QSocketNotifier *mouseNotifier;
+ int mouseFD;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSE_QWS_H
diff --git a/src/gui/embedded/qscreendriverfactory_qws.cpp b/src/gui/embedded/qscreendriverfactory_qws.cpp
index 2290627..b531798 100644
--- a/src/gui/embedded/qscreendriverfactory_qws.cpp
+++ b/src/gui/embedded/qscreendriverfactory_qws.cpp
@@ -47,6 +47,7 @@
#include "qscreentransformed_qws.h"
#include "qscreenvfb_qws.h"
#include "qscreenmulti_qws_p.h"
+#include "qscreenqnx_qws.h"
#include <stdlib.h>
#include "private/qfactoryloader_p.h"
#include "qscreendriverplugin_qws.h"
@@ -105,6 +106,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QScreen *QScreenDriverFactory::create(const QString& key, int displayId)
{
QString driver = key.toLower();
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_QNX)
+ if (driver == QLatin1String("qnx") || driver.isEmpty())
+ return new QQnxScreen(displayId);
+#endif
#ifndef QT_NO_QWS_QVFB
if (driver == QLatin1String("qvfb") || driver.isEmpty())
return new QVFbScreen(displayId);
@@ -146,6 +151,9 @@ QStringList QScreenDriverFactory::keys()
{
QStringList list;
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_QNX)
+ list << QLatin1String("QNX");
+#endif
#ifndef QT_NO_QWS_QVFB
list << QLatin1String("QVFb");
#endif
diff --git a/src/gui/embedded/qscreenqnx_qws.cpp b/src/gui/embedded/qscreenqnx_qws.cpp
new file mode 100644
index 0000000..7101bc7
--- /dev/null
+++ b/src/gui/embedded/qscreenqnx_qws.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreenqnx_qws.h"
+#include "qdebug.h"
+
+#include <gf/gf.h>
+
+// This struct holds all the pointers to QNX's internals
+struct QQnxScreenContext
+{
+ inline QQnxScreenContext()
+ : device(0), display(0), layer(0), hwSurface(0), memSurface(0), context(0)
+ {}
+
+ gf_dev_t device;
+ gf_dev_info_t deviceInfo;
+ gf_display_t display;
+ gf_display_info_t displayInfo;
+ gf_layer_t layer;
+ gf_surface_t hwSurface;
+ gf_surface_t memSurface;
+ gf_surface_info_t memSurfaceInfo;
+ gf_context_t context;
+};
+
+/*!
+ \class QQnxScreen
+ \preliminary
+ \ingroup qws
+ \since 4.6
+ \internal
+
+ \brief The QQnxScreen class implements a screen driver
+ for QNX io-display based devices.
+
+ Note - you never have to instanciate this class, the QScreenDriverFactory
+ does that for us based on the \c{QWS_DISPLAY} environment variable.
+
+ To activate this driver, set \c{QWS_DISPLAY} to \c{qnx}.
+
+ Example:
+ \c{QWS_DISPLAY=qnx; export QWS_DISPLAY}
+
+ By default, the main layer of the first display of the first device is used.
+ If you have multiple graphic cards, multiple displays or multiple layers and
+ don't want to connect to the default, you can override that with setting
+ the corresponding options \c{device}, \c{display} or \c{layer} in the \c{QWS_DISPLAY} variable:
+
+ \c{QWS_DISPLAY=qnx:device=3:display=4:layer=5}
+
+ In addition, it is suggested to set the physical width and height of the display.
+ QQnxScreen will use that information to compute the dots per inch (DPI) in order to render
+ fonts correctly. If this informaiton is omitted, QQnxScreen defaults to 72 dpi.
+
+ \c{QWS_DISPLAY=qnx:mmWidth=120:mmHeight=80}
+
+ \c{mmWidth} and \c{mmHeight} are the physical width/height of the screen in millimeters.
+
+ \sa QScreen, QScreenDriverPlugin, {Running Qt for Embedded Linux Applications}{Running Applications}
+*/
+
+/*!
+ Constructs a QQnxScreen object. The \a display_id argument
+ identifies the Qt for Embedded Linux server to connect to.
+*/
+QQnxScreen::QQnxScreen(int display_id)
+ : QScreen(display_id), d(new QQnxScreenContext)
+{
+}
+
+/*!
+ Destroys this QQnxScreen object.
+*/
+QQnxScreen::~QQnxScreen()
+{
+ delete d;
+}
+
+/*! \reimp
+*/
+bool QQnxScreen::initDevice()
+{
+ // implement this if you have multiple processes that want to access the display
+ // (not required if QT_NO_QWS_MULTIPROCESS is set)
+ return true;
+}
+
+/*! \internal
+ Attaches to the named device \a name.
+*/
+static bool attachDevice(QQnxScreenContext * const d, const char *name)
+{
+ int ret = gf_dev_attach(&d->device, name, &d->deviceInfo);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_dev_attach(%s) failed with error code %d", name, ret);
+ return false;
+ }
+ return true;
+}
+
+/*! \internal
+ Attaches to the display at index \a displayIndex.
+ */
+static bool attachDisplay(QQnxScreenContext * const d, int displayIndex)
+{
+ int ret = gf_display_attach(&d->display, d->device, displayIndex, &d->displayInfo);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_display_attach(%d) failed with error code %d",
+ displayIndex, ret);
+ return false;
+ }
+ return true;
+}
+
+/*! \internal
+ Attaches to the layer \a layerIndex.
+ */
+static bool attachLayer(QQnxScreenContext * const d, int layerIndex)
+{
+ int ret = gf_layer_attach(&d->layer, d->display, layerIndex, 0);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_layer_attach(%d) failed with error code %d", layerIndex,
+ ret);
+ return false;
+ }
+ gf_layer_enable(d->layer);
+
+ return true;
+}
+
+/*! \internal
+ Creates a new hardware surface (usually on the Gfx card memory) with the dimensions \a w * \a h.
+ */
+static bool createHwSurface(QQnxScreenContext * const d, int w, int h)
+{
+ int ret = gf_surface_create_layer(&d->hwSurface, &d->layer, 1, 0,
+ w, h, GF_FORMAT_ARGB8888, 0, 0);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_surface_create_layer(%dx%d) failed with error code %d",
+ w, h, ret);
+ return false;
+ }
+
+ gf_layer_set_surfaces(d->layer, &d->hwSurface, 1);
+
+ ret = gf_layer_update(d->layer, 0);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_layer_update() failed with error code %d\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+/*! \internal
+ Creates an in-memory, linear accessible surface of dimensions \a w * \a h.
+ This is the main surface that QWS blits to.
+ */
+static bool createMemSurface(QQnxScreenContext * const d, int w, int h)
+{
+ // Note: gf_surface_attach() could also be used, so we'll create the buffer
+ // and let the surface point to it. Here, we use surface_create instead.
+
+ int ret = gf_surface_create(&d->memSurface, d->device, w, h,
+ GF_FORMAT_ARGB8888, 0,
+ GF_SURFACE_CREATE_CPU_FAST_ACCESS | GF_SURFACE_CREATE_CPU_LINEAR_ACCESSIBLE
+ | GF_SURFACE_PHYS_CONTIG);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_surface_create(%dx%d) failed with error code %d",
+ w, h, ret);
+ return false;
+ }
+
+ gf_surface_get_info(d->memSurface, &d->memSurfaceInfo);
+
+ if (d->memSurfaceInfo.sid == unsigned(GF_SID_INVALID)) {
+ qWarning("QQnxScreen: gf_surface_get_info() failed.");
+ return false;
+ }
+
+ return true;
+}
+
+/* \internal
+ Creates a QNX gf context and sets our memory surface on it.
+ */
+static bool createContext(QQnxScreenContext * const d)
+{
+ int ret = gf_context_create(&d->context);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_context_create() failed with error code %d", ret);
+ return false;
+ }
+
+ ret = gf_context_set_surface(d->context, d->memSurface);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_context_set_surface() failed with error code %d", ret);
+ return false;
+ }
+
+ return true;
+}
+
+/*! \reimp
+ Connects to QNX's io-display based device based on the \a displaySpec parameters
+ from the \c{QWS_DISPLAY} environment variable. See the QQnxScreen class documentation
+ for possible parameters.
+
+ \sa QQnxScreen
+ */
+bool QQnxScreen::connect(const QString &displaySpec)
+{
+ const QStringList params = displaySpec.split(QLatin1Char(':'), QString::SkipEmptyParts);
+
+ bool isOk = false;
+ QRegExp deviceRegExp(QLatin1String("^device=(.+)$"));
+ if (params.indexOf(deviceRegExp) != -1) {
+ isOk = attachDevice(d, deviceRegExp.cap(1).toLocal8Bit().constData());
+ } else {
+ // no device specified - attach to device 0 (the default)
+ isOk = attachDevice(d, GF_DEVICE_INDEX(0));
+ }
+
+ if (!isOk)
+ return false;
+
+ qDebug("QQnxScreen: Attached to Device, number of displays: %d", d->deviceInfo.ndisplays);
+
+ // default to display 0
+ int displayIndex = 0;
+ QRegExp displayRegexp(QLatin1String("^display=(\\d+)$"));
+ if (params.indexOf(displayRegexp) != -1) {
+ displayIndex = displayRegexp.cap(1).toInt();
+ }
+
+ if (!attachDisplay(d, displayIndex))
+ return false;
+
+ qDebug("QQnxScreen: Attached to Display %d, resolution %dx%d, refresh %d Hz",
+ displayIndex, d->displayInfo.xres, d->displayInfo.yres,
+ d->displayInfo.refresh);
+
+
+ // default to main_layer_index from the displayInfo struct
+ int layerIndex = 0;
+ QRegExp layerRegexp(QLatin1String("^layer=(\\d+)$"));
+ if (params.indexOf(layerRegexp) != -1) {
+ layerIndex = layerRegexp.cap(1).toInt();
+ } else {
+ layerIndex = d->displayInfo.main_layer_index;
+ }
+
+ if (!attachLayer(d, layerIndex))
+ return false;
+
+ // tell QWSDisplay the width and height of the display
+ w = dw = d->displayInfo.xres;
+ h = dh = d->displayInfo.yres;
+
+ // we only support 32 bit displays for now.
+ QScreen::d = 32;
+
+ // assume 72 dpi as default, to calculate the physical dimensions if not specified
+ const int defaultDpi = 72;
+
+ // Handle display physical size spec.
+ QRegExp mmWidthRegexp(QLatin1String("^mmWidth=(\\d+)$"));
+ if (params.indexOf(mmWidthRegexp) == -1) {
+ physWidth = qRound(dw * 25.4 / defaultDpi);
+ } else {
+ physWidth = mmWidthRegexp.cap(1).toInt();
+ }
+
+ QRegExp mmHeightRegexp(QLatin1String("^mmHeight=(\\d+)$"));
+ if (params.indexOf(mmHeightRegexp) == -1) {
+ physHeight = qRound(dh * 25.4 / defaultDpi);
+ } else {
+ physHeight = mmHeightRegexp.cap(1).toInt();
+ }
+
+ // create a hardware surface with our dimensions. In the old days, it was possible
+ // to get a pointer directly to the hw surface, so we could blit directly. Now, we
+ // have to use one indirection more, because it's not guaranteed that the hw surface
+ // is mappable into our process.
+ if (!createHwSurface(d, w, h))
+ return false;
+
+ // create an in-memory linear surface that is used by QWS. QWS will blit directly in here.
+ if (!createMemSurface(d, w, h))
+ return false;
+
+ // set the address of the in-memory buffer that QWS is blitting to
+ data = d->memSurfaceInfo.vaddr;
+ // set the line stepping
+ lstep = d->memSurfaceInfo.stride;
+
+ // the overall size of the in-memory buffer is linestep * height
+ size = mapsize = lstep * h;
+
+ // create a QNX drawing context
+ if (!createContext(d))
+ return false;
+
+ // we're always using a software cursor for now. Initialize it here.
+ QScreenCursor::initSoftwareCursor();
+
+ // done, the driver should be connected to the display now.
+ return true;
+}
+
+/*! \reimp
+ */
+void QQnxScreen::disconnect()
+{
+ if (d->context)
+ gf_context_free(d->context);
+
+ if (d->memSurface)
+ gf_surface_free(d->memSurface);
+
+ if (d->hwSurface)
+ gf_surface_free(d->hwSurface);
+
+ if (d->layer)
+ gf_layer_detach(d->layer);
+
+ if (d->display)
+ gf_display_detach(d->display);
+
+ if (d->device)
+ gf_dev_detach(d->device);
+
+ d->memSurface = 0;
+ d->hwSurface = 0;
+ d->context = 0;
+ d->layer = 0;
+ d->display = 0;
+ d->device = 0;
+}
+
+/*! \reimp
+ */
+void QQnxScreen::shutdownDevice()
+{
+}
+
+
+/*! \reimp
+ QQnxScreen doesn't support setting the mode, use io-display instead.
+ */
+void QQnxScreen::setMode(int,int,int)
+{
+ qWarning("QQnxScreen: Unable to change mode, use io-display instead.");
+}
+
+/*! \reimp
+ */
+bool QQnxScreen::supportsDepth(int depth) const
+{
+ // only 32-bit for the moment
+ return depth == 32;
+}
+
+/*! \reimp
+ */
+void QQnxScreen::exposeRegion(QRegion r, int changing)
+{
+ // here is where the actual magic happens. QWS will call exposeRegion whenever
+ // a region on the screen is dirty and needs to be updated on the actual screen.
+
+ // first, call the parent implementation. The parent implementation will update
+ // the region on our in-memory surface
+ QScreen::exposeRegion(r, changing);
+
+ // now our in-memory surface should be up to date with the latest changes.
+ // the code below copies the region from the in-memory surface to the hardware.
+
+ // just get the bounding rectangle of the region. Most screen updates are rectangular
+ // anyways. Code could be optimized to blit each and every member of the region
+ // individually, but in real life, the speed-up is neglectable
+ const QRect br = r.boundingRect();
+ if (br.isEmpty())
+ return; // ignore empty regions because gf_draw_blit2 doesn't like 0x0 dimensions
+
+ // start drawing.
+ int ret = gf_draw_begin(d->context);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_draw_begin() failed with error code %d", ret);
+ return;
+ }
+
+ // blit the changed region from the memory surface to the hardware surface
+ ret = gf_draw_blit2(d->context, d->memSurface, d->hwSurface,
+ br.x(), br.y(), br.right(), br.bottom(), br.x(), br.y());
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_draw_blit2() failed with error code %d", ret);
+ }
+
+ // flush all drawing commands (in our case, a single blit)
+ ret = gf_draw_flush(d->context);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_draw_flush() failed with error code %d", ret);
+ }
+
+ // tell QNX that we're done drawing.
+ gf_draw_end(d->context);
+}
+
diff --git a/src/gui/embedded/qscreenqnx_qws.h b/src/gui/embedded/qscreenqnx_qws.h
new file mode 100644
index 0000000..837c061
--- /dev/null
+++ b/src/gui/embedded/qscreenqnx_qws.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREENQNX_QWS_H
+#define QSCREENQNX_QWS_H
+
+#include <QtGui/qscreen_qws.h>
+
+#ifndef QT_NO_QWS_QNX
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+struct QQnxScreenContext;
+
+class QQnxScreen : public QScreen
+{
+public:
+ explicit QQnxScreen(int display_id);
+ ~QQnxScreen();
+
+ bool initDevice();
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ void shutdownDevice();
+ void setMode(int,int,int);
+ bool supportsDepth(int) const;
+
+ void exposeRegion(QRegion r, int changing);
+
+private:
+ QQnxScreenContext * const d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QWS_QNX
+
+#endif
diff --git a/src/gui/embedded/qwindowsystem_qws.cpp b/src/gui/embedded/qwindowsystem_qws.cpp
index 0580198..624ba84 100644
--- a/src/gui/embedded/qwindowsystem_qws.cpp
+++ b/src/gui/embedded/qwindowsystem_qws.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
+
#include "qwindowsystem_qws.h"
#include "qwsevent_qws.h"
#include "qwscommand_qws_p.h"
@@ -71,24 +73,26 @@
#include <qdebug.h>
-#include <unistd.h>
+#include "qkbddriverfactory_qws.h"
+#include "qmousedriverfactory_qws.h"
+
+#include <qbuffer.h>
+#include <qdir.h>
+
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qfontengine_qpf_p.h>
+
+#include "qwindowsystem_p.h"
+
+
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifndef QT_NO_QWS_MULTIPROCESS
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#ifndef Q_OS_DARWIN
-# include <sys/sem.h>
-#endif
#include <sys/param.h>
#include <sys/mount.h>
#endif
-#include <signal.h>
-#include <fcntl.h>
#if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
#ifdef QT_USE_OLD_QWS_SOUND
@@ -101,17 +105,6 @@
#endif
#endif
-#include "qkbddriverfactory_qws.h"
-#include "qmousedriverfactory_qws.h"
-
-#include <qbuffer.h>
-#include <qdir.h>
-
-#include <private/qwindowsurface_qws_p.h>
-#include <private/qfontengine_qpf_p.h>
-
-#include "qwindowsystem_p.h"
-
//#define QWS_DEBUG_FONTCLEANUP
QT_BEGIN_NAMESPACE
@@ -1400,7 +1393,7 @@ void QWSServerPrivate::initServer(int flags)
#ifndef QT_NO_QWS_MULTIPROCESS
if (!geteuid()) {
-#if !defined(Q_OS_FREEBSD) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_DARWIN) && !defined(QT_LINUXBASE)
+#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
if(mount(0,"/var/shm", "shm", 0, 0)) {
/* This just confuses people with 2.2 kernels
if (errno != EBUSY)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 6770206..5aae93e 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -6747,6 +6747,16 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent
*/
/*!
+ \fn const QObjectList &QGraphicsObject::children() const
+ \internal
+
+ This function returns the same value as QObject::children(). It's
+ provided to differentiate between the obsolete member
+ QGraphicsItem::children() and QObject::children(). QGraphicsItem now
+ provides childItems() instead.
+*/
+
+/*!
\property QGraphicsObject::transformOriginPoint
\brief the transformation origin
diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h
index adf9438..b5d8d84 100644
--- a/src/gui/graphicsview/qgraphicstransform.h
+++ b/src/gui/graphicsview/qgraphicstransform.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
@@ -34,7 +34,7 @@
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -65,7 +65,7 @@ public:
QTransform transform() const;
virtual void applyTo(QTransform *transform) const = 0;
-protected slots:
+protected Q_SLOTS:
void update();
protected:
diff --git a/src/gui/inputmethod/qinputcontextplugin.h b/src/gui/inputmethod/qinputcontextplugin.h
index 8ab8f84..c0c127b 100644
--- a/src/gui/inputmethod/qinputcontextplugin.h
+++ b/src/gui/inputmethod/qinputcontextplugin.h
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-#if !defined(QT_NO_IM) && !defined(QT_NO_LIBRARY)
+#if !defined(QT_NO_IM)
class QInputContext;
class QInputContextPluginPrivate;
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index 9b21163..074b189 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -53,6 +53,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qdebug.h"
#include "qximinputcontext_p.h"
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 3453408..5181689 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qabstracteventdispatcher.h"
#include "qaccessible.h"
#include "qapplication.h"
diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp
index 347afc8..00695fa 100644
--- a/src/gui/kernel/qapplication_qws.cpp
+++ b/src/gui/kernel/qapplication_qws.cpp
@@ -101,7 +101,11 @@
#include <locale.h>
#include <errno.h>
#include <fcntl.h>
-#include <sys/time.h>
+#ifdef Q_OS_VXWORKS
+# include <sys/times.h>
+#else
+# include <sys/time.h>
+#endif
#include <sys/stat.h>
#include <sys/types.h>
@@ -194,7 +198,14 @@ QString qws_dataDir()
static QString result;
if (!result.isEmpty())
return result;
- QByteArray dataDir = QString::fromLatin1("/tmp/qtembedded-%1").arg(qws_display_id).toLocal8Bit();
+ QByteArray dataDir;
+#ifdef QT_QWS_TEMP_DIR
+ dataDir = QT_QWS_TEMP_DIR;
+#else
+ dataDir = "/tmp";
+#endif
+ dataDir += "/qtembedded-";
+ dataDir += QByteArray::number(qws_display_id);
if (QT_MKDIR(dataDir, 0700)) {
if (errno != EEXIST) {
qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
@@ -208,7 +219,7 @@ QString qws_dataDir()
if (!S_ISDIR(buf.st_mode))
qFatal("%s is not a directory", dataDir.constData());
-#ifndef Q_OS_INTEGRITY
+#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS)
if (buf.st_uid != getuid())
qFatal("Qt for Embedded Linux data directory is not owned by user %d", getuid());
diff --git a/src/gui/kernel/qboxlayout.cpp b/src/gui/kernel/qboxlayout.cpp
index 770f5bb..23d20ff 100644
--- a/src/gui/kernel/qboxlayout.cpp
+++ b/src/gui/kernel/qboxlayout.cpp
@@ -527,7 +527,7 @@ void QBoxLayoutPrivate::calcHfw(int w)
You will almost always want to use QVBoxLayout and QHBoxLayout
rather than QBoxLayout because of their convenient constructors.
- \sa QGridLayout, QStackedLayout, {Layout Classes}
+ \sa QGridLayout, QStackedLayout, {Layout Management}
*/
/*!
@@ -1295,7 +1295,7 @@ QBoxLayout::Direction QBoxLayout::direction() const
\image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
- \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+ \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
*/
@@ -1413,7 +1413,7 @@ QHBoxLayout::~QHBoxLayout()
\image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets
- \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+ \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
*/
/*!
diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp
index 7ac874e..558f570 100644
--- a/src/gui/kernel/qgridlayout.cpp
+++ b/src/gui/kernel/qgridlayout.cpp
@@ -1046,7 +1046,7 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const
the margin width for a top-level layout, or to the same as the
parent layout.
- \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+ \sa QBoxLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
*/
diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp
index e750088..941db8f 100644
--- a/src/gui/kernel/qlayout.cpp
+++ b/src/gui/kernel/qlayout.cpp
@@ -83,7 +83,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
For users of QLayout subclasses or of QMainWindow there is seldom
any need to use the basic functions provided by QLayout, such as
- setSizeConstraint() or setMenuBar(). See \l{Layout Classes}
+ setSizeConstraint() or setMenuBar(). See \l{Layout Management}
for more information.
To make your own layout manager, implement the functions
@@ -98,7 +98,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
Geometry management stops when the layout manager is deleted.
- \sa QLayoutItem, {Layout Classes}, {Basic Layouts Example},
+ \sa QLayoutItem, {Layout Management}, {Basic Layouts Example},
{Border Layout Example}, {Flow Layout Example}
*/
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index 1c8394b..1ac51e0 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -74,11 +74,19 @@
#include <X11/Xutil.h>
#include <X11/Xos.h>
#ifdef index
-# undef index
+# undef index
#endif
#ifdef rindex
-# undef rindex
+# undef rindex
#endif
+#ifdef Q_OS_VXWORS
+# ifdef open
+# undef open
+# endif
+# ifdef getpid
+# undef getpid
+# endif
+#endif // Q_OS_VXWORKS
#include <X11/Xatom.h>
//#define QT_NO_SHAPE
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 7026525..bca607c 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -505,7 +505,7 @@ void QWidget::setAutoFillBackground(bool enabled)
been outlined to indicate their full sizes.
If you want to use a QWidget to hold child widgets you will usually want to
- add a layout to the parent QWidget. See \l{Layout Classes} for more
+ add a layout to the parent QWidget. See \l{Layout Management} for more
information.
@@ -8854,7 +8854,7 @@ QRegion QWidget::mask() const
The layout manager sets the geometry of the widget's children
that have been added to the layout.
- \sa setLayout(), sizePolicy(), {Layout Classes}
+ \sa setLayout(), sizePolicy(), {Layout Management}
*/
QLayout *QWidget::layout() const
{
@@ -8884,7 +8884,7 @@ QLayout *QWidget::layout() const
The QWidget will take ownership of \a layout.
- \sa layout(), {Layout Classes}
+ \sa layout(), {Layout Management}
*/
void QWidget::setLayout(QLayout *l)
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
index 659331f..359434e 100644
--- a/src/gui/kernel/qx11embed_x11.cpp
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qx11embed_x11.h"
#include <qapplication.h>
#include <qevent.h>
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 34bc578..01c6159 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -39,6 +39,9 @@
**
****************************************************************************/
+
+#include "qplatformdefs.h"
+
#include "qbackingstore_p.h"
#include <QtCore/qglobal.h>
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index 6dbb94b..13b5eba 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -51,6 +51,15 @@
#include <QtGui/qimage.h>
#include <QtGui/qpixmap.h>
+#if defined(Q_OS_VXWORKS)
+# if defined(m_data)
+# undef m_data
+# endif
+# if defined(m_type)
+# undef m_type
+# endif
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index 275ec13..b568f43 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -114,6 +114,23 @@ public:
qSwap(buffer, other.buffer);
}
+ inline void insertBlank(int pos, int count) {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos < siz);
+ reserve(siz + count);
+ for (int i = siz - pos - 1; i >= 0; --i)
+ buffer[pos + count + i] = buffer[pos + i];
+ siz += count;
+ }
+
+ inline void removeAndShift(int pos, int count) {
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos < siz);
+ for (int i=pos; i<siz-count; ++i)
+ buffer[i] = buffer[i+count];
+ siz -= count;
+ }
+
inline QDataBuffer &operator<<(const Type &t) { add(t); return *this; }
private:
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index 7a9eda3..c41b040 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -134,7 +134,9 @@
#define ErrRaster_MemoryOverflow -4
-
+#if defined(VXWORKS)
+# include <vxWorksCommon.h> /* needed for setjmp.h */
+#endif
#include <string.h> /* for qt_ft_memcpy() */
#include <setjmp.h>
#include <limits.h>
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index 401fad9..9c073f2 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qoutlinemapper_p.h"
+#include "qbezier_p.h"
#include "qmath.h"
@@ -199,51 +200,69 @@ void QOutlineMapper::endOutline()
}
} else {
// ## TODO: this case needs to be plain code polygonal paths
- QPainterPath path;
+ QTransform matrix(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33);
+
if (m_element_types.isEmpty()) {
if (!m_elements.isEmpty())
- path.moveTo(m_elements.at(0));
+ m_elements_dev << m_elements.at(0) * matrix;
for (int i=1; i<m_elements.size(); ++i)
- path.lineTo(m_elements.at(i));
+ m_elements_dev << m_elements.at(i) * matrix;
+
} else {
- for (int i=0; i<m_elements.size(); ++i) {
- switch (m_element_types.at(i)) {
+ for (int i=0, t=0; i<m_elements.size(); ++i) {
+ switch (m_element_types.at(t)) {
case QPainterPath::MoveToElement:
- path.moveTo(m_elements.at(i));
+ m_elements_dev << m_elements.at(i) * matrix;
+ ++t;
break;
case QPainterPath::LineToElement:
- path.lineTo(m_elements.at(i));
+ m_elements_dev << m_elements.at(i) * matrix;
+ ++t;
break;
- case QPainterPath::CurveToElement:
- path.cubicTo(m_elements.at(i), m_elements.at(i+1), m_elements.at(i+2));
+ case QPainterPath::CurveToElement: {
+ QPolygonF segment = QBezier::fromPoints(m_elements.at(i-1),
+ m_elements.at(i),
+ m_elements.at(i+1),
+ m_elements.at(i+2)).toPolygon();
+ if (segment.size() > 3)
+ m_element_types.insertBlank(t, segment.size() - 3);
+ else if (segment.size() < 3)
+ m_element_types.removeAndShift(t, 3 - segment.size());
+
+ for (QPolygonF::const_iterator it = segment.constBegin();
+ it < segment.constEnd(); ++it, ++t) {
+ m_elements_dev << *it * matrix;
+ m_element_types.at(t) = QPainterPath::LineToElement;
+ }
i += 2;
- break;
+ } break;
default:
Q_ASSERT(false);
break;
}
}
+ element_count = m_elements_dev.size();
}
- path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path);
- uint old_txop = m_txop;
- m_txop = QTransform::TxNone;
- if (path.isEmpty())
- m_valid = false;
- else
- convertPath(path);
- m_txop = old_txop;
- return;
}
elements = m_elements_dev.data();
}
if (m_round_coords) {
// round coordinates to match outlines drawn with drawLine_midpoint_i
- for (int i = 0; i < m_elements.size(); ++i)
+ for (int i = 0; i < element_count; ++i)
elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta),
qFloor(elements[i].y() + aliasedCoordinateDelta));
}
+#ifdef QT_DEBUG_CONVERT
+ for (int i=0; i<element_count; ++i) {
+ printf("%d: (%.2f, %.2f)\n",
+ !m_element_types.isEmpty() ? m_element_types.at(i) : -1,
+ elements[i].x(),
+ elements[i].y());
+ }
+#endif
+
controlPointRect = boundingRect(elements, element_count);
#ifdef QT_DEBUG_CONVERT
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index dfd3e16..69e490a 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1672,34 +1672,6 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
QPaintEngineEx::drawRects(rects, rectCount);
}
-void QRasterPaintEnginePrivate::strokeProjective(const QPainterPath &path)
-{
- Q_Q(QRasterPaintEngine);
- QRasterPaintEngineState *s = q->state();
-
- const QPen &pen = s->lastPen;
- QPainterPathStroker pathStroker;
- pathStroker.setWidth(pen.width() == 0 ? qreal(1) : pen.width());
- pathStroker.setCapStyle(pen.capStyle());
- pathStroker.setJoinStyle(pen.joinStyle());
- pathStroker.setMiterLimit(pen.miterLimit());
- pathStroker.setDashOffset(pen.dashOffset());
-
- if (qpen_style(pen) == Qt::CustomDashLine)
- pathStroker.setDashPattern(pen.dashPattern());
- else
- pathStroker.setDashPattern(qpen_style(pen));
-
- outlineMapper->setMatrix(QTransform());
- const QPainterPath stroke = pen.isCosmetic()
- ? pathStroker.createStroke(s->matrix.map(path))
- : s->matrix.map(pathStroker.createStroke(path));
-
- rasterize(outlineMapper->convertPath(stroke), s->penData.blend, &s->penData, rasterBuffer);
- outlinemapper_xform_dirty = true;
-}
-
-
/*!
\internal
@@ -1969,67 +1941,6 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
fillRect(r, &d->solid_color_filler);
}
-/*!
- \reimp
-*/
-void QRasterPaintEngine::drawPath(const QPainterPath &path)
-{
-#ifdef QT_DEBUG_DRAW
- QRectF bounds = path.boundingRect();
- qDebug(" - QRasterPaintEngine::drawPath(), [%.2f, %.2f, %.2f, %.2f]",
- bounds.x(), bounds.y(), bounds.width(), bounds.height());
-#endif
-
- if (path.isEmpty())
- return;
-
- // Filling..,
- Q_D(QRasterPaintEngine);
- QRasterPaintEngineState *s = state();
-
- ensureBrush();
- if (s->brushData.blend) {
- ensureOutlineMapper();
- fillPath(path, &s->brushData);
- }
-
- // Stroking...
- ensurePen();
- if (!s->penData.blend)
- return;
- {
- if (s->matrix.type() >= QTransform::TxProject) {
- d->strokeProjective(path);
- } else {
- Q_ASSERT(s->stroker);
- d->outlineMapper->beginOutline(Qt::WindingFill);
- qreal txscale = 1;
- if (s->pen.isCosmetic() || (qt_scaleForTransform(s->matrix, &txscale) && txscale != 1)) {
- const qreal strokeWidth = d->basicStroker.strokeWidth();
- const QRectF clipRect = d->dashStroker ? d->dashStroker->clipRect() : QRectF();
- if (d->dashStroker)
- d->dashStroker->setClipRect(d->deviceRect);
- d->basicStroker.setStrokeWidth(strokeWidth * txscale);
- d->outlineMapper->setMatrix(QTransform());
- s->stroker->strokePath(path, d->outlineMapper, s->matrix);
- d->outlinemapper_xform_dirty = true;
- d->basicStroker.setStrokeWidth(strokeWidth);
- if (d->dashStroker)
- d->dashStroker->setClipRect(clipRect);
- } else {
- ensureOutlineMapper();
- s->stroker->strokePath(path, d->outlineMapper, QTransform());
- }
- d->outlineMapper->endOutline();
-
- ProcessSpans blend = d->getPenFunc(d->outlineMapper->controlPointRect,
- &s->penData);
- d->rasterize(d->outlineMapper->outline(), blend, &s->penData, d->rasterBuffer);
- }
- }
-
-}
-
static inline bool isAbove(const QPointF *a, const QPointF *b)
{
return a->y() < b->y();
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 283c442..3dab491 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -165,7 +165,6 @@ public:
void updateMatrix(const QTransform &matrix);
- void drawPath(const QPainterPath &path);
void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
void fillPath(const QPainterPath &path, QSpanData *fillData);
@@ -327,7 +326,6 @@ public:
inline const QClipData *clip() const;
- void strokeProjective(const QPainterPath &path);
void initializeRasterizer(QSpanData *data);
void recalculateFastImages();
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 797a5ab..8ec881e 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -42,6 +42,7 @@
#include "qpaintengineex_p.h"
#include "qpainter_p.h"
#include "qstroker_p.h"
+#include "qbezier_p.h"
#include <private/qpainterpath_p.h>
#include <qvarlengtharray.h>
@@ -91,6 +92,40 @@ QRectF QVectorPath::controlPointRect() const
return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
}
+QPainterPath QVectorPath::convertToPainterPath() const
+{
+ QPainterPath path;
+
+ if (m_count == 0)
+ return path;
+
+ const QPointF *points = (const QPointF *) m_points;
+
+ if (m_elements) {
+ for (int i=0; i<m_count; ++i) {
+ switch (m_elements[i]) {
+ case QPainterPath::MoveToElement:
+ path.moveTo(points[i]);
+ break;
+ case QPainterPath::LineToElement:
+ path.lineTo(points[i]);
+ break;
+ case QPainterPath::CurveToElement:
+ path.cubicTo(points[i], points[i+1], points[i+2]);
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ path.moveTo(points[0]);
+ for (int i=1; i<m_count; ++i)
+ path.lineTo(points[i]);
+ }
+
+ return path;
+}
+
const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
{
Q_ASSERT(path.d_func());
@@ -450,13 +485,14 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
QVectorPath strokePath(d->strokeHandler->pts.data(),
d->strokeHandler->types.size(),
d->strokeHandler->types.data(),
- QVectorPath::WindingFill);
+ flags);
fill(strokePath, pen.brush());
} else {
const qreal strokeWidth = d->stroker.strokeWidth();
d->stroker.setStrokeWidth(strokeWidth * txscale);
// For cosmetic pens we need a bit of trickery... We to process xform the input points
if (types) {
+ bool isProject = state()->matrix.type() >= QTransform::TxProject;
while (points < lastPoint) {
switch (*types) {
case QPainterPath::MoveToElement: {
@@ -474,10 +510,30 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
break;
}
case QPainterPath::CurveToElement: {
- QPointF c1 = ((QPointF *) points)[0] * state()->matrix;
- QPointF c2 = ((QPointF *) points)[1] * state()->matrix;
- QPointF e = ((QPointF *) points)[2] * state()->matrix;
- d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
+ // Convert projective xformed curves to line
+ // segments so they can be transformed more
+ // accurately
+ if (isProject) {
+ // -1 access here is safe because there is
+ // always an element prior to the cubicTo, we
+ // just need the value..
+ QPolygonF segment =
+ QBezier::fromPoints(*(((QPointF *) points) - 1),
+ *((QPointF *) points),
+ *(((QPointF *) points) + 1),
+ *(((QPointF *) points) + 2)).toPolygon();
+
+ for (QPolygonF::const_iterator it = segment.constBegin();
+ it < segment.constEnd(); ++it) {
+ const QPointF pt = *it * state()->matrix;
+ d->activeStroker->lineTo(pt.x(), pt.y());
+ }
+ } else {
+ QPointF c1 = ((QPointF *) points)[0] * state()->matrix;
+ QPointF c2 = ((QPointF *) points)[1] * state()->matrix;
+ QPointF e = ((QPointF *) points)[2] * state()->matrix;
+ d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
+ }
points += 6;
types += 3;
flags |= QVectorPath::CurvedShapeHint;
@@ -512,7 +568,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
QVectorPath strokePath(d->strokeHandler->pts.data(),
d->strokeHandler->types.size(),
d->strokeHandler->types.data(),
- QVectorPath::WindingFill);
+ flags);
QTransform xform = state()->matrix;
state()->matrix = QTransform();
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index ea86cf5..09972b0 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -3271,6 +3271,8 @@ void QPainterPath::setDirty(bool dirty)
{
d_func()->dirtyBounds = dirty;
d_func()->dirtyControlBounds = dirty;
+ delete d_func()->pathConverter;
+ d_func()->pathConverter = 0;
}
void QPainterPath::computeBoundingRect() const
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 6968f4e..a34c354 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -60,6 +60,10 @@
#include <private/qfontengineglyphcache_p.h>
+#if defined(Q_OS_VXWORKS) && defined(m_type)
+# undef m_type
+#endif
+
struct glyph_metrics_t;
typedef unsigned int glyph_t;
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index 291d35c..69d4de2 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -50,6 +50,10 @@
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
+#if defined(Q_OS_VXWORKS) && defined(m_type)
+# undef m_type
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index b6b85fa..9264c9c 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -130,6 +130,8 @@ public:
static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode);
+ QPainterPath convertToPainterPath() const;
+
private:
Q_DISABLE_COPY(QVectorPath)
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index b07acd5..9f046ff 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -67,6 +67,11 @@
#ifndef QT_NO_CSSPARSER
+// VxWorks defines NONE as (-1) "for times when NULL won't do"
+#if defined(Q_OS_VXWORKS) && defined(NONE)
+# undef NONE
+#endif
+
QT_BEGIN_NAMESPACE
namespace QCss
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index d348e1b..34239ff 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -360,7 +360,7 @@ static QString qwsFontPath()
return fontpath;
}
-#ifdef QFONTDATABASE_DEBUG
+#if defined(QFONTDATABASE_DEBUG) && defined(QT_FONTS_ARE_RESOURCES)
class FriendlyResource : public QResource
{
public:
@@ -694,8 +694,12 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QFontDef def = request;
def.pixelSize = pixelSize;
+#ifdef QT_NO_QWS_SHARE_FONTS
+ bool shareFonts = false;
+#else
static bool dontShareFonts = !qgetenv("QWS_NO_SHARE_FONTS").isEmpty();
bool shareFonts = !dontShareFonts;
+#endif
QFontEngine *engine = 0;
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index b255694..ed8abb8 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -331,16 +331,37 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
#if defined(DEBUG_FONTENGINE)
qDebug() << "found existing qpf:" << fileName;
#endif
- if (::access(encodedName, W_OK | R_OK) == 0)
- fd = QT_OPEN(encodedName, O_RDWR, 0);
- else if (::access(encodedName, R_OK) == 0)
- fd = QT_OPEN(encodedName, O_RDONLY, 0);
+ if (::access(encodedName, W_OK | R_OK) == 0) {
+ fd = QT_OPEN(encodedName, O_RDWR);
+ }
+ // read-write access failed - try read-only access
+ if (fd == -1 && ::access(encodedName, R_OK) == 0) {
+ fd = QT_OPEN(encodedName, O_RDONLY);
+ if (fd == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning("QFontEngineQPF: unable to open %s", encodedName.constData());
+#endif
+ return;
+ }
+ }
+ if (fd == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qWarning("QFontEngineQPF: insufficient access rights to %s", encodedName.constData());
+#endif
+ return;
+ }
} else {
#if defined(DEBUG_FONTENGINE)
qDebug() << "creating qpf on the fly:" << fileName;
#endif
if (::access(QFile::encodeName(qws_fontCacheDir()), W_OK) == 0) {
fd = QT_OPEN(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644);
+ if (fd == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "QFontEngineQPF: open() failed for %s", encodedName.constData());
+#endif
+ return;
+ }
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
@@ -348,7 +369,17 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
generator.generate();
buffer.close();
const QByteArray &data = buffer.data();
- QT_WRITE(fd, data.constData(), data.size());
+ if (QT_WRITE(fd, data.constData(), data.size()) == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "QFontEngineQPF: write() failed for %s", encodedName.constData());
+#endif
+ return;
+ }
+ } else {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "QFontEngineQPF: access() failed for %s", qPrintable(qws_fontCacheDir()));
+#endif
+ return;
}
}
}
@@ -356,7 +387,7 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
QT_STATBUF st;
if (QT_FSTAT(fd, &st)) {
#if defined(DEBUG_FONTENGINE)
- qDebug() << "stat failed!";
+ qErrnoWarning(errno, "QFontEngineQPF: fstat failed!");
#endif
return;
}
@@ -486,8 +517,13 @@ QFontEngineQPF::~QFontEngineQPF()
qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, QFile::encodeName(fileName));
#endif
delete renderingFontEngine;
- if (fontData)
- munmap((void *)fontData, dataSize);
+ if (fontData) {
+ if (munmap((void *)fontData, dataSize) == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "~QFontEngineQPF: Unable to munmap");
+#endif
+ }
+ }
if (fd != -1)
::close(fd);
#if !defined(QT_NO_FREETYPE)
diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp
index 70ce8f9..10bee2c 100644
--- a/src/gui/text/qfontengine_qws.cpp
+++ b/src/gui/text/qfontengine_qws.cpp
@@ -396,7 +396,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn)
uchar* data = (uchar*)mmap( 0, // any address
st.st_size, // whole file
PROT_READ, // read-only memory
-#if !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_INTEGRITY)
+#if !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS)
MAP_FILE | MAP_PRIVATE, // swap-backed map from file
#else
MAP_PRIVATE,
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index ea37e04..e66b07c 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -60,6 +60,15 @@ QT_BEGIN_NAMESPACE
#define PMDEBUG if(0) qDebug
+// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
+#if !defined(Q_CC_DIAB)
+# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
+ QTextUndoCommand c = { a1, a2, a3, a4, a5, a6, { a7 }, a8 }
+#else
+# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
+ QTextUndoCommand c = { a1, a2, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
+#endif
+
/*
Structure of a document:
@@ -406,9 +415,9 @@ int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator,
int b = blocks.findNode(pos);
QTextBlockData *B = blocks.fragment(b);
- QTextUndoCommand c = { QTextUndoCommand::BlockInserted, editBlock != 0,
- op, charFormat, strPos, pos, { blockFormat },
- B->revision };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockInserted, editBlock != 0,
+ op, charFormat, strPos, pos, blockFormat,
+ B->revision);
appendUndoItem(c);
Q_ASSERT(undoState == undoStack.size());
@@ -447,9 +456,9 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format
int b = blocks.findNode(pos);
QTextBlockData *B = blocks.fragment(b);
- QTextUndoCommand c = { QTextUndoCommand::Inserted, editBlock != 0,
- QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength },
- B->revision };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Inserted, editBlock != 0,
+ QTextUndoCommand::MoveCursor, format, strPos, pos, strLength,
+ B->revision);
appendUndoItem(c);
B->revision = undoState;
Q_ASSERT(undoState == undoStack.size());
@@ -606,12 +615,12 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
int blockRevision = B->revision;
QTextFragmentData *X = fragments.fragment(x);
- QTextUndoCommand c = { QTextUndoCommand::Removed, editBlock != 0,
- op, X->format, X->stringPosition, key, { X->size_array[0] },
- blockRevision };
- QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, editBlock != 0,
- op, X->format, X->stringPosition, dstKey, { X->size_array[0] },
- blockRevision };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Removed, editBlock != 0,
+ op, X->format, X->stringPosition, key, X->size_array[0],
+ blockRevision);
+ QT_INIT_TEXTUNDOCOMMAND(cInsert, QTextUndoCommand::Inserted, editBlock != 0,
+ op, X->format, X->stringPosition, dstKey, X->size_array[0],
+ blockRevision);
if (key+1 != blocks.position(b)) {
// qDebug("remove_string from %d length %d", key, X->size_array[0]);
@@ -723,8 +732,8 @@ void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFor
fragment->format = newFormatIdx;
}
- QTextUndoCommand c = { QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
- 0, pos, { length }, 0 };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
+ 0, pos, length, 0);
appendUndoItem(c);
pos += length;
@@ -783,8 +792,8 @@ void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlo
block(it)->invalidate();
- QTextUndoCommand c = { QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
- 0, it.position(), { 1 }, 0 };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
+ 0, it.position(), 1, 0);
appendUndoItem(c);
if (group != oldGroup) {
@@ -1298,8 +1307,8 @@ void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
if (f)
documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());
- QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, editBlock != 0, QTextUndoCommand::MoveCursor, oldFormatIndex,
- 0, 0, { obj->d_func()->objectIndex }, 0 };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::GroupFormatChange, editBlock != 0, QTextUndoCommand::MoveCursor, oldFormatIndex,
+ 0, 0, obj->d_func()->objectIndex, 0);
appendUndoItem(c);
endEditBlock();
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index a940aa4..cb09452 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -54,7 +54,11 @@
QT_BEGIN_NAMESPACE
QTextCopyHelper::QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat, const QTextCharFormat &fmt)
+#if defined(Q_CC_DIAB) // compiler bug
+ : formatCollection(*_destination.d->priv->formatCollection()), originalText((const QString)_source.d->priv->buffer())
+#else
: formatCollection(*_destination.d->priv->formatCollection()), originalText(_source.d->priv->buffer())
+#endif
{
src = _source.d->priv;
dst = _destination.d->priv;
diff --git a/src/gui/util/qdesktopservices_x11.cpp b/src/gui/util/qdesktopservices_x11.cpp
index f0202d4..0a3c2d0 100644
--- a/src/gui/util/qdesktopservices_x11.cpp
+++ b/src/gui/util/qdesktopservices_x11.cpp
@@ -56,7 +56,11 @@ QT_BEGIN_NAMESPACE
inline static bool launch(const QUrl &url, const QString &client)
{
+#if !defined(QT_NO_PROCESS)
return (QProcess::startDetached(client + QLatin1Char(' ') + QString::fromLatin1(url.toEncoded().constData())));
+#else
+ return (::system((client + QLatin1Char(' ') + QString::fromLatin1(url.toEncoded().constData())).toLocal8Bit().constData()) != -1);
+#endif
}
static bool openDocument(const QUrl &url)
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index 433406c..7fa26ae 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -976,7 +976,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
#endif
case Qt::Key_Enter:
case Qt::Key_Return:
- d->edit->d_func()->modifiedState = d->edit->d_func()->undoState = 0;
+ d->edit->d_func()->control->clearUndo();
d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged);
selectAll();
event->ignore();
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
new file mode 100644
index 0000000..106d8f2
--- /dev/null
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -0,0 +1,1749 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlinecontrol_p.h"
+
+#ifndef QT_NO_LINEEDIT
+
+#include "qabstractitemview.h"
+#include "qclipboard.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qlist.h"
+#endif
+#include "qapplication.h"
+#ifndef QT_NO_GRAPHICSVIEW
+#include "qgraphicssceneevent.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ Updates the display text based of the current edit text
+ If the text has changed will emit displayTextChanged()
+*/
+void QLineControl::updateDisplayText()
+{
+ QString orig = m_textLayout.text();
+ QString str;
+ if (m_echoMode == QLineEdit::NoEcho)
+ str = QString::fromLatin1("");
+ else
+ str = m_text;
+
+ if (m_echoMode == QLineEdit::Password || (m_echoMode == QLineEdit::PasswordEchoOnEdit
+ && !m_passwordEchoEditing))
+ str.fill(m_passwordCharacter);
+
+ // replace certain non-printable characters with spaces (to avoid
+ // drawing boxes when using fonts that don't have glyphs for such
+ // characters)
+ QChar* uc = str.data();
+ for (int i = 0; i < (int)str.length(); ++i) {
+ if ((uc[i] < 0x20 && uc[i] != 0x09)
+ || uc[i] == QChar::LineSeparator
+ || uc[i] == QChar::ParagraphSeparator
+ || uc[i] == QChar::ObjectReplacementCharacter)
+ uc[i] = QChar(0x0020);
+ }
+
+ m_textLayout.setText(str);
+
+ QTextOption option;
+ option.setTextDirection(m_layoutDirection);
+ option.setFlags(QTextOption::IncludeTrailingSpaces);
+ m_textLayout.setTextOption(option);
+
+ m_textLayout.beginLayout();
+ QTextLine l = m_textLayout.createLine();
+ m_textLayout.endLayout();
+ m_ascent = qRound(l.ascent());
+
+ if (str != orig)
+ emit displayTextChanged(str);
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \internal
+
+ Copies the currently selected text into the clipboard using the given
+ \a mode.
+
+ \note If the echo mode is set to a mode other than Normal then copy
+ will not work. This is to prevent using copy as a method of bypassing
+ password features of the line control.
+*/
+void QLineControl::copy(QClipboard::Mode mode) const
+{
+ QString t = selectedText();
+ if (!t.isEmpty() && m_echoMode == QLineEdit::Normal) {
+ disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
+ QApplication::clipboard()->setText(t, mode);
+ connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
+ this, SLOT(_q_clipboardChanged()));
+ }
+}
+
+/*!
+ \internal
+
+ Inserts the text stored in the application clipboard into the line
+ control.
+
+ \sa insert()
+*/
+void QLineControl::paste()
+{
+ insert(QApplication::clipboard()->text(QClipboard::Clipboard));
+}
+
+#endif // !QT_NO_CLIPBOARD
+
+/*!
+ \internal
+
+ Handles the behavior for the backspace key or function.
+ Removes the current selection if there is a selection, otherwise
+ removes the character prior to the cursor position.
+
+ \sa del()
+*/
+void QLineControl::backspace()
+{
+ int priorState = m_undoState;
+ if (hasSelectedText()) {
+ removeSelectedText();
+ } else if (m_cursor) {
+ --m_cursor;
+ if (m_maskData)
+ m_cursor = prevMaskBlank(m_cursor);
+ QChar uc = m_text.at(m_cursor);
+ if (m_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 = m_text.at(m_cursor - 1);
+ if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
+ internalDelete(true);
+ --m_cursor;
+ }
+ }
+ internalDelete(true);
+ }
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Handles the behavior for the delete key or function.
+ Removes the current selection if there is a selection, otherwise
+ removes the character after the cursor position.
+
+ \sa del()
+*/
+void QLineControl::del()
+{
+ int priorState = m_undoState;
+ if (hasSelectedText()) {
+ removeSelectedText();
+ } else {
+ int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
+ while (n--)
+ internalDelete();
+ }
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Inserts the given \a newText at the current cursor position.
+ If there is any selected text it is removed prior to insertion of
+ the new text.
+*/
+void QLineControl::insert(const QString &newText)
+{
+ int priorState = m_undoState;
+ removeSelectedText();
+ internalInsert(newText);
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Clears the line control text.
+*/
+void QLineControl::clear()
+{
+ int priorState = m_undoState;
+ m_selstart = 0;
+ m_selend = m_text.length();
+ removeSelectedText();
+ separate();
+ finishChange(priorState, /*update*/false, /*edited*/false);
+}
+
+/*!
+ \internal
+
+ Sets \a length characters from the given \a start position as selected.
+ The given \a start position must be within the current text for
+ the line control. If \a length characters cannot be selected, then
+ the selection will extend to the end of the current text.
+*/
+void QLineControl::setSelection(int start, int length)
+{
+ if(start < 0 || start > (int)m_text.length()){
+ qWarning("QLineControl::setSelection: Invalid start position");
+ return;
+ }
+
+ if (length > 0) {
+ if (start == m_selstart && start + length == m_selend)
+ return;
+ m_selstart = start;
+ m_selend = qMin(start + length, (int)m_text.length());
+ m_cursor = m_selend;
+ } else {
+ if (start == m_selend && start + length == m_selstart)
+ return;
+ m_selstart = qMax(start + length, 0);
+ m_selend = start;
+ m_cursor = m_selstart;
+ }
+ emit selectionChanged();
+}
+
+void QLineControl::_q_clipboardChanged()
+{
+}
+
+void QLineControl::_q_deleteSelected()
+{
+ if (!hasSelectedText())
+ return;
+
+ int priorState = m_undoState;
+ emit resetInputContext();
+ removeSelectedText();
+ separate();
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Initializes the line control with a starting text value of \a txt.
+*/
+void QLineControl::init(const QString &txt)
+{
+ m_text = txt;
+ updateDisplayText();
+ m_cursor = m_text.length();
+}
+
+/*!
+ \internal
+
+ Sets the password echo editing to \a editing. If password echo editing
+ is true, then the text of the password is displayed even if the echo
+ mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing
+ does not affect other echo modes.
+*/
+void QLineControl::updatePasswordEchoEditing(bool editing)
+{
+ m_passwordEchoEditing = editing;
+ updateDisplayText();
+}
+
+/*!
+ \internal
+
+ Returns the cursor position of the given \a x pixel value in relation
+ to the displayed text. The given \a betweenOrOn specified what kind
+ of cursor position is requested.
+*/
+int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
+{
+ return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
+}
+
+/*!
+ \internal
+
+ Returns the bounds of the current cursor, as defined as a
+ between characters cursor.
+*/
+QRect QLineControl::cursorRect() const
+{
+ QTextLine l = m_textLayout.lineAt(0);
+ int c = m_cursor;
+ if (m_preeditCursor != -1)
+ c += m_preeditCursor;
+ int cix = qRound(l.cursorToX(c));
+ int w = m_cursorWidth;
+ int ch = l.height() + 1;
+
+ return QRect(cix-5, 0, w+9, ch);
+}
+
+/*!
+ \internal
+
+ Fixes the current text so that it is valid given any set validators.
+
+ Returns true if the text was changed. Otherwise returns false.
+*/
+bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable
+{
+#ifndef QT_NO_VALIDATOR
+ if (m_validator) {
+ QString textCopy = m_text;
+ int cursorCopy = m_cursor;
+ m_validator->fixup(textCopy);
+ if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
+ if (textCopy != m_text || cursorCopy != m_cursor)
+ internalSetText(textCopy, cursorCopy);
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+/*!
+ \internal
+
+ Moves the cursor to the given position \a pos. If \a mark is true will
+ adjust the currently selected text.
+*/
+void QLineControl::moveCursor(int pos, bool mark)
+{
+ if (pos != m_cursor) {
+ separate();
+ if (m_maskData)
+ pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
+ }
+ if (mark) {
+ int anchor;
+ if (m_selend > m_selstart && m_cursor == m_selstart)
+ anchor = m_selend;
+ else if (m_selend > m_selstart && m_cursor == m_selend)
+ anchor = m_selstart;
+ else
+ anchor = m_cursor;
+ m_selstart = qMin(anchor, pos);
+ m_selend = qMax(anchor, pos);
+ updateDisplayText();
+ } else {
+ internalDeselect();
+ }
+ m_cursor = pos;
+ if (mark || m_selDirty) {
+ m_selDirty = false;
+ emit selectionChanged();
+ }
+ emitCursorPositionChanged();
+}
+
+/*!
+ \internal
+
+ Applies the given input method event \a event to the text of the line
+ control
+*/
+void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
+{
+ int priorState = m_undoState;
+ removeSelectedText();
+
+ int c = m_cursor; // cursor position after insertion of commit string
+ if (event->replacementStart() <= 0)
+ c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength());
+
+ m_cursor += event->replacementStart();
+
+ // insert commit string
+ if (event->replacementLength()) {
+ m_selstart = m_cursor;
+ m_selend = m_selstart + event->replacementLength();
+ removeSelectedText();
+ }
+ if (!event->commitString().isEmpty())
+ insert(event->commitString());
+
+ m_cursor = qMin(c, m_text.length());
+
+ setPreeditArea(m_cursor, event->preeditString());
+ m_preeditCursor = event->preeditString().length();
+ m_hideCursor = false;
+ QList<QTextLayout::FormatRange> formats;
+ for (int i = 0; i < event->attributes().size(); ++i) {
+ const QInputMethodEvent::Attribute &a = event->attributes().at(i);
+ if (a.type == QInputMethodEvent::Cursor) {
+ m_preeditCursor = a.start;
+ m_hideCursor = !a.length;
+ } else if (a.type == QInputMethodEvent::TextFormat) {
+ QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
+ if (f.isValid()) {
+ QTextLayout::FormatRange o;
+ o.start = a.start + m_cursor;
+ o.length = a.length;
+ o.format = f;
+ formats.append(o);
+ }
+ }
+ }
+ m_textLayout.setAdditionalFormats(formats);
+ updateDisplayText();
+ if (!event->commitString().isEmpty())
+ emitCursorPositionChanged();
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Draws the display text for the line control using the given
+ \a painter, \a clip, and \a offset. Which aspects of the display text
+ are drawn is specified by the given \a flags.
+
+ If the flags contain DrawSelections, then the selection or input mask
+ backgrounds and foregrounds will be applied before drawing the text.
+
+ If the flags contain DrawCursor a cursor of the current cursorWidth()
+ will be drawn after drawing the text.
+
+ The display text will only be drawn if the flags contain DrawText
+*/
+void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags)
+{
+ QVector<QTextLayout::FormatRange> selections;
+ if (flags & DrawSelections) {
+ QTextLayout::FormatRange o;
+ if (m_selstart < m_selend) {
+ o.start = m_selstart;
+ o.length = m_selend - m_selstart;
+ o.format.setBackground(m_palette.brush(QPalette::Highlight));
+ o.format.setForeground(m_palette.brush(QPalette::HighlightedText));
+ } else {
+ // mask selection
+ o.start = m_cursor;
+ o.length = 1;
+ o.format.setBackground(m_palette.brush(QPalette::Text));
+ o.format.setForeground(m_palette.brush(QPalette::Window));
+ }
+ selections.append(o);
+ }
+
+ if (flags & DrawText)
+ m_textLayout.draw(painter, offset, selections, clip);
+
+ if (flags & DrawCursor){
+ if(!m_blinkPeriod || m_blinkStatus)
+ m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth);
+ }
+}
+
+/*!
+ \internal
+
+ Sets the selection to cover the word at the given cursor position.
+ The word boundries is defined by the behavior of QTextLayout::SkipWords
+ cursor mode.
+*/
+void QLineControl::selectWordAtPos(int cursor)
+{
+ int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords);
+ moveCursor(c, false);
+ // ## text layout should support end of words.
+ int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords);
+ while (end > cursor && m_text[end-1].isSpace())
+ --end;
+ moveCursor(end, true);
+}
+
+/*!
+ \internal
+
+ Completes a change to the line control text. If the change is not valid
+ will undo the line control state back to the given \a validateFromState.
+
+ If \a edited is true and the change is valid, will emit textEdited() in
+ addition to textChanged(). Otherwise only emits textChanged() on a valid
+ change.
+
+ The \a update value is currently unused.
+*/
+bool QLineControl::finishChange(int validateFromState, bool update, bool edited)
+{
+ Q_UNUSED(update)
+ bool lineDirty = m_selDirty;
+ if (m_textDirty) {
+ // do validation
+ bool wasValidInput = m_validInput;
+ m_validInput = true;
+#ifndef QT_NO_VALIDATOR
+ if (m_validator) {
+ m_validInput = false;
+ QString textCopy = m_text;
+ int cursorCopy = m_cursor;
+ m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
+ if (m_validInput) {
+ if (m_text != textCopy) {
+ internalSetText(textCopy, cursorCopy);
+ return true;
+ }
+ m_cursor = cursorCopy;
+ }
+ }
+#endif
+ if (validateFromState >= 0 && wasValidInput && !m_validInput) {
+ if (m_transactions.count())
+ return false;
+ internalUndo(validateFromState);
+ m_history.resize(m_undoState);
+ if (m_modifiedState > m_undoState)
+ m_modifiedState = -1;
+ m_validInput = true;
+ m_textDirty = false;
+ }
+ updateDisplayText();
+ lineDirty |= m_textDirty;
+ if (m_textDirty) {
+ m_textDirty = false;
+ QString actualText = text();
+ if (edited)
+ emit textEdited(actualText);
+ emit textChanged(actualText);
+ }
+ }
+ if (m_selDirty) {
+ m_selDirty = false;
+ emit selectionChanged();
+ }
+ emitCursorPositionChanged();
+ return true;
+}
+
+/*!
+ \internal
+
+ An internal function for setting the text of the line control.
+*/
+void QLineControl::internalSetText(const QString &txt, int pos, bool edited)
+{
+ internalDeselect();
+ emit resetInputContext();
+ QString oldText = m_text;
+ if (m_maskData) {
+ m_text = maskString(0, txt, true);
+ m_text += clearString(m_text.length(), m_maxLength - m_text.length());
+ } else {
+ m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
+ }
+ m_history.clear();
+ m_modifiedState = m_undoState = 0;
+ m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
+ m_textDirty = (oldText != m_text);
+ finishChange(-1, true, edited);
+}
+
+
+/*!
+ \internal
+
+ Adds the given \a command to the undo history
+ of the line control. Does not apply the command.
+*/
+void QLineControl::addCommand(const Command &cmd)
+{
+ if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) {
+ m_history.resize(m_undoState + 2);
+ m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend);
+ } else {
+ m_history.resize(m_undoState + 1);
+ }
+ m_separator = false;
+ m_history[m_undoState++] = cmd;
+}
+
+/*!
+ \internal
+
+ Inserts the given string \a s into the line
+ control.
+
+ Also adds the appropriate commands into the undo history.
+ This function does not call finishChange(), and may leave the text
+ in an invalid state.
+*/
+void QLineControl::internalInsert(const QString &s)
+{
+ if (hasSelectedText())
+ addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ if (m_maskData) {
+ QString ms = maskString(m_cursor, s);
+ for (int i = 0; i < (int) ms.length(); ++i) {
+ addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
+ addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
+ }
+ m_text.replace(m_cursor, ms.length(), ms);
+ m_cursor += ms.length();
+ m_cursor = nextMaskBlank(m_cursor);
+ m_textDirty = true;
+ } else {
+ int remaining = m_maxLength - m_text.length();
+ if (remaining != 0) {
+ m_text.insert(m_cursor, s.left(remaining));
+ for (int i = 0; i < (int) s.left(remaining).length(); ++i)
+ addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
+ m_textDirty = true;
+ }
+ }
+}
+
+/*!
+ \internal
+
+ deletes a single character from the current text. If \a wasBackspace,
+ the character prior to the cursor is removed. Otherwise the character
+ after the cursor is removed.
+
+ Also adds the appropriate commands into the undo history.
+ This function does not call finishChange(), and may leave the text
+ in an invalid state.
+*/
+void QLineControl::internalDelete(bool wasBackspace)
+{
+ if (m_cursor < (int) m_text.length()) {
+ if (hasSelectedText())
+ addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
+ m_cursor, m_text.at(m_cursor), -1, -1));
+ if (m_maskData) {
+ m_text.replace(m_cursor, 1, clearString(m_cursor, 1));
+ addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1));
+ } else {
+ m_text.remove(m_cursor, 1);
+ }
+ m_textDirty = true;
+ }
+}
+
+/*!
+ \internal
+
+ removes the currently selected text from the line control.
+
+ Also adds the appropriate commands into the undo history.
+ This function does not call finishChange(), and may leave the text
+ in an invalid state.
+*/
+void QLineControl::removeSelectedText()
+{
+ if (m_selstart < m_selend && m_selend <= (int) m_text.length()) {
+ separate();
+ int i ;
+ addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ if (m_selstart <= m_cursor && m_cursor < m_selend) {
+ // cursor is within the selection. Split up the commands
+ // to be able to restore the correct cursor position
+ for (i = m_cursor; i >= m_selstart; --i)
+ addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1));
+ for (i = m_selend - 1; i > m_cursor; --i)
+ addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1));
+ } else {
+ for (i = m_selend-1; i >= m_selstart; --i)
+ addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
+ }
+ if (m_maskData) {
+ m_text.replace(m_selstart, m_selend - m_selstart, clearString(m_selstart, m_selend - m_selstart));
+ for (int i = 0; i < m_selend - m_selstart; ++i)
+ addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1));
+ } else {
+ m_text.remove(m_selstart, m_selend - m_selstart);
+ }
+ if (m_cursor > m_selstart)
+ m_cursor -= qMin(m_cursor, m_selend) - m_selstart;
+ internalDeselect();
+ m_textDirty = true;
+ }
+}
+
+/*!
+ \internal
+
+ Parses the input mask specified by \a maskFields to generate
+ the mask data used to handle input masks.
+*/
+void QLineControl::parseInputMask(const QString &maskFields)
+{
+ int delimiter = maskFields.indexOf(QLatin1Char(';'));
+ if (maskFields.isEmpty() || delimiter == 0) {
+ if (m_maskData) {
+ delete [] m_maskData;
+ m_maskData = 0;
+ m_maxLength = 32767;
+ internalSetText(QString());
+ }
+ return;
+ }
+
+ if (delimiter == -1) {
+ m_blank = QLatin1Char(' ');
+ m_inputMask = maskFields;
+ } else {
+ m_inputMask = maskFields.left(delimiter);
+ m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
+ }
+
+ // calculate m_maxLength / m_maskData length
+ m_maxLength = 0;
+ QChar c = 0;
+ for (int i=0; i<m_inputMask.length(); i++) {
+ c = m_inputMask.at(i);
+ if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) {
+ m_maxLength++;
+ continue;
+ }
+ if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
+ c != QLatin1Char('<') && c != QLatin1Char('>') &&
+ c != QLatin1Char('{') && c != QLatin1Char('}') &&
+ c != QLatin1Char('[') && c != QLatin1Char(']'))
+ m_maxLength++;
+ }
+
+ delete [] m_maskData;
+ m_maskData = new MaskInputData[m_maxLength];
+
+ MaskInputData::Casemode m = MaskInputData::NoCaseMode;
+ c = 0;
+ bool s;
+ bool escape = false;
+ int index = 0;
+ for (int i = 0; i < m_inputMask.length(); i++) {
+ c = m_inputMask.at(i);
+ if (escape) {
+ s = true;
+ m_maskData[index].maskChar = c;
+ m_maskData[index].separator = s;
+ m_maskData[index].caseMode = m;
+ index++;
+ escape = false;
+ } else if (c == QLatin1Char('<')) {
+ m = MaskInputData::Lower;
+ } else if (c == QLatin1Char('>')) {
+ m = MaskInputData::Upper;
+ } else if (c == QLatin1Char('!')) {
+ m = MaskInputData::NoCaseMode;
+ } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
+ switch (c.unicode()) {
+ case 'A':
+ case 'a':
+ case 'N':
+ case 'n':
+ case 'X':
+ case 'x':
+ case '9':
+ case '0':
+ case 'D':
+ case 'd':
+ case '#':
+ case 'H':
+ case 'h':
+ case 'B':
+ case 'b':
+ s = false;
+ break;
+ case '\\':
+ escape = true;
+ default:
+ s = true;
+ break;
+ }
+
+ if (!escape) {
+ m_maskData[index].maskChar = c;
+ m_maskData[index].separator = s;
+ m_maskData[index].caseMode = m;
+ index++;
+ }
+ }
+ }
+ internalSetText(m_text);
+}
+
+
+/*!
+ \internal
+
+ checks if the key is valid compared to the inputMask
+*/
+bool QLineControl::isValidInput(QChar key, QChar mask) const
+{
+ switch (mask.unicode()) {
+ case 'A':
+ if (key.isLetter())
+ return true;
+ break;
+ case 'a':
+ if (key.isLetter() || key == m_blank)
+ return true;
+ break;
+ case 'N':
+ if (key.isLetterOrNumber())
+ return true;
+ break;
+ case 'n':
+ if (key.isLetterOrNumber() || key == m_blank)
+ return true;
+ break;
+ case 'X':
+ if (key.isPrint())
+ return true;
+ break;
+ case 'x':
+ if (key.isPrint() || key == m_blank)
+ return true;
+ break;
+ case '9':
+ if (key.isNumber())
+ return true;
+ break;
+ case '0':
+ if (key.isNumber() || key == m_blank)
+ return true;
+ break;
+ case 'D':
+ if (key.isNumber() && key.digitValue() > 0)
+ return true;
+ break;
+ case 'd':
+ if ((key.isNumber() && key.digitValue() > 0) || key == m_blank)
+ return true;
+ break;
+ case '#':
+ if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank)
+ return true;
+ break;
+ case 'B':
+ if (key == QLatin1Char('0') || key == QLatin1Char('1'))
+ return true;
+ break;
+ case 'b':
+ if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank)
+ return true;
+ break;
+ case 'H':
+ if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
+ return true;
+ break;
+ case 'h':
+ if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank)
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+/*!
+ \internal
+
+ Returns true if the given text \a str is valid for any
+ validator or input mask set for the line control.
+
+ Otherwise returns false
+*/
+bool QLineControl::hasAcceptableInput(const QString &str) const
+{
+#ifndef QT_NO_VALIDATOR
+ QString textCopy = str;
+ int cursorCopy = m_cursor;
+ if (m_validator && m_validator->validate(textCopy, cursorCopy)
+ != QValidator::Acceptable)
+ return false;
+#endif
+
+ if (!m_maskData)
+ return true;
+
+ if (str.length() != m_maxLength)
+ return false;
+
+ for (int i=0; i < m_maxLength; ++i) {
+ if (m_maskData[i].separator) {
+ if (str.at(i) != m_maskData[i].maskChar)
+ return false;
+ } else {
+ if (!isValidInput(str.at(i), m_maskData[i].maskChar))
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ \internal
+
+ Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
+ specifies from where characters should be gotten when a separator is met in \a str - true means
+ that blanks will be used, false that previous input is used.
+ Calling this when no inputMask is set is undefined.
+*/
+QString QLineControl::maskString(uint pos, const QString &str, bool clear) const
+{
+ if (pos >= (uint)m_maxLength)
+ return QString::fromLatin1("");
+
+ QString fill;
+ fill = clear ? clearString(0, m_maxLength) : m_text;
+
+ int strIndex = 0;
+ QString s = QString::fromLatin1("");
+ int i = pos;
+ while (i < m_maxLength) {
+ if (strIndex < str.length()) {
+ if (m_maskData[i].separator) {
+ s += m_maskData[i].maskChar;
+ if (str[(int)strIndex] == m_maskData[i].maskChar)
+ strIndex++;
+ ++i;
+ } else {
+ if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) {
+ switch (m_maskData[i].caseMode) {
+ case MaskInputData::Upper:
+ s += str[(int)strIndex].toUpper();
+ break;
+ case MaskInputData::Lower:
+ s += str[(int)strIndex].toLower();
+ break;
+ default:
+ s += str[(int)strIndex];
+ }
+ ++i;
+ } else {
+ // search for separator first
+ int n = findInMask(i, true, true, str[(int)strIndex]);
+ if (n != -1) {
+ if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
+ s += fill.mid(i, n-i+1);
+ i = n + 1; // update i to find + 1
+ }
+ } else {
+ // search for valid m_blank if not
+ n = findInMask(i, true, false, str[(int)strIndex]);
+ if (n != -1) {
+ s += fill.mid(i, n-i);
+ switch (m_maskData[n].caseMode) {
+ case MaskInputData::Upper:
+ s += str[(int)strIndex].toUpper();
+ break;
+ case MaskInputData::Lower:
+ s += str[(int)strIndex].toLower();
+ break;
+ default:
+ s += str[(int)strIndex];
+ }
+ i = n + 1; // updates i to find + 1
+ }
+ }
+ }
+ ++strIndex;
+ }
+ } else
+ break;
+ }
+
+ return s;
+}
+
+
+
+/*!
+ \internal
+
+ Returns a "cleared" string with only separators and blank chars.
+ Calling this when no inputMask is set is undefined.
+*/
+QString QLineControl::clearString(uint pos, uint len) const
+{
+ if (pos >= (uint)m_maxLength)
+ return QString();
+
+ QString s;
+ int end = qMin((uint)m_maxLength, pos + len);
+ for (int i = pos; i < end; ++i)
+ if (m_maskData[i].separator)
+ s += m_maskData[i].maskChar;
+ else
+ s += m_blank;
+
+ return s;
+}
+
+/*!
+ \internal
+
+ Strips blank parts of the input in a QLineControl when an inputMask is set,
+ separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
+*/
+QString QLineControl::stripString(const QString &str) const
+{
+ if (!m_maskData)
+ return str;
+
+ QString s;
+ int end = qMin(m_maxLength, (int)str.length());
+ for (int i = 0; i < end; ++i)
+ if (m_maskData[i].separator)
+ s += m_maskData[i].maskChar;
+ else
+ if (str[i] != m_blank)
+ s += str[i];
+
+ return s;
+}
+
+/*!
+ \internal
+ searches forward/backward in m_maskData for either a separator or a m_blank
+*/
+int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
+{
+ if (pos >= m_maxLength || pos < 0)
+ return -1;
+
+ int end = forward ? m_maxLength : -1;
+ int step = forward ? 1 : -1;
+ int i = pos;
+
+ while (i != end) {
+ if (findSeparator) {
+ if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar)
+ return i;
+ } else {
+ if (!m_maskData[i].separator) {
+ if (searchChar.isNull())
+ return i;
+ else if (isValidInput(searchChar, m_maskData[i].maskChar))
+ return i;
+ }
+ }
+ i += step;
+ }
+ return -1;
+}
+
+void QLineControl::internalUndo(int until)
+{
+ if (!isUndoAvailable())
+ return;
+ internalDeselect();
+ while (m_undoState && m_undoState > until) {
+ Command& cmd = m_history[--m_undoState];
+ switch (cmd.type) {
+ case Insert:
+ m_text.remove(cmd.pos, 1);
+ m_cursor = cmd.pos;
+ break;
+ case SetSelection:
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ case Remove:
+ case RemoveSelection:
+ m_text.insert(cmd.pos, cmd.uc);
+ m_cursor = cmd.pos + 1;
+ break;
+ case Delete:
+ case DeleteSelection:
+ m_text.insert(cmd.pos, cmd.uc);
+ m_cursor = cmd.pos;
+ break;
+ case Separator:
+ continue;
+ }
+ if (until < 0 && m_undoState) {
+ Command& next = m_history[m_undoState-1];
+ if (next.type != cmd.type && next.type < RemoveSelection
+ && (cmd.type < RemoveSelection || next.type == Separator))
+ break;
+ }
+ }
+ m_textDirty = true;
+ emitCursorPositionChanged();
+}
+
+void QLineControl::internalRedo()
+{
+ if (!isRedoAvailable())
+ return;
+ internalDeselect();
+ while (m_undoState < (int)m_history.size()) {
+ Command& cmd = m_history[m_undoState++];
+ switch (cmd.type) {
+ case Insert:
+ m_text.insert(cmd.pos, cmd.uc);
+ m_cursor = cmd.pos + 1;
+ break;
+ case SetSelection:
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ case Remove:
+ case Delete:
+ case RemoveSelection:
+ case DeleteSelection:
+ m_text.remove(cmd.pos, 1);
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ case Separator:
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ }
+ if (m_undoState < (int)m_history.size()) {
+ Command& next = m_history[m_undoState];
+ if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
+ && (next.type < RemoveSelection || cmd.type == Separator))
+ break;
+ }
+ }
+ m_textDirty = true;
+ emitCursorPositionChanged();
+}
+
+/*!
+ \internal
+
+ If the current cursor position differs from the last emited cursor
+ position, emits cursorPositionChanged().
+*/
+void QLineControl::emitCursorPositionChanged()
+{
+ if (m_cursor != m_lastCursorPos) {
+ const int oldLast = m_lastCursorPos;
+ m_lastCursorPos = m_cursor;
+ cursorPositionChanged(oldLast, m_cursor);
+ }
+}
+
+#ifndef QT_NO_COMPLETER
+// iterating forward(dir=1)/backward(dir=-1) from the
+// current row based. dir=0 indicates a new completion prefix was set.
+bool QLineControl::advanceToEnabledItem(int dir)
+{
+ int start = m_completer->currentRow();
+ if (start == -1)
+ return false;
+ int i = start + dir;
+ if (dir == 0) dir = 1;
+ do {
+ if (!m_completer->setCurrentRow(i)) {
+ if (!m_completer->wrapAround())
+ break;
+ i = i > 0 ? 0 : m_completer->completionCount() - 1;
+ } else {
+ QModelIndex currentIndex = m_completer->currentIndex();
+ if (m_completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
+ return true;
+ i += dir;
+ }
+ } while (i != start);
+
+ m_completer->setCurrentRow(start); // restore
+ return false;
+}
+
+void QLineControl::complete(int key)
+{
+ if (!m_completer || isReadOnly() || echoMode() != QLineEdit::Normal)
+ return;
+
+ QString text = this->text();
+ if (m_completer->completionMode() == QCompleter::InlineCompletion) {
+ if (key == Qt::Key_Backspace)
+ return;
+ int n = 0;
+ if (key == Qt::Key_Up || key == Qt::Key_Down) {
+ if (textAfterSelection().length())
+ return;
+ QString prefix = hasSelectedText() ? textBeforeSelection()
+ : text;
+ if (text.compare(m_completer->currentCompletion(), m_completer->caseSensitivity()) != 0
+ || prefix.compare(m_completer->completionPrefix(), m_completer->caseSensitivity()) != 0) {
+ m_completer->setCompletionPrefix(prefix);
+ } else {
+ n = (key == Qt::Key_Up) ? -1 : +1;
+ }
+ } else {
+ m_completer->setCompletionPrefix(text);
+ }
+ if (!advanceToEnabledItem(n))
+ return;
+ } else {
+#ifndef QT_KEYPAD_NAVIGATION
+ if (text.isEmpty()) {
+ m_completer->popup()->hide();
+ return;
+ }
+#endif
+ m_completer->setCompletionPrefix(text);
+ }
+
+ m_completer->complete();
+}
+#endif
+
+void QLineControl::setCursorBlinkPeriod(int msec)
+{
+ if (msec == m_blinkPeriod)
+ return;
+ if (m_blinkTimer) {
+ killTimer(m_blinkTimer);
+ }
+ if (msec) {
+ m_blinkTimer = startTimer(msec / 2);
+ m_blinkStatus = 1;
+ } else {
+ m_blinkTimer = 0;
+ if (m_blinkStatus == 0)
+ emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
+ }
+ m_blinkPeriod = msec;
+}
+
+void QLineControl::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_blinkTimer) {
+ m_blinkStatus = !m_blinkStatus;
+ emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
+ } else if (event->timerId() == m_deleteAllTimer) {
+ killTimer(m_deleteAllTimer);
+ m_deleteAllTimer = 0;
+ clear();
+ } else if (event->timerId() == m_tripleClickTimer) {
+ killTimer(m_tripleClickTimer);
+ m_tripleClickTimer = 0;
+ }
+}
+
+bool QLineControl::processEvent(QEvent* ev)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled()) {
+ if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) {
+ QKeyEvent *ke = (QKeyEvent *)ev;
+ if (ke->key() == Qt::Key_Back) {
+ if (ke->isAutoRepeat()) {
+ // Swallow it. We don't want back keys running amok.
+ ke->accept();
+ return true;
+ }
+ if ((ev->type() == QEvent::KeyRelease)
+ && !isReadOnly()
+ && deleteAllTimer) {
+ killTimer(m_deleteAllTimer);
+ m_deleteAllTimer = 0;
+ backspace();
+ ke->accept();
+ return true;
+ }
+ }
+ }
+ }
+#endif
+ switch(ev->type()){
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMousePress:{
+ QGraphicsSceneMouseEvent *gvEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
+ QMouseEvent* mouse = new QMouseEvent(ev->type(),
+ gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers());
+ processMouseEvent(mouse); break;
+ }
+#endif
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ processMouseEvent(static_cast<QMouseEvent*>(ev)); break;
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ processKeyEvent(static_cast<QKeyEvent*>(ev)); break;
+ case QEvent::InputMethod:
+ processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break;
+#ifndef QT_NO_SHORTCUT
+ case QEvent::ShortcutOverride:{
+ QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
+ if (ke == QKeySequence::Copy
+ || ke == QKeySequence::Paste
+ || ke == QKeySequence::Cut
+ || ke == QKeySequence::Redo
+ || ke == QKeySequence::Undo
+ || ke == QKeySequence::MoveToNextWord
+ || ke == QKeySequence::MoveToPreviousWord
+ || ke == QKeySequence::MoveToStartOfDocument
+ || ke == QKeySequence::MoveToEndOfDocument
+ || ke == QKeySequence::SelectNextWord
+ || ke == QKeySequence::SelectPreviousWord
+ || ke == QKeySequence::SelectStartOfLine
+ || ke == QKeySequence::SelectEndOfLine
+ || ke == QKeySequence::SelectStartOfBlock
+ || ke == QKeySequence::SelectEndOfBlock
+ || ke == QKeySequence::SelectStartOfDocument
+ || ke == QKeySequence::SelectAll
+ || ke == QKeySequence::SelectEndOfDocument) {
+ ke->accept();
+ } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
+ || ke->modifiers() == Qt::KeypadModifier) {
+ if (ke->key() < Qt::Key_Escape) {
+ ke->accept();
+ } else {
+ switch (ke->key()) {
+ case Qt::Key_Delete:
+ case Qt::Key_Home:
+ case Qt::Key_End:
+ case Qt::Key_Backspace:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ ke->accept();
+ default:
+ break;
+ }
+ }
+ }
+ }
+#endif
+ default:
+ return false;
+ }
+ return true;
+}
+
+void QLineControl::processMouseEvent(QMouseEvent* ev)
+{
+
+ switch (ev->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::MouseButtonPress:{
+ if (m_tripleClickTimer
+ && (ev->pos() - m_tripleClick).manhattanLength()
+ < QApplication::startDragDistance()) {
+ selectAll();
+ return;
+ }
+ if (ev->button() == Qt::RightButton)
+ return;
+
+ bool mark = ev->modifiers() & Qt::ShiftModifier;
+ int cursor = xToPos(ev->pos().x());
+ moveCursor(cursor, mark);
+ break;
+ }
+ case QEvent::MouseButtonDblClick:
+ if (ev->button() == Qt::LeftButton) {
+ selectWordAtPos(xToPos(ev->pos().x()));
+ if (m_tripleClickTimer)
+ killTimer(m_tripleClickTimer);
+ m_tripleClickTimer = startTimer(QApplication::doubleClickInterval());
+ m_tripleClick = ev->pos();
+ }
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::MouseButtonRelease:
+#ifndef QT_NO_CLIPBOARD
+ if (QApplication::clipboard()->supportsSelection()) {
+ if (ev->button() == Qt::LeftButton) {
+ copy(QClipboard::Selection);
+ } else if (!isReadOnly() && ev->button() == Qt::MidButton) {
+ deselect();
+ insert(QApplication::clipboard()->text(QClipboard::Selection));
+ }
+ }
+#endif
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::MouseMove:
+ if (ev->buttons() & Qt::LeftButton) {
+ moveCursor(xToPos(ev->pos().x()), true);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void QLineControl::processKeyEvent(QKeyEvent* event)
+{
+ bool inlineCompletionAccepted = false;
+
+#ifndef QT_NO_COMPLETER
+ if (m_completer) {
+ QCompleter::CompletionMode completionMode = m_completer->completionMode();
+ if ((completionMode == QCompleter::PopupCompletion
+ || completionMode == QCompleter::UnfilteredPopupCompletion)
+ && m_completer->popup()
+ && m_completer->popup()->isVisible()) {
+ // The following keys are forwarded by the completer to the widget
+ // Ignoring the events lets the completer provide suitable default behavior
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ event->ignore();
+ return;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_F4:
+#ifdef QT_KEYPAD_NAVIGATION
+ case Qt::Key_Select:
+ if (!QApplication::keypadNavigationEnabled())
+ break;
+#endif
+ m_completer->popup()->hide(); // just hide. will end up propagating to parent
+ default:
+ break; // normal key processing
+ }
+ } else if (completionMode == QCompleter::InlineCompletion) {
+ switch (event->key()) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_F4:
+#ifdef QT_KEYPAD_NAVIGATION
+ case Qt::Key_Select:
+ if (!QApplication::keypadNavigationEnabled())
+ break;
+#endif
+ if (!m_completer->currentCompletion().isEmpty() && hasSelectedText()
+ && textAfterSelection().isEmpty()) {
+ setText(m_completer->currentCompletion());
+ inlineCompletionAccepted = true;
+ }
+ default:
+ break; // normal key processing
+ }
+ }
+ }
+#endif // QT_NO_COMPLETER
+
+ if (echoMode() == QLineEdit::PasswordEchoOnEdit
+ && !passwordEchoEditing()
+ && !isReadOnly()
+ && !event->text().isEmpty()
+#ifdef QT_KEYPAD_NAVIGATION
+ && event->key() != Qt::Key_Select
+ && event->key() != Qt::Key_Up
+ && event->key() != Qt::Key_Down
+ && event->key() != Qt::Key_Back
+#endif
+ && !(event->modifiers() & Qt::ControlModifier)) {
+ // Clear the edit and reset to normal echo mode while editing; the
+ // echo mode switches back when the edit loses focus
+ // ### resets current content. dubious code; you can
+ // navigate with keys up, down, back, and select(?), but if you press
+ // "left" or "right" it clears?
+ updatePasswordEchoEditing(true);
+ clear();
+ }
+
+ if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
+ if (hasAcceptableInput() || fixup()) {
+ emit accepted();
+ emit editingFinished();
+ }
+ if (inlineCompletionAccepted)
+ event->accept();
+ else
+ event->ignore();
+ return;
+ }
+ bool unknown = false;
+
+ if (false) {
+ }
+#ifndef QT_NO_SHORTCUT
+ else if (event == QKeySequence::Undo) {
+ if (!isReadOnly())
+ undo();
+ }
+ else if (event == QKeySequence::Redo) {
+ if (!isReadOnly())
+ redo();
+ }
+ else if (event == QKeySequence::SelectAll) {
+ selectAll();
+ }
+#ifndef QT_NO_CLIPBOARD
+ else if (event == QKeySequence::Copy) {
+ copy();
+ }
+ else if (event == QKeySequence::Paste) {
+ if (!isReadOnly())
+ paste();
+ }
+ else if (event == QKeySequence::Cut) {
+ if (!isReadOnly()) {
+ copy();
+ del();
+ }
+ }
+ else if (event == QKeySequence::DeleteEndOfLine) {
+ if (!isReadOnly()) {
+ setSelection(cursor(), end());
+ copy();
+ del();
+ }
+ }
+#endif //QT_NO_CLIPBOARD
+ else if (event == QKeySequence::MoveToStartOfLine) {
+ home(0);
+ }
+ else if (event == QKeySequence::MoveToEndOfLine) {
+ end(0);
+ }
+ else if (event == QKeySequence::SelectStartOfLine) {
+ home(1);
+ }
+ else if (event == QKeySequence::SelectEndOfLine) {
+ end(1);
+ }
+ else if (event == QKeySequence::MoveToNextChar) {
+#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
+ if (hasSelectedText()) {
+#else
+ if (hasSelectedText() && m_completer
+ && m_completer->completionMode() == QCompleter::InlineCompletion) {
+#endif
+ moveCursor(selectionEnd(), false);
+ } else {
+ cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
+ }
+ }
+ else if (event == QKeySequence::SelectNextChar) {
+ cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
+ }
+ else if (event == QKeySequence::MoveToPreviousChar) {
+#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
+ if (hasSelectedText()) {
+#else
+ if (hasSelectedText() && m_completer
+ && m_completer->completionMode() == QCompleter::InlineCompletion) {
+#endif
+ moveCursor(selectionStart(), false);
+ } else {
+ cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1);
+ }
+ }
+ else if (event == QKeySequence::SelectPreviousChar) {
+ cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1);
+ }
+ else if (event == QKeySequence::MoveToNextWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
+ else
+ layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
+ }
+ else if (event == QKeySequence::MoveToPreviousWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
+ else if (!isReadOnly()) {
+ layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
+ }
+ }
+ else if (event == QKeySequence::SelectNextWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
+ else
+ layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
+ }
+ else if (event == QKeySequence::SelectPreviousWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
+ else
+ layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
+ }
+ else if (event == QKeySequence::Delete) {
+ if (!isReadOnly())
+ del();
+ }
+ else if (event == QKeySequence::DeleteEndOfWord) {
+ if (!isReadOnly()) {
+ cursorWordForward(true);
+ del();
+ }
+ }
+ else if (event == QKeySequence::DeleteStartOfWord) {
+ if (!isReadOnly()) {
+ cursorWordBackward(true);
+ del();
+ }
+ }
+#endif // QT_NO_SHORTCUT
+ else {
+#ifdef Q_WS_MAC
+ if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
+ Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
+ if (myModifiers & Qt::ShiftModifier) {
+ if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
+ || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
+ || myModifiers == Qt::ShiftModifier) {
+
+ event->key() == Qt::Key_Up ? home(1) : end(1);
+ }
+ } else {
+ if ((myModifiers == Qt::ControlModifier
+ || myModifiers == Qt::AltModifier
+ || myModifiers == Qt::NoModifier)) {
+ event->key() == Qt::Key_Up ? home(0) : end(0);
+ }
+ }
+ }
+#endif
+ if (event->modifiers() & Qt::ControlModifier) {
+ switch (event->key()) {
+ case Qt::Key_Backspace:
+ if (!isReadOnly()) {
+ cursorWordBackward(true);
+ del();
+ }
+ break;
+#ifndef QT_NO_COMPLETER
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ complete(event->key());
+ break;
+#endif
+#if defined(Q_WS_X11)
+ case Qt::Key_E:
+ end(0);
+ break;
+
+ case Qt::Key_U:
+ if (!isReadOnly()) {
+ setSelection(0, text().size());
+#ifndef QT_NO_CLIPBOARD
+ copy();
+#endif
+ del();
+ }
+ break;
+#endif
+ default:
+ unknown = true;
+ }
+ } else { // ### check for *no* modifier
+ switch (event->key()) {
+ case Qt::Key_Backspace:
+ if (!isReadOnly()) {
+ backspace();
+#ifndef QT_NO_COMPLETER
+ complete(Qt::Key_Backspace);
+#endif
+ }
+ break;
+#ifdef QT_KEYPAD_NAVIGATION
+ case Qt::Key_Back:
+ if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
+ && !isReadOnly()) {
+ if (text().length() == 0) {
+ setText(m_cancelText);
+
+ if (passwordEchoEditing)
+ updatePasswordEchoEditing(false);
+
+ setEditFocus(false);
+ } else if (!deleteAllTimer) {
+ deleteAllTimer = startTimer(750);
+ }
+ } else {
+ unknown = true;
+ }
+ break;
+#endif
+
+ default:
+ unknown = true;
+ }
+ }
+ }
+
+ if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
+ setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
+ unknown = false;
+ }
+
+ if (unknown && !isReadOnly()) {
+ QString t = event->text();
+ if (!t.isEmpty() && t.at(0).isPrint()) {
+ insert(t);
+#ifndef QT_NO_COMPLETER
+ complete(event->key());
+#endif
+ event->accept();
+ return;
+ }
+ }
+
+ if (unknown)
+ event->ignore();
+ else
+ event->accept();
+}
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
new file mode 100644
index 0000000..9cad857
--- /dev/null
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -0,0 +1,741 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINECONTROL_P_H
+#define QLINECONTROL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qglobal.h"
+
+#ifndef QT_NO_LINEEDIT
+#include "private/qwidget_p.h"
+#include "QtGui/qlineedit.h"
+#include "QtGui/qtextlayout.h"
+#include "QtGui/qstyleoption.h"
+#include "QtCore/qpointer.h"
+#include "QtGui/qlineedit.h"
+#include "QtGui/qclipboard.h"
+#include "QtCore/qpoint.h"
+#include "QtGui/qcompleter.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QLineControl : public QObject
+{
+ Q_OBJECT
+
+public:
+ QLineControl(const QString &txt = QString())
+ : m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight),
+ m_hideCursor(false), m_separator(0), m_readOnly(0),
+ m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0),
+ m_validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0),
+ m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1),
+ m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
+ m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
+ {
+ init(txt);
+ }
+
+ ~QLineControl()
+ {
+ delete [] m_maskData;
+ }
+
+ int nextMaskBlank(int pos);
+ int prevMaskBlank(int pos);
+
+ bool isUndoAvailable() const;
+ bool isRedoAvailable() const;
+ void clearUndo();
+ bool isModified() const;
+ void setModified(bool modified);
+
+ bool allSelected() const;
+ bool hasSelectedText() const;
+
+ int width() const;
+ int height() const;
+ int ascent() const;
+
+ void setSelection(int start, int length);
+
+ QString selectedText() const;
+ QString textBeforeSelection() const;
+ QString textAfterSelection() const;
+
+ int selectionStart() const;
+ int selectionEnd() const;
+ bool inSelection(int x) const;
+
+ void removeSelection();
+
+ int start() const;
+ int end() const;
+
+#ifndef QT_NO_CLIPBOARD
+ void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
+ void paste();
+#endif
+
+ int cursor() const;
+ int preeditCursor() const;
+
+ int cursorWidth() const;
+ void setCursorWidth(int value);
+
+ void moveCursor(int pos, bool mark = false);
+ void cursorForward(bool mark, int steps);
+ void cursorWordForward(bool mark);
+ void cursorWordBackward(bool mark);
+ void home(bool mark);
+ void end(bool mark);
+
+ int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
+ QRect cursorRect() const;
+
+ qreal cursorToX(int cursor) const;
+ qreal cursorToX() const;
+
+ bool isReadOnly() const;
+ void setReadOnly(bool enable);
+
+ QString text() const;
+ void setText(const QString &txt);
+
+ QString displayText() const;
+
+ void backspace();
+ void del();
+ void deselect();
+ void selectAll();
+ void insert(const QString &);
+ void clear();
+ void undo();
+ void redo();
+ void selectWordAtPos(int);
+
+ uint echoMode() const;
+ void setEchoMode(uint mode);
+
+ void setMaxLength(int maxLength);
+ int maxLength() const;
+
+ const QValidator *validator() const;
+ void setValidator(const QValidator *);
+
+#ifndef QT_NO_COMPLETER
+ QCompleter *completer() const;
+ void setCompleter(const QCompleter*);
+ void complete(int key);
+#endif
+
+ void setCursorPosition(int pos);
+ int cursorPosition() const;
+
+ bool hasAcceptableInput() const;
+ bool fixup();
+
+ QString inputMask() const;
+ void setInputMask(const QString &mask);
+
+ // input methods
+#ifndef QT_NO_IM
+ bool composeMode() const;
+ void setPreeditArea(int cursor, const QString &text);
+#endif
+
+ QString preeditAreaText() const;
+
+ void updatePasswordEchoEditing(bool editing);
+ bool passwordEchoEditing() const;
+
+ QChar passwordCharacter() const;
+ void setPasswordCharacter(const QChar &character);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection direction);
+ void setFont(const QFont &font);
+
+ void processInputMethodEvent(QInputMethodEvent *event);
+ void processMouseEvent(QMouseEvent* ev);
+ void processKeyEvent(QKeyEvent* ev);
+
+ int cursorBlinkPeriod() const;
+ void setCursorBlinkPeriod(int msec);
+
+ QString cancelText() const;
+ void setCancelText(const QString &text);
+
+ enum DrawFlags {
+ DrawText = 0x01,
+ DrawSelections = 0x02,
+ DrawCursor = 0x04,
+ DrawAll = DrawText | DrawSelections | DrawCursor
+ };
+ void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll);
+
+ bool processEvent(QEvent *ev);
+
+private:
+ void init(const QString &txt);
+ void removeSelectedText();
+ void internalSetText(const QString &txt, int pos = -1, bool edited = true);
+ void updateDisplayText();
+
+ void internalInsert(const QString &s);
+ void internalDelete(bool wasBackspace = false);
+ void internalRemove(int pos);
+
+ inline void internalDeselect()
+ {
+ m_selDirty |= (m_selend > m_selstart);
+ m_selstart = m_selend = 0;
+ }
+
+ void internalUndo(int until = -1);
+ void internalRedo();
+
+ QString m_text;
+ QPalette m_palette;
+ int m_cursor;
+ int m_preeditCursor;
+ int m_cursorWidth;
+ Qt::LayoutDirection m_layoutDirection;
+ uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
+ uint m_separator : 1;
+ uint m_readOnly : 1;
+ uint m_dragEnabled : 1;
+ uint m_echoMode : 2;
+ uint m_textDirty : 1;
+ uint m_selDirty : 1;
+ uint m_validInput : 1;
+ int m_blinkPeriod; // 0 for non-blinking cursor
+ int m_blinkTimer;
+ int m_deleteAllTimer;
+ int m_blinkStatus;
+ int m_ascent;
+ int m_maxLength;
+ int m_lastCursorPos;
+ QList<int> m_transactions;
+ QPoint m_tripleClick;
+ int m_tripleClickTimer;
+ QString m_cancelText;
+
+ void emitCursorPositionChanged();
+
+ bool finishChange(int validateFromState = -1, bool update = false, bool edited = true);
+
+ QPointer<QValidator> m_validator;
+ QPointer<QCompleter> m_completer;
+#ifndef QT_NO_COMPLETER
+ bool advanceToEnabledItem(int dir);
+#endif
+
+ struct MaskInputData {
+ enum Casemode { NoCaseMode, Upper, Lower };
+ QChar maskChar; // either the separator char or the inputmask
+ bool separator;
+ Casemode caseMode;
+ };
+ QString m_inputMask;
+ QChar m_blank;
+ MaskInputData *m_maskData;
+
+ // undo/redo handling
+ enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
+ struct Command {
+ inline Command() {}
+ inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
+ uint type : 4;
+ QChar uc;
+ int pos, selStart, selEnd;
+ };
+ int m_modifiedState;
+ int m_undoState;
+ QVector<Command> m_history;
+ void addCommand(const Command& cmd);
+
+ inline void separate() { m_separator = true; }
+
+ // selection
+ int m_selstart;
+ int m_selend;
+
+ // masking
+ void parseInputMask(const QString &maskFields);
+ bool isValidInput(QChar key, QChar mask) const;
+ bool hasAcceptableInput(const QString &text) const;
+ QString maskString(uint pos, const QString &str, bool clear = false) const;
+ QString clearString(uint pos, uint len) const;
+ QString stripString(const QString &str) const;
+ int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
+
+ // complex text layout
+ QTextLayout m_textLayout;
+
+ bool m_passwordEchoEditing;
+ QChar m_passwordCharacter;
+
+Q_SIGNALS:
+ void cursorPositionChanged(int, int);
+ void selectionChanged();
+
+ void displayTextChanged(const QString &);
+ void textChanged(const QString &);
+ void textEdited(const QString &);
+
+ void resetInputContext();
+
+ void accepted();
+ void editingFinished();
+ void updateNeeded(const QRect &);
+
+protected:
+ virtual void timerEvent(QTimerEvent *event);
+
+private slots:
+ void _q_clipboardChanged();
+ void _q_deleteSelected();
+
+};
+
+inline int QLineControl::nextMaskBlank(int pos)
+{
+ int c = findInMask(pos, true, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : m_maxLength);
+}
+
+inline int QLineControl::prevMaskBlank(int pos)
+{
+ int c = findInMask(pos, false, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : 0);
+}
+
+inline bool QLineControl::isUndoAvailable() const
+{
+ return !m_readOnly && m_undoState;
+}
+
+inline bool QLineControl::isRedoAvailable() const
+{
+ return !m_readOnly && m_undoState < (int)m_history.size();
+}
+
+inline void QLineControl::clearUndo()
+{
+ m_history.clear();
+ m_modifiedState = m_undoState = 0;
+}
+
+inline bool QLineControl::isModified() const
+{
+ return m_modifiedState != m_undoState;
+}
+
+inline void QLineControl::setModified(bool modified)
+{
+ m_modifiedState = modified ? -1 : m_undoState;
+}
+
+inline bool QLineControl::allSelected() const
+{
+ return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length();
+}
+
+inline bool QLineControl::hasSelectedText() const
+{
+ return !m_text.isEmpty() && m_selend > m_selstart;
+}
+
+inline int QLineControl::width() const
+{
+ return qRound(m_textLayout.lineAt(0).width()) + 1;
+}
+
+inline int QLineControl::height() const
+{
+ return qRound(m_textLayout.lineAt(0).height()) + 1;
+}
+
+inline int QLineControl::ascent() const
+{
+ return m_ascent;
+}
+
+inline QString QLineControl::selectedText() const
+{
+ if (hasSelectedText())
+ return m_text.mid(m_selstart, m_selend - m_selstart);
+ return QString();
+}
+
+inline QString QLineControl::textBeforeSelection() const
+{
+ if (hasSelectedText())
+ return m_text.left(m_selstart);
+ return QString();
+}
+
+inline QString QLineControl::textAfterSelection() const
+{
+ if (hasSelectedText())
+ return m_text.mid(m_selend);
+ return QString();
+}
+
+inline int QLineControl::selectionStart() const
+{
+ return hasSelectedText() ? m_selstart : -1;
+}
+
+inline int QLineControl::selectionEnd() const
+{
+ return hasSelectedText() ? m_selend : -1;
+}
+
+inline int QLineControl::start() const
+{
+ return 0;
+}
+
+inline int QLineControl::end() const
+{
+ return m_text.length();
+}
+
+inline void QLineControl::removeSelection()
+{
+ int priorState = m_undoState;
+ removeSelectedText();
+ finishChange(priorState);
+}
+
+inline bool QLineControl::inSelection(int x) const
+{
+ if (m_selstart >= m_selend)
+ return false;
+ int pos = xToPos(x, QTextLine::CursorOnCharacter);
+ return pos >= m_selstart && pos < m_selend;
+}
+
+inline int QLineControl::cursor() const
+{
+ return m_cursor;
+}
+
+inline int QLineControl::preeditCursor() const
+{
+ return m_preeditCursor;
+}
+
+inline int QLineControl::cursorWidth() const
+{
+ return m_cursorWidth;
+}
+
+inline void QLineControl::setCursorWidth(int value)
+{
+ m_cursorWidth = value;
+}
+
+inline void QLineControl::cursorForward(bool mark, int steps)
+{
+ int c = m_cursor;
+ if (steps > 0) {
+ while (steps--)
+ c = m_textLayout.nextCursorPosition(c);
+ } else if (steps < 0) {
+ while (steps++)
+ c = m_textLayout.previousCursorPosition(c);
+ }
+ moveCursor(c, mark);
+}
+
+inline void QLineControl::cursorWordForward(bool mark)
+{
+ moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark);
+}
+
+inline void QLineControl::home(bool mark)
+{
+ moveCursor(0, mark);
+}
+
+inline void QLineControl::end(bool mark)
+{
+ moveCursor(text().length(), mark);
+}
+
+inline void QLineControl::cursorWordBackward(bool mark)
+{
+ moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark);
+}
+
+inline qreal QLineControl::cursorToX(int cursor) const
+{
+ return m_textLayout.lineAt(0).cursorToX(cursor);
+}
+
+inline qreal QLineControl::cursorToX() const
+{
+ return cursorToX(m_cursor);
+}
+
+inline bool QLineControl::isReadOnly() const
+{
+ return m_readOnly;
+}
+
+inline void QLineControl::setReadOnly(bool enable)
+{
+ m_readOnly = enable;
+}
+
+inline QString QLineControl::text() const
+{
+ QString res = m_maskData ? stripString(m_text) : m_text;
+ return (res.isNull() ? QString::fromLatin1("") : res);
+}
+
+inline void QLineControl::setText(const QString &txt)
+{
+ internalSetText(txt, -1, false);
+}
+
+inline QString QLineControl::displayText() const
+{
+ return m_textLayout.text();
+}
+
+inline void QLineControl::deselect()
+{
+ internalDeselect();
+ finishChange();
+}
+
+inline void QLineControl::selectAll()
+{
+ m_selstart = m_selend = m_cursor = 0;
+ moveCursor(m_text.length(), true);
+}
+
+inline void QLineControl::undo()
+{
+ internalUndo();
+ finishChange(-1, true);
+}
+
+inline void QLineControl::redo()
+{
+ internalRedo();
+ finishChange();
+}
+
+inline uint QLineControl::echoMode() const
+{
+ return m_echoMode;
+}
+
+inline void QLineControl::setEchoMode(uint mode)
+{
+ m_echoMode = mode;
+ m_passwordEchoEditing = false;
+ updateDisplayText();
+}
+
+inline void QLineControl::setMaxLength(int maxLength)
+{
+ if (m_maskData)
+ return;
+ m_maxLength = maxLength;
+ setText(m_text);
+}
+
+inline int QLineControl::maxLength() const
+{
+ return m_maxLength;
+}
+
+inline const QValidator *QLineControl::validator() const
+{
+ return m_validator;
+}
+
+inline void QLineControl::setValidator(const QValidator *v)
+{
+ m_validator = const_cast<QValidator*>(v);
+}
+
+#ifndef QT_NO_COMPLETER
+inline QCompleter *QLineControl::completer() const
+{
+ return m_completer;
+}
+
+/* Note that you must set the widget for the completer seperately */
+inline void QLineControl::setCompleter(const QCompleter* c)
+{
+ m_completer = const_cast<QCompleter*>(c);
+}
+#endif
+
+inline void QLineControl::setCursorPosition(int pos)
+{
+ if (pos < 0)
+ pos = 0;
+ if (pos < m_text.length())
+ moveCursor(pos);
+}
+
+inline int QLineControl::cursorPosition() const
+{
+ return m_cursor;
+}
+
+inline bool QLineControl::hasAcceptableInput() const
+{
+ return hasAcceptableInput(m_text);
+}
+
+inline QString QLineControl::inputMask() const
+{
+ return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString();
+}
+
+inline void QLineControl::setInputMask(const QString &mask)
+{
+ parseInputMask(mask);
+ if (m_maskData)
+ moveCursor(nextMaskBlank(0));
+}
+
+// input methods
+#ifndef QT_NO_IM
+inline bool QLineControl::composeMode() const
+{
+ return !m_textLayout.preeditAreaText().isEmpty();
+}
+
+inline void QLineControl::setPreeditArea(int cursor, const QString &text)
+{
+ m_textLayout.setPreeditArea(cursor, text);
+}
+#endif
+
+inline QString QLineControl::preeditAreaText() const
+{
+ return m_textLayout.preeditAreaText();
+}
+
+inline bool QLineControl::passwordEchoEditing() const
+{
+ return m_passwordEchoEditing;
+}
+
+inline QChar QLineControl::passwordCharacter() const
+{
+ return m_passwordCharacter;
+}
+
+inline void QLineControl::setPasswordCharacter(const QChar &character)
+{
+ m_passwordCharacter = character;
+ updateDisplayText();
+}
+
+inline Qt::LayoutDirection QLineControl::layoutDirection() const
+{
+ return m_layoutDirection;
+}
+
+inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction)
+{
+ if (direction != m_layoutDirection) {
+ m_layoutDirection = direction;
+ updateDisplayText();
+ }
+}
+
+inline void QLineControl::setFont(const QFont &font)
+{
+ m_textLayout.setFont(font);
+ updateDisplayText();
+}
+
+inline int QLineControl::cursorBlinkPeriod() const
+{
+ return m_blinkPeriod;
+}
+
+inline QString QLineControl::cancelText() const
+{
+ return m_cancelText;
+}
+
+inline void QLineControl::setCancelText(const QString &text)
+{
+ m_cancelText = text;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_LINEEDIT
+
+#endif // QLINECONTROL_P_H
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index c7f3e97..e0f5bc9 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -86,21 +86,12 @@
#include <limits.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
-static inline bool shouldEnableInputMethod(QLineEdit *lineedit)
-{
- const QLineEdit::EchoMode mode = lineedit->echoMode();
- return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit);
-}
-
/*!
Initialize \a option with the values from this QLineEdit. This method
is useful for subclasses when they need a QStyleOptionFrame or QStyleOptionFrameV2, but don't want
@@ -122,7 +113,7 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const
: 0;
option->midLineWidth = 0;
option->state |= QStyle::State_Sunken;
- if (d->readOnly)
+ if (d->control->isReadOnly())
option->state |= QStyle::State_ReadOnly;
#ifdef QT_KEYPAD_NAVIGATION
if (hasEditFocus())
@@ -350,14 +341,9 @@ QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget*
{
Q_D(QLineEdit);
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);
- }
+ d->init(contents);
+ d->control->setInputMask(inputMask);
+ d->control->moveCursor(d->control->nextMaskBlank(contents.length()));
}
#endif
@@ -388,19 +374,13 @@ QLineEdit::~QLineEdit()
QString QLineEdit::text() const
{
Q_D(const QLineEdit);
- QString res = d->text;
- if (d->maskData)
- res = d->stripString(d->text);
- return (res.isNull() ? QString::fromLatin1("") : res);
+ return d->control->text();
}
void QLineEdit::setText(const QString& text)
{
Q_D(QLineEdit);
- d->setText(text, -1, false);
-#ifdef QT_KEYPAD_NAVIGATION
- d->origText = d->text;
-#endif
+ d->control->setText(text);
}
@@ -421,17 +401,7 @@ void QLineEdit::setText(const QString& text)
QString QLineEdit::displayText() const
{
Q_D(const QLineEdit);
- if (d->echoMode == NoEcho)
- return QString::fromLatin1("");
- QString res = d->text;
-
- if (d->echoMode == Password || (d->echoMode == PasswordEchoOnEdit
- && !d->passwordEchoEditing)) {
- QStyleOptionFrameV2 opt;
- initStyleOption(&opt);
- res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
- }
- return (res.isNull() ? QString::fromLatin1("") : res);
+ return d->control->displayText();
}
@@ -456,20 +426,15 @@ QString QLineEdit::displayText() const
int QLineEdit::maxLength() const
{
Q_D(const QLineEdit);
- return d->maxLength;
+ return d->control->maxLength();
}
void QLineEdit::setMaxLength(int maxLength)
{
Q_D(QLineEdit);
- if (d->maskData)
- return;
- d->maxLength = maxLength;
- setText(d->text);
+ d->control->setMaxLength(maxLength);
}
-
-
/*!
\property QLineEdit::frame
\brief whether the line edit draws itself with a frame
@@ -536,22 +501,20 @@ void QLineEdit::setFrame(bool enable)
QLineEdit::EchoMode QLineEdit::echoMode() const
{
Q_D(const QLineEdit);
- return (EchoMode) d->echoMode;
+ return (EchoMode) d->control->echoMode();
}
void QLineEdit::setEchoMode(EchoMode mode)
{
Q_D(QLineEdit);
- if (mode == (EchoMode)d->echoMode)
+ if (mode == (EchoMode)d->control->echoMode())
return;
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
- d->echoMode = mode;
- d->passwordEchoEditing = false;
- d->updateTextLayout();
+ setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod());
+ d->control->setEchoMode(mode);
update();
#ifdef Q_WS_MAC
if (hasFocus())
- qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
+ qt_mac_secure_keyboard(mode == Password || mode == NoEcho);
#endif
}
@@ -567,7 +530,7 @@ void QLineEdit::setEchoMode(EchoMode mode)
const QValidator * QLineEdit::validator() const
{
Q_D(const QLineEdit);
- return d->validator;
+ return d->control->validator();
}
/*!
@@ -585,7 +548,7 @@ const QValidator * QLineEdit::validator() const
void QLineEdit::setValidator(const QValidator *v)
{
Q_D(QLineEdit);
- d->validator = const_cast<QValidator*>(v);
+ d->control->setValidator(v);
}
#endif // QT_NO_VALIDATOR
@@ -609,23 +572,23 @@ void QLineEdit::setValidator(const QValidator *v)
void QLineEdit::setCompleter(QCompleter *c)
{
Q_D(QLineEdit);
- if (c == d->completer)
+ if (c == d->control->completer())
return;
- if (d->completer) {
- disconnect(d->completer, 0, this, 0);
- d->completer->setWidget(0);
- if (d->completer->parent() == this)
- delete d->completer;
+ if (d->control->completer()) {
+ disconnect(d->control->completer(), 0, this, 0);
+ d->control->completer()->setWidget(0);
+ if (d->control->completer()->parent() == this)
+ delete d->control->completer();
}
- d->completer = c;
+ d->control->setCompleter(c);
if (!c)
return;
if (c->widget() == 0)
c->setWidget(this);
if (hasFocus()) {
- QObject::connect(d->completer, SIGNAL(activated(QString)),
+ QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
this, SLOT(setText(QString)));
- QObject::connect(d->completer, SIGNAL(highlighted(QString)),
+ QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
this, SLOT(_q_completionHighlighted(QString)));
}
}
@@ -638,83 +601,9 @@ void QLineEdit::setCompleter(QCompleter *c)
QCompleter *QLineEdit::completer() const
{
Q_D(const QLineEdit);
- 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 QLineEditPrivate::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 QLineEditPrivate::complete(int key)
-{
- if (!completer || readOnly || echoMode != QLineEdit::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();
+ return d->control->completer();
}
-void QLineEditPrivate::_q_completionHighlighted(QString newText)
-{
- Q_Q(QLineEdit);
- 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
/*!
@@ -729,10 +618,10 @@ QSize QLineEdit::sizeHint() const
Q_D(const QLineEdit);
ensurePolished();
QFontMetrics fm(font());
- int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin
+ int h = qMax(fm.lineSpacing(), 14) + 2*d->verticalMargin
+ d->topTextMargin + d->bottomTextMargin
+ d->topmargin + d->bottommargin;
- int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin
+ int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin
+ d->leftTextMargin + d->rightTextMargin
+ d->leftmargin + d->rightmargin; // "some"
QStyleOptionFrameV2 opt;
@@ -753,7 +642,7 @@ QSize QLineEdit::minimumSizeHint() const
Q_D(const QLineEdit);
ensurePolished();
QFontMetrics fm = fontMetrics();
- int h = fm.height() + qMax(2*verticalMargin, fm.leading())
+ int h = fm.height() + qMax(2*d->verticalMargin, fm.leading())
+ d->topmargin + d->bottommargin;
int w = fm.maxWidth() + d->leftmargin + d->rightmargin;
QStyleOptionFrameV2 opt;
@@ -775,17 +664,13 @@ QSize QLineEdit::minimumSizeHint() const
int QLineEdit::cursorPosition() const
{
Q_D(const QLineEdit);
- return d->cursor;
+ return d->control->cursorPosition();
}
void QLineEdit::setCursorPosition(int pos)
{
Q_D(QLineEdit);
- if (pos < 0)
- pos = 0;
-
- if (pos <= d->text.length())
- d->moveCursor(pos);
+ d->control->setCursorPosition(pos);
}
/*!
@@ -807,22 +692,17 @@ int QLineEdit::cursorPositionAt(const QPoint &pos)
bool QLineEdit::validateAndSet(const QString &newText, int newPos,
int newMarkAnchor, int newMarkDrag)
{
- Q_D(QLineEdit);
- 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;
+ // The suggested functions above in the docs don't seem to validate,
+ // below code tries to mimic previous behaviour.
+ QString oldText = text();
+ setText(newText);
+ if(!hasAcceptableInput()){
+ setText(oldText);
+ return false;
}
- return false;
+ setCursorPosition(newPos);
+ setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag));
+ return true;
}
#endif //QT3_SUPPORT
@@ -863,15 +743,7 @@ void QLineEdit::setAlignment(Qt::Alignment alignment)
void QLineEdit::cursorForward(bool mark, int steps)
{
Q_D(QLineEdit);
- 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);
+ d->control->cursorForward(mark, steps);
}
@@ -896,7 +768,7 @@ void QLineEdit::cursorBackward(bool mark, int steps)
void QLineEdit::cursorWordForward(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
+ d->control->cursorWordForward(mark);
}
/*!
@@ -909,7 +781,7 @@ void QLineEdit::cursorWordForward(bool mark)
void QLineEdit::cursorWordBackward(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
+ d->control->cursorWordBackward(mark);
}
@@ -924,26 +796,7 @@ void QLineEdit::cursorWordBackward(bool mark)
void QLineEdit::backspace()
{
Q_D(QLineEdit);
- 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);
+ d->control->backspace();
}
/*!
@@ -957,15 +810,7 @@ void QLineEdit::backspace()
void QLineEdit::del()
{
Q_D(QLineEdit);
- 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);
+ d->control->del();
}
/*!
@@ -980,7 +825,7 @@ void QLineEdit::del()
void QLineEdit::home(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(0, mark);
+ d->control->home(mark);
}
/*!
@@ -995,7 +840,7 @@ void QLineEdit::home(bool mark)
void QLineEdit::end(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(d->text.length(), mark);
+ d->control->end(mark);
}
@@ -1020,16 +865,13 @@ void QLineEdit::end(bool mark)
bool QLineEdit::isModified() const
{
Q_D(const QLineEdit);
- return d->modifiedState != d->undoState;
+ return d->control->isModified();
}
void QLineEdit::setModified(bool modified)
{
Q_D(QLineEdit);
- if (modified)
- d->modifiedState = -1;
- else
- d->modifiedState = d->undoState;
+ d->control->setModified(modified);
}
@@ -1057,7 +899,7 @@ Use setModified(false) instead.
bool QLineEdit::hasSelectedText() const
{
Q_D(const QLineEdit);
- return d->hasSelectedText();
+ return d->control->hasSelectedText();
}
/*!
@@ -1075,9 +917,7 @@ bool QLineEdit::hasSelectedText() const
QString QLineEdit::selectedText() const
{
Q_D(const QLineEdit);
- if (d->hasSelectedText())
- return d->text.mid(d->selstart, d->selend - d->selstart);
- return QString();
+ return d->control->selectedText();
}
/*!
@@ -1090,7 +930,7 @@ QString QLineEdit::selectedText() const
int QLineEdit::selectionStart() const
{
Q_D(const QLineEdit);
- return d->hasSelectedText() ? d->selstart : -1;
+ return d->control->selectionStart();
}
@@ -1120,9 +960,10 @@ void QLineEdit::setEdited(bool on) { setModified(on); }
int QLineEdit::characterAt(int xpos, QChar *chr) const
{
Q_D(const QLineEdit);
- int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin);
- if (chr && pos < (int) d->text.length())
- *chr = d->text.at(pos);
+ int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + d->horizontalMargin);
+ QString txt = d->control->text();
+ if (chr && pos < (int) txt.length())
+ *chr = txt.at(pos);
return pos;
}
@@ -1133,9 +974,9 @@ int QLineEdit::characterAt(int xpos, QChar *chr) const
bool QLineEdit::getSelection(int *start, int *end)
{
Q_D(QLineEdit);
- if (d->hasSelectedText() && start && end) {
- *start = d->selstart;
- *end = d->selend;
+ if (d->control->hasSelectedText() && start && end) {
+ *start = selectionStart();
+ *end = *start + selectedText().length();
return true;
}
return false;
@@ -1153,30 +994,19 @@ bool QLineEdit::getSelection(int *start, int *end)
void QLineEdit::setSelection(int start, int length)
{
Q_D(QLineEdit);
- if (start < 0 || start > (int)d->text.length()) {
+ if (start < 0 || start > (int)d->control->text().length()) {
qWarning("QLineEdit::setSelection: Invalid start position (%d)", start);
return;
- } else {
- if (length > 0) {
- d->selstart = start;
- d->selend = qMin(start + length, (int)d->text.length());
- d->cursor = d->selend;
- } else {
- d->selstart = qMax(start + length, 0);
- d->selend = start;
- d->cursor = d->selstart;
- }
}
- if (d->hasSelectedText()){
+ d->control->setSelection(start, length);
+
+ if (d->control->hasSelectedText()){
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
if (!style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(false);
}
-
- update();
- d->emitCursorPositionChanged();
}
@@ -1192,7 +1022,7 @@ void QLineEdit::setSelection(int start, int length)
bool QLineEdit::isUndoAvailable() const
{
Q_D(const QLineEdit);
- return d->isUndoAvailable();
+ return d->control->isUndoAvailable();
}
/*!
@@ -1208,7 +1038,7 @@ bool QLineEdit::isUndoAvailable() const
bool QLineEdit::isRedoAvailable() const
{
Q_D(const QLineEdit);
- return d->isRedoAvailable();
+ return d->control->isRedoAvailable();
}
/*!
@@ -1244,7 +1074,7 @@ void QLineEdit::setDragEnabled(bool b)
bool QLineEdit::hasAcceptableInput() const
{
Q_D(const QLineEdit);
- return d->hasAcceptableInput(d->text);
+ return d->control->hasAcceptableInput();
}
/*!
@@ -1350,15 +1180,13 @@ void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) con
QString QLineEdit::inputMask() const
{
Q_D(const QLineEdit);
- return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString());
+ return d->control->inputMask();
}
void QLineEdit::setInputMask(const QString &inputMask)
{
Q_D(QLineEdit);
- d->parseInputMask(inputMask);
- if (d->maskData)
- d->moveCursor(d->nextMaskBlank(0));
+ d->control->setInputMask(inputMask);
}
/*!
@@ -1373,8 +1201,7 @@ void QLineEdit::setInputMask(const QString &inputMask)
void QLineEdit::selectAll()
{
Q_D(QLineEdit);
- d->selstart = d->selend = d->cursor = 0;
- d->moveCursor(d->text.length(), true);
+ d->control->selectAll();
}
/*!
@@ -1386,8 +1213,7 @@ void QLineEdit::selectAll()
void QLineEdit::deselect()
{
Q_D(QLineEdit);
- d->deselect();
- d->finishChange();
+ d->control->deselect();
}
@@ -1402,10 +1228,7 @@ void QLineEdit::insert(const QString &newText)
{
// q->resetInputContext(); //#### FIX ME IN QT
Q_D(QLineEdit);
- int priorState = d->undoState;
- d->removeSelectedText();
- d->insert(newText);
- d->finishChange(priorState);
+ d->control->insert(newText);
}
/*!
@@ -1416,13 +1239,8 @@ void QLineEdit::insert(const QString &newText)
void QLineEdit::clear()
{
Q_D(QLineEdit);
- int priorState = d->undoState;
resetInputContext();
- d->selstart = 0;
- d->selend = d->text.length();
- d->removeSelectedText();
- d->separate();
- d->finishChange(priorState, /*update*/false, /*edited*/false);
+ d->control->clear();
}
/*!
@@ -1435,8 +1253,7 @@ void QLineEdit::undo()
{
Q_D(QLineEdit);
resetInputContext();
- d->undo();
- d->finishChange(-1, true);
+ d->control->undo();
}
/*!
@@ -1447,8 +1264,7 @@ void QLineEdit::redo()
{
Q_D(QLineEdit);
resetInputContext();
- d->redo();
- d->finishChange();
+ d->control->redo();
}
@@ -1470,16 +1286,16 @@ void QLineEdit::redo()
bool QLineEdit::isReadOnly() const
{
Q_D(const QLineEdit);
- return d->readOnly;
+ return d->control->isReadOnly();
}
void QLineEdit::setReadOnly(bool enable)
{
Q_D(QLineEdit);
- if (d->readOnly != enable) {
- d->readOnly = enable;
- setAttribute(Qt::WA_MacShowFocusRect, !d->readOnly);
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
+ if (d->control->isReadOnly() != enable) {
+ d->control->setReadOnly(enable);
+ setAttribute(Qt::WA_MacShowFocusRect, !enable);
+ setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod());
#ifndef QT_NO_CURSOR
setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
@@ -1518,7 +1334,7 @@ void QLineEdit::cut()
void QLineEdit::copy() const
{
Q_D(const QLineEdit);
- d->copy();
+ d->control->copy();
}
/*!
@@ -1535,23 +1351,7 @@ void QLineEdit::copy() const
void QLineEdit::paste()
{
Q_D(QLineEdit);
- if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) {
- // Clear the edit and reset to normal echo mode when pasting; the echo
- // mode switches back when the edit loses focus. ### changes a public
- // property, resets current content
- d->updatePasswordEchoEditing(true);
- clear();
- }
- insert(QApplication::clipboard()->text(QClipboard::Clipboard));
-}
-
-void QLineEditPrivate::copy(bool clipboard) const
-{
- Q_Q(const QLineEdit);
- QString t = q->selectedText();
- if (!t.isEmpty() && echoMode == QLineEdit::Normal) {
- QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection);
- }
+ d->control->paste();
}
#endif // !QT_NO_CLIPBOARD
@@ -1561,57 +1361,10 @@ void QLineEditPrivate::copy(bool clipboard) const
bool QLineEdit::event(QEvent * e)
{
Q_D(QLineEdit);
-#ifndef QT_NO_SHORTCUT
- if (e->type() == QEvent::ShortcutOverride && !d->readOnly) {
- QKeyEvent* ke = (QKeyEvent*) e;
- if (ke == QKeySequence::Copy
- || ke == QKeySequence::Paste
- || ke == QKeySequence::Cut
- || ke == QKeySequence::Redo
- || ke == QKeySequence::Undo
- || ke == QKeySequence::MoveToNextWord
- || ke == QKeySequence::MoveToPreviousWord
- || ke == QKeySequence::MoveToStartOfDocument
- || ke == QKeySequence::MoveToEndOfDocument
- || ke == QKeySequence::SelectNextWord
- || ke == QKeySequence::SelectPreviousWord
- || ke == QKeySequence::SelectStartOfLine
- || ke == QKeySequence::SelectEndOfLine
- || ke == QKeySequence::SelectStartOfBlock
- || ke == QKeySequence::SelectEndOfBlock
- || ke == QKeySequence::SelectStartOfDocument
- || ke == QKeySequence::SelectAll
- || ke == QKeySequence::SelectEndOfDocument) {
- ke->accept();
- } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
- || ke->modifiers() == Qt::KeypadModifier) {
- if (ke->key() < Qt::Key_Escape) {
- ke->accept();
- } else {
- switch (ke->key()) {
- case Qt::Key_Delete:
- case Qt::Key_Home:
- case Qt::Key_End:
- case Qt::Key_Backspace:
- case Qt::Key_Left:
- case Qt::Key_Right:
- ke->accept();
- default:
- break;
- }
- }
- }
- } else
-#endif
- if (e->type() == QEvent::Timer) {
+ if (e->type() == QEvent::Timer) {
// should be timerEvent, is here for binary compatibility
int timerId = ((QTimerEvent*)e)->timerId();
- if (timerId == d->cursorTimer) {
- QStyleOptionFrameV2 opt;
- initStyleOption(&opt);
- if(!hasSelectedText()
- || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
- d->setCursorVisible(!d->cursorVisible);
+ if (false) {
#ifndef QT_NO_DRAGANDDROP
} else if (timerId == d->dndTimer.timerId()) {
d->drag();
@@ -1619,60 +1372,31 @@ bool QLineEdit::event(QEvent * e)
}
else if (timerId == d->tripleClickTimer.timerId())
d->tripleClickTimer.stop();
-#ifdef QT_KEYPAD_NAVIGATION
- else if (timerId == d->deleteAllTimer.timerId()) {
- d->deleteAllTimer.stop();
- clear();
- }
-#endif
} else if (e->type() == QEvent::ContextMenu) {
#ifndef QT_NO_IM
- if (d->composeMode())
+ if (d->control->composeMode())
return true;
#endif
- d->separate();
+ //d->separate();
} else if (e->type() == QEvent::WindowActivate) {
QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate()));
+ }else if(e->type() == QEvent::ShortcutOverride){
+ d->control->processEvent(e);
}
+
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled()) {
- if ((e->type() == QEvent::KeyPress) || (e->type() == QEvent::KeyRelease)) {
- QKeyEvent *ke = (QKeyEvent *)e;
- if (ke->key() == Qt::Key_Back) {
- if (ke->isAutoRepeat()) {
- // Swallow it. We don't want back keys running amok.
- ke->accept();
- return true;
- }
- if ((e->type() == QEvent::KeyRelease)
- && !isReadOnly()
- && d->deleteAllTimer.isActive()) {
- d->deleteAllTimer.stop();
- backspace();
- ke->accept();
- return true;
- }
- }
- } else if (e->type() == QEvent::EnterEditFocus) {
+ if (e->type() == QEvent::EnterEditFocus) {
end(false);
- if (!d->cursorTimer) {
- int cft = QApplication::cursorFlashTime();
- d->cursorTimer = cft ? startTimer(cft/2) : -1;
- }
+ int cft = QApplication::cursorFlashTime();
+ d->control->setCursorBlinkPeriod(cft/2);
} else if (e->type() == QEvent::LeaveEditFocus) {
d->setCursorVisible(false);
- if (d->cursorTimer > 0)
- killTimer(d->cursorTimer);
- d->cursorTimer = 0;
-
- if (!d->emitingEditingFinished) {
- if (hasAcceptableInput() || d->fixup()) {
- d->emitingEditingFinished = true;
- emit editingFinished();
- d->emitingEditingFinished = false;
- }
- }
+ d->control->setCursorBlinkPeriod(0);
+ if (d->control->hasAcceptableInput() || d->control->fixup())
+ emit editingFinished();
}
+ return true;
}
#endif
return QWidget::event(e);
@@ -1684,15 +1408,15 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
if (e->button() == Qt::RightButton)
return;
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
setEditFocus(true);
// Get the completion list to pop up.
- if (d->completer)
- d->completer->complete();
+ if (d->control->completer())
+ d->control->completer()->complete();
}
#endif
if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
@@ -1703,18 +1427,16 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
bool mark = e->modifiers() & Qt::ShiftModifier;
int cursor = d->xToPos(e->pos().x());
#ifndef QT_NO_DRAGANDDROP
- if (!mark && d->dragEnabled && d->echoMode == Normal &&
- e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) {
- d->cursor = cursor;
- update();
+ if (!mark && d->dragEnabled && d->control->echoMode() == Normal &&
+ e->button() == Qt::LeftButton && d->control->inSelection(e->pos().x())) {
+ d->control->moveCursor(cursor);
d->dndPos = e->pos();
if (!d->dndTimer.isActive())
d->dndTimer.start(QApplication::startDragTime(), this);
- d->emitCursorPositionChanged();
} else
#endif
{
- d->moveCursor(cursor, mark);
+ d->control->moveCursor(cursor, mark);
}
}
@@ -1724,7 +1446,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
if (e->buttons() & Qt::LeftButton) {
#ifndef QT_NO_DRAGANDDROP
@@ -1734,7 +1456,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
} else
#endif
{
- d->moveCursor(d->xToPos(e->pos().x()), true);
+ d->control->moveCursor(d->xToPos(e->pos().x()), true);
}
}
}
@@ -1745,7 +1467,7 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
#ifndef QT_NO_DRAGANDDROP
if (e->button() == Qt::LeftButton) {
if (d->dndTimer.isActive()) {
@@ -1758,9 +1480,9 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
#ifndef QT_NO_CLIPBOARD
if (QApplication::clipboard()->supportsSelection()) {
if (e->button() == Qt::LeftButton) {
- d->copy(false);
- } else if (!d->readOnly && e->button() == Qt::MidButton) {
- d->deselect();
+ d->control->copy(QClipboard::Selection);
+ } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) {
+ deselect();
insert(QApplication::clipboard()->text(QClipboard::Selection));
}
}
@@ -1773,16 +1495,9 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
if (e->button() == Qt::LeftButton) {
- deselect();
- d->cursor = d->xToPos(e->pos().x());
- d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords);
- // ## text layout should support end of words.
- int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords);
- while (end > d->cursor && d->text[end-1].isSpace())
- --end;
- d->moveCursor(end, true);
+ d->control->selectWordAtPos(d->xToPos(e->pos().x()));
d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
d->tripleClick = e->pos();
}
@@ -1822,65 +1537,15 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
void QLineEdit::keyPressEvent(QKeyEvent *event)
{
Q_D(QLineEdit);
-
- bool inlineCompletionAccepted = false;
-
-#ifndef QT_NO_COMPLETER
- if (d->completer) {
- QCompleter::CompletionMode completionMode = d->completer->completionMode();
- if ((completionMode == QCompleter::PopupCompletion
- || completionMode == QCompleter::UnfilteredPopupCompletion)
- &&d->completer->popup()
- && d->completer->popup()->isVisible()) {
- // The following keys are forwarded by the completer to the widget
- // Ignoring the events lets the completer provide suitable default behavior
- switch (event->key()) {
- case Qt::Key_Escape:
- event->ignore();
- return;
- case Qt::Key_Enter:
- case Qt::Key_Return:
- case Qt::Key_F4:
-#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Select:
- if (!QApplication::keypadNavigationEnabled())
- break;
-#endif
- d->completer->popup()->hide(); // just hide. will end up propagating to parent
- default:
- break; // normal key processing
- }
- } else if (completionMode == QCompleter::InlineCompletion) {
- switch (event->key()) {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- case Qt::Key_F4:
-#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Select:
- if (!QApplication::keypadNavigationEnabled())
- break;
-#endif
- if (!d->completer->currentCompletion().isEmpty() && d->selend > d->selstart
- && d->selend == d->text.length()) {
- setText(d->completer->currentCompletion());
- inlineCompletionAccepted = true;
- }
- default:
- break; // normal key processing
- }
- }
- }
-#endif // QT_NO_COMPLETER
-
-#ifdef QT_KEYPAD_NAVIGATION
+ #ifdef QT_KEYPAD_NAVIGATION
bool select = false;
switch (event->key()) {
case Qt::Key_Select:
if (QApplication::keypadNavigationEnabled()) {
if (hasEditFocus()) {
setEditFocus(false);
- if (d->completer && d->completer->popup()->isVisible())
- d->completer->popup()->hide();
+ if (d->control->completer() && d->control->completer()->popup()->isVisible())
+ d->control->completer()->popup()->hide();
select = true;
}
}
@@ -1916,273 +1581,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event)
return; // Just start. No action.
}
#endif
-
- if (echoMode() == PasswordEchoOnEdit
- && !d->passwordEchoEditing
- && !isReadOnly()
- && !event->text().isEmpty()
-#ifdef QT_KEYPAD_NAVIGATION
- && event->key() != Qt::Key_Select
- && event->key() != Qt::Key_Up
- && event->key() != Qt::Key_Down
- && event->key() != Qt::Key_Back
-#endif
- && !(event->modifiers() & Qt::ControlModifier)) {
- // Clear the edit and reset to normal echo mode while editing; the
- // echo mode switches back when the edit loses focus. ### changes a
- // public property, resets current content. dubious code; you can
- // navigate with keys up, down, back, and select(?), but if you press
- // "left" or "right" it clears?
- d->updatePasswordEchoEditing(true);
- clear();
- }
-
- d->setCursorVisible(true);
- if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
- if (hasAcceptableInput() || d->fixup()) {
- emit returnPressed();
- d->emitingEditingFinished = true;
- emit editingFinished();
- d->emitingEditingFinished = false;
- }
- if (inlineCompletionAccepted)
- event->accept();
- else
- event->ignore();
- return;
- }
- bool unknown = false;
-
- if (false) {
- }
-#ifndef QT_NO_SHORTCUT
- else if (event == QKeySequence::Undo) {
- if (!d->readOnly)
- undo();
- }
- else if (event == QKeySequence::Redo) {
- if (!d->readOnly)
- redo();
- }
- else if (event == QKeySequence::SelectAll) {
- selectAll();
- }
-#ifndef QT_NO_CLIPBOARD
- else if (event == QKeySequence::Copy) {
- copy();
- }
- else if (event == QKeySequence::Paste) {
- if (!d->readOnly)
- paste();
- }
- else if (event == QKeySequence::Cut) {
- if (!d->readOnly) {
- cut();
- }
- }
- else if (event == QKeySequence::DeleteEndOfLine) {
- if (!d->readOnly) {
- setSelection(d->cursor, d->text.size());
- copy();
- del();
- }
- }
-#endif //QT_NO_CLIPBOARD
- else if (event == QKeySequence::MoveToStartOfLine) {
- home(0);
- }
- else if (event == QKeySequence::MoveToEndOfLine) {
- end(0);
- }
- else if (event == QKeySequence::SelectStartOfLine) {
- home(1);
- }
- else if (event == QKeySequence::SelectEndOfLine) {
- end(1);
- }
- else if (event == QKeySequence::MoveToNextChar) {
-#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
- if (d->hasSelectedText()) {
-#else
- if (d->hasSelectedText() && d->completer
- && d->completer->completionMode() == QCompleter::InlineCompletion) {
-#endif
- d->moveCursor(d->selend, false);
- } else {
- cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- }
- else if (event == QKeySequence::SelectNextChar) {
- cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- else if (event == QKeySequence::MoveToPreviousChar) {
-#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
- if (d->hasSelectedText()) {
-#else
- if (d->hasSelectedText() && d->completer
- && d->completer->completionMode() == QCompleter::InlineCompletion) {
-#endif
- d->moveCursor(d->selstart, false);
- } else {
- cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- }
- else if (event == QKeySequence::SelectPreviousChar) {
- cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- else if (event == QKeySequence::MoveToNextWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
- else
- layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
- }
- else if (event == QKeySequence::MoveToPreviousWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
- else if (!d->readOnly) {
- layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
- }
- }
- else if (event == QKeySequence::SelectNextWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
- else
- layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
- }
- else if (event == QKeySequence::SelectPreviousWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
- else
- layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
- }
- else if (event == QKeySequence::Delete) {
- if (!d->readOnly)
- del();
- }
- else if (event == QKeySequence::DeleteEndOfWord) {
- if (!d->readOnly) {
- cursorWordForward(true);
- del();
- }
- }
- else if (event == QKeySequence::DeleteStartOfWord) {
- if (!d->readOnly) {
- cursorWordBackward(true);
- del();
- }
- }
-#endif // QT_NO_SHORTCUT
- else {
-#ifdef Q_WS_MAC
- if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
- Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
- if (myModifiers & Qt::ShiftModifier) {
- if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
- || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
- || myModifiers == Qt::ShiftModifier) {
-
- event->key() == Qt::Key_Up ? home(1) : end(1);
- }
- } else {
- if ((myModifiers == Qt::ControlModifier
- || myModifiers == Qt::AltModifier
- || myModifiers == Qt::NoModifier)) {
- event->key() == Qt::Key_Up ? home(0) : end(0);
- }
- }
- }
-#endif
- if (event->modifiers() & Qt::ControlModifier) {
- switch (event->key()) {
- case Qt::Key_Backspace:
- if (!d->readOnly) {
- cursorWordBackward(true);
- del();
- }
- break;
-#ifndef QT_NO_COMPLETER
- case Qt::Key_Up:
- case Qt::Key_Down:
- d->complete(event->key());
- break;
-#endif
-#if defined(Q_WS_X11)
- case Qt::Key_E:
- end(0);
- break;
-
- case Qt::Key_U:
- if (!d->readOnly) {
- setSelection(0, d->text.size());
-#ifndef QT_NO_CLIPBOARD
- copy();
-#endif
- del();
- }
- break;
-#endif
- default:
- unknown = true;
- }
- } else { // ### check for *no* modifier
- switch (event->key()) {
- case Qt::Key_Backspace:
- if (!d->readOnly) {
- backspace();
-#ifndef QT_NO_COMPLETER
- d->complete(Qt::Key_Backspace);
-#endif
- }
- break;
-#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Back:
- if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
- && !isReadOnly()) {
- if (text().length() == 0) {
- setText(d->origText);
-
- if (d->passwordEchoEditing)
- d->updatePasswordEchoEditing(false);
-
- setEditFocus(false);
- } else if (!d->deleteAllTimer.isActive()) {
- d->deleteAllTimer.start(750, this);
- }
- } else {
- unknown = true;
- }
- break;
-#endif
-
- default:
- unknown = true;
- }
- }
- }
-
- if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
- setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
- d->updateTextLayout();
- update();
- unknown = false;
- }
-
- if (unknown && !d->readOnly) {
- QString t = event->text();
- if (!t.isEmpty() && t.at(0).isPrint()) {
- insert(t);
-#ifndef QT_NO_COMPLETER
- d->complete(event->key());
-#endif
- event->accept();
- return;
- }
- }
-
- if (unknown)
- event->ignore();
- else
- event->accept();
+ d->control->processKeyEvent(event);
}
/*!
@@ -2196,50 +1595,17 @@ QRect QLineEdit::cursorRect() const
return d->cursorRect();
}
-/*!
- This function is not intended as polymorphic usage. Just a shared code
- fragment that calls QInputContext::mouseHandler for this
- class.
-*/
-bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
-{
-#if !defined QT_NO_IM
- Q_Q(QLineEdit);
- if ( composeMode() ) {
- int tmp_cursor = xToPos(e->pos().x());
- int mousePos = tmp_cursor - cursor;
- if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) {
- mousePos = -1;
- // don't send move events outside the preedit area
- if ( e->type() == QEvent::MouseMove )
- return true;
- }
-
- QInputContext *qic = q->inputContext();
- if ( qic )
- // may be causing reset() in some input methods
- qic->mouseHandler(mousePos, e);
- if (!textLayout.preeditAreaText().isEmpty())
- return true;
- }
-#else
- Q_UNUSED(e);
-#endif
-
- return false;
-}
-
/*! \reimp
*/
void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
{
Q_D(QLineEdit);
- if (d->readOnly) {
+ if (d->control->isReadOnly()) {
e->ignore();
return;
}
- if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) {
+ if (echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing()) {
// Clear the edit and reset to normal echo mode while entering input
// method data; the echo mode switches back when the edit loses focus.
// ### changes a public property, resets current content.
@@ -2259,55 +1625,11 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
}
#endif
- int priorState = d->undoState;
- d->removeSelectedText();
-
- int c = d->cursor; // cursor position after insertion of commit string
- if (e->replacementStart() <= 0)
- c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength());
-
- d->cursor += e->replacementStart();
+ d->control->processInputMethodEvent(e);
- // insert commit string
- if (e->replacementLength()) {
- d->selstart = d->cursor;
- d->selend = d->selstart + e->replacementLength();
- d->removeSelectedText();
- }
- if (!e->commitString().isEmpty())
- d->insert(e->commitString());
-
- d->cursor = qMin(c, d->text.length());
-
- d->textLayout.setPreeditArea(d->cursor, e->preeditString());
- d->preeditCursor = e->preeditString().length();
- d->hideCursor = false;
- QList<QTextLayout::FormatRange> formats;
- for (int i = 0; i < e->attributes().size(); ++i) {
- const QInputMethodEvent::Attribute &a = e->attributes().at(i);
- if (a.type == QInputMethodEvent::Cursor) {
- d->preeditCursor = a.start;
- d->hideCursor = !a.length;
- } else if (a.type == QInputMethodEvent::TextFormat) {
- QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
- if (f.isValid()) {
- QTextLayout::FormatRange o;
- o.start = a.start + d->cursor;
- o.length = a.length;
- o.format = f;
- formats.append(o);
- }
- }
- }
- d->textLayout.setAdditionalFormats(formats);
- d->updateTextLayout();
- update();
- if (!e->commitString().isEmpty())
- d->emitCursorPositionChanged();
- d->finishChange(priorState);
#ifndef QT_NO_COMPLETER
if (!e->commitString().isEmpty())
- d->complete(Qt::Key_unknown);
+ d->control->complete(Qt::Key_unknown);
#endif
}
@@ -2322,9 +1644,9 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
case Qt::ImFont:
return font();
case Qt::ImCursorPosition:
- return QVariant((d->selend - d->selstart == 0) ? d->cursor : d->selend);
+ return QVariant(d->control->hasSelectedText() ? d->control->selectionEnd() : d->control->cursor());
case Qt::ImSurroundingText:
- return QVariant(d->text);
+ return QVariant(text());
case Qt::ImCurrentSelection:
return QVariant(selectedText());
default:
@@ -2341,36 +1663,34 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
if (e->reason() == Qt::TabFocusReason ||
e->reason() == Qt::BacktabFocusReason ||
e->reason() == Qt::ShortcutFocusReason) {
- if (d->maskData)
- d->moveCursor(d->nextMaskBlank(0));
- else if (!d->hasSelectedText())
+ if (!d->control->inputMask().isEmpty())
+ d->control->moveCursor(d->control->nextMaskBlank(0));
+ else if (!d->control->hasSelectedText())
selectAll();
}
#ifdef QT_KEYPAD_NAVIGATION
if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason))
#endif
- if (!d->cursorTimer) {
- int cft = QApplication::cursorFlashTime();
- d->cursorTimer = cft ? startTimer(cft/2) : -1;
- }
+ int cft = QApplication::cursorFlashTime();
+ d->control->setCursorBlinkPeriod(cft/2);
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
- if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty())
+ if((!hasSelectedText() && d->control->preeditAreaText().isEmpty())
|| style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(true);
#ifdef Q_WS_MAC
- if (d->echoMode == Password || d->echoMode == NoEcho)
+ if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho)
qt_mac_secure_keyboard(true);
#endif
#ifdef QT_KEYPAD_NAVIGATION
- d->origText = d->text;
+ d->control->setCancelText(d->text);
#endif
#ifndef QT_NO_COMPLETER
- if (d->completer) {
- d->completer->setWidget(this);
- QObject::connect(d->completer, SIGNAL(activated(QString)),
+ if (d->control->completer()) {
+ d->control->completer()->setWidget(this);
+ QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
this, SLOT(setText(QString)));
- QObject::connect(d->completer, SIGNAL(highlighted(QString)),
+ QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
this, SLOT(_q_completionHighlighted(QString)));
}
#endif
@@ -2383,7 +1703,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
void QLineEdit::focusOutEvent(QFocusEvent *e)
{
Q_D(QLineEdit);
- if (d->passwordEchoEditing) {
+ if (d->control->passwordEchoEditing()) {
// Reset the echomode back to PasswordEchoOnEdit when the widget loses
// focus.
d->updatePasswordEchoEditing(false);
@@ -2395,37 +1715,29 @@ void QLineEdit::focusOutEvent(QFocusEvent *e)
deselect();
d->setCursorVisible(false);
- if (d->cursorTimer > 0)
- killTimer(d->cursorTimer);
- d->cursorTimer = 0;
-
+ d->control->setCursorBlinkPeriod(0);
#ifdef QT_KEYPAD_NAVIGATION
// editingFinished() is already emitted on LeaveEditFocus
if (!QApplication::keypadNavigationEnabled())
#endif
if (reason != Qt::PopupFocusReason
|| !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) {
- if (!d->emitingEditingFinished) {
- if (hasAcceptableInput() || d->fixup()) {
- d->emitingEditingFinished = true;
+ if (hasAcceptableInput() || d->control->fixup())
emit editingFinished();
- d->emitingEditingFinished = false;
- }
- }
#ifdef QT3_SUPPORT
emit lostFocus();
#endif
}
#ifdef Q_WS_MAC
- if (d->echoMode == Password || d->echoMode == NoEcho)
+ if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho)
qt_mac_secure_keyboard(false);
#endif
#ifdef QT_KEYPAD_NAVIGATION
- d->origText = QString();
+ d->control->setCancelText(QString());
#endif
#ifndef QT_NO_COMPLETER
- if (d->completer) {
- QObject::disconnect(d->completer, 0, this, 0);
+ if (d->control->completer()) {
+ QObject::disconnect(d->control->completer(), 0, this, 0);
}
#endif
update();
@@ -2455,24 +1767,19 @@ void QLineEdit::paintEvent(QPaintEvent *)
Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment));
switch (va & Qt::AlignVertical_Mask) {
case Qt::AlignBottom:
- d->vscroll = r.y() + r.height() - fm.height() - verticalMargin;
+ d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin;
break;
case Qt::AlignTop:
- d->vscroll = r.y() + verticalMargin;
+ d->vscroll = r.y() + d->verticalMargin;
break;
default:
//center
d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2;
break;
}
- QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height());
- QTextLine line = d->textLayout.lineAt(0);
+ QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height());
- int cursor = d->cursor;
- if (d->preeditCursor != -1)
- cursor += d->preeditCursor;
- // locate cursor position
- int cix = qRound(line.cursorToX(cursor));
+ int cix = qRound(d->control->cursorToX());
// horizontal scrolling. d->hscroll is the left indent from the beginning
// of the text line to the left edge of lineRect. we update this value
@@ -2482,7 +1789,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
// (cix).
int minLB = qMax(0, -fm.minLeftBearing());
int minRB = qMax(0, -fm.minRightBearing());
- int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
+ int widthUsed = d->control->width() + minRB;
if ((minLB + widthUsed) <= lineRect.width()) {
// text fits in lineRect; use hscroll for alignment
switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
@@ -2510,7 +1817,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
d->hscroll = widthUsed - lineRect.width() + 1;
}
// the y offset is there to keep the baseline constant in case we have script changes in the text.
- QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent - fm.ascent());
+ QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
// draw text, selections and cursors
#ifndef QT_NO_STYLE_STYLESHEET
@@ -2520,33 +1827,23 @@ void QLineEdit::paintEvent(QPaintEvent *)
#endif
p.setPen(pal.text().color());
- QVector<QTextLayout::FormatRange> selections;
+ int flags = QLineControl::DrawText;
+
#ifdef QT_KEYPAD_NAVIGATION
if (!QApplication::keypadNavigationEnabled() || hasEditFocus())
#endif
- if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) {
- QTextLayout::FormatRange o;
- if (d->selstart < d->selend) {
- o.start = d->selstart;
- o.length = d->selend - d->selstart;
- o.format.setBackground(pal.brush(QPalette::Highlight));
- o.format.setForeground(pal.brush(QPalette::HighlightedText));
- } else {
- // mask selection
- o.start = d->cursor;
- o.length = 1;
- o.format.setBackground(pal.brush(QPalette::Text));
- o.format.setForeground(pal.brush(QPalette::Window));
- }
- selections.append(o);
- }
+ if (d->control->hasSelectedText() || (d->cursorVisible && !d->control->inputMask().isEmpty() && !d->control->isReadOnly()))
+ flags |= QLineControl::DrawSelections;
// Asian users see an IM selection text as cursor on candidate
// selection phase of input method, so the ordinary cursor should be
// invisible if we have a preedit string.
- d->textLayout.draw(&p, topLeft, selections, r);
- if (d->cursorVisible && !d->readOnly && !d->hideCursor)
- d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth));
+ if (d->cursorVisible && !d->control->isReadOnly())
+ flags |= QLineControl::DrawCursor;
+
+ d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth));
+ d->control->draw(&p, topLeft, r, flags);
+
}
@@ -2556,12 +1853,11 @@ void QLineEdit::paintEvent(QPaintEvent *)
void QLineEdit::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QLineEdit);
- if (!d->readOnly && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
+ if (!d->control->isReadOnly() && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
e->acceptProposedAction();
- d->cursor = d->xToPos(e->pos().x());
+ d->control->moveCursor(d->xToPos(e->pos().x()), false);
d->cursorVisible = true;
update();
- d->emitCursorPositionChanged();
}
}
@@ -2587,13 +1883,14 @@ void QLineEdit::dropEvent(QDropEvent* e)
Q_D(QLineEdit);
QString str = e->mimeData()->text();
- if (!str.isNull() && !d->readOnly) {
+ if (!str.isNull() && !d->control->isReadOnly()) {
if (e->source() == this && e->dropAction() == Qt::CopyAction)
deselect();
- d->cursor =d->xToPos(e->pos().x());
- int selStart = d->cursor;
- int oldSelStart = d->selstart;
- int oldSelEnd = d->selend;
+ int cursorPos = d->xToPos(e->pos().x());
+ int selStart = cursorPos;
+ int oldSelStart = d->control->selectionStart();
+ int oldSelEnd = d->control->selectionEnd();
+ d->control->moveCursor(cursorPos, false);
d->cursorVisible = false;
e->acceptProposedAction();
insert(str);
@@ -2615,22 +1912,6 @@ void QLineEdit::dropEvent(QDropEvent* e)
}
}
-void QLineEditPrivate::drag()
-{
- Q_Q(QLineEdit);
- dndTimer.stop();
- QMimeData *data = new QMimeData;
- data->setText(q->selectedText());
- QDrag *drag = new QDrag(q);
- drag->setMimeData(data);
- Qt::DropAction action = drag->start();
- if (action == Qt::MoveAction && !readOnly && drag->target() != q) {
- int priorState = undoState;
- removeSelectedText();
- finishChange(priorState);
- }
-}
-
#endif // QT_NO_DRAGANDDROP
#ifndef QT_NO_CONTEXTMENU
@@ -2675,37 +1956,39 @@ QMenu *QLineEdit::createStandardContextMenu()
popup->setObjectName(QLatin1String("qt_edit_menu"));
QAction *action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo));
- action->setEnabled(d->isUndoAvailable());
+ action->setEnabled(d->control->isUndoAvailable());
connect(action, SIGNAL(triggered()), SLOT(undo()));
action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo));
- action->setEnabled(d->isRedoAvailable());
+ action->setEnabled(d->control->isRedoAvailable());
connect(action, SIGNAL(triggered()), SLOT(redo()));
popup->addSeparator();
#ifndef QT_NO_CLIPBOARD
action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut));
- action->setEnabled(!d->readOnly && d->hasSelectedText() && d->echoMode == QLineEdit::Normal);
+ action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()
+ && d->control->echoMode() == QLineEdit::Normal);
connect(action, SIGNAL(triggered()), SLOT(cut()));
action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy));
- action->setEnabled(d->hasSelectedText() && d->echoMode == QLineEdit::Normal);
+ action->setEnabled(d->control->hasSelectedText()
+ && d->control->echoMode() == QLineEdit::Normal);
connect(action, SIGNAL(triggered()), SLOT(copy()));
action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste));
- action->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty());
+ action->setEnabled(!d->control->isReadOnly() && !QApplication::clipboard()->text().isEmpty());
connect(action, SIGNAL(triggered()), SLOT(paste()));
#endif
action = popup->addAction(QLineEdit::tr("Delete"));
- action->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText());
+ action->setEnabled(!d->control->isReadOnly() && !d->control->text().isEmpty() && d->control->hasSelectedText());
connect(action, SIGNAL(triggered()), SLOT(_q_deleteSelected()));
popup->addSeparator();
action = popup->addAction(QLineEdit::tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll));
- action->setEnabled(!d->text.isEmpty() && !d->allSelected());
+ action->setEnabled(!d->control->text().isEmpty() && !d->control->allSelected());
d->selectAllAction = action;
connect(action, SIGNAL(triggered()), SLOT(selectAll()));
@@ -2719,9 +2002,9 @@ QMenu *QLineEdit::createStandardContextMenu()
#endif
#if defined(Q_WS_WIN)
- if (!d->readOnly && qt_use_rtl_extensions) {
+ if (!d->control->isReadOnly() && qt_use_rtl_extensions) {
#else
- if (!d->readOnly) {
+ if (!d->control->isReadOnly()) {
#endif
popup->addSeparator();
QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup);
@@ -2735,806 +2018,26 @@ QMenu *QLineEdit::createStandardContextMenu()
void QLineEdit::changeEvent(QEvent *ev)
{
Q_D(QLineEdit);
- if(ev->type() == QEvent::ActivationChange) {
+ switch(ev->type())
+ {
+ case QEvent::ActivationChange:
if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
update();
- } else if (ev->type() == QEvent::FontChange
- || ev->type() == QEvent::StyleChange
- || ev->type() == QEvent::LayoutDirectionChange) {
- d->updateTextLayout();
- }
- QWidget::changeEvent(ev);
-}
-
-void QLineEditPrivate::_q_handleWindowActivate()
-{
- Q_Q(QLineEdit);
- if (!q->hasFocus() && q->hasSelectedText())
- q->deselect();
-}
-
-void QLineEditPrivate::_q_deleteSelected()
-{
- Q_Q(QLineEdit);
- if (!hasSelectedText())
- return;
-
- int priorState = undoState;
- q->resetInputContext();
- removeSelectedText();
- separate();
- finishChange(priorState);
-}
-
-void QLineEditPrivate::init(const QString& txt)
-{
- Q_Q(QLineEdit);
-#ifndef QT_NO_CURSOR
- q->setCursor(Qt::IBeamCursor);
-#endif
- q->setFocusPolicy(Qt::StrongFocus);
- q->setAttribute(Qt::WA_InputMethodEnabled);
- // Specifies that this widget can use more, but is able to survive on
- // less, horizontal space; and is fixed vertically.
- q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
- q->setBackgroundRole(QPalette::Base);
- q->setAttribute(Qt::WA_KeyCompression);
- q->setMouseTracking(true);
- q->setAcceptDrops(true);
- text = txt;
- updateTextLayout();
- cursor = text.length();
-
- q->setAttribute(Qt::WA_MacShowFocusRect);
-}
-
-void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
-{
- Q_Q(QLineEdit);
- passwordEchoEditing = editing;
- q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q));
- updateTextLayout();
- q->update();
-}
-
-void QLineEditPrivate::updateTextLayout()
-{
- // replace certain non-printable characters with spaces (to avoid
- // drawing boxes when using fonts that don't have glyphs for such
- // characters)
- Q_Q(QLineEdit);
- QString str = q->displayText();
- QChar* uc = str.data();
- for (int i = 0; i < (int)str.length(); ++i) {
- if ((uc[i] < 0x20 && uc[i] != 0x09)
- || uc[i] == QChar::LineSeparator
- || uc[i] == QChar::ParagraphSeparator
- || uc[i] == QChar::ObjectReplacementCharacter)
- uc[i] = QChar(0x0020);
- }
- textLayout.setFont(q->font());
- textLayout.setText(str);
- QTextOption option;
- option.setTextDirection(q->layoutDirection());
- option.setFlags(QTextOption::IncludeTrailingSpaces);
- textLayout.setTextOption(option);
-
- textLayout.beginLayout();
- QTextLine l = textLayout.createLine();
- textLayout.endLayout();
- ascent = qRound(l.ascent());
-}
-
-int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
-{
- QRect cr = adjustedContentsRect();
- x-= cr.x() - hscroll + horizontalMargin;
- QTextLine l = textLayout.lineAt(0);
- return l.xToCursor(x, betweenOrOn);
-}
-
-QRect QLineEditPrivate::cursorRect() const
-{
- Q_Q(const QLineEdit);
- QRect cr = adjustedContentsRect();
- int cix = cr.x() - hscroll + horizontalMargin;
- QTextLine l = textLayout.lineAt(0);
- int c = cursor;
- if (preeditCursor != -1)
- c += preeditCursor;
- cix += qRound(l.cursorToX(c));
- int ch = qMin(cr.height(), q->fontMetrics().height() + 1);
- int w = q->style()->pixelMetric(QStyle::PM_TextCursorWidth);
- return QRect(cix-5, vscroll, w + 9, ch);
-}
-
-QRect QLineEditPrivate::adjustedContentsRect() const
-{
- Q_Q(const QLineEdit);
- QStyleOptionFrameV2 opt;
- q->initStyleOption(&opt);
- QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
- r.setX(r.x() + leftTextMargin);
- r.setY(r.y() + topTextMargin);
- r.setRight(r.right() - rightTextMargin);
- r.setBottom(r.bottom() - bottomTextMargin);
- return r;
-}
-
-bool QLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable
-{
-#ifndef QT_NO_VALIDATOR
- if (validator) {
- QString textCopy = text;
- int cursorCopy = cursor;
- validator->fixup(textCopy);
- if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
- if (textCopy != text || cursorCopy != cursor)
- setText(textCopy, cursorCopy);
- return true;
- }
- }
-#endif
- return false;
-}
-
-void QLineEditPrivate::moveCursor(int pos, bool mark)
-{
- Q_Q(QLineEdit);
- if (pos != cursor) {
- separate();
- if (maskData)
- pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
- }
- bool fullUpdate = mark || hasSelectedText();
- if (mark) {
- int anchor;
- if (selend > selstart && cursor == selstart)
- anchor = selend;
- else if (selend > selstart && cursor == selend)
- anchor = selstart;
- else
- anchor = cursor;
- selstart = qMin(anchor, pos);
- selend = qMax(anchor, pos);
- updateTextLayout();
- } else {
- deselect();
- }
- if (fullUpdate) {
- cursor = pos;
- q->update();
- } else {
- setCursorVisible(false);
- cursor = pos;
- setCursorVisible(true);
- if (!adjustedContentsRect().contains(cursorRect()))
- q->update();
- }
- QStyleOptionFrameV2 opt;
- q->initStyleOption(&opt);
- if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q))
- setCursorVisible(false);
- if (mark || selDirty) {
- selDirty = false;
- emit q->selectionChanged();
- }
- emitCursorPositionChanged();
-}
-
-void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited)
-{
- Q_Q(QLineEdit);
- bool lineDirty = selDirty;
- if (textDirty) {
- // do validation
- bool wasValidInput = validInput;
- validInput = true;
-#ifndef QT_NO_VALIDATOR
- if (validator) {
- validInput = false;
- QString textCopy = text;
- int cursorCopy = cursor;
- validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
- if (validInput) {
- if (text != textCopy) {
- setText(textCopy, cursorCopy);
- return;
- }
- cursor = cursorCopy;
- }
- }
-#endif
- if (validateFromState >= 0 && wasValidInput && !validInput) {
- undo(validateFromState);
- history.resize(undoState);
- if (modifiedState > undoState)
- modifiedState = -1;
- validInput = true;
- textDirty = false;
- }
- updateTextLayout();
- lineDirty |= textDirty;
- if (textDirty) {
- textDirty = false;
- QString actualText = maskData ? stripString(text) : text;
- if (edited)
- emit q->textEdited(actualText);
- q->updateMicroFocus();
-#ifndef QT_NO_COMPLETER
- if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion)
- complete(-1); // update the popup on cut/paste/del
-#endif
- emit q->textChanged(actualText);
- }
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
-#endif
- }
- if (selDirty) {
- selDirty = false;
- emit q->selectionChanged();
- }
- if (lineDirty || update)
- q->update();
- emitCursorPositionChanged();
-}
-
-void QLineEditPrivate::emitCursorPositionChanged()
-{
- Q_Q(QLineEdit);
- if (cursor != lastCursorPos) {
- const int oldLast = lastCursorPos;
- lastCursorPos = cursor;
- emit q->cursorPositionChanged(oldLast, cursor);
- }
-}
-
-void QLineEditPrivate::setText(const QString& txt, int pos, bool edited)
-{
- Q_Q(QLineEdit);
- q->resetInputContext();
- deselect();
- QString oldText = text;
- if (maskData) {
- text = maskString(0, txt, true);
- text += clearString(text.length(), maxLength - text.length());
- } else {
- text = txt.isEmpty() ? txt : txt.left(maxLength);
- }
- history.clear();
- modifiedState = undoState = 0;
- cursor = (pos < 0 || pos > text.length()) ? text.length() : pos;
- textDirty = (oldText != text);
- finishChange(-1, true, edited);
-}
-
-
-void QLineEditPrivate::setCursorVisible(bool visible)
-{
- Q_Q(QLineEdit);
- if ((bool)cursorVisible == visible)
- return;
- if (cursorTimer)
- cursorVisible = visible;
- QRect r = cursorRect();
- if (maskData)
- q->update();
- else
- q->update(r);
-}
-
-void QLineEditPrivate::addCommand(const Command& cmd)
-{
- if (separator && undoState && history[undoState-1].type != Separator) {
- history.resize(undoState + 2);
- history[undoState++] = Command(Separator, cursor, 0, selstart, selend);
- } else {
- history.resize(undoState + 1);
- }
- separator = false;
- history[undoState++] = cmd;
-}
-
-void QLineEditPrivate::insert(const QString& s)
-{
- if (hasSelectedText())
- addCommand(Command(SetSelection, cursor, 0, selstart, selend));
- if (maskData) {
- QString ms = maskString(cursor, s);
- for (int i = 0; i < (int) ms.length(); ++i) {
- addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i), -1, -1));
- addCommand(Command(Insert, cursor+i, ms.at(i), -1, -1));
- }
- text.replace(cursor, ms.length(), ms);
- cursor += ms.length();
- cursor = nextMaskBlank(cursor);
- textDirty = true;
- } else {
- int remaining = maxLength - text.length();
- if (remaining != 0) {
- text.insert(cursor, s.left(remaining));
- for (int i = 0; i < (int) s.left(remaining).length(); ++i)
- addCommand(Command(Insert, cursor++, s.at(i), -1, -1));
- textDirty = true;
- }
- }
-}
-
-void QLineEditPrivate::del(bool wasBackspace)
-{
- if (cursor < (int) text.length()) {
- if (hasSelectedText())
- addCommand(Command(SetSelection, cursor, 0, selstart, selend));
- addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor), -1, -1));
- if (maskData) {
- text.replace(cursor, 1, clearString(cursor, 1));
- addCommand(Command(Insert, cursor, text.at(cursor), -1, -1));
- } else {
- text.remove(cursor, 1);
- }
- textDirty = true;
- }
-}
-
-void QLineEditPrivate::removeSelectedText()
-{
- if (selstart < selend && selend <= (int) text.length()) {
- separate();
- int i ;
- addCommand(Command(SetSelection, cursor, 0, selstart, selend));
- if (selstart <= cursor && cursor < selend) {
- // cursor is within the selection. Split up the commands
- // to be able to restore the correct cursor position
- for (i = cursor; i >= selstart; --i)
- addCommand (Command(DeleteSelection, i, text.at(i), -1, 1));
- for (i = selend - 1; i > cursor; --i)
- addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i), -1, -1));
- } else {
- for (i = selend-1; i >= selstart; --i)
- addCommand (Command(RemoveSelection, i, text.at(i), -1, -1));
- }
- if (maskData) {
- text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart));
- for (int i = 0; i < selend - selstart; ++i)
- addCommand(Command(Insert, selstart + i, text.at(selstart + i), -1, -1));
- } else {
- text.remove(selstart, selend - selstart);
- }
- if (cursor > selstart)
- cursor -= qMin(cursor, selend) - selstart;
- deselect();
- textDirty = true;
-
- // adjust hscroll to avoid gap
- const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing());
- updateTextLayout();
- const QTextLine line = textLayout.lineAt(0);
- const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
- hscroll = qMin(hscroll, widthUsed);
- }
-}
-
-void QLineEditPrivate::parseInputMask(const QString &maskFields)
-{
- int delimiter = maskFields.indexOf(QLatin1Char(';'));
- if (maskFields.isEmpty() || delimiter == 0) {
- if (maskData) {
- delete [] maskData;
- maskData = 0;
- maxLength = 32767;
- setText(QString());
- }
- return;
- }
-
- if (delimiter == -1) {
- blank = QLatin1Char(' ');
- inputMask = maskFields;
- } else {
- inputMask = maskFields.left(delimiter);
- blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
- }
-
- // calculate maxLength / maskData length
- maxLength = 0;
- QChar c = 0;
- for (int i=0; i<inputMask.length(); i++) {
- c = inputMask.at(i);
- if (i > 0 && inputMask.at(i-1) == QLatin1Char('\\')) {
- maxLength++;
- continue;
- }
- if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
- c != QLatin1Char('<') && c != QLatin1Char('>') &&
- c != QLatin1Char('{') && c != QLatin1Char('}') &&
- c != QLatin1Char('[') && c != QLatin1Char(']'))
- maxLength++;
- }
-
- delete [] maskData;
- maskData = new MaskInputData[maxLength];
-
- MaskInputData::Casemode m = MaskInputData::NoCaseMode;
- c = 0;
- bool s;
- bool escape = false;
- int index = 0;
- for (int i = 0; i < inputMask.length(); i++) {
- c = inputMask.at(i);
- if (escape) {
- s = true;
- maskData[index].maskChar = c;
- maskData[index].separator = s;
- maskData[index].caseMode = m;
- index++;
- escape = false;
- } else if (c == QLatin1Char('<')) {
- m = MaskInputData::Lower;
- } else if (c == QLatin1Char('>')) {
- m = MaskInputData::Upper;
- } else if (c == QLatin1Char('!')) {
- m = MaskInputData::NoCaseMode;
- } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
- switch (c.unicode()) {
- case 'A':
- case 'a':
- case 'N':
- case 'n':
- case 'X':
- case 'x':
- case '9':
- case '0':
- case 'D':
- case 'd':
- case '#':
- case 'H':
- case 'h':
- case 'B':
- case 'b':
- s = false;
- break;
- case '\\':
- escape = true;
- default:
- s = true;
- break;
- }
-
- if (!escape) {
- maskData[index].maskChar = c;
- maskData[index].separator = s;
- maskData[index].caseMode = m;
- index++;
- }
- }
- }
- setText(text);
-}
-
-
-/* checks if the key is valid compared to the inputMask */
-bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const
-{
- switch (mask.unicode()) {
- case 'A':
- if (key.isLetter())
- return true;
break;
- case 'a':
- if (key.isLetter() || key == blank)
- return true;
+ case QEvent::FontChange:
+ d->control->setFont(font());
break;
- case 'N':
- if (key.isLetterOrNumber())
- return true;
- break;
- case 'n':
- if (key.isLetterOrNumber() || key == blank)
- return true;
- break;
- case 'X':
- if (key.isPrint())
- return true;
- break;
- case 'x':
- if (key.isPrint() || key == blank)
- return true;
- break;
- case '9':
- if (key.isNumber())
- return true;
- break;
- case '0':
- if (key.isNumber() || key == blank)
- return true;
- break;
- case 'D':
- if (key.isNumber() && key.digitValue() > 0)
- return true;
- break;
- case 'd':
- if ((key.isNumber() && key.digitValue() > 0) || key == blank)
- return true;
- break;
- case '#':
- if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank)
- return true;
- break;
- case 'B':
- if (key == QLatin1Char('0') || key == QLatin1Char('1'))
- return true;
- break;
- case 'b':
- if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank)
- return true;
- break;
- case 'H':
- if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
- return true;
+ case QEvent::StyleChange:
+ d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter));
+ update();
break;
- case 'h':
- if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank)
- return true;
+ case QEvent::LayoutDirectionChange:
+ d->control->setLayoutDirection(layoutDirection());
break;
default:
break;
}
- return false;
-}
-
-bool QLineEditPrivate::hasAcceptableInput(const QString &str) const
-{
-#ifndef QT_NO_VALIDATOR
- QString textCopy = str;
- int cursorCopy = cursor;
- if (validator && validator->validate(textCopy, cursorCopy)
- != QValidator::Acceptable)
- return false;
-#endif
-
- if (!maskData)
- return true;
-
- if (str.length() != maxLength)
- return false;
-
- for (int i=0; i < maxLength; ++i) {
- if (maskData[i].separator) {
- if (str.at(i) != maskData[i].maskChar)
- return false;
- } else {
- if (!isValidInput(str.at(i), maskData[i].maskChar))
- return false;
- }
- }
- return true;
-}
-
-/*
- Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
- specifies from where characters should be gotten when a separator is met in \a str - true means
- that blanks will be used, false that previous input is used.
- Calling this when no inputMask is set is undefined.
-*/
-QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const
-{
- if (pos >= (uint)maxLength)
- return QString::fromLatin1("");
-
- QString fill;
- fill = clear ? clearString(0, maxLength) : text;
-
- int strIndex = 0;
- QString s = QString::fromLatin1("");
- int i = pos;
- while (i < maxLength) {
- if (strIndex < str.length()) {
- if (maskData[i].separator) {
- s += maskData[i].maskChar;
- if (str[(int)strIndex] == maskData[i].maskChar)
- strIndex++;
- ++i;
- } else {
- if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) {
- switch (maskData[i].caseMode) {
- case MaskInputData::Upper:
- s += str[(int)strIndex].toUpper();
- break;
- case MaskInputData::Lower:
- s += str[(int)strIndex].toLower();
- break;
- default:
- s += str[(int)strIndex];
- }
- ++i;
- } else {
- // search for separator first
- int n = findInMask(i, true, true, str[(int)strIndex]);
- if (n != -1) {
- if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) {
- s += fill.mid(i, n-i+1);
- i = n + 1; // update i to find + 1
- }
- } else {
- // search for valid blank if not
- n = findInMask(i, true, false, str[(int)strIndex]);
- if (n != -1) {
- s += fill.mid(i, n-i);
- switch (maskData[n].caseMode) {
- case MaskInputData::Upper:
- s += str[(int)strIndex].toUpper();
- break;
- case MaskInputData::Lower:
- s += str[(int)strIndex].toLower();
- break;
- default:
- s += str[(int)strIndex];
- }
- i = n + 1; // updates i to find + 1
- }
- }
- }
- strIndex++;
- }
- } else
- break;
- }
-
- return s;
-}
-
-
-
-/*
- Returns a "cleared" string with only separators and blank chars.
- Calling this when no inputMask is set is undefined.
-*/
-QString QLineEditPrivate::clearString(uint pos, uint len) const
-{
- if (pos >= (uint)maxLength)
- return QString();
-
- QString s;
- int end = qMin((uint)maxLength, pos + len);
- for (int i=pos; i<end; i++)
- if (maskData[i].separator)
- s += maskData[i].maskChar;
- else
- s += blank;
-
- return s;
-}
-
-/*
- Strips blank parts of the input in a QLineEdit when an inputMask is set,
- separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
-*/
-QString QLineEditPrivate::stripString(const QString &str) const
-{
- if (!maskData)
- return str;
-
- QString s;
- int end = qMin(maxLength, (int)str.length());
- for (int i=0; i < end; i++)
- if (maskData[i].separator)
- s += maskData[i].maskChar;
- else
- if (str[i] != blank)
- s += str[i];
-
- return s;
-}
-
-/* searches forward/backward in maskData for either a separator or a blank */
-int QLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
-{
- if (pos >= maxLength || pos < 0)
- return -1;
-
- int end = forward ? maxLength : -1;
- int step = forward ? 1 : -1;
- int i = pos;
-
- while (i != end) {
- if (findSeparator) {
- if (maskData[i].separator && maskData[i].maskChar == searchChar)
- return i;
- } else {
- if (!maskData[i].separator) {
- if (searchChar.isNull())
- return i;
- else if (isValidInput(searchChar, maskData[i].maskChar))
- return i;
- }
- }
- i += step;
- }
- return -1;
-}
-
-void QLineEditPrivate::undo(int until)
-{
- if (!isUndoAvailable())
- return;
- deselect();
- while (undoState && undoState > until) {
- Command& cmd = history[--undoState];
- switch (cmd.type) {
- case Insert:
- text.remove(cmd.pos, 1);
- cursor = cmd.pos;
- break;
- case SetSelection:
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- case Remove:
- case RemoveSelection:
- text.insert(cmd.pos, cmd.uc);
- cursor = cmd.pos + 1;
- break;
- case Delete:
- case DeleteSelection:
- text.insert(cmd.pos, cmd.uc);
- cursor = cmd.pos;
- break;
- case Separator:
- continue;
- }
- if (until < 0 && undoState) {
- Command& next = history[undoState-1];
- if (next.type != cmd.type && next.type < RemoveSelection
- && (cmd.type < RemoveSelection || next.type == Separator))
- break;
- }
- }
- textDirty = true;
- emitCursorPositionChanged();
-}
-
-void QLineEditPrivate::redo() {
- if (!isRedoAvailable())
- return;
- deselect();
- while (undoState < (int)history.size()) {
- Command& cmd = history[undoState++];
- switch (cmd.type) {
- case Insert:
- text.insert(cmd.pos, cmd.uc);
- cursor = cmd.pos + 1;
- break;
- case SetSelection:
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- case Remove:
- case Delete:
- case RemoveSelection:
- case DeleteSelection:
- text.remove(cmd.pos, 1);
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- case Separator:
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- }
- if (undoState < (int)history.size()) {
- Command& next = history[undoState];
- if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
- && (next.type < RemoveSelection || cmd.type == Separator))
- break;
- }
- }
- textDirty = true;
- emitCursorPositionChanged();
+ QWidget::changeEvent(ev);
}
/*!
diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h
index a97dc9a..daac6a7 100644
--- a/src/gui/widgets/qlineedit.h
+++ b/src/gui/widgets/qlineedit.h
@@ -268,6 +268,8 @@ private:
Q_DECLARE_PRIVATE(QLineEdit)
Q_PRIVATE_SLOT(d_func(), void _q_handleWindowActivate())
Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected())
+ Q_PRIVATE_SLOT(d_func(), void _q_textEdited(const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged(int, int))
#ifndef QT_NO_COMPLETER
Q_PRIVATE_SLOT(d_func(), void _q_completionHighlighted(QString))
#endif
diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp
new file mode 100644
index 0000000..0e39304
--- /dev/null
+++ b/src/gui/widgets/qlineedit_p.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlineedit.h"
+#include "qlineedit_p.h"
+
+#ifndef QT_NO_LINEEDIT
+
+#include "qabstractitemview.h"
+#include "qclipboard.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qlist.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+const int QLineEditPrivate::verticalMargin(1);
+const int QLineEditPrivate::horizontalMargin(2);
+
+int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
+{
+ QRect cr = adjustedContentsRect();
+ x-= cr.x() - hscroll + horizontalMargin;
+ return control->xToPos(x, betweenOrOn);
+}
+
+QRect QLineEditPrivate::cursorRect() const
+{
+ QRect cr = adjustedContentsRect();
+ int cix = cr.x() - hscroll + horizontalMargin;
+ QRect crect = control->cursorRect();
+ crect.moveTo(crect.topLeft() + QPoint(cix, vscroll));
+ return crect;
+}
+
+#ifndef QT_NO_COMPLETER
+
+void QLineEditPrivate::_q_completionHighlighted(QString newText)
+{
+ Q_Q(QLineEdit);
+ if (control->completer()->completionMode() != QCompleter::InlineCompletion) {
+ q->setText(newText);
+ } else {
+ int c = control->cursor();
+ QString text = control->text();
+ q->setText(text.left(c) + newText.mid(c));
+ control->moveCursor(control->end(), false);
+ control->moveCursor(c, true);
+ }
+}
+
+#endif // QT_NO_COMPLETER
+
+void QLineEditPrivate::_q_clipboardChanged()
+{
+}
+
+void QLineEditPrivate::_q_handleWindowActivate()
+{
+ Q_Q(QLineEdit);
+ if (!q->hasFocus() && control->hasSelectedText())
+ control->deselect();
+}
+
+void QLineEditPrivate::_q_deleteSelected()
+{
+}
+
+void QLineEditPrivate::_q_textEdited(const QString &text)
+{
+ Q_Q(QLineEdit);
+#ifndef QT_NO_COMPLETER
+ if (control->completer() &&
+ control->completer()->completionMode() != QCompleter::InlineCompletion)
+ control->complete(-1); // update the popup on cut/paste/del
+#endif
+ emit q->textEdited(text);
+}
+
+void QLineEditPrivate::_q_cursorPositionChanged(int from, int to)
+{
+ Q_Q(QLineEdit);
+ q->update();
+ emit q->cursorPositionChanged(from, to);
+}
+
+void QLineEditPrivate::init(const QString& txt)
+{
+ Q_Q(QLineEdit);
+ control = new QLineControl(txt);
+ QObject::connect(control, SIGNAL(textChanged(const QString &)),
+ q, SIGNAL(textChanged(const QString &)));
+ QObject::connect(control, SIGNAL(textEdited(const QString &)),
+ q, SLOT(_q_textEdited(const QString &)));
+ QObject::connect(control, SIGNAL(cursorPositionChanged(int, int)),
+ q, SLOT(_q_cursorPositionChanged(int, int)));
+ QObject::connect(control, SIGNAL(selectionChanged()),
+ q, SIGNAL(selectionChanged()));
+ QObject::connect(control, SIGNAL(accepted()),
+ q, SIGNAL(returnPressed()));
+ QObject::connect(control, SIGNAL(editingFinished()),
+ q, SIGNAL(editingFinished()));
+
+ // for now, going completely overboard with updates.
+ QObject::connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(update()));
+
+ QObject::connect(control, SIGNAL(displayTextChanged(const QString &)),
+ q, SLOT(update()));
+ control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter));
+#ifndef QT_NO_CURSOR
+ q->setCursor(Qt::IBeamCursor);
+#endif
+ q->setFocusPolicy(Qt::StrongFocus);
+ q->setAttribute(Qt::WA_InputMethodEnabled);
+ // Specifies that this widget can use more, but is able to survive on
+ // less, horizontal space; and is fixed vertically.
+ q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
+ q->setBackgroundRole(QPalette::Base);
+ q->setAttribute(Qt::WA_KeyCompression);
+ q->setMouseTracking(true);
+ q->setAcceptDrops(true);
+
+ q->setAttribute(Qt::WA_MacShowFocusRect);
+}
+
+QRect QLineEditPrivate::adjustedContentsRect() const
+{
+ Q_Q(const QLineEdit);
+ QStyleOptionFrameV2 opt;
+ q->initStyleOption(&opt);
+ QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
+ r.setX(r.x() + leftTextMargin);
+ r.setY(r.y() + topTextMargin);
+ r.setRight(r.right() - rightTextMargin);
+ r.setBottom(r.bottom() - bottomTextMargin);
+ return r;
+}
+
+void QLineEditPrivate::setCursorVisible(bool visible)
+{
+ Q_Q(QLineEdit);
+ if ((bool)cursorVisible == visible)
+ return;
+ cursorVisible = visible;
+ QRect r = cursorRect();
+ if (control->inputMask().isEmpty())
+ q->update(r);
+ else
+ q->update();
+}
+
+void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
+{
+ Q_Q(QLineEdit);
+ control->updatePasswordEchoEditing(editing);
+ q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod());
+}
+
+/*!
+ This function is not intended as polymorphic usage. Just a shared code
+ fragment that calls QInputContext::mouseHandler for this
+ class.
+*/
+bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
+{
+#if !defined QT_NO_IM
+ Q_Q(QLineEdit);
+ if ( control->composeMode() ) {
+ int tmp_cursor = xToPos(e->pos().x());
+ int mousePos = tmp_cursor - control->cursor();
+ if ( mousePos < 0 || mousePos > control->preeditAreaText().length() ) {
+ mousePos = -1;
+ // don't send move events outside the preedit area
+ if ( e->type() == QEvent::MouseMove )
+ return true;
+ }
+
+ QInputContext *qic = q->inputContext();
+ if ( qic )
+ // may be causing reset() in some input methods
+ qic->mouseHandler(mousePos, e);
+ if (!control->preeditAreaText().isEmpty())
+ return true;
+ }
+#else
+ Q_UNUSED(e);
+#endif
+
+ return false;
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QLineEditPrivate::drag()
+{
+ Q_Q(QLineEdit);
+ dndTimer.stop();
+ QMimeData *data = new QMimeData;
+ data->setText(control->selectedText());
+ QDrag *drag = new QDrag(q);
+ drag->setMimeData(data);
+ Qt::DropAction action = drag->start();
+ if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q)
+ control->removeSelection();
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h
index 7a4ff26..230023d 100644
--- a/src/gui/widgets/qlineedit_p.h
+++ b/src/gui/widgets/qlineedit_p.h
@@ -65,6 +65,8 @@
#include "QtCore/qpointer.h"
#include "QtGui/qlineedit.h"
+#include "private/qlinecontrol_p.h"
+
QT_BEGIN_NAMESPACE
class QLineEditPrivate : public QWidgetPrivate
@@ -73,167 +75,64 @@ class QLineEditPrivate : public QWidgetPrivate
public:
QLineEditPrivate()
- : cursor(0), preeditCursor(0), cursorTimer(0), frame(1),
- cursorVisible(0), hideCursor(false), separator(0), readOnly(0),
- dragEnabled(0), contextMenuEnabled(1), echoMode(0), textDirty(0),
- selDirty(0), validInput(1), alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0),
- maxLength(32767), hscroll(0), vscroll(0), lastCursorPos(-1), maskData(0),
- modifiedState(0), undoState(0), selstart(0), selend(0), userInput(false),
- emitingEditingFinished(false), passwordEchoEditing(false)
-#ifndef QT_NO_COMPLETER
- , completer(0)
-#endif
- , leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0)
- {
- }
+ : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0),
+ dragEnabled(0), hscroll(0), vscroll(0),
+ alignment(Qt::AlignLeading | Qt::AlignVCenter),
+ leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0)
+ {
+ }
~QLineEditPrivate()
{
- delete [] maskData;
}
+
+ QLineControl *control;
+
+#ifndef QT_NO_CONTEXTMENU
+ QPointer<QAction> selectAllAction;
+#endif
void init(const QString&);
- QString text;
- int cursor;
- int preeditCursor;
- int cursorTimer; // -1 for non blinking cursor.
+ int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
+ QRect cursorRect() const;
+ void setCursorVisible(bool visible);
+
+ void updatePasswordEchoEditing(bool);
+
+ inline bool shouldEnableInputMethod() const
+ {
+ return !control->isReadOnly() && (control->echoMode() == QLineEdit::Normal || control->echoMode() == QLineEdit::PasswordEchoOnEdit);
+ }
+
QPoint tripleClick;
QBasicTimer tripleClickTimer;
uint frame : 1;
+ uint contextMenuEnabled : 1;
uint cursorVisible : 1;
- uint hideCursor : 1; // used to hide the cursor inside preedit areas
- uint separator : 1;
- uint readOnly : 1;
uint dragEnabled : 1;
- uint contextMenuEnabled : 1;
- uint echoMode : 2;
- uint textDirty : 1;
- uint selDirty : 1;
- uint validInput : 1;
- uint alignment;
- int ascent;
- int maxLength;
int hscroll;
int vscroll;
- int lastCursorPos;
-
-#ifndef QT_NO_CONTEXTMENU
- QPointer<QAction> selectAllAction;
-#endif
+ uint alignment;
+ static const int verticalMargin;
+ static const int horizontalMargin;
- inline void emitCursorPositionChanged();
bool sendMouseEventToInputContext(QMouseEvent *e);
- void finishChange(int validateFromState = -1, bool update = false, bool edited = true);
-
- QPointer<QValidator> validator;
- struct MaskInputData {
- enum Casemode { NoCaseMode, Upper, Lower };
- QChar maskChar; // either the separator char or the inputmask
- bool separator;
- Casemode caseMode;
- };
- QString inputMask;
- QChar blank;
- MaskInputData *maskData;
- inline int nextMaskBlank(int pos) {
- int c = findInMask(pos, true, false);
- separator |= (c != pos);
- return (c != -1 ? c : maxLength);
- }
- inline int prevMaskBlank(int pos) {
- int c = findInMask(pos, false, false);
- separator |= (c != pos);
- return (c != -1 ? c : 0);
- }
-
- void setCursorVisible(bool visible);
-
-
- // undo/redo handling
- enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
- struct Command {
- inline Command() {}
- inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
- uint type : 4;
- QChar uc;
- int pos, selStart, selEnd;
- };
- int modifiedState;
- int undoState;
- QVector<Command> history;
- void addCommand(const Command& cmd);
- void insert(const QString& s);
- void del(bool wasBackspace = false);
- void remove(int pos);
-
- inline void separate() { separator = true; }
- void undo(int until = -1);
- void redo();
- inline bool isUndoAvailable() const { return !readOnly && undoState; }
- inline bool isRedoAvailable() const { return !readOnly && undoState < (int)history.size(); }
-
- // selection
- int selstart, selend;
- inline bool allSelected() const { return !text.isEmpty() && selstart == 0 && selend == (int)text.length(); }
- inline bool hasSelectedText() const { return !text.isEmpty() && selend > selstart; }
- inline void deselect() { selDirty |= (selend > selstart); selstart = selend = 0; }
- void removeSelectedText();
-#ifndef QT_NO_CLIPBOARD
- void copy(bool clipboard = true) const;
-#endif
- inline bool inSelection(int x) const
- { if (selstart >= selend) return false;
- int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; }
-
- // masking
- void parseInputMask(const QString &maskFields);
- bool isValidInput(QChar key, QChar mask) const;
- bool hasAcceptableInput(const QString &text) const;
- QString maskString(uint pos, const QString &str, bool clear = false) const;
- QString clearString(uint pos, uint len) const;
- QString stripString(const QString &str) const;
- int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
-
- // input methods
- bool composeMode() const { return !textLayout.preeditAreaText().isEmpty(); }
-
- // complex text layout
- QTextLayout textLayout;
- void updateTextLayout();
- void moveCursor(int pos, bool mark = false);
- void setText(const QString& txt, int pos = -1, bool edited = true);
- int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
- QRect cursorRect() const;
- bool fixup();
-
QRect adjustedContentsRect() const;
-#ifndef QT_NO_DRAGANDDROP
- // drag and drop
- QPoint dndPos;
- QBasicTimer dndTimer;
- void drag();
-#endif
-
+ void _q_clipboardChanged();
void _q_handleWindowActivate();
void _q_deleteSelected();
- bool userInput;
- bool emitingEditingFinished;
-
-#ifdef QT_KEYPAD_NAVIGATION
- QBasicTimer deleteAllTimer; // keypad navigation
- QString origText;
-#endif
-
- bool passwordEchoEditing;
- void updatePasswordEchoEditing(bool editing);
+ void _q_textEdited(const QString &);
+ void _q_cursorPositionChanged(int, int);
#ifndef QT_NO_COMPLETER
- QPointer<QCompleter> completer;
- void complete(int key = -1);
void _q_completionHighlighted(QString);
- bool advanceToEnabledItem(int n);
+#endif
+#ifndef QT_NO_DRAGANDDROP
+ QPoint dndPos;
+ QBasicTimer dndTimer;
+ void drag();
#endif
int leftTextMargin;
diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h
index ce78959..5c27d1d 100644
--- a/src/gui/widgets/qvalidator.h
+++ b/src/gui/widgets/qvalidator.h
@@ -61,7 +61,7 @@ class Q_GUI_EXPORT QValidator : public QObject
{
Q_OBJECT
public:
- explicit QValidator(QObject * parent);
+ explicit QValidator(QObject * parent=0);
~QValidator();
enum State {
@@ -100,7 +100,7 @@ class Q_GUI_EXPORT QIntValidator : public QValidator
Q_PROPERTY(int top READ top WRITE setTop)
public:
- explicit QIntValidator(QObject * parent);
+ explicit QIntValidator(QObject * parent=0);
QIntValidator(int bottom, int top, QObject * parent);
~QIntValidator();
diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri
index 2d809a1..8f24fac 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -30,6 +30,7 @@ HEADERS += \
widgets/qlcdnumber.h \
widgets/qlineedit.h \
widgets/qlineedit_p.h \
+ widgets/qlinecontrol_p.h \
widgets/qmainwindow.h \
widgets/qmainwindowlayout_p.h \
widgets/qmdiarea.h \
@@ -101,7 +102,9 @@ SOURCES += \
widgets/qgroupbox.cpp \
widgets/qlabel.cpp \
widgets/qlcdnumber.cpp \
+ widgets/qlineedit_p.cpp \
widgets/qlineedit.cpp \
+ widgets/qlinecontrol.cpp \
widgets/qmainwindow.cpp \
widgets/qmainwindowlayout.cpp \
widgets/qmdiarea.cpp \