~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/widgets/qlineedit.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the widgets module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qlineedit.h"
 
30
#include "qlineedit_p.h"
 
31
 
 
32
#ifndef QT_NO_LINEEDIT
 
33
#include "qaction.h"
 
34
#include "qapplication.h"
 
35
#include "qclipboard.h"
 
36
#include "qdrag.h"
 
37
#include "qdrawutil.h"
 
38
#include "qevent.h"
 
39
#include "qfontmetrics.h"
 
40
#include "qmenu.h"
 
41
#include "qpainter.h"
 
42
#include "qpixmap.h"
 
43
#include "qpointer.h"
 
44
#include "qstringlist.h"
 
45
#include "qstyle.h"
 
46
#include "qstyleoption.h"
 
47
#include "qtimer.h"
 
48
#include "qvalidator.h"
 
49
#include "qvariant.h"
 
50
#include "qvector.h"
 
51
#include "qwhatsthis.h"
 
52
#include "qdebug.h"
 
53
#include <private/qinternal_p.h>
 
54
#ifndef QT_NO_ACCESSIBILITY
 
55
#include "qaccessible.h"
 
56
#endif
 
57
#if defined(Q_WS_X11) || defined(Q_WS_QWS)
 
58
#ifndef QT_NO_IM
 
59
#include "qinputcontext.h"
 
60
#include "qlist.h"
 
61
#endif
 
62
#endif
 
63
 
 
64
#ifndef QT_NO_ACCEL
 
65
#include "qkeysequence.h"
 
66
#define ACCEL_KEY(k) "\t" + QString(QKeySequence(Qt::CTRL | Qt::Key_ ## k))
 
67
#else
 
68
#define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k)
 
69
#endif
 
70
 
 
71
#ifdef Q_WS_MAC
 
72
extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
 
73
#endif
 
74
 
 
75
#include <limits.h>
 
76
 
 
77
#define innerMargin 1
 
78
 
 
79
QStyleOptionFrame QLineEditPrivate::getStyleOption() const
 
80
{
 
81
    Q_Q(const QLineEdit);
 
82
    QStyleOptionFrame opt;
 
83
    opt.rect = q->rect();
 
84
    opt.palette = q->palette();
 
85
    opt.lineWidth = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
 
86
    opt.midLineWidth = 0;
 
87
    opt.state = QStyle::State_None | QStyle::State_Sunken;
 
88
    return opt;
 
89
}
 
90
 
 
91
/*!
 
92
    \class QLineEdit
 
93
    \brief The QLineEdit widget is a one-line text editor.
 
94
 
 
95
    \ingroup basic
 
96
    \mainclass
 
97
 
 
98
    A line edit allows the user to enter and edit a single line of
 
99
    plain text with a useful collection of editing functions,
 
100
    including undo and redo, cut and paste, and drag and drop.
 
101
 
 
102
    By changing the echoMode() of a line edit, it can also be used as
 
103
    a "write-only" field, for inputs such as passwords.
 
104
 
 
105
    The length of the text can be constrained to maxLength(). The text
 
106
    can be arbitrarily constrained using a validator() or an
 
107
    inputMask(), or both.
 
108
 
 
109
    A related class is QTextEdit which allows multi-line, rich text
 
110
    editing.
 
111
 
 
112
    You can change the text with setText() or insert(). The text is
 
113
    retrieved with text(); the displayed text (which may be different,
 
114
    see \l{EchoMode}) is retrieved with displayText(). Text can be
 
115
    selected with setSelection() or selectAll(), and the selection can
 
116
    be cut(), copy()ied and paste()d. The text can be aligned with
 
117
    setAlignment().
 
118
 
 
119
    When the text changes the textChanged() signal is emitted; when
 
120
    the text changes other than by calling setText() the textEdited()
 
121
    signal is emitted; when the cursor is moved the
 
122
    cursorPositionChanged() signal is emitted; and when the Return or
 
123
    Enter key is pressed the returnPressed() signal is emitted.
 
124
 
 
125
    When editing is finished, either because the line edit lost focus
 
126
    or Return/Enter is pressed the editingFinished() signal is
 
127
    emitted.
 
128
 
 
129
    Note that if there is a validator set on the line edit, the
 
130
    returnPressed()/editingFinished() signals will only be emitted if
 
131
    the validator returns \c Acceptable.
 
132
 
 
133
    By default, QLineEdits have a frame as specified by the Windows
 
134
    and Motif style guides; you can turn it off by calling
 
135
    setFrame(false).
 
136
 
 
137
    The default key bindings are described below. The line edit also
 
138
    provides a context menu (usually invoked by a right mouse click)
 
139
    that presents some of these editing options.
 
140
    \target desc
 
141
    \table
 
142
    \header \i Keypress \i Action
 
143
    \row \i Left Arrow \i Moves the cursor one character to the left.
 
144
    \row \i Shift+Left Arrow \i Moves and selects text one character to the left.
 
145
    \row \i Right Arrow \i Moves the cursor one character to the right.
 
146
    \row \i Shift+Right Arrow \i Moves and selects text one character to the right.
 
147
    \row \i Home \i Moves the cursor to the beginning of the line.
 
148
    \row \i End \i Moves the cursor to the end of the line.
 
149
    \row \i Backspace \i Deletes the character to the left of the cursor.
 
150
    \row \i Ctrl+Backspace \i Deletes the word to the left of the cursor.
 
151
    \row \i Delete \i Deletes the character to the right of the cursor.
 
152
    \row \i Ctrl+Delete \i Deletes the word to the right of the cursor.
 
153
    \row \i Ctrl+A \i Moves the cursor to the beginning of the line.
 
154
    \row \i Ctrl+B \i Moves the cursor one character to the left.
 
155
    \row \i Ctrl+C \i Copies the selected text to the clipboard.
 
156
    \row \i Ctrl+Insert \i Copies the selected text to the clipboard.
 
157
    \row \i Ctrl+D \i Deletes the character to the right of the cursor.
 
158
    \row \i Ctrl+E \i Moves the cursor to the end of the line.
 
159
    \row \i Ctrl+F \i Moves the cursor one character to the right.
 
160
    \row \i Ctrl+H \i Deletes the character to the left of the cursor.
 
161
    \row \i Ctrl+K \i Deletes to the end of the line.
 
162
    \row \i Ctrl+V \i Pastes the clipboard text into line edit.
 
163
    \row \i Shift+Insert \i Pastes the clipboard text into line edit.
 
164
    \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard.
 
165
    \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard.
 
166
    \row \i Ctrl+Z \i Undoes the last operation.
 
167
    \row \i Ctrl+Y \i Redoes the last undone operation.
 
168
    \endtable
 
169
 
 
170
    Any other key sequence that represents a valid character, will
 
171
    cause the character to be inserted into the line edit.
 
172
 
 
173
    \inlineimage macintosh-lineedit.png Screenshot in Macintosh style
 
174
    \inlineimage windows-lineedit.png Screenshot in Windows style
 
175
 
 
176
    \sa QTextEdit, QLabel, QComboBox, {fowler}{GUI Design Handbook: Field, Entry}
 
177
*/
 
178
 
 
179
 
 
180
/*!
 
181
    \fn void QLineEdit::textChanged(const QString &text)
 
182
 
 
183
    This signal is emitted whenever the text changes. The \a text
 
184
    argument is the new text.
 
185
 
 
186
    Unlike textEdited(), this signal is also emitted when
 
187
    programmatically setting the text via setText().
 
188
*/
 
189
 
 
190
/*!
 
191
    \fn void QLineEdit::textEdited(const QString &text)
 
192
 
 
193
    This signal is emitted whenever the text is edited. The \a text
 
194
    argument is the next text.
 
195
 
 
196
    Unlike textChanged(), this signal is \e not emitted when
 
197
    programmatically setting the text via setText().
 
198
*/
 
199
 
 
200
/*!
 
201
    \fn void QLineEdit::cursorPositionChanged(int old, int new)
 
202
 
 
203
    This signal is emitted whenever the cursor moves. The previous
 
204
    position is given by \a old, and the new position by \a new.
 
205
 
 
206
    \sa setCursorPosition(), cursorPosition()
 
207
*/
 
208
 
 
209
/*!
 
210
    \fn void QLineEdit::selectionChanged()
 
211
 
 
212
    This signal is emitted whenever the selection changes.
 
213
 
 
214
    \sa hasSelectedText(), selectedText()
 
215
*/
 
216
 
 
217
/*!
 
218
    Constructs a line edit with no text.
 
219
 
 
220
    The maximum text length is set to 32767 characters.
 
221
 
 
222
    The \a parent argument is sent to the QWidget constructor.
 
223
 
 
224
    \sa setText(), setMaxLength()
 
225
*/
 
226
QLineEdit::QLineEdit(QWidget* parent)
 
227
    : QWidget(*new QLineEditPrivate, parent,0)
 
228
{
 
229
    Q_D(QLineEdit);
 
230
    d->init(QString());
 
231
}
 
232
 
 
233
/*!
 
234
    Constructs a line edit containing the text \a contents.
 
235
 
 
236
    The cursor position is set to the end of the line and the maximum
 
237
    text length to 32767 characters.
 
238
 
 
239
    The \a parent and argument is sent to the QWidget
 
240
    constructor.
 
241
 
 
242
    \sa text(), setMaxLength()
 
243
*/
 
244
QLineEdit::QLineEdit(const QString& contents, QWidget* parent)
 
245
    : QWidget(*new QLineEditPrivate, parent, 0)
 
246
{
 
247
    Q_D(QLineEdit);
 
248
    d->init(contents);
 
249
}
 
250
 
 
251
 
 
252
#ifdef QT3_SUPPORT
 
253
/*!
 
254
    Constructs a line edit with no text.
 
255
 
 
256
    The maximum text length is set to 32767 characters.
 
257
 
 
258
    The \a parent and \a name arguments are sent to the QWidget constructor.
 
259
 
 
260
    \sa setText(), setMaxLength()
 
261
*/
 
262
QLineEdit::QLineEdit(QWidget* parent, const char* name)
 
263
    : QWidget(*new QLineEditPrivate, parent,0)
 
264
{
 
265
    Q_D(QLineEdit);
 
266
    setObjectName(name);
 
267
    d->init(QString());
 
268
}
 
269
 
 
270
/*!
 
271
    Constructs a line edit containing the text \a contents.
 
272
 
 
273
    The cursor position is set to the end of the line and the maximum
 
274
    text length to 32767 characters.
 
275
 
 
276
    The \a parent and \a name arguments are sent to the QWidget
 
277
    constructor.
 
278
 
 
279
    \sa text(), setMaxLength()
 
280
*/
 
281
 
 
282
QLineEdit::QLineEdit(const QString& contents, QWidget* parent, const char* name)
 
283
    : QWidget(*new QLineEditPrivate, parent, 0)
 
284
{
 
285
    Q_D(QLineEdit);
 
286
    setObjectName(name);
 
287
    d->init(contents);
 
288
}
 
289
 
 
290
/*!
 
291
    Constructs a line edit with an input \a inputMask and the text \a
 
292
    contents.
 
293
 
 
294
    The cursor position is set to the end of the line and the maximum
 
295
    text length is set to the length of the mask (the number of mask
 
296
    characters and separators).
 
297
 
 
298
    The \a parent and \a name arguments are sent to the QWidget
 
299
    constructor.
 
300
 
 
301
    \sa setMask() text()
 
302
*/
 
303
QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget* parent, const char* name)
 
304
    : QWidget(*new QLineEditPrivate, parent, 0)
 
305
{
 
306
    Q_D(QLineEdit);
 
307
    setObjectName(name);
 
308
    d->parseInputMask(inputMask);
 
309
    if (d->maskData) {
 
310
        QString ms = d->maskString(0, contents);
 
311
        d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length()));
 
312
        d->cursor = d->nextMaskBlank(ms.length());
 
313
    } else {
 
314
        d->init(contents);
 
315
    }
 
316
}
 
317
#endif
 
318
 
 
319
/*!
 
320
    Destroys the line edit.
 
321
*/
 
322
 
 
323
QLineEdit::~QLineEdit()
 
324
{
 
325
}
 
326
 
 
327
 
 
328
/*!
 
329
    \property QLineEdit::text
 
330
    \brief the line edit's text
 
331
 
 
332
    Setting this property clears the selection, clears the undo/redo
 
333
    history, moves the cursor to the end of the line and resets the
 
334
    \c modified property to false. The text is not validated when
 
335
    inserted with setText().
 
336
 
 
337
    The text is truncated to maxLength() length.
 
338
 
 
339
    \sa insert(), clear()
 
340
*/
 
341
QString QLineEdit::text() const
 
342
{
 
343
    Q_D(const QLineEdit);
 
344
    QString res = d->text;
 
345
    if (d->maskData)
 
346
        res = d->stripString(d->text);
 
347
    return (res.isNull() ? QString::fromLatin1("") : res);
 
348
}
 
349
 
 
350
void QLineEdit::setText(const QString& text)
 
351
{
 
352
    Q_D(QLineEdit);
 
353
    d->setText(text, -1, false);
 
354
}
 
355
 
 
356
 
 
357
/*!
 
358
    \property QLineEdit::displayText
 
359
    \brief the displayed text
 
360
 
 
361
    If \c EchoMode is \c Normal this returns the same as text(); if
 
362
    \c EchoMode is \c Password it returns a string of asterisks
 
363
    text().length() characters long, e.g. "******"; if \c EchoMode is
 
364
    \c NoEcho returns an empty string, "".
 
365
 
 
366
    \sa setEchoMode() text() EchoMode
 
367
*/
 
368
 
 
369
QString QLineEdit::displayText() const
 
370
{
 
371
    Q_D(const QLineEdit);
 
372
    if (d->echoMode == NoEcho)
 
373
        return QString::fromLatin1("");
 
374
    QString res = d->text;
 
375
    if (d->echoMode == Password) {
 
376
        QStyleOptionFrame opt = d->getStyleOption();
 
377
        res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
 
378
    }
 
379
    return (res.isNull() ? QString::fromLatin1("") : res);
 
380
}
 
381
 
 
382
 
 
383
/*!
 
384
    \property QLineEdit::maxLength
 
385
    \brief the maximum permitted length of the text
 
386
 
 
387
    If the text is too long, it is truncated at the limit.
 
388
 
 
389
    If truncation occurs any selected text will be unselected, the
 
390
    cursor position is set to 0 and the first part of the string is
 
391
    shown.
 
392
 
 
393
    If the line edit has an input mask, the mask defines the maximum
 
394
    string length.
 
395
 
 
396
    \sa inputMask
 
397
*/
 
398
 
 
399
int QLineEdit::maxLength() const
 
400
{
 
401
    Q_D(const QLineEdit);
 
402
    return d->maxLength;
 
403
}
 
404
 
 
405
void QLineEdit::setMaxLength(int maxLength)
 
406
{
 
407
    Q_D(QLineEdit);
 
408
    if (d->maskData)
 
409
        return;
 
410
    d->maxLength = maxLength;
 
411
    setText(d->text);
 
412
}
 
413
 
 
414
 
 
415
 
 
416
/*!
 
417
    \property QLineEdit::frame
 
418
    \brief whether the line edit draws itself with a frame
 
419
 
 
420
    If enabled (the default) the line edit draws itself inside a
 
421
    frame, otherwise the line edit draws itself without any frame.
 
422
*/
 
423
bool QLineEdit::hasFrame() const
 
424
{
 
425
    Q_D(const QLineEdit);
 
426
    return d->frame;
 
427
}
 
428
 
 
429
 
 
430
void QLineEdit::setFrame(bool enable)
 
431
{
 
432
    Q_D(QLineEdit);
 
433
    d->frame = enable;
 
434
    update();
 
435
    updateGeometry();
 
436
}
 
437
 
 
438
 
 
439
/*!
 
440
    \enum QLineEdit::EchoMode
 
441
 
 
442
    This enum type describes how a line edit should display its
 
443
    contents.
 
444
 
 
445
    \value Normal   Display characters as they are entered. This is the
 
446
                    default.
 
447
    \value NoEcho   Do not display anything. This may be appropriate
 
448
                    for passwords where even the length of the
 
449
                    password should be kept secret.
 
450
    \value Password  Display asterisks instead of the characters
 
451
                    actually entered.
 
452
 
 
453
    \sa setEchoMode() echoMode()
 
454
*/
 
455
 
 
456
 
 
457
/*!
 
458
    \property QLineEdit::echoMode
 
459
    \brief the line edit's echo mode
 
460
 
 
461
    The initial setting is \c Normal, but QLineEdit also supports \c
 
462
    NoEcho and \c Password modes.
 
463
 
 
464
    The widget's display and the ability to copy or drag the text is
 
465
    affected by this setting.
 
466
 
 
467
    \sa EchoMode displayText()
 
468
*/
 
469
 
 
470
QLineEdit::EchoMode QLineEdit::echoMode() const
 
471
{
 
472
    Q_D(const QLineEdit);
 
473
    return (EchoMode) d->echoMode;
 
474
}
 
475
 
 
476
void QLineEdit::setEchoMode(EchoMode mode)
 
477
{
 
478
    Q_D(QLineEdit);
 
479
    if(mode == (EchoMode)d->echoMode)
 
480
        return;
 
481
    d->echoMode = mode;
 
482
    d->updateTextLayout();
 
483
    update();
 
484
#ifdef Q_WS_MAC
 
485
    if(hasFocus())
 
486
        qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
 
487
#endif
 
488
}
 
489
 
 
490
 
 
491
 
 
492
/*!
 
493
    Returns a pointer to the current input validator, or 0 if no
 
494
    validator has been set.
 
495
 
 
496
    \sa setValidator()
 
497
*/
 
498
 
 
499
const QValidator * QLineEdit::validator() const
 
500
{
 
501
    Q_D(const QLineEdit);
 
502
    return d->validator;
 
503
}
 
504
 
 
505
/*!
 
506
    Sets this line edit to only accept input that the validator, \a v,
 
507
    will accept. This allows you to place any arbitrary constraints on
 
508
    the text which may be entered.
 
509
 
 
510
    If \a v == 0, setValidator() removes the current input validator.
 
511
    The initial setting is to have no input validator (i.e. any input
 
512
    is accepted up to maxLength()).
 
513
 
 
514
    \sa validator() QIntValidator QDoubleValidator QRegExpValidator
 
515
*/
 
516
 
 
517
void QLineEdit::setValidator(const QValidator *v)
 
518
{
 
519
    Q_D(QLineEdit);
 
520
    d->validator = const_cast<QValidator*>(v);
 
521
}
 
522
 
 
523
 
 
524
 
 
525
/*!
 
526
    Returns a recommended size for the widget.
 
527
 
 
528
    The width returned, in pixels, is usually enough for about 15 to
 
529
    20 characters.
 
530
*/
 
531
 
 
532
QSize QLineEdit::sizeHint() const
 
533
{
 
534
    Q_D(const QLineEdit);
 
535
    ensurePolished();
 
536
    QFontMetrics fm(font());
 
537
    int h = qMax(fm.lineSpacing(), 14) + 2*innerMargin;
 
538
    int w = fm.width('x') * 17; // "some"
 
539
    int m = d->frame ? style()->pixelMetric(QStyle::PM_DefaultFrameWidth) : 0;
 
540
    QStyleOptionFrame opt;
 
541
    opt.rect = rect();
 
542
    opt.palette = palette();
 
543
    opt.state = QStyle::State_None;
 
544
    return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w + m, h + m).
 
545
                                     expandedTo(QApplication::globalStrut()), this));
 
546
}
 
547
 
 
548
 
 
549
/*!
 
550
    Returns a minimum size for the line edit.
 
551
 
 
552
    The width returned is enough for at least one character.
 
553
*/
 
554
 
 
555
QSize QLineEdit::minimumSizeHint() const
 
556
{
 
557
    Q_D(const QLineEdit);
 
558
    ensurePolished();
 
559
    QFontMetrics fm = fontMetrics();
 
560
    int h = fm.height() + qMax(2*innerMargin, fm.leading());
 
561
    int w = fm.maxWidth();
 
562
    int m = d->frame ? style()->pixelMetric(QStyle::PM_DefaultFrameWidth) : 0;
 
563
    return QSize(w + m, h + m);
 
564
}
 
565
 
 
566
 
 
567
/*!
 
568
    \property QLineEdit::cursorPosition
 
569
    \brief the current cursor position for this line edit
 
570
 
 
571
    Setting the cursor position causes a repaint when appropriate.
 
572
*/
 
573
 
 
574
int QLineEdit::cursorPosition() const
 
575
{
 
576
    Q_D(const QLineEdit);
 
577
    return d->cursor;
 
578
}
 
579
 
 
580
void QLineEdit::setCursorPosition(int pos)
 
581
{
 
582
    Q_D(QLineEdit);
 
583
    if (pos < 0)
 
584
        pos = 0;
 
585
 
 
586
    if (pos <= d->text.length())
 
587
        d->moveCursor(pos);
 
588
}
 
589
 
 
590
/*!
 
591
    Returns the \c cursorPostion under the point \a pos.
 
592
*/
 
593
// ### What should this do if the point is outside of contentsRect? Currently returns 0.
 
594
int QLineEdit::cursorPositionAt(const QPoint &pos)
 
595
{
 
596
    Q_D(QLineEdit);
 
597
    return d->xToPos(pos.x());
 
598
}
 
599
 
 
600
 
 
601
#ifdef QT3_SUPPORT
 
602
/*! \obsolete
 
603
 
 
604
    Use setText(), setCursorPosition() and setSelection() instead.
 
605
*/
 
606
bool QLineEdit::validateAndSet(const QString &newText, int newPos,
 
607
                                 int newMarkAnchor, int newMarkDrag)
 
608
{
 
609
    Q_D(QLineEdit);
 
610
    int priorState = d->undoState;
 
611
    d->selstart = 0;
 
612
    d->selend = d->text.length();
 
613
    d->removeSelectedText();
 
614
    d->insert(newText);
 
615
    d->finishChange(priorState);
 
616
    if (d->undoState > priorState) {
 
617
        d->cursor = newPos;
 
618
        d->selstart = qMin(newMarkAnchor, newMarkDrag);
 
619
        d->selend = qMax(newMarkAnchor, newMarkDrag);
 
620
        update();
 
621
        d->emitCursorPositionChanged();
 
622
        return true;
 
623
    }
 
624
    return false;
 
625
}
 
626
#endif //QT3_SUPPORT
 
627
 
 
628
/*!
 
629
    \property QLineEdit::alignment
 
630
    \brief the alignment of the line edit
 
631
 
 
632
    Only horizontal alignments are allowed in here, Qt::AlignJustify
 
633
    will map to Qt::AlignLeft.
 
634
 
 
635
    \sa Qt::Alignment
 
636
*/
 
637
 
 
638
Qt::Alignment QLineEdit::alignment() const
 
639
{
 
640
    Q_D(const QLineEdit);
 
641
    return QFlag(d->alignment);
 
642
}
 
643
 
 
644
void QLineEdit::setAlignment(Qt::Alignment alignment)
 
645
{
 
646
    Q_D(QLineEdit);
 
647
    d->alignment = alignment & Qt::AlignHorizontal_Mask;
 
648
    update();
 
649
}
 
650
 
 
651
 
 
652
/*!
 
653
    Moves the cursor forward \a steps characters. If \a mark is true
 
654
    each character moved over is added to the selection; if \a mark is
 
655
    false the selection is cleared.
 
656
 
 
657
    \sa cursorBackward()
 
658
*/
 
659
 
 
660
void QLineEdit::cursorForward(bool mark, int steps)
 
661
{
 
662
    Q_D(QLineEdit);
 
663
    int cursor = d->cursor;
 
664
    if (steps > 0) {
 
665
        while(steps--)
 
666
            cursor = d->textLayout.nextCursorPosition(cursor);
 
667
    } else if (steps < 0) {
 
668
        while (steps++)
 
669
            cursor = d->textLayout.previousCursorPosition(cursor);
 
670
    }
 
671
    d->moveCursor(cursor, mark);
 
672
}
 
673
 
 
674
 
 
675
/*!
 
676
    Moves the cursor back \a steps characters. If \a mark is true each
 
677
    character moved over is added to the selection; if \a mark is
 
678
    false the selection is cleared.
 
679
 
 
680
    \sa cursorForward()
 
681
*/
 
682
void QLineEdit::cursorBackward(bool mark, int steps)
 
683
{
 
684
    cursorForward(mark, -steps);
 
685
}
 
686
 
 
687
/*!
 
688
    Moves the cursor one word forward. If \a mark is true, the word is
 
689
    also selected.
 
690
 
 
691
    \sa cursorWordBackward()
 
692
*/
 
693
void QLineEdit::cursorWordForward(bool mark)
 
694
{
 
695
    Q_D(QLineEdit);
 
696
    d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
 
697
}
 
698
 
 
699
/*!
 
700
    Moves the cursor one word backward. If \a mark is true, the word
 
701
    is also selected.
 
702
 
 
703
    \sa cursorWordForward()
 
704
*/
 
705
 
 
706
void QLineEdit::cursorWordBackward(bool mark)
 
707
{
 
708
    Q_D(QLineEdit);
 
709
    d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
 
710
}
 
711
 
 
712
 
 
713
/*!
 
714
    If no text is selected, deletes the character to the left of the
 
715
    text cursor and moves the cursor one position to the left. If any
 
716
    text is selected, the cursor is moved to the beginning of the
 
717
    selected text and the selected text is deleted.
 
718
 
 
719
    \sa del()
 
720
*/
 
721
void QLineEdit::backspace()
 
722
{
 
723
    Q_D(QLineEdit);
 
724
    int priorState = d->undoState;
 
725
    if (d->hasSelectedText()) {
 
726
        d->removeSelectedText();
 
727
    } else if (d->cursor) {
 
728
            --d->cursor;
 
729
            if (d->maskData)
 
730
                d->cursor = d->prevMaskBlank(d->cursor);
 
731
            QChar uc = d->text.at(d->cursor);
 
732
            if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
 
733
                // second half of a surrogate, check if we have the first half as well,
 
734
                // if yes delete both at once
 
735
                uc = d->text.at(d->cursor - 1);
 
736
                if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
 
737
                    d->del(true);
 
738
                    --d->cursor;
 
739
                }
 
740
            }
 
741
            d->del(true);
 
742
    }
 
743
    d->finishChange(priorState);
 
744
}
 
745
 
 
746
/*!
 
747
    If no text is selected, deletes the character to the right of the
 
748
    text cursor. If any text is selected, the cursor is moved to the
 
749
    beginning of the selected text and the selected text is deleted.
 
750
 
 
751
    \sa backspace()
 
752
*/
 
753
 
 
754
void QLineEdit::del()
 
755
{
 
756
    Q_D(QLineEdit);
 
757
    int priorState = d->undoState;
 
758
    if (d->hasSelectedText()) {
 
759
        d->removeSelectedText();
 
760
    } else {
 
761
        int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor;
 
762
        while (n--)
 
763
            d->del();
 
764
    }
 
765
    d->finishChange(priorState);
 
766
}
 
767
 
 
768
/*!
 
769
    Moves the text cursor to the beginning of the line unless it is
 
770
    already there. If \a mark is true, text is selected towards the
 
771
    first position; otherwise, any selected text is unselected if the
 
772
    cursor is moved.
 
773
 
 
774
    \sa end()
 
775
*/
 
776
 
 
777
void QLineEdit::home(bool mark)
 
778
{
 
779
    Q_D(QLineEdit);
 
780
    d->moveCursor(0, mark);
 
781
}
 
782
 
 
783
/*!
 
784
    Moves the text cursor to the end of the line unless it is already
 
785
    there. If \a mark is true, text is selected towards the last
 
786
    position; otherwise, any selected text is unselected if the cursor
 
787
    is moved.
 
788
 
 
789
    \sa home()
 
790
*/
 
791
 
 
792
void QLineEdit::end(bool mark)
 
793
{
 
794
    Q_D(QLineEdit);
 
795
    d->moveCursor(d->text.length(), mark);
 
796
}
 
797
 
 
798
 
 
799
/*!
 
800
    \property QLineEdit::modified
 
801
    \brief whether the line edit's contents has been modified by the user
 
802
 
 
803
    The modified flag is never read by QLineEdit; it has a default value
 
804
    of false and is changed to true whenever the user changes the line
 
805
    edit's contents.
 
806
 
 
807
    This is useful for things that need to provide a default value but
 
808
    do not start out knowing what the default should be (perhaps it
 
809
    depends on other fields on the form). Start the line edit without
 
810
    the best default, and when the default is known, if modified()
 
811
    returns false (the user hasn't entered any text), insert the
 
812
    default value.
 
813
 
 
814
    Calling setText() resets the modified flag to false.
 
815
*/
 
816
 
 
817
bool QLineEdit::isModified() const
 
818
{
 
819
    Q_D(const QLineEdit);
 
820
    return d->modifiedState != d->undoState;
 
821
}
 
822
 
 
823
void QLineEdit::setModified(bool modified)
 
824
{
 
825
    Q_D(QLineEdit);
 
826
    if (modified)
 
827
        d->modifiedState = -1;
 
828
    else
 
829
        d->modifiedState = d->undoState;
 
830
}
 
831
 
 
832
 
 
833
/*!\fn QLineEdit::clearModified()
 
834
 
 
835
Use setModified(false) instead.
 
836
 
 
837
    \sa isModified()
 
838
*/
 
839
 
 
840
 
 
841
/*!
 
842
    \property QLineEdit::hasSelectedText
 
843
    \brief whether there is any text selected
 
844
 
 
845
    hasSelectedText() returns true if some or all of the text has been
 
846
    selected by the user; otherwise returns false.
 
847
 
 
848
    \sa selectedText()
 
849
*/
 
850
 
 
851
 
 
852
bool QLineEdit::hasSelectedText() const
 
853
{
 
854
    Q_D(const QLineEdit);
 
855
    return d->hasSelectedText();
 
856
}
 
857
 
 
858
/*!
 
859
    \property QLineEdit::selectedText
 
860
    \brief the selected text
 
861
 
 
862
    If there is no selected text this property's value is
 
863
    an empty string.
 
864
 
 
865
    \sa hasSelectedText()
 
866
*/
 
867
 
 
868
QString QLineEdit::selectedText() const
 
869
{
 
870
    Q_D(const QLineEdit);
 
871
    if (d->hasSelectedText())
 
872
        return d->text.mid(d->selstart, d->selend - d->selstart);
 
873
    return QString();
 
874
}
 
875
 
 
876
/*!
 
877
    selectionStart() returns the index of the first selected character in the
 
878
    line edit or -1 if no text is selected.
 
879
 
 
880
    \sa selectedText()
 
881
*/
 
882
 
 
883
int QLineEdit::selectionStart() const
 
884
{
 
885
    Q_D(const QLineEdit);
 
886
    return d->hasSelectedText() ? d->selstart : -1;
 
887
}
 
888
 
 
889
 
 
890
#ifdef QT3_SUPPORT
 
891
 
 
892
/*!
 
893
    \fn void QLineEdit::lostFocus()
 
894
 
 
895
    This signal is emitted when the line edit has lost focus.
 
896
 
 
897
    Use editingFinished() instead
 
898
    \sa editingFinished(), returnPressed()
 
899
*/
 
900
 
 
901
/*!
 
902
    Use isModified() instead.
 
903
*/
 
904
bool QLineEdit::edited() const { return isModified(); }
 
905
/*!
 
906
    Use setModified()  or setText().
 
907
*/
 
908
void QLineEdit::setEdited(bool on) { setModified(on); }
 
909
 
 
910
/*!
 
911
    There exists no equivalent functionality in Qt 4.
 
912
*/
 
913
int QLineEdit::characterAt(int xpos, QChar *chr) const
 
914
{
 
915
    Q_D(const QLineEdit);
 
916
    int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + innerMargin);
 
917
    if (chr && pos < (int) d->text.length())
 
918
        *chr = d->text.at(pos);
 
919
    return pos;
 
920
 
 
921
}
 
922
 
 
923
/*!
 
924
    Use selectedText() and selectionStart() instead.
 
925
*/
 
926
bool QLineEdit::getSelection(int *start, int *end)
 
927
{
 
928
    Q_D(QLineEdit);
 
929
    if (d->hasSelectedText() && start && end) {
 
930
        *start = d->selstart;
 
931
        *end = d->selend;
 
932
        return true;
 
933
    }
 
934
    return false;
 
935
}
 
936
#endif
 
937
 
 
938
 
 
939
/*!
 
940
    Selects text from position \a start and for \a length characters.
 
941
    Negative lengths are allowed.
 
942
 
 
943
    \sa deselect() selectAll() selectedText()
 
944
*/
 
945
 
 
946
void QLineEdit::setSelection(int start, int length)
 
947
{
 
948
    Q_D(QLineEdit);
 
949
    if (start < 0 || start > (int)d->text.length()) {
 
950
        qWarning("QLineEdit: Invalid start position: %d.", start);
 
951
        return;
 
952
    } else {
 
953
        if (length > 0) {
 
954
            d->selstart = start;
 
955
            d->selend = qMin(start + length, (int)d->text.length());
 
956
            d->cursor = d->selend;
 
957
        } else {
 
958
            d->selstart = qMax(start + length, 0);
 
959
            d->selend = start;
 
960
            d->cursor = d->selstart;
 
961
        }
 
962
    }
 
963
    update();
 
964
    d->emitCursorPositionChanged();
 
965
}
 
966
 
 
967
 
 
968
/*!
 
969
    \property QLineEdit::undoAvailable
 
970
    \brief whether undo is available
 
971
*/
 
972
 
 
973
bool QLineEdit::isUndoAvailable() const
 
974
{
 
975
    Q_D(const QLineEdit);
 
976
    return d->isUndoAvailable();
 
977
}
 
978
 
 
979
/*!
 
980
    \property QLineEdit::redoAvailable
 
981
    \brief whether redo is available
 
982
*/
 
983
 
 
984
bool QLineEdit::isRedoAvailable() const
 
985
{
 
986
    Q_D(const QLineEdit);
 
987
    return d->isRedoAvailable();
 
988
}
 
989
 
 
990
/*!
 
991
    \property QLineEdit::dragEnabled
 
992
    \brief whether the lineedit starts a drag if the user presses and
 
993
    moves the mouse on some selected text
 
994
 
 
995
    Dragging is disabled by default.
 
996
*/
 
997
 
 
998
bool QLineEdit::dragEnabled() const
 
999
{
 
1000
    Q_D(const QLineEdit);
 
1001
    return d->dragEnabled;
 
1002
}
 
1003
 
 
1004
void QLineEdit::setDragEnabled(bool b)
 
1005
{
 
1006
    Q_D(QLineEdit);
 
1007
    d->dragEnabled = b;
 
1008
}
 
1009
 
 
1010
 
 
1011
/*!
 
1012
    \property QLineEdit::acceptableInput
 
1013
    \brief whether the input satisfies the inputMask and the
 
1014
    validator.
 
1015
 
 
1016
    \sa setInputMask(), setValidator()
 
1017
*/
 
1018
bool QLineEdit::hasAcceptableInput() const
 
1019
{
 
1020
    Q_D(const QLineEdit);
 
1021
    return d->hasAcceptableInput(d->text);
 
1022
}
 
1023
 
 
1024
/*!
 
1025
    \property QLineEdit::inputMask
 
1026
    \brief The validation input mask
 
1027
 
 
1028
    If no mask is set, inputMask() returns an empty string.
 
1029
 
 
1030
    Sets the QLineEdit's validation mask. Validators can be used
 
1031
    instead of, or in conjunction with masks; see setValidator().
 
1032
 
 
1033
    Unset the mask and return to normal QLineEdit operation by passing
 
1034
    an empty string ("") or just calling setInputMask() with no
 
1035
    arguments.
 
1036
 
 
1037
    The mask format understands these mask characters:
 
1038
    \table
 
1039
    \header \i Character \i Meaning
 
1040
    \row \i \c A \i ASCII alphabetic character required. A-Z, a-z.
 
1041
    \row \i \c a \i ASCII alphabetic character permitted but not required.
 
1042
    \row \i \c N \i ASCII alphanumeric character required. A-Z, a-z, 0-9.
 
1043
    \row \i \c n \i ASCII alphanumeric character permitted but not required.
 
1044
    \row \i \c X \i Any character required.
 
1045
    \row \i \c x \i Any character permitted but not required.
 
1046
    \row \i \c 9 \i ASCII digit required. 0-9.
 
1047
    \row \i \c 0 \i ASCII digit permitted but not required.
 
1048
    \row \i \c D \i ASCII digit required. 1-9.
 
1049
    \row \i \c d \i ASCII digit permitted but not required (1-9).
 
1050
    \row \i \c # \i ASCII digit or plus/minus sign permitted but not required.
 
1051
    \row \i \c > \i All following alphabetic characters are uppercased.
 
1052
    \row \i \c < \i All following alphabetic characters are lowercased.
 
1053
    \row \i \c ! \i Switch off case conversion.
 
1054
    \row \i <tt>\\</tt> \i Use <tt>\\</tt> to escape the special
 
1055
                           characters listed above to use them as
 
1056
                           separators.
 
1057
    \endtable
 
1058
 
 
1059
    The mask consists of a string of mask characters and separators,
 
1060
    optionally followed by a semicolon and the character used for
 
1061
    blanks: the blank characters are always removed from the text
 
1062
    after editing. The default blank character is space.
 
1063
 
 
1064
    Examples:
 
1065
    \table
 
1066
    \header \i Mask \i Notes
 
1067
    \row \i \c 000.000.000.000;_ \i IP address; blanks are \c{_}.
 
1068
    \row \i \c 0000-00-00 \i ISO Date; blanks are \c space
 
1069
    \row \i \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \i License number;
 
1070
    blanks are \c - and all (alphabetic) characters are converted to
 
1071
    uppercase.
 
1072
    \endtable
 
1073
 
 
1074
    To get range control (e.g. for an IP address) use masks together
 
1075
    with \link setValidator() validators\endlink.
 
1076
 
 
1077
    \sa maxLength
 
1078
*/
 
1079
QString QLineEdit::inputMask() const
 
1080
{
 
1081
    Q_D(const QLineEdit);
 
1082
    return (d->maskData ? d->inputMask + ';' + d->blank : QString());
 
1083
}
 
1084
 
 
1085
void QLineEdit::setInputMask(const QString &inputMask)
 
1086
{
 
1087
    Q_D(QLineEdit);
 
1088
    d->parseInputMask(inputMask);
 
1089
    if (d->maskData)
 
1090
        d->moveCursor(d->nextMaskBlank(0));
 
1091
}
 
1092
 
 
1093
/*!
 
1094
    Selects all the text (i.e. highlights it) and moves the cursor to
 
1095
    the end. This is useful when a default value has been inserted
 
1096
    because if the user types before clicking on the widget, the
 
1097
    selected text will be deleted.
 
1098
 
 
1099
    \sa setSelection() deselect()
 
1100
*/
 
1101
 
 
1102
void QLineEdit::selectAll()
 
1103
{
 
1104
    Q_D(QLineEdit);
 
1105
    d->selstart = d->selend = d->cursor = 0;
 
1106
    d->moveCursor(d->text.length(), true);
 
1107
}
 
1108
 
 
1109
/*!
 
1110
    Deselects any selected text.
 
1111
 
 
1112
    \sa setSelection() selectAll()
 
1113
*/
 
1114
 
 
1115
void QLineEdit::deselect()
 
1116
{
 
1117
    Q_D(QLineEdit);
 
1118
    d->deselect();
 
1119
    d->finishChange();
 
1120
}
 
1121
 
 
1122
 
 
1123
/*!
 
1124
    Deletes any selected text, inserts \a newText, and validates the
 
1125
    result. If it is valid, it sets it as the new contents of the line
 
1126
    edit.
 
1127
 
 
1128
    \sa setText(), clear()
 
1129
*/
 
1130
void QLineEdit::insert(const QString &newText)
 
1131
{
 
1132
//     q->resetInputContext(); //#### FIX ME IN QT
 
1133
    Q_D(QLineEdit);
 
1134
    int priorState = d->undoState;
 
1135
    d->removeSelectedText();
 
1136
    d->insert(newText);
 
1137
    d->finishChange(priorState);
 
1138
}
 
1139
 
 
1140
/*!
 
1141
    Clears the contents of the line edit.
 
1142
 
 
1143
    \sa setText(), insert()
 
1144
*/
 
1145
void QLineEdit::clear()
 
1146
{
 
1147
    Q_D(QLineEdit);
 
1148
    int priorState = d->undoState;
 
1149
    resetInputContext();
 
1150
    d->selstart = 0;
 
1151
    d->selend = d->text.length();
 
1152
    d->removeSelectedText();
 
1153
    d->separate();
 
1154
    d->finishChange(priorState);
 
1155
}
 
1156
 
 
1157
/*!
 
1158
    Undoes the last operation if undo is \link
 
1159
    QLineEdit::undoAvailable available\endlink. Deselects any current
 
1160
    selection, and updates the selection start to the current cursor
 
1161
    position.
 
1162
*/
 
1163
void QLineEdit::undo()
 
1164
{
 
1165
    Q_D(QLineEdit);
 
1166
    resetInputContext();
 
1167
    d->undo();
 
1168
    d->finishChange(-1, true);
 
1169
}
 
1170
 
 
1171
/*!
 
1172
    Redoes the last operation if redo is \link
 
1173
    QLineEdit::redoAvailable available\endlink.
 
1174
*/
 
1175
void QLineEdit::redo()
 
1176
{
 
1177
    Q_D(QLineEdit);
 
1178
    resetInputContext();
 
1179
    d->redo();
 
1180
    d->finishChange();
 
1181
}
 
1182
 
 
1183
 
 
1184
/*!
 
1185
    \property QLineEdit::readOnly
 
1186
    \brief whether the line edit is read only.
 
1187
 
 
1188
    In read-only mode, the user can still copy the text to the
 
1189
    clipboard, or drag and drop the text (if echoMode() is \c Normal),
 
1190
    but cannot edit it.
 
1191
 
 
1192
    QLineEdit does not show a cursor in read-only mode.
 
1193
 
 
1194
    \sa setEnabled()
 
1195
*/
 
1196
 
 
1197
bool QLineEdit::isReadOnly() const
 
1198
{
 
1199
    Q_D(const QLineEdit);
 
1200
    return d->readOnly;
 
1201
}
 
1202
 
 
1203
void QLineEdit::setReadOnly(bool enable)
 
1204
{
 
1205
    Q_D(QLineEdit);
 
1206
    d->readOnly = enable;
 
1207
    update();
 
1208
}
 
1209
 
 
1210
 
 
1211
#ifndef QT_NO_CLIPBOARD
 
1212
/*!
 
1213
    Copies the selected text to the clipboard and deletes it, if there
 
1214
    is any, and if echoMode() is \c Normal.
 
1215
 
 
1216
    If the current validator disallows deleting the selected text,
 
1217
    cut() will copy without deleting.
 
1218
 
 
1219
    \sa copy() paste() setValidator()
 
1220
*/
 
1221
 
 
1222
void QLineEdit::cut()
 
1223
{
 
1224
    if (hasSelectedText()) {
 
1225
        copy();
 
1226
        del();
 
1227
    }
 
1228
}
 
1229
 
 
1230
 
 
1231
/*!
 
1232
    Copies the selected text to the clipboard, if there is any, and if
 
1233
    echoMode() is \c Normal.
 
1234
 
 
1235
    \sa cut() paste()
 
1236
*/
 
1237
 
 
1238
void QLineEdit::copy() const
 
1239
{
 
1240
    Q_D(const QLineEdit);
 
1241
    d->copy();
 
1242
}
 
1243
 
 
1244
/*!
 
1245
    Inserts the clipboard's text at the cursor position, deleting any
 
1246
    selected text, providing the line edit is not \link
 
1247
    QLineEdit::readOnly read-only\endlink.
 
1248
 
 
1249
    If the end result would not be acceptable to the current
 
1250
    \link setValidator() validator\endlink, nothing happens.
 
1251
 
 
1252
    \sa copy() cut()
 
1253
*/
 
1254
 
 
1255
void QLineEdit::paste()
 
1256
{
 
1257
    insert(QApplication::clipboard()->text(QClipboard::Clipboard));
 
1258
}
 
1259
 
 
1260
void QLineEditPrivate::copy(bool clipboard) const
 
1261
{
 
1262
    Q_Q(const QLineEdit);
 
1263
    QString t = q->selectedText();
 
1264
    if (!t.isEmpty() && echoMode == QLineEdit::Normal) {
 
1265
        q->disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), q, 0);
 
1266
        QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection);
 
1267
        q->connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
 
1268
                 q, SLOT(clipboardChanged()));
 
1269
    }
 
1270
}
 
1271
 
 
1272
#endif // !QT_NO_CLIPBOARD
 
1273
 
 
1274
/*! \reimp
 
1275
*/
 
1276
bool QLineEdit::event(QEvent * e)
 
1277
{
 
1278
    Q_D(QLineEdit);
 
1279
    if (e->type() == QEvent::ShortcutOverride && !d->readOnly) {
 
1280
        QKeyEvent* ke = (QKeyEvent*) e;
 
1281
        if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
 
1282
             || ke->modifiers() == Qt::KeypadModifier) {
 
1283
            if (ke->key() < Qt::Key_Escape) {
 
1284
                ke->accept();
 
1285
            } else if (ke->modifiers() == Qt::NoModifier
 
1286
                        || ke->modifiers() == Qt::ShiftModifier) {
 
1287
                switch (ke->key()) {
 
1288
                case Qt::Key_Delete:
 
1289
                case Qt::Key_Home:
 
1290
                case Qt::Key_End:
 
1291
                case Qt::Key_Backspace:
 
1292
                case Qt::Key_Left:
 
1293
                case Qt::Key_Right:
 
1294
                    ke->accept();
 
1295
                default:
 
1296
                    break;
 
1297
                }
 
1298
            }
 
1299
        } else if (ke->modifiers() & Qt::ControlModifier) {
 
1300
            switch (ke->key()) {
 
1301
// Those are too frequently used for application functionality
 
1302
/*            case Qt::Key_A:
 
1303
            case Qt::Key_B:
 
1304
            case Qt::Key_D:
 
1305
            case Qt::Key_E:
 
1306
            case Qt::Key_F:
 
1307
            case Qt::Key_H:
 
1308
            case Qt::Key_K:
 
1309
*/
 
1310
            case Qt::Key_C:
 
1311
            case Qt::Key_V:
 
1312
            case Qt::Key_X:
 
1313
            case Qt::Key_Y:
 
1314
            case Qt::Key_Z:
 
1315
            case Qt::Key_Left:
 
1316
            case Qt::Key_Right:
 
1317
#if !defined(Q_WS_MAC)
 
1318
            case Qt::Key_Insert:
 
1319
            case Qt::Key_Delete:
 
1320
#endif
 
1321
                ke->accept();
 
1322
            default:
 
1323
                break;
 
1324
            }
 
1325
        }
 
1326
    } else if (e->type() == QEvent::Timer) {
 
1327
        // should be timerEvent, is here for binary compatibility
 
1328
        int timerId = ((QTimerEvent*)e)->timerId();
 
1329
        if (timerId == d->cursorTimer) {
 
1330
            QStyleOptionFrame opt = d->getStyleOption();
 
1331
            if(!hasSelectedText()
 
1332
               || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
 
1333
                d->setCursorVisible(!d->cursorVisible);
 
1334
#ifndef QT_NO_DRAGANDDROP
 
1335
        } else if (timerId == d->dndTimer.timerId()) {
 
1336
            d->drag();
 
1337
#endif
 
1338
        }
 
1339
        else if (timerId == d->tripleClickTimer.timerId())
 
1340
            d->tripleClickTimer.stop();
 
1341
    } else if (e->type() == QEvent::ContextMenu) {
 
1342
#ifndef QT_NO_IM
 
1343
        if (d->composeMode())
 
1344
            return true;
 
1345
#endif
 
1346
        d->separate();
 
1347
    }
 
1348
    return QWidget::event(e);
 
1349
}
 
1350
 
 
1351
/*! \reimp
 
1352
*/
 
1353
void QLineEdit::mousePressEvent(QMouseEvent* e)
 
1354
{
 
1355
    Q_D(QLineEdit);
 
1356
    if (d->sendMouseEventToInputContext(e))
 
1357
        return;
 
1358
    if (e->button() == Qt::RightButton)
 
1359
        return;
 
1360
    if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
 
1361
         QApplication::startDragDistance()) {
 
1362
        selectAll();
 
1363
        return;
 
1364
    }
 
1365
    bool mark = e->modifiers() & Qt::ShiftModifier;
 
1366
    int cursor = d->xToPos(e->pos().x());
 
1367
#ifndef QT_NO_DRAGANDDROP
 
1368
    if (!mark && d->dragEnabled && d->echoMode == Normal &&
 
1369
         e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) {
 
1370
        d->cursor = cursor;
 
1371
        update();
 
1372
        d->dndPos = e->pos();
 
1373
        if (!d->dndTimer.isActive())
 
1374
            d->dndTimer.start(QApplication::startDragTime(), this);
 
1375
        d->emitCursorPositionChanged();
 
1376
    } else
 
1377
#endif
 
1378
    {
 
1379
        d->moveCursor(cursor, mark);
 
1380
    }
 
1381
}
 
1382
 
 
1383
/*! \reimp
 
1384
*/
 
1385
void QLineEdit::mouseMoveEvent(QMouseEvent * e)
 
1386
{
 
1387
    Q_D(QLineEdit);
 
1388
    if (d->sendMouseEventToInputContext(e))
 
1389
        return;
 
1390
 
 
1391
    if (e->buttons() & Qt::LeftButton) {
 
1392
#ifndef QT_NO_DRAGANDDROP
 
1393
        if (d->dndTimer.isActive()) {
 
1394
            if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
 
1395
                d->drag();
 
1396
        } else
 
1397
#endif
 
1398
        {
 
1399
            d->moveCursor(d->xToPos(e->pos().x()), true);
 
1400
        }
 
1401
    }
 
1402
}
 
1403
 
 
1404
/*! \reimp
 
1405
*/
 
1406
void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
 
1407
{
 
1408
    Q_D(QLineEdit);
 
1409
    if (d->sendMouseEventToInputContext(e))
 
1410
        return;
 
1411
#ifndef QT_NO_DRAGANDDROP
 
1412
    if (e->button() == Qt::LeftButton) {
 
1413
        if (d->dndTimer.isActive()) {
 
1414
            d->dndTimer.stop();
 
1415
            deselect();
 
1416
            return;
 
1417
        }
 
1418
    }
 
1419
#endif
 
1420
#ifndef QT_NO_CLIPBOARD
 
1421
    if (QApplication::clipboard()->supportsSelection()) {
 
1422
        if (e->button() == Qt::LeftButton) {
 
1423
            d->copy(false);
 
1424
        } else if (!d->readOnly && e->button() == Qt::MidButton) {
 
1425
            d->deselect();
 
1426
            insert(QApplication::clipboard()->text(QClipboard::Selection));
 
1427
        }
 
1428
    }
 
1429
#endif
 
1430
}
 
1431
 
 
1432
/*! \reimp
 
1433
*/
 
1434
void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
 
1435
{
 
1436
    Q_D(QLineEdit);
 
1437
    if (d->sendMouseEventToInputContext(e))
 
1438
        return;
 
1439
    if (e->button() == Qt::LeftButton) {
 
1440
        deselect();
 
1441
        d->cursor = d->xToPos(e->pos().x());
 
1442
        d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords);
 
1443
        // ## text layout should support end of words.
 
1444
        int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords);
 
1445
        while (end > d->cursor && d->text[end-1].isSpace())
 
1446
            --end;
 
1447
        d->moveCursor(end, true);
 
1448
        d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
 
1449
        d->tripleClick = e->pos();
 
1450
    }
 
1451
}
 
1452
 
 
1453
/*!
 
1454
    \fn void  QLineEdit::returnPressed()
 
1455
 
 
1456
    This signal is emitted when the Return or Enter key is pressed.
 
1457
    Note that if there is a validator() or inputMask() set on the line
 
1458
    edit, the returnPressed() signal will only be emitted if the input
 
1459
    follows the inputMask() and the validator() returns \c Acceptable.
 
1460
*/
 
1461
 
 
1462
/*!
 
1463
    \fn void  QLineEdit::editingFinished()
 
1464
 
 
1465
    This signal is emitted when the Return or Enter key is pressed or
 
1466
    the line edit looses focus. Note that if there is a validator() or
 
1467
    inputMask() set on the line edit and enter/return is pressed, the
 
1468
    editingFinished() signal will only be emitted if the input follows
 
1469
    the inputMask() and the validator() returns \c Acceptable.
 
1470
*/
 
1471
 
 
1472
/*!
 
1473
    Converts the given key press \a event into a line edit action.
 
1474
 
 
1475
    If Return or Enter is pressed and the current text is valid (or
 
1476
    can be \link QValidator::fixup() made valid\endlink by the
 
1477
    validator), the signal returnPressed() is emitted.
 
1478
 
 
1479
    The default key bindings are listed in the class's detailed
 
1480
    description.
 
1481
*/
 
1482
 
 
1483
void QLineEdit::keyPressEvent(QKeyEvent *event)
 
1484
{
 
1485
    Q_D(QLineEdit);
 
1486
    d->setCursorVisible(true);
 
1487
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
 
1488
        const QValidator * v = d->validator;
 
1489
        if (hasAcceptableInput()) {
 
1490
            emit returnPressed();
 
1491
            emit editingFinished();
 
1492
        }
 
1493
#ifndef QT_NO_VALIDATOR
 
1494
        else {
 
1495
            QString textCopy = d->text;
 
1496
            int cursorCopy = d->cursor;
 
1497
            if (v && v->validate(textCopy, cursorCopy) != QValidator::Acceptable)
 
1498
                v->fixup(textCopy);
 
1499
 
 
1500
            if (d->hasAcceptableInput(textCopy)) {
 
1501
                if (v && (textCopy != d->text || cursorCopy != d->cursor))
 
1502
                    d->setText(textCopy, cursorCopy);
 
1503
                emit returnPressed();
 
1504
                emit editingFinished();
 
1505
            }
 
1506
        }
 
1507
#endif
 
1508
        event->ignore();
 
1509
        return;
 
1510
    }
 
1511
    bool unknown = false;
 
1512
 
 
1513
    if (event->modifiers() & Qt::ControlModifier) {
 
1514
        switch (event->key()) {
 
1515
        case Qt::Key_A:
 
1516
#if defined(Q_WS_X11)
 
1517
            home(event->modifiers() & Qt::ShiftModifier);
 
1518
#else
 
1519
            selectAll();
 
1520
#endif
 
1521
            break;
 
1522
        case Qt::Key_B:
 
1523
            cursorForward(event->modifiers() & Qt::ShiftModifier, -1);
 
1524
            break;
 
1525
#ifndef QT_NO_CLIPBOARD
 
1526
        case Qt::Key_C:
 
1527
            copy();
 
1528
            break;
 
1529
#endif
 
1530
        case Qt::Key_D:
 
1531
            if (!d->readOnly)
 
1532
                del();
 
1533
            break;
 
1534
        case Qt::Key_E:
 
1535
            end(event->modifiers() & Qt::ShiftModifier);
 
1536
            break;
 
1537
        case Qt::Key_F:
 
1538
            cursorForward(event->modifiers() & Qt::ShiftModifier, 1);
 
1539
            break;
 
1540
        case Qt::Key_H:
 
1541
            if (!d->readOnly)
 
1542
                backspace();
 
1543
            break;
 
1544
        case Qt::Key_K:
 
1545
            if (!d->readOnly) {
 
1546
                int priorState = d->undoState;
 
1547
                d->deselect();
 
1548
                while (d->cursor < (int) d->text.length())
 
1549
                    d->del();
 
1550
                d->finishChange(priorState);
 
1551
            }
 
1552
            break;
 
1553
#if defined(Q_WS_X11)
 
1554
        case Qt::Key_U:
 
1555
            if (!d->readOnly)
 
1556
                clear();
 
1557
            break;
 
1558
#endif
 
1559
#ifndef QT_NO_CLIPBOARD
 
1560
        case Qt::Key_V:
 
1561
            if (!d->readOnly)
 
1562
                paste();
 
1563
            break;
 
1564
        case Qt::Key_X:
 
1565
            if (!d->readOnly && d->hasSelectedText() && echoMode() == Normal) {
 
1566
                copy();
 
1567
                del();
 
1568
            }
 
1569
            break;
 
1570
#if !defined(Q_WS_MAC)
 
1571
        case Qt::Key_Insert:
 
1572
            copy();
 
1573
            break;
 
1574
#endif
 
1575
#endif
 
1576
        case Qt::Key_Delete:
 
1577
            if (!d->readOnly) {
 
1578
                cursorWordForward(true);
 
1579
                del();
 
1580
            }
 
1581
            break;
 
1582
        case Qt::Key_Backspace:
 
1583
            if (!d->readOnly) {
 
1584
                cursorWordBackward(true);
 
1585
                del();
 
1586
            }
 
1587
            break;
 
1588
        case Qt::Key_Right:
 
1589
        case Qt::Key_Left:
 
1590
            if ((layoutDirection() == Qt::RightToLeft) == (event->key() == Qt::Key_Right)) {
 
1591
#ifndef Q_WS_MAC
 
1592
                if (echoMode() == Normal)
 
1593
                    cursorWordBackward(event->modifiers() & Qt::ShiftModifier);
 
1594
                else
 
1595
#endif
 
1596
                    home(event->modifiers() & Qt::ShiftModifier);
 
1597
            } else {
 
1598
#ifndef Q_WS_MAC
 
1599
                if (echoMode() == Normal)
 
1600
                    cursorWordForward(event->modifiers() & Qt::ShiftModifier);
 
1601
                else
 
1602
#endif
 
1603
                    end(event->modifiers() & Qt::ShiftModifier);
 
1604
            }
 
1605
            break;
 
1606
        case Qt::Key_Z:
 
1607
            if (!d->readOnly) {
 
1608
                if(event->modifiers() & Qt::ShiftModifier)
 
1609
                    redo();
 
1610
                else
 
1611
                    undo();
 
1612
            }
 
1613
            break;
 
1614
        case Qt::Key_Y:
 
1615
            if (!d->readOnly)
 
1616
                redo();
 
1617
            break;
 
1618
        default:
 
1619
            unknown = true;
 
1620
        }
 
1621
    } else { // ### check for *no* modifier
 
1622
        switch (event->key()) {
 
1623
        case Qt::Key_Shift:
 
1624
            // ### TODO
 
1625
            break;
 
1626
        case Qt::Key_Left:
 
1627
        case Qt::Key_Right: {
 
1628
            int step =  ((layoutDirection() == Qt::RightToLeft) == (event->key() == Qt::Key_Right)) ? -1 : 1;
 
1629
#ifdef Q_WS_MAC
 
1630
            if (event->modifiers() & Qt::AltModifier) {
 
1631
                if (step < 0)
 
1632
                    cursorWordBackward(event->modifiers() & Qt::ShiftModifier);
 
1633
                else
 
1634
                    cursorWordForward(event->modifiers() & Qt::ShiftModifier);
 
1635
            } else if (event->modifiers() & Qt::MetaModifier) {
 
1636
                if (step < 0)
 
1637
                    home(event->modifiers() & Qt::ShiftModifier);
 
1638
                else
 
1639
                    end(event->modifiers() & Qt::ShiftModifier);
 
1640
            } else
 
1641
#endif
 
1642
            {
 
1643
                cursorForward(event->modifiers() & Qt::ShiftModifier, step);
 
1644
            }
 
1645
        }
 
1646
        break;
 
1647
        case Qt::Key_Backspace:
 
1648
            if (!d->readOnly)
 
1649
                backspace();
 
1650
            break;
 
1651
        case Qt::Key_Home:
 
1652
#ifdef Q_WS_MAC
 
1653
            break; // Home and End do nothing on the mac (but Up and Down do).
 
1654
        case Qt::Key_Up:
 
1655
#endif
 
1656
            home(event->modifiers() & Qt::ShiftModifier);
 
1657
            break;
 
1658
        case Qt::Key_End:
 
1659
#ifdef Q_WS_MAC
 
1660
            break;
 
1661
        case Qt::Key_Down:
 
1662
#endif
 
1663
            end(event->modifiers() & Qt::ShiftModifier);
 
1664
            break;
 
1665
        case Qt::Key_Delete:
 
1666
            if (!d->readOnly) {
 
1667
#if !defined(Q_WS_MAC)
 
1668
                if (event->modifiers() & Qt::ShiftModifier) {
 
1669
                    cut();
 
1670
                    break;
 
1671
                }
 
1672
#endif
 
1673
                del();
 
1674
            }
 
1675
            break;
 
1676
#if !defined(Q_WS_MAC)
 
1677
        case Qt::Key_Insert:
 
1678
            if (!d->readOnly && event->modifiers() & Qt::ShiftModifier)
 
1679
                paste();
 
1680
            else
 
1681
                unknown = true;
 
1682
            break;
 
1683
#endif
 
1684
        case Qt::Key_F14: // Undo key on Sun keyboards
 
1685
            if (!d->readOnly)
 
1686
                undo();
 
1687
            break;
 
1688
#ifndef QT_NO_CLIPBOARD
 
1689
        case Qt::Key_F16: // Copy key on Sun keyboards
 
1690
            copy();
 
1691
            break;
 
1692
        case Qt::Key_F18: // Paste key on Sun keyboards
 
1693
            if (!d->readOnly)
 
1694
                paste();
 
1695
            break;
 
1696
        case Qt::Key_F20: // Cut key on Sun keyboards
 
1697
            if (!d->readOnly && hasSelectedText() && echoMode() == Normal) {
 
1698
                copy();
 
1699
                del();
 
1700
            }
 
1701
            break;
 
1702
#endif
 
1703
        default:
 
1704
            unknown = true;
 
1705
        }
 
1706
    }
 
1707
    if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
 
1708
        setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
 
1709
        d->updateTextLayout();
 
1710
        update();
 
1711
        unknown = false;
 
1712
    }
 
1713
 
 
1714
    if (unknown && !d->readOnly) {
 
1715
        QString t = event->text();
 
1716
        if (!t.isEmpty() && t.at(0).isPrint()) {
 
1717
            insert(t);
 
1718
            event->accept();
 
1719
            return;
 
1720
        }
 
1721
    }
 
1722
 
 
1723
    if (unknown)
 
1724
        event->ignore();
 
1725
    else
 
1726
        event->accept();
 
1727
}
 
1728
 
 
1729
/*!
 
1730
  This function is not intended as polymorphic usage. Just a shared code
 
1731
  fragment that calls QInputContext::mouseHandler for this
 
1732
  class.
 
1733
*/
 
1734
bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
 
1735
{
 
1736
    // ##### currently X11 only
 
1737
#if (defined(Q_WS_X11) || defined(Q_WS_QWS)) && !defined QT_NO_IM
 
1738
    Q_Q(QLineEdit);
 
1739
    if ( composeMode() ) {
 
1740
        int tmp_cursor = xToPosInternal( e->pos().x(), QTextLine::CursorOnCharacter );
 
1741
        int mousePos = tmp_cursor - cursor;
 
1742
        if ( mousePos < 0 || mousePos >= textLayout.preeditAreaText().length() ) {
 
1743
            mousePos = -1;
 
1744
            // don't send move events outside the preedit area
 
1745
            if ( e->type() == QEvent::MouseMove )
 
1746
                return TRUE;
 
1747
        }
 
1748
 
 
1749
        QInputContext *qic = q->inputContext();
 
1750
        if ( qic )
 
1751
            // may be causing reset() in some input methods
 
1752
            qic->mouseHandler(mousePos, e);
 
1753
        if (!textLayout.preeditAreaText().isEmpty())
 
1754
            return TRUE;
 
1755
    }
 
1756
#else
 
1757
    Q_UNUSED(e);
 
1758
#endif
 
1759
 
 
1760
    return FALSE;
 
1761
}
 
1762
 
 
1763
/*! \reimp
 
1764
 */
 
1765
void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
 
1766
{
 
1767
    Q_D(QLineEdit);
 
1768
    if (d->readOnly) {
 
1769
        e->ignore();
 
1770
        return;
 
1771
    }
 
1772
 
 
1773
    d->removeSelectedText();
 
1774
 
 
1775
    int c = d->cursor; // cursor position after insertion of commit string
 
1776
    if (e->replacementStart() <= 0)
 
1777
        c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength());
 
1778
 
 
1779
    d->cursor += e->replacementStart();
 
1780
 
 
1781
    // insert commit string
 
1782
    if (e->replacementLength()) {
 
1783
        d->selstart = d->cursor;
 
1784
        d->selend = d->selstart + e->replacementLength();
 
1785
        d->removeSelectedText();
 
1786
    }
 
1787
    if (!e->commitString().isEmpty())
 
1788
        d->insert(e->commitString());
 
1789
 
 
1790
    d->cursor = c;
 
1791
 
 
1792
    d->textLayout.setPreeditArea(d->cursor, e->preeditString());
 
1793
    QList<QTextLayout::FormatRange> formats;
 
1794
    for (int i = 0; i < e->attributes().size(); ++i) {
 
1795
        const QInputMethodEvent::Attribute &a = e->attributes().at(i);
 
1796
        if (a.type != QInputMethodEvent::TextFormat)
 
1797
            continue;
 
1798
        QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
 
1799
        if (f.isValid()) {
 
1800
            QTextLayout::FormatRange o;
 
1801
            o.start = a.start + d->cursor;
 
1802
            o.length = a.length;
 
1803
            o.format = f;
 
1804
            formats.append(o);
 
1805
        }
 
1806
    }
 
1807
    d->textLayout.setAdditionalFormats(formats);
 
1808
    d->updateTextLayout();
 
1809
    update();
 
1810
    if (!e->commitString().isEmpty())
 
1811
        d->emitCursorPositionChanged();
 
1812
}
 
1813
 
 
1814
/*!\reimp
 
1815
*/
 
1816
QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
 
1817
{
 
1818
    Q_D(const QLineEdit);
 
1819
    switch(property) {
 
1820
    case Qt::ImMicroFocus:
 
1821
        return d->cursorRect();
 
1822
    case Qt::ImFont:
 
1823
        return font();
 
1824
    case Qt::ImCursorPosition:
 
1825
        return QVariant(d->cursor);
 
1826
    case Qt::ImSurroundingText:
 
1827
        return QVariant(d->text);
 
1828
    case Qt::ImCurrentSelection:
 
1829
        return QVariant(selectedText());
 
1830
    default:
 
1831
        return QVariant();
 
1832
    }
 
1833
}
 
1834
 
 
1835
/*!\reimp
 
1836
*/
 
1837
 
 
1838
void QLineEdit::focusInEvent(QFocusEvent *e)
 
1839
{
 
1840
    Q_D(QLineEdit);
 
1841
    if (e->reason() == Qt::TabFocusReason ||
 
1842
         e->reason() == Qt::BacktabFocusReason  ||
 
1843
         e->reason() == Qt::ShortcutFocusReason)
 
1844
        d->maskData ? d->moveCursor(d->nextMaskBlank(0)) : selectAll();
 
1845
    if (!d->cursorTimer) {
 
1846
        int cft = QApplication::cursorFlashTime();
 
1847
        d->cursorTimer = cft ? startTimer(cft/2) : -1;
 
1848
    }
 
1849
    QStyleOptionFrame opt = d->getStyleOption();
 
1850
    if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty())
 
1851
       || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
 
1852
        d->setCursorVisible(true);
 
1853
#ifdef Q_WS_MAC
 
1854
    if(d->echoMode == Password || d->echoMode == NoEcho)
 
1855
        qt_mac_secure_keyboard(true);
 
1856
#endif
 
1857
    update();
 
1858
}
 
1859
 
 
1860
/*!\reimp
 
1861
*/
 
1862
 
 
1863
void QLineEdit::focusOutEvent(QFocusEvent *e)
 
1864
{
 
1865
    Q_D(QLineEdit);
 
1866
    if (e->reason() != Qt::ActiveWindowFocusReason &&
 
1867
         e->reason() != Qt::PopupFocusReason)
 
1868
        deselect();
 
1869
    d->setCursorVisible(false);
 
1870
    if (d->cursorTimer > 0)
 
1871
        killTimer(d->cursorTimer);
 
1872
    d->cursorTimer = 0;
 
1873
    if (e->reason() != Qt::PopupFocusReason) {
 
1874
        emit editingFinished();
 
1875
#ifdef QT3_SUPPORT
 
1876
        emit lostFocus();
 
1877
#endif
 
1878
    }
 
1879
#ifdef Q_WS_MAC
 
1880
    if(d->echoMode == Password || d->echoMode == NoEcho)
 
1881
        qt_mac_secure_keyboard(false);
 
1882
#endif
 
1883
    update();
 
1884
}
 
1885
 
 
1886
/*!\reimp
 
1887
*/
 
1888
void QLineEdit::paintEvent(QPaintEvent *)
 
1889
{
 
1890
    Q_D(QLineEdit);
 
1891
    QPainter p(this);
 
1892
 
 
1893
    QRect r = rect();
 
1894
    const QPalette &pal = palette();
 
1895
 
 
1896
    if (d->frame) {
 
1897
        int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
 
1898
        QStyleOptionFrame opt;
 
1899
        opt.init(this);
 
1900
        opt.lineWidth = frameWidth;
 
1901
        opt.midLineWidth = 0;
 
1902
        opt.state |= QStyle::State_Sunken;
 
1903
        style()->drawPrimitive(QStyle::PE_FrameLineEdit, &opt, &p, this);
 
1904
 
 
1905
        r.adjust(frameWidth, frameWidth, -frameWidth, -frameWidth);
 
1906
    }
 
1907
    p.setClipRect(r);
 
1908
 
 
1909
    QStyleOptionFrame panel = d->getStyleOption();
 
1910
    panel.state |= (isEnabled() ? QStyle::State_Enabled : QStyle::State_None);
 
1911
    style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this);
 
1912
 
 
1913
    QFontMetrics fm = fontMetrics();
 
1914
    QRect lineRect(r.x() + innerMargin, r.y() + (r.height() - fm.height() + 1) / 2,
 
1915
                    r.width() - 2*innerMargin, fm.height());
 
1916
    QTextLine line = d->textLayout.lineAt(0);
 
1917
 
 
1918
    // locate cursor position
 
1919
    int cix = qRound(line.cursorToX(d->cursor));
 
1920
 
 
1921
    // horizontal scrolling
 
1922
    int minLB = qMax(0, -fm.minLeftBearing());
 
1923
    int minRB = qMax(0, -fm.minRightBearing());
 
1924
 
 
1925
 
 
1926
    int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
 
1927
    if ((minLB + widthUsed) <=  lineRect.width()) {
 
1928
        Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment));
 
1929
        va &= ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask);
 
1930
        switch (va) {
 
1931
        case Qt::AlignRight:
 
1932
            d->hscroll = widthUsed - lineRect.width() + 1;
 
1933
            break;
 
1934
        case Qt::AlignHCenter:
 
1935
            d->hscroll = (widthUsed - lineRect.width()) / 2;
 
1936
            break;
 
1937
        default:
 
1938
            // Left
 
1939
            d->hscroll = 0;
 
1940
            break;
 
1941
        }
 
1942
        d->hscroll -= minLB;
 
1943
    } else if (cix - d->hscroll >= lineRect.width()) {
 
1944
        d->hscroll = cix - lineRect.width() + 1;
 
1945
    } else if (cix - d->hscroll < 0) {
 
1946
        d->hscroll = cix;
 
1947
    } else if (widthUsed - d->hscroll < lineRect.width()) {
 
1948
        d->hscroll = widthUsed - lineRect.width() + 1;
 
1949
    }
 
1950
    // the y offset is there to keep the baseline constant in case we have script changes in the text.
 
1951
    QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent-fm.ascent());
 
1952
 
 
1953
    // draw text, selections and cursors
 
1954
    p.setPen(pal.text().color());
 
1955
    bool supressCursor = d->readOnly;
 
1956
 
 
1957
    QVector<QTextLayout::FormatRange> selections;
 
1958
    if (d->selstart < d->selend || (d->cursorVisible && d->maskData)) {
 
1959
        QTextLayout::FormatRange o;
 
1960
        const QPalette &pal = palette();
 
1961
        if (d->selstart < d->selend) {
 
1962
            o.start = d->selstart;
 
1963
            o.length = d->selend - d->selstart;
 
1964
            o.format.setBackground(pal.brush(QPalette::Highlight));
 
1965
            o.format.setForeground(pal.brush(QPalette::HighlightedText));
 
1966
        } else {
 
1967
            // mask selection
 
1968
            o.start = d->cursor;
 
1969
            o.length = 1;
 
1970
            o.format.setBackground(pal.brush(QPalette::Text));
 
1971
            o.format.setForeground(pal.brush(QPalette::Background));
 
1972
        }
 
1973
        selections.append(o);
 
1974
    }
 
1975
 
 
1976
    // Asian users see an IM selection text as cursor on candidate
 
1977
    // selection phase of input method, so the ordinary cursor should be
 
1978
    // invisible if we have a preedit string.
 
1979
    bool showCursor = (d->cursorVisible && !supressCursor && !d->textLayout.preeditAreaText().length());
 
1980
    d->textLayout.draw(&p, topLeft, selections, r);
 
1981
    if (showCursor && d->textLayout.preeditAreaText().isEmpty())
 
1982
        d->textLayout.drawCursor(&p, topLeft, d->cursor);
 
1983
 
 
1984
}
 
1985
 
 
1986
 
 
1987
#ifndef QT_NO_DRAGANDDROP
 
1988
/*!\reimp
 
1989
*/
 
1990
void QLineEdit::dragMoveEvent(QDragMoveEvent *e)
 
1991
{
 
1992
    Q_D(QLineEdit);
 
1993
    if (!d->readOnly && e->mimeData()->hasFormat("text/plain")) {
 
1994
        e->acceptProposedAction();
 
1995
        d->cursor = d->xToPos(e->pos().x());
 
1996
        d->cursorVisible = true;
 
1997
        update();
 
1998
        d->emitCursorPositionChanged();
 
1999
    }
 
2000
}
 
2001
 
 
2002
/*!\reimp */
 
2003
void QLineEdit::dragEnterEvent(QDragEnterEvent * e)
 
2004
{
 
2005
    QLineEdit::dragMoveEvent(e);
 
2006
}
 
2007
 
 
2008
/*!\reimp */
 
2009
void QLineEdit::dragLeaveEvent(QDragLeaveEvent *)
 
2010
{
 
2011
    Q_D(QLineEdit);
 
2012
    if (d->cursorVisible) {
 
2013
        d->cursorVisible = false;
 
2014
        update();
 
2015
    }
 
2016
}
 
2017
 
 
2018
/*!\reimp */
 
2019
void QLineEdit::dropEvent(QDropEvent* e)
 
2020
{
 
2021
    Q_D(QLineEdit);
 
2022
    QString str = e->mimeData()->text();
 
2023
 
 
2024
    if (!str.isNull() && !d->readOnly) {
 
2025
        if (e->source() == this && e->dropAction() == Qt::CopyAction)
 
2026
            deselect();
 
2027
        d->cursor =d->xToPos(e->pos().x());
 
2028
        int selStart = d->cursor;
 
2029
        int oldSelStart = d->selstart;
 
2030
        int oldSelEnd = d->selend;
 
2031
        d->cursorVisible = false;
 
2032
        e->acceptProposedAction();
 
2033
        insert(str);
 
2034
        if (e->source() == this) {
 
2035
            if (e->dropAction() == Qt::MoveAction) {
 
2036
                if (selStart > oldSelStart && selStart <= oldSelEnd)
 
2037
                    setSelection(oldSelStart, str.length());
 
2038
                else if (selStart > oldSelEnd)
 
2039
                    setSelection(selStart - str.length(), str.length());
 
2040
                else
 
2041
                    setSelection(selStart, str.length());
 
2042
            } else {
 
2043
                setSelection(selStart, str.length());
 
2044
            }
 
2045
        }
 
2046
    } else {
 
2047
        e->ignore();
 
2048
        update();
 
2049
    }
 
2050
}
 
2051
 
 
2052
void QLineEditPrivate::drag()
 
2053
{
 
2054
    Q_Q(QLineEdit);
 
2055
    dndTimer.stop();
 
2056
    QMimeData *data = new QMimeData;
 
2057
    data->setText(q->selectedText());
 
2058
    QDrag *drag = new QDrag(q);
 
2059
    drag->setMimeData(data);
 
2060
    Qt::DropAction action = drag->start();
 
2061
    if (action == Qt::MoveAction && !readOnly && drag->target() != q) {
 
2062
        int priorState = undoState;
 
2063
        removeSelectedText();
 
2064
        finishChange(priorState);
 
2065
    }
 
2066
}
 
2067
 
 
2068
#endif // QT_NO_DRAGANDDROP
 
2069
 
 
2070
/*!
 
2071
    Shows the standard context menu created with
 
2072
    createStandardContextMenu().
 
2073
 
 
2074
    If you do not want the line edit to have a context menu, you can set
 
2075
    its \l contextMenuPolicy to Qt::NoContextMenu. If you want to
 
2076
    customize the context menu, reimplement this function. If you want
 
2077
    to extend the standard context menu, reimplement this function, call
 
2078
    createStandardContextMenu() and extend the menu returned.
 
2079
 
 
2080
    \code
 
2081
        void LineEdit::contextMenuEvent(QContextMenuEvent *event)
 
2082
        {
 
2083
            QMenu *menu = createStandardContextMenu();
 
2084
            menu->addAction(tr("My Menu Item"));
 
2085
            //...
 
2086
            menu->exec(event->globalPos());
 
2087
            delete menu;
 
2088
        }
 
2089
    \endcode
 
2090
 
 
2091
    The \a event parameter is used to obtain the position where
 
2092
    the mouse cursor was when the event was generated.
 
2093
 
 
2094
    \sa setContextMenuPolicy()
 
2095
*/
 
2096
void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
 
2097
{
 
2098
    QMenu *menu = createStandardContextMenu();
 
2099
    menu->exec(event->globalPos());
 
2100
    delete menu;
 
2101
}
 
2102
 
 
2103
/*!  This function creates the standard context menu which is shown
 
2104
  when the user clicks on the line edit with the right mouse
 
2105
  button. It is called from the default contextMenuEvent() handler.
 
2106
  The popup menu's ownership is transferred to the caller.
 
2107
*/
 
2108
 
 
2109
QMenu *QLineEdit::createStandardContextMenu()
 
2110
{
 
2111
    Q_D(QLineEdit);
 
2112
#ifndef QT_NO_POPUPMENU
 
2113
    d->actions[QLineEditPrivate::UndoAct]->setEnabled(d->isUndoAvailable());
 
2114
    d->actions[QLineEditPrivate::RedoAct]->setEnabled(d->isRedoAvailable());
 
2115
#ifndef QT_NO_CLIPBOARD
 
2116
    d->actions[QLineEditPrivate::CutAct]->setEnabled(!d->readOnly && d->hasSelectedText());
 
2117
    d->actions[QLineEditPrivate::CopyAct]->setEnabled(d->hasSelectedText());
 
2118
    d->actions[QLineEditPrivate::PasteAct]->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty());
 
2119
#else
 
2120
    d->actions[QLineEditPrivate::CutAct]->setEnabled(false);
 
2121
    d->actions[QLineEditPrivate::CopyAct]->setEnabled(false);
 
2122
    d->actions[QLineEditPrivate::PasteAct]->setEnabled(false);
 
2123
#endif
 
2124
    d->actions[QLineEditPrivate::ClearAct]->setEnabled(!d->readOnly && !d->text.isEmpty());
 
2125
    d->actions[QLineEditPrivate::SelectAllAct]->setEnabled(!d->text.isEmpty() && !d->allSelected());
 
2126
 
 
2127
    QMenu *popup = new QMenu(this);
 
2128
    popup->setObjectName("qt_edit_menu");
 
2129
    popup->addAction(d->actions[QLineEditPrivate::UndoAct]);
 
2130
    popup->addAction(d->actions[QLineEditPrivate::RedoAct]);
 
2131
    popup->addSeparator();
 
2132
    popup->addAction(d->actions[QLineEditPrivate::CutAct]);
 
2133
    popup->addAction(d->actions[QLineEditPrivate::CopyAct]);
 
2134
    popup->addAction(d->actions[QLineEditPrivate::PasteAct]);
 
2135
    popup->addAction(d->actions[QLineEditPrivate::ClearAct]);
 
2136
    popup->addSeparator();
 
2137
    popup->addAction(d->actions[QLineEditPrivate::SelectAllAct]);
 
2138
#if (defined(Q_WS_X11) || defined(Q_WS_QWS)) && !defined(QT_NO_IM)
 
2139
    QInputContext *qic = inputContext();
 
2140
    if (qic) {
 
2141
        QList<QAction *> imActions = qic->actions();
 
2142
        for (int i = 0; i < imActions.size(); ++i)
 
2143
            popup->addAction(imActions.at(i));
 
2144
    }
 
2145
#endif
 
2146
    return popup;
 
2147
#else
 
2148
    return 0;
 
2149
#endif
 
2150
}
 
2151
 
 
2152
/*! \reimp */
 
2153
void QLineEdit::changeEvent(QEvent *ev)
 
2154
{
 
2155
    Q_D(QLineEdit);
 
2156
    if(ev->type() == QEvent::ActivationChange) {
 
2157
        if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
 
2158
            update();
 
2159
    } else if (ev->type() == QEvent::FontChange) {
 
2160
        d->updateTextLayout();
 
2161
    }
 
2162
    QWidget::changeEvent(ev);
 
2163
}
 
2164
 
 
2165
void QLineEditPrivate::clipboardChanged()
 
2166
{
 
2167
}
 
2168
 
 
2169
void QLineEditPrivate::init(const QString& txt)
 
2170
{
 
2171
    Q_Q(QLineEdit);
 
2172
#ifndef QT_NO_CURSOR
 
2173
    q->setCursor(Qt::IBeamCursor);
 
2174
#endif
 
2175
    q->setFocusPolicy(Qt::StrongFocus);
 
2176
    q->setAttribute(Qt::WA_InputMethodEnabled);
 
2177
    //   Specifies that this widget can use more, but is able to survive on
 
2178
    //   less, horizontal space; and is fixed vertically.
 
2179
    q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
 
2180
    q->setBackgroundRole(QPalette::Base);
 
2181
    q->setAttribute(Qt::WA_KeyCompression);
 
2182
    q->setMouseTracking(true);
 
2183
    q->setAcceptDrops(true);
 
2184
    text = txt;
 
2185
    updateTextLayout();
 
2186
    cursor = text.length();
 
2187
 
 
2188
    actions[UndoAct] = new QAction(q->tr("&Undo") + ACCEL_KEY(Z), q);
 
2189
    QObject::connect(actions[UndoAct], SIGNAL(triggered()), q, SLOT(undo()));
 
2190
    actions[RedoAct] = new QAction(q->tr("&Redo") + ACCEL_KEY(Y), q);
 
2191
    QObject::connect(actions[RedoAct], SIGNAL(triggered()), q, SLOT(redo()));
 
2192
    //popup->insertSeparator();
 
2193
    actions[CutAct] = new QAction(q->tr("Cu&t") + ACCEL_KEY(X), q);
 
2194
    QObject::connect(actions[CutAct], SIGNAL(triggered()), q, SLOT(cut()));
 
2195
    actions[CopyAct] = new QAction(q->tr("&Copy") + ACCEL_KEY(C), q);
 
2196
    QObject::connect(actions[CopyAct], SIGNAL(triggered()), q, SLOT(copy()));
 
2197
    actions[PasteAct] = new QAction(q->tr("&Paste") + ACCEL_KEY(V), q);
 
2198
    QObject::connect(actions[PasteAct], SIGNAL(triggered()), q, SLOT(paste()));
 
2199
    actions[ClearAct] = new QAction(q->tr("Clear"), q);
 
2200
    QObject::connect(actions[ClearAct], SIGNAL(triggered()), q, SLOT(clear()));
 
2201
    //popup->insertSeparator();
 
2202
    actions[SelectAllAct] = new QAction(q->tr("Select All")
 
2203
#ifndef Q_WS_X11
 
2204
                                        + ACCEL_KEY(A)
 
2205
#endif
 
2206
                                        , q);
 
2207
    QObject::connect(actions[SelectAllAct], SIGNAL(triggered()), q, SLOT(selectAll()));
 
2208
}
 
2209
 
 
2210
void QLineEditPrivate::updateTextLayout()
 
2211
{
 
2212
    // replace all non-printable characters with spaces (to avoid
 
2213
    // drawing boxes when using fonts that don't have glyphs for such
 
2214
    // characters)
 
2215
    Q_Q(QLineEdit);
 
2216
    QString str = q->displayText();
 
2217
    QChar* uc = str.data();
 
2218
    for (int i = 0; i < (int)str.length(); ++i) {
 
2219
        if (! uc[i].isPrint())
 
2220
            uc[i] = QChar(0x0020);
 
2221
    }
 
2222
    textLayout.setFont(q->font());
 
2223
    textLayout.setText(str);
 
2224
    QTextOption option;
 
2225
    option.setTextDirection(q->layoutDirection());
 
2226
    option.setFlags(QTextOption::IncludeTrailingSpaces);
 
2227
    textLayout.setTextOption(option);
 
2228
 
 
2229
    textLayout.beginLayout();
 
2230
    QTextLine l = textLayout.createLine();
 
2231
    textLayout.endLayout();
 
2232
    ascent = qRound(l.ascent());
 
2233
}
 
2234
 
 
2235
int QLineEditPrivate::xToPosInternal(int x, QTextLine::CursorPosition betweenOrOn) const
 
2236
{
 
2237
    Q_Q(const QLineEdit);
 
2238
    x-= q->contentsRect().x() - hscroll + innerMargin;
 
2239
    QTextLine l = textLayout.lineAt(0);
 
2240
    if (x >= 0 && x < l.naturalTextWidth())
 
2241
        return l.xToCursor(x, betweenOrOn);
 
2242
    return x < 0 ? -1 : text.length();
 
2243
}
 
2244
 
 
2245
 
 
2246
int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
 
2247
{
 
2248
    int pos = xToPosInternal(x, betweenOrOn);
 
2249
    return (pos < 0) ? 0 : pos;
 
2250
}
 
2251
 
 
2252
 
 
2253
QRect QLineEditPrivate::cursorRect() const
 
2254
{
 
2255
    Q_Q(const QLineEdit);
 
2256
    QRect cr = q->contentsRect();
 
2257
    int cix = cr.x() - hscroll + innerMargin;
 
2258
    QTextLine l = textLayout.lineAt(0);
 
2259
    cix += qRound(l.cursorToX(cursor));
 
2260
    int ch = qMin(cr.height(), q->fontMetrics().height() + 1);
 
2261
    return QRect(cix-5, cr.y() + (cr.height() -  ch) / 2, 10, ch);
 
2262
}
 
2263
 
 
2264
void QLineEditPrivate::moveCursor(int pos, bool mark)
 
2265
{
 
2266
    Q_Q(QLineEdit);
 
2267
    if (pos != cursor) {
 
2268
        separate();
 
2269
        if (maskData)
 
2270
            pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
 
2271
    }
 
2272
    bool fullUpdate = mark || hasSelectedText();
 
2273
    if (mark) {
 
2274
        int anchor;
 
2275
        if (selend > selstart && cursor == selstart)
 
2276
            anchor = selend;
 
2277
        else if (selend > selstart && cursor == selend)
 
2278
            anchor = selstart;
 
2279
        else
 
2280
            anchor = cursor;
 
2281
        selstart = qMin(anchor, pos);
 
2282
        selend = qMax(anchor, pos);
 
2283
        updateTextLayout();
 
2284
    } else {
 
2285
        deselect();
 
2286
    }
 
2287
    if (fullUpdate) {
 
2288
        cursor = pos;
 
2289
        q->update();
 
2290
    } else {
 
2291
        setCursorVisible(false);
 
2292
        cursor = pos;
 
2293
        setCursorVisible(true);
 
2294
    }
 
2295
    QStyleOptionFrame opt = getStyleOption();
 
2296
    if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q))
 
2297
        setCursorVisible(false);
 
2298
    if (mark || selDirty) {
 
2299
        selDirty = false;
 
2300
        emit q->selectionChanged();
 
2301
    }
 
2302
    emitCursorPositionChanged();
 
2303
}
 
2304
 
 
2305
void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited)
 
2306
{
 
2307
    Q_Q(QLineEdit);
 
2308
    bool lineDirty = selDirty;
 
2309
    if (textDirty) {
 
2310
        // do validation
 
2311
        bool wasValidInput = validInput;
 
2312
        validInput = true;
 
2313
#ifndef QT_NO_VALIDATOR
 
2314
        if (validator && validateFromState >= 0) {
 
2315
            QString textCopy = text;
 
2316
            int cursorCopy = cursor;
 
2317
            validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
 
2318
            if (validInput) {
 
2319
                if (text != textCopy) {
 
2320
                    setText(textCopy, cursorCopy);
 
2321
                    return;
 
2322
                }
 
2323
                cursor = cursorCopy;
 
2324
            }
 
2325
        }
 
2326
#endif
 
2327
        if (validateFromState >= 0 && wasValidInput && !validInput) {
 
2328
            undo(validateFromState);
 
2329
            history.resize(undoState);
 
2330
            if (modifiedState > undoState)
 
2331
                modifiedState = -1;
 
2332
            validInput = true;
 
2333
            textDirty = false;
 
2334
        }
 
2335
        updateTextLayout();
 
2336
        lineDirty |= textDirty;
 
2337
        if (textDirty) {
 
2338
            textDirty = false;
 
2339
            QString actualText = maskData ? stripString(text) : text;
 
2340
            if (edited)
 
2341
                emit q->textEdited(actualText);
 
2342
            emit q->textChanged(actualText);
 
2343
        }
 
2344
#ifndef QT_NO_ACCESSIBILITY
 
2345
        QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
 
2346
#endif
 
2347
    }
 
2348
    if (selDirty) {
 
2349
        selDirty = false;
 
2350
        emit q->selectionChanged();
 
2351
    }
 
2352
    if (lineDirty || update)
 
2353
        q->update();
 
2354
    emitCursorPositionChanged();
 
2355
}
 
2356
 
 
2357
void QLineEditPrivate::emitCursorPositionChanged()
 
2358
{
 
2359
    Q_Q(QLineEdit);
 
2360
    if (cursor != lastCursorPos) {
 
2361
        const int oldLast = lastCursorPos;
 
2362
        lastCursorPos = cursor;
 
2363
        emit q->cursorPositionChanged(oldLast, cursor);
 
2364
    }
 
2365
}
 
2366
 
 
2367
void QLineEditPrivate::setText(const QString& txt, int pos, bool edited)
 
2368
{
 
2369
    Q_Q(QLineEdit);
 
2370
    q->resetInputContext();
 
2371
    deselect();
 
2372
    QString oldText = text;
 
2373
    if (maskData) {
 
2374
        text = maskString(0, txt, true);
 
2375
        text += clearString(text.length(), maxLength - text.length());
 
2376
    } else {
 
2377
        text = txt.isEmpty() ? txt : txt.left(maxLength);
 
2378
    }
 
2379
    history.clear();
 
2380
    modifiedState =  undoState = 0;
 
2381
    cursor = (pos < 0 || pos > text.length()) ? text.length() : pos;
 
2382
    textDirty = (oldText != text);
 
2383
    finishChange(-1, true, edited);
 
2384
}
 
2385
 
 
2386
 
 
2387
void QLineEditPrivate::setCursorVisible(bool visible)
 
2388
{
 
2389
    Q_Q(QLineEdit);
 
2390
    if ((bool)cursorVisible == visible)
 
2391
        return;
 
2392
    if (cursorTimer)
 
2393
        cursorVisible = visible;
 
2394
    QRect r = cursorRect();
 
2395
    if (maskData || !q->contentsRect().contains(r))
 
2396
        q->update();
 
2397
    else
 
2398
        q->update(r);
 
2399
}
 
2400
 
 
2401
void QLineEditPrivate::addCommand(const Command& cmd)
 
2402
{
 
2403
    if (separator && undoState && history[undoState-1].type != Separator) {
 
2404
        history.resize(undoState + 2);
 
2405
        history[undoState++] = Command(Separator, 0, 0);
 
2406
    } else {
 
2407
        history.resize(undoState + 1);
 
2408
    }
 
2409
    separator = false;
 
2410
    history[undoState++] = cmd;
 
2411
}
 
2412
 
 
2413
void QLineEditPrivate::insert(const QString& s)
 
2414
{
 
2415
    if (maskData) {
 
2416
        QString ms = maskString(cursor, s);
 
2417
        for (int i = 0; i < (int) ms.length(); ++i) {
 
2418
            addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i)));
 
2419
            addCommand(Command(Insert, cursor+i, ms.at(i)));
 
2420
        }
 
2421
        text.replace(cursor, ms.length(), ms);
 
2422
        cursor += ms.length();
 
2423
        cursor = nextMaskBlank(cursor);
 
2424
    } else {
 
2425
        int remaining = maxLength - text.length();
 
2426
        text.insert(cursor, s.left(remaining));
 
2427
        for (int i = 0; i < (int) s.left(remaining).length(); ++i)
 
2428
            addCommand(Command(Insert, cursor++, s.at(i)));
 
2429
    }
 
2430
    textDirty = true;
 
2431
}
 
2432
 
 
2433
void QLineEditPrivate::del(bool wasBackspace)
 
2434
{
 
2435
    if (cursor < (int) text.length()) {
 
2436
        addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor)));
 
2437
        if (maskData) {
 
2438
            text.replace(cursor, 1, clearString(cursor, 1));
 
2439
            addCommand(Command(Insert, cursor, text.at(cursor)));
 
2440
        } else {
 
2441
            text.remove(cursor, 1);
 
2442
        }
 
2443
        textDirty = true;
 
2444
    }
 
2445
}
 
2446
 
 
2447
void QLineEditPrivate::removeSelectedText()
 
2448
{
 
2449
    if (selstart < selend && selend <= (int) text.length()) {
 
2450
        separate();
 
2451
        int i ;
 
2452
        if (selstart <= cursor && cursor < selend) {
 
2453
            // cursor is within the selection. Split up the commands
 
2454
            // to be able to restore the correct cursor position
 
2455
            for (i = cursor; i >= selstart; --i)
 
2456
                addCommand (Command(DeleteSelection, i, text.at(i)));
 
2457
            for (i = selend - 1; i > cursor; --i)
 
2458
                addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i)));
 
2459
        } else {
 
2460
            for (i = selend-1; i >= selstart; --i)
 
2461
                addCommand (Command(RemoveSelection, i, text.at(i)));
 
2462
        }
 
2463
        if (maskData) {
 
2464
            text.replace(selstart, selend - selstart,  clearString(selstart, selend - selstart));
 
2465
            for (int i = 0; i < selend - selstart; ++i)
 
2466
                addCommand(Command(Insert, selstart + i, text.at(selstart + i)));
 
2467
        } else {
 
2468
            text.remove(selstart, selend - selstart);
 
2469
        }
 
2470
        if (cursor > selstart)
 
2471
            cursor -= qMin(cursor, selend) - selstart;
 
2472
        deselect();
 
2473
        textDirty = true;
 
2474
    }
 
2475
}
 
2476
 
 
2477
void QLineEditPrivate::parseInputMask(const QString &maskFields)
 
2478
{
 
2479
    int delimiter = maskFields.indexOf(';');
 
2480
    if (maskFields.isEmpty() || delimiter == 0) {
 
2481
        if (maskData) {
 
2482
            delete [] maskData;
 
2483
            maskData = 0;
 
2484
            maxLength = 32767;
 
2485
            setText(QString());
 
2486
        }
 
2487
        return;
 
2488
    }
 
2489
 
 
2490
    if (delimiter == -1) {
 
2491
        blank = ' ';
 
2492
        inputMask = maskFields;
 
2493
    } else {
 
2494
        inputMask = maskFields.left(delimiter);
 
2495
        blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QChar(' ');
 
2496
    }
 
2497
 
 
2498
    // calculate maxLength / maskData length
 
2499
    maxLength = 0;
 
2500
    QChar c = 0;
 
2501
    for (int i=0; i<inputMask.length(); i++) {
 
2502
        c = inputMask.at(i);
 
2503
        if (i > 0 && inputMask.at(i-1) == '\\') {
 
2504
            maxLength++;
 
2505
            continue;
 
2506
        }
 
2507
        if (c != '\\' && c != '!' &&
 
2508
             c != '<' && c != '>' &&
 
2509
             c != '{' && c != '}' &&
 
2510
             c != '[' && c != ']')
 
2511
            maxLength++;
 
2512
    }
 
2513
 
 
2514
    delete [] maskData;
 
2515
    maskData = new MaskInputData[maxLength];
 
2516
 
 
2517
    MaskInputData::Casemode m = MaskInputData::NoCaseMode;
 
2518
    c = 0;
 
2519
    bool s;
 
2520
    bool escape = false;
 
2521
    int index = 0;
 
2522
    for (int i = 0; i < inputMask.length(); i++) {
 
2523
        c = inputMask.at(i);
 
2524
        if (escape) {
 
2525
            s = true;
 
2526
            maskData[index].maskChar = c;
 
2527
            maskData[index].separator = s;
 
2528
            maskData[index].caseMode = m;
 
2529
            index++;
 
2530
            escape = false;
 
2531
        } else if (c == '<') {
 
2532
                m = MaskInputData::Lower;
 
2533
        } else if (c == '>') {
 
2534
            m = MaskInputData::Upper;
 
2535
        } else if (c == '!') {
 
2536
            m = MaskInputData::NoCaseMode;
 
2537
        } else if (c != '{' && c != '}' && c != '[' && c != ']') {
 
2538
            switch (c.unicode()) {
 
2539
            case 'A':
 
2540
            case 'a':
 
2541
            case 'N':
 
2542
            case 'n':
 
2543
            case 'X':
 
2544
            case 'x':
 
2545
            case '9':
 
2546
            case '0':
 
2547
            case 'D':
 
2548
            case 'd':
 
2549
            case '#':
 
2550
                s = false;
 
2551
                break;
 
2552
            case '\\':
 
2553
                escape = true;
 
2554
            default:
 
2555
                s = true;
 
2556
                break;
 
2557
            }
 
2558
 
 
2559
            if (!escape) {
 
2560
                maskData[index].maskChar = c;
 
2561
                maskData[index].separator = s;
 
2562
                maskData[index].caseMode = m;
 
2563
                index++;
 
2564
            }
 
2565
        }
 
2566
    }
 
2567
    setText(text);
 
2568
}
 
2569
 
 
2570
 
 
2571
/* checks if the key is valid compared to the inputMask */
 
2572
bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const
 
2573
{
 
2574
    switch (mask.unicode()) {
 
2575
    case 'A':
 
2576
        if (key.isLetter())
 
2577
            return true;
 
2578
        break;
 
2579
    case 'a':
 
2580
        if (key.isLetter() || key == blank)
 
2581
            return true;
 
2582
        break;
 
2583
    case 'N':
 
2584
        if (key.isLetterOrNumber())
 
2585
            return true;
 
2586
        break;
 
2587
    case 'n':
 
2588
        if (key.isLetterOrNumber() || key == blank)
 
2589
            return true;
 
2590
        break;
 
2591
    case 'X':
 
2592
        if (key.isPrint())
 
2593
            return true;
 
2594
        break;
 
2595
    case 'x':
 
2596
        if (key.isPrint() || key == blank)
 
2597
            return true;
 
2598
        break;
 
2599
    case '9':
 
2600
        if (key.isNumber())
 
2601
            return true;
 
2602
        break;
 
2603
    case '0':
 
2604
        if (key.isNumber() || key == blank)
 
2605
            return true;
 
2606
        break;
 
2607
    case 'D':
 
2608
        if (key.isNumber() && key.digitValue() > 0)
 
2609
            return true;
 
2610
        break;
 
2611
    case 'd':
 
2612
        if ((key.isNumber() && key.digitValue() > 0) || key == blank)
 
2613
            return true;
 
2614
        break;
 
2615
    case '#':
 
2616
        if (key.isNumber() || key == '+' || key == '-' || key == blank)
 
2617
            return true;
 
2618
        break;
 
2619
    default:
 
2620
        break;
 
2621
    }
 
2622
    return false;
 
2623
}
 
2624
 
 
2625
bool QLineEditPrivate::hasAcceptableInput(const QString &str) const
 
2626
{
 
2627
#ifndef QT_NO_VALIDATOR
 
2628
    QString textCopy = str;
 
2629
    int cursorCopy = cursor;
 
2630
    if (validator && validator->validate(textCopy, cursorCopy)
 
2631
        != QValidator::Acceptable)
 
2632
        return false;
 
2633
#endif
 
2634
 
 
2635
    if (!maskData)
 
2636
        return true;
 
2637
 
 
2638
    if (str.length() != maxLength)
 
2639
        return false;
 
2640
 
 
2641
    for (int i=0; i < maxLength; ++i) {
 
2642
        if (maskData[i].separator) {
 
2643
            if (str.at(i) != maskData[i].maskChar)
 
2644
                return false;
 
2645
        } else {
 
2646
            if (!isValidInput(str.at(i), maskData[i].maskChar))
 
2647
                return false;
 
2648
        }
 
2649
    }
 
2650
    return true;
 
2651
}
 
2652
 
 
2653
/*
 
2654
  Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
 
2655
  specifies from where characters should be gotten when a separator is met in \a str - true means
 
2656
  that blanks will be used, false that previous input is used.
 
2657
  Calling this when no inputMask is set is undefined.
 
2658
*/
 
2659
QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const
 
2660
{
 
2661
    if (pos >= (uint)maxLength)
 
2662
        return QString::fromLatin1("");
 
2663
 
 
2664
    QString fill;
 
2665
    fill = clear ? clearString(0, maxLength) : text;
 
2666
 
 
2667
    int strIndex = 0;
 
2668
    QString s = QString::fromLatin1("");
 
2669
    int i = pos;
 
2670
    while (i < maxLength) {
 
2671
        if (strIndex < str.length()) {
 
2672
            if (maskData[i].separator) {
 
2673
                s += maskData[i].maskChar;
 
2674
                if (str[(int)strIndex] == maskData[i].maskChar)
 
2675
                    strIndex++;
 
2676
                ++i;
 
2677
            } else {
 
2678
                if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) {
 
2679
                    switch (maskData[i].caseMode) {
 
2680
                    case MaskInputData::Upper:
 
2681
                        s += str[(int)strIndex].toUpper();
 
2682
                        break;
 
2683
                    case MaskInputData::Lower:
 
2684
                        s += str[(int)strIndex].toLower();
 
2685
                        break;
 
2686
                    default:
 
2687
                        s += str[(int)strIndex];
 
2688
                    }
 
2689
                    ++i;
 
2690
                } else {
 
2691
                    // search for separator first
 
2692
                    int n = findInMask(i, true, true, str[(int)strIndex]);
 
2693
                    if (n != -1) {
 
2694
                        if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) {
 
2695
                            s += fill.mid(i, n-i+1);
 
2696
                            i = n + 1; // update i to find + 1
 
2697
                        }
 
2698
                    } else {
 
2699
                        // search for valid blank if not
 
2700
                        n = findInMask(i, true, false, str[(int)strIndex]);
 
2701
                        if (n != -1) {
 
2702
                            s += fill.mid(i, n-i);
 
2703
                            switch (maskData[n].caseMode) {
 
2704
                            case MaskInputData::Upper:
 
2705
                                s += str[(int)strIndex].toUpper();
 
2706
                                break;
 
2707
                            case MaskInputData::Lower:
 
2708
                                s += str[(int)strIndex].toLower();
 
2709
                                break;
 
2710
                            default:
 
2711
                                s += str[(int)strIndex];
 
2712
                            }
 
2713
                            i = n + 1; // updates i to find + 1
 
2714
                        }
 
2715
                    }
 
2716
                }
 
2717
                strIndex++;
 
2718
            }
 
2719
        } else
 
2720
            break;
 
2721
    }
 
2722
 
 
2723
    return s;
 
2724
}
 
2725
 
 
2726
 
 
2727
 
 
2728
/*
 
2729
  Returns a "cleared" string with only separators and blank chars.
 
2730
  Calling this when no inputMask is set is undefined.
 
2731
*/
 
2732
QString QLineEditPrivate::clearString(uint pos, uint len) const
 
2733
{
 
2734
    if (pos >= (uint)maxLength)
 
2735
        return QString();
 
2736
 
 
2737
    QString s;
 
2738
    int end = qMin((uint)maxLength, pos + len);
 
2739
    for (int i=pos; i<end; i++)
 
2740
        if (maskData[i].separator)
 
2741
            s += maskData[i].maskChar;
 
2742
        else
 
2743
            s += blank;
 
2744
 
 
2745
    return s;
 
2746
}
 
2747
 
 
2748
/*
 
2749
  Strips blank parts of the input in a QLineEdit when an inputMask is set,
 
2750
  separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
 
2751
*/
 
2752
QString QLineEditPrivate::stripString(const QString &str) const
 
2753
{
 
2754
    if (!maskData)
 
2755
        return str;
 
2756
 
 
2757
    QString s;
 
2758
    int end = qMin(maxLength, (int)str.length());
 
2759
    for (int i=0; i < end; i++)
 
2760
        if (maskData[i].separator)
 
2761
            s += maskData[i].maskChar;
 
2762
        else
 
2763
            if (str[i] != blank)
 
2764
                s += str[i];
 
2765
 
 
2766
    return s;
 
2767
}
 
2768
 
 
2769
/* searches forward/backward in maskData for either a separator or a blank */
 
2770
int QLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
 
2771
{
 
2772
    if (pos >= maxLength || pos < 0)
 
2773
        return -1;
 
2774
 
 
2775
    int end = forward ? maxLength : -1;
 
2776
    int step = forward ? 1 : -1;
 
2777
    int i = pos;
 
2778
 
 
2779
    while (i != end) {
 
2780
        if (findSeparator) {
 
2781
            if (maskData[i].separator && maskData[i].maskChar == searchChar)
 
2782
                return i;
 
2783
        } else {
 
2784
            if (!maskData[i].separator) {
 
2785
                if (searchChar.isNull())
 
2786
                    return i;
 
2787
                else if (isValidInput(searchChar, maskData[i].maskChar))
 
2788
                    return i;
 
2789
            }
 
2790
        }
 
2791
        i += step;
 
2792
    }
 
2793
    return -1;
 
2794
}
 
2795
 
 
2796
void QLineEditPrivate::undo(int until)
 
2797
{
 
2798
    if (!isUndoAvailable())
 
2799
        return;
 
2800
    deselect();
 
2801
    while (undoState && undoState > until) {
 
2802
        Command& cmd = history[--undoState];
 
2803
        switch (cmd.type) {
 
2804
        case Insert:
 
2805
            text.remove(cmd.pos, 1);
 
2806
            cursor = cmd.pos;
 
2807
            break;
 
2808
        case Remove:
 
2809
        case RemoveSelection:
 
2810
            text.insert(cmd.pos, cmd.uc);
 
2811
            cursor = cmd.pos + 1;
 
2812
            break;
 
2813
        case Delete:
 
2814
        case DeleteSelection:
 
2815
            text.insert(cmd.pos, cmd.uc);
 
2816
            cursor = cmd.pos;
 
2817
            break;
 
2818
        case Separator:
 
2819
            continue;
 
2820
        }
 
2821
        if (until < 0 && undoState) {
 
2822
            Command& next = history[undoState-1];
 
2823
            if (next.type != cmd.type && next.type < RemoveSelection
 
2824
                 && !(cmd.type >= RemoveSelection && next.type != Separator))
 
2825
                break;
 
2826
        }
 
2827
    }
 
2828
    textDirty = true;
 
2829
    emitCursorPositionChanged();
 
2830
}
 
2831
 
 
2832
void QLineEditPrivate::redo() {
 
2833
    if (!isRedoAvailable())
 
2834
        return;
 
2835
    deselect();
 
2836
    while (undoState < (int)history.size()) {
 
2837
        Command& cmd = history[undoState++];
 
2838
        switch (cmd.type) {
 
2839
        case Insert:
 
2840
            text.insert(cmd.pos, cmd.uc);
 
2841
            cursor = cmd.pos + 1;
 
2842
            break;
 
2843
        case Remove:
 
2844
        case Delete:
 
2845
        case RemoveSelection:
 
2846
        case DeleteSelection:
 
2847
            text.remove(cmd.pos, 1);
 
2848
            cursor = cmd.pos;
 
2849
            break;
 
2850
        case Separator:
 
2851
            continue;
 
2852
        }
 
2853
        if (undoState < (int)history.size()) {
 
2854
            Command& next = history[undoState];
 
2855
            if (next.type != cmd.type && cmd.type < RemoveSelection
 
2856
                 && !(next.type >= RemoveSelection && cmd.type != Separator))
 
2857
                break;
 
2858
        }
 
2859
    }
 
2860
    textDirty = true;
 
2861
    emitCursorPositionChanged();
 
2862
}
 
2863
 
 
2864
/*!
 
2865
    \fn void QLineEdit::repaintArea(int a, int b)
 
2866
 
 
2867
    Use update() instead.
 
2868
*/
 
2869
 
 
2870
/*!
 
2871
    \fn void QLineEdit::cursorLeft(bool mark, int steps)
 
2872
 
 
2873
    Use cursorForward() with a negative number of steps instead. For
 
2874
    example, cursorForward(mark, -steps).
 
2875
*/
 
2876
 
 
2877
/*!
 
2878
    \fn void QLineEdit::cursorRight(bool mark, int steps)
 
2879
 
 
2880
    Use cursorForward() instead.
 
2881
*/
 
2882
 
 
2883
/*!
 
2884
    \fn bool QLineEdit::frame() const
 
2885
 
 
2886
    Use hasFrame() instead.
 
2887
*/
 
2888
 
 
2889
/*!
 
2890
    \fn void QLineEdit::clearValidator()
 
2891
 
 
2892
    Use setValidator(0) instead.
 
2893
*/
 
2894
 
 
2895
/*!
 
2896
    \fn bool QLineEdit::hasMarkedText() const
 
2897
 
 
2898
    Use hasSelectedText() instead.
 
2899
*/
 
2900
 
 
2901
/*!
 
2902
    \fn QString QLineEdit::markedText() const
 
2903
 
 
2904
    Use selectedText() instead.
 
2905
*/
 
2906
 
 
2907
 
 
2908
#include "moc_qlineedit.cpp"
 
2909
 
 
2910
#endif // QT_NO_LINEEDIT