Changeset 561 for trunk/src/gui/widgets/qlineedit.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/widgets/qlineedit.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 80 80 #include "private/qshortcutmap_p.h" 81 81 #include "qkeysequence.h" 82 #define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1 String("\t") + QString(QKeySequence(k)) : QString())82 #define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString()) 83 83 #else 84 84 #define ACCEL_KEY(k) QString() … … 87 87 #include <limits.h> 88 88 89 #define verticalMargin 190 #define horizontalMargin 291 92 89 QT_BEGIN_NAMESPACE 93 90 … … 95 92 extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp 96 93 #endif 97 98 static inline bool shouldEnableInputMethod(QLineEdit *lineedit)99 {100 const QLineEdit::EchoMode mode = lineedit->echoMode();101 return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit);102 }103 94 104 95 /*! … … 123 114 option->midLineWidth = 0; 124 115 option->state |= QStyle::State_Sunken; 125 if (d-> readOnly)116 if (d->control->isReadOnly()) 126 117 option->state |= QStyle::State_ReadOnly; 127 118 #ifdef QT_KEYPAD_NAVIGATION … … 138 129 139 130 \ingroup basicwidgets 140 \mainclass 131 141 132 142 133 A line edit allows the user to enter and edit a single line of … … 351 342 Q_D(QLineEdit); 352 343 setObjectName(QString::fromAscii(name)); 353 d->parseInputMask(inputMask); 354 if (d->maskData) { 355 QString ms = d->maskString(0, contents); 356 d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length())); 357 d->cursor = d->nextMaskBlank(ms.length()); 358 } else { 359 d->init(contents); 360 } 344 d->init(contents); 345 d->control->setInputMask(inputMask); 346 d->control->moveCursor(d->control->nextMaskBlank(contents.length())); 361 347 } 362 348 #endif … … 389 375 { 390 376 Q_D(const QLineEdit); 391 QString res = d->text; 392 if (d->maskData) 393 res = d->stripString(d->text); 394 return (res.isNull() ? QString::fromLatin1("") : res); 377 return d->control->text(); 395 378 } 396 379 … … 398 381 { 399 382 Q_D(QLineEdit); 400 d->setText(text, -1, false); 401 #ifdef QT_KEYPAD_NAVIGATION 402 d->origText = d->text; 403 #endif 404 } 405 383 d->control->setText(text); 384 } 385 386 // ### Qt 4.7: remove this #if guard 387 #if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5) 388 /*! 389 \since 4.7 390 391 \property QLineEdit::placeholderText 392 \brief the line edit's placeholder text 393 394 Setting this property makes the line edit display a grayed-out 395 placeholder text as long as the text() is empty and the widget doesn't 396 have focus. 397 398 By default, this property contains an empty string. 399 400 \sa text() 401 */ 402 QString QLineEdit::placeholderText() const 403 { 404 Q_D(const QLineEdit); 405 return d->placeholderText; 406 } 407 408 void QLineEdit::setPlaceholderText(const QString& placeholderText) 409 { 410 Q_D(QLineEdit); 411 if (d->placeholderText != placeholderText) { 412 d->placeholderText = placeholderText; 413 if (!hasFocus()) 414 update(); 415 } 416 } 417 #endif 406 418 407 419 /*! … … 422 434 { 423 435 Q_D(const QLineEdit); 424 if (d->echoMode == NoEcho) 425 return QString::fromLatin1(""); 426 QString res = d->text; 427 428 if (d->echoMode == Password || (d->echoMode == PasswordEchoOnEdit 429 && !d->passwordEchoEditing)) { 430 QStyleOptionFrameV2 opt; 431 initStyleOption(&opt); 432 res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this)); 433 } 434 return (res.isNull() ? QString::fromLatin1("") : res); 436 return d->control->displayText(); 435 437 } 436 438 … … 457 459 { 458 460 Q_D(const QLineEdit); 459 return d-> maxLength;461 return d->control->maxLength(); 460 462 } 461 463 … … 463 465 { 464 466 Q_D(QLineEdit); 465 if (d->maskData) 466 return; 467 d->maxLength = maxLength; 468 setText(d->text); 469 } 470 471 467 d->control->setMaxLength(maxLength); 468 } 472 469 473 470 /*! … … 537 534 { 538 535 Q_D(const QLineEdit); 539 return (EchoMode) d-> echoMode;536 return (EchoMode) d->control->echoMode(); 540 537 } 541 538 … … 543 540 { 544 541 Q_D(QLineEdit); 545 if (mode == (EchoMode)d-> echoMode)542 if (mode == (EchoMode)d->control->echoMode()) 546 543 return; 547 setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); 548 d->echoMode = mode; 549 d->passwordEchoEditing = false; 550 d->updateTextLayout(); 544 Qt::InputMethodHints imHints = inputMethodHints(); 545 if (mode == Password) { 546 imHints |= Qt::ImhHiddenText; 547 } else { 548 imHints &= ~Qt::ImhHiddenText; 549 } 550 setInputMethodHints(imHints); 551 d->control->setEchoMode(mode); 551 552 update(); 552 553 #ifdef Q_WS_MAC 553 554 if (hasFocus()) 554 qt_mac_secure_keyboard( d->echoMode == Password || d->echoMode == NoEcho);555 qt_mac_secure_keyboard(mode == Password || mode == NoEcho); 555 556 #endif 556 557 } … … 568 569 { 569 570 Q_D(const QLineEdit); 570 return d-> validator;571 return d->control->validator(); 571 572 } 572 573 … … 586 587 { 587 588 Q_D(QLineEdit); 588 d-> validator = const_cast<QValidator*>(v);589 d->control->setValidator(v); 589 590 } 590 591 #endif // QT_NO_VALIDATOR … … 610 611 { 611 612 Q_D(QLineEdit); 612 if (c == d->co mpleter)613 if (c == d->control->completer()) 613 614 return; 614 if (d->co mpleter) {615 disconnect(d->co mpleter, 0, this, 0);616 d->co mpleter->setWidget(0);617 if (d->co mpleter->parent() == this)618 delete d->co mpleter;619 } 620 d->co mpleter = c;615 if (d->control->completer()) { 616 disconnect(d->control->completer(), 0, this, 0); 617 d->control->completer()->setWidget(0); 618 if (d->control->completer()->parent() == this) 619 delete d->control->completer(); 620 } 621 d->control->setCompleter(c); 621 622 if (!c) 622 623 return; … … 624 625 c->setWidget(this); 625 626 if (hasFocus()) { 626 QObject::connect(d->co mpleter, SIGNAL(activated(QString)),627 QObject::connect(d->control->completer(), SIGNAL(activated(QString)), 627 628 this, SLOT(setText(QString))); 628 QObject::connect(d->co mpleter, SIGNAL(highlighted(QString)),629 QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)), 629 630 this, SLOT(_q_completionHighlighted(QString))); 630 631 } … … 639 640 { 640 641 Q_D(const QLineEdit); 641 return d->completer; 642 } 643 644 // looks for an enabled item iterating forward(dir=1)/backward(dir=-1) from the 645 // current row based. dir=0 indicates a new completion prefix was set. 646 bool QLineEditPrivate::advanceToEnabledItem(int dir) 647 { 648 int start = completer->currentRow(); 649 if (start == -1) 650 return false; 651 int i = start + dir; 652 if (dir == 0) dir = 1; 653 do { 654 if (!completer->setCurrentRow(i)) { 655 if (!completer->wrapAround()) 656 break; 657 i = i > 0 ? 0 : completer->completionCount() - 1; 658 } else { 659 QModelIndex currentIndex = completer->currentIndex(); 660 if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled) 661 return true; 662 i += dir; 663 } 664 } while (i != start); 665 666 completer->setCurrentRow(start); // restore 667 return false; 668 } 669 670 void QLineEditPrivate::complete(int key) 671 { 672 if (!completer || readOnly || echoMode != QLineEdit::Normal) 673 return; 674 675 if (completer->completionMode() == QCompleter::InlineCompletion) { 676 if (key == Qt::Key_Backspace) 677 return; 678 int n = 0; 679 if (key == Qt::Key_Up || key == Qt::Key_Down) { 680 if (selend != 0 && selend != text.length()) 681 return; 682 QString prefix = hasSelectedText() ? text.left(selstart) : text; 683 if (text.compare(completer->currentCompletion(), completer->caseSensitivity()) != 0 684 || prefix.compare(completer->completionPrefix(), completer->caseSensitivity()) != 0) { 685 completer->setCompletionPrefix(prefix); 686 } else { 687 n = (key == Qt::Key_Up) ? -1 : +1; 688 } 689 } else { 690 completer->setCompletionPrefix(text); 691 } 692 if (!advanceToEnabledItem(n)) 693 return; 694 } else { 695 #ifndef QT_KEYPAD_NAVIGATION 696 if (text.isEmpty()) { 697 completer->popup()->hide(); 698 return; 699 } 700 #endif 701 completer->setCompletionPrefix(text); 702 } 703 704 completer->complete(); 705 } 706 707 void QLineEditPrivate::_q_completionHighlighted(QString newText) 708 { 709 Q_Q(QLineEdit); 710 if (completer->completionMode() != QCompleter::InlineCompletion) 711 q->setText(newText); 712 else { 713 int c = cursor; 714 q->setText(text.left(c) + newText.mid(c)); 715 q->setSelection(text.length(), c - newText.length()); 716 } 717 } 642 return d->control->completer(); 643 } 644 718 645 #endif // QT_NO_COMPLETER 719 646 … … 730 657 ensurePolished(); 731 658 QFontMetrics fm(font()); 732 int h = qMax(fm. lineSpacing(), 14) + 2*verticalMargin659 int h = qMax(fm.height(), 14) + 2*d->verticalMargin 733 660 + d->topTextMargin + d->bottomTextMargin 734 661 + d->topmargin + d->bottommargin; 735 int w = fm.width(QLatin1Char('x')) * 17 + 2* horizontalMargin662 int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin 736 663 + d->leftTextMargin + d->rightTextMargin 737 664 + d->leftmargin + d->rightmargin; // "some" … … 754 681 ensurePolished(); 755 682 QFontMetrics fm = fontMetrics(); 756 int h = fm.height() + qMax(2* verticalMargin, fm.leading())683 int h = fm.height() + qMax(2*d->verticalMargin, fm.leading()) 757 684 + d->topmargin + d->bottommargin; 758 685 int w = fm.maxWidth() + d->leftmargin + d->rightmargin; … … 776 703 { 777 704 Q_D(const QLineEdit); 778 return d->c ursor;705 return d->control->cursorPosition(); 779 706 } 780 707 … … 782 709 { 783 710 Q_D(QLineEdit); 784 if (pos < 0) 785 pos = 0; 786 787 if (pos <= d->text.length()) 788 d->moveCursor(pos); 711 d->control->setCursorPosition(pos); 789 712 } 790 713 … … 808 731 int newMarkAnchor, int newMarkDrag) 809 732 { 810 Q_D(QLineEdit); 811 int priorState = d->undoState; 812 d->selstart = 0; 813 d->selend = d->text.length(); 814 d->removeSelectedText(); 815 d->insert(newText); 816 d->finishChange(priorState); 817 if (d->undoState > priorState) { 818 d->cursor = newPos; 819 d->selstart = qMin(newMarkAnchor, newMarkDrag); 820 d->selend = qMax(newMarkAnchor, newMarkDrag); 821 update(); 822 d->emitCursorPositionChanged(); 823 return true; 824 } 825 return false; 733 // The suggested functions above in the docs don't seem to validate, 734 // below code tries to mimic previous behaviour. 735 QString oldText = text(); 736 setText(newText); 737 if(!hasAcceptableInput()){ 738 setText(oldText); 739 return false; 740 } 741 setCursorPosition(newPos); 742 setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag)); 743 return true; 826 744 } 827 745 #endif //QT3_SUPPORT … … 864 782 { 865 783 Q_D(QLineEdit); 866 int cursor = d->cursor; 867 if (steps > 0) { 868 while(steps--) 869 cursor = d->textLayout.nextCursorPosition(cursor); 870 } else if (steps < 0) { 871 while (steps++) 872 cursor = d->textLayout.previousCursorPosition(cursor); 873 } 874 d->moveCursor(cursor, mark); 784 d->control->cursorForward(mark, steps); 875 785 } 876 786 … … 897 807 { 898 808 Q_D(QLineEdit); 899 d-> moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords),mark);809 d->control->cursorWordForward(mark); 900 810 } 901 811 … … 910 820 { 911 821 Q_D(QLineEdit); 912 d-> moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords),mark);822 d->control->cursorWordBackward(mark); 913 823 } 914 824 … … 925 835 { 926 836 Q_D(QLineEdit); 927 int priorState = d->undoState; 928 if (d->hasSelectedText()) { 929 d->removeSelectedText(); 930 } else if (d->cursor) { 931 --d->cursor; 932 if (d->maskData) 933 d->cursor = d->prevMaskBlank(d->cursor); 934 QChar uc = d->text.at(d->cursor); 935 if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { 936 // second half of a surrogate, check if we have the first half as well, 937 // if yes delete both at once 938 uc = d->text.at(d->cursor - 1); 939 if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { 940 d->del(true); 941 --d->cursor; 942 } 943 } 944 d->del(true); 945 } 946 d->finishChange(priorState); 837 d->control->backspace(); 947 838 } 948 839 … … 958 849 { 959 850 Q_D(QLineEdit); 960 int priorState = d->undoState; 961 if (d->hasSelectedText()) { 962 d->removeSelectedText(); 963 } else { 964 int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor; 965 while (n--) 966 d->del(); 967 } 968 d->finishChange(priorState); 851 d->control->del(); 969 852 } 970 853 … … 981 864 { 982 865 Q_D(QLineEdit); 983 d-> moveCursor(0,mark);866 d->control->home(mark); 984 867 } 985 868 … … 996 879 { 997 880 Q_D(QLineEdit); 998 d-> moveCursor(d->text.length(),mark);881 d->control->end(mark); 999 882 } 1000 883 … … 1021 904 { 1022 905 Q_D(const QLineEdit); 1023 return d-> modifiedState != d->undoState;906 return d->control->isModified(); 1024 907 } 1025 908 … … 1027 910 { 1028 911 Q_D(QLineEdit); 1029 if (modified) 1030 d->modifiedState = -1; 1031 else 1032 d->modifiedState = d->undoState; 912 d->control->setModified(modified); 1033 913 } 1034 914 … … 1058 938 { 1059 939 Q_D(const QLineEdit); 1060 return d-> hasSelectedText();940 return d->control->hasSelectedText(); 1061 941 } 1062 942 … … 1076 956 { 1077 957 Q_D(const QLineEdit); 1078 if (d->hasSelectedText()) 1079 return d->text.mid(d->selstart, d->selend - d->selstart); 1080 return QString(); 958 return d->control->selectedText(); 1081 959 } 1082 960 … … 1091 969 { 1092 970 Q_D(const QLineEdit); 1093 return d-> hasSelectedText() ? d->selstart : -1;971 return d->control->selectionStart(); 1094 972 } 1095 973 … … 1121 999 { 1122 1000 Q_D(const QLineEdit); 1123 int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin); 1124 if (chr && pos < (int) d->text.length()) 1125 *chr = d->text.at(pos); 1001 int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + d->horizontalMargin); 1002 QString txt = d->control->text(); 1003 if (chr && pos < (int) txt.length()) 1004 *chr = txt.at(pos); 1126 1005 return pos; 1127 1006 … … 1134 1013 { 1135 1014 Q_D(QLineEdit); 1136 if (d-> hasSelectedText() && start && end) {1137 *start = d->selstart;1138 *end = d->selend;1015 if (d->control->hasSelectedText() && start && end) { 1016 *start = selectionStart(); 1017 *end = *start + selectedText().length(); 1139 1018 return true; 1140 1019 } … … 1154 1033 { 1155 1034 Q_D(QLineEdit); 1156 if (start < 0 || start > (int)d-> text.length()) {1035 if (start < 0 || start > (int)d->control->text().length()) { 1157 1036 qWarning("QLineEdit::setSelection: Invalid start position (%d)", start); 1158 1037 return; 1159 } else { 1160 if (length > 0) { 1161 d->selstart = start; 1162 d->selend = qMin(start + length, (int)d->text.length()); 1163 d->cursor = d->selend; 1164 } else { 1165 d->selstart = qMax(start + length, 0); 1166 d->selend = start; 1167 d->cursor = d->selstart; 1168 } 1169 } 1170 1171 if (d->hasSelectedText()){ 1038 } 1039 1040 d->control->setSelection(start, length); 1041 1042 if (d->control->hasSelectedText()){ 1172 1043 QStyleOptionFrameV2 opt; 1173 1044 initStyleOption(&opt); … … 1175 1046 d->setCursorVisible(false); 1176 1047 } 1177 1178 update();1179 d->emitCursorPositionChanged();1180 1048 } 1181 1049 … … 1193 1061 { 1194 1062 Q_D(const QLineEdit); 1195 return d-> isUndoAvailable();1063 return d->control->isUndoAvailable(); 1196 1064 } 1197 1065 … … 1209 1077 { 1210 1078 Q_D(const QLineEdit); 1211 return d-> isRedoAvailable();1079 return d->control->isRedoAvailable(); 1212 1080 } 1213 1081 … … 1245 1113 { 1246 1114 Q_D(const QLineEdit); 1247 return d-> hasAcceptableInput(d->text);1115 return d->control->hasAcceptableInput(); 1248 1116 } 1249 1117 … … 1264 1132 updateGeometry(); 1265 1133 update(); 1134 } 1135 1136 /*! 1137 \since 4.6 1138 Sets the \a margins around the text inside the frame. 1139 1140 See also textMargins(). 1141 */ 1142 void QLineEdit::setTextMargins(const QMargins &margins) 1143 { 1144 setTextMargins(margins.left(), margins.top(), margins.right(), margins.bottom()); 1266 1145 } 1267 1146 … … 1283 1162 if (bottom) 1284 1163 *bottom = d->bottomTextMargin; 1164 } 1165 1166 /*! 1167 \since 4.6 1168 Returns the widget's text margins. 1169 1170 \sa setTextMargins() 1171 */ 1172 QMargins QLineEdit::textMargins() const 1173 { 1174 Q_D(const QLineEdit); 1175 return QMargins(d->leftTextMargin, d->topTextMargin, d->rightTextMargin, d->bottomTextMargin); 1285 1176 } 1286 1177 … … 1351 1242 { 1352 1243 Q_D(const QLineEdit); 1353 return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString());1244 return d->control->inputMask(); 1354 1245 } 1355 1246 … … 1357 1248 { 1358 1249 Q_D(QLineEdit); 1359 d->parseInputMask(inputMask); 1360 if (d->maskData) 1361 d->moveCursor(d->nextMaskBlank(0)); 1250 d->control->setInputMask(inputMask); 1362 1251 } 1363 1252 … … 1374 1263 { 1375 1264 Q_D(QLineEdit); 1376 d->selstart = d->selend = d->cursor = 0; 1377 d->moveCursor(d->text.length(), true); 1265 d->control->selectAll(); 1378 1266 } 1379 1267 … … 1387 1275 { 1388 1276 Q_D(QLineEdit); 1389 d->deselect(); 1390 d->finishChange(); 1277 d->control->deselect(); 1391 1278 } 1392 1279 … … 1403 1290 // q->resetInputContext(); //#### FIX ME IN QT 1404 1291 Q_D(QLineEdit); 1405 int priorState = d->undoState; 1406 d->removeSelectedText(); 1407 d->insert(newText); 1408 d->finishChange(priorState); 1292 d->control->insert(newText); 1409 1293 } 1410 1294 … … 1417 1301 { 1418 1302 Q_D(QLineEdit); 1419 int priorState = d->undoState;1420 1303 resetInputContext(); 1421 d->selstart = 0; 1422 d->selend = d->text.length(); 1423 d->removeSelectedText(); 1424 d->separate(); 1425 d->finishChange(priorState, /*update*/false, /*edited*/false); 1304 d->control->clear(); 1426 1305 } 1427 1306 … … 1436 1315 Q_D(QLineEdit); 1437 1316 resetInputContext(); 1438 d->undo(); 1439 d->finishChange(-1, true); 1317 d->control->undo(); 1440 1318 } 1441 1319 … … 1448 1326 Q_D(QLineEdit); 1449 1327 resetInputContext(); 1450 d->redo(); 1451 d->finishChange(); 1328 d->control->redo(); 1452 1329 } 1453 1330 … … 1471 1348 { 1472 1349 Q_D(const QLineEdit); 1473 return d-> readOnly;1350 return d->control->isReadOnly(); 1474 1351 } 1475 1352 … … 1477 1354 { 1478 1355 Q_D(QLineEdit); 1479 if (d-> readOnly!= enable) {1480 d-> readOnly = enable;1481 setAttribute(Qt::WA_MacShowFocusRect, ! d->readOnly);1482 setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));1356 if (d->control->isReadOnly() != enable) { 1357 d->control->setReadOnly(enable); 1358 setAttribute(Qt::WA_MacShowFocusRect, !enable); 1359 setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod()); 1483 1360 #ifndef QT_NO_CURSOR 1484 1361 setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor); … … 1519 1396 { 1520 1397 Q_D(const QLineEdit); 1521 d->co py();1398 d->control->copy(); 1522 1399 } 1523 1400 … … 1536 1413 { 1537 1414 Q_D(QLineEdit); 1538 if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) { 1539 // Clear the edit and reset to normal echo mode when pasting; the echo 1540 // mode switches back when the edit loses focus. ### changes a public 1541 // property, resets current content 1542 d->updatePasswordEchoEditing(true); 1543 clear(); 1544 } 1545 insert(QApplication::clipboard()->text(QClipboard::Clipboard)); 1546 } 1547 1548 void QLineEditPrivate::copy(bool clipboard) const 1549 { 1550 Q_Q(const QLineEdit); 1551 QString t = q->selectedText(); 1552 if (!t.isEmpty() && echoMode == QLineEdit::Normal) { 1553 q->disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), q, 0); 1554 QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection); 1555 q->connect(QApplication::clipboard(), SIGNAL(selectionChanged()), 1556 q, SLOT(_q_clipboardChanged())); 1557 } 1415 d->control->paste(); 1558 1416 } 1559 1417 … … 1565 1423 { 1566 1424 Q_D(QLineEdit); 1567 #ifndef QT_NO_SHORTCUT 1568 if (e->type() == QEvent::ShortcutOverride && !d->readOnly) { 1569 QKeyEvent* ke = (QKeyEvent*) e; 1570 if (ke == QKeySequence::Copy 1571 || ke == QKeySequence::Paste 1572 || ke == QKeySequence::Cut 1573 || ke == QKeySequence::Redo 1574 || ke == QKeySequence::Undo 1575 || ke == QKeySequence::MoveToNextWord 1576 || ke == QKeySequence::MoveToPreviousWord 1577 || ke == QKeySequence::MoveToStartOfDocument 1578 || ke == QKeySequence::MoveToEndOfDocument 1579 || ke == QKeySequence::SelectNextWord 1580 || ke == QKeySequence::SelectPreviousWord 1581 || ke == QKeySequence::SelectStartOfLine 1582 || ke == QKeySequence::SelectEndOfLine 1583 || ke == QKeySequence::SelectStartOfBlock 1584 || ke == QKeySequence::SelectEndOfBlock 1585 || ke == QKeySequence::SelectStartOfDocument 1586 || ke == QKeySequence::SelectAll 1587 || ke == QKeySequence::SelectEndOfDocument) { 1588 ke->accept(); 1589 } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier 1590 || ke->modifiers() == Qt::KeypadModifier) { 1591 if (ke->key() < Qt::Key_Escape) { 1592 ke->accept(); 1593 } else { 1594 switch (ke->key()) { 1595 case Qt::Key_Delete: 1596 case Qt::Key_Home: 1597 case Qt::Key_End: 1598 case Qt::Key_Backspace: 1599 case Qt::Key_Left: 1600 case Qt::Key_Right: 1601 ke->accept(); 1602 default: 1603 break; 1604 } 1605 } 1606 } 1607 } else 1608 #endif 1609 if (e->type() == QEvent::Timer) { 1425 if (e->type() == QEvent::Timer) { 1610 1426 // should be timerEvent, is here for binary compatibility 1611 1427 int timerId = ((QTimerEvent*)e)->timerId(); 1612 if (timerId == d->cursorTimer) { 1613 QStyleOptionFrameV2 opt; 1614 initStyleOption(&opt); 1615 if(!hasSelectedText() 1616 || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) 1617 d->setCursorVisible(!d->cursorVisible); 1428 if (false) { 1618 1429 #ifndef QT_NO_DRAGANDDROP 1619 1430 } else if (timerId == d->dndTimer.timerId()) { … … 1623 1434 else if (timerId == d->tripleClickTimer.timerId()) 1624 1435 d->tripleClickTimer.stop(); 1625 #ifdef QT_KEYPAD_NAVIGATION1626 else if (timerId == d->deleteAllTimer.timerId()) {1627 d->deleteAllTimer.stop();1628 clear();1629 }1630 #endif1631 1436 } else if (e->type() == QEvent::ContextMenu) { 1632 1437 #ifndef QT_NO_IM 1633 if (d->co mposeMode())1438 if (d->control->composeMode()) 1634 1439 return true; 1635 1440 #endif 1636 d->separate();1441 //d->separate(); 1637 1442 } else if (e->type() == QEvent::WindowActivate) { 1638 1443 QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate())); 1639 } 1444 }else if(e->type() == QEvent::ShortcutOverride){ 1445 d->control->processEvent(e); 1446 } else if (e->type() == QEvent::KeyRelease) { 1447 d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); 1448 } else if (e->type() == QEvent::Show) { 1449 //In order to get the cursor blinking if QComboBox::setEditable is called when the combobox has focus 1450 if (hasFocus()) { 1451 d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); 1452 QStyleOptionFrameV2 opt; 1453 initStyleOption(&opt); 1454 if ((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) 1455 || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) 1456 d->setCursorVisible(true); 1457 } 1458 } 1459 1640 1460 #ifdef QT_KEYPAD_NAVIGATION 1641 1461 if (QApplication::keypadNavigationEnabled()) { 1642 if ((e->type() == QEvent::KeyPress) || (e->type() == QEvent::KeyRelease)) { 1643 QKeyEvent *ke = (QKeyEvent *)e; 1644 if (ke->key() == Qt::Key_Back) { 1645 if (ke->isAutoRepeat()) { 1646 // Swallow it. We don't want back keys running amok. 1647 ke->accept(); 1648 return true; 1649 } 1650 if ((e->type() == QEvent::KeyRelease) 1651 && !isReadOnly() 1652 && d->deleteAllTimer.isActive()) { 1653 d->deleteAllTimer.stop(); 1654 backspace(); 1655 ke->accept(); 1656 return true; 1657 } 1658 } 1659 } else if (e->type() == QEvent::EnterEditFocus) { 1462 if (e->type() == QEvent::EnterEditFocus) { 1660 1463 end(false); 1661 if (!d->cursorTimer) { 1662 int cft = QApplication::cursorFlashTime(); 1663 d->cursorTimer = cft ? startTimer(cft/2) : -1; 1664 } 1464 d->setCursorVisible(true); 1465 d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); 1665 1466 } else if (e->type() == QEvent::LeaveEditFocus) { 1666 1467 d->setCursorVisible(false); 1667 if (d->cursorTimer > 0) 1668 killTimer(d->cursorTimer); 1669 d->cursorTimer = 0; 1670 1671 if (!d->emitingEditingFinished) { 1672 if (hasAcceptableInput() || d->fixup()) { 1673 d->emitingEditingFinished = true; 1674 emit editingFinished(); 1675 d->emitingEditingFinished = false; 1676 } 1677 } 1468 d->control->setCursorBlinkPeriod(0); 1469 if (d->control->hasAcceptableInput() || d->control->fixup()) 1470 emit editingFinished(); 1678 1471 } 1679 1472 } … … 1688 1481 Q_D(QLineEdit); 1689 1482 if (d->sendMouseEventToInputContext(e)) 1690 1483 return; 1691 1484 if (e->button() == Qt::RightButton) 1692 1485 return; … … 1695 1488 setEditFocus(true); 1696 1489 // Get the completion list to pop up. 1697 if (d->co mpleter)1698 d->co mpleter->complete();1490 if (d->control->completer()) 1491 d->control->completer()->complete(); 1699 1492 } 1700 1493 #endif … … 1707 1500 int cursor = d->xToPos(e->pos().x()); 1708 1501 #ifndef QT_NO_DRAGANDDROP 1709 if (!mark && d->dragEnabled && d->echoMode == Normal && 1710 e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) { 1711 d->cursor = cursor; 1712 update(); 1502 if (!mark && d->dragEnabled && d->control->echoMode() == Normal && 1503 e->button() == Qt::LeftButton && d->control->inSelection(e->pos().x())) { 1713 1504 d->dndPos = e->pos(); 1714 1505 if (!d->dndTimer.isActive()) 1715 1506 d->dndTimer.start(QApplication::startDragTime(), this); 1716 d->emitCursorPositionChanged();1717 1507 } else 1718 1508 #endif 1719 1509 { 1720 d-> moveCursor(cursor, mark);1510 d->control->moveCursor(cursor, mark); 1721 1511 } 1722 1512 } … … 1728 1518 Q_D(QLineEdit); 1729 1519 if (d->sendMouseEventToInputContext(e)) 1730 1520 return; 1731 1521 1732 1522 if (e->buttons() & Qt::LeftButton) { … … 1738 1528 #endif 1739 1529 { 1740 d-> moveCursor(d->xToPos(e->pos().x()), true);1530 d->control->moveCursor(d->xToPos(e->pos().x()), true); 1741 1531 } 1742 1532 } … … 1749 1539 Q_D(QLineEdit); 1750 1540 if (d->sendMouseEventToInputContext(e)) 1751 1541 return; 1752 1542 #ifndef QT_NO_DRAGANDDROP 1753 1543 if (e->button() == Qt::LeftButton) { … … 1762 1552 if (QApplication::clipboard()->supportsSelection()) { 1763 1553 if (e->button() == Qt::LeftButton) { 1764 d->co py(false);1765 } else if (!d-> readOnly&& e->button() == Qt::MidButton) {1766 d ->deselect();1554 d->control->copy(QClipboard::Selection); 1555 } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) { 1556 deselect(); 1767 1557 insert(QApplication::clipboard()->text(QClipboard::Selection)); 1768 1558 } 1769 1559 } 1770 1560 #endif 1561 1562 if (!isReadOnly() && rect().contains(e->pos())) 1563 d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus); 1564 d->clickCausedFocus = 0; 1771 1565 } 1772 1566 … … 1777 1571 Q_D(QLineEdit); 1778 1572 if (d->sendMouseEventToInputContext(e)) 1779 1573 return; 1780 1574 if (e->button() == Qt::LeftButton) { 1781 deselect(); 1782 d->cursor = d->xToPos(e->pos().x()); 1783 d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords); 1784 // ## text layout should support end of words. 1785 int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords); 1786 while (end > d->cursor && d->text[end-1].isSpace()) 1787 --end; 1788 d->moveCursor(end, true); 1575 d->control->selectWordAtPos(d->xToPos(e->pos().x())); 1789 1576 d->tripleClickTimer.start(QApplication::doubleClickInterval(), this); 1790 1577 d->tripleClick = e->pos(); … … 1826 1613 { 1827 1614 Q_D(QLineEdit); 1828 1829 bool inlineCompletionAccepted = false; 1830 1831 #ifndef QT_NO_COMPLETER 1832 if (d->completer) { 1833 QCompleter::CompletionMode completionMode = d->completer->completionMode(); 1834 if ((completionMode == QCompleter::PopupCompletion 1835 || completionMode == QCompleter::UnfilteredPopupCompletion) 1836 &&d->completer->popup() 1837 && d->completer->popup()->isVisible()) { 1838 // The following keys are forwarded by the completer to the widget 1839 // Ignoring the events lets the completer provide suitable default behavior 1840 switch (event->key()) { 1841 case Qt::Key_Escape: 1842 event->ignore(); 1843 return; 1844 case Qt::Key_Enter: 1845 case Qt::Key_Return: 1846 case Qt::Key_F4: 1847 #ifdef QT_KEYPAD_NAVIGATION 1848 case Qt::Key_Select: 1849 if (!QApplication::keypadNavigationEnabled()) 1850 break; 1851 #endif 1852 d->completer->popup()->hide(); // just hide. will end up propagating to parent 1853 default: 1854 break; // normal key processing 1855 } 1856 } else if (completionMode == QCompleter::InlineCompletion) { 1857 switch (event->key()) { 1858 case Qt::Key_Enter: 1859 case Qt::Key_Return: 1860 case Qt::Key_F4: 1861 #ifdef QT_KEYPAD_NAVIGATION 1862 case Qt::Key_Select: 1863 if (!QApplication::keypadNavigationEnabled()) 1864 break; 1865 #endif 1866 if (!d->completer->currentCompletion().isEmpty() && d->selend > d->selstart 1867 && d->selend == d->text.length()) { 1868 setText(d->completer->currentCompletion()); 1869 inlineCompletionAccepted = true; 1870 } 1871 default: 1872 break; // normal key processing 1873 } 1874 } 1875 } 1876 #endif // QT_NO_COMPLETER 1877 1878 #ifdef QT_KEYPAD_NAVIGATION 1615 #ifdef QT_KEYPAD_NAVIGATION 1879 1616 bool select = false; 1880 1617 switch (event->key()) { … … 1883 1620 if (hasEditFocus()) { 1884 1621 setEditFocus(false); 1885 if (d->co mpleter && d->completer->popup()->isVisible())1886 d->co mpleter->popup()->hide();1622 if (d->control->completer() && d->control->completer()->popup()->isVisible()) 1623 d->control->completer()->popup()->hide(); 1887 1624 select = true; 1888 1625 } … … 1903 1640 { 1904 1641 setEditFocus(true); 1642 #ifndef Q_OS_SYMBIAN 1905 1643 clear(); 1644 #endif 1906 1645 } else { 1907 1646 event->ignore(); … … 1920 1659 } 1921 1660 #endif 1922 1923 if (echoMode() == PasswordEchoOnEdit 1924 && !d->passwordEchoEditing 1925 && !isReadOnly() 1926 && !event->text().isEmpty() 1927 #ifdef QT_KEYPAD_NAVIGATION 1928 && event->key() != Qt::Key_Select 1929 && event->key() != Qt::Key_Up 1930 && event->key() != Qt::Key_Down 1931 && event->key() != Qt::Key_Back 1932 #endif 1933 && !(event->modifiers() & Qt::ControlModifier)) { 1934 // Clear the edit and reset to normal echo mode while editing; the 1935 // echo mode switches back when the edit loses focus. ### changes a 1936 // public property, resets current content. dubious code; you can 1937 // navigate with keys up, down, back, and select(?), but if you press 1938 // "left" or "right" it clears? 1939 d->updatePasswordEchoEditing(true); 1940 clear(); 1941 } 1942 1943 d->setCursorVisible(true); 1944 if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { 1945 if (hasAcceptableInput() || d->fixup()) { 1946 emit returnPressed(); 1947 d->emitingEditingFinished = true; 1948 emit editingFinished(); 1949 d->emitingEditingFinished = false; 1950 } 1951 if (inlineCompletionAccepted) 1952 event->accept(); 1953 else 1954 event->ignore(); 1955 return; 1956 } 1957 bool unknown = false; 1958 1959 if (false) { 1960 } 1961 #ifndef QT_NO_SHORTCUT 1962 else if (event == QKeySequence::Undo) { 1963 if (!d->readOnly) 1964 undo(); 1965 } 1966 else if (event == QKeySequence::Redo) { 1967 if (!d->readOnly) 1968 redo(); 1969 } 1970 else if (event == QKeySequence::SelectAll) { 1971 selectAll(); 1972 } 1973 #ifndef QT_NO_CLIPBOARD 1974 else if (event == QKeySequence::Copy) { 1975 copy(); 1976 } 1977 else if (event == QKeySequence::Paste) { 1978 if (!d->readOnly) 1979 paste(); 1980 } 1981 else if (event == QKeySequence::Cut) { 1982 if (!d->readOnly) { 1983 cut(); 1984 } 1985 } 1986 else if (event == QKeySequence::DeleteEndOfLine) { 1987 if (!d->readOnly) { 1988 setSelection(d->cursor, d->text.size()); 1989 copy(); 1990 del(); 1991 } 1992 } 1993 #endif //QT_NO_CLIPBOARD 1994 else if (event == QKeySequence::MoveToStartOfLine) { 1995 home(0); 1996 } 1997 else if (event == QKeySequence::MoveToEndOfLine) { 1998 end(0); 1999 } 2000 else if (event == QKeySequence::SelectStartOfLine) { 2001 home(1); 2002 } 2003 else if (event == QKeySequence::SelectEndOfLine) { 2004 end(1); 2005 } 2006 else if (event == QKeySequence::MoveToNextChar) { 2007 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) 2008 if (d->hasSelectedText()) { 2009 #else 2010 if (d->hasSelectedText() && d->completer 2011 && d->completer->completionMode() == QCompleter::InlineCompletion) { 2012 #endif 2013 d->moveCursor(d->selend, false); 2014 } else { 2015 cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); 2016 } 2017 } 2018 else if (event == QKeySequence::SelectNextChar) { 2019 cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); 2020 } 2021 else if (event == QKeySequence::MoveToPreviousChar) { 2022 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) 2023 if (d->hasSelectedText()) { 2024 #else 2025 if (d->hasSelectedText() && d->completer 2026 && d->completer->completionMode() == QCompleter::InlineCompletion) { 2027 #endif 2028 d->moveCursor(d->selstart, false); 2029 } else { 2030 cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); 2031 } 2032 } 2033 else if (event == QKeySequence::SelectPreviousChar) { 2034 cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); 2035 } 2036 else if (event == QKeySequence::MoveToNextWord) { 2037 if (echoMode() == Normal) 2038 layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0); 2039 else 2040 layoutDirection() == Qt::LeftToRight ? end(0) : home(0); 2041 } 2042 else if (event == QKeySequence::MoveToPreviousWord) { 2043 if (echoMode() == Normal) 2044 layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0); 2045 else if (!d->readOnly) { 2046 layoutDirection() == Qt::LeftToRight ? home(0) : end(0); 2047 } 2048 } 2049 else if (event == QKeySequence::SelectNextWord) { 2050 if (echoMode() == Normal) 2051 layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1); 2052 else 2053 layoutDirection() == Qt::LeftToRight ? end(1) : home(1); 2054 } 2055 else if (event == QKeySequence::SelectPreviousWord) { 2056 if (echoMode() == Normal) 2057 layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1); 2058 else 2059 layoutDirection() == Qt::LeftToRight ? home(1) : end(1); 2060 } 2061 else if (event == QKeySequence::Delete) { 2062 if (!d->readOnly) 2063 del(); 2064 } 2065 else if (event == QKeySequence::DeleteEndOfWord) { 2066 if (!d->readOnly) { 2067 cursorWordForward(true); 2068 del(); 2069 } 2070 } 2071 else if (event == QKeySequence::DeleteStartOfWord) { 2072 if (!d->readOnly) { 2073 cursorWordBackward(true); 2074 del(); 2075 } 2076 } 2077 #endif // QT_NO_SHORTCUT 2078 else { 2079 #ifdef Q_WS_MAC 2080 if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) { 2081 Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier); 2082 if (myModifiers & Qt::ShiftModifier) { 2083 if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier) 2084 || myModifiers == (Qt::AltModifier|Qt::ShiftModifier) 2085 || myModifiers == Qt::ShiftModifier) { 2086 2087 event->key() == Qt::Key_Up ? home(1) : end(1); 2088 } 2089 } else { 2090 if ((myModifiers == Qt::ControlModifier 2091 || myModifiers == Qt::AltModifier 2092 || myModifiers == Qt::NoModifier)) { 2093 event->key() == Qt::Key_Up ? home(0) : end(0); 2094 } 2095 } 2096 } 2097 #endif 2098 if (event->modifiers() & Qt::ControlModifier) { 2099 switch (event->key()) { 2100 case Qt::Key_Backspace: 2101 if (!d->readOnly) { 2102 cursorWordBackward(true); 2103 del(); 2104 } 2105 break; 2106 #ifndef QT_NO_COMPLETER 2107 case Qt::Key_Up: 2108 case Qt::Key_Down: 2109 d->complete(event->key()); 2110 break; 2111 #endif 2112 #if defined(Q_WS_X11) 2113 case Qt::Key_E: 2114 end(0); 2115 break; 2116 2117 case Qt::Key_U: 2118 if (!d->readOnly) { 2119 setSelection(0, d->text.size()); 2120 #ifndef QT_NO_CLIPBOARD 2121 copy(); 2122 #endif 2123 del(); 2124 } 2125 break; 2126 #endif 2127 default: 2128 unknown = true; 2129 } 2130 } else { // ### check for *no* modifier 2131 switch (event->key()) { 2132 case Qt::Key_Backspace: 2133 if (!d->readOnly) { 2134 backspace(); 2135 #ifndef QT_NO_COMPLETER 2136 d->complete(Qt::Key_Backspace); 2137 #endif 2138 } 2139 break; 2140 #ifdef QT_KEYPAD_NAVIGATION 2141 case Qt::Key_Back: 2142 if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() 2143 && !isReadOnly()) { 2144 if (text().length() == 0) { 2145 setText(d->origText); 2146 2147 if (d->passwordEchoEditing) 2148 d->updatePasswordEchoEditing(false); 2149 2150 setEditFocus(false); 2151 } else if (!d->deleteAllTimer.isActive()) { 2152 d->deleteAllTimer.start(750, this); 2153 } 2154 } else { 2155 unknown = true; 2156 } 2157 break; 2158 #endif 2159 2160 default: 2161 unknown = true; 2162 } 2163 } 2164 } 2165 2166 if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) { 2167 setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); 2168 d->updateTextLayout(); 2169 update(); 2170 unknown = false; 2171 } 2172 2173 if (unknown && !d->readOnly) { 2174 QString t = event->text(); 2175 if (!t.isEmpty() && t.at(0).isPrint()) { 2176 insert(t); 2177 #ifndef QT_NO_COMPLETER 2178 d->complete(event->key()); 2179 #endif 2180 event->accept(); 2181 return; 2182 } 2183 } 2184 2185 if (unknown) 2186 event->ignore(); 2187 else 2188 event->accept(); 1661 d->control->processKeyEvent(event); 1662 if (event->isAccepted()) 1663 d->control->setCursorBlinkPeriod(0); 2189 1664 } 2190 1665 … … 2198 1673 Q_D(const QLineEdit); 2199 1674 return d->cursorRect(); 2200 }2201 2202 /*!2203 This function is not intended as polymorphic usage. Just a shared code2204 fragment that calls QInputContext::mouseHandler for this2205 class.2206 */2207 bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )2208 {2209 #if !defined QT_NO_IM2210 Q_Q(QLineEdit);2211 if ( composeMode() ) {2212 int tmp_cursor = xToPos(e->pos().x());2213 int mousePos = tmp_cursor - cursor;2214 if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) {2215 mousePos = -1;2216 // don't send move events outside the preedit area2217 if ( e->type() == QEvent::MouseMove )2218 return true;2219 }2220 2221 QInputContext *qic = q->inputContext();2222 if ( qic )2223 // may be causing reset() in some input methods2224 qic->mouseHandler(mousePos, e);2225 if (!textLayout.preeditAreaText().isEmpty())2226 return true;2227 }2228 #else2229 Q_UNUSED(e);2230 #endif2231 2232 return false;2233 1675 } 2234 1676 … … 2238 1680 { 2239 1681 Q_D(QLineEdit); 2240 if (d-> readOnly) {1682 if (d->control->isReadOnly()) { 2241 1683 e->ignore(); 2242 1684 return; 2243 1685 } 2244 1686 2245 if (echoMode() == PasswordEchoOnEdit && !d-> passwordEchoEditing) {1687 if (echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing()) { 2246 1688 // Clear the edit and reset to normal echo mode while entering input 2247 1689 // method data; the echo mode switches back when the edit loses focus. … … 2259 1701 && !e->preeditString().isEmpty()) { 2260 1702 setEditFocus(true); 1703 #ifndef Q_OS_SYMBIAN 2261 1704 selectAll(); // so text is replaced rather than appended to 2262 } 2263 #endif 2264 2265 int priorState = d->undoState; 2266 d->removeSelectedText(); 2267 2268 int c = d->cursor; // cursor position after insertion of commit string 2269 if (e->replacementStart() <= 0) 2270 c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength()); 2271 2272 d->cursor += e->replacementStart(); 2273 2274 // insert commit string 2275 if (e->replacementLength()) { 2276 d->selstart = d->cursor; 2277 d->selend = d->selstart + e->replacementLength(); 2278 d->removeSelectedText(); 2279 } 2280 if (!e->commitString().isEmpty()) 2281 d->insert(e->commitString()); 2282 2283 d->cursor = qMin(c, d->text.length()); 2284 2285 d->textLayout.setPreeditArea(d->cursor, e->preeditString()); 2286 d->preeditCursor = e->preeditString().length(); 2287 d->hideCursor = false; 2288 QList<QTextLayout::FormatRange> formats; 2289 for (int i = 0; i < e->attributes().size(); ++i) { 2290 const QInputMethodEvent::Attribute &a = e->attributes().at(i); 2291 if (a.type == QInputMethodEvent::Cursor) { 2292 d->preeditCursor = a.start; 2293 d->hideCursor = !a.length; 2294 } else if (a.type == QInputMethodEvent::TextFormat) { 2295 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat(); 2296 if (f.isValid()) { 2297 QTextLayout::FormatRange o; 2298 o.start = a.start + d->cursor; 2299 o.length = a.length; 2300 o.format = f; 2301 formats.append(o); 2302 } 2303 } 2304 } 2305 d->textLayout.setAdditionalFormats(formats); 2306 d->updateTextLayout(); 2307 update(); 2308 if (!e->commitString().isEmpty()) 2309 d->emitCursorPositionChanged(); 2310 d->finishChange(priorState); 1705 #endif 1706 } 1707 #endif 1708 1709 d->control->processInputMethodEvent(e); 1710 2311 1711 #ifndef QT_NO_COMPLETER 2312 1712 if (!e->commitString().isEmpty()) 2313 d->co mplete(Qt::Key_unknown);1713 d->control->complete(Qt::Key_unknown); 2314 1714 #endif 2315 1715 } … … 2326 1726 return font(); 2327 1727 case Qt::ImCursorPosition: 2328 return QVariant( (d->selend - d->selstart == 0) ? d->cursor : d->selend);1728 return QVariant(d->control->cursor()); 2329 1729 case Qt::ImSurroundingText: 2330 return QVariant( d->text);1730 return QVariant(text()); 2331 1731 case Qt::ImCurrentSelection: 2332 1732 return QVariant(selectedText()); 1733 case Qt::ImMaximumTextLength: 1734 return QVariant(maxLength()); 1735 case Qt::ImAnchorPosition: 1736 if (d->control->selectionStart() == d->control->selectionEnd()) 1737 return QVariant(d->control->cursor()); 1738 else if (d->control->selectionStart() == d->control->cursor()) 1739 return QVariant(d->control->selectionEnd()); 1740 else 1741 return QVariant(d->control->selectionStart()); 2333 1742 default: 2334 1743 return QVariant(); … … 2345 1754 e->reason() == Qt::BacktabFocusReason || 2346 1755 e->reason() == Qt::ShortcutFocusReason) { 2347 if ( d->maskData)2348 d-> moveCursor(d->nextMaskBlank(0));2349 else if (!d-> hasSelectedText())1756 if (!d->control->inputMask().isEmpty()) 1757 d->control->moveCursor(d->control->nextMaskBlank(0)); 1758 else if (!d->control->hasSelectedText()) 2350 1759 selectAll(); 1760 } else if (e->reason() == Qt::MouseFocusReason) { 1761 d->clickCausedFocus = 1; 2351 1762 } 2352 1763 #ifdef QT_KEYPAD_NAVIGATION 2353 if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason)) 2354 #endif 2355 if (!d->cursorTimer) { 2356 int cft = QApplication::cursorFlashTime(); 2357 d->cursorTimer = cft ? startTimer(cft/2) : -1; 2358 } 1764 if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && ( e->reason() == Qt::PopupFocusReason 1765 #ifdef Q_OS_SYMBIAN 1766 || e->reason() == Qt::ActiveWindowFocusReason 1767 #endif 1768 ))) { 1769 #endif 1770 d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); 2359 1771 QStyleOptionFrameV2 opt; 2360 1772 initStyleOption(&opt); 2361 if((!hasSelectedText() && d-> textLayout.preeditAreaText().isEmpty())1773 if((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) 2362 1774 || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) 2363 1775 d->setCursorVisible(true); 2364 1776 #ifdef Q_WS_MAC 2365 if (d-> echoMode == Password || d->echoMode== NoEcho)1777 if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) 2366 1778 qt_mac_secure_keyboard(true); 2367 1779 #endif 2368 1780 #ifdef QT_KEYPAD_NAVIGATION 2369 d->origText = d->text; 1781 d->control->setCancelText(d->control->text()); 1782 } 2370 1783 #endif 2371 1784 #ifndef QT_NO_COMPLETER 2372 if (d->co mpleter) {2373 d->co mpleter->setWidget(this);2374 QObject::connect(d->co mpleter, SIGNAL(activated(QString)),1785 if (d->control->completer()) { 1786 d->control->completer()->setWidget(this); 1787 QObject::connect(d->control->completer(), SIGNAL(activated(QString)), 2375 1788 this, SLOT(setText(QString))); 2376 QObject::connect(d->co mpleter, SIGNAL(highlighted(QString)),1789 QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)), 2377 1790 this, SLOT(_q_completionHighlighted(QString))); 2378 1791 } … … 2387 1800 { 2388 1801 Q_D(QLineEdit); 2389 if (d-> passwordEchoEditing) {1802 if (d->control->passwordEchoEditing()) { 2390 1803 // Reset the echomode back to PasswordEchoOnEdit when the widget loses 2391 1804 // focus. … … 2399 1812 2400 1813 d->setCursorVisible(false); 2401 if (d->cursorTimer > 0) 2402 killTimer(d->cursorTimer); 2403 d->cursorTimer = 0; 2404 1814 d->control->setCursorBlinkPeriod(0); 2405 1815 #ifdef QT_KEYPAD_NAVIGATION 2406 1816 // editingFinished() is already emitted on LeaveEditFocus … … 2409 1819 if (reason != Qt::PopupFocusReason 2410 1820 || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { 2411 if (!d->emitingEditingFinished) { 2412 if (hasAcceptableInput() || d->fixup()) { 2413 d->emitingEditingFinished = true; 1821 if (hasAcceptableInput() || d->control->fixup()) 2414 1822 emit editingFinished(); 2415 d->emitingEditingFinished = false;2416 }2417 }2418 1823 #ifdef QT3_SUPPORT 2419 1824 emit lostFocus(); … … 2421 1826 } 2422 1827 #ifdef Q_WS_MAC 2423 if (d-> echoMode == Password || d->echoMode== NoEcho)1828 if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) 2424 1829 qt_mac_secure_keyboard(false); 2425 1830 #endif 2426 1831 #ifdef QT_KEYPAD_NAVIGATION 2427 d-> origText = QString();1832 d->control->setCancelText(QString()); 2428 1833 #endif 2429 1834 #ifndef QT_NO_COMPLETER 2430 if (d->co mpleter) {2431 QObject::disconnect(d->co mpleter, 0, this, 0);1835 if (d->control->completer()) { 1836 QObject::disconnect(d->control->completer(), 0, this, 0); 2432 1837 } 2433 1838 #endif … … 2459 1864 switch (va & Qt::AlignVertical_Mask) { 2460 1865 case Qt::AlignBottom: 2461 d->vscroll = r.y() + r.height() - fm.height() - verticalMargin;1866 d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin; 2462 1867 break; 2463 1868 case Qt::AlignTop: 2464 d->vscroll = r.y() + verticalMargin;1869 d->vscroll = r.y() + d->verticalMargin; 2465 1870 break; 2466 1871 default: … … 2469 1874 break; 2470 1875 } 2471 QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height()); 2472 QTextLine line = d->textLayout.lineAt(0); 2473 2474 int cursor = d->cursor; 2475 if (d->preeditCursor != -1) 2476 cursor += d->preeditCursor; 2477 // locate cursor position 2478 int cix = qRound(line.cursorToX(cursor)); 1876 QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height()); 1877 1878 if (d->control->text().isEmpty()) { 1879 if (!hasFocus() && !d->placeholderText.isEmpty()) { 1880 QColor col = pal.text().color(); 1881 col.setAlpha(128); 1882 QPen oldpen = p.pen(); 1883 p.setPen(col); 1884 p.drawText(lineRect, va, d->placeholderText); 1885 p.setPen(oldpen); 1886 return; 1887 } 1888 } 1889 1890 int cix = qRound(d->control->cursorToX()); 2479 1891 2480 1892 // horizontal scrolling. d->hscroll is the left indent from the beginning … … 2486 1898 int minLB = qMax(0, -fm.minLeftBearing()); 2487 1899 int minRB = qMax(0, -fm.minRightBearing()); 2488 int widthUsed = qRound( line.naturalTextWidth()) + 1 + minRB;1900 int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; 2489 1901 if ((minLB + widthUsed) <= lineRect.width()) { 2490 1902 // text fits in lineRect; use hscroll for alignment … … 2514 1926 } 2515 1927 // the y offset is there to keep the baseline constant in case we have script changes in the text. 2516 QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d-> ascent- fm.ascent());1928 QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); 2517 1929 2518 1930 // draw text, selections and cursors 2519 1931 #ifndef QT_NO_STYLE_STYLESHEET 2520 1932 if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) { 2521 cssStyle-> focusPalette(this, &panel, &pal);1933 cssStyle->styleSheetPalette(this, &panel, &pal); 2522 1934 } 2523 1935 #endif 2524 1936 p.setPen(pal.text().color()); 2525 1937 2526 QVector<QTextLayout::FormatRange> selections; 1938 int flags = QLineControl::DrawText; 1939 2527 1940 #ifdef QT_KEYPAD_NAVIGATION 2528 1941 if (!QApplication::keypadNavigationEnabled() || hasEditFocus()) 2529 1942 #endif 2530 if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) { 2531 QTextLayout::FormatRange o; 2532 if (d->selstart < d->selend) { 2533 o.start = d->selstart; 2534 o.length = d->selend - d->selstart; 2535 o.format.setBackground(pal.brush(QPalette::Highlight)); 2536 o.format.setForeground(pal.brush(QPalette::HighlightedText)); 2537 } else { 2538 // mask selection 2539 o.start = d->cursor; 2540 o.length = 1; 2541 o.format.setBackground(pal.brush(QPalette::Text)); 2542 o.format.setForeground(pal.brush(QPalette::Window)); 2543 } 2544 selections.append(o); 1943 if (d->control->hasSelectedText() || (d->cursorVisible && !d->control->inputMask().isEmpty() && !d->control->isReadOnly())){ 1944 flags |= QLineControl::DrawSelections; 1945 // Palette only used for selections/mask and may not be in sync 1946 if(d->control->palette() != pal) 1947 d->control->setPalette(pal); 2545 1948 } 2546 1949 … … 2548 1951 // selection phase of input method, so the ordinary cursor should be 2549 1952 // invisible if we have a preedit string. 2550 d->textLayout.draw(&p, topLeft, selections, r); 2551 if (d->cursorVisible && !d->readOnly && !d->hideCursor) 2552 d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth)); 1953 if (d->cursorVisible && !d->control->isReadOnly()) 1954 flags |= QLineControl::DrawCursor; 1955 1956 d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth)); 1957 d->control->draw(&p, topLeft, r, flags); 1958 2553 1959 } 2554 1960 … … 2560 1966 { 2561 1967 Q_D(QLineEdit); 2562 if (!d-> readOnly&& e->mimeData()->hasFormat(QLatin1String("text/plain"))) {1968 if (!d->control->isReadOnly() && e->mimeData()->hasFormat(QLatin1String("text/plain"))) { 2563 1969 e->acceptProposedAction(); 2564 d->c ursor = d->xToPos(e->pos().x());1970 d->control->moveCursor(d->xToPos(e->pos().x()), false); 2565 1971 d->cursorVisible = true; 2566 1972 update(); 2567 d->emitCursorPositionChanged();2568 1973 } 2569 1974 } … … 2591 1996 QString str = e->mimeData()->text(); 2592 1997 2593 if (!str.isNull() && !d-> readOnly) {1998 if (!str.isNull() && !d->control->isReadOnly()) { 2594 1999 if (e->source() == this && e->dropAction() == Qt::CopyAction) 2595 2000 deselect(); 2596 d->cursor =d->xToPos(e->pos().x()); 2597 int selStart = d->cursor; 2598 int oldSelStart = d->selstart; 2599 int oldSelEnd = d->selend; 2001 int cursorPos = d->xToPos(e->pos().x()); 2002 int selStart = cursorPos; 2003 int oldSelStart = d->control->selectionStart(); 2004 int oldSelEnd = d->control->selectionEnd(); 2005 d->control->moveCursor(cursorPos, false); 2600 2006 d->cursorVisible = false; 2601 2007 e->acceptProposedAction(); … … 2619 2025 } 2620 2026 2621 void QLineEditPrivate::drag()2622 {2623 Q_Q(QLineEdit);2624 dndTimer.stop();2625 QMimeData *data = new QMimeData;2626 data->setText(q->selectedText());2627 QDrag *drag = new QDrag(q);2628 drag->setMimeData(data);2629 Qt::DropAction action = drag->start();2630 if (action == Qt::MoveAction && !readOnly && drag->target() != q) {2631 int priorState = undoState;2632 removeSelectedText();2633 finishChange(priorState);2634 }2635 }2636 2637 2027 #endif // QT_NO_DRAGANDDROP 2638 2028 … … 2677 2067 QMenu *popup = new QMenu(this); 2678 2068 popup->setObjectName(QLatin1String("qt_edit_menu")); 2679 2680 QAction *action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo)); 2681 action->setEnabled(d->isUndoAvailable()); 2682 connect(action, SIGNAL(triggered()), SLOT(undo())); 2683 2684 action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo)); 2685 action->setEnabled(d->isRedoAvailable()); 2686 connect(action, SIGNAL(triggered()), SLOT(redo())); 2687 2688 popup->addSeparator(); 2069 QAction *action = 0; 2070 2071 if (!isReadOnly()) { 2072 action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo)); 2073 action->setEnabled(d->control->isUndoAvailable()); 2074 connect(action, SIGNAL(triggered()), SLOT(undo())); 2075 2076 action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo)); 2077 action->setEnabled(d->control->isRedoAvailable()); 2078 connect(action, SIGNAL(triggered()), SLOT(redo())); 2079 2080 popup->addSeparator(); 2081 } 2689 2082 2690 2083 #ifndef QT_NO_CLIPBOARD 2691 action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut)); 2692 action->setEnabled(!d->readOnly && d->hasSelectedText()); 2693 connect(action, SIGNAL(triggered()), SLOT(cut())); 2084 if (!isReadOnly()) { 2085 action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut)); 2086 action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText() 2087 && d->control->echoMode() == QLineEdit::Normal); 2088 connect(action, SIGNAL(triggered()), SLOT(cut())); 2089 } 2694 2090 2695 2091 action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy)); 2696 action->setEnabled(d->hasSelectedText()); 2092 action->setEnabled(d->control->hasSelectedText() 2093 && d->control->echoMode() == QLineEdit::Normal); 2697 2094 connect(action, SIGNAL(triggered()), SLOT(copy())); 2698 2095 2699 action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste)); 2700 action->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty()); 2701 connect(action, SIGNAL(triggered()), SLOT(paste())); 2702 #endif 2703 2704 action = popup->addAction(QLineEdit::tr("Delete")); 2705 action->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText()); 2706 connect(action, SIGNAL(triggered()), SLOT(_q_deleteSelected())); 2707 2708 popup->addSeparator(); 2096 if (!isReadOnly()) { 2097 action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste)); 2098 action->setEnabled(!d->control->isReadOnly() && !QApplication::clipboard()->text().isEmpty()); 2099 connect(action, SIGNAL(triggered()), SLOT(paste())); 2100 } 2101 #endif 2102 2103 if (!isReadOnly()) { 2104 action = popup->addAction(QLineEdit::tr("Delete")); 2105 action->setEnabled(!d->control->isReadOnly() && !d->control->text().isEmpty() && d->control->hasSelectedText()); 2106 connect(action, SIGNAL(triggered()), d->control, SLOT(_q_deleteSelected())); 2107 } 2108 2109 if (!popup->isEmpty()) 2110 popup->addSeparator(); 2709 2111 2710 2112 action = popup->addAction(QLineEdit::tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll)); 2711 action->setEnabled(!d-> text.isEmpty() && !d->allSelected());2113 action->setEnabled(!d->control->text().isEmpty() && !d->control->allSelected()); 2712 2114 d->selectAllAction = action; 2713 2115 connect(action, SIGNAL(triggered()), SLOT(selectAll())); … … 2723 2125 2724 2126 #if defined(Q_WS_WIN) 2725 if (!d-> readOnly&& qt_use_rtl_extensions) {2127 if (!d->control->isReadOnly() && qt_use_rtl_extensions) { 2726 2128 #else 2727 if (!d-> readOnly) {2129 if (!d->control->isReadOnly()) { 2728 2130 #endif 2729 2131 popup->addSeparator(); … … 2739 2141 { 2740 2142 Q_D(QLineEdit); 2741 if(ev->type() == QEvent::ActivationChange) { 2143 switch(ev->type()) 2144 { 2145 case QEvent::ActivationChange: 2742 2146 if (!palette().isEqual(QPalette::Active, QPalette::Inactive)) 2743 2147 update(); 2744 } else if (ev->type() == QEvent::FontChange 2745 || ev->type() == QEvent::StyleChange 2746 || ev->type() == QEvent::LayoutDirectionChange) { 2747 d->updateTextLayout(); 2748 } 2749 QWidget::changeEvent(ev); 2750 } 2751 2752 void QLineEditPrivate::_q_clipboardChanged() 2753 { 2754 } 2755 2756 void QLineEditPrivate::_q_handleWindowActivate() 2757 { 2758 Q_Q(QLineEdit); 2759 if (!q->hasFocus() && q->hasSelectedText()) 2760 q->deselect(); 2761 } 2762 2763 void QLineEditPrivate::_q_deleteSelected() 2764 { 2765 Q_Q(QLineEdit); 2766 if (!hasSelectedText()) 2767 return; 2768 2769 int priorState = undoState; 2770 q->resetInputContext(); 2771 removeSelectedText(); 2772 separate(); 2773 finishChange(priorState); 2774 } 2775 2776 void QLineEditPrivate::init(const QString& txt) 2777 { 2778 Q_Q(QLineEdit); 2779 #ifndef QT_NO_CURSOR 2780 q->setCursor(Qt::IBeamCursor); 2781 #endif 2782 q->setFocusPolicy(Qt::StrongFocus); 2783 q->setAttribute(Qt::WA_InputMethodEnabled); 2784 // Specifies that this widget can use more, but is able to survive on 2785 // less, horizontal space; and is fixed vertically. 2786 q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit)); 2787 q->setBackgroundRole(QPalette::Base); 2788 q->setAttribute(Qt::WA_KeyCompression); 2789 q->setMouseTracking(true); 2790 q->setAcceptDrops(true); 2791 text = txt; 2792 updateTextLayout(); 2793 cursor = text.length(); 2794 2795 q->setAttribute(Qt::WA_MacShowFocusRect); 2796 } 2797 2798 void QLineEditPrivate::updatePasswordEchoEditing(bool editing) 2799 { 2800 Q_Q(QLineEdit); 2801 passwordEchoEditing = editing; 2802 q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q)); 2803 updateTextLayout(); 2804 q->update(); 2805 } 2806 2807 void QLineEditPrivate::updateTextLayout() 2808 { 2809 // replace certain non-printable characters with spaces (to avoid 2810 // drawing boxes when using fonts that don't have glyphs for such 2811 // characters) 2812 Q_Q(QLineEdit); 2813 QString str = q->displayText(); 2814 QChar* uc = str.data(); 2815 for (int i = 0; i < (int)str.length(); ++i) { 2816 if ((uc[i] < 0x20 && uc[i] != 0x09) 2817 || uc[i] == QChar::LineSeparator 2818 || uc[i] == QChar::ParagraphSeparator 2819 || uc[i] == QChar::ObjectReplacementCharacter) 2820 uc[i] = QChar(0x0020); 2821 } 2822 textLayout.setFont(q->font()); 2823 textLayout.setText(str); 2824 QTextOption option; 2825 option.setTextDirection(q->layoutDirection()); 2826 option.setFlags(QTextOption::IncludeTrailingSpaces); 2827 textLayout.setTextOption(option); 2828 2829 textLayout.beginLayout(); 2830 QTextLine l = textLayout.createLine(); 2831 textLayout.endLayout(); 2832 ascent = qRound(l.ascent()); 2833 } 2834 2835 int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const 2836 { 2837 QRect cr = adjustedContentsRect(); 2838 x-= cr.x() - hscroll + horizontalMargin; 2839 QTextLine l = textLayout.lineAt(0); 2840 return l.xToCursor(x, betweenOrOn); 2841 } 2842 2843 QRect QLineEditPrivate::cursorRect() const 2844 { 2845 Q_Q(const QLineEdit); 2846 QRect cr = adjustedContentsRect(); 2847 int cix = cr.x() - hscroll + horizontalMargin; 2848 QTextLine l = textLayout.lineAt(0); 2849 int c = cursor; 2850 if (preeditCursor != -1) 2851 c += preeditCursor; 2852 cix += qRound(l.cursorToX(c)); 2853 int ch = qMin(cr.height(), q->fontMetrics().height() + 1); 2854 int w = q->style()->pixelMetric(QStyle::PM_TextCursorWidth); 2855 return QRect(cix-5, vscroll, w + 9, ch); 2856 } 2857 2858 QRect QLineEditPrivate::adjustedContentsRect() const 2859 { 2860 Q_Q(const QLineEdit); 2861 QStyleOptionFrameV2 opt; 2862 q->initStyleOption(&opt); 2863 QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q); 2864 r.setX(r.x() + leftTextMargin); 2865 r.setY(r.y() + topTextMargin); 2866 r.setRight(r.right() - rightTextMargin); 2867 r.setBottom(r.bottom() - bottomTextMargin); 2868 return r; 2869 } 2870 2871 bool QLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable 2872 { 2873 #ifndef QT_NO_VALIDATOR 2874 if (validator) { 2875 QString textCopy = text; 2876 int cursorCopy = cursor; 2877 validator->fixup(textCopy); 2878 if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { 2879 if (textCopy != text || cursorCopy != cursor) 2880 setText(textCopy, cursorCopy); 2881 return true; 2148 break; 2149 case QEvent::FontChange: 2150 d->control->setFont(font()); 2151 break; 2152 case QEvent::StyleChange: 2153 { 2154 QStyleOptionFrameV2 opt; 2155 initStyleOption(&opt); 2156 d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this)); 2882 2157 } 2883 } 2884 #endif 2885 return false; 2886 } 2887 2888 void QLineEditPrivate::moveCursor(int pos, bool mark) 2889 { 2890 Q_Q(QLineEdit); 2891 if (pos != cursor) { 2892 separate(); 2893 if (maskData) 2894 pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); 2895 } 2896 bool fullUpdate = mark || hasSelectedText(); 2897 if (mark) { 2898 int anchor; 2899 if (selend > selstart && cursor == selstart) 2900 anchor = selend; 2901 else if (selend > selstart && cursor == selend) 2902 anchor = selstart; 2903 else 2904 anchor = cursor; 2905 selstart = qMin(anchor, pos); 2906 selend = qMax(anchor, pos); 2907 updateTextLayout(); 2908 } else { 2909 deselect(); 2910 } 2911 if (fullUpdate) { 2912 cursor = pos; 2913 q->update(); 2914 } else { 2915 setCursorVisible(false); 2916 cursor = pos; 2917 setCursorVisible(true); 2918 if (!adjustedContentsRect().contains(cursorRect())) 2919 q->update(); 2920 } 2921 QStyleOptionFrameV2 opt; 2922 q->initStyleOption(&opt); 2923 if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q)) 2924 setCursorVisible(false); 2925 if (mark || selDirty) { 2926 selDirty = false; 2927 emit q->selectionChanged(); 2928 } 2929 emitCursorPositionChanged(); 2930 } 2931 2932 void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited) 2933 { 2934 Q_Q(QLineEdit); 2935 bool lineDirty = selDirty; 2936 if (textDirty) { 2937 // do validation 2938 bool wasValidInput = validInput; 2939 validInput = true; 2940 #ifndef QT_NO_VALIDATOR 2941 if (validator) { 2942 validInput = false; 2943 QString textCopy = text; 2944 int cursorCopy = cursor; 2945 validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid); 2946 if (validInput) { 2947 if (text != textCopy) { 2948 setText(textCopy, cursorCopy); 2949 return; 2950 } 2951 cursor = cursorCopy; 2952 } 2953 } 2954 #endif 2955 if (validateFromState >= 0 && wasValidInput && !validInput) { 2956 undo(validateFromState); 2957 history.resize(undoState); 2958 if (modifiedState > undoState) 2959 modifiedState = -1; 2960 validInput = true; 2961 textDirty = false; 2962 } 2963 updateTextLayout(); 2964 lineDirty |= textDirty; 2965 if (textDirty) { 2966 textDirty = false; 2967 QString actualText = maskData ? stripString(text) : text; 2968 if (edited) 2969 emit q->textEdited(actualText); 2970 q->updateMicroFocus(); 2971 #ifndef QT_NO_COMPLETER 2972 if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion) 2973 complete(-1); // update the popup on cut/paste/del 2974 #endif 2975 emit q->textChanged(actualText); 2976 } 2977 #ifndef QT_NO_ACCESSIBILITY 2978 QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged); 2979 #endif 2980 } 2981 if (selDirty) { 2982 selDirty = false; 2983 emit q->selectionChanged(); 2984 } 2985 if (lineDirty || update) 2986 q->update(); 2987 emitCursorPositionChanged(); 2988 } 2989 2990 void QLineEditPrivate::emitCursorPositionChanged() 2991 { 2992 Q_Q(QLineEdit); 2993 if (cursor != lastCursorPos) { 2994 const int oldLast = lastCursorPos; 2995 lastCursorPos = cursor; 2996 emit q->cursorPositionChanged(oldLast, cursor); 2997 } 2998 } 2999 3000 void QLineEditPrivate::setText(const QString& txt, int pos, bool edited) 3001 { 3002 Q_Q(QLineEdit); 3003 q->resetInputContext(); 3004 deselect(); 3005 QString oldText = text; 3006 if (maskData) { 3007 text = maskString(0, txt, true); 3008 text += clearString(text.length(), maxLength - text.length()); 3009 } else { 3010 text = txt.isEmpty() ? txt : txt.left(maxLength); 3011 } 3012 history.clear(); 3013 modifiedState = undoState = 0; 3014 cursor = (pos < 0 || pos > text.length()) ? text.length() : pos; 3015 textDirty = (oldText != text); 3016 finishChange(-1, true, edited); 3017 } 3018 3019 3020 void QLineEditPrivate::setCursorVisible(bool visible) 3021 { 3022 Q_Q(QLineEdit); 3023 if ((bool)cursorVisible == visible) 3024 return; 3025 if (cursorTimer) 3026 cursorVisible = visible; 3027 QRect r = cursorRect(); 3028 if (maskData) 3029 q->update(); 3030 else 3031 q->update(r); 3032 } 3033 3034 void QLineEditPrivate::addCommand(const Command& cmd) 3035 { 3036 if (separator && undoState && history[undoState-1].type != Separator) { 3037 history.resize(undoState + 2); 3038 history[undoState++] = Command(Separator, cursor, 0, selstart, selend); 3039 } else { 3040 history.resize(undoState + 1); 3041 } 3042 separator = false; 3043 history[undoState++] = cmd; 3044 } 3045 3046 void QLineEditPrivate::insert(const QString& s) 3047 { 3048 if (hasSelectedText()) 3049 addCommand(Command(SetSelection, cursor, 0, selstart, selend)); 3050 if (maskData) { 3051 QString ms = maskString(cursor, s); 3052 for (int i = 0; i < (int) ms.length(); ++i) { 3053 addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i), -1, -1)); 3054 addCommand(Command(Insert, cursor+i, ms.at(i), -1, -1)); 3055 } 3056 text.replace(cursor, ms.length(), ms); 3057 cursor += ms.length(); 3058 cursor = nextMaskBlank(cursor); 3059 textDirty = true; 3060 } else { 3061 int remaining = maxLength - text.length(); 3062 if (remaining != 0) { 3063 text.insert(cursor, s.left(remaining)); 3064 for (int i = 0; i < (int) s.left(remaining).length(); ++i) 3065 addCommand(Command(Insert, cursor++, s.at(i), -1, -1)); 3066 textDirty = true; 3067 } 3068 } 3069 } 3070 3071 void QLineEditPrivate::del(bool wasBackspace) 3072 { 3073 if (cursor < (int) text.length()) { 3074 if (hasSelectedText()) 3075 addCommand(Command(SetSelection, cursor, 0, selstart, selend)); 3076 addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor), -1, -1)); 3077 if (maskData) { 3078 text.replace(cursor, 1, clearString(cursor, 1)); 3079 addCommand(Command(Insert, cursor, text.at(cursor), -1, -1)); 3080 } else { 3081 text.remove(cursor, 1); 3082 } 3083 textDirty = true; 3084 } 3085 } 3086 3087 void QLineEditPrivate::removeSelectedText() 3088 { 3089 if (selstart < selend && selend <= (int) text.length()) { 3090 separate(); 3091 int i ; 3092 addCommand(Command(SetSelection, cursor, 0, selstart, selend)); 3093 if (selstart <= cursor && cursor < selend) { 3094 // cursor is within the selection. Split up the commands 3095 // to be able to restore the correct cursor position 3096 for (i = cursor; i >= selstart; --i) 3097 addCommand (Command(DeleteSelection, i, text.at(i), -1, 1)); 3098 for (i = selend - 1; i > cursor; --i) 3099 addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i), -1, -1)); 3100 } else { 3101 for (i = selend-1; i >= selstart; --i) 3102 addCommand (Command(RemoveSelection, i, text.at(i), -1, -1)); 3103 } 3104 if (maskData) { 3105 text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); 3106 for (int i = 0; i < selend - selstart; ++i) 3107 addCommand(Command(Insert, selstart + i, text.at(selstart + i), -1, -1)); 3108 } else { 3109 text.remove(selstart, selend - selstart); 3110 } 3111 if (cursor > selstart) 3112 cursor -= qMin(cursor, selend) - selstart; 3113 deselect(); 3114 textDirty = true; 3115 3116 // adjust hscroll to avoid gap 3117 const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing()); 3118 updateTextLayout(); 3119 const QTextLine line = textLayout.lineAt(0); 3120 const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB; 3121 hscroll = qMin(hscroll, widthUsed); 3122 } 3123 } 3124 3125 void QLineEditPrivate::parseInputMask(const QString &maskFields) 3126 { 3127 int delimiter = maskFields.indexOf(QLatin1Char(';')); 3128 if (maskFields.isEmpty() || delimiter == 0) { 3129 if (maskData) { 3130 delete [] maskData; 3131 maskData = 0; 3132 maxLength = 32767; 3133 setText(QString()); 3134 } 3135 return; 3136 } 3137 3138 if (delimiter == -1) { 3139 blank = QLatin1Char(' '); 3140 inputMask = maskFields; 3141 } else { 3142 inputMask = maskFields.left(delimiter); 3143 blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); 3144 } 3145 3146 // calculate maxLength / maskData length 3147 maxLength = 0; 3148 QChar c = 0; 3149 for (int i=0; i<inputMask.length(); i++) { 3150 c = inputMask.at(i); 3151 if (i > 0 && inputMask.at(i-1) == QLatin1Char('\\')) { 3152 maxLength++; 3153 continue; 3154 } 3155 if (c != QLatin1Char('\\') && c != QLatin1Char('!') && 3156 c != QLatin1Char('<') && c != QLatin1Char('>') && 3157 c != QLatin1Char('{') && c != QLatin1Char('}') && 3158 c != QLatin1Char('[') && c != QLatin1Char(']')) 3159 maxLength++; 3160 } 3161 3162 delete [] maskData; 3163 maskData = new MaskInputData[maxLength]; 3164 3165 MaskInputData::Casemode m = MaskInputData::NoCaseMode; 3166 c = 0; 3167 bool s; 3168 bool escape = false; 3169 int index = 0; 3170 for (int i = 0; i < inputMask.length(); i++) { 3171 c = inputMask.at(i); 3172 if (escape) { 3173 s = true; 3174 maskData[index].maskChar = c; 3175 maskData[index].separator = s; 3176 maskData[index].caseMode = m; 3177 index++; 3178 escape = false; 3179 } else if (c == QLatin1Char('<')) { 3180 m = MaskInputData::Lower; 3181 } else if (c == QLatin1Char('>')) { 3182 m = MaskInputData::Upper; 3183 } else if (c == QLatin1Char('!')) { 3184 m = MaskInputData::NoCaseMode; 3185 } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) { 3186 switch (c.unicode()) { 3187 case 'A': 3188 case 'a': 3189 case 'N': 3190 case 'n': 3191 case 'X': 3192 case 'x': 3193 case '9': 3194 case '0': 3195 case 'D': 3196 case 'd': 3197 case '#': 3198 case 'H': 3199 case 'h': 3200 case 'B': 3201 case 'b': 3202 s = false; 3203 break; 3204 case '\\': 3205 escape = true; 3206 default: 3207 s = true; 3208 break; 3209 } 3210 3211 if (!escape) { 3212 maskData[index].maskChar = c; 3213 maskData[index].separator = s; 3214 maskData[index].caseMode = m; 3215 index++; 3216 } 3217 } 3218 } 3219 setText(text); 3220 } 3221 3222 3223 /* checks if the key is valid compared to the inputMask */ 3224 bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const 3225 { 3226 switch (mask.unicode()) { 3227 case 'A': 3228 if (key.isLetter()) 3229 return true; 2158 update(); 3230 2159 break; 3231 case 'a': 3232 if (key.isLetter() || key == blank) 3233 return true; 3234 break; 3235 case 'N': 3236 if (key.isLetterOrNumber()) 3237 return true; 3238 break; 3239 case 'n': 3240 if (key.isLetterOrNumber() || key == blank) 3241 return true; 3242 break; 3243 case 'X': 3244 if (key.isPrint()) 3245 return true; 3246 break; 3247 case 'x': 3248 if (key.isPrint() || key == blank) 3249 return true; 3250 break; 3251 case '9': 3252 if (key.isNumber()) 3253 return true; 3254 break; 3255 case '0': 3256 if (key.isNumber() || key == blank) 3257 return true; 3258 break; 3259 case 'D': 3260 if (key.isNumber() && key.digitValue() > 0) 3261 return true; 3262 break; 3263 case 'd': 3264 if ((key.isNumber() && key.digitValue() > 0) || key == blank) 3265 return true; 3266 break; 3267 case '#': 3268 if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) 3269 return true; 3270 break; 3271 case 'B': 3272 if (key == QLatin1Char('0') || key == QLatin1Char('1')) 3273 return true; 3274 break; 3275 case 'b': 3276 if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) 3277 return true; 3278 break; 3279 case 'H': 3280 if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F'))) 3281 return true; 3282 break; 3283 case 'h': 3284 if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) 3285 return true; 2160 case QEvent::LayoutDirectionChange: 2161 d->control->setLayoutDirection(layoutDirection()); 3286 2162 break; 3287 2163 default: 3288 2164 break; 3289 2165 } 3290 return false; 3291 } 3292 3293 bool QLineEditPrivate::hasAcceptableInput(const QString &str) const 3294 { 3295 #ifndef QT_NO_VALIDATOR 3296 QString textCopy = str; 3297 int cursorCopy = cursor; 3298 if (validator && validator->validate(textCopy, cursorCopy) 3299 != QValidator::Acceptable) 3300 return false; 3301 #endif 3302 3303 if (!maskData) 3304 return true; 3305 3306 if (str.length() != maxLength) 3307 return false; 3308 3309 for (int i=0; i < maxLength; ++i) { 3310 if (maskData[i].separator) { 3311 if (str.at(i) != maskData[i].maskChar) 3312 return false; 3313 } else { 3314 if (!isValidInput(str.at(i), maskData[i].maskChar)) 3315 return false; 3316 } 3317 } 3318 return true; 3319 } 3320 3321 /* 3322 Applies the inputMask on \a str starting from position \a pos in the mask. \a clear 3323 specifies from where characters should be gotten when a separator is met in \a str - true means 3324 that blanks will be used, false that previous input is used. 3325 Calling this when no inputMask is set is undefined. 3326 */ 3327 QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const 3328 { 3329 if (pos >= (uint)maxLength) 3330 return QString::fromLatin1(""); 3331 3332 QString fill; 3333 fill = clear ? clearString(0, maxLength) : text; 3334 3335 int strIndex = 0; 3336 QString s = QString::fromLatin1(""); 3337 int i = pos; 3338 while (i < maxLength) { 3339 if (strIndex < str.length()) { 3340 if (maskData[i].separator) { 3341 s += maskData[i].maskChar; 3342 if (str[(int)strIndex] == maskData[i].maskChar) 3343 strIndex++; 3344 ++i; 3345 } else { 3346 if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { 3347 switch (maskData[i].caseMode) { 3348 case MaskInputData::Upper: 3349 s += str[(int)strIndex].toUpper(); 3350 break; 3351 case MaskInputData::Lower: 3352 s += str[(int)strIndex].toLower(); 3353 break; 3354 default: 3355 s += str[(int)strIndex]; 3356 } 3357 ++i; 3358 } else { 3359 // search for separator first 3360 int n = findInMask(i, true, true, str[(int)strIndex]); 3361 if (n != -1) { 3362 if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { 3363 s += fill.mid(i, n-i+1); 3364 i = n + 1; // update i to find + 1 3365 } 3366 } else { 3367 // search for valid blank if not 3368 n = findInMask(i, true, false, str[(int)strIndex]); 3369 if (n != -1) { 3370 s += fill.mid(i, n-i); 3371 switch (maskData[n].caseMode) { 3372 case MaskInputData::Upper: 3373 s += str[(int)strIndex].toUpper(); 3374 break; 3375 case MaskInputData::Lower: 3376 s += str[(int)strIndex].toLower(); 3377 break; 3378 default: 3379 s += str[(int)strIndex]; 3380 } 3381 i = n + 1; // updates i to find + 1 3382 } 3383 } 3384 } 3385 strIndex++; 3386 } 3387 } else 3388 break; 3389 } 3390 3391 return s; 3392 } 3393 3394 3395 3396 /* 3397 Returns a "cleared" string with only separators and blank chars. 3398 Calling this when no inputMask is set is undefined. 3399 */ 3400 QString QLineEditPrivate::clearString(uint pos, uint len) const 3401 { 3402 if (pos >= (uint)maxLength) 3403 return QString(); 3404 3405 QString s; 3406 int end = qMin((uint)maxLength, pos + len); 3407 for (int i=pos; i<end; i++) 3408 if (maskData[i].separator) 3409 s += maskData[i].maskChar; 3410 else 3411 s += blank; 3412 3413 return s; 3414 } 3415 3416 /* 3417 Strips blank parts of the input in a QLineEdit when an inputMask is set, 3418 separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". 3419 */ 3420 QString QLineEditPrivate::stripString(const QString &str) const 3421 { 3422 if (!maskData) 3423 return str; 3424 3425 QString s; 3426 int end = qMin(maxLength, (int)str.length()); 3427 for (int i=0; i < end; i++) 3428 if (maskData[i].separator) 3429 s += maskData[i].maskChar; 3430 else 3431 if (str[i] != blank) 3432 s += str[i]; 3433 3434 return s; 3435 } 3436 3437 /* searches forward/backward in maskData for either a separator or a blank */ 3438 int QLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const 3439 { 3440 if (pos >= maxLength || pos < 0) 3441 return -1; 3442 3443 int end = forward ? maxLength : -1; 3444 int step = forward ? 1 : -1; 3445 int i = pos; 3446 3447 while (i != end) { 3448 if (findSeparator) { 3449 if (maskData[i].separator && maskData[i].maskChar == searchChar) 3450 return i; 3451 } else { 3452 if (!maskData[i].separator) { 3453 if (searchChar.isNull()) 3454 return i; 3455 else if (isValidInput(searchChar, maskData[i].maskChar)) 3456 return i; 3457 } 3458 } 3459 i += step; 3460 } 3461 return -1; 3462 } 3463 3464 void QLineEditPrivate::undo(int until) 3465 { 3466 if (!isUndoAvailable()) 3467 return; 3468 deselect(); 3469 while (undoState && undoState > until) { 3470 Command& cmd = history[--undoState]; 3471 switch (cmd.type) { 3472 case Insert: 3473 text.remove(cmd.pos, 1); 3474 cursor = cmd.pos; 3475 break; 3476 case SetSelection: 3477 selstart = cmd.selStart; 3478 selend = cmd.selEnd; 3479 cursor = cmd.pos; 3480 break; 3481 case Remove: 3482 case RemoveSelection: 3483 text.insert(cmd.pos, cmd.uc); 3484 cursor = cmd.pos + 1; 3485 break; 3486 case Delete: 3487 case DeleteSelection: 3488 text.insert(cmd.pos, cmd.uc); 3489 cursor = cmd.pos; 3490 break; 3491 case Separator: 3492 continue; 3493 } 3494 if (until < 0 && undoState) { 3495 Command& next = history[undoState-1]; 3496 if (next.type != cmd.type && next.type < RemoveSelection 3497 && (cmd.type < RemoveSelection || next.type == Separator)) 3498 break; 3499 } 3500 } 3501 textDirty = true; 3502 emitCursorPositionChanged(); 3503 } 3504 3505 void QLineEditPrivate::redo() { 3506 if (!isRedoAvailable()) 3507 return; 3508 deselect(); 3509 while (undoState < (int)history.size()) { 3510 Command& cmd = history[undoState++]; 3511 switch (cmd.type) { 3512 case Insert: 3513 text.insert(cmd.pos, cmd.uc); 3514 cursor = cmd.pos + 1; 3515 break; 3516 case SetSelection: 3517 selstart = cmd.selStart; 3518 selend = cmd.selEnd; 3519 cursor = cmd.pos; 3520 break; 3521 case Remove: 3522 case Delete: 3523 case RemoveSelection: 3524 case DeleteSelection: 3525 text.remove(cmd.pos, 1); 3526 cursor = cmd.pos; 3527 break; 3528 case Separator: 3529 selstart = cmd.selStart; 3530 selend = cmd.selEnd; 3531 cursor = cmd.pos; 3532 break; 3533 } 3534 if (undoState < (int)history.size()) { 3535 Command& next = history[undoState]; 3536 if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator 3537 && (next.type < RemoveSelection || cmd.type == Separator)) 3538 break; 3539 } 3540 } 3541 textDirty = true; 3542 emitCursorPositionChanged(); 2166 QWidget::changeEvent(ev); 3543 2167 } 3544 2168 … … 3674 2298 /*! 3675 2299 \fn int QLineEdit::margin() const 3676 Returns the wi th of thethe margin around the contents of the widget.2300 Returns the width of the margin around the contents of the widget. 3677 2301 3678 2302 Use QWidget::getContentsMargins() instead.
Note:
See TracChangeset
for help on using the changeset viewer.