~ubuntu-branches/ubuntu/precise/qt4-x11/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/kubuntu_97_a11y_qt_and_qml_backport.diff/src/gui/widgets/qlinecontrol.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell, Jonathan Riddell, Felix Geyer
  • Date: 2011-11-01 16:23:55 UTC
  • mfrom: (15.3.22 sid)
  • Revision ID: package-import@ubuntu.com-20111101162355-4dhsj6563ii8enl6
Tags: 4:4.7.4-1ubuntu1
[ Jonathan Riddell ]
* Merge from Debian Git packaging.  Remaining Ubuntu changes:
  - Do not package ibase/firebird package, remove from debian/rules and
    debian/control
  - libqt4-sql-ibase not recommend for libqt4-sql
  - build with -no-phonon
  - do not build libqt4-phonon, disable in debian/control
  - Build packages with lzma compression using the dh addon from pkg-kde-tools
  - Rules to remove po dir in clean
  - Add MessagesQt.sh
  - Rules to create Messages.sh link to MessagesQt.sh and rules to create po
    dir and exectue extract-messages.sh in common-install-prehook-impl
  - Make libqt4-dev depend on libx11-dev
  - Add and install Trolltech.conf in libqtcore4.install
  - Build QtWebkit and use it only for QtAssistant
    + Rule to put qt_webkit_version.pri in mkspecs/modules
    + Rule to remove libQtWebKit* after build
    + Exclude usr/bin/assistant-qt4 from dh_shlibdeps
  - Fix Lucid upgrades: libqt4-help breaks/replaces libqtcore4 (<< 4:4.7.0)
  - Change OpenGL backend from GL to GLES 2 for armel (Debian does this for
    armhf)
    + Build-depend and make libqt4-opengl-dev depend on libgles2-mesa-dev
      instead of libgl1-mesa-dev and libglu1-mesa-dev
    + Pass "-opengl es2" to configure
  - Pass extra_configure_opts += -arch armv6 on both armel and armhf and not
    just armhf
  - In debian/rules Move documentation building to override_dh_auto_install where
    dh_listpackages works as expected with dpkg-buildpackage. (LP: #857377)
  - debian/compat is 9 and build-depend on newer debhelper for multiarch
* debian/patches/blacklist-diginotar-certs.diff is now
  debian/patches/blacklist-diginotar-cert.diff to match Debian
* Add prefix to some patches to clarify they come from Ubuntu rather than Debian
 - kubuntu_97_a11y_qt_and_qml_backport.diff
 - kubuntu_98_fix_accessible_menu.diff
 - kubuntu_99_notify_qml_name_description_change.diff

[ Felix Geyer ]
* Use DEB_*_MAINT_APPEND instead of setting CXXFLAGS and LDFLAGS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
 
5
** Contact: Nokia Corporation (qt-info@nokia.com)
 
6
**
 
7
** This file is part of the QtGui module of the Qt Toolkit.
 
8
**
 
9
** $QT_BEGIN_LICENSE:LGPL$
 
10
** GNU Lesser General Public License Usage
 
11
** This file may be used under the terms of the GNU Lesser General Public
 
12
** License version 2.1 as published by the Free Software Foundation and
 
13
** appearing in the file LICENSE.LGPL included in the packaging of this
 
14
** file. Please review the following information to ensure the GNU Lesser
 
15
** General Public License version 2.1 requirements will be met:
 
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
17
**
 
18
** In addition, as a special exception, Nokia gives you certain additional
 
19
** rights. These rights are described in the Nokia Qt LGPL Exception
 
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
21
**
 
22
** GNU General Public License Usage
 
23
** Alternatively, this file may be used under the terms of the GNU General
 
24
** Public License version 3.0 as published by the Free Software Foundation
 
25
** and appearing in the file LICENSE.GPL included in the packaging of this
 
26
** file. Please review the following information to ensure the GNU General
 
27
** Public License version 3.0 requirements will be met:
 
28
** http://www.gnu.org/copyleft/gpl.html.
 
29
**
 
30
** Other Usage
 
31
** Alternatively, this file may be used in accordance with the terms and
 
32
** conditions contained in a signed written agreement between you and Nokia.
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qlinecontrol_p.h"
 
43
 
 
44
#ifndef QT_NO_LINEEDIT
 
45
 
 
46
#include "qabstractitemview.h"
 
47
#include "qclipboard.h"
 
48
#ifndef QT_NO_ACCESSIBILITY
 
49
#include "qaccessible.h"
 
50
#endif
 
51
#ifndef QT_NO_IM
 
52
#include "qinputcontext.h"
 
53
#include "qlist.h"
 
54
#endif
 
55
#include "qapplication.h"
 
56
#ifndef QT_NO_GRAPHICSVIEW
 
57
#include "qgraphicssceneevent.h"
 
58
#endif
 
59
 
 
60
QT_BEGIN_NAMESPACE
 
61
 
 
62
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
 
63
static const int qt_passwordEchoDelay = QT_GUI_PASSWORD_ECHO_DELAY;
 
64
#endif
 
65
 
 
66
/*!
 
67
    \macro QT_GUI_PASSWORD_ECHO_DELAY
 
68
 
 
69
    \internal
 
70
 
 
71
    Defines the amount of time in milliseconds the last entered character
 
72
    should be displayed unmasked in the Password echo mode.
 
73
 
 
74
    If not defined in qplatformdefs.h there will be no delay in masking
 
75
    password characters.
 
76
*/
 
77
 
 
78
/*!
 
79
    \internal
 
80
 
 
81
    Updates the display text based of the current edit text
 
82
    If the text has changed will emit displayTextChanged()
 
83
*/
 
84
void QLineControl::updateDisplayText(bool forceUpdate)
 
85
{
 
86
    QString orig = m_textLayout.text();
 
87
    QString str;
 
88
    if (m_echoMode == QLineEdit::NoEcho)
 
89
        str = QString::fromLatin1("");
 
90
    else
 
91
        str = m_text;
 
92
 
 
93
    if (m_echoMode == QLineEdit::Password) {
 
94
        str.fill(m_passwordCharacter);
 
95
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
 
96
        if (m_passwordEchoTimer != 0 && m_cursor > 0 && m_cursor <= m_text.length()) {
 
97
            int cursor = m_cursor - 1;
 
98
            QChar uc = m_text.at(cursor);
 
99
            str[cursor] = uc;
 
100
            if (cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
 
101
                // second half of a surrogate, check if we have the first half as well,
 
102
                // if yes restore both at once
 
103
                uc = m_text.at(cursor - 1);
 
104
                if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00)
 
105
                    str[cursor - 1] = uc;
 
106
            }
 
107
        }
 
108
#endif
 
109
    } else if (m_echoMode == QLineEdit::PasswordEchoOnEdit && !m_passwordEchoEditing) {
 
110
        str.fill(m_passwordCharacter);
 
111
    }
 
112
 
 
113
    // replace certain non-printable characters with spaces (to avoid
 
114
    // drawing boxes when using fonts that don't have glyphs for such
 
115
    // characters)
 
116
    QChar* uc = str.data();
 
117
    for (int i = 0; i < (int)str.length(); ++i) {
 
118
        if ((uc[i] < 0x20 && uc[i] != 0x09)
 
119
            || uc[i] == QChar::LineSeparator
 
120
            || uc[i] == QChar::ParagraphSeparator
 
121
            || uc[i] == QChar::ObjectReplacementCharacter)
 
122
            uc[i] = QChar(0x0020);
 
123
    }
 
124
 
 
125
    m_textLayout.setText(str);
 
126
 
 
127
    QTextOption option;
 
128
    option.setTextDirection(m_layoutDirection);
 
129
    option.setFlags(QTextOption::IncludeTrailingSpaces);
 
130
    m_textLayout.setTextOption(option);
 
131
 
 
132
    m_textLayout.beginLayout();
 
133
    QTextLine l = m_textLayout.createLine();
 
134
    m_textLayout.endLayout();
 
135
    m_ascent = qRound(l.ascent());
 
136
 
 
137
    if (str != orig || forceUpdate)
 
138
        emit displayTextChanged(str);
 
139
}
 
140
 
 
141
#ifndef QT_NO_CLIPBOARD
 
142
/*!
 
143
    \internal
 
144
 
 
145
    Copies the currently selected text into the clipboard using the given
 
146
    \a mode.
 
147
  
 
148
    \note If the echo mode is set to a mode other than Normal then copy
 
149
    will not work.  This is to prevent using copy as a method of bypassing
 
150
    password features of the line control.
 
151
*/
 
152
void QLineControl::copy(QClipboard::Mode mode) const
 
153
{
 
154
    QString t = selectedText();
 
155
    if (!t.isEmpty() && m_echoMode == QLineEdit::Normal) {
 
156
        disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
 
157
        QApplication::clipboard()->setText(t, mode);
 
158
        connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
 
159
                   this, SLOT(_q_clipboardChanged()));
 
160
    }
 
161
}
 
162
 
 
163
/*!
 
164
    \internal
 
165
 
 
166
    Inserts the text stored in the application clipboard into the line
 
167
    control.
 
168
 
 
169
    \sa insert()
 
170
*/
 
171
void QLineControl::paste(QClipboard::Mode clipboardMode)
 
172
{
 
173
    QString clip = QApplication::clipboard()->text(clipboardMode);
 
174
    if (!clip.isEmpty() || hasSelectedText()) {
 
175
        separate(); //make it a separate undo/redo command
 
176
        insert(clip);
 
177
        separate();
 
178
    }
 
179
}
 
180
 
 
181
#endif // !QT_NO_CLIPBOARD
 
182
 
 
183
/*!
 
184
    \internal
 
185
 
 
186
    Handles the behavior for the backspace key or function.
 
187
    Removes the current selection if there is a selection, otherwise
 
188
    removes the character prior to the cursor position.
 
189
 
 
190
    \sa del()
 
191
*/
 
192
void QLineControl::backspace()
 
193
{
 
194
    int priorState = m_undoState;
 
195
    if (hasSelectedText()) {
 
196
        removeSelectedText();
 
197
    } else if (m_cursor) {
 
198
            --m_cursor;
 
199
            if (m_maskData)
 
200
                m_cursor = prevMaskBlank(m_cursor);
 
201
            QChar uc = m_text.at(m_cursor);
 
202
            if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
 
203
                // second half of a surrogate, check if we have the first half as well,
 
204
                // if yes delete both at once
 
205
                uc = m_text.at(m_cursor - 1);
 
206
                if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
 
207
                    internalDelete(true);
 
208
                    --m_cursor;
 
209
                }
 
210
            }
 
211
            internalDelete(true);
 
212
    }
 
213
    finishChange(priorState);
 
214
}
 
215
 
 
216
/*!
 
217
    \internal
 
218
 
 
219
    Handles the behavior for the delete key or function.
 
220
    Removes the current selection if there is a selection, otherwise
 
221
    removes the character after the cursor position.
 
222
 
 
223
    \sa del()
 
224
*/
 
225
void QLineControl::del()
 
226
{
 
227
    int priorState = m_undoState;
 
228
    if (hasSelectedText()) {
 
229
        removeSelectedText();
 
230
    } else {
 
231
        int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
 
232
        while (n--)
 
233
            internalDelete();
 
234
    }
 
235
    finishChange(priorState);
 
236
}
 
237
 
 
238
/*!
 
239
    \internal
 
240
 
 
241
    Inserts the given \a newText at the current cursor position.
 
242
    If there is any selected text it is removed prior to insertion of
 
243
    the new text.
 
244
*/
 
245
void QLineControl::insert(const QString &newText)
 
246
{
 
247
    int priorState = m_undoState;
 
248
    removeSelectedText();
 
249
    internalInsert(newText);
 
250
    finishChange(priorState);
 
251
}
 
252
 
 
253
/*!
 
254
    \internal
 
255
 
 
256
    Clears the line control text.
 
257
*/
 
258
void QLineControl::clear()
 
259
{
 
260
    int priorState = m_undoState;
 
261
    m_selstart = 0;
 
262
    m_selend = m_text.length();
 
263
    removeSelectedText();
 
264
    separate();
 
265
    finishChange(priorState, /*update*/false, /*edited*/false);
 
266
}
 
267
 
 
268
/*!
 
269
    \internal
 
270
 
 
271
    Sets \a length characters from the given \a start position as selected.
 
272
    The given \a start position must be within the current text for
 
273
    the line control.  If \a length characters cannot be selected, then
 
274
    the selection will extend to the end of the current text.
 
275
*/
 
276
void QLineControl::setSelection(int start, int length)
 
277
{
 
278
    if(start < 0 || start > (int)m_text.length()){
 
279
        qWarning("QLineControl::setSelection: Invalid start position");
 
280
        return;
 
281
    }
 
282
 
 
283
    if (length > 0) {
 
284
        if (start == m_selstart && start + length == m_selend)
 
285
            return;
 
286
        m_selstart = start;
 
287
        m_selend = qMin(start + length, (int)m_text.length());
 
288
        m_cursor = m_selend;
 
289
    } else if (length < 0){
 
290
        if (start == m_selend && start + length == m_selstart)
 
291
            return;
 
292
        m_selstart = qMax(start + length, 0);
 
293
        m_selend = start;
 
294
        m_cursor = m_selstart;
 
295
    } else if (m_selstart != m_selend) {
 
296
        m_selstart = 0;
 
297
        m_selend = 0;
 
298
        m_cursor = start;
 
299
    } else {
 
300
        m_cursor = start;
 
301
        emitCursorPositionChanged();
 
302
        return;
 
303
    }
 
304
    emit selectionChanged();
 
305
    emitCursorPositionChanged();
 
306
}
 
307
 
 
308
void QLineControl::_q_clipboardChanged()
 
309
{
 
310
}
 
311
 
 
312
void QLineControl::_q_deleteSelected()
 
313
{
 
314
    if (!hasSelectedText())
 
315
        return;
 
316
 
 
317
    int priorState = m_undoState;
 
318
    emit resetInputContext();
 
319
    removeSelectedText();
 
320
    separate();
 
321
    finishChange(priorState);
 
322
}
 
323
 
 
324
/*!
 
325
    \internal
 
326
 
 
327
    Initializes the line control with a starting text value of \a txt.
 
328
*/
 
329
void QLineControl::init(const QString &txt)
 
330
{
 
331
    m_text = txt;
 
332
    updateDisplayText();
 
333
    m_cursor = m_text.length();
 
334
}
 
335
 
 
336
/*!
 
337
    \internal
 
338
 
 
339
    Sets the password echo editing to \a editing.  If password echo editing
 
340
    is true, then the text of the password is displayed even if the echo
 
341
    mode is set to QLineEdit::PasswordEchoOnEdit.  Password echoing editing
 
342
    does not affect other echo modes.
 
343
*/
 
344
void QLineControl::updatePasswordEchoEditing(bool editing)
 
345
{
 
346
    cancelPasswordEchoTimer();
 
347
    m_passwordEchoEditing = editing;
 
348
    updateDisplayText();
 
349
}
 
350
 
 
351
/*!
 
352
    \internal
 
353
 
 
354
    Returns the cursor position of the given \a x pixel value in relation
 
355
    to the displayed text.  The given \a betweenOrOn specified what kind
 
356
    of cursor position is requested.
 
357
*/
 
358
int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
 
359
{
 
360
    return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
 
361
}
 
362
 
 
363
/*!
 
364
    \internal
 
365
 
 
366
    Returns the bounds of the current cursor, as defined as a
 
367
    between characters cursor.
 
368
*/
 
369
QRect QLineControl::cursorRect() const
 
370
{
 
371
    QTextLine l = m_textLayout.lineAt(0);
 
372
    int c = m_cursor;
 
373
    if (m_preeditCursor != -1)
 
374
        c += m_preeditCursor;
 
375
    int cix = qRound(l.cursorToX(c));
 
376
    int w = m_cursorWidth;
 
377
    int ch = l.height() + 1;
 
378
 
 
379
    return QRect(cix-5, 0, w+9, ch);
 
380
}
 
381
 
 
382
/*!
 
383
    \internal
 
384
 
 
385
    Fixes the current text so that it is valid given any set validators.
 
386
 
 
387
    Returns true if the text was changed.  Otherwise returns false.
 
388
*/
 
389
bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable
 
390
{
 
391
#ifndef QT_NO_VALIDATOR
 
392
    if (m_validator) {
 
393
        QString textCopy = m_text;
 
394
        int cursorCopy = m_cursor;
 
395
        m_validator->fixup(textCopy);
 
396
        if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
 
397
            if (textCopy != m_text || cursorCopy != m_cursor)
 
398
                internalSetText(textCopy, cursorCopy);
 
399
            return true;
 
400
        }
 
401
    }
 
402
#endif
 
403
    return false;
 
404
}
 
405
 
 
406
/*!
 
407
    \internal
 
408
 
 
409
    Moves the cursor to the given position \a pos.   If \a mark is true will
 
410
    adjust the currently selected text.
 
411
*/
 
412
void QLineControl::moveCursor(int pos, bool mark)
 
413
{
 
414
    if (pos != m_cursor) {
 
415
        separate();
 
416
        if (m_maskData)
 
417
            pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
 
418
    }
 
419
    if (mark) {
 
420
        int anchor;
 
421
        if (m_selend > m_selstart && m_cursor == m_selstart)
 
422
            anchor = m_selend;
 
423
        else if (m_selend > m_selstart && m_cursor == m_selend)
 
424
            anchor = m_selstart;
 
425
        else
 
426
            anchor = m_cursor;
 
427
        m_selstart = qMin(anchor, pos);
 
428
        m_selend = qMax(anchor, pos);
 
429
        updateDisplayText();
 
430
    } else {
 
431
        internalDeselect();
 
432
    }
 
433
    m_cursor = pos;
 
434
    if (mark || m_selDirty) {
 
435
        m_selDirty = false;
 
436
        emit selectionChanged();
 
437
    }
 
438
    emitCursorPositionChanged();
 
439
}
 
440
 
 
441
/*!
 
442
    \internal
 
443
 
 
444
    Applies the given input method event \a event to the text of the line
 
445
    control
 
446
*/
 
447
void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
 
448
{
 
449
    int priorState = 0;
 
450
    bool isGettingInput = !event->commitString().isEmpty()
 
451
            || event->preeditString() != preeditAreaText()
 
452
            || event->replacementLength() > 0;
 
453
    bool cursorPositionChanged = false;
 
454
 
 
455
    if (isGettingInput) {
 
456
        // If any text is being input, remove selected text.
 
457
        priorState = m_undoState;
 
458
        if (echoMode() == QLineEdit::PasswordEchoOnEdit && !passwordEchoEditing()) {
 
459
            updatePasswordEchoEditing(true);
 
460
            m_selstart = 0;
 
461
            m_selend = m_text.length();
 
462
        }
 
463
        removeSelectedText();
 
464
    }
 
465
 
 
466
    int c = m_cursor; // cursor position after insertion of commit string
 
467
    if (event->replacementStart() <= 0)
 
468
        c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength());
 
469
 
 
470
    m_cursor += event->replacementStart();
 
471
    if (m_cursor < 0)
 
472
        m_cursor = 0;
 
473
 
 
474
    // insert commit string
 
475
    if (event->replacementLength()) {
 
476
        m_selstart = m_cursor;
 
477
        m_selend = m_selstart + event->replacementLength();
 
478
        removeSelectedText();
 
479
    }
 
480
    if (!event->commitString().isEmpty()) {
 
481
        internalInsert(event->commitString());
 
482
        cursorPositionChanged = true;
 
483
    }
 
484
 
 
485
    m_cursor = qBound(0, c, m_text.length());
 
486
 
 
487
    for (int i = 0; i < event->attributes().size(); ++i) {
 
488
        const QInputMethodEvent::Attribute &a = event->attributes().at(i);
 
489
        if (a.type == QInputMethodEvent::Selection) {
 
490
            m_cursor = qBound(0, a.start + a.length, m_text.length());
 
491
            if (a.length) {
 
492
                m_selstart = qMax(0, qMin(a.start, m_text.length()));
 
493
                m_selend = m_cursor;
 
494
                if (m_selend < m_selstart) {
 
495
                    qSwap(m_selstart, m_selend);
 
496
                }
 
497
            } else {
 
498
                m_selstart = m_selend = 0;
 
499
            }
 
500
            cursorPositionChanged = true;
 
501
        }
 
502
    }
 
503
#ifndef QT_NO_IM
 
504
    setPreeditArea(m_cursor, event->preeditString());
 
505
#endif //QT_NO_IM
 
506
    const int oldPreeditCursor = m_preeditCursor;
 
507
    m_preeditCursor = event->preeditString().length();
 
508
    m_hideCursor = false;
 
509
    QList<QTextLayout::FormatRange> formats;
 
510
    for (int i = 0; i < event->attributes().size(); ++i) {
 
511
        const QInputMethodEvent::Attribute &a = event->attributes().at(i);
 
512
        if (a.type == QInputMethodEvent::Cursor) {
 
513
            m_preeditCursor = a.start;
 
514
            m_hideCursor = !a.length;
 
515
        } else if (a.type == QInputMethodEvent::TextFormat) {
 
516
            QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
 
517
            if (f.isValid()) {
 
518
                QTextLayout::FormatRange o;
 
519
                o.start = a.start + m_cursor;
 
520
                o.length = a.length;
 
521
                o.format = f;
 
522
                formats.append(o);
 
523
            }
 
524
        }
 
525
    }
 
526
    m_textLayout.setAdditionalFormats(formats);
 
527
    updateDisplayText(/*force*/ true);
 
528
    if (cursorPositionChanged)
 
529
        emitCursorPositionChanged();
 
530
    else if (m_preeditCursor != oldPreeditCursor)
 
531
        emit updateMicroFocus();
 
532
    if (isGettingInput)
 
533
        finishChange(priorState);
 
534
}
 
535
 
 
536
/*!
 
537
    \internal
 
538
 
 
539
    Draws the display text for the line control using the given 
 
540
    \a painter, \a clip, and \a offset.  Which aspects of the display text
 
541
    are drawn is specified by the given \a flags.
 
542
 
 
543
    If the flags contain DrawSelections, then the selection or input mask
 
544
    backgrounds and foregrounds will be applied before drawing the text.
 
545
 
 
546
    If the flags contain DrawCursor a cursor of the current cursorWidth()
 
547
    will be drawn after drawing the text.
 
548
 
 
549
    The display text will only be drawn if the flags contain DrawText
 
550
*/
 
551
void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags)
 
552
{
 
553
    QVector<QTextLayout::FormatRange> selections;
 
554
    if (flags & DrawSelections) {
 
555
        QTextLayout::FormatRange o;
 
556
        if (m_selstart < m_selend) {
 
557
            o.start = m_selstart;
 
558
            o.length = m_selend - m_selstart;
 
559
            o.format.setBackground(m_palette.brush(QPalette::Highlight));
 
560
            o.format.setForeground(m_palette.brush(QPalette::HighlightedText));
 
561
        } else {
 
562
            // mask selection
 
563
            if(!m_blinkPeriod || m_blinkStatus){
 
564
                o.start = m_cursor;
 
565
                o.length = 1;
 
566
                o.format.setBackground(m_palette.brush(QPalette::Text));
 
567
                o.format.setForeground(m_palette.brush(QPalette::Window));
 
568
            }
 
569
        }
 
570
        selections.append(o);
 
571
    }
 
572
 
 
573
    if (flags & DrawText)
 
574
        m_textLayout.draw(painter, offset, selections, clip);
 
575
 
 
576
    if (flags & DrawCursor){
 
577
        int cursor = m_cursor;
 
578
        if (m_preeditCursor != -1)
 
579
            cursor += m_preeditCursor;
 
580
        if (!m_hideCursor && (!m_blinkPeriod || m_blinkStatus))
 
581
            m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth);
 
582
    }
 
583
}
 
584
 
 
585
/*!
 
586
    \internal
 
587
 
 
588
    Sets the selection to cover the word at the given cursor position.
 
589
    The word boundaries are defined by the behavior of QTextLayout::SkipWords
 
590
    cursor mode.
 
591
*/
 
592
void QLineControl::selectWordAtPos(int cursor)
 
593
{
 
594
    int next = cursor + 1;
 
595
    if(next > end())
 
596
        --next;
 
597
    int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords);
 
598
    moveCursor(c, false);
 
599
    // ## text layout should support end of words.
 
600
    int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords);
 
601
    while (end > cursor && m_text[end-1].isSpace())
 
602
        --end;
 
603
    moveCursor(end, true);
 
604
}
 
605
 
 
606
/*!
 
607
    \internal
 
608
 
 
609
    Completes a change to the line control text.  If the change is not valid
 
610
    will undo the line control state back to the given \a validateFromState.
 
611
 
 
612
    If \a edited is true and the change is valid, will emit textEdited() in
 
613
    addition to textChanged().  Otherwise only emits textChanged() on a valid
 
614
    change.
 
615
 
 
616
    The \a update value is currently unused.
 
617
*/
 
618
bool QLineControl::finishChange(int validateFromState, bool update, bool edited)
 
619
{
 
620
    Q_UNUSED(update)
 
621
    bool lineDirty = m_selDirty;
 
622
    if (m_textDirty) {
 
623
        // do validation
 
624
        bool wasValidInput = m_validInput;
 
625
        m_validInput = true;
 
626
#ifndef QT_NO_VALIDATOR
 
627
        if (m_validator) {
 
628
            m_validInput = false;
 
629
            QString textCopy = m_text;
 
630
            int cursorCopy = m_cursor;
 
631
            m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
 
632
            if (m_validInput) {
 
633
                if (m_text != textCopy) {
 
634
                    internalSetText(textCopy, cursorCopy);
 
635
                    return true;
 
636
                }
 
637
                m_cursor = cursorCopy;
 
638
            }
 
639
        }
 
640
#endif
 
641
        if (validateFromState >= 0 && wasValidInput && !m_validInput) {
 
642
            if (m_transactions.count())
 
643
                return false;
 
644
            internalUndo(validateFromState);
 
645
            m_history.resize(m_undoState);
 
646
            if (m_modifiedState > m_undoState)
 
647
                m_modifiedState = -1;
 
648
            m_validInput = true;
 
649
            m_textDirty = false;
 
650
        }
 
651
        updateDisplayText();
 
652
        lineDirty |= m_textDirty;
 
653
        if (m_textDirty) {
 
654
            m_textDirty = false;
 
655
            QString actualText = text();
 
656
            if (edited)
 
657
                emit textEdited(actualText);
 
658
            emit textChanged(actualText);
 
659
        }
 
660
    }
 
661
    if (m_selDirty) {
 
662
        m_selDirty = false;
 
663
        emit selectionChanged();
 
664
    }
 
665
    emitCursorPositionChanged();
 
666
    return true;
 
667
}
 
668
 
 
669
/*!
 
670
    \internal
 
671
 
 
672
    An internal function for setting the text of the line control.
 
673
*/
 
674
void QLineControl::internalSetText(const QString &txt, int pos, bool edited)
 
675
{
 
676
    cancelPasswordEchoTimer();
 
677
    internalDeselect();
 
678
    emit resetInputContext();
 
679
    QString oldText = m_text;
 
680
    if (m_maskData) {
 
681
        m_text = maskString(0, txt, true);
 
682
        m_text += clearString(m_text.length(), m_maxLength - m_text.length());
 
683
    } else {
 
684
        m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
 
685
    }
 
686
    m_history.clear();
 
687
    m_modifiedState =  m_undoState = 0;
 
688
    m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
 
689
    m_textDirty = (oldText != m_text);
 
690
    finishChange(-1, true, edited);
 
691
}
 
692
 
 
693
 
 
694
/*!
 
695
    \internal
 
696
 
 
697
    Adds the given \a command to the undo history
 
698
    of the line control.  Does not apply the command.
 
699
*/
 
700
void QLineControl::addCommand(const Command &cmd)
 
701
{
 
702
    if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) {
 
703
        m_history.resize(m_undoState + 2);
 
704
        m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend);
 
705
    } else {
 
706
        m_history.resize(m_undoState + 1);
 
707
    }
 
708
    m_separator = false;
 
709
    m_history[m_undoState++] = cmd;
 
710
}
 
711
 
 
712
/*!
 
713
    \internal
 
714
 
 
715
    Inserts the given string \a s into the line
 
716
    control.
 
717
 
 
718
    Also adds the appropriate commands into the undo history.
 
719
    This function does not call finishChange(), and may leave the text
 
720
    in an invalid state.
 
721
*/
 
722
void QLineControl::internalInsert(const QString &s)
 
723
{
 
724
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
 
725
    if (m_echoMode == QLineEdit::Password) {
 
726
        if (m_passwordEchoTimer != 0)
 
727
            killTimer(m_passwordEchoTimer);
 
728
        m_passwordEchoTimer = startTimer(qt_passwordEchoDelay);
 
729
    }
 
730
#endif
 
731
    if (hasSelectedText())
 
732
        addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
 
733
    if (m_maskData) {
 
734
        QString ms = maskString(m_cursor, s);
 
735
        for (int i = 0; i < (int) ms.length(); ++i) {
 
736
            addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
 
737
            addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
 
738
        }
 
739
        m_text.replace(m_cursor, ms.length(), ms);
 
740
        m_cursor += ms.length();
 
741
        m_cursor = nextMaskBlank(m_cursor);
 
742
        m_textDirty = true;
 
743
    } else {
 
744
        int remaining = m_maxLength - m_text.length();
 
745
        if (remaining != 0) {
 
746
            m_text.insert(m_cursor, s.left(remaining));
 
747
            for (int i = 0; i < (int) s.left(remaining).length(); ++i)
 
748
               addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
 
749
            m_textDirty = true;
 
750
        }
 
751
    }
 
752
}
 
753
 
 
754
/*!
 
755
    \internal
 
756
 
 
757
    deletes a single character from the current text.  If \a wasBackspace,
 
758
    the character prior to the cursor is removed.  Otherwise the character
 
759
    after the cursor is removed.
 
760
 
 
761
    Also adds the appropriate commands into the undo history.
 
762
    This function does not call finishChange(), and may leave the text
 
763
    in an invalid state.
 
764
*/
 
765
void QLineControl::internalDelete(bool wasBackspace)
 
766
{
 
767
    if (m_cursor < (int) m_text.length()) {
 
768
        cancelPasswordEchoTimer();
 
769
        if (hasSelectedText())
 
770
            addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
 
771
        addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
 
772
                   m_cursor, m_text.at(m_cursor), -1, -1));
 
773
        if (m_maskData) {
 
774
            m_text.replace(m_cursor, 1, clearString(m_cursor, 1));
 
775
            addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1));
 
776
        } else {
 
777
            m_text.remove(m_cursor, 1);
 
778
        }
 
779
        m_textDirty = true;
 
780
    }
 
781
}
 
782
 
 
783
/*!
 
784
    \internal
 
785
 
 
786
    removes the currently selected text from the line control.
 
787
 
 
788
    Also adds the appropriate commands into the undo history.
 
789
    This function does not call finishChange(), and may leave the text
 
790
    in an invalid state.
 
791
*/
 
792
void QLineControl::removeSelectedText()
 
793
{
 
794
    if (m_selstart < m_selend && m_selend <= (int) m_text.length()) {
 
795
        cancelPasswordEchoTimer();
 
796
        separate();
 
797
        int i ;
 
798
        addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
 
799
        if (m_selstart <= m_cursor && m_cursor < m_selend) {
 
800
            // cursor is within the selection. Split up the commands
 
801
            // to be able to restore the correct cursor position
 
802
            for (i = m_cursor; i >= m_selstart; --i)
 
803
                addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1));
 
804
            for (i = m_selend - 1; i > m_cursor; --i)
 
805
                addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1));
 
806
        } else {
 
807
            for (i = m_selend-1; i >= m_selstart; --i)
 
808
                addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
 
809
        }
 
810
        if (m_maskData) {
 
811
            m_text.replace(m_selstart, m_selend - m_selstart,  clearString(m_selstart, m_selend - m_selstart));
 
812
            for (int i = 0; i < m_selend - m_selstart; ++i)
 
813
                addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1));
 
814
        } else {
 
815
            m_text.remove(m_selstart, m_selend - m_selstart);
 
816
        }
 
817
        if (m_cursor > m_selstart)
 
818
            m_cursor -= qMin(m_cursor, m_selend) - m_selstart;
 
819
        internalDeselect();
 
820
        m_textDirty = true;
 
821
    }
 
822
}
 
823
 
 
824
/*!
 
825
    \internal
 
826
 
 
827
    Parses the input mask specified by \a maskFields to generate
 
828
    the mask data used to handle input masks.
 
829
*/
 
830
void QLineControl::parseInputMask(const QString &maskFields)
 
831
{
 
832
    int delimiter = maskFields.indexOf(QLatin1Char(';'));
 
833
    if (maskFields.isEmpty() || delimiter == 0) {
 
834
        if (m_maskData) {
 
835
            delete [] m_maskData;
 
836
            m_maskData = 0;
 
837
            m_maxLength = 32767;
 
838
            internalSetText(QString());
 
839
        }
 
840
        return;
 
841
    }
 
842
 
 
843
    if (delimiter == -1) {
 
844
        m_blank = QLatin1Char(' ');
 
845
        m_inputMask = maskFields;
 
846
    } else {
 
847
        m_inputMask = maskFields.left(delimiter);
 
848
        m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
 
849
    }
 
850
 
 
851
    // calculate m_maxLength / m_maskData length
 
852
    m_maxLength = 0;
 
853
    QChar c = 0;
 
854
    for (int i=0; i<m_inputMask.length(); i++) {
 
855
        c = m_inputMask.at(i);
 
856
        if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) {
 
857
            m_maxLength++;
 
858
            continue;
 
859
        }
 
860
        if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
 
861
             c != QLatin1Char('<') && c != QLatin1Char('>') &&
 
862
             c != QLatin1Char('{') && c != QLatin1Char('}') &&
 
863
             c != QLatin1Char('[') && c != QLatin1Char(']'))
 
864
            m_maxLength++;
 
865
    }
 
866
 
 
867
    delete [] m_maskData;
 
868
    m_maskData = new MaskInputData[m_maxLength];
 
869
 
 
870
    MaskInputData::Casemode m = MaskInputData::NoCaseMode;
 
871
    c = 0;
 
872
    bool s;
 
873
    bool escape = false;
 
874
    int index = 0;
 
875
    for (int i = 0; i < m_inputMask.length(); i++) {
 
876
        c = m_inputMask.at(i);
 
877
        if (escape) {
 
878
            s = true;
 
879
            m_maskData[index].maskChar = c;
 
880
            m_maskData[index].separator = s;
 
881
            m_maskData[index].caseMode = m;
 
882
            index++;
 
883
            escape = false;
 
884
        } else if (c == QLatin1Char('<')) {
 
885
                m = MaskInputData::Lower;
 
886
        } else if (c == QLatin1Char('>')) {
 
887
            m = MaskInputData::Upper;
 
888
        } else if (c == QLatin1Char('!')) {
 
889
            m = MaskInputData::NoCaseMode;
 
890
        } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
 
891
            switch (c.unicode()) {
 
892
            case 'A':
 
893
            case 'a':
 
894
            case 'N':
 
895
            case 'n':
 
896
            case 'X':
 
897
            case 'x':
 
898
            case '9':
 
899
            case '0':
 
900
            case 'D':
 
901
            case 'd':
 
902
            case '#':
 
903
            case 'H':
 
904
            case 'h':
 
905
            case 'B':
 
906
            case 'b':
 
907
                s = false;
 
908
                break;
 
909
            case '\\':
 
910
                escape = true;
 
911
            default:
 
912
                s = true;
 
913
                break;
 
914
            }
 
915
 
 
916
            if (!escape) {
 
917
                m_maskData[index].maskChar = c;
 
918
                m_maskData[index].separator = s;
 
919
                m_maskData[index].caseMode = m;
 
920
                index++;
 
921
            }
 
922
        }
 
923
    }
 
924
    internalSetText(m_text);
 
925
}
 
926
 
 
927
 
 
928
/*!
 
929
    \internal
 
930
 
 
931
    checks if the key is valid compared to the inputMask
 
932
*/
 
933
bool QLineControl::isValidInput(QChar key, QChar mask) const
 
934
{
 
935
    switch (mask.unicode()) {
 
936
    case 'A':
 
937
        if (key.isLetter())
 
938
            return true;
 
939
        break;
 
940
    case 'a':
 
941
        if (key.isLetter() || key == m_blank)
 
942
            return true;
 
943
        break;
 
944
    case 'N':
 
945
        if (key.isLetterOrNumber())
 
946
            return true;
 
947
        break;
 
948
    case 'n':
 
949
        if (key.isLetterOrNumber() || key == m_blank)
 
950
            return true;
 
951
        break;
 
952
    case 'X':
 
953
        if (key.isPrint())
 
954
            return true;
 
955
        break;
 
956
    case 'x':
 
957
        if (key.isPrint() || key == m_blank)
 
958
            return true;
 
959
        break;
 
960
    case '9':
 
961
        if (key.isNumber())
 
962
            return true;
 
963
        break;
 
964
    case '0':
 
965
        if (key.isNumber() || key == m_blank)
 
966
            return true;
 
967
        break;
 
968
    case 'D':
 
969
        if (key.isNumber() && key.digitValue() > 0)
 
970
            return true;
 
971
        break;
 
972
    case 'd':
 
973
        if ((key.isNumber() && key.digitValue() > 0) || key == m_blank)
 
974
            return true;
 
975
        break;
 
976
    case '#':
 
977
        if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank)
 
978
            return true;
 
979
        break;
 
980
    case 'B':
 
981
        if (key == QLatin1Char('0') || key == QLatin1Char('1'))
 
982
            return true;
 
983
        break;
 
984
    case 'b':
 
985
        if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank)
 
986
            return true;
 
987
        break;
 
988
    case 'H':
 
989
        if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
 
990
            return true;
 
991
        break;
 
992
    case 'h':
 
993
        if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank)
 
994
            return true;
 
995
        break;
 
996
    default:
 
997
        break;
 
998
    }
 
999
    return false;
 
1000
}
 
1001
 
 
1002
/*!
 
1003
    \internal
 
1004
 
 
1005
    Returns true if the given text \a str is valid for any
 
1006
    validator or input mask set for the line control.
 
1007
 
 
1008
    Otherwise returns false
 
1009
*/
 
1010
bool QLineControl::hasAcceptableInput(const QString &str) const
 
1011
{
 
1012
#ifndef QT_NO_VALIDATOR
 
1013
    QString textCopy = str;
 
1014
    int cursorCopy = m_cursor;
 
1015
    if (m_validator && m_validator->validate(textCopy, cursorCopy)
 
1016
        != QValidator::Acceptable)
 
1017
        return false;
 
1018
#endif
 
1019
 
 
1020
    if (!m_maskData)
 
1021
        return true;
 
1022
 
 
1023
    if (str.length() != m_maxLength)
 
1024
        return false;
 
1025
 
 
1026
    for (int i=0; i < m_maxLength; ++i) {
 
1027
        if (m_maskData[i].separator) {
 
1028
            if (str.at(i) != m_maskData[i].maskChar)
 
1029
                return false;
 
1030
        } else {
 
1031
            if (!isValidInput(str.at(i), m_maskData[i].maskChar))
 
1032
                return false;
 
1033
        }
 
1034
    }
 
1035
    return true;
 
1036
}
 
1037
 
 
1038
/*!
 
1039
    \internal
 
1040
 
 
1041
    Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
 
1042
    specifies from where characters should be gotten when a separator is met in \a str - true means
 
1043
    that blanks will be used, false that previous input is used.
 
1044
    Calling this when no inputMask is set is undefined.
 
1045
*/
 
1046
QString QLineControl::maskString(uint pos, const QString &str, bool clear) const
 
1047
{
 
1048
    if (pos >= (uint)m_maxLength)
 
1049
        return QString::fromLatin1("");
 
1050
 
 
1051
    QString fill;
 
1052
    fill = clear ? clearString(0, m_maxLength) : m_text;
 
1053
 
 
1054
    int strIndex = 0;
 
1055
    QString s = QString::fromLatin1("");
 
1056
    int i = pos;
 
1057
    while (i < m_maxLength) {
 
1058
        if (strIndex < str.length()) {
 
1059
            if (m_maskData[i].separator) {
 
1060
                s += m_maskData[i].maskChar;
 
1061
                if (str[(int)strIndex] == m_maskData[i].maskChar)
 
1062
                    strIndex++;
 
1063
                ++i;
 
1064
            } else {
 
1065
                if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) {
 
1066
                    switch (m_maskData[i].caseMode) {
 
1067
                    case MaskInputData::Upper:
 
1068
                        s += str[(int)strIndex].toUpper();
 
1069
                        break;
 
1070
                    case MaskInputData::Lower:
 
1071
                        s += str[(int)strIndex].toLower();
 
1072
                        break;
 
1073
                    default:
 
1074
                        s += str[(int)strIndex];
 
1075
                    }
 
1076
                    ++i;
 
1077
                } else {
 
1078
                    // search for separator first
 
1079
                    int n = findInMask(i, true, true, str[(int)strIndex]);
 
1080
                    if (n != -1) {
 
1081
                        if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
 
1082
                            s += fill.mid(i, n-i+1);
 
1083
                            i = n + 1; // update i to find + 1
 
1084
                        }
 
1085
                    } else {
 
1086
                        // search for valid m_blank if not
 
1087
                        n = findInMask(i, true, false, str[(int)strIndex]);
 
1088
                        if (n != -1) {
 
1089
                            s += fill.mid(i, n-i);
 
1090
                            switch (m_maskData[n].caseMode) {
 
1091
                            case MaskInputData::Upper:
 
1092
                                s += str[(int)strIndex].toUpper();
 
1093
                                break;
 
1094
                            case MaskInputData::Lower:
 
1095
                                s += str[(int)strIndex].toLower();
 
1096
                                break;
 
1097
                            default:
 
1098
                                s += str[(int)strIndex];
 
1099
                            }
 
1100
                            i = n + 1; // updates i to find + 1
 
1101
                        }
 
1102
                    }
 
1103
                }
 
1104
                ++strIndex;
 
1105
            }
 
1106
        } else
 
1107
            break;
 
1108
    }
 
1109
 
 
1110
    return s;
 
1111
}
 
1112
 
 
1113
 
 
1114
 
 
1115
/*!
 
1116
    \internal
 
1117
 
 
1118
    Returns a "cleared" string with only separators and blank chars.
 
1119
    Calling this when no inputMask is set is undefined.
 
1120
*/
 
1121
QString QLineControl::clearString(uint pos, uint len) const
 
1122
{
 
1123
    if (pos >= (uint)m_maxLength)
 
1124
        return QString();
 
1125
 
 
1126
    QString s;
 
1127
    int end = qMin((uint)m_maxLength, pos + len);
 
1128
    for (int i = pos; i < end; ++i)
 
1129
        if (m_maskData[i].separator)
 
1130
            s += m_maskData[i].maskChar;
 
1131
        else
 
1132
            s += m_blank;
 
1133
 
 
1134
    return s;
 
1135
}
 
1136
 
 
1137
/*!
 
1138
    \internal
 
1139
 
 
1140
    Strips blank parts of the input in a QLineControl when an inputMask is set,
 
1141
    separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
 
1142
*/
 
1143
QString QLineControl::stripString(const QString &str) const
 
1144
{
 
1145
    if (!m_maskData)
 
1146
        return str;
 
1147
 
 
1148
    QString s;
 
1149
    int end = qMin(m_maxLength, (int)str.length());
 
1150
    for (int i = 0; i < end; ++i)
 
1151
        if (m_maskData[i].separator)
 
1152
            s += m_maskData[i].maskChar;
 
1153
        else
 
1154
            if (str[i] != m_blank)
 
1155
                s += str[i];
 
1156
 
 
1157
    return s;
 
1158
}
 
1159
 
 
1160
/*!
 
1161
    \internal
 
1162
    searches forward/backward in m_maskData for either a separator or a m_blank
 
1163
*/
 
1164
int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
 
1165
{
 
1166
    if (pos >= m_maxLength || pos < 0)
 
1167
        return -1;
 
1168
 
 
1169
    int end = forward ? m_maxLength : -1;
 
1170
    int step = forward ? 1 : -1;
 
1171
    int i = pos;
 
1172
 
 
1173
    while (i != end) {
 
1174
        if (findSeparator) {
 
1175
            if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar)
 
1176
                return i;
 
1177
        } else {
 
1178
            if (!m_maskData[i].separator) {
 
1179
                if (searchChar.isNull())
 
1180
                    return i;
 
1181
                else if (isValidInput(searchChar, m_maskData[i].maskChar))
 
1182
                    return i;
 
1183
            }
 
1184
        }
 
1185
        i += step;
 
1186
    }
 
1187
    return -1;
 
1188
}
 
1189
 
 
1190
void QLineControl::internalUndo(int until)
 
1191
{
 
1192
    if (!isUndoAvailable())
 
1193
        return;
 
1194
    cancelPasswordEchoTimer();
 
1195
    internalDeselect();
 
1196
    while (m_undoState && m_undoState > until) {
 
1197
        Command& cmd = m_history[--m_undoState];
 
1198
        switch (cmd.type) {
 
1199
        case Insert:
 
1200
            m_text.remove(cmd.pos, 1);
 
1201
            m_cursor = cmd.pos;
 
1202
            break;
 
1203
        case SetSelection:
 
1204
            m_selstart = cmd.selStart;
 
1205
            m_selend = cmd.selEnd;
 
1206
            m_cursor = cmd.pos;
 
1207
            break;
 
1208
        case Remove:
 
1209
        case RemoveSelection:
 
1210
            m_text.insert(cmd.pos, cmd.uc);
 
1211
            m_cursor = cmd.pos + 1;
 
1212
            break;
 
1213
        case Delete:
 
1214
        case DeleteSelection:
 
1215
            m_text.insert(cmd.pos, cmd.uc);
 
1216
            m_cursor = cmd.pos;
 
1217
            break;
 
1218
        case Separator:
 
1219
            continue;
 
1220
        }
 
1221
        if (until < 0 && m_undoState) {
 
1222
            Command& next = m_history[m_undoState-1];
 
1223
            if (next.type != cmd.type && next.type < RemoveSelection
 
1224
                 && (cmd.type < RemoveSelection || next.type == Separator))
 
1225
                break;
 
1226
        }
 
1227
    }
 
1228
    m_textDirty = true;
 
1229
    emitCursorPositionChanged();
 
1230
}
 
1231
 
 
1232
void QLineControl::internalRedo()
 
1233
{
 
1234
    if (!isRedoAvailable())
 
1235
        return;
 
1236
    internalDeselect();
 
1237
    while (m_undoState < (int)m_history.size()) {
 
1238
        Command& cmd = m_history[m_undoState++];
 
1239
        switch (cmd.type) {
 
1240
        case Insert:
 
1241
            m_text.insert(cmd.pos, cmd.uc);
 
1242
            m_cursor = cmd.pos + 1;
 
1243
            break;
 
1244
        case SetSelection:
 
1245
            m_selstart = cmd.selStart;
 
1246
            m_selend = cmd.selEnd;
 
1247
            m_cursor = cmd.pos;
 
1248
            break;
 
1249
        case Remove:
 
1250
        case Delete:
 
1251
        case RemoveSelection:
 
1252
        case DeleteSelection:
 
1253
            m_text.remove(cmd.pos, 1);
 
1254
            m_selstart = cmd.selStart;
 
1255
            m_selend = cmd.selEnd;
 
1256
            m_cursor = cmd.pos;
 
1257
            break;
 
1258
        case Separator:
 
1259
            m_selstart = cmd.selStart;
 
1260
            m_selend = cmd.selEnd;
 
1261
            m_cursor = cmd.pos;
 
1262
            break;
 
1263
        }
 
1264
        if (m_undoState < (int)m_history.size()) {
 
1265
            Command& next = m_history[m_undoState];
 
1266
            if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
 
1267
                 && (next.type < RemoveSelection || cmd.type == Separator))
 
1268
                break;
 
1269
        }
 
1270
    }
 
1271
    m_textDirty = true;
 
1272
    emitCursorPositionChanged();
 
1273
}
 
1274
 
 
1275
/*!
 
1276
    \internal
 
1277
 
 
1278
    If the current cursor position differs from the last emitted cursor
 
1279
    position, emits cursorPositionChanged().
 
1280
*/
 
1281
void QLineControl::emitCursorPositionChanged()
 
1282
{
 
1283
    if (m_cursor != m_lastCursorPos) {
 
1284
        const int oldLast = m_lastCursorPos;
 
1285
        m_lastCursorPos = m_cursor;
 
1286
        cursorPositionChanged(oldLast, m_cursor);
 
1287
    }
 
1288
}
 
1289
 
 
1290
#ifndef QT_NO_COMPLETER
 
1291
// iterating forward(dir=1)/backward(dir=-1) from the
 
1292
// current row based. dir=0 indicates a new completion prefix was set.
 
1293
bool QLineControl::advanceToEnabledItem(int dir)
 
1294
{
 
1295
    int start = m_completer->currentRow();
 
1296
    if (start == -1)
 
1297
        return false;
 
1298
    int i = start + dir;
 
1299
    if (dir == 0) dir = 1;
 
1300
    do {
 
1301
        if (!m_completer->setCurrentRow(i)) {
 
1302
            if (!m_completer->wrapAround())
 
1303
                break;
 
1304
            i = i > 0 ? 0 : m_completer->completionCount() - 1;
 
1305
        } else {
 
1306
            QModelIndex currentIndex = m_completer->currentIndex();
 
1307
            if (m_completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
 
1308
                return true;
 
1309
            i += dir;
 
1310
        }
 
1311
    } while (i != start);
 
1312
 
 
1313
    m_completer->setCurrentRow(start); // restore
 
1314
    return false;
 
1315
}
 
1316
 
 
1317
void QLineControl::complete(int key)
 
1318
{
 
1319
    if (!m_completer || isReadOnly() || echoMode() != QLineEdit::Normal)
 
1320
        return;
 
1321
 
 
1322
    QString text = this->text();
 
1323
    if (m_completer->completionMode() == QCompleter::InlineCompletion) {
 
1324
        if (key == Qt::Key_Backspace)
 
1325
            return;
 
1326
        int n = 0;
 
1327
        if (key == Qt::Key_Up || key == Qt::Key_Down) {
 
1328
            if (textAfterSelection().length())
 
1329
                return;
 
1330
            QString prefix = hasSelectedText() ? textBeforeSelection()
 
1331
                : text;
 
1332
            if (text.compare(m_completer->currentCompletion(), m_completer->caseSensitivity()) != 0
 
1333
                || prefix.compare(m_completer->completionPrefix(), m_completer->caseSensitivity()) != 0) {
 
1334
                m_completer->setCompletionPrefix(prefix);
 
1335
            } else {
 
1336
                n = (key == Qt::Key_Up) ? -1 : +1;
 
1337
            }
 
1338
        } else {
 
1339
            m_completer->setCompletionPrefix(text);
 
1340
        }
 
1341
        if (!advanceToEnabledItem(n))
 
1342
            return;
 
1343
    } else {
 
1344
#ifndef QT_KEYPAD_NAVIGATION
 
1345
        if (text.isEmpty()) {
 
1346
            m_completer->popup()->hide();
 
1347
            return;
 
1348
        }
 
1349
#endif
 
1350
        m_completer->setCompletionPrefix(text);
 
1351
    }
 
1352
 
 
1353
    m_completer->complete();
 
1354
}
 
1355
#endif
 
1356
 
 
1357
void QLineControl::setCursorBlinkPeriod(int msec)
 
1358
{
 
1359
    if (msec == m_blinkPeriod)
 
1360
        return;
 
1361
    if (m_blinkTimer) {
 
1362
        killTimer(m_blinkTimer);
 
1363
    }
 
1364
    if (msec) {
 
1365
        m_blinkTimer = startTimer(msec / 2);
 
1366
        m_blinkStatus = 1;
 
1367
    } else {
 
1368
        m_blinkTimer = 0;
 
1369
        if (m_blinkStatus == 1)
 
1370
            emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
 
1371
    }
 
1372
    m_blinkPeriod = msec;
 
1373
}
 
1374
 
 
1375
void QLineControl::resetCursorBlinkTimer()
 
1376
{
 
1377
    if (m_blinkPeriod == 0 || m_blinkTimer == 0)
 
1378
        return;
 
1379
    killTimer(m_blinkTimer);
 
1380
    m_blinkTimer = startTimer(m_blinkPeriod / 2);
 
1381
    m_blinkStatus = 1;
 
1382
}
 
1383
 
 
1384
void QLineControl::timerEvent(QTimerEvent *event)
 
1385
{
 
1386
    if (event->timerId() == m_blinkTimer) {
 
1387
        m_blinkStatus = !m_blinkStatus;
 
1388
        emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
 
1389
    } else if (event->timerId() == m_deleteAllTimer) {
 
1390
        killTimer(m_deleteAllTimer);
 
1391
        m_deleteAllTimer = 0;
 
1392
        clear();
 
1393
    } else if (event->timerId() == m_tripleClickTimer) {
 
1394
        killTimer(m_tripleClickTimer);
 
1395
        m_tripleClickTimer = 0;
 
1396
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
 
1397
    } else if (event->timerId() == m_passwordEchoTimer) {
 
1398
        killTimer(m_passwordEchoTimer);
 
1399
        m_passwordEchoTimer = 0;
 
1400
        updateDisplayText();
 
1401
#endif
 
1402
    }
 
1403
}
 
1404
 
 
1405
bool QLineControl::processEvent(QEvent* ev)
 
1406
{
 
1407
#ifdef QT_KEYPAD_NAVIGATION
 
1408
    if (QApplication::keypadNavigationEnabled()) {
 
1409
        if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) {
 
1410
            QKeyEvent *ke = (QKeyEvent *)ev;
 
1411
            if (ke->key() == Qt::Key_Back) {
 
1412
                if (ke->isAutoRepeat()) {
 
1413
                    // Swallow it. We don't want back keys running amok.
 
1414
                    ke->accept();
 
1415
                    return true;
 
1416
                }
 
1417
                if ((ev->type() == QEvent::KeyRelease)
 
1418
                    && !isReadOnly()
 
1419
                    && m_deleteAllTimer) {
 
1420
                    killTimer(m_deleteAllTimer);
 
1421
                    m_deleteAllTimer = 0;
 
1422
                    backspace();
 
1423
                    ke->accept();
 
1424
                    return true;
 
1425
                }
 
1426
            }
 
1427
        }
 
1428
    }
 
1429
#endif
 
1430
    switch(ev->type()){
 
1431
#ifndef QT_NO_GRAPHICSVIEW
 
1432
        case QEvent::GraphicsSceneMouseDoubleClick:
 
1433
        case QEvent::GraphicsSceneMouseMove:
 
1434
        case QEvent::GraphicsSceneMouseRelease:
 
1435
        case QEvent::GraphicsSceneMousePress:{
 
1436
               QGraphicsSceneMouseEvent *gvEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
 
1437
               QMouseEvent* mouse = new QMouseEvent(ev->type(),
 
1438
                    gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers());
 
1439
               processMouseEvent(mouse); break;
 
1440
        }
 
1441
#endif
 
1442
        case QEvent::MouseButtonPress:
 
1443
        case QEvent::MouseButtonRelease:
 
1444
        case QEvent::MouseButtonDblClick:
 
1445
        case QEvent::MouseMove:
 
1446
            processMouseEvent(static_cast<QMouseEvent*>(ev)); break;
 
1447
        case QEvent::KeyPress:
 
1448
        case QEvent::KeyRelease:
 
1449
            processKeyEvent(static_cast<QKeyEvent*>(ev)); break;
 
1450
        case QEvent::InputMethod:
 
1451
            processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break;
 
1452
#ifndef QT_NO_SHORTCUT
 
1453
        case QEvent::ShortcutOverride:{
 
1454
            if (isReadOnly())
 
1455
                return false;
 
1456
            QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
 
1457
            if (ke == QKeySequence::Copy
 
1458
                || ke == QKeySequence::Paste
 
1459
                || ke == QKeySequence::Cut
 
1460
                || ke == QKeySequence::Redo
 
1461
                || ke == QKeySequence::Undo
 
1462
                || ke == QKeySequence::MoveToNextWord
 
1463
                || ke == QKeySequence::MoveToPreviousWord
 
1464
                || ke == QKeySequence::MoveToStartOfDocument
 
1465
                || ke == QKeySequence::MoveToEndOfDocument
 
1466
                || ke == QKeySequence::SelectNextWord
 
1467
                || ke == QKeySequence::SelectPreviousWord
 
1468
                || ke == QKeySequence::SelectStartOfLine
 
1469
                || ke == QKeySequence::SelectEndOfLine
 
1470
                || ke == QKeySequence::SelectStartOfBlock
 
1471
                || ke == QKeySequence::SelectEndOfBlock
 
1472
                || ke == QKeySequence::SelectStartOfDocument
 
1473
                || ke == QKeySequence::SelectAll
 
1474
                || ke == QKeySequence::SelectEndOfDocument) {
 
1475
                ke->accept();
 
1476
            } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
 
1477
                       || ke->modifiers() == Qt::KeypadModifier) {
 
1478
                if (ke->key() < Qt::Key_Escape) {
 
1479
                    ke->accept();
 
1480
                } else {
 
1481
                    switch (ke->key()) {
 
1482
                    case Qt::Key_Delete:
 
1483
                    case Qt::Key_Home:
 
1484
                    case Qt::Key_End:
 
1485
                    case Qt::Key_Backspace:
 
1486
                    case Qt::Key_Left:
 
1487
                    case Qt::Key_Right:
 
1488
                        ke->accept();
 
1489
                    default:
 
1490
                        break;
 
1491
                    }
 
1492
                }
 
1493
            }
 
1494
        }
 
1495
#endif
 
1496
        default:
 
1497
            return false;
 
1498
    }
 
1499
    return true;
 
1500
}
 
1501
 
 
1502
void QLineControl::processMouseEvent(QMouseEvent* ev)
 
1503
{
 
1504
 
 
1505
    switch (ev->type()) {
 
1506
        case QEvent::GraphicsSceneMousePress:
 
1507
        case QEvent::MouseButtonPress:{
 
1508
            if (m_tripleClickTimer
 
1509
                && (ev->pos() - m_tripleClick).manhattanLength()
 
1510
                    < QApplication::startDragDistance()) {
 
1511
                selectAll();
 
1512
                return;
 
1513
            }
 
1514
            if (ev->button() == Qt::RightButton)
 
1515
                return;
 
1516
 
 
1517
            bool mark = ev->modifiers() & Qt::ShiftModifier;
 
1518
            int cursor = xToPos(ev->pos().x());
 
1519
            moveCursor(cursor, mark);
 
1520
            break;
 
1521
        }
 
1522
        case QEvent::GraphicsSceneMouseDoubleClick:
 
1523
        case QEvent::MouseButtonDblClick:
 
1524
            if (ev->button() == Qt::LeftButton) {
 
1525
                selectWordAtPos(xToPos(ev->pos().x()));
 
1526
                if (m_tripleClickTimer)
 
1527
                    killTimer(m_tripleClickTimer);
 
1528
                m_tripleClickTimer = startTimer(QApplication::doubleClickInterval());
 
1529
                m_tripleClick = ev->pos();
 
1530
            }
 
1531
            break;
 
1532
        case QEvent::GraphicsSceneMouseRelease:
 
1533
        case QEvent::MouseButtonRelease:
 
1534
#ifndef QT_NO_CLIPBOARD
 
1535
            if (QApplication::clipboard()->supportsSelection()) {
 
1536
                if (ev->button() == Qt::LeftButton) {
 
1537
                    copy(QClipboard::Selection);
 
1538
                } else if (!isReadOnly() && ev->button() == Qt::MidButton) {
 
1539
                    deselect();
 
1540
                    insert(QApplication::clipboard()->text(QClipboard::Selection));
 
1541
                }
 
1542
            }
 
1543
#endif
 
1544
            break;
 
1545
        case QEvent::GraphicsSceneMouseMove:
 
1546
        case QEvent::MouseMove:
 
1547
            if (ev->buttons() & Qt::LeftButton) {
 
1548
                moveCursor(xToPos(ev->pos().x()), true);
 
1549
            }
 
1550
            break;
 
1551
        default:
 
1552
            break;
 
1553
    }
 
1554
}
 
1555
 
 
1556
void QLineControl::processKeyEvent(QKeyEvent* event)
 
1557
{
 
1558
    bool inlineCompletionAccepted = false;
 
1559
 
 
1560
#ifndef QT_NO_COMPLETER
 
1561
    if (m_completer) {
 
1562
        QCompleter::CompletionMode completionMode = m_completer->completionMode();
 
1563
        if ((completionMode == QCompleter::PopupCompletion
 
1564
             || completionMode == QCompleter::UnfilteredPopupCompletion)
 
1565
            && m_completer->popup()
 
1566
            && m_completer->popup()->isVisible()) {
 
1567
            // The following keys are forwarded by the completer to the widget
 
1568
            // Ignoring the events lets the completer provide suitable default behavior
 
1569
            switch (event->key()) {
 
1570
            case Qt::Key_Escape:
 
1571
                event->ignore();
 
1572
                return;
 
1573
            case Qt::Key_Enter:
 
1574
            case Qt::Key_Return:
 
1575
            case Qt::Key_F4:
 
1576
#ifdef QT_KEYPAD_NAVIGATION
 
1577
            case Qt::Key_Select:
 
1578
                if (!QApplication::keypadNavigationEnabled())
 
1579
                    break;
 
1580
#endif
 
1581
                m_completer->popup()->hide(); // just hide. will end up propagating to parent
 
1582
            default:
 
1583
                break; // normal key processing
 
1584
            }
 
1585
        } else if (completionMode == QCompleter::InlineCompletion) {
 
1586
            switch (event->key()) {
 
1587
            case Qt::Key_Enter:
 
1588
            case Qt::Key_Return:
 
1589
            case Qt::Key_F4:
 
1590
#ifdef QT_KEYPAD_NAVIGATION
 
1591
            case Qt::Key_Select:
 
1592
                if (!QApplication::keypadNavigationEnabled())
 
1593
                    break;
 
1594
#endif
 
1595
                if (!m_completer->currentCompletion().isEmpty() && hasSelectedText()
 
1596
                    && textAfterSelection().isEmpty()) {
 
1597
                    setText(m_completer->currentCompletion());
 
1598
                    inlineCompletionAccepted = true;
 
1599
                }
 
1600
            default:
 
1601
                break; // normal key processing
 
1602
            }
 
1603
        }
 
1604
    }
 
1605
#endif // QT_NO_COMPLETER
 
1606
 
 
1607
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
 
1608
        if (hasAcceptableInput() || fixup()) {
 
1609
            emit accepted();
 
1610
            emit editingFinished();
 
1611
        }
 
1612
        if (inlineCompletionAccepted)
 
1613
            event->accept();
 
1614
        else
 
1615
            event->ignore();
 
1616
        return;
 
1617
    }
 
1618
 
 
1619
    if (echoMode() == QLineEdit::PasswordEchoOnEdit
 
1620
        && !passwordEchoEditing()
 
1621
        && !isReadOnly()
 
1622
        && !event->text().isEmpty()
 
1623
#ifdef QT_KEYPAD_NAVIGATION
 
1624
        && event->key() != Qt::Key_Select
 
1625
        && event->key() != Qt::Key_Up
 
1626
        && event->key() != Qt::Key_Down
 
1627
        && event->key() != Qt::Key_Back
 
1628
#endif
 
1629
        && !(event->modifiers() & Qt::ControlModifier)) {
 
1630
        // Clear the edit and reset to normal echo mode while editing; the
 
1631
        // echo mode switches back when the edit loses focus
 
1632
        // ### resets current content.  dubious code; you can
 
1633
        // navigate with keys up, down, back, and select(?), but if you press
 
1634
        // "left" or "right" it clears?
 
1635
        updatePasswordEchoEditing(true);
 
1636
        clear();
 
1637
    }
 
1638
 
 
1639
    bool unknown = false;
 
1640
 
 
1641
    if (false) {
 
1642
    }
 
1643
#ifndef QT_NO_SHORTCUT
 
1644
    else if (event == QKeySequence::Undo) {
 
1645
        if (!isReadOnly())
 
1646
            undo();
 
1647
    }
 
1648
    else if (event == QKeySequence::Redo) {
 
1649
        if (!isReadOnly())
 
1650
            redo();
 
1651
    }
 
1652
    else if (event == QKeySequence::SelectAll) {
 
1653
        selectAll();
 
1654
    }
 
1655
#ifndef QT_NO_CLIPBOARD
 
1656
    else if (event == QKeySequence::Copy) {
 
1657
        copy();
 
1658
    }
 
1659
    else if (event == QKeySequence::Paste) {
 
1660
        if (!isReadOnly()) {
 
1661
            QClipboard::Mode mode = QClipboard::Clipboard;
 
1662
#ifdef Q_WS_X11
 
1663
            if (event->modifiers() == (Qt::CTRL | Qt::SHIFT) && event->key() == Qt::Key_Insert)
 
1664
                mode = QClipboard::Selection;
 
1665
#endif
 
1666
            paste(mode);
 
1667
        }
 
1668
    }
 
1669
    else if (event == QKeySequence::Cut) {
 
1670
        if (!isReadOnly()) {
 
1671
            copy();
 
1672
            del();
 
1673
        }
 
1674
    }
 
1675
    else if (event == QKeySequence::DeleteEndOfLine) {
 
1676
        if (!isReadOnly()) {
 
1677
            setSelection(cursor(), end());
 
1678
            copy();
 
1679
            del();
 
1680
        }
 
1681
    }
 
1682
#endif //QT_NO_CLIPBOARD
 
1683
    else if (event == QKeySequence::MoveToStartOfLine || event == QKeySequence::MoveToStartOfBlock) {
 
1684
        home(0);
 
1685
    }
 
1686
    else if (event == QKeySequence::MoveToEndOfLine || event == QKeySequence::MoveToEndOfBlock) {
 
1687
        end(0);
 
1688
    }
 
1689
    else if (event == QKeySequence::SelectStartOfLine || event == QKeySequence::SelectStartOfBlock) {
 
1690
        home(1);
 
1691
    }
 
1692
    else if (event == QKeySequence::SelectEndOfLine || event == QKeySequence::SelectEndOfBlock) {
 
1693
        end(1);
 
1694
    }
 
1695
    else if (event == QKeySequence::MoveToNextChar) {
 
1696
#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
 
1697
        if (hasSelectedText()) {
 
1698
#else
 
1699
        if (hasSelectedText() && m_completer
 
1700
            && m_completer->completionMode() == QCompleter::InlineCompletion) {
 
1701
#endif
 
1702
            moveCursor(selectionEnd(), false);
 
1703
        } else {
 
1704
            cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
 
1705
        }
 
1706
    }
 
1707
    else if (event == QKeySequence::SelectNextChar) {
 
1708
        cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
 
1709
    }
 
1710
    else if (event == QKeySequence::MoveToPreviousChar) {
 
1711
#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
 
1712
        if (hasSelectedText()) {
 
1713
#else
 
1714
        if (hasSelectedText() && m_completer
 
1715
            && m_completer->completionMode() == QCompleter::InlineCompletion) {
 
1716
#endif
 
1717
            moveCursor(selectionStart(), false);
 
1718
        } else {
 
1719
            cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1);
 
1720
        }
 
1721
    }
 
1722
    else if (event == QKeySequence::SelectPreviousChar) {
 
1723
        cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1);
 
1724
    }
 
1725
    else if (event == QKeySequence::MoveToNextWord) {
 
1726
        if (echoMode() == QLineEdit::Normal)
 
1727
            layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
 
1728
        else
 
1729
            layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
 
1730
    }
 
1731
    else if (event == QKeySequence::MoveToPreviousWord) {
 
1732
        if (echoMode() == QLineEdit::Normal)
 
1733
            layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
 
1734
        else if (!isReadOnly()) {
 
1735
            layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
 
1736
        }
 
1737
    }
 
1738
    else if (event == QKeySequence::SelectNextWord) {
 
1739
        if (echoMode() == QLineEdit::Normal)
 
1740
            layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
 
1741
        else
 
1742
            layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
 
1743
    }
 
1744
    else if (event == QKeySequence::SelectPreviousWord) {
 
1745
        if (echoMode() == QLineEdit::Normal)
 
1746
            layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
 
1747
        else
 
1748
            layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
 
1749
    }
 
1750
    else if (event == QKeySequence::Delete) {
 
1751
        if (!isReadOnly())
 
1752
            del();
 
1753
    }
 
1754
    else if (event == QKeySequence::DeleteEndOfWord) {
 
1755
        if (!isReadOnly()) {
 
1756
            cursorWordForward(true);
 
1757
            del();
 
1758
        }
 
1759
    }
 
1760
    else if (event == QKeySequence::DeleteStartOfWord) {
 
1761
        if (!isReadOnly()) {
 
1762
            cursorWordBackward(true);
 
1763
            del();
 
1764
        }
 
1765
    }
 
1766
#endif // QT_NO_SHORTCUT
 
1767
    else {
 
1768
        bool handled = false;
 
1769
#ifdef Q_WS_MAC
 
1770
        if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
 
1771
            Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
 
1772
            if (myModifiers & Qt::ShiftModifier) {
 
1773
                if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
 
1774
                        || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
 
1775
                        || myModifiers == Qt::ShiftModifier) {
 
1776
 
 
1777
                    event->key() == Qt::Key_Up ? home(1) : end(1);
 
1778
                }
 
1779
            } else {
 
1780
                if ((myModifiers == Qt::ControlModifier
 
1781
                     || myModifiers == Qt::AltModifier
 
1782
                     || myModifiers == Qt::NoModifier)) {
 
1783
                    event->key() == Qt::Key_Up ? home(0) : end(0);
 
1784
                }
 
1785
            }
 
1786
            handled = true;
 
1787
        }
 
1788
#endif
 
1789
        if (event->modifiers() & Qt::ControlModifier) {
 
1790
            switch (event->key()) {
 
1791
            case Qt::Key_Backspace:
 
1792
                if (!isReadOnly()) {
 
1793
                    cursorWordBackward(true);
 
1794
                    del();
 
1795
                }
 
1796
                break;
 
1797
#ifndef QT_NO_COMPLETER
 
1798
            case Qt::Key_Up:
 
1799
            case Qt::Key_Down:
 
1800
                complete(event->key());
 
1801
                break;
 
1802
#endif
 
1803
#if defined(Q_WS_X11)
 
1804
            case Qt::Key_E:
 
1805
                end(0);
 
1806
                break;
 
1807
 
 
1808
            case Qt::Key_U:
 
1809
                if (!isReadOnly()) {
 
1810
                    setSelection(0, text().size());
 
1811
#ifndef QT_NO_CLIPBOARD
 
1812
                    copy();
 
1813
#endif
 
1814
                    del();
 
1815
                }
 
1816
            break;
 
1817
#endif
 
1818
            default:
 
1819
                if (!handled)
 
1820
                    unknown = true;
 
1821
            }
 
1822
        } else { // ### check for *no* modifier
 
1823
            switch (event->key()) {
 
1824
            case Qt::Key_Backspace:
 
1825
                if (!isReadOnly()) {
 
1826
                    backspace();
 
1827
#ifndef QT_NO_COMPLETER
 
1828
                    complete(Qt::Key_Backspace);
 
1829
#endif
 
1830
                }
 
1831
                break;
 
1832
#ifdef QT_KEYPAD_NAVIGATION
 
1833
            case Qt::Key_Back:
 
1834
                if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
 
1835
                    && !isReadOnly()) {
 
1836
                    if (text().length() == 0) {
 
1837
                        setText(m_cancelText);
 
1838
 
 
1839
                        if (passwordEchoEditing())
 
1840
                            updatePasswordEchoEditing(false);
 
1841
 
 
1842
                        emit editFocusChange(false);
 
1843
                    } else if (!m_deleteAllTimer) {
 
1844
                        m_deleteAllTimer = startTimer(750);
 
1845
                    }
 
1846
                } else {
 
1847
                    unknown = true;
 
1848
                }
 
1849
                break;
 
1850
#endif
 
1851
            default:
 
1852
                if (!handled)
 
1853
                    unknown = true;
 
1854
            }
 
1855
        }
 
1856
    }
 
1857
 
 
1858
    if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
 
1859
        setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
 
1860
        unknown = false;
 
1861
    }
 
1862
 
 
1863
    if (unknown && !isReadOnly()) {
 
1864
        QString t = event->text();
 
1865
        if (!t.isEmpty() && t.at(0).isPrint()) {
 
1866
            insert(t);
 
1867
#ifndef QT_NO_COMPLETER
 
1868
            complete(event->key());
 
1869
#endif
 
1870
            event->accept();
 
1871
            return;
 
1872
        }
 
1873
    }
 
1874
 
 
1875
    if (unknown)
 
1876
        event->ignore();
 
1877
    else
 
1878
        event->accept();
 
1879
}
 
1880
 
 
1881
 
 
1882
QT_END_NAMESPACE
 
1883
 
 
1884
#endif