00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "qlineedit.h"
00038 #include "qlineedit_p.h"
00039
00040 #ifndef QT_NO_LINEEDIT
00041 #include "qaction.h"
00042 #include "qapplication.h"
00043 #include "qclipboard.h"
00044 #include "qdrag.h"
00045 #include "qdrawutil.h"
00046 #include "qevent.h"
00047 #include "qfontmetrics.h"
00048 #include "qmenu.h"
00049 #include "qpainter.h"
00050 #include "qpixmap.h"
00051 #include "qpointer.h"
00052 #include "qstringlist.h"
00053 #include "qstyle.h"
00054 #include "qstyleoption.h"
00055 #include "qtimer.h"
00056 #include "qvalidator.h"
00057 #include "qvariant.h"
00058 #include "qvector.h"
00059 #include "qwhatsthis.h"
00060 #include "qdebug.h"
00061 #include "qtextedit.h"
00062 #include <private/qtextedit_p.h>
00063 #ifndef QT_NO_ACCESSIBILITY
00064 #include "qaccessible.h"
00065 #endif
00066 #ifndef QT_NO_IM
00067 #include "qinputcontext.h"
00068 #include "qlist.h"
00069 #endif
00070 #include "qabstractitemview.h"
00071
00072 #ifndef QT_NO_SHORTCUT
00073 #include "qkeysequence.h"
00074 #define ACCEL_KEY(k) QLatin1String("\t") + QString(QKeySequence(Qt::CTRL | Qt::Key_ ## k))
00075 #else
00076 #define ACCEL_KEY(k) QLatin1String("\t") + QString("Ctrl+" #k)
00077 #endif
00078
00079 #ifdef Q_WS_MAC
00080 extern void qt_mac_secure_keyboard(bool);
00081 #endif
00082
00083 #include <limits.h>
00084
00085 #define verticalMargin 1
00086 #define horizontalMargin 2
00087
00088 QStyleOptionFrame QLineEditPrivate::getStyleOption() const
00089 {
00090 Q_Q(const QLineEdit);
00091 QStyleOptionFrame opt;
00092 opt.init(q);
00093 opt.rect = q->contentsRect();
00094 opt.lineWidth = frame ? q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) : 0;
00095 opt.midLineWidth = 0;
00096 opt.state |= QStyle::State_Sunken;
00097 if (readOnly)
00098 opt.state |= QStyle::State_ReadOnly;
00099 #ifdef QT_KEYPAD_NAVIGATION
00100 if (q->hasEditFocus())
00101 opt.state |= QStyle::State_HasEditFocus;
00102 #endif
00103 return opt;
00104 }
00105
00242 QLineEdit::QLineEdit(QWidget* parent)
00243 : QWidget(*new QLineEditPrivate, parent,0)
00244 {
00245 Q_D(QLineEdit);
00246 d->init(QString());
00247 }
00248
00260 QLineEdit::QLineEdit(const QString& contents, QWidget* parent)
00261 : QWidget(*new QLineEditPrivate, parent, 0)
00262 {
00263 Q_D(QLineEdit);
00264 d->init(contents);
00265 }
00266
00267
00268 #ifdef QT3_SUPPORT
00269
00278 QLineEdit::QLineEdit(QWidget* parent, const char* name)
00279 : QWidget(*new QLineEditPrivate, parent,0)
00280 {
00281 Q_D(QLineEdit);
00282 setObjectName(QString::fromAscii(name));
00283 d->init(QString());
00284 }
00285
00298 QLineEdit::QLineEdit(const QString& contents, QWidget* parent, const char* name)
00299 : QWidget(*new QLineEditPrivate, parent, 0)
00300 {
00301 Q_D(QLineEdit);
00302 setObjectName(QString::fromAscii(name));
00303 d->init(contents);
00304 }
00305
00319 QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget* parent, const char* name)
00320 : QWidget(*new QLineEditPrivate, parent, 0)
00321 {
00322 Q_D(QLineEdit);
00323 setObjectName(QString::fromAscii(name));
00324 d->parseInputMask(inputMask);
00325 if (d->maskData) {
00326 QString ms = d->maskString(0, contents);
00327 d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length()));
00328 d->cursor = d->nextMaskBlank(ms.length());
00329 } else {
00330 d->init(contents);
00331 }
00332 }
00333 #endif
00334
00339 QLineEdit::~QLineEdit()
00340 {
00341 }
00342
00343
00357 QString QLineEdit::text() const
00358 {
00359 Q_D(const QLineEdit);
00360 QString res = d->text;
00361 if (d->maskData)
00362 res = d->stripString(d->text);
00363 return (res.isNull() ? QString::fromLatin1("") : res);
00364 }
00365
00366 void QLineEdit::setText(const QString& text)
00367 {
00368 Q_D(QLineEdit);
00369 d->setText(text, -1, false);
00370 #ifdef QT_KEYPAD_NAVIGATION
00371 d->origText = d->text;
00372 #endif
00373 }
00374
00375
00388 QString QLineEdit::displayText() const
00389 {
00390 Q_D(const QLineEdit);
00391 if (d->echoMode == NoEcho)
00392 return QString::fromLatin1("");
00393 QString res = d->text;
00394
00395 if (d->echoMode == Password || d->echoMode == PasswordEchoOnEdit) {
00396 QStyleOptionFrame opt = d->getStyleOption();
00397 res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
00398 }
00399 return (res.isNull() ? QString::fromLatin1("") : res);
00400 }
00401
00402
00419 int QLineEdit::maxLength() const
00420 {
00421 Q_D(const QLineEdit);
00422 return d->maxLength;
00423 }
00424
00425 void QLineEdit::setMaxLength(int maxLength)
00426 {
00427 Q_D(QLineEdit);
00428 if (d->maskData)
00429 return;
00430 d->maxLength = maxLength;
00431 setText(d->text);
00432 }
00433
00434
00435
00443 bool QLineEdit::hasFrame() const
00444 {
00445 Q_D(const QLineEdit);
00446 return d->frame;
00447 }
00448
00449
00450 void QLineEdit::setFrame(bool enable)
00451 {
00452 Q_D(QLineEdit);
00453 d->frame = enable;
00454 update();
00455 updateGeometry();
00456 }
00457
00458
00492 QLineEdit::EchoMode QLineEdit::echoMode() const
00493 {
00494 Q_D(const QLineEdit);
00495 return (EchoMode) d->echoMode;
00496 }
00497
00498 void QLineEdit::setEchoMode(EchoMode mode)
00499 {
00500 Q_D(QLineEdit);
00501 if(mode == (EchoMode)d->echoMode)
00502 return;
00503 d->echoMode = mode;
00504 d->updateTextLayout();
00505 update();
00506 #ifdef Q_WS_MAC
00507 if (hasFocus())
00508 qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
00509 #endif
00510 }
00511
00512
00513 #ifndef QT_NO_VALIDATOR
00514
00521 const QValidator * QLineEdit::validator() const
00522 {
00523 Q_D(const QLineEdit);
00524 return d->validator;
00525 }
00526
00539 void QLineEdit::setValidator(const QValidator *v)
00540 {
00541 Q_D(QLineEdit);
00542 d->validator = const_cast<QValidator*>(v);
00543 }
00544 #endif // QT_NO_VALIDATOR
00545
00546 #ifndef QT_NO_COMPLETER
00547
00560 void QLineEdit::setCompleter(QCompleter *c)
00561 {
00562 Q_D(QLineEdit);
00563 if (c == d->completer)
00564 return;
00565 if (d->completer) {
00566 QObject::disconnect(d->completer, SIGNAL(activated(QString)),
00567 this, SLOT(setText(QString)));
00568 QObject::disconnect(d->completer, SIGNAL(highlighted(QString)),
00569 this, SLOT(_q_completionHighlighted(QString)));
00570 d->completer->setWidget(0);
00571 if (d->completer->parent() == this)
00572 delete d->completer;
00573 }
00574 d->completer = c;
00575 if (!c)
00576 return;
00577 c->setWidget(this);
00578 QObject::connect(c, SIGNAL(activated(QString)),
00579 this, SLOT(setText(QString)));
00580 QObject::connect(c, SIGNAL(highlighted(QString)),
00581 this, SLOT(_q_completionHighlighted(QString)));
00582 }
00583
00589 QCompleter *QLineEdit::completer() const
00590 {
00591 Q_D(const QLineEdit);
00592 return d->completer;
00593 }
00594
00595 bool QLineEditPrivate::advanceToNextEnabledItem(int n )
00596 {
00597 while (true) {
00598 QModelIndex currentIndex = completer->currentIndex();
00599 if (!currentIndex.isValid())
00600 return false;
00601 if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
00602 return true;
00603 if (!completer->setCurrentRow(completer->currentRow() + n))
00604 break;
00605 }
00606
00607 return false;
00608 }
00609
00610 void QLineEditPrivate::complete(int key)
00611 {
00612 if (!completer || readOnly || echoMode != QLineEdit::Normal)
00613 return;
00614
00615 if (completer->completionMode() == QCompleter::InlineCompletion) {
00616 if (key == Qt::Key_Backspace)
00617 return;
00618 int n = 1;
00619 if (key == Qt::Key_Up || key == Qt::Key_Down) {
00620 if (selend != 0 && selend != text.length())
00621 return;
00622 QString prefix = text.left(cursor);
00623 if (prefix != completer->completionPrefix()) {
00624 completer->setCompletionPrefix(prefix);
00625 } else {
00626 n = (key == Qt::Key_Up) ? -1 : +1;
00627 completer->setCurrentRow(completer->currentRow() + n);
00628 }
00629 } else
00630 completer->setCompletionPrefix(text);
00631 if (!advanceToNextEnabledItem(n))
00632 return;
00633 } else {
00634 if (text.isEmpty()) {
00635 completer->popup()->hide();
00636 return;
00637 }
00638 completer->setCompletionPrefix(text);
00639 }
00640
00641 completer->complete();
00642 }
00643
00644 void QLineEditPrivate::_q_completionHighlighted(QString newText)
00645 {
00646 Q_Q(QLineEdit);
00647 if (completer->completionMode() != QCompleter::InlineCompletion)
00648 q->setText(newText);
00649 else {
00650 int c = cursor;
00651 q->setText(text.left(c) + newText.mid(c));
00652 q->setSelection(text.length(), c - newText.length());
00653 }
00654 }
00655 #endif // QT_NO_COMPLETER
00656
00664 QSize QLineEdit::sizeHint() const
00665 {
00666 Q_D(const QLineEdit);
00667 ensurePolished();
00668 QFontMetrics fm(font());
00669 int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin
00670 + d->topmargin + d->bottommargin;
00671 int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin
00672 + d->leftmargin + d->rightmargin;
00673 QStyleOptionFrame opt = d->getStyleOption();
00674 return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
00675 expandedTo(QApplication::globalStrut()), this));
00676 }
00677
00678
00685 QSize QLineEdit::minimumSizeHint() const
00686 {
00687 Q_D(const QLineEdit);
00688 ensurePolished();
00689 QFontMetrics fm = fontMetrics();
00690 int h = fm.height() + qMax(2*horizontalMargin, fm.leading())
00691 + d->topmargin + d->bottommargin;
00692 int w = fm.maxWidth() + d->leftmargin + d->rightmargin;
00693 QStyleOptionFrame opt = d->getStyleOption();
00694 return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
00695 expandedTo(QApplication::globalStrut()), this));
00696 }
00697
00698
00706 int QLineEdit::cursorPosition() const
00707 {
00708 Q_D(const QLineEdit);
00709 return d->cursor;
00710 }
00711
00712 void QLineEdit::setCursorPosition(int pos)
00713 {
00714 Q_D(QLineEdit);
00715 if (pos < 0)
00716 pos = 0;
00717
00718 if (pos <= d->text.length())
00719 d->moveCursor(pos);
00720 }
00721
00725
00726 int QLineEdit::cursorPositionAt(const QPoint &pos)
00727 {
00728 Q_D(QLineEdit);
00729 return d->xToPos(pos.x());
00730 }
00731
00732
00733 #ifdef QT3_SUPPORT
00734
00738 bool QLineEdit::validateAndSet(const QString &newText, int newPos,
00739 int newMarkAnchor, int newMarkDrag)
00740 {
00741 Q_D(QLineEdit);
00742 int priorState = d->undoState;
00743 d->selstart = 0;
00744 d->selend = d->text.length();
00745 d->removeSelectedText();
00746 d->insert(newText);
00747 d->finishChange(priorState);
00748 if (d->undoState > priorState) {
00749 d->cursor = newPos;
00750 d->selstart = qMin(newMarkAnchor, newMarkDrag);
00751 d->selend = qMax(newMarkAnchor, newMarkDrag);
00752 update();
00753 d->emitCursorPositionChanged();
00754 return true;
00755 }
00756 return false;
00757 }
00758 #endif //QT3_SUPPORT
00759
00770 Qt::Alignment QLineEdit::alignment() const
00771 {
00772 Q_D(const QLineEdit);
00773 return QFlag(d->alignment);
00774 }
00775
00776 void QLineEdit::setAlignment(Qt::Alignment alignment)
00777 {
00778 Q_D(QLineEdit);
00779 d->alignment = alignment & Qt::AlignHorizontal_Mask;
00780 update();
00781 }
00782
00783
00792 void QLineEdit::cursorForward(bool mark, int steps)
00793 {
00794 Q_D(QLineEdit);
00795 int cursor = d->cursor;
00796 if (steps > 0) {
00797 while(steps--)
00798 cursor = d->textLayout.nextCursorPosition(cursor);
00799 } else if (steps < 0) {
00800 while (steps++)
00801 cursor = d->textLayout.previousCursorPosition(cursor);
00802 }
00803 d->moveCursor(cursor, mark);
00804 }
00805
00806
00814 void QLineEdit::cursorBackward(bool mark, int steps)
00815 {
00816 cursorForward(mark, -steps);
00817 }
00818
00825 void QLineEdit::cursorWordForward(bool mark)
00826 {
00827 Q_D(QLineEdit);
00828 d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
00829 }
00830
00838 void QLineEdit::cursorWordBackward(bool mark)
00839 {
00840 Q_D(QLineEdit);
00841 d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
00842 }
00843
00844
00853 void QLineEdit::backspace()
00854 {
00855 Q_D(QLineEdit);
00856 int priorState = d->undoState;
00857 if (d->hasSelectedText()) {
00858 d->removeSelectedText();
00859 } else if (d->cursor) {
00860 --d->cursor;
00861 if (d->maskData)
00862 d->cursor = d->prevMaskBlank(d->cursor);
00863 QChar uc = d->text.at(d->cursor);
00864 if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
00865
00866
00867 uc = d->text.at(d->cursor - 1);
00868 if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
00869 d->del(true);
00870 --d->cursor;
00871 }
00872 }
00873 d->del(true);
00874 }
00875 d->finishChange(priorState);
00876 }
00877
00886 void QLineEdit::del()
00887 {
00888 Q_D(QLineEdit);
00889 int priorState = d->undoState;
00890 if (d->hasSelectedText()) {
00891 d->removeSelectedText();
00892 } else {
00893 int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor;
00894 while (n--)
00895 d->del();
00896 }
00897 d->finishChange(priorState);
00898 }
00899
00909 void QLineEdit::home(bool mark)
00910 {
00911 Q_D(QLineEdit);
00912 d->moveCursor(0, mark);
00913 }
00914
00924 void QLineEdit::end(bool mark)
00925 {
00926 Q_D(QLineEdit);
00927 d->moveCursor(d->text.length(), mark);
00928 }
00929
00930
00949 bool QLineEdit::isModified() const
00950 {
00951 Q_D(const QLineEdit);
00952 return d->modifiedState != d->undoState;
00953 }
00954
00955 void QLineEdit::setModified(bool modified)
00956 {
00957 Q_D(QLineEdit);
00958 if (modified)
00959 d->modifiedState = -1;
00960 else
00961 d->modifiedState = d->undoState;
00962 }
00963
00964
00984 bool QLineEdit::hasSelectedText() const
00985 {
00986 Q_D(const QLineEdit);
00987 return d->hasSelectedText();
00988 }
00989
01000 QString QLineEdit::selectedText() const
01001 {
01002 Q_D(const QLineEdit);
01003 if (d->hasSelectedText())
01004 return d->text.mid(d->selstart, d->selend - d->selstart);
01005 return QString();
01006 }
01007
01015 int QLineEdit::selectionStart() const
01016 {
01017 Q_D(const QLineEdit);
01018 return d->hasSelectedText() ? d->selstart : -1;
01019 }
01020
01021
01022 #ifdef QT3_SUPPORT
01023
01036 bool QLineEdit::edited() const { return isModified(); }
01040 void QLineEdit::setEdited(bool on) { setModified(on); }
01041
01045 int QLineEdit::characterAt(int xpos, QChar *chr) const
01046 {
01047 Q_D(const QLineEdit);
01048 int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin);
01049 if (chr && pos < (int) d->text.length())
01050 *chr = d->text.at(pos);
01051 return pos;
01052
01053 }
01054
01058 bool QLineEdit::getSelection(int *start, int *end)
01059 {
01060 Q_D(QLineEdit);
01061 if (d->hasSelectedText() && start && end) {
01062 *start = d->selstart;
01063 *end = d->selend;
01064 return true;
01065 }
01066 return false;
01067 }
01068 #endif
01069
01070
01078 void QLineEdit::setSelection(int start, int length)
01079 {
01080 Q_D(QLineEdit);
01081 if (start < 0 || start > (int)d->text.length()) {
01082 qWarning("QLineEdit::setSelection: Invalid start position (%d)", start);
01083 return;
01084 } else {
01085 if (length > 0) {
01086 d->selstart = start;
01087 d->selend = qMin(start + length, (int)d->text.length());
01088 d->cursor = d->selend;
01089 } else {
01090 d->selstart = qMax(start + length, 0);
01091 d->selend = start;
01092 d->cursor = d->selstart;
01093 }
01094 }
01095 update();
01096 d->emitCursorPositionChanged();
01097 }
01098
01099
01105 bool QLineEdit::isUndoAvailable() const
01106 {
01107 Q_D(const QLineEdit);
01108 return d->isUndoAvailable();
01109 }
01110
01116 bool QLineEdit::isRedoAvailable() const
01117 {
01118 Q_D(const QLineEdit);
01119 return d->isRedoAvailable();
01120 }
01121
01130 bool QLineEdit::dragEnabled() const
01131 {
01132 Q_D(const QLineEdit);
01133 return d->dragEnabled;
01134 }
01135
01136 void QLineEdit::setDragEnabled(bool b)
01137 {
01138 Q_D(QLineEdit);
01139 d->dragEnabled = b;
01140 }
01141
01142
01150 bool QLineEdit::hasAcceptableInput() const
01151 {
01152 Q_D(const QLineEdit);
01153 return d->hasAcceptableInput(d->text);
01154 }
01155
01216 QString QLineEdit::inputMask() const
01217 {
01218 Q_D(const QLineEdit);
01219 return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString());
01220 }
01221
01222 void QLineEdit::setInputMask(const QString &inputMask)
01223 {
01224 Q_D(QLineEdit);
01225 d->parseInputMask(inputMask);
01226 if (d->maskData)
01227 d->moveCursor(d->nextMaskBlank(0));
01228 }
01229
01239 void QLineEdit::selectAll()
01240 {
01241 Q_D(QLineEdit);
01242 d->selstart = d->selend = d->cursor = 0;
01243 d->moveCursor(d->text.length(), true);
01244 }
01245
01252 void QLineEdit::deselect()
01253 {
01254 Q_D(QLineEdit);
01255 d->deselect();
01256 d->finishChange();
01257 }
01258
01259
01267 void QLineEdit::insert(const QString &newText)
01268 {
01269
01270 Q_D(QLineEdit);
01271 int priorState = d->undoState;
01272 d->removeSelectedText();
01273 d->insert(newText);
01274 d->finishChange(priorState);
01275 }
01276
01282 void QLineEdit::clear()
01283 {
01284 Q_D(QLineEdit);
01285 int priorState = d->undoState;
01286 resetInputContext();
01287 d->selstart = 0;
01288 d->selend = d->text.length();
01289 d->removeSelectedText();
01290 d->separate();
01291 d->finishChange(priorState);
01292 }
01293
01300 void QLineEdit::undo()
01301 {
01302 Q_D(QLineEdit);
01303 resetInputContext();
01304 d->undo();
01305 d->finishChange(-1, true);
01306 }
01307
01312 void QLineEdit::redo()
01313 {
01314 Q_D(QLineEdit);
01315 resetInputContext();
01316 d->redo();
01317 d->finishChange();
01318 }
01319
01320
01334 bool QLineEdit::isReadOnly() const
01335 {
01336 Q_D(const QLineEdit);
01337 return d->readOnly;
01338 }
01339
01340 void QLineEdit::setReadOnly(bool enable)
01341 {
01342 Q_D(QLineEdit);
01343 d->readOnly = enable;
01344 update();
01345 }
01346
01347
01348 #ifndef QT_NO_CLIPBOARD
01349
01359 void QLineEdit::cut()
01360 {
01361 if (hasSelectedText()) {
01362 copy();
01363 del();
01364 }
01365 }
01366
01367
01375 void QLineEdit::copy() const
01376 {
01377 Q_D(const QLineEdit);
01378 d->copy();
01379 }
01380
01392 void QLineEdit::paste()
01393 {
01394 insert(QApplication::clipboard()->text(QClipboard::Clipboard));
01395 }
01396
01397 void QLineEditPrivate::copy(bool clipboard) const
01398 {
01399 Q_Q(const QLineEdit);
01400 QString t = q->selectedText();
01401 if (!t.isEmpty() && echoMode == QLineEdit::Normal) {
01402 q->disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), q, 0);
01403 QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection);
01404 q->connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
01405 q, SLOT(_q_clipboardChanged()));
01406 }
01407 }
01408
01409 #endif // !QT_NO_CLIPBOARD
01410
01413 bool QLineEdit::event(QEvent * e)
01414 {
01415 Q_D(QLineEdit);
01416 if (e->type() == QEvent::ShortcutOverride && !d->readOnly) {
01417 QKeyEvent* ke = (QKeyEvent*) e;
01418 if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
01419 || ke->modifiers() == Qt::KeypadModifier) {
01420 if (ke->key() < Qt::Key_Escape) {
01421 ke->accept();
01422 } else {
01423 switch (ke->key()) {
01424 case Qt::Key_Delete:
01425 case Qt::Key_Home:
01426 case Qt::Key_End:
01427 case Qt::Key_Backspace:
01428 case Qt::Key_Left:
01429 case Qt::Key_Right:
01430 ke->accept();
01431 default:
01432 break;
01433 }
01434 }
01435 } else if (ke->modifiers() & Qt::ControlModifier) {
01436 switch (ke->key()) {
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446 case Qt::Key_C:
01447 case Qt::Key_V:
01448 case Qt::Key_X:
01449 case Qt::Key_Y:
01450 case Qt::Key_Z:
01451 case Qt::Key_Left:
01452 case Qt::Key_Right:
01453 #if !defined(Q_WS_MAC)
01454 case Qt::Key_Insert:
01455 case Qt::Key_Delete:
01456 #endif
01457 ke->accept();
01458 default:
01459 break;
01460 }
01461 }
01462 } else if (e->type() == QEvent::Timer) {
01463
01464 int timerId = ((QTimerEvent*)e)->timerId();
01465 if (timerId == d->cursorTimer) {
01466 QStyleOptionFrame opt = d->getStyleOption();
01467 if(!hasSelectedText()
01468 || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
01469 d->setCursorVisible(!d->cursorVisible);
01470 #ifndef QT_NO_DRAGANDDROP
01471 } else if (timerId == d->dndTimer.timerId()) {
01472 d->drag();
01473 #endif
01474 }
01475 else if (timerId == d->tripleClickTimer.timerId())
01476 d->tripleClickTimer.stop();
01477 #ifdef QT_KEYPAD_NAVIGATION
01478 else if (timerId == d->deleteAllTimer.timerId()) {
01479 d->deleteAllTimer.stop();
01480 clear();
01481 }
01482 #endif
01483 } else if (e->type() == QEvent::ContextMenu) {
01484 #ifndef QT_NO_IM
01485 if (d->composeMode())
01486 return true;
01487 #endif
01488 d->separate();
01489 }
01490 #ifdef QT_KEYPAD_NAVIGATION
01491 else if (e->type() == QEvent::KeyRelease) {
01492 if (QApplication::keypadNavigationEnabled()) {
01493 QKeyEvent *ke = (QKeyEvent *)e;
01494 if ( !ke->isAutoRepeat() && !isReadOnly()
01495 && ke->key() == Qt::Key_Back
01496 && d->deleteAllTimer.isActive()) {
01497 d->deleteAllTimer.stop();
01498 backspace();
01499 ke->accept();
01500 return true;
01501 }
01502 }
01503 }
01504 #endif
01505 return QWidget::event(e);
01506 }
01507
01510 void QLineEdit::mousePressEvent(QMouseEvent* e)
01511 {
01512 Q_D(QLineEdit);
01513 if (d->sendMouseEventToInputContext(e))
01514 return;
01515 if (e->button() == Qt::RightButton)
01516 return;
01517 #ifdef QT_KEYPAD_NAVIGATION
01518 if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
01519 setEditFocus(true);
01520 #endif
01521 if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
01522 QApplication::startDragDistance()) {
01523 selectAll();
01524 return;
01525 }
01526 bool mark = e->modifiers() & Qt::ShiftModifier;
01527 int cursor = d->xToPos(e->pos().x());
01528 #ifndef QT_NO_DRAGANDDROP
01529 if (!mark && d->dragEnabled && d->echoMode == Normal &&
01530 e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) {
01531 d->cursor = cursor;
01532 update();
01533 d->dndPos = e->pos();
01534 if (!d->dndTimer.isActive())
01535 d->dndTimer.start(QApplication::startDragTime(), this);
01536 d->emitCursorPositionChanged();
01537 } else
01538 #endif
01539 {
01540 d->moveCursor(cursor, mark);
01541 }
01542 }
01543
01546 void QLineEdit::mouseMoveEvent(QMouseEvent * e)
01547 {
01548 Q_D(QLineEdit);
01549 if (d->sendMouseEventToInputContext(e))
01550 return;
01551
01552 if (e->buttons() & Qt::LeftButton) {
01553 #ifndef QT_NO_DRAGANDDROP
01554 if (d->dndTimer.isActive()) {
01555 if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
01556 d->drag();
01557 } else
01558 #endif
01559 {
01560 d->moveCursor(d->xToPos(e->pos().x()), true);
01561 }
01562 }
01563 }
01564
01567 void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
01568 {
01569 Q_D(QLineEdit);
01570 if (d->sendMouseEventToInputContext(e))
01571 return;
01572 #ifndef QT_NO_DRAGANDDROP
01573 if (e->button() == Qt::LeftButton) {
01574 if (d->dndTimer.isActive()) {
01575 d->dndTimer.stop();
01576 deselect();
01577 return;
01578 }
01579 }
01580 #endif
01581 #ifndef QT_NO_CLIPBOARD
01582 if (QApplication::clipboard()->supportsSelection()) {
01583 if (e->button() == Qt::LeftButton) {
01584 d->copy(false);
01585 } else if (!d->readOnly && e->button() == Qt::MidButton) {
01586 d->deselect();
01587 insert(QApplication::clipboard()->text(QClipboard::Selection));
01588 }
01589 }
01590 #endif
01591 }
01592
01595 void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
01596 {
01597 Q_D(QLineEdit);
01598 if (d->sendMouseEventToInputContext(e))
01599 return;
01600 if (e->button() == Qt::LeftButton) {
01601 deselect();
01602 d->cursor = d->xToPos(e->pos().x());
01603 d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords);
01604
01605 int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords);
01606 while (end > d->cursor && d->text[end-1].isSpace())
01607 --end;
01608 d->moveCursor(end, true);
01609 d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
01610 d->tripleClick = e->pos();
01611 }
01612 }
01613
01645 void QLineEdit::keyPressEvent(QKeyEvent *event)
01646 {
01647 Q_D(QLineEdit);
01648
01649 #ifndef QT_NO_COMPLETER
01650 if (d->completer && d->completer->popup()->isVisible()) {
01651
01652
01653 switch (event->key()) {
01654 case Qt::Key_Escape:
01655 event->ignore();
01656 return;
01657 case Qt::Key_Enter:
01658 case Qt::Key_Return:
01659 case Qt::Key_F4:
01660 d->completer->popup()->hide();
01661 default:
01662 break;
01663 }
01664 }
01665 #endif // QT_NO_COMPLETER
01666
01667 #ifdef QT_KEYPAD_NAVIGATION
01668 bool select = false;
01669 switch (event->key()) {
01670 case Qt::Key_Select:
01671 if (QApplication::keypadNavigationEnabled()) {
01672 if (hasEditFocus()) {
01673 setEditFocus(false);
01674 select = true;
01675 }
01676 }
01677 break;
01678 case Qt::Key_Back:
01679 case Qt::Key_No:
01680 if (!QApplication::keypadNavigationEnabled() || !hasEditFocus()) {
01681 event->ignore();
01682 return;
01683 }
01684 break;
01685 default:
01686 if (QApplication::keypadNavigationEnabled()) {
01687 if (!hasEditFocus() && !(event->modifiers() & Qt::ControlModifier)) {
01688 if (!event->text().isEmpty() && event->text().at(0).isPrint()
01689 && !isReadOnly())
01690 {
01691 setEditFocus(true);
01692 clear();
01693 } else {
01694 event->ignore();
01695 return;
01696 }
01697 }
01698 }
01699 }
01700
01701
01702
01703 if (QApplication::keypadNavigationEnabled() && !select && !hasEditFocus()) {
01704 setEditFocus(true);
01705 if (event->key() == Qt::Key_Select)
01706 return;
01707 }
01708 #endif
01709
01710
01711 if(echoMode() == PasswordEchoOnEdit &&
01712 !isReadOnly() &&
01713 !event->text().isEmpty() &&
01714 #ifdef QT_KEYPAD_NAVIGATION
01715 event->key() != Qt::Key_Select &&
01716 event->key() != Qt::Key_Up &&
01717 event->key() != Qt::Key_Down &&
01718 event->key() != Qt::Key_Back &&
01719 #endif
01720 !(event->modifiers() & Qt::ControlModifier))
01721 {
01722 setEchoMode(Normal);
01723 clear();
01724 d->resumePassword = true;
01725 }
01726
01727 d->setCursorVisible(true);
01728 if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
01729 if (hasAcceptableInput() || d->fixup()) {
01730 emit returnPressed();
01731 d->emitingEditingFinished = true;
01732 emit editingFinished();
01733 d->emitingEditingFinished = false;
01734 }
01735 event->ignore();
01736 return;
01737 }
01738 bool unknown = false;
01739
01740 if (false) {
01741 }
01742 #ifndef QT_NO_SHORTCUT
01743 else if (event == QKeySequence::Undo) {
01744 if (!d->readOnly)
01745 undo();
01746 }
01747 else if (event == QKeySequence::Redo) {
01748 if (!d->readOnly)
01749 redo();
01750 }
01751 else if (event == QKeySequence::SelectAll) {
01752 selectAll();
01753 }
01754 #ifndef QT_NO_CLIPBOARD
01755 else if (event == QKeySequence::Copy) {
01756 copy();
01757 }
01758 else if (event == QKeySequence::Paste) {
01759 if (!d->readOnly)
01760 paste();
01761 }
01762 else if (event == QKeySequence::Cut) {
01763 if (!d->readOnly) {
01764 copy();
01765 del();
01766 }
01767 }
01768 else if (event == QKeySequence::DeleteEndOfLine) {
01769 if (!d->readOnly) {
01770 setSelection(d->cursor, d->text.size());
01771 copy();
01772 del();
01773 }
01774 }
01775 #endif //QT_NO_CLIPBOARD
01776 else if (event == QKeySequence::MoveToStartOfLine) {
01777 home(0);
01778 }
01779 else if (event == QKeySequence::MoveToEndOfLine) {
01780 end(0);
01781 }
01782 else if (event == QKeySequence::SelectStartOfLine) {
01783 home(1);
01784 }
01785 else if (event == QKeySequence::SelectEndOfLine) {
01786 end(1);
01787 }
01788 else if (event == QKeySequence::MoveToNextChar) {
01789 #ifndef Q_WS_WIN
01790 if (d->hasSelectedText()) {
01791 #else
01792 if (d->hasSelectedText() && d->completer
01793 && d->completer->completionMode() == QCompleter::InlineCompletion) {
01794 #endif
01795 d->moveCursor(d->selend, false);
01796 } else {
01797 cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
01798 }
01799 }
01800 else if (event == QKeySequence::SelectNextChar) {
01801 cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
01802 }
01803 else if (event == QKeySequence::MoveToPreviousChar) {
01804 #ifndef Q_WS_WIN
01805 if (d->hasSelectedText()) {
01806 #else
01807 if (d->hasSelectedText() && d->completer
01808 && d->completer->completionMode() == QCompleter::InlineCompletion) {
01809 #endif
01810 d->moveCursor(d->selstart, false);
01811 } else {
01812 cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
01813 }
01814 }
01815 else if (event == QKeySequence::SelectPreviousChar) {
01816 cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
01817 }
01818 else if (event == QKeySequence::MoveToNextWord) {
01819 if (echoMode() == Normal)
01820 layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
01821 else
01822 layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
01823 }
01824 else if (event == QKeySequence::MoveToPreviousWord) {
01825 if (echoMode() == Normal)
01826 layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
01827 else if (!d->readOnly) {
01828 layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
01829 }
01830 }
01831 else if (event == QKeySequence::SelectNextWord) {
01832 if (echoMode() == Normal)
01833 layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
01834 else
01835 layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
01836 }
01837 else if (event == QKeySequence::SelectPreviousWord) {
01838 if (echoMode() == Normal)
01839 layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
01840 else
01841 layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
01842 }
01843 else if (event == QKeySequence::Delete) {
01844 if (!d->readOnly)
01845 del();
01846 }
01847 else if (event == QKeySequence::DeleteEndOfWord) {
01848 if (!d->readOnly) {
01849 cursorWordForward(true);
01850 del();
01851 }
01852 }
01853 else if (event == QKeySequence::DeleteStartOfWord) {
01854 if (!d->readOnly) {
01855 cursorWordBackward(true);
01856 del();
01857 }
01858 }
01859 #endif // QT_NO_SHORTCUT
01860 else {
01861 #ifdef Q_WS_MAC
01862 if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
01863 Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
01864 if (myModifiers & Qt::ShiftModifier) {
01865 if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
01866 || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
01867 || myModifiers == Qt::ShiftModifier) {
01868
01869 event->key() == Qt::Key_Up ? home(1) : end(1);
01870 }
01871 } else {
01872 if ((myModifiers == Qt::ControlModifier
01873 || myModifiers == Qt::AltModifier
01874 || myModifiers == Qt::NoModifier)) {
01875 event->key() == Qt::Key_Up ? home(0) : end(0);
01876 }
01877 }
01878 }
01879 #endif
01880 if (event->modifiers() & Qt::ControlModifier) {
01881 switch (event->key()) {
01882 case Qt::Key_Backspace:
01883 if (!d->readOnly) {
01884 cursorWordBackward(true);
01885 del();
01886 }
01887 break;
01888 #ifndef QT_NO_COMPLETER
01889 case Qt::Key_Up:
01890 case Qt::Key_Down:
01891 d->complete(event->key());
01892 break;
01893 #endif
01894 #if defined(Q_WS_X11)
01895 case Qt::Key_E:
01896 end(0);
01897 break;
01898
01899 case Qt::Key_U:
01900 if (!d->readOnly) {
01901 setSelection(0, d->text.size());
01902 #ifndef QT_NO_CLIPBOARD
01903 copy();
01904 #endif
01905 del();
01906 }
01907 break;
01908 #endif
01909 default:
01910 unknown = true;
01911 }
01912 } else {
01913 switch (event->key()) {
01914 case Qt::Key_Backspace:
01915 if (!d->readOnly) {
01916 backspace();
01917 #ifndef QT_NO_COMPLETER
01918 d->complete(Qt::Key_Backspace);
01919 #endif
01920 }
01921 break;
01922 #ifdef QT_KEYPAD_NAVIGATION
01923 case Qt::Key_Back:
01924 if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
01925 && !isReadOnly()) {
01926 if (text().length() == 0) {
01927 setText(d->origText);
01928
01929 if (d->resumePassword)
01930 {
01931 setEchoMode(PasswordEchoOnEdit);
01932 d->resumePassword = false;
01933 }
01934
01935 setEditFocus(false);
01936 } else if (!d->deleteAllTimer.isActive()) {
01937 d->deleteAllTimer.start(750, this);
01938 }
01939 } else {
01940 unknown = true;
01941 }
01942 break;
01943 #endif
01944
01945 default:
01946 unknown = true;
01947 }
01948 }
01949 }
01950
01951 if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
01952 setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
01953 d->updateTextLayout();
01954 update();
01955 unknown = false;
01956 }
01957
01958 if (unknown && !d->readOnly) {
01959 QString t = event->text();
01960 if (!t.isEmpty() && t.at(0).isPrint()) {
01961 insert(t);
01962 #ifndef QT_NO_COMPLETER
01963 d->complete(event->key());
01964 #endif
01965 event->accept();
01966 return;
01967 }
01968 }
01969
01970 if (unknown)
01971 event->ignore();
01972 else
01973 event->accept();
01974 }
01975
01981 bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
01982 {
01983 #if !defined QT_NO_IM
01984 Q_Q(QLineEdit);
01985 if ( composeMode() ) {
01986 int tmp_cursor = xToPos(e->pos().x());
01987 int mousePos = tmp_cursor - cursor;
01988 if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) {
01989 mousePos = -1;
01990
01991 if ( e->type() == QEvent::MouseMove )
01992 return true;
01993 }
01994
01995 QInputContext *qic = q->inputContext();
01996 if ( qic )
01997
01998 qic->mouseHandler(mousePos, e);
01999 if (!textLayout.preeditAreaText().isEmpty())
02000 return true;
02001 }
02002 #else
02003 Q_UNUSED(e);
02004 #endif
02005
02006 return false;
02007 }
02008
02011 void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
02012 {
02013 Q_D(QLineEdit);
02014 if (d->readOnly) {
02015 e->ignore();
02016 return;
02017 }
02018
02019
02020 if(echoMode() == PasswordEchoOnEdit)
02021 {
02022 setEchoMode(Normal);
02023 clear();
02024 d->resumePassword = true;
02025 }
02026
02027
02028 #ifdef QT_KEYPAD_NAVIGATION
02029 if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
02030 setEditFocus(true);
02031 #endif
02032
02033 int priorState = d->undoState;
02034 d->removeSelectedText();
02035
02036 int c = d->cursor;
02037 if (e->replacementStart() <= 0)
02038 c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength());
02039
02040 d->cursor += e->replacementStart();
02041
02042
02043 if (e->replacementLength()) {
02044 d->selstart = d->cursor;
02045 d->selend = d->selstart + e->replacementLength();
02046 d->removeSelectedText();
02047 }
02048 if (!e->commitString().isEmpty())
02049 d->insert(e->commitString());
02050
02051 d->cursor = c;
02052
02053 d->textLayout.setPreeditArea(d->cursor, e->preeditString());
02054 d->preeditCursor = e->preeditString().length();
02055 d->hideCursor = false;
02056 QList<QTextLayout::FormatRange> formats;
02057 for (int i = 0; i < e->attributes().size(); ++i) {
02058 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
02059 if (a.type == QInputMethodEvent::Cursor) {
02060 d->preeditCursor = a.start;
02061 d->hideCursor = !a.length;
02062 } else if (a.type == QInputMethodEvent::TextFormat) {
02063 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
02064 if (f.isValid()) {
02065 QTextLayout::FormatRange o;
02066 o.start = a.start + d->cursor;
02067 o.length = a.length;
02068 o.format = f;
02069 formats.append(o);
02070 }
02071 }
02072 }
02073 d->textLayout.setAdditionalFormats(formats);
02074 d->updateTextLayout();
02075 update();
02076 if (!e->commitString().isEmpty())
02077 d->emitCursorPositionChanged();
02078 d->finishChange(priorState);
02079 }
02080
02083 QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
02084 {
02085 Q_D(const QLineEdit);
02086 switch(property) {
02087 case Qt::ImMicroFocus:
02088 return d->cursorRect();
02089 case Qt::ImFont:
02090 return font();
02091 case Qt::ImCursorPosition:
02092 return QVariant(d->cursor);
02093 case Qt::ImSurroundingText:
02094 return QVariant(d->text);
02095 case Qt::ImCurrentSelection:
02096 return QVariant(selectedText());
02097 default:
02098 return QVariant();
02099 }
02100 }
02101
02105 void QLineEdit::focusInEvent(QFocusEvent *e)
02106 {
02107 Q_D(QLineEdit);
02108 if (e->reason() == Qt::TabFocusReason ||
02109 e->reason() == Qt::BacktabFocusReason ||
02110 e->reason() == Qt::ShortcutFocusReason)
02111 if (d->maskData)
02112 d->moveCursor(d->nextMaskBlank(0));
02113 else if (!d->hasSelectedText())
02114 selectAll();
02115 if (!d->cursorTimer) {
02116 int cft = QApplication::cursorFlashTime();
02117 d->cursorTimer = cft ? startTimer(cft/2) : -1;
02118 }
02119 QStyleOptionFrame opt = d->getStyleOption();
02120 if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty())
02121 || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
02122 d->setCursorVisible(true);
02123 #ifdef Q_WS_MAC
02124 if (d->echoMode == Password || d->echoMode == NoEcho)
02125 qt_mac_secure_keyboard(true);
02126 #endif
02127 #ifdef QT_KEYPAD_NAVIGATION
02128 d->origText = d->text;
02129 #endif
02130 update();
02131 }
02132
02136 void QLineEdit::focusOutEvent(QFocusEvent *e)
02137 {
02138 Q_D(QLineEdit);
02139
02140
02141 if(d->resumePassword){
02142 setEchoMode(PasswordEchoOnEdit);
02143 d->resumePassword = false;
02144 }
02145
02146
02147 Qt::FocusReason reason = e->reason();
02148 if (reason != Qt::ActiveWindowFocusReason &&
02149 reason != Qt::PopupFocusReason)
02150 deselect();
02151
02152 d->setCursorVisible(false);
02153 if (d->cursorTimer > 0)
02154 killTimer(d->cursorTimer);
02155 d->cursorTimer = 0;
02156 if (reason != Qt::PopupFocusReason
02157 && !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) {
02158 if (!d->emitingEditingFinished) {
02159 if (hasAcceptableInput() || d->fixup()) {
02160 d->emitingEditingFinished = true;
02161 emit editingFinished();
02162 d->emitingEditingFinished = false;
02163 }
02164 }
02165 #ifdef QT3_SUPPORT
02166 emit lostFocus();
02167 #endif
02168 }
02169 #ifdef Q_WS_MAC
02170 if (d->echoMode == Password || d->echoMode == NoEcho)
02171 qt_mac_secure_keyboard(false);
02172 #endif
02173 #ifdef QT_KEYPAD_NAVIGATION
02174 d->origText = QString();
02175 #endif
02176 update();
02177 }
02178
02181 void QLineEdit::paintEvent(QPaintEvent *)
02182 {
02183 Q_D(QLineEdit);
02184 QPainter p(this);
02185
02186 QRect r = rect();
02187 const QPalette &pal = palette();
02188
02189 QStyleOptionFrame panel = d->getStyleOption();
02190 style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this);
02191 r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
02192 p.setClipRect(r);
02193
02194 QFontMetrics fm = fontMetrics();
02195 QRect lineRect(r.x() + horizontalMargin, r.y() + (r.height() - fm.height() + 1) / 2,
02196 r.width() - 2*horizontalMargin, fm.height());
02197 QTextLine line = d->textLayout.lineAt(0);
02198
02199 int cursor = d->cursor;
02200 if (d->preeditCursor != -1)
02201 cursor += d->preeditCursor;
02202
02203 int cix = qRound(line.cursorToX(cursor));
02204
02205
02206 int minLB = qMax(0, -fm.minLeftBearing());
02207 int minRB = qMax(0, -fm.minRightBearing());
02208
02209
02210 int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
02211 if ((minLB + widthUsed) <= lineRect.width()) {
02212 Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment));
02213 va &= ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask);
02214 switch (va) {
02215 case Qt::AlignRight:
02216 d->hscroll = widthUsed - lineRect.width() + 1;
02217 break;
02218 case Qt::AlignHCenter:
02219 d->hscroll = (widthUsed - lineRect.width()) / 2;
02220 break;
02221 default:
02222
02223 d->hscroll = 0;
02224 break;
02225 }
02226 d->hscroll -= minLB;
02227 } else if (cix - d->hscroll >= lineRect.width()) {
02228 d->hscroll = cix - lineRect.width() + 1;
02229 } else if (cix - d->hscroll < 0) {
02230 d->hscroll = cix;
02231 } else if (widthUsed - d->hscroll < lineRect.width()) {
02232 d->hscroll = widthUsed - lineRect.width() + 1;
02233 }
02234
02235 QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent-fm.ascent());
02236
02237
02238 p.setPen(pal.text().color());
02239
02240 QVector<QTextLayout::FormatRange> selections;
02241 if (d->selstart < d->selend || (d->cursorVisible && d->maskData)) {
02242 QTextLayout::FormatRange o;
02243 const QPalette &pal = palette();
02244 if (d->selstart < d->selend) {
02245 o.start = d->selstart;
02246 o.length = d->selend - d->selstart;
02247 o.format.setBackground(pal.brush(QPalette::Highlight));
02248 o.format.setForeground(pal.brush(QPalette::HighlightedText));
02249 } else {
02250
02251 o.start = d->cursor;
02252 o.length = 1;
02253 o.format.setBackground(pal.brush(QPalette::Text));
02254 o.format.setForeground(pal.brush(QPalette::Window));
02255 }
02256 selections.append(o);
02257 }
02258
02259
02260
02261
02262 d->textLayout.draw(&p, topLeft, selections, r);
02263 if (d->cursorVisible && !d->readOnly && !d->hideCursor)
02264 d->textLayout.drawCursor(&p, topLeft, cursor);
02265
02266 }
02267
02268
02269 #ifndef QT_NO_DRAGANDDROP
02270
02272 void QLineEdit::dragMoveEvent(QDragMoveEvent *e)
02273 {
02274 Q_D(QLineEdit);
02275 if (!d->readOnly && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
02276 e->acceptProposedAction();
02277 d->cursor = d->xToPos(e->pos().x());
02278 d->cursorVisible = true;
02279 update();
02280 d->emitCursorPositionChanged();
02281 }
02282 }
02283
02285 void QLineEdit::dragEnterEvent(QDragEnterEvent * e)
02286 {
02287 QLineEdit::dragMoveEvent(e);
02288 }
02289
02291 void QLineEdit::dragLeaveEvent(QDragLeaveEvent *)
02292 {
02293 Q_D(QLineEdit);
02294 if (d->cursorVisible) {
02295 d->cursorVisible = false;
02296 update();
02297 }
02298 }
02299
02301 void QLineEdit::dropEvent(QDropEvent* e)
02302 {
02303 Q_D(QLineEdit);
02304 QString str = e->mimeData()->text();
02305
02306 if (!str.isNull() && !d->readOnly) {
02307 if (e->source() == this && e->dropAction() == Qt::CopyAction)
02308 deselect();
02309 d->cursor =d->xToPos(e->pos().x());
02310 int selStart = d->cursor;
02311 int oldSelStart = d->selstart;
02312 int oldSelEnd = d->selend;
02313 d->cursorVisible = false;
02314 e->acceptProposedAction();
02315 insert(str);
02316 if (e->source() == this) {
02317 if (e->dropAction() == Qt::MoveAction) {
02318 if (selStart > oldSelStart && selStart <= oldSelEnd)
02319 setSelection(oldSelStart, str.length());
02320 else if (selStart > oldSelEnd)
02321 setSelection(selStart - str.length(), str.length());
02322 else
02323 setSelection(selStart, str.length());
02324 } else {
02325 setSelection(selStart, str.length());
02326 }
02327 }
02328 } else {
02329 e->ignore();
02330 update();
02331 }
02332 }
02333
02334 void QLineEditPrivate::drag()
02335 {
02336 Q_Q(QLineEdit);
02337 dndTimer.stop();
02338 QMimeData *data = new QMimeData;
02339 data->setText(q->selectedText());
02340 QDrag *drag = new QDrag(q);
02341 drag->setMimeData(data);
02342 Qt::DropAction action = drag->start();
02343 if (action == Qt::MoveAction && !readOnly && drag->target() != q) {
02344 int priorState = undoState;
02345 removeSelectedText();
02346 finishChange(priorState);
02347 }
02348 }
02349
02350 #endif // QT_NO_DRAGANDDROP
02351
02352 #ifndef QT_NO_CONTEXTMENU
02353
02379 void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
02380 {
02381 QPointer<QMenu> menu = createStandardContextMenu();
02382 menu->exec(event->globalPos());
02383 delete menu;
02384 }
02385
02392 QMenu *QLineEdit::createStandardContextMenu()
02393 {
02394 Q_D(QLineEdit);
02395 d->actions[QLineEditPrivate::UndoAct]->setEnabled(d->isUndoAvailable());
02396 d->actions[QLineEditPrivate::RedoAct]->setEnabled(d->isRedoAvailable());
02397 #ifndef QT_NO_CLIPBOARD
02398 d->actions[QLineEditPrivate::CutAct]->setEnabled(!d->readOnly && d->hasSelectedText());
02399 d->actions[QLineEditPrivate::CopyAct]->setEnabled(d->hasSelectedText());
02400 d->actions[QLineEditPrivate::PasteAct]->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty());
02401 #else
02402 d->actions[QLineEditPrivate::CutAct]->setEnabled(false);
02403 d->actions[QLineEditPrivate::CopyAct]->setEnabled(false);
02404 d->actions[QLineEditPrivate::PasteAct]->setEnabled(false);
02405 #endif
02406 d->actions[QLineEditPrivate::ClearAct]->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText());
02407 d->actions[QLineEditPrivate::SelectAllAct]->setEnabled(!d->text.isEmpty() && !d->allSelected());
02408
02409 QMenu *popup = new QMenu(this);
02410 popup->setObjectName(QLatin1String("qt_edit_menu"));
02411 popup->addAction(d->actions[QLineEditPrivate::UndoAct]);
02412 popup->addAction(d->actions[QLineEditPrivate::RedoAct]);
02413 popup->addSeparator();
02414 popup->addAction(d->actions[QLineEditPrivate::CutAct]);
02415 popup->addAction(d->actions[QLineEditPrivate::CopyAct]);
02416 popup->addAction(d->actions[QLineEditPrivate::PasteAct]);
02417 popup->addAction(d->actions[QLineEditPrivate::ClearAct]);
02418 popup->addSeparator();
02419 popup->addAction(d->actions[QLineEditPrivate::SelectAllAct]);
02420 #if !defined(QT_NO_IM)
02421 QInputContext *qic = inputContext();
02422 if (qic) {
02423 QList<QAction *> imActions = qic->actions();
02424 for (int i = 0; i < imActions.size(); ++i)
02425 popup->addAction(imActions.at(i));
02426 }
02427 #endif
02428
02429 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
02430 #if defined(Q_WS_WIN)
02431 extern bool qt_use_rtl_extensions;
02432 if (!d->readOnly && qt_use_rtl_extensions) {
02433 #elif defined(Q_WS_X11)
02434 if (!d->readOnly) {
02435 #endif
02436 popup->addSeparator();
02437 QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup);
02438 popup->addMenu(ctrlCharacterMenu);
02439 }
02440 #endif
02441 return popup;
02442 }
02443 #endif // QT_NO_CONTEXTMENU
02444
02446 void QLineEdit::changeEvent(QEvent *ev)
02447 {
02448 Q_D(QLineEdit);
02449 if(ev->type() == QEvent::ActivationChange) {
02450 if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
02451 update();
02452 } else if (ev->type() == QEvent::FontChange || ev->type() == QEvent::StyleChange) {
02453 d->updateTextLayout();
02454 }
02455 QWidget::changeEvent(ev);
02456 }
02457
02458 void QLineEditPrivate::_q_clipboardChanged()
02459 {
02460 }
02461
02462 void QLineEditPrivate::_q_deleteSelected()
02463 {
02464 Q_Q(QLineEdit);
02465 if (!hasSelectedText())
02466 return;
02467
02468 int priorState = undoState;
02469 q->resetInputContext();
02470 removeSelectedText();
02471 separate();
02472 finishChange(priorState);
02473 }
02474 void QLineEditPrivate::init(const QString& txt)
02475 {
02476 Q_Q(QLineEdit);
02477 #ifndef QT_NO_CURSOR
02478 q->setCursor(Qt::IBeamCursor);
02479 #endif
02480 q->setFocusPolicy(Qt::StrongFocus);
02481 q->setAttribute(Qt::WA_InputMethodEnabled);
02482
02483
02484 q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
02485 q->setBackgroundRole(QPalette::Base);
02486 q->setAttribute(Qt::WA_KeyCompression);
02487 q->setMouseTracking(true);
02488 q->setAcceptDrops(true);
02489 text = txt;
02490 updateTextLayout();
02491 cursor = text.length();
02492
02493 #ifndef QT_NO_MENU
02494 actions[UndoAct] = new QAction(QLineEdit::tr("&Undo") + ACCEL_KEY(Z), q);
02495 QObject::connect(actions[UndoAct], SIGNAL(triggered()), q, SLOT(undo()));
02496 actions[RedoAct] = new QAction(QLineEdit::tr("&Redo") + ACCEL_KEY(Y), q);
02497 QObject::connect(actions[RedoAct], SIGNAL(triggered()), q, SLOT(redo()));
02498
02499 #ifndef QT_NO_CLIPBOARD
02500 actions[CutAct] = new QAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(X), q);
02501 QObject::connect(actions[CutAct], SIGNAL(triggered()), q, SLOT(cut()));
02502 actions[CopyAct] = new QAction(QLineEdit::tr("&Copy") + ACCEL_KEY(C), q);
02503 QObject::connect(actions[CopyAct], SIGNAL(triggered()), q, SLOT(copy()));
02504 actions[PasteAct] = new QAction(QLineEdit::tr("&Paste") + ACCEL_KEY(V), q);
02505 QObject::connect(actions[PasteAct], SIGNAL(triggered()), q, SLOT(paste()));
02506 #endif
02507 actions[ClearAct] = new QAction(QLineEdit::tr("Delete"), q);
02508 QObject::connect(actions[ClearAct], SIGNAL(triggered()), q, SLOT(_q_deleteSelected()));
02509
02510 actions[SelectAllAct] = new QAction(QLineEdit::tr("Select All")
02511 + ACCEL_KEY(A)
02512 , q);
02513 QObject::connect(actions[SelectAllAct], SIGNAL(triggered()), q, SLOT(selectAll()));
02514 #endif // QT_NO_MENU
02515 }
02516
02517 void QLineEditPrivate::updateTextLayout()
02518 {
02519
02520
02521
02522 Q_Q(QLineEdit);
02523 QString str = q->displayText();
02524 QChar* uc = str.data();
02525 for (int i = 0; i < (int)str.length(); ++i) {
02526 if (!uc[i].isPrint() || uc[i] == QChar::LineSeparator)
02527 uc[i] = QChar(0x0020);
02528 }
02529 textLayout.setFont(q->font());
02530 textLayout.setText(str);
02531 QTextOption option;
02532 option.setTextDirection(q->layoutDirection());
02533 option.setFlags(QTextOption::IncludeTrailingSpaces);
02534 textLayout.setTextOption(option);
02535
02536 textLayout.beginLayout();
02537 QTextLine l = textLayout.createLine();
02538 textLayout.endLayout();
02539 ascent = qRound(l.ascent());
02540 }
02541
02542 int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
02543 {
02544 QRect cr = adjustedContentsRect();
02545 x-= cr.x() - hscroll + horizontalMargin;
02546 QTextLine l = textLayout.lineAt(0);
02547 return l.xToCursor(x, betweenOrOn);
02548 }
02549
02550 QRect QLineEditPrivate::cursorRect() const
02551 {
02552 Q_Q(const QLineEdit);
02553 QRect cr = adjustedContentsRect();
02554 int cix = cr.x() - hscroll + horizontalMargin;
02555 QTextLine l = textLayout.lineAt(0);
02556 int c = cursor;
02557 if (preeditCursor != -1)
02558 c += preeditCursor;
02559 cix += qRound(l.cursorToX(c));
02560 int ch = qMin(cr.height(), q->fontMetrics().height() + 1);
02561 return QRect(cix-5, cr.y() + (cr.height() - ch) / 2, 10, ch);
02562 }
02563
02564 QRect QLineEditPrivate::adjustedContentsRect() const
02565 {
02566 Q_Q(const QLineEdit);
02567 QStyleOptionFrame opt = getStyleOption();
02568 return q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
02569 }
02570
02571 bool QLineEditPrivate::fixup()
02572 {
02573 #ifndef QT_NO_VALIDATOR
02574 if (validator) {
02575 QString textCopy = text;
02576 int cursorCopy = cursor;
02577 validator->fixup(textCopy);
02578 if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
02579 if (textCopy != text || cursorCopy != cursor)
02580 setText(textCopy, cursorCopy);
02581 return true;
02582 }
02583 }
02584 #endif
02585 return false;
02586 }
02587
02588
02589 void QLineEditPrivate::moveCursor(int pos, bool mark)
02590 {
02591 Q_Q(QLineEdit);
02592 if (pos != cursor) {
02593 separate();
02594 if (maskData)
02595 pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
02596 }
02597 bool fullUpdate = mark || hasSelectedText();
02598 if (mark) {
02599 int anchor;
02600 if (selend > selstart && cursor == selstart)
02601 anchor = selend;
02602 else if (selend > selstart && cursor == selend)
02603 anchor = selstart;
02604 else
02605 anchor = cursor;
02606 selstart = qMin(anchor, pos);
02607 selend = qMax(anchor, pos);
02608 updateTextLayout();
02609 } else {
02610 deselect();
02611 }
02612 if (fullUpdate) {
02613 cursor = pos;
02614 q->update();
02615 } else {
02616 setCursorVisible(false);
02617 cursor = pos;
02618 setCursorVisible(true);
02619 if (!adjustedContentsRect().contains(cursorRect()))
02620 q->update();
02621 }
02622 QStyleOptionFrame opt = getStyleOption();
02623 if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q))
02624 setCursorVisible(false);
02625 if (mark || selDirty) {
02626 selDirty = false;
02627 emit q->selectionChanged();
02628 }
02629 emitCursorPositionChanged();
02630 }
02631
02632 void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited)
02633 {
02634 Q_Q(QLineEdit);
02635 bool lineDirty = selDirty;
02636 if (textDirty) {
02637
02638 bool wasValidInput = validInput;
02639 validInput = true;
02640 #ifndef QT_NO_VALIDATOR
02641 if (validator) {
02642 validInput = false;
02643 QString textCopy = text;
02644 int cursorCopy = cursor;
02645 validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
02646 if (validInput) {
02647 if (text != textCopy) {
02648 setText(textCopy, cursorCopy);
02649 return;
02650 }
02651 cursor = cursorCopy;
02652 }
02653 }
02654 #endif
02655 if (validateFromState >= 0 && wasValidInput && !validInput) {
02656 undo(validateFromState);
02657 history.resize(undoState);
02658 if (modifiedState > undoState)
02659 modifiedState = -1;
02660 validInput = true;
02661 textDirty = false;
02662 }
02663 updateTextLayout();
02664 lineDirty |= textDirty;
02665 if (textDirty) {
02666 textDirty = false;
02667 QString actualText = maskData ? stripString(text) : text;
02668 if (edited)
02669 emit q->textEdited(actualText);
02670 q->updateMicroFocus();
02671 emit q->textChanged(actualText);
02672 #ifndef QT_NO_COMPLETER
02673 if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion)
02674 complete(-1);
02675 #endif
02676 }
02677 #ifndef QT_NO_ACCESSIBILITY
02678 QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
02679 #endif
02680 }
02681 if (selDirty) {
02682 selDirty = false;
02683 emit q->selectionChanged();
02684 }
02685 if (lineDirty || update)
02686 q->update();
02687 emitCursorPositionChanged();
02688 }
02689
02690 void QLineEditPrivate::emitCursorPositionChanged()
02691 {
02692 Q_Q(QLineEdit);
02693 if (cursor != lastCursorPos) {
02694 const int oldLast = lastCursorPos;
02695 lastCursorPos = cursor;
02696 emit q->cursorPositionChanged(oldLast, cursor);
02697 }
02698 }
02699
02700 void QLineEditPrivate::setText(const QString& txt, int pos, bool edited)
02701 {
02702 Q_Q(QLineEdit);
02703 q->resetInputContext();
02704 deselect();
02705 QString oldText = text;
02706 if (maskData) {
02707 text = maskString(0, txt, true);
02708 text += clearString(text.length(), maxLength - text.length());
02709 } else {
02710 text = txt.isEmpty() ? txt : txt.left(maxLength);
02711 }
02712 history.clear();
02713 modifiedState = undoState = 0;
02714 cursor = (pos < 0 || pos > text.length()) ? text.length() : pos;
02715 textDirty = (oldText != text);
02716 finishChange(-1, true, edited);
02717 }
02718
02719
02720 void QLineEditPrivate::setCursorVisible(bool visible)
02721 {
02722 Q_Q(QLineEdit);
02723 if ((bool)cursorVisible == visible)
02724 return;
02725 if (cursorTimer)
02726 cursorVisible = visible;
02727 QRect r = cursorRect();
02728 if (maskData)
02729 q->update();
02730 else
02731 q->update(r);
02732 }
02733
02734 void QLineEditPrivate::addCommand(const Command& cmd)
02735 {
02736 if (separator && undoState && history[undoState-1].type != Separator) {
02737 history.resize(undoState + 2);
02738 history[undoState++] = Command(Separator, 0, 0);
02739 } else {
02740 history.resize(undoState + 1);
02741 }
02742 separator = false;
02743 history[undoState++] = cmd;
02744 }
02745
02746 void QLineEditPrivate::insert(const QString& s)
02747 {
02748 if (maskData) {
02749 QString ms = maskString(cursor, s);
02750 for (int i = 0; i < (int) ms.length(); ++i) {
02751 addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i)));
02752 addCommand(Command(Insert, cursor+i, ms.at(i)));
02753 }
02754 text.replace(cursor, ms.length(), ms);
02755 cursor += ms.length();
02756 cursor = nextMaskBlank(cursor);
02757 } else {
02758 int remaining = maxLength - text.length();
02759 text.insert(cursor, s.left(remaining));
02760 for (int i = 0; i < (int) s.left(remaining).length(); ++i)
02761 addCommand(Command(Insert, cursor++, s.at(i)));
02762 }
02763 textDirty = true;
02764 }
02765
02766 void QLineEditPrivate::del(bool wasBackspace)
02767 {
02768 if (cursor < (int) text.length()) {
02769 addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor)));
02770 if (maskData) {
02771 text.replace(cursor, 1, clearString(cursor, 1));
02772 addCommand(Command(Insert, cursor, text.at(cursor)));
02773 } else {
02774 text.remove(cursor, 1);
02775 }
02776 textDirty = true;
02777 }
02778 }
02779
02780 void QLineEditPrivate::removeSelectedText()
02781 {
02782 if (selstart < selend && selend <= (int) text.length()) {
02783 separate();
02784 int i ;
02785 if (selstart <= cursor && cursor < selend) {
02786
02787
02788 for (i = cursor; i >= selstart; --i)
02789 addCommand (Command(DeleteSelection, i, text.at(i)));
02790 for (i = selend - 1; i > cursor; --i)
02791 addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i)));
02792 } else {
02793 for (i = selend-1; i >= selstart; --i)
02794 addCommand (Command(RemoveSelection, i, text.at(i)));
02795 }
02796 if (maskData) {
02797 text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart));
02798 for (int i = 0; i < selend - selstart; ++i)
02799 addCommand(Command(Insert, selstart + i, text.at(selstart + i)));
02800 } else {
02801 text.remove(selstart, selend - selstart);
02802 }
02803 if (cursor > selstart)
02804 cursor -= qMin(cursor, selend) - selstart;
02805 deselect();
02806 textDirty = true;
02807 }
02808 }
02809
02810 void QLineEditPrivate::parseInputMask(const QString &maskFields)
02811 {
02812 int delimiter = maskFields.indexOf(QLatin1Char(';'));
02813 if (maskFields.isEmpty() || delimiter == 0) {
02814 if (maskData) {
02815 delete [] maskData;
02816 maskData = 0;
02817 maxLength = 32767;
02818 setText(QString());
02819 }
02820 return;
02821 }
02822
02823 if (delimiter == -1) {
02824 blank = QLatin1Char(' ');
02825 inputMask = maskFields;
02826 } else {
02827 inputMask = maskFields.left(delimiter);
02828 blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
02829 }
02830
02831
02832 maxLength = 0;
02833 QChar c = 0;
02834 for (int i=0; i<inputMask.length(); i++) {
02835 c = inputMask.at(i);
02836 if (i > 0 && inputMask.at(i-1) == QLatin1Char('\\')) {
02837 maxLength++;
02838 continue;
02839 }
02840 if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
02841 c != QLatin1Char('<') && c != QLatin1Char('>') &&
02842 c != QLatin1Char('{') && c != QLatin1Char('}') &&
02843 c != QLatin1Char('[') && c != QLatin1Char(']'))
02844 maxLength++;
02845 }
02846
02847 delete [] maskData;
02848 maskData = new MaskInputData[maxLength];
02849
02850 MaskInputData::Casemode m = MaskInputData::NoCaseMode;
02851 c = 0;
02852 bool s;
02853 bool escape = false;
02854 int index = 0;
02855 for (int i = 0; i < inputMask.length(); i++) {
02856 c = inputMask.at(i);
02857 if (escape) {
02858 s = true;
02859 maskData[index].maskChar = c;
02860 maskData[index].separator = s;
02861 maskData[index].caseMode = m;
02862 index++;
02863 escape = false;
02864 } else if (c == QLatin1Char('<')) {
02865 m = MaskInputData::Lower;
02866 } else if (c == QLatin1Char('>')) {
02867 m = MaskInputData::Upper;
02868 } else if (c == QLatin1Char('!')) {
02869 m = MaskInputData::NoCaseMode;
02870 } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
02871 switch (c.unicode()) {
02872 case 'A':
02873 case 'a':
02874 case 'N':
02875 case 'n':
02876 case 'X':
02877 case 'x':
02878 case '9':
02879 case '0':
02880 case 'D':
02881 case 'd':
02882 case '#':
02883 case 'H':
02884 case 'h':
02885 case 'B':
02886 case 'b':
02887 s = false;
02888 break;
02889 case '\\':
02890 escape = true;
02891 default:
02892 s = true;
02893 break;
02894 }
02895
02896 if (!escape) {
02897 maskData[index].maskChar = c;
02898 maskData[index].separator = s;
02899 maskData[index].caseMode = m;
02900 index++;
02901 }
02902 }
02903 }
02904 setText(text);
02905 }
02906
02907
02908
02909 bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const
02910 {
02911 switch (mask.unicode()) {
02912 case 'A':
02913 if (key.isLetter())
02914 return true;
02915 break;
02916 case 'a':
02917 if (key.isLetter() || key == blank)
02918 return true;
02919 break;
02920 case 'N':
02921 if (key.isLetterOrNumber())
02922 return true;
02923 break;
02924 case 'n':
02925 if (key.isLetterOrNumber() || key == blank)
02926 return true;
02927 break;
02928 case 'X':
02929 if (key.isPrint())
02930 return true;
02931 break;
02932 case 'x':
02933 if (key.isPrint() || key == blank)
02934 return true;
02935 break;
02936 case '9':
02937 if (key.isNumber())
02938 return true;
02939 break;
02940 case '0':
02941 if (key.isNumber() || key == blank)
02942 return true;
02943 break;
02944 case 'D':
02945 if (key.isNumber() && key.digitValue() > 0)
02946 return true;
02947 break;
02948 case 'd':
02949 if ((key.isNumber() && key.digitValue() > 0) || key == blank)
02950 return true;
02951 break;
02952 case '#':
02953 if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank)
02954 return true;
02955 break;
02956 case 'B':
02957 if (key == QLatin1Char('0') || key == QLatin1Char('1'))
02958 return true;
02959 break;
02960 case 'b':
02961 if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank)
02962 return true;
02963 break;
02964 case 'H':
02965 if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
02966 return true;
02967 break;
02968 case 'h':
02969 if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank)
02970 return true;
02971 break;
02972 default:
02973 break;
02974 }
02975 return false;
02976 }
02977
02978 bool QLineEditPrivate::hasAcceptableInput(const QString &str) const
02979 {
02980 #ifndef QT_NO_VALIDATOR
02981 QString textCopy = str;
02982 int cursorCopy = cursor;
02983 if (validator && validator->validate(textCopy, cursorCopy)
02984 != QValidator::Acceptable)
02985 return false;
02986 #endif
02987
02988 if (!maskData)
02989 return true;
02990
02991 if (str.length() != maxLength)
02992 return false;
02993
02994 for (int i=0; i < maxLength; ++i) {
02995 if (maskData[i].separator) {
02996 if (str.at(i) != maskData[i].maskChar)
02997 return false;
02998 } else {
02999 if (!isValidInput(str.at(i), maskData[i].maskChar))
03000 return false;
03001 }
03002 }
03003 return true;
03004 }
03005
03006
03007
03008
03009
03010
03011
03012 QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const
03013 {
03014 if (pos >= (uint)maxLength)
03015 return QString::fromLatin1("");
03016
03017 QString fill;
03018 fill = clear ? clearString(0, maxLength) : text;
03019
03020 int strIndex = 0;
03021 QString s = QString::fromLatin1("");
03022 int i = pos;
03023 while (i < maxLength) {
03024 if (strIndex < str.length()) {
03025 if (maskData[i].separator) {
03026 s += maskData[i].maskChar;
03027 if (str[(int)strIndex] == maskData[i].maskChar)
03028 strIndex++;
03029 ++i;
03030 } else {
03031 if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) {
03032 switch (maskData[i].caseMode) {
03033 case MaskInputData::Upper:
03034 s += str[(int)strIndex].toUpper();
03035 break;
03036 case MaskInputData::Lower:
03037 s += str[(int)strIndex].toLower();
03038 break;
03039 default:
03040 s += str[(int)strIndex];
03041 }
03042 ++i;
03043 } else {
03044
03045 int n = findInMask(i, true, true, str[(int)strIndex]);
03046 if (n != -1) {
03047 if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) {
03048 s += fill.mid(i, n-i+1);
03049 i = n + 1;
03050 }
03051 } else {
03052
03053 n = findInMask(i, true, false, str[(int)strIndex]);
03054 if (n != -1) {
03055 s += fill.mid(i, n-i);
03056 switch (maskData[n].caseMode) {
03057 case MaskInputData::Upper:
03058 s += str[(int)strIndex].toUpper();
03059 break;
03060 case MaskInputData::Lower:
03061 s += str[(int)strIndex].toLower();
03062 break;
03063 default:
03064 s += str[(int)strIndex];
03065 }
03066 i = n + 1;
03067 }
03068 }
03069 }
03070 strIndex++;
03071 }
03072 } else
03073 break;
03074 }
03075
03076 return s;
03077 }
03078
03079
03080
03081
03082
03083
03084
03085 QString QLineEditPrivate::clearString(uint pos, uint len) const
03086 {
03087 if (pos >= (uint)maxLength)
03088 return QString();
03089
03090 QString s;
03091 int end = qMin((uint)maxLength, pos + len);
03092 for (int i=pos; i<end; i++)
03093 if (maskData[i].separator)
03094 s += maskData[i].maskChar;
03095 else
03096 s += blank;
03097
03098 return s;
03099 }
03100
03101
03102
03103
03104
03105 QString QLineEditPrivate::stripString(const QString &str) const
03106 {
03107 if (!maskData)
03108 return str;
03109
03110 QString s;
03111 int end = qMin(maxLength, (int)str.length());
03112 for (int i=0; i < end; i++)
03113 if (maskData[i].separator)
03114 s += maskData[i].maskChar;
03115 else
03116 if (str[i] != blank)
03117 s += str[i];
03118
03119 return s;
03120 }
03121
03122
03123 int QLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
03124 {
03125 if (pos >= maxLength || pos < 0)
03126 return -1;
03127
03128 int end = forward ? maxLength : -1;
03129 int step = forward ? 1 : -1;
03130 int i = pos;
03131
03132 while (i != end) {
03133 if (findSeparator) {
03134 if (maskData[i].separator && maskData[i].maskChar == searchChar)
03135 return i;
03136 } else {
03137 if (!maskData[i].separator) {
03138 if (searchChar.isNull())
03139 return i;
03140 else if (isValidInput(searchChar, maskData[i].maskChar))
03141 return i;
03142 }
03143 }
03144 i += step;
03145 }
03146 return -1;
03147 }
03148
03149 void QLineEditPrivate::undo(int until)
03150 {
03151 if (!isUndoAvailable())
03152 return;
03153 deselect();
03154 while (undoState && undoState > until) {
03155 Command& cmd = history[--undoState];
03156 switch (cmd.type) {
03157 case Insert:
03158 text.remove(cmd.pos, 1);
03159 cursor = cmd.pos;
03160 break;
03161 case Remove:
03162 case RemoveSelection:
03163 text.insert(cmd.pos, cmd.uc);
03164 cursor = cmd.pos + 1;
03165 break;
03166 case Delete:
03167 case DeleteSelection:
03168 text.insert(cmd.pos, cmd.uc);
03169 cursor = cmd.pos;
03170 break;
03171 case Separator:
03172 continue;
03173 }
03174 if (until < 0 && undoState) {
03175 Command& next = history[undoState-1];
03176 if (next.type != cmd.type && next.type < RemoveSelection
03177 && !(cmd.type >= RemoveSelection && next.type != Separator))
03178 break;
03179 }
03180 }
03181 textDirty = true;
03182 emitCursorPositionChanged();
03183 }
03184
03185 void QLineEditPrivate::redo() {
03186 if (!isRedoAvailable())
03187 return;
03188 deselect();
03189 while (undoState < (int)history.size()) {
03190 Command& cmd = history[undoState++];
03191 switch (cmd.type) {
03192 case Insert:
03193 text.insert(cmd.pos, cmd.uc);
03194 cursor = cmd.pos + 1;
03195 break;
03196 case Remove:
03197 case Delete:
03198 case RemoveSelection:
03199 case DeleteSelection:
03200 text.remove(cmd.pos, 1);
03201 cursor = cmd.pos;
03202 break;
03203 case Separator:
03204 continue;
03205 }
03206 if (undoState < (int)history.size()) {
03207 Command& next = history[undoState];
03208 if (next.type != cmd.type && cmd.type < RemoveSelection
03209 && !(next.type >= RemoveSelection && cmd.type != Separator))
03210 break;
03211 }
03212 }
03213 textDirty = true;
03214 emitCursorPositionChanged();
03215 }
03216
03364 #include "moc_qlineedit.cpp"
03365
03366 #endif // QT_NO_LINEEDIT