From 22ff3df15cc3143e6410b02f39b967d1d76cf2d6 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 17:37:43 +1000 Subject: Manual cherrypick of QLineControl from kinetic-declarativeui-qfxlineedit Splits out the control logic of QLineEdit into QLineControl, which is somewhat similar to QTextEdit. This was originally worked on in the ianws-qt-lineedit-textedit-research repository, and then further developed in kinetic in the kinetic-declarativeui-qfxlineedit branch. Note that this also includes a tiny change to qvalidator.h which allows validators to be used in qml. --- src/gui/widgets/qlinecontrol.cpp | 1707 ++++++++++++++++++++++++++++++++ src/gui/widgets/qlinecontrol_p.h | 715 ++++++++++++++ src/gui/widgets/qlinecontrol_p_p.h | 105 ++ src/gui/widgets/qlineedit.cpp | 1885 ++++-------------------------------- src/gui/widgets/qlineedit.h | 2 + src/gui/widgets/qlineedit_p.cpp | 253 +++++ src/gui/widgets/qlineedit_p.h | 174 +--- src/gui/widgets/qvalidator.h | 6 +- src/gui/widgets/widgets.pri | 3 + 9 files changed, 3010 insertions(+), 1840 deletions(-) create mode 100644 src/gui/widgets/qlinecontrol.cpp create mode 100644 src/gui/widgets/qlinecontrol_p.h create mode 100644 src/gui/widgets/qlinecontrol_p_p.h create mode 100644 src/gui/widgets/qlineedit_p.cpp diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp new file mode 100644 index 0000000..b762a00 --- /dev/null +++ b/src/gui/widgets/qlinecontrol.cpp @@ -0,0 +1,1707 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlinecontrol_p.h" + +#ifndef QT_NO_LINEEDIT + +#include "qabstractitemview.h" +#include "qclipboard.h" +#ifndef QT_NO_ACCESSIBILITY +#include "qaccessible.h" +#endif +#ifndef QT_NO_IM +#include "qinputcontext.h" +#include "qlist.h" +#endif +#include "qapplication.h" +#ifndef QT_NO_GRAPHICSVIEW +#include "qgraphicssceneevent.h" +#endif + +QT_BEGIN_NAMESPACE + +/* + Updates the display text based of the current edit text + If the text has changed will emit displayTextChanged() +*/ +void QLineControl::updateDisplayText() +{ + QString orig = textLayout.text(); + QString str; + if (m_echoMode == QLineEdit::NoEcho) + str = QString::fromLatin1(""); + else + str = m_text; + + if (m_echoMode == QLineEdit::Password || (m_echoMode == QLineEdit::PasswordEchoOnEdit + && !m_passwordEchoEditing)) + str.fill(m_passwordCharacter); + + // replace certain non-printable characters with spaces (to avoid + // drawing boxes when using fonts that don't have glyphs for such + // characters) + QChar* uc = str.data(); + for (int i = 0; i < (int)str.length(); ++i) { + if ((uc[i] < 0x20 && uc[i] != 0x09) + || uc[i] == QChar::LineSeparator + || uc[i] == QChar::ParagraphSeparator + || uc[i] == QChar::ObjectReplacementCharacter) + uc[i] = QChar(0x0020); + } + + textLayout.setText(str); + + QTextOption option; + option.setTextDirection(m_layoutDirection); + option.setFlags(QTextOption::IncludeTrailingSpaces); + textLayout.setTextOption(option); + + textLayout.beginLayout(); + QTextLine l = textLayout.createLine(); + textLayout.endLayout(); + m_ascent = qRound(l.ascent()); + + if (str != orig) + emit displayTextChanged(str); +} + +#ifndef QT_NO_CLIPBOARD +/* + Copies the currently selected text into the clipboard using the given + \a mode. + + \note If the echo mode is set to a mode other than Normal then copy + will not work. This is to prevent using copy as a method of bypassing + password features of the line control. +*/ +void QLineControl::copy(QClipboard::Mode mode) const +{ + QString t = selectedText(); + if (!t.isEmpty() && m_echoMode == QLineEdit::Normal) { + disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0); + QApplication::clipboard()->setText(t, mode); + connect(QApplication::clipboard(), SIGNAL(selectionChanged()), + this, SLOT(_q_clipboardChanged())); + } +} + +/* + Inserts the text stored in the application clipboard into the line + control. + + \sa insert() +*/ +void QLineControl::paste() +{ + insert(QApplication::clipboard()->text(QClipboard::Clipboard)); +} + +#endif // !QT_NO_CLIPBOARD + +/* + Handles the behavior for the backspace key or function. + Removes the current selection if there is a selection, otherwise + removes the character prior to the cursor position. + + \sa del() +*/ +void QLineControl::backspace() +{ + int priorState = undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else if (m_cursor) { + --m_cursor; + if (maskData) + m_cursor = prevMaskBlank(m_cursor); + QChar uc = m_text.at(m_cursor); + if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { + // second half of a surrogate, check if we have the first half as well, + // if yes delete both at once + uc = m_text.at(m_cursor - 1); + if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { + p_del(true); + --m_cursor; + } + } + p_del(true); + } + finishChange(priorState); +} + +/* + Handles the behavior for the delete key or function. + Removes the current selection if there is a selection, otherwise + removes the character after the cursor position. + + \sa del() +*/ +void QLineControl::del() +{ + int priorState = undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else { + int n = textLayout.nextCursorPosition(m_cursor) - m_cursor; + while (n--) + p_del(); + } + finishChange(priorState); +} + +/* + Inserts the given \a newText at the current cursor position. + If there is any selected text it is removed prior to insertion of + the new text. +*/ +void QLineControl::insert(const QString &newText) +{ + int priorState = undoState; + removeSelectedText(); + p_insert(newText); + finishChange(priorState); +} + +/* + Clears the line control text. +*/ +void QLineControl::clear() +{ + int priorState = undoState; + selstart = 0; + selend = m_text.length(); + removeSelectedText(); + separate(); + finishChange(priorState, /*update*/false, /*edited*/false); +} + +/* + Sets \a length characters from the given \a start position as selected. + The given \a start position must be within the current text for + the line control. If \a length characters cannot be selected, then + the selection will extend to the end of the current text. +*/ +void QLineControl::setSelection(int start, int length) +{ + Q_ASSERT_X(start >= 0 && start <= (int)m_text.length(), + "QLineControl::setSelection", "Invalid start position"); + + if (length > 0) { + selstart = start; + selend = qMin(start + length, (int)m_text.length()); + m_cursor = selend; + } else { + selstart = qMax(start + length, 0); + selend = start; + m_cursor = selstart; + } +} + +void QLineControl::_q_clipboardChanged() +{ +} + +void QLineControl::_q_deleteSelected() +{ + if (!hasSelectedText()) + return; + + int priorState = undoState; + emit resetInputContext(); + removeSelectedText(); + separate(); + finishChange(priorState); +} + +/* + Initializes the line control with a starting text value of \a txt. +*/ +void QLineControl::init(const QString& txt) +{ + m_text = txt; + updateDisplayText(); + m_cursor = m_text.length(); +} + +/* + Sets the password echo editing to \a editing. If password echo editing + is true, then the text of the password is displayed even if the echo + mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing + does not affect other echo modes. +*/ +void QLineControl::updatePasswordEchoEditing(bool editing) +{ + m_passwordEchoEditing = editing; + updateDisplayText(); +} + +/* + Returns the cursor position of the given \a x pixel value in relation + to the displayed text. The given \a betweenOrOn specified what kind + of cursor position is requested. +*/ +int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const +{ + return textLayout.lineAt(0).xToCursor(x, betweenOrOn); +} + +/* + Returns the bounds of the current cursor, as defined as a + between characters cursor. +*/ +QRect QLineControl::cursorRect() const +{ + QTextLine l = textLayout.lineAt(0); + int c = m_cursor; + if (m_preeditCursor != -1) + c += m_preeditCursor; + int cix = qRound(l.cursorToX(c)); + int w = m_cursorWidth; + int ch = l.height() + 1; + + return QRect(cix-5, 0, w+9, ch); +} + +/* + Fixes the current text so that it is valid given any set validators. + + Returns true if the text was changed. Otherwise returns false. +*/ +bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable +{ +#ifndef QT_NO_VALIDATOR + if (m_validator) { + QString textCopy = m_text; + int cursorCopy = m_cursor; + m_validator->fixup(textCopy); + if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { + if (textCopy != m_text || cursorCopy != m_cursor) + p_setText(textCopy, cursorCopy); + return true; + } + } +#endif + return false; +} + +/* + Moves the cursor to the given position \a pos. If \a mark is true will + adjust the currently selected text. +*/ +void QLineControl::moveCursor(int pos, bool mark) +{ + if (pos != m_cursor) { + separate(); + if (maskData) + pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); + } + if (mark) { + int anchor; + if (selend > selstart && m_cursor == selstart) + anchor = selend; + else if (selend > selstart && m_cursor == selend) + anchor = selstart; + else + anchor = m_cursor; + selstart = qMin(anchor, pos); + selend = qMax(anchor, pos); + updateDisplayText(); + } else { + p_deselect(); + } + m_cursor = pos; + if (mark || selDirty) { + selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); +} + +/* + Applies the given input method event \a event to the text of the line + control +*/ +void QLineControl::processInputMethodEvent(QInputMethodEvent *event) +{ + int priorState = undoState; + removeSelectedText(); + + int c = m_cursor; // cursor position after insertion of commit string + if (event->replacementStart() <= 0) + c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); + + m_cursor += event->replacementStart(); + + // insert commit string + if (event->replacementLength()) { + selstart = m_cursor; + selend = selstart + event->replacementLength(); + removeSelectedText(); + } + if (!event->commitString().isEmpty()) + insert(event->commitString()); + + m_cursor = qMin(c, m_text.length()); + + setPreeditArea(m_cursor, event->preeditString()); + m_preeditCursor = event->preeditString().length(); + hideCursor = false; + QList formats; + for (int i = 0; i < event->attributes().size(); ++i) { + const QInputMethodEvent::Attribute &a = event->attributes().at(i); + if (a.type == QInputMethodEvent::Cursor) { + m_preeditCursor = a.start; + hideCursor = !a.length; + } else if (a.type == QInputMethodEvent::TextFormat) { + QTextCharFormat f = qvariant_cast(a.value).toCharFormat(); + if (f.isValid()) { + QTextLayout::FormatRange o; + o.start = a.start + m_cursor; + o.length = a.length; + o.format = f; + formats.append(o); + } + } + } + textLayout.setAdditionalFormats(formats); + updateDisplayText(); + if (!event->commitString().isEmpty()) + emitCursorPositionChanged(); + finishChange(priorState); +} + +/* + Draws the display text for the line control using the given + \a painter, \a clip, and \a offset. Which aspects of the display text + are drawn is specified by the given \a flags. + + If the flags contain DrawSelections, then the selection or input mask + backgrounds and foregrounds will be applied before drawing the text. + + If the flags contain DrawCursor a cursor of the current cursorWidth() + will be drawn after drawing the text. + + The display text will only be drawn if the flags contain DrawText +*/ +void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags) +{ + QVector selections; + if (flags & DrawSelections) { + QTextLayout::FormatRange o; + if (selstart < selend) { + o.start = selstart; + o.length = selend - selstart; + o.format.setBackground(m_palette.brush(QPalette::Highlight)); + o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); + } else { + // mask selection + o.start = m_cursor; + o.length = 1; + o.format.setBackground(m_palette.brush(QPalette::Text)); + o.format.setForeground(m_palette.brush(QPalette::Window)); + } + selections.append(o); + } + + if (flags & DrawText) + textLayout.draw(painter, offset, selections, clip); + + if (flags & DrawCursor){ + if(!m_blinkPeriod || m_blinkStatus) + textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + } +} + +/* + Sets the selection to cover the word at the given cursor position. + The word boundries is defined by the behavior of QTextLayout::SkipWords + cursor mode. +*/ +void QLineControl::selectWordAtPos(int cursor) +{ + int c = textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + moveCursor(c, false); + // ## text layout should support end of words. + int end = textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + while (end > cursor && m_text[end-1].isSpace()) + --end; + moveCursor(end, true); +} + +/* + Completes a change to the line control text. If the change is not valid + will undo the line control state back to the given \a validateFromState. + + If \a edited is true and the change is valid, will emit textEdited() in + addition to textChanged(). Otherwise only emits textChanged() on a valid + change. + + The \a update value is currently unused. +*/ + +bool QLineControl::finishChange(int validateFromState, bool update, bool edited) +{ + Q_UNUSED(update) + bool lineDirty = selDirty; + if (textDirty) { + // do validation + bool wasValidInput = validInput; + validInput = true; +#ifndef QT_NO_VALIDATOR + if (m_validator) { + validInput = false; + QString textCopy = m_text; + int cursorCopy = m_cursor; + validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); + if (validInput) { + if (m_text != textCopy) { + p_setText(textCopy, cursorCopy); + return true; + } + m_cursor = cursorCopy; + } + } +#endif + if (validateFromState >= 0 && wasValidInput && !validInput) { + if (transactions.count()) + return false; + p_undo(validateFromState); + history.resize(undoState); + if (modifiedState > undoState) + modifiedState = -1; + validInput = true; + textDirty = false; + } + updateDisplayText(); + lineDirty |= textDirty; + if (textDirty) { + textDirty = false; + QString actualText = text(); + if (edited) + emit textEdited(actualText); + emit textChanged(actualText); + } + } + if (selDirty) { + selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); + return true; +} + +/* + An internal function for setting the text of the line control. +*/ +void QLineControl::p_setText(const QString& txt, int pos, bool edited) +{ + p_deselect(); + emit resetInputContext(); + QString oldText = m_text; + if (maskData) { + m_text = maskString(0, txt, true); + m_text += clearString(m_text.length(), m_maxLength - m_text.length()); + } else { + m_text = txt.isEmpty() ? txt : txt.left(m_maxLength); + } + history.clear(); + modifiedState = undoState = 0; + m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos; + textDirty = (oldText != m_text); + finishChange(-1, true, edited); +} + + +/* + Adds the given \a command to the undo history + of the line control. Does not apply the command. +*/ +void QLineControl::addCommand(const Command& cmd) +{ + if (separator && undoState && history[undoState-1].type != Separator) { + history.resize(undoState + 2); + history[undoState++] = Command(Separator, m_cursor, 0, selstart, selend); + } else { + history.resize(undoState + 1); + } + separator = false; + history[undoState++] = cmd; +} + +/* + Inserts the given string \a s into the line + control. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::p_insert(const QString& s) +{ + if (hasSelectedText()) + addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); + if (maskData) { + QString ms = maskString(m_cursor, s); + for (int i = 0; i < (int) ms.length(); ++i) { + addCommand (Command(DeleteSelection, m_cursor+i, m_text.at(m_cursor+i), -1, -1)); + addCommand(Command(Insert, m_cursor+i, ms.at(i), -1, -1)); + } + m_text.replace(m_cursor, ms.length(), ms); + m_cursor += ms.length(); + m_cursor = nextMaskBlank(m_cursor); + textDirty = true; + } else { + int remaining = m_maxLength - m_text.length(); + if (remaining != 0) { + m_text.insert(m_cursor, s.left(remaining)); + for (int i = 0; i < (int) s.left(remaining).length(); ++i) + addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1)); + textDirty = true; + } + } +} + +/* + \internal + deletes a single character from the current text. If \a wasBackspace, + the character prior to the cursor is removed. Otherwise the character + after the cursor is removed. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::p_del(bool wasBackspace) +{ + if (m_cursor < (int) m_text.length()) { + if (hasSelectedText()) + addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); + addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); + if (maskData) { + m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); + addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); + } else { + m_text.remove(m_cursor, 1); + } + textDirty = true; + } +} + +/* + \internal + removes the currently selected text from the line control. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::removeSelectedText() +{ + if (selstart < selend && selend <= (int) m_text.length()) { + separate(); + int i ; + addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); + if (selstart <= m_cursor && m_cursor < selend) { + // cursor is within the selection. Split up the commands + // to be able to restore the correct cursor position + for (i = m_cursor; i >= selstart; --i) + addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1)); + for (i = selend - 1; i > m_cursor; --i) + addCommand (Command(DeleteSelection, i - m_cursor + selstart - 1, m_text.at(i), -1, -1)); + } else { + for (i = selend-1; i >= selstart; --i) + addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1)); + } + if (maskData) { + m_text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); + for (int i = 0; i < selend - selstart; ++i) + addCommand(Command(Insert, selstart + i, m_text.at(selstart + i), -1, -1)); + } else { + m_text.remove(selstart, selend - selstart); + } + if (m_cursor > selstart) + m_cursor -= qMin(m_cursor, selend) - selstart; + p_deselect(); + textDirty = true; + } +} + +/* + Parses the input mask specified by \a maskFields to generate + the mask data used to handle input masks. +*/ +void QLineControl::parseInputMask(const QString &maskFields) +{ + int delimiter = maskFields.indexOf(QLatin1Char(';')); + if (maskFields.isEmpty() || delimiter == 0) { + if (maskData) { + delete [] maskData; + maskData = 0; + m_maxLength = 32767; + p_setText(QString()); + } + return; + } + + if (delimiter == -1) { + blank = QLatin1Char(' '); + m_inputMask = maskFields; + } else { + m_inputMask = maskFields.left(delimiter); + blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); + } + + // calculate m_maxLength / maskData length + m_maxLength = 0; + QChar c = 0; + for (int i=0; i 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) { + m_maxLength++; + continue; + } + if (c != QLatin1Char('\\') && c != QLatin1Char('!') && + c != QLatin1Char('<') && c != QLatin1Char('>') && + c != QLatin1Char('{') && c != QLatin1Char('}') && + c != QLatin1Char('[') && c != QLatin1Char(']')) + m_maxLength++; + } + + delete [] maskData; + maskData = new MaskInputData[m_maxLength]; + + MaskInputData::Casemode m = MaskInputData::NoCaseMode; + c = 0; + bool s; + bool escape = false; + int index = 0; + for (int i = 0; i < m_inputMask.length(); i++) { + c = m_inputMask.at(i); + if (escape) { + s = true; + maskData[index].maskChar = c; + maskData[index].separator = s; + maskData[index].caseMode = m; + index++; + escape = false; + } else if (c == QLatin1Char('<')) { + m = MaskInputData::Lower; + } else if (c == QLatin1Char('>')) { + m = MaskInputData::Upper; + } else if (c == QLatin1Char('!')) { + m = MaskInputData::NoCaseMode; + } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) { + switch (c.unicode()) { + case 'A': + case 'a': + case 'N': + case 'n': + case 'X': + case 'x': + case '9': + case '0': + case 'D': + case 'd': + case '#': + case 'H': + case 'h': + case 'B': + case 'b': + s = false; + break; + case '\\': + escape = true; + default: + s = true; + break; + } + + if (!escape) { + maskData[index].maskChar = c; + maskData[index].separator = s; + maskData[index].caseMode = m; + index++; + } + } + } + p_setText(m_text); +} + + +/* checks if the key is valid compared to the inputMask */ +bool QLineControl::isValidInput(QChar key, QChar mask) const +{ + switch (mask.unicode()) { + case 'A': + if (key.isLetter()) + return true; + break; + case 'a': + if (key.isLetter() || key == blank) + return true; + break; + case 'N': + if (key.isLetterOrNumber()) + return true; + break; + case 'n': + if (key.isLetterOrNumber() || key == blank) + return true; + break; + case 'X': + if (key.isPrint()) + return true; + break; + case 'x': + if (key.isPrint() || key == blank) + return true; + break; + case '9': + if (key.isNumber()) + return true; + break; + case '0': + if (key.isNumber() || key == blank) + return true; + break; + case 'D': + if (key.isNumber() && key.digitValue() > 0) + return true; + break; + case 'd': + if ((key.isNumber() && key.digitValue() > 0) || key == blank) + return true; + break; + case '#': + if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) + return true; + break; + case 'B': + if (key == QLatin1Char('0') || key == QLatin1Char('1')) + return true; + break; + case 'b': + if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) + return true; + break; + case 'H': + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F'))) + return true; + break; + case 'h': + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) + return true; + break; + default: + break; + } + return false; +} + +/* + Returns true if the given text \a str is valid for any + validator or input mask set for the line control. + + Otherwise returns false +*/ +bool QLineControl::hasAcceptableInput(const QString &str) const +{ +#ifndef QT_NO_VALIDATOR + QString textCopy = str; + int cursorCopy = m_cursor; + if (m_validator && m_validator->validate(textCopy, cursorCopy) + != QValidator::Acceptable) + return false; +#endif + + if (!maskData) + return true; + + if (str.length() != m_maxLength) + return false; + + for (int i=0; i < m_maxLength; ++i) { + if (maskData[i].separator) { + if (str.at(i) != maskData[i].maskChar) + return false; + } else { + if (!isValidInput(str.at(i), maskData[i].maskChar)) + return false; + } + } + return true; +} + +/* + Applies the inputMask on \a str starting from position \a pos in the mask. \a clear + specifies from where characters should be gotten when a separator is met in \a str - true means + that blanks will be used, false that previous input is used. + Calling this when no inputMask is set is undefined. +*/ +QString QLineControl::maskString(uint pos, const QString &str, bool clear) const +{ + if (pos >= (uint)m_maxLength) + return QString::fromLatin1(""); + + QString fill; + fill = clear ? clearString(0, m_maxLength) : m_text; + + int strIndex = 0; + QString s = QString::fromLatin1(""); + int i = pos; + while (i < m_maxLength) { + if (strIndex < str.length()) { + if (maskData[i].separator) { + s += maskData[i].maskChar; + if (str[(int)strIndex] == maskData[i].maskChar) + strIndex++; + ++i; + } else { + if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { + switch (maskData[i].caseMode) { + case MaskInputData::Upper: + s += str[(int)strIndex].toUpper(); + break; + case MaskInputData::Lower: + s += str[(int)strIndex].toLower(); + break; + default: + s += str[(int)strIndex]; + } + ++i; + } else { + // search for separator first + int n = findInMask(i, true, true, str[(int)strIndex]); + if (n != -1) { + if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { + s += fill.mid(i, n-i+1); + i = n + 1; // update i to find + 1 + } + } else { + // search for valid blank if not + n = findInMask(i, true, false, str[(int)strIndex]); + if (n != -1) { + s += fill.mid(i, n-i); + switch (maskData[n].caseMode) { + case MaskInputData::Upper: + s += str[(int)strIndex].toUpper(); + break; + case MaskInputData::Lower: + s += str[(int)strIndex].toLower(); + break; + default: + s += str[(int)strIndex]; + } + i = n + 1; // updates i to find + 1 + } + } + } + strIndex++; + } + } else + break; + } + + return s; +} + + + +/* + Returns a "cleared" string with only separators and blank chars. + Calling this when no inputMask is set is undefined. +*/ +QString QLineControl::clearString(uint pos, uint len) const +{ + if (pos >= (uint)m_maxLength) + return QString(); + + QString s; + int end = qMin((uint)m_maxLength, pos + len); + for (int i=pos; i= m_maxLength || pos < 0) + return -1; + + int end = forward ? m_maxLength : -1; + int step = forward ? 1 : -1; + int i = pos; + + while (i != end) { + if (findSeparator) { + if (maskData[i].separator && maskData[i].maskChar == searchChar) + return i; + } else { + if (!maskData[i].separator) { + if (searchChar.isNull()) + return i; + else if (isValidInput(searchChar, maskData[i].maskChar)) + return i; + } + } + i += step; + } + return -1; +} + +void QLineControl::p_undo(int until) +{ + if (!isUndoAvailable()) + return; + p_deselect(); + while (undoState && undoState > until) { + Command& cmd = history[--undoState]; + switch (cmd.type) { + case Insert: + m_text.remove(cmd.pos, 1); + m_cursor = cmd.pos; + break; + case SetSelection: + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case RemoveSelection: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos + 1; + break; + case Delete: + case DeleteSelection: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos; + break; + case Separator: + continue; + } + if (until < 0 && undoState) { + Command& next = history[undoState-1]; + if (next.type != cmd.type && next.type < RemoveSelection + && (cmd.type < RemoveSelection || next.type == Separator)) + break; + } + } + textDirty = true; + emitCursorPositionChanged(); +} + +void QLineControl::p_redo() { + if (!isRedoAvailable()) + return; + p_deselect(); + while (undoState < (int)history.size()) { + Command& cmd = history[undoState++]; + switch (cmd.type) { + case Insert: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos + 1; + break; + case SetSelection: + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case Delete: + case RemoveSelection: + case DeleteSelection: + m_text.remove(cmd.pos, 1); + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Separator: + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + } + if (undoState < (int)history.size()) { + Command& next = history[undoState]; + if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator + && (next.type < RemoveSelection || cmd.type == Separator)) + break; + } + } + textDirty = true; + emitCursorPositionChanged(); +} + +/* + If the current cursor position differs from the last emited cursor + position, emits cursorPositionChanged(). +*/ +void QLineControl::emitCursorPositionChanged() +{ + if (m_cursor != lastCursorPos) { + const int oldLast = lastCursorPos; + lastCursorPos = m_cursor; + cursorPositionChanged(oldLast, m_cursor); + } +} + +#ifndef QT_NO_COMPLETER +// iterating forward(dir=1)/backward(dir=-1) from the +// current row based. dir=0 indicates a new completion prefix was set. +bool QLineControl::advanceToEnabledItem(int dir) +{ + int start = m_completer->currentRow(); + if (start == -1) + return false; + int i = start + dir; + if (dir == 0) dir = 1; + do { + if (!m_completer->setCurrentRow(i)) { + if (!m_completer->wrapAround()) + break; + i = i > 0 ? 0 : m_completer->completionCount() - 1; + } else { + QModelIndex currentIndex = m_completer->currentIndex(); + if (m_completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled) + return true; + i += dir; + } + } while (i != start); + + m_completer->setCurrentRow(start); // restore + return false; +} + +void QLineControl::complete(int key) +{ + if (!m_completer || isReadOnly() || echoMode() != QLineEdit::Normal) + return; + + QString text = this->text(); + if (m_completer->completionMode() == QCompleter::InlineCompletion) { + if (key == Qt::Key_Backspace) + return; + int n = 0; + if (key == Qt::Key_Up || key == Qt::Key_Down) { + if (textAfterSelection().length()) + return; + QString prefix = hasSelectedText() ? textBeforeSelection() + : text; + if (text.compare(m_completer->currentCompletion(), m_completer->caseSensitivity()) != 0 + || prefix.compare(m_completer->completionPrefix(), m_completer->caseSensitivity()) != 0) { + m_completer->setCompletionPrefix(prefix); + } else { + n = (key == Qt::Key_Up) ? -1 : +1; + } + } else { + m_completer->setCompletionPrefix(text); + } + if (!advanceToEnabledItem(n)) + return; + } else { +#ifndef QT_KEYPAD_NAVIGATION + if (text.isEmpty()) { + m_completer->popup()->hide(); + return; + } +#endif + m_completer->setCompletionPrefix(text); + } + + m_completer->complete(); +} +#endif + +void QLineControl::setCursorBlinkPeriod(int msec) +{ + if(msec == m_blinkPeriod) + return; + if(m_blinkTimer){ + killTimer(m_blinkTimer); + } + if(msec){ + m_blinkTimer = startTimer(msec/2); + m_blinkStatus = 1; + }else{ + m_blinkTimer = 0; + if(m_blinkStatus == 0) + emit updateNeeded(inputMask().isEmpty()?cursorRect():QRect()); + } + m_blinkPeriod = msec; +} + +void QLineControl::timerEvent ( QTimerEvent * event ) +{ + if(event->timerId() == m_blinkTimer) { + m_blinkStatus = !m_blinkStatus; + emit updateNeeded(inputMask().isEmpty()?cursorRect():QRect()); + }else if(event->timerId() == m_deleteAllTimer){ + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + clear(); + }else if(event->timerId() == m_tripleClickTimer){ + killTimer(m_tripleClickTimer); + m_tripleClickTimer = 0; + } +} + +bool QLineControl::processEvent(QEvent* ev) +{ +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + //TODO: Needs a call to processKeyEvent? + } else if (e->type() == QEvent::EnterEditFocus) { + end(false); + int cft = QApplication::cursorFlashTime(); + control->setCursorBlinkPeriod(cft/2); + } else if (e->type() == QEvent::LeaveEditFocus) { + d->setCursorVisible(false);//!!! + control->setCursorBlinkPeriod(0); + if (!m_emitingEditingFinished) { + if (hasAcceptableInput() || fixup()) { + m_emitingEditingFinished = true; + emit editingFinished(); + m_emitingEditingFinished = false; + } + } + } + return; + } +#endif + switch(ev->type()){ +#ifndef QT_NO_GRAPHICSVIEW + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMousePress:{ + QGraphicsSceneMouseEvent *gvEv = static_cast(ev); + QMouseEvent* mouse = new QMouseEvent(ev->type(), + gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers()); + processMouseEvent(mouse); break; + } +#endif + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + processMouseEvent(static_cast(ev)); break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + processKeyEvent(static_cast(ev)); break; + case QEvent::InputMethod: + processInputMethodEvent(static_cast(ev)); break; +#ifndef QT_NO_SHORTCUT + case QEvent::ShortcutOverride:{ + QKeyEvent* ke = static_cast(ev); + if (ke == QKeySequence::Copy + || ke == QKeySequence::Paste + || ke == QKeySequence::Cut + || ke == QKeySequence::Redo + || ke == QKeySequence::Undo + || ke == QKeySequence::MoveToNextWord + || ke == QKeySequence::MoveToPreviousWord + || ke == QKeySequence::MoveToStartOfDocument + || ke == QKeySequence::MoveToEndOfDocument + || ke == QKeySequence::SelectNextWord + || ke == QKeySequence::SelectPreviousWord + || ke == QKeySequence::SelectStartOfLine + || ke == QKeySequence::SelectEndOfLine + || ke == QKeySequence::SelectStartOfBlock + || ke == QKeySequence::SelectEndOfBlock + || ke == QKeySequence::SelectStartOfDocument + || ke == QKeySequence::SelectAll + || ke == QKeySequence::SelectEndOfDocument) { + ke->accept(); + } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier + || ke->modifiers() == Qt::KeypadModifier) { + if (ke->key() < Qt::Key_Escape) { + ke->accept(); + } else { + switch (ke->key()) { + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + ke->accept(); + default: + break; + } + } + } + } +#endif + default: + return false; + } + return true; +} + +void QLineControl::processMouseEvent(QMouseEvent* ev) +{ + + switch (ev->type()){ + case QEvent::GraphicsSceneMousePress: + case QEvent::MouseButtonPress:{ + if (m_tripleClickTimer && (ev->pos() - m_tripleClick).manhattanLength() < + QApplication::startDragDistance()) { + selectAll(); + return; + } + if (ev->button() == Qt::RightButton) + return; +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + setEditFocus(true); + // Get the completion list to pop up. + if (m_completer) + m_completer->complete(); + } +#endif + + bool mark = ev->modifiers() & Qt::ShiftModifier; + int cursor = xToPos(ev->pos().x()); + moveCursor(cursor, mark); + break; + } + case QEvent::MouseButtonDblClick: + if (ev->button() == Qt::LeftButton) { + selectWordAtPos(xToPos(ev->pos().x())); + if(m_tripleClickTimer) + killTimer(m_tripleClickTimer); + m_tripleClickTimer = startTimer(QApplication::doubleClickInterval()); + m_tripleClick = ev->pos(); + } + break; + case QEvent::GraphicsSceneMouseRelease: + case QEvent::MouseButtonRelease: +#ifndef QT_NO_CLIPBOARD + if (QApplication::clipboard()->supportsSelection()) { + if (ev->button() == Qt::LeftButton) { + copy(QClipboard::Selection); + } else if (!isReadOnly() && ev->button() == Qt::MidButton) { + deselect(); + insert(QApplication::clipboard()->text(QClipboard::Selection)); + } + } +#endif + break; + case QEvent::GraphicsSceneMouseMove: + case QEvent::MouseMove: + if (ev->buttons() & Qt::LeftButton) { + moveCursor(xToPos(ev->pos().x()), true); + } + break; + default: + break; + } +} + +void QLineControl::processKeyEvent(QKeyEvent* event) +{ + + bool inlineCompletionAccepted = false; + +#ifndef QT_NO_COMPLETER + if (m_completer) { + QCompleter::CompletionMode completionMode = m_completer->completionMode(); + if ((completionMode == QCompleter::PopupCompletion + || completionMode == QCompleter::UnfilteredPopupCompletion) + && m_completer->popup() + && m_completer->popup()->isVisible()) { + // The following keys are forwarded by the completer to the widget + // Ignoring the events lets the completer provide suitable default behavior + switch (event->key()) { + case Qt::Key_Escape: + event->ignore(); + return; + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_F4: +#ifdef QT_KEYPAD_NAVIGATION + case Qt::Key_Select: + if (!QApplication::keypadNavigationEnabled()) + break; +#endif + m_completer->popup()->hide(); // just hide. will end up propagating to parent + default: + break; // normal key processing + } + } else if (completionMode == QCompleter::InlineCompletion) { + switch (event->key()) { + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_F4: +#ifdef QT_KEYPAD_NAVIGATION + case Qt::Key_Select: + if (!QApplication::keypadNavigationEnabled()) + break; +#endif + if (!m_completer->currentCompletion().isEmpty() && hasSelectedText() + && textAfterSelection().isEmpty()) { + setText(m_completer->currentCompletion()); + inlineCompletionAccepted = true; + } + default: + break; // normal key processing + } + } + } +#endif // QT_NO_COMPLETER + + + + if (echoMode() == QLineEdit::PasswordEchoOnEdit + && !passwordEchoEditing() + && !isReadOnly() + && !event->text().isEmpty() +#ifdef QT_KEYPAD_NAVIGATION + && event->key() != Qt::Key_Select + && event->key() != Qt::Key_Up + && event->key() != Qt::Key_Down + && event->key() != Qt::Key_Back +#endif + && !(event->modifiers() & Qt::ControlModifier)) { + // Clear the edit and reset to normal echo mode while editing; the + // echo mode switches back when the edit loses focus + // ### resets current content. dubious code; you can + // navigate with keys up, down, back, and select(?), but if you press + // "left" or "right" it clears? + updatePasswordEchoEditing(true);//TODO: used to set a WA too + clear(); + } + + //setCursorVisible(true);TODO: Who handles this? + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + if (hasAcceptableInput() || fixup()) { + emit accepted(); + emitingEditingFinished = true; + emit editingFinished(); + emitingEditingFinished = false; + } + if (inlineCompletionAccepted) + event->accept(); + else + event->ignore(); + return; + } + bool unknown = false; + + if (false) { + } +#ifndef QT_NO_SHORTCUT + else if (event == QKeySequence::Undo) { + if (!isReadOnly()) + undo(); + } + else if (event == QKeySequence::Redo) { + if (!isReadOnly()) + redo(); + } + else if (event == QKeySequence::SelectAll) { + selectAll(); + } +#ifndef QT_NO_CLIPBOARD + else if (event == QKeySequence::Copy) { + copy(); + } + else if (event == QKeySequence::Paste) { + if (!isReadOnly()) + paste(); + } + else if (event == QKeySequence::Cut) { + if (!isReadOnly()) { + copy(); + del(); + } + } + else if (event == QKeySequence::DeleteEndOfLine) { + if (!isReadOnly()) { + setSelection(cursor(), end()); + copy(); + del(); + } + } +#endif //QT_NO_CLIPBOARD + else if (event == QKeySequence::MoveToStartOfLine) { + home(0); + } + else if (event == QKeySequence::MoveToEndOfLine) { + end(0); + } + else if (event == QKeySequence::SelectStartOfLine) { + home(1); + } + else if (event == QKeySequence::SelectEndOfLine) { + end(1); + } + else if (event == QKeySequence::MoveToNextChar) { +#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) + if (hasSelectedText()) { +#else + if (hasSelectedText() && m_completer + && m_completer->completionMode() == QCompleter::InlineCompletion) { +#endif + moveCursor(selectionEnd(), false); + } else { + cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); + } + } + else if (event == QKeySequence::SelectNextChar) { + cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); + } + else if (event == QKeySequence::MoveToPreviousChar) { +#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) + if (hasSelectedText()) { +#else + if (hasSelectedText() && m_completer + && m_completer->completionMode() == QCompleter::InlineCompletion) { +#endif + moveCursor(selectionStart(), false); + } else { + cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1); + } + } + else if (event == QKeySequence::SelectPreviousChar) { + cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1); + } + else if (event == QKeySequence::MoveToNextWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0); + else + layoutDirection() == Qt::LeftToRight ? end(0) : home(0); + } + else if (event == QKeySequence::MoveToPreviousWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0); + else if (!isReadOnly()) { + layoutDirection() == Qt::LeftToRight ? home(0) : end(0); + } + } + else if (event == QKeySequence::SelectNextWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1); + else + layoutDirection() == Qt::LeftToRight ? end(1) : home(1); + } + else if (event == QKeySequence::SelectPreviousWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1); + else + layoutDirection() == Qt::LeftToRight ? home(1) : end(1); + } + else if (event == QKeySequence::Delete) { + if (!isReadOnly()) + del(); + } + else if (event == QKeySequence::DeleteEndOfWord) { + if (!isReadOnly()) { + cursorWordForward(true); + del(); + } + } + else if (event == QKeySequence::DeleteStartOfWord) { + if (!isReadOnly()) { + cursorWordBackward(true); + del(); + } + } +#endif // QT_NO_SHORTCUT + else { +#ifdef Q_WS_MAC + if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) { + Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier); + if (myModifiers & Qt::ShiftModifier) { + if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier) + || myModifiers == (Qt::AltModifier|Qt::ShiftModifier) + || myModifiers == Qt::ShiftModifier) { + + event->key() == Qt::Key_Up ? home(1) : end(1); + } + } else { + if ((myModifiers == Qt::ControlModifier + || myModifiers == Qt::AltModifier + || myModifiers == Qt::NoModifier)) { + event->key() == Qt::Key_Up ? home(0) : end(0); + } + } + } +#endif + if (event->modifiers() & Qt::ControlModifier) { + switch (event->key()) { + case Qt::Key_Backspace: + if (!isReadOnly()) { + cursorWordBackward(true); + del(); + } + break; +#ifndef QT_NO_COMPLETER + case Qt::Key_Up: + case Qt::Key_Down: + complete(event->key()); + break; +#endif +#if defined(Q_WS_X11) + case Qt::Key_E: + end(0); + break; + + case Qt::Key_U: + if (!isReadOnly()) { + setSelection(0, text().size()); +#ifndef QT_NO_CLIPBOARD + copy(); +#endif + del(); + } + break; +#endif + default: + unknown = true; + } + } else { // ### check for *no* modifier + switch (event->key()) { + case Qt::Key_Backspace: + if (!isReadOnly()) { + backspace(); +#ifndef QT_NO_COMPLETER + complete(Qt::Key_Backspace); +#endif + } + break; +#ifdef QT_KEYPAD_NAVIGATION//TODO: This section + case Qt::Key_Back: + if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() + && !isReadOnly()) { + if (text().length() == 0) { + setText(d->origText); + + if (d->passwordEchoEditing) + d->updatePasswordEchoEditing(false); + + setEditFocus(false); + } else if (!d->deleteAllTimer.isActive()) { + d->deleteAllTimer.start(750, this); + } + } else { + unknown = true; + } + break; +#endif + + default: + unknown = true; + } + } + } + + if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) { + setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); + unknown = false; + } + + if (unknown && !isReadOnly()) { + QString t = event->text(); + if (!t.isEmpty() && t.at(0).isPrint()) { + insert(t); +#ifndef QT_NO_COMPLETER + complete(event->key()); +#endif + event->accept(); + return; + } + } + + if (unknown) + event->ignore(); + else + event->accept(); +} + + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h new file mode 100644 index 0000000..bb27778 --- /dev/null +++ b/src/gui/widgets/qlinecontrol_p.h @@ -0,0 +1,715 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINECONTROL_P_H +#define QLINECONTROL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +#ifndef QT_NO_LINEEDIT +#include "private/qwidget_p.h" +#include "QtGui/qlineedit.h" +#include "QtGui/qtextlayout.h" +#include "QtGui/qstyleoption.h" +#include "QtCore/qpointer.h" +#include "QtGui/qlineedit.h" +#include "QtGui/qclipboard.h" +#include "QtCore/qpoint.h" +#include "QtGui/qcompleter.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QLineControl : public QObject +{ + Q_OBJECT +public: + + QLineControl(const QString &txt = QString()) + : emitingEditingFinished(0), + m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), + hideCursor(false), separator(0), readOnly(0), + dragEnabled(0), m_echoMode(0), textDirty(0), selDirty(0), + validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), + m_ascent(0), m_maxLength(32767), lastCursorPos(-1), + m_tripleClickTimer(0), maskData(0), modifiedState(0), undoState(0), + selstart(0), selend(0), m_passwordEchoEditing(false) + { + init(txt); + } + + ~QLineControl() + { + delete [] maskData; + } + + int nextMaskBlank(int pos); + int prevMaskBlank(int pos); + + bool isUndoAvailable() const; + bool isRedoAvailable() const; + void clearUndo(); + bool isModified() const; + void setModified(bool modified); + + bool allSelected() const; + bool hasSelectedText() const; + + int width() const; + int height() const; + int ascent() const; + + void setSelection(int start, int length); + + QString selectedText() const; + QString textBeforeSelection() const; + QString textAfterSelection() const; + + int selectionStart() const; + int selectionEnd() const; + bool inSelection(int x) const; + + void removeSelection(); + + int start() const; + int end() const; + +#ifndef QT_NO_CLIPBOARD + void copy(QClipboard::Mode mode = QClipboard::Clipboard) const; + void paste(); +#endif + + int cursor() const; + int preeditCursor() const; + + int cursorWidth() const; + void setCursorWidth(int value); + + void moveCursor(int pos, bool mark = false); + void cursorForward(bool mark, int steps); + void cursorWordForward(bool mark); + void cursorWordBackward(bool mark); + void home(bool mark); + void end(bool mark); + + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; + QRect cursorRect() const; + + qreal cursorToX(int cursor) const; + qreal cursorToX() const; + + bool isReadOnly() const; + void setReadOnly(bool enable); + + QString text() const; + void setText(const QString &); + + QString displayText() const; + + void backspace(); + void del(); + void deselect(); + void selectAll(); + void insert(const QString &); + void clear(); + void undo(); + void redo(); + void selectWordAtPos(int); + + uint echoMode() const; + void setEchoMode(uint mode); + + void setMaxLength(int maxLength); + int maxLength() const; + + const QValidator *validator() const; + void setValidator(const QValidator *); + +#ifndef QT_NO_COMPLETER + QCompleter *completer() const; + void setCompleter(const QCompleter*); + void complete(int key); +#endif + + void setCursorPosition(int pos); + int cursorPosition() const; + + bool hasAcceptableInput() const; + bool fixup(); + + QString inputMask() const; + void setInputMask(const QString &mask); + + // input methods +#ifndef QT_NO_IM + bool composeMode() const; + void setPreeditArea(int cursor, const QString &text); +#endif + + QString preeditAreaText() const; + + void updatePasswordEchoEditing(bool editing); + bool passwordEchoEditing() const; + + QChar passwordCharacter() const; + void setPasswordCharacter(const QChar &character); + + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection(Qt::LayoutDirection direction); + void setFont(const QFont &font); + + void processInputMethodEvent(QInputMethodEvent *event); + void processMouseEvent(QMouseEvent* ev); + void processKeyEvent(QKeyEvent* ev); + + int cursorBlinkPeriod() const; + void setCursorBlinkPeriod(int msec); + + enum DrawFlags { + DrawText = 0x01, + DrawSelections = 0x02, + DrawCursor = 0x04, + DrawAll = DrawText | DrawSelections | DrawCursor + }; + void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll); + + bool processEvent(QEvent* ev); + + bool emitingEditingFinished;//Needed in QLineEdit FocusOut event +private: + void init(const QString&); + void removeSelectedText(); + void p_setText(const QString& txt, int pos = -1, bool edited = true); + void updateDisplayText(); + + void p_insert(const QString& s); + void p_del(bool wasBackspace = false); + void p_remove(int pos); + inline void p_deselect() { selDirty |= (selend > selstart); selstart = selend = 0; } + void p_undo(int until = -1); + void p_redo(); + + QString m_text; + QPalette m_palette; + int m_cursor; + int m_preeditCursor; + int m_cursorWidth; + Qt::LayoutDirection m_layoutDirection; + uint hideCursor : 1; // used to hide the m_cursor inside preedit areas + uint separator : 1; + uint readOnly : 1; + uint dragEnabled : 1; + uint m_echoMode : 2; + uint textDirty : 1; + uint selDirty : 1; + uint validInput : 1; + int m_blinkPeriod; // 0 for non-blinking cursor + int m_blinkTimer; + int m_deleteAllTimer; + int m_blinkStatus; + int m_ascent; + int m_maxLength; + int lastCursorPos; + QList transactions; + QPoint m_tripleClick; + int m_tripleClickTimer; + + void emitCursorPositionChanged(); + + bool finishChange(int validateFromState = -1, bool update = false, bool edited = true); + + QPointer m_validator; + QPointer m_completer; +#ifndef QT_NO_COMPLETER + bool advanceToEnabledItem(int dir); +#endif + + struct MaskInputData { + enum Casemode { NoCaseMode, Upper, Lower }; + QChar maskChar; // either the separator char or the inputmask + bool separator; + Casemode caseMode; + }; + QString m_inputMask; + QChar blank; + MaskInputData *maskData; + + + // undo/redo handling + enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; + struct Command { + inline Command() {} + inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} + uint type : 4; + QChar uc; + int pos, selStart, selEnd; + }; + int modifiedState; + int undoState; + QVector history; + void addCommand(const Command& cmd); + + inline void separate() { separator = true; } + + // selection + int selstart, selend; + + // masking + void parseInputMask(const QString &maskFields); + bool isValidInput(QChar key, QChar mask) const; + bool hasAcceptableInput(const QString &text) const; + QString maskString(uint pos, const QString &str, bool clear = false) const; + QString clearString(uint pos, uint len) const; + QString stripString(const QString &str) const; + int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; + + + // complex text layout + QTextLayout textLayout; + + bool m_passwordEchoEditing; + QChar m_passwordCharacter; + +Q_SIGNALS: + void cursorPositionChanged(int, int); + void selectionChanged(); + + void displayTextChanged(const QString &); + void textChanged(const QString &); + void textEdited(const QString &); + + void resetInputContext(); + + void accepted(); + void editingFinished(); + void updateNeeded(const QRect &); +protected: + virtual void timerEvent ( QTimerEvent * event ); +private slots: + void _q_clipboardChanged(); + void _q_deleteSelected(); + +}; + +inline int QLineControl::nextMaskBlank(int pos) +{ + int c = findInMask(pos, true, false); + separator |= (c != pos); + return (c != -1 ? c : m_maxLength); +} + +inline int QLineControl::prevMaskBlank(int pos) +{ + int c = findInMask(pos, false, false); + separator |= (c != pos); + return (c != -1 ? c : 0); +} + +inline bool QLineControl::isUndoAvailable() const +{ + return !readOnly && undoState; +} + +inline bool QLineControl::isRedoAvailable() const +{ + return !readOnly && undoState < (int)history.size(); +} + +inline void QLineControl::clearUndo() +{ + history.clear(); + modifiedState = undoState = 0; +} + +inline bool QLineControl::isModified() const +{ + return modifiedState != undoState; +} + +inline void QLineControl::setModified(bool modified) +{ + modifiedState = modified ? -1 : undoState; +} + +inline bool QLineControl::allSelected() const +{ + return !m_text.isEmpty() && selstart == 0 && selend == (int)m_text.length(); +} + +inline bool QLineControl::hasSelectedText() const +{ + return !m_text.isEmpty() && selend > selstart; +} + +inline int QLineControl::width() const +{ + return qRound(textLayout.lineAt(0).width()) + 1; +} + +inline int QLineControl::height() const +{ + return qRound(textLayout.lineAt(0).height()) + 1; +} + +inline int QLineControl::ascent() const +{ + return m_ascent; +} + +inline QString QLineControl::selectedText() const +{ + if (hasSelectedText()) + return m_text.mid(selstart, selend - selstart); + return QString(); +} + +inline QString QLineControl::textBeforeSelection() const +{ + if (hasSelectedText()) + return m_text.left(selstart); + return QString(); +} + +inline QString QLineControl::textAfterSelection() const +{ + if (hasSelectedText()) + return m_text.mid(selend); + return QString(); +} + +inline int QLineControl::selectionStart() const +{ + return hasSelectedText() ? selstart : -1; +} + +inline int QLineControl::selectionEnd() const +{ + return hasSelectedText() ? selend : -1; +} + +inline int QLineControl::start() const +{ + return 0; +} + +inline int QLineControl::end() const +{ + return m_text.length(); +} + +inline void QLineControl::removeSelection() +{ + int priorState = undoState; + removeSelectedText(); + finishChange(priorState); +} + +inline bool QLineControl::inSelection(int x) const +{ + if (selstart >= selend) return false; + int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; +} + +inline int QLineControl::cursor() const +{ + return m_cursor; +} + +inline int QLineControl::preeditCursor() const +{ + return m_preeditCursor; +} + +inline int QLineControl::cursorWidth() const +{ + return m_cursorWidth; +} + +inline void QLineControl::setCursorWidth(int value) +{ + m_cursorWidth = value; +} + +inline void QLineControl::cursorForward(bool mark, int steps) +{ + int c = m_cursor; + if (steps > 0) { + while(steps--) + c = textLayout.nextCursorPosition(c); + } else if (steps < 0) { + while (steps++) + c = textLayout.previousCursorPosition(c); + } + moveCursor(c, mark); +} + +inline void QLineControl::cursorWordForward(bool mark) +{ + moveCursor(textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); +} + +inline void QLineControl::home(bool mark) +{ + moveCursor(0, mark); +} + +inline void QLineControl::end(bool mark) +{ + moveCursor(text().length(), mark); +} + +inline void QLineControl::cursorWordBackward(bool mark) +{ + moveCursor(textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); +} + +inline qreal QLineControl::cursorToX(int cursor) const +{ + return textLayout.lineAt(0).cursorToX(cursor); +} + +inline qreal QLineControl::cursorToX() const +{ + return cursorToX(m_cursor); +} + +inline bool QLineControl::isReadOnly() const +{ + return readOnly; +} + +inline void QLineControl::setReadOnly(bool enable) +{ + readOnly = enable; +} + +inline QString QLineControl::text() const +{ + QString res = maskData ? stripString(m_text) : m_text; + return (res.isNull() ? QString::fromLatin1("") : res); +} + +inline void QLineControl::setText(const QString &txt) +{ + p_setText(txt, -1, false); +} + +inline QString QLineControl::displayText() const +{ + return textLayout.text(); +} + +inline void QLineControl::deselect() +{ + p_deselect(); finishChange(); +} + +inline void QLineControl::selectAll() +{ + selstart = selend = m_cursor = 0; moveCursor(m_text.length(), true); +} + +inline void QLineControl::undo() +{ + p_undo(), finishChange(-1, true); +} + +inline void QLineControl::redo() +{ + p_redo(), finishChange(); +} + +inline uint QLineControl::echoMode() const +{ + return m_echoMode; +} + +inline void QLineControl::setEchoMode(uint mode) +{ + m_echoMode = mode; + m_passwordEchoEditing = false; + updateDisplayText(); +} + +inline void QLineControl::setMaxLength(int maxLength) +{ + if (maskData) + return; + m_maxLength = maxLength; + setText(m_text); +} + +inline int QLineControl::maxLength() const +{ + return m_maxLength; +} + +inline const QValidator *QLineControl::validator() const +{ + return m_validator; +} + +inline void QLineControl::setValidator(const QValidator *v) +{ + m_validator = const_cast(v); +} + +#ifndef QT_NO_COMPLETER +inline QCompleter *QLineControl::completer() const +{ + return m_completer; +} + +/* Note that you must set the widget for the completer seperately */ +inline void QLineControl::setCompleter(const QCompleter* c) +{ + m_completer = const_cast(c); +} +#endif + +inline void QLineControl::setCursorPosition(int pos) +{ + if (pos < 0) pos = 0; + if (pos < m_text.length()) + moveCursor(pos); +} + +inline int QLineControl::cursorPosition() const +{ + return m_cursor; +} + +inline bool QLineControl::hasAcceptableInput() const +{ + return hasAcceptableInput(m_text); +} + +inline QString QLineControl::inputMask() const +{ + return maskData ? m_inputMask + QLatin1Char(';') + blank : QString(); +} + +inline void QLineControl::setInputMask(const QString &mask) +{ + parseInputMask(mask); + if (maskData) + moveCursor(nextMaskBlank(0)); +} + +// input methods +#ifndef QT_NO_IM +inline bool QLineControl::composeMode() const +{ + return !textLayout.preeditAreaText().isEmpty(); +} + +inline void QLineControl::setPreeditArea(int cursor, const QString &text) +{ + textLayout.setPreeditArea(cursor, text); +} +#endif + +inline QString QLineControl::preeditAreaText() const +{ + return textLayout.preeditAreaText(); +} + +inline bool QLineControl::passwordEchoEditing() const +{ + return m_passwordEchoEditing; +} + +inline QChar QLineControl::passwordCharacter() const +{ + return m_passwordCharacter; +} + +inline void QLineControl::setPasswordCharacter(const QChar &character) +{ + m_passwordCharacter = character; + updateDisplayText(); +} + +inline Qt::LayoutDirection QLineControl::layoutDirection() const +{ + return m_layoutDirection; +} + +inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction) +{ + if (direction != m_layoutDirection) { + m_layoutDirection = direction; + updateDisplayText(); + } +} + +inline void QLineControl::setFont(const QFont &font) +{ + textLayout.setFont(font); + updateDisplayText(); +} + +inline int QLineControl::cursorBlinkPeriod() const +{ + return m_blinkPeriod; +} + +QT_END_NAMESPACE + +QT_END_HEADER +#endif // QT_NO_LINEEDIT + + +#endif // QLINECONTROL_P_H diff --git a/src/gui/widgets/qlinecontrol_p_p.h b/src/gui/widgets/qlinecontrol_p_p.h new file mode 100644 index 0000000..e76794b --- /dev/null +++ b/src/gui/widgets/qlinecontrol_p_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINECONTROL_P_P_H +#define QLINECONTROL_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qobject_p.h" +#include "QtGui/qtextlayout.h" + +QT_BEGIN_NAMESPACE + +class QMimeData; +class QAbstractScrollArea; +class QInputContext; + +class QLineControlPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QLineControl) +public: + QLineControlPrivate() + : cursor(0), preeditCursor(0), cursorWidth(1), cursorTimer(0), + maxLength(32767), modifiedState(0), undoState(0), + selStart(0), selEnd(0), textInteractionFlags(0), + cursorVisible(0), hideCursor(0), echoMode(0) + {} + + QPalette palette; + QVector history; + QTextLayout textLayout; // display text + QString text; + + int cursor; + int preeditCursor; + int lastCursorPos; + int cursorWidth; + int cursorTimer; + + int maxLength; + + int modifiedState; + int undoState; + + int selStart, selEnd; + + Qt::TextInteractionFlags textInteractionFlags; + + // keep together and at end + uint cursorVisible : 1; + uint hideCursor : 1; // used to hide the cursor inside preedit areas + uint echoMode : 2; +}; + +QT_END_NAMESPACE + +#endif // QLINECONTROL_P_H + diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index d1067a8..baaad32 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -86,21 +86,12 @@ #include -#define verticalMargin 1 -#define horizontalMargin 2 - QT_BEGIN_NAMESPACE #ifdef Q_WS_MAC extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp #endif -static inline bool shouldEnableInputMethod(QLineEdit *lineedit) -{ - const QLineEdit::EchoMode mode = lineedit->echoMode(); - return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit); -} - /*! Initialize \a option with the values from this QLineEdit. This method is useful for subclasses when they need a QStyleOptionFrame or QStyleOptionFrameV2, but don't want @@ -122,7 +113,7 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const : 0; option->midLineWidth = 0; option->state |= QStyle::State_Sunken; - if (d->readOnly) + if (d->control->isReadOnly()) option->state |= QStyle::State_ReadOnly; #ifdef QT_KEYPAD_NAVIGATION if (hasEditFocus()) @@ -350,14 +341,14 @@ QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget* { Q_D(QLineEdit); setObjectName(QString::fromAscii(name)); - d->parseInputMask(inputMask); - if (d->maskData) { - QString ms = d->maskString(0, contents); - d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length())); - d->cursor = d->nextMaskBlank(ms.length()); - } else { + //d->control->parseInputMask(inputMask); + //if (d->control->maskData) { + // QString ms = d->control->maskString(0, contents); + // d->init(ms + d->control->clearString(ms.length(), d->control->maxLength() - ms.length())); + // d->control->moveCursor(d->control->nextMaskBlank(ms.length())); + // } else { d->init(contents); - } + // } } #endif @@ -388,19 +379,13 @@ QLineEdit::~QLineEdit() QString QLineEdit::text() const { Q_D(const QLineEdit); - QString res = d->text; - if (d->maskData) - res = d->stripString(d->text); - return (res.isNull() ? QString::fromLatin1("") : res); + return d->control->text(); } void QLineEdit::setText(const QString& text) { Q_D(QLineEdit); - d->setText(text, -1, false); -#ifdef QT_KEYPAD_NAVIGATION - d->origText = d->text; -#endif + d->control->setText(text); } @@ -421,17 +406,7 @@ void QLineEdit::setText(const QString& text) QString QLineEdit::displayText() const { Q_D(const QLineEdit); - if (d->echoMode == NoEcho) - return QString::fromLatin1(""); - QString res = d->text; - - if (d->echoMode == Password || (d->echoMode == PasswordEchoOnEdit - && !d->passwordEchoEditing)) { - QStyleOptionFrameV2 opt; - initStyleOption(&opt); - res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this)); - } - return (res.isNull() ? QString::fromLatin1("") : res); + return d->control->displayText(); } @@ -456,20 +431,15 @@ QString QLineEdit::displayText() const int QLineEdit::maxLength() const { Q_D(const QLineEdit); - return d->maxLength; + return d->control->maxLength(); } void QLineEdit::setMaxLength(int maxLength) { Q_D(QLineEdit); - if (d->maskData) - return; - d->maxLength = maxLength; - setText(d->text); + d->control->setMaxLength(maxLength); } - - /*! \property QLineEdit::frame \brief whether the line edit draws itself with a frame @@ -536,22 +506,20 @@ void QLineEdit::setFrame(bool enable) QLineEdit::EchoMode QLineEdit::echoMode() const { Q_D(const QLineEdit); - return (EchoMode) d->echoMode; + return (EchoMode) d->control->echoMode(); } void QLineEdit::setEchoMode(EchoMode mode) { Q_D(QLineEdit); - if (mode == (EchoMode)d->echoMode) + if (mode == (EchoMode)d->control->echoMode()) return; - setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); - d->echoMode = mode; - d->passwordEchoEditing = false; - d->updateTextLayout(); + setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod()); + d->control->setEchoMode(mode); update(); #ifdef Q_WS_MAC if (hasFocus()) - qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho); + qt_mac_secure_keyboard(mode == Password || mode == NoEcho); #endif } @@ -567,7 +535,7 @@ void QLineEdit::setEchoMode(EchoMode mode) const QValidator * QLineEdit::validator() const { Q_D(const QLineEdit); - return d->validator; + return d->control->validator(); } /*! @@ -585,7 +553,7 @@ const QValidator * QLineEdit::validator() const void QLineEdit::setValidator(const QValidator *v) { Q_D(QLineEdit); - d->validator = const_cast(v); + d->control->setValidator(v); } #endif // QT_NO_VALIDATOR @@ -609,23 +577,23 @@ void QLineEdit::setValidator(const QValidator *v) void QLineEdit::setCompleter(QCompleter *c) { Q_D(QLineEdit); - if (c == d->completer) + if (c == d->control->completer()) return; - if (d->completer) { - disconnect(d->completer, 0, this, 0); - d->completer->setWidget(0); - if (d->completer->parent() == this) - delete d->completer; + if (d->control->completer()) { + disconnect(d->control->completer(), 0, this, 0); + d->control->completer()->setWidget(0); + if (d->control->completer()->parent() == this) + delete d->control->completer(); } - d->completer = c; + d->control->setCompleter(c); if (!c) return; if (c->widget() == 0) c->setWidget(this); if (hasFocus()) { - QObject::connect(d->completer, SIGNAL(activated(QString)), + QObject::connect(d->control->completer(), SIGNAL(activated(QString)), this, SLOT(setText(QString))); - QObject::connect(d->completer, SIGNAL(highlighted(QString)), + QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)), this, SLOT(_q_completionHighlighted(QString))); } } @@ -638,83 +606,9 @@ void QLineEdit::setCompleter(QCompleter *c) QCompleter *QLineEdit::completer() const { Q_D(const QLineEdit); - return d->completer; -} - -// looks for an enabled item iterating forward(dir=1)/backward(dir=-1) from the -// current row based. dir=0 indicates a new completion prefix was set. -bool QLineEditPrivate::advanceToEnabledItem(int dir) -{ - int start = completer->currentRow(); - if (start == -1) - return false; - int i = start + dir; - if (dir == 0) dir = 1; - do { - if (!completer->setCurrentRow(i)) { - if (!completer->wrapAround()) - break; - i = i > 0 ? 0 : completer->completionCount() - 1; - } else { - QModelIndex currentIndex = completer->currentIndex(); - if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled) - return true; - i += dir; - } - } while (i != start); - - completer->setCurrentRow(start); // restore - return false; -} - -void QLineEditPrivate::complete(int key) -{ - if (!completer || readOnly || echoMode != QLineEdit::Normal) - return; - - if (completer->completionMode() == QCompleter::InlineCompletion) { - if (key == Qt::Key_Backspace) - return; - int n = 0; - if (key == Qt::Key_Up || key == Qt::Key_Down) { - if (selend != 0 && selend != text.length()) - return; - QString prefix = hasSelectedText() ? text.left(selstart) : text; - if (text.compare(completer->currentCompletion(), completer->caseSensitivity()) != 0 - || prefix.compare(completer->completionPrefix(), completer->caseSensitivity()) != 0) { - completer->setCompletionPrefix(prefix); - } else { - n = (key == Qt::Key_Up) ? -1 : +1; - } - } else { - completer->setCompletionPrefix(text); - } - if (!advanceToEnabledItem(n)) - return; - } else { -#ifndef QT_KEYPAD_NAVIGATION - if (text.isEmpty()) { - completer->popup()->hide(); - return; - } -#endif - completer->setCompletionPrefix(text); - } - - completer->complete(); + return d->control->completer(); } -void QLineEditPrivate::_q_completionHighlighted(QString newText) -{ - Q_Q(QLineEdit); - if (completer->completionMode() != QCompleter::InlineCompletion) - q->setText(newText); - else { - int c = cursor; - q->setText(text.left(c) + newText.mid(c)); - q->setSelection(text.length(), c - newText.length()); - } -} #endif // QT_NO_COMPLETER /*! @@ -729,10 +623,10 @@ QSize QLineEdit::sizeHint() const Q_D(const QLineEdit); ensurePolished(); QFontMetrics fm(font()); - int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin + int h = qMax(fm.lineSpacing(), 14) + 2*d->verticalMargin + d->topTextMargin + d->bottomTextMargin + d->topmargin + d->bottommargin; - int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin + int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin + d->leftTextMargin + d->rightTextMargin + d->leftmargin + d->rightmargin; // "some" QStyleOptionFrameV2 opt; @@ -753,7 +647,7 @@ QSize QLineEdit::minimumSizeHint() const Q_D(const QLineEdit); ensurePolished(); QFontMetrics fm = fontMetrics(); - int h = fm.height() + qMax(2*verticalMargin, fm.leading()) + int h = fm.height() + qMax(2*d->verticalMargin, fm.leading()) + d->topmargin + d->bottommargin; int w = fm.maxWidth() + d->leftmargin + d->rightmargin; QStyleOptionFrameV2 opt; @@ -775,17 +669,13 @@ QSize QLineEdit::minimumSizeHint() const int QLineEdit::cursorPosition() const { Q_D(const QLineEdit); - return d->cursor; + return d->control->cursorPosition(); } void QLineEdit::setCursorPosition(int pos) { Q_D(QLineEdit); - if (pos < 0) - pos = 0; - - if (pos <= d->text.length()) - d->moveCursor(pos); + d->control->setCursorPosition(pos); } /*! @@ -807,22 +697,12 @@ int QLineEdit::cursorPositionAt(const QPoint &pos) bool QLineEdit::validateAndSet(const QString &newText, int newPos, int newMarkAnchor, int newMarkDrag) { - Q_D(QLineEdit); - int priorState = d->undoState; - d->selstart = 0; - d->selend = d->text.length(); - d->removeSelectedText(); - d->insert(newText); - d->finishChange(priorState); - if (d->undoState > priorState) { - d->cursor = newPos; - d->selstart = qMin(newMarkAnchor, newMarkDrag); - d->selend = qMax(newMarkAnchor, newMarkDrag); - update(); - d->emitCursorPositionChanged(); - return true; - } - return false; + // Note, this doesn't validate', but then neither + // does the suggested functions above in the docs. + setText(newText); + setCursorPosition(newPos); + setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag)); + return true; } #endif //QT3_SUPPORT @@ -863,15 +743,7 @@ void QLineEdit::setAlignment(Qt::Alignment alignment) void QLineEdit::cursorForward(bool mark, int steps) { Q_D(QLineEdit); - int cursor = d->cursor; - if (steps > 0) { - while(steps--) - cursor = d->textLayout.nextCursorPosition(cursor); - } else if (steps < 0) { - while (steps++) - cursor = d->textLayout.previousCursorPosition(cursor); - } - d->moveCursor(cursor, mark); + d->control->cursorForward(mark, steps); } @@ -896,7 +768,7 @@ void QLineEdit::cursorBackward(bool mark, int steps) void QLineEdit::cursorWordForward(bool mark) { Q_D(QLineEdit); - d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark); + d->control->cursorWordForward(mark); } /*! @@ -909,7 +781,7 @@ void QLineEdit::cursorWordForward(bool mark) void QLineEdit::cursorWordBackward(bool mark) { Q_D(QLineEdit); - d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark); + d->control->cursorWordBackward(mark); } @@ -924,26 +796,7 @@ void QLineEdit::cursorWordBackward(bool mark) void QLineEdit::backspace() { Q_D(QLineEdit); - int priorState = d->undoState; - if (d->hasSelectedText()) { - d->removeSelectedText(); - } else if (d->cursor) { - --d->cursor; - if (d->maskData) - d->cursor = d->prevMaskBlank(d->cursor); - QChar uc = d->text.at(d->cursor); - if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { - // second half of a surrogate, check if we have the first half as well, - // if yes delete both at once - uc = d->text.at(d->cursor - 1); - if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { - d->del(true); - --d->cursor; - } - } - d->del(true); - } - d->finishChange(priorState); + d->control->backspace(); } /*! @@ -957,15 +810,7 @@ void QLineEdit::backspace() void QLineEdit::del() { Q_D(QLineEdit); - int priorState = d->undoState; - if (d->hasSelectedText()) { - d->removeSelectedText(); - } else { - int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor; - while (n--) - d->del(); - } - d->finishChange(priorState); + d->control->del(); } /*! @@ -980,7 +825,7 @@ void QLineEdit::del() void QLineEdit::home(bool mark) { Q_D(QLineEdit); - d->moveCursor(0, mark); + d->control->home(mark); } /*! @@ -995,7 +840,7 @@ void QLineEdit::home(bool mark) void QLineEdit::end(bool mark) { Q_D(QLineEdit); - d->moveCursor(d->text.length(), mark); + d->control->end(mark); } @@ -1020,16 +865,13 @@ void QLineEdit::end(bool mark) bool QLineEdit::isModified() const { Q_D(const QLineEdit); - return d->modifiedState != d->undoState; + return d->control->isModified(); } void QLineEdit::setModified(bool modified) { Q_D(QLineEdit); - if (modified) - d->modifiedState = -1; - else - d->modifiedState = d->undoState; + d->control->setModified(modified); } @@ -1057,7 +899,7 @@ Use setModified(false) instead. bool QLineEdit::hasSelectedText() const { Q_D(const QLineEdit); - return d->hasSelectedText(); + return d->control->hasSelectedText(); } /*! @@ -1075,9 +917,7 @@ bool QLineEdit::hasSelectedText() const QString QLineEdit::selectedText() const { Q_D(const QLineEdit); - if (d->hasSelectedText()) - return d->text.mid(d->selstart, d->selend - d->selstart); - return QString(); + return d->control->selectedText(); } /*! @@ -1090,7 +930,7 @@ QString QLineEdit::selectedText() const int QLineEdit::selectionStart() const { Q_D(const QLineEdit); - return d->hasSelectedText() ? d->selstart : -1; + return d->control->selectionStart(); } @@ -1120,9 +960,10 @@ void QLineEdit::setEdited(bool on) { setModified(on); } int QLineEdit::characterAt(int xpos, QChar *chr) const { Q_D(const QLineEdit); - int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin); - if (chr && pos < (int) d->text.length()) - *chr = d->text.at(pos); + int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + d->horizontalMargin); + QString txt = d->control->text(); + if (chr && pos < (int) txt.length()) + *chr = txt.at(pos); return pos; } @@ -1133,9 +974,9 @@ int QLineEdit::characterAt(int xpos, QChar *chr) const bool QLineEdit::getSelection(int *start, int *end) { Q_D(QLineEdit); - if (d->hasSelectedText() && start && end) { - *start = d->selstart; - *end = d->selend; + if (d->control->hasSelectedText() && start && end) { + *start = selectionStart(); + *end = *start + selectedText().length(); return true; } return false; @@ -1153,30 +994,19 @@ bool QLineEdit::getSelection(int *start, int *end) void QLineEdit::setSelection(int start, int length) { Q_D(QLineEdit); - if (start < 0 || start > (int)d->text.length()) { + if (start < 0 || start > (int)d->control->text().length()) { qWarning("QLineEdit::setSelection: Invalid start position (%d)", start); return; - } else { - if (length > 0) { - d->selstart = start; - d->selend = qMin(start + length, (int)d->text.length()); - d->cursor = d->selend; - } else { - d->selstart = qMax(start + length, 0); - d->selend = start; - d->cursor = d->selstart; - } } - if (d->hasSelectedText()){ + d->control->setSelection(start, length); + + if (d->control->hasSelectedText()){ QStyleOptionFrameV2 opt; initStyleOption(&opt); if (!style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) d->setCursorVisible(false); } - - update(); - d->emitCursorPositionChanged(); } @@ -1192,7 +1022,7 @@ void QLineEdit::setSelection(int start, int length) bool QLineEdit::isUndoAvailable() const { Q_D(const QLineEdit); - return d->isUndoAvailable(); + return d->control->isUndoAvailable(); } /*! @@ -1208,7 +1038,7 @@ bool QLineEdit::isUndoAvailable() const bool QLineEdit::isRedoAvailable() const { Q_D(const QLineEdit); - return d->isRedoAvailable(); + return d->control->isRedoAvailable(); } /*! @@ -1244,7 +1074,7 @@ void QLineEdit::setDragEnabled(bool b) bool QLineEdit::hasAcceptableInput() const { Q_D(const QLineEdit); - return d->hasAcceptableInput(d->text); + return d->control->hasAcceptableInput(); } /*! @@ -1350,15 +1180,13 @@ void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) con QString QLineEdit::inputMask() const { Q_D(const QLineEdit); - return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString()); + return d->control->inputMask(); } void QLineEdit::setInputMask(const QString &inputMask) { Q_D(QLineEdit); - d->parseInputMask(inputMask); - if (d->maskData) - d->moveCursor(d->nextMaskBlank(0)); + d->control->setInputMask(inputMask); } /*! @@ -1373,8 +1201,7 @@ void QLineEdit::setInputMask(const QString &inputMask) void QLineEdit::selectAll() { Q_D(QLineEdit); - d->selstart = d->selend = d->cursor = 0; - d->moveCursor(d->text.length(), true); + d->control->selectAll(); } /*! @@ -1386,8 +1213,7 @@ void QLineEdit::selectAll() void QLineEdit::deselect() { Q_D(QLineEdit); - d->deselect(); - d->finishChange(); + d->control->deselect(); } @@ -1402,10 +1228,7 @@ void QLineEdit::insert(const QString &newText) { // q->resetInputContext(); //#### FIX ME IN QT Q_D(QLineEdit); - int priorState = d->undoState; - d->removeSelectedText(); - d->insert(newText); - d->finishChange(priorState); + d->control->insert(newText); } /*! @@ -1416,13 +1239,8 @@ void QLineEdit::insert(const QString &newText) void QLineEdit::clear() { Q_D(QLineEdit); - int priorState = d->undoState; resetInputContext(); - d->selstart = 0; - d->selend = d->text.length(); - d->removeSelectedText(); - d->separate(); - d->finishChange(priorState, /*update*/false, /*edited*/false); + d->control->clear(); } /*! @@ -1435,8 +1253,7 @@ void QLineEdit::undo() { Q_D(QLineEdit); resetInputContext(); - d->undo(); - d->finishChange(-1, true); + d->control->undo(); } /*! @@ -1447,8 +1264,7 @@ void QLineEdit::redo() { Q_D(QLineEdit); resetInputContext(); - d->redo(); - d->finishChange(); + d->control->redo(); } @@ -1470,16 +1286,16 @@ void QLineEdit::redo() bool QLineEdit::isReadOnly() const { Q_D(const QLineEdit); - return d->readOnly; + return d->control->isReadOnly(); } void QLineEdit::setReadOnly(bool enable) { Q_D(QLineEdit); - if (d->readOnly != enable) { - d->readOnly = enable; - setAttribute(Qt::WA_MacShowFocusRect, !d->readOnly); - setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); + if (d->control->isReadOnly() != enable) { + d->control->setReadOnly(enable); + setAttribute(Qt::WA_MacShowFocusRect, !enable); + setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod()); #ifndef QT_NO_CURSOR setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor); #endif @@ -1518,7 +1334,7 @@ void QLineEdit::cut() void QLineEdit::copy() const { Q_D(const QLineEdit); - d->copy(); + d->control->copy(); } /*! @@ -1535,23 +1351,7 @@ void QLineEdit::copy() const void QLineEdit::paste() { Q_D(QLineEdit); - if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) { - // Clear the edit and reset to normal echo mode when pasting; the echo - // mode switches back when the edit loses focus. ### changes a public - // property, resets current content - d->updatePasswordEchoEditing(true); - clear(); - } - insert(QApplication::clipboard()->text(QClipboard::Clipboard)); -} - -void QLineEditPrivate::copy(bool clipboard) const -{ - Q_Q(const QLineEdit); - QString t = q->selectedText(); - if (!t.isEmpty() && echoMode == QLineEdit::Normal) { - QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection); - } + d->control->paste(); } #endif // !QT_NO_CLIPBOARD @@ -1561,57 +1361,10 @@ void QLineEditPrivate::copy(bool clipboard) const bool QLineEdit::event(QEvent * e) { Q_D(QLineEdit); -#ifndef QT_NO_SHORTCUT - if (e->type() == QEvent::ShortcutOverride && !d->readOnly) { - QKeyEvent* ke = (QKeyEvent*) e; - if (ke == QKeySequence::Copy - || ke == QKeySequence::Paste - || ke == QKeySequence::Cut - || ke == QKeySequence::Redo - || ke == QKeySequence::Undo - || ke == QKeySequence::MoveToNextWord - || ke == QKeySequence::MoveToPreviousWord - || ke == QKeySequence::MoveToStartOfDocument - || ke == QKeySequence::MoveToEndOfDocument - || ke == QKeySequence::SelectNextWord - || ke == QKeySequence::SelectPreviousWord - || ke == QKeySequence::SelectStartOfLine - || ke == QKeySequence::SelectEndOfLine - || ke == QKeySequence::SelectStartOfBlock - || ke == QKeySequence::SelectEndOfBlock - || ke == QKeySequence::SelectStartOfDocument - || ke == QKeySequence::SelectAll - || ke == QKeySequence::SelectEndOfDocument) { - ke->accept(); - } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - ke->accept(); - } else { - switch (ke->key()) { - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - ke->accept(); - default: - break; - } - } - } - } else -#endif if (e->type() == QEvent::Timer) { // should be timerEvent, is here for binary compatibility int timerId = ((QTimerEvent*)e)->timerId(); - if (timerId == d->cursorTimer) { - QStyleOptionFrameV2 opt; - initStyleOption(&opt); - if(!hasSelectedText() - || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) - d->setCursorVisible(!d->cursorVisible); + if (false) { #ifndef QT_NO_DRAGANDDROP } else if (timerId == d->dndTimer.timerId()) { d->drag(); @@ -1619,62 +1372,20 @@ bool QLineEdit::event(QEvent * e) } else if (timerId == d->tripleClickTimer.timerId()) d->tripleClickTimer.stop(); -#ifdef QT_KEYPAD_NAVIGATION - else if (timerId == d->deleteAllTimer.timerId()) { - d->deleteAllTimer.stop(); - clear(); - } -#endif } else if (e->type() == QEvent::ContextMenu) { #ifndef QT_NO_IM - if (d->composeMode()) + if (d->control->composeMode()) return true; #endif - d->separate(); + //d->separate(); } else if (e->type() == QEvent::WindowActivate) { QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate())); + }else if(e->type() == QEvent::ShortcutOverride){ + d->control->processEvent(e); + }else if(e->type() == QEvent::LayoutDirectionChange){ + d->control->setLayoutDirection((layoutDirection())); } -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - if ((e->type() == QEvent::KeyPress) || (e->type() == QEvent::KeyRelease)) { - QKeyEvent *ke = (QKeyEvent *)e; - if (ke->key() == Qt::Key_Back) { - if (ke->isAutoRepeat()) { - // Swallow it. We don't want back keys running amok. - ke->accept(); - return true; - } - if ((e->type() == QEvent::KeyRelease) - && !isReadOnly() - && d->deleteAllTimer.isActive()) { - d->deleteAllTimer.stop(); - backspace(); - ke->accept(); - return true; - } - } - } else if (e->type() == QEvent::EnterEditFocus) { - end(false); - if (!d->cursorTimer) { - int cft = QApplication::cursorFlashTime(); - d->cursorTimer = cft ? startTimer(cft/2) : -1; - } - } else if (e->type() == QEvent::LeaveEditFocus) { - d->setCursorVisible(false); - if (d->cursorTimer > 0) - killTimer(d->cursorTimer); - d->cursorTimer = 0; - - if (!d->emitingEditingFinished) { - if (hasAcceptableInput() || d->fixup()) { - d->emitingEditingFinished = true; - emit editingFinished(); - d->emitingEditingFinished = false; - } - } - } - } -#endif + return QWidget::event(e); } @@ -1684,37 +1395,35 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; if (e->button() == Qt::RightButton) return; #ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { setEditFocus(true); // Get the completion list to pop up. - if (d->completer) - d->completer->complete(); + if (d->control->completer()) + d->control->completer()->complete(); } #endif if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() < QApplication::startDragDistance()) { selectAll(); - return; + return; } bool mark = e->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(e->pos().x()); #ifndef QT_NO_DRAGANDDROP - if (!mark && d->dragEnabled && d->echoMode == Normal && - e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) { - d->cursor = cursor; - update(); + if (!mark && d->dragEnabled && d->control->echoMode() == Normal && + e->button() == Qt::LeftButton && d->control->inSelection(e->pos().x())) { + d->control->moveCursor(cursor); d->dndPos = e->pos(); if (!d->dndTimer.isActive()) d->dndTimer.start(QApplication::startDragTime(), this); - d->emitCursorPositionChanged(); } else #endif { - d->moveCursor(cursor, mark); + d->control->moveCursor(cursor, mark); } } @@ -1724,7 +1433,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; if (e->buttons() & Qt::LeftButton) { #ifndef QT_NO_DRAGANDDROP @@ -1734,7 +1443,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) } else #endif { - d->moveCursor(d->xToPos(e->pos().x()), true); + d->control->moveCursor(d->xToPos(e->pos().x()), true); } } } @@ -1745,26 +1454,19 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; + + if (e->buttons() & Qt::LeftButton) { #ifndef QT_NO_DRAGANDDROP - if (e->button() == Qt::LeftButton) { if (d->dndTimer.isActive()) { - d->dndTimer.stop(); - deselect(); - return; - } - } + if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) + d->drag(); + } else #endif -#ifndef QT_NO_CLIPBOARD - if (QApplication::clipboard()->supportsSelection()) { - if (e->button() == Qt::LeftButton) { - d->copy(false); - } else if (!d->readOnly && e->button() == Qt::MidButton) { - d->deselect(); - insert(QApplication::clipboard()->text(QClipboard::Selection)); + { + d->control->moveCursor(d->xToPos(e->pos().x()), true); } } -#endif } /*! \reimp @@ -1773,16 +1475,9 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; if (e->button() == Qt::LeftButton) { - deselect(); - d->cursor = d->xToPos(e->pos().x()); - d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords); - // ## text layout should support end of words. - int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords); - while (end > d->cursor && d->text[end-1].isSpace()) - --end; - d->moveCursor(end, true); + d->control->selectWordAtPos(d->xToPos(e->pos().x())); d->tripleClickTimer.start(QApplication::doubleClickInterval(), this); d->tripleClick = e->pos(); } @@ -1822,65 +1517,15 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e) void QLineEdit::keyPressEvent(QKeyEvent *event) { Q_D(QLineEdit); - - bool inlineCompletionAccepted = false; - -#ifndef QT_NO_COMPLETER - if (d->completer) { - QCompleter::CompletionMode completionMode = d->completer->completionMode(); - if ((completionMode == QCompleter::PopupCompletion - || completionMode == QCompleter::UnfilteredPopupCompletion) - &&d->completer->popup() - && d->completer->popup()->isVisible()) { - // The following keys are forwarded by the completer to the widget - // Ignoring the events lets the completer provide suitable default behavior - switch (event->key()) { - case Qt::Key_Escape: - event->ignore(); - return; - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_F4: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) - break; -#endif - d->completer->popup()->hide(); // just hide. will end up propagating to parent - default: - break; // normal key processing - } - } else if (completionMode == QCompleter::InlineCompletion) { - switch (event->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_F4: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) - break; -#endif - if (!d->completer->currentCompletion().isEmpty() && d->selend > d->selstart - && d->selend == d->text.length()) { - setText(d->completer->currentCompletion()); - inlineCompletionAccepted = true; - } - default: - break; // normal key processing - } - } - } -#endif // QT_NO_COMPLETER - -#ifdef QT_KEYPAD_NAVIGATION + #ifdef QT_KEYPAD_NAVIGATION bool select = false; switch (event->key()) { case Qt::Key_Select: if (QApplication::keypadNavigationEnabled()) { if (hasEditFocus()) { setEditFocus(false); - if (d->completer && d->completer->popup()->isVisible()) - d->completer->popup()->hide(); + if (d->control->completer() && d->control->completer()->popup()->isVisible()) + d->control->completer()->popup()->hide(); select = true; } } @@ -1916,274 +1561,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) return; // Just start. No action. } #endif - - if (echoMode() == PasswordEchoOnEdit - && !d->passwordEchoEditing - && !isReadOnly() - && !event->text().isEmpty() -#ifdef QT_KEYPAD_NAVIGATION - && event->key() != Qt::Key_Select - && event->key() != Qt::Key_Up - && event->key() != Qt::Key_Down - && event->key() != Qt::Key_Back -#endif - && !(event->modifiers() & Qt::ControlModifier)) { - // Clear the edit and reset to normal echo mode while editing; the - // echo mode switches back when the edit loses focus. ### changes a - // public property, resets current content. dubious code; you can - // navigate with keys up, down, back, and select(?), but if you press - // "left" or "right" it clears? - d->updatePasswordEchoEditing(true); - clear(); - } - - d->setCursorVisible(true); - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - if (hasAcceptableInput() || d->fixup()) { - emit returnPressed(); - d->emitingEditingFinished = true; - emit editingFinished(); - d->emitingEditingFinished = false; - } - if (inlineCompletionAccepted) - event->accept(); - else - event->ignore(); - return; - } - bool unknown = false; - - if (false) { - } -#ifndef QT_NO_SHORTCUT - else if (event == QKeySequence::Undo) { - if (!d->readOnly) - undo(); - } - else if (event == QKeySequence::Redo) { - if (!d->readOnly) - redo(); - } - else if (event == QKeySequence::SelectAll) { - selectAll(); - } -#ifndef QT_NO_CLIPBOARD - else if (event == QKeySequence::Copy) { - copy(); - } - else if (event == QKeySequence::Paste) { - if (!d->readOnly) - paste(); - } - else if (event == QKeySequence::Cut) { - if (!d->readOnly) { - cut(); - } - } - else if (event == QKeySequence::DeleteEndOfLine) { - if (!d->readOnly) { - setSelection(d->cursor, d->text.size()); - copy(); - del(); - } - } -#endif //QT_NO_CLIPBOARD - else if (event == QKeySequence::MoveToStartOfLine) { - home(0); - } - else if (event == QKeySequence::MoveToEndOfLine) { - end(0); - } - else if (event == QKeySequence::SelectStartOfLine) { - home(1); - } - else if (event == QKeySequence::SelectEndOfLine) { - end(1); - } - else if (event == QKeySequence::MoveToNextChar) { -#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) - if (d->hasSelectedText()) { -#else - if (d->hasSelectedText() && d->completer - && d->completer->completionMode() == QCompleter::InlineCompletion) { -#endif - d->moveCursor(d->selend, false); - } else { - cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - } - else if (event == QKeySequence::SelectNextChar) { - cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - else if (event == QKeySequence::MoveToPreviousChar) { -#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) - if (d->hasSelectedText()) { -#else - if (d->hasSelectedText() && d->completer - && d->completer->completionMode() == QCompleter::InlineCompletion) { -#endif - d->moveCursor(d->selstart, false); - } else { - cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - } - else if (event == QKeySequence::SelectPreviousChar) { - cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - else if (event == QKeySequence::MoveToNextWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0); - else - layoutDirection() == Qt::LeftToRight ? end(0) : home(0); - } - else if (event == QKeySequence::MoveToPreviousWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0); - else if (!d->readOnly) { - layoutDirection() == Qt::LeftToRight ? home(0) : end(0); - } - } - else if (event == QKeySequence::SelectNextWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1); - else - layoutDirection() == Qt::LeftToRight ? end(1) : home(1); - } - else if (event == QKeySequence::SelectPreviousWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1); - else - layoutDirection() == Qt::LeftToRight ? home(1) : end(1); - } - else if (event == QKeySequence::Delete) { - if (!d->readOnly) - del(); - } - else if (event == QKeySequence::DeleteEndOfWord) { - if (!d->readOnly) { - cursorWordForward(true); - del(); - } - } - else if (event == QKeySequence::DeleteStartOfWord) { - if (!d->readOnly) { - cursorWordBackward(true); - del(); - } - } -#endif // QT_NO_SHORTCUT - else { -#ifdef Q_WS_MAC - if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) { - Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier); - if (myModifiers & Qt::ShiftModifier) { - if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier) - || myModifiers == (Qt::AltModifier|Qt::ShiftModifier) - || myModifiers == Qt::ShiftModifier) { - - event->key() == Qt::Key_Up ? home(1) : end(1); - } - } else { - if ((myModifiers == Qt::ControlModifier - || myModifiers == Qt::AltModifier - || myModifiers == Qt::NoModifier)) { - event->key() == Qt::Key_Up ? home(0) : end(0); - } - } - } -#endif - if (event->modifiers() & Qt::ControlModifier) { - switch (event->key()) { - case Qt::Key_Backspace: - if (!d->readOnly) { - cursorWordBackward(true); - del(); - } - break; -#ifndef QT_NO_COMPLETER - case Qt::Key_Up: - case Qt::Key_Down: - d->complete(event->key()); - break; -#endif -#if defined(Q_WS_X11) - case Qt::Key_E: - end(0); - break; - - case Qt::Key_U: - if (!d->readOnly) { - setSelection(0, d->text.size()); -#ifndef QT_NO_CLIPBOARD - copy(); -#endif - del(); - } - break; -#endif - default: - unknown = true; - } - } else { // ### check for *no* modifier - switch (event->key()) { - case Qt::Key_Backspace: - if (!d->readOnly) { - backspace(); -#ifndef QT_NO_COMPLETER - d->complete(Qt::Key_Backspace); -#endif - } - break; -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() - && !isReadOnly()) { - if (text().length() == 0) { - setText(d->origText); - - if (d->passwordEchoEditing) - d->updatePasswordEchoEditing(false); - - setEditFocus(false); - } else if (!d->deleteAllTimer.isActive()) { - d->deleteAllTimer.start(750, this); - } - } else { - unknown = true; - } - break; -#endif - - default: - unknown = true; - } - } - } - - if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) { - setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); - d->updateTextLayout(); - update(); - unknown = false; - } - - if (unknown && !d->readOnly) { - QString t = event->text(); - if (!t.isEmpty() && t.at(0).isPrint() && - ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { - insert(t); -#ifndef QT_NO_COMPLETER - d->complete(event->key()); -#endif - event->accept(); - return; - } - } - - if (unknown) - event->ignore(); - else - event->accept(); + d->control->processKeyEvent(event); } /*! @@ -2197,50 +1575,17 @@ QRect QLineEdit::cursorRect() const return d->cursorRect(); } -/*! - This function is not intended as polymorphic usage. Just a shared code - fragment that calls QInputContext::mouseHandler for this - class. -*/ -bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e ) -{ -#if !defined QT_NO_IM - Q_Q(QLineEdit); - if ( composeMode() ) { - int tmp_cursor = xToPos(e->pos().x()); - int mousePos = tmp_cursor - cursor; - if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) { - mousePos = -1; - // don't send move events outside the preedit area - if ( e->type() == QEvent::MouseMove ) - return true; - } - - QInputContext *qic = q->inputContext(); - if ( qic ) - // may be causing reset() in some input methods - qic->mouseHandler(mousePos, e); - if (!textLayout.preeditAreaText().isEmpty()) - return true; - } -#else - Q_UNUSED(e); -#endif - - return false; -} - /*! \reimp */ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) { Q_D(QLineEdit); - if (d->readOnly) { + if (d->control->isReadOnly()) { e->ignore(); return; } - if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) { + if (echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing()) { // Clear the edit and reset to normal echo mode while entering input // method data; the echo mode switches back when the edit loses focus. // ### changes a public property, resets current content. @@ -2248,6 +1593,8 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) clear(); } + d->control->processInputMethodEvent(e); + #ifdef QT_KEYPAD_NAVIGATION // Focus in if currently in navigation focus on the widget // Only focus in on preedits, to allow input methods to @@ -2260,55 +1607,9 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) } #endif - int priorState = d->undoState; - d->removeSelectedText(); - - int c = d->cursor; // cursor position after insertion of commit string - if (e->replacementStart() <= 0) - c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength()); - - d->cursor += e->replacementStart(); - - // insert commit string - if (e->replacementLength()) { - d->selstart = d->cursor; - d->selend = d->selstart + e->replacementLength(); - d->removeSelectedText(); - } - if (!e->commitString().isEmpty()) - d->insert(e->commitString()); - - d->cursor = qMin(c, d->text.length()); - - d->textLayout.setPreeditArea(d->cursor, e->preeditString()); - d->preeditCursor = e->preeditString().length(); - d->hideCursor = false; - QList formats; - for (int i = 0; i < e->attributes().size(); ++i) { - const QInputMethodEvent::Attribute &a = e->attributes().at(i); - if (a.type == QInputMethodEvent::Cursor) { - d->preeditCursor = a.start; - d->hideCursor = !a.length; - } else if (a.type == QInputMethodEvent::TextFormat) { - QTextCharFormat f = qvariant_cast(a.value).toCharFormat(); - if (f.isValid()) { - QTextLayout::FormatRange o; - o.start = a.start + d->cursor; - o.length = a.length; - o.format = f; - formats.append(o); - } - } - } - d->textLayout.setAdditionalFormats(formats); - d->updateTextLayout(); - update(); - if (!e->commitString().isEmpty()) - d->emitCursorPositionChanged(); - d->finishChange(priorState); #ifndef QT_NO_COMPLETER if (!e->commitString().isEmpty()) - d->complete(Qt::Key_unknown); + d->control->complete(Qt::Key_unknown); #endif } @@ -2323,9 +1624,9 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const case Qt::ImFont: return font(); case Qt::ImCursorPosition: - return QVariant((d->selend - d->selstart == 0) ? d->cursor : d->selend); + return QVariant(d->control->hasSelectedText() ? d->control->selectionEnd() : d->control->cursor()); case Qt::ImSurroundingText: - return QVariant(d->text); + return QVariant(text()); case Qt::ImCurrentSelection: return QVariant(selectedText()); default: @@ -2342,36 +1643,34 @@ void QLineEdit::focusInEvent(QFocusEvent *e) if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason || e->reason() == Qt::ShortcutFocusReason) { - if (d->maskData) - d->moveCursor(d->nextMaskBlank(0)); - else if (!d->hasSelectedText()) + if (!d->control->inputMask().isEmpty()) + d->control->moveCursor(d->control->nextMaskBlank(0)); + else if (!d->control->hasSelectedText()) selectAll(); } #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason)) #endif - if (!d->cursorTimer) { - int cft = QApplication::cursorFlashTime(); - d->cursorTimer = cft ? startTimer(cft/2) : -1; - } + int cft = QApplication::cursorFlashTime(); + d->control->setCursorBlinkPeriod(cft/2); QStyleOptionFrameV2 opt; initStyleOption(&opt); - if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty()) + if((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) d->setCursorVisible(true); #ifdef Q_WS_MAC - if (d->echoMode == Password || d->echoMode == NoEcho) + if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) qt_mac_secure_keyboard(true); #endif #ifdef QT_KEYPAD_NAVIGATION d->origText = d->text; #endif #ifndef QT_NO_COMPLETER - if (d->completer) { - d->completer->setWidget(this); - QObject::connect(d->completer, SIGNAL(activated(QString)), + if (d->control->completer()) { + d->control->completer()->setWidget(this); + QObject::connect(d->control->completer(), SIGNAL(activated(QString)), this, SLOT(setText(QString))); - QObject::connect(d->completer, SIGNAL(highlighted(QString)), + QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)), this, SLOT(_q_completionHighlighted(QString))); } #endif @@ -2384,7 +1683,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e) void QLineEdit::focusOutEvent(QFocusEvent *e) { Q_D(QLineEdit); - if (d->passwordEchoEditing) { + if (d->control->passwordEchoEditing()) { // Reset the echomode back to PasswordEchoOnEdit when the widget loses // focus. d->updatePasswordEchoEditing(false); @@ -2396,21 +1695,18 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) deselect(); d->setCursorVisible(false); - if (d->cursorTimer > 0) - killTimer(d->cursorTimer); - d->cursorTimer = 0; - + d->control->setCursorBlinkPeriod(0); #ifdef QT_KEYPAD_NAVIGATION // editingFinished() is already emitted on LeaveEditFocus if (!QApplication::keypadNavigationEnabled()) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (!d->emitingEditingFinished) { - if (hasAcceptableInput() || d->fixup()) { - d->emitingEditingFinished = true; + if (!d->control->emitingEditingFinished) { + if (hasAcceptableInput() || d->control->fixup()) { + d->control->emitingEditingFinished = true; emit editingFinished(); - d->emitingEditingFinished = false; + d->control->emitingEditingFinished = false; } } #ifdef QT3_SUPPORT @@ -2418,15 +1714,15 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif } #ifdef Q_WS_MAC - if (d->echoMode == Password || d->echoMode == NoEcho) + if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) qt_mac_secure_keyboard(false); #endif #ifdef QT_KEYPAD_NAVIGATION d->origText = QString(); #endif #ifndef QT_NO_COMPLETER - if (d->completer) { - QObject::disconnect(d->completer, 0, this, 0); + if (d->control->completer()) { + QObject::disconnect(d->control->completer(), 0, this, 0); } #endif update(); @@ -2456,24 +1752,19 @@ void QLineEdit::paintEvent(QPaintEvent *) Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment)); switch (va & Qt::AlignVertical_Mask) { case Qt::AlignBottom: - d->vscroll = r.y() + r.height() - fm.height() - verticalMargin; + d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin; break; case Qt::AlignTop: - d->vscroll = r.y() + verticalMargin; + d->vscroll = r.y() + d->verticalMargin; break; default: //center d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2; break; } - QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height()); - QTextLine line = d->textLayout.lineAt(0); + QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height()); - int cursor = d->cursor; - if (d->preeditCursor != -1) - cursor += d->preeditCursor; - // locate cursor position - int cix = qRound(line.cursorToX(cursor)); + int cix = qRound(d->control->cursorToX()); // horizontal scrolling. d->hscroll is the left indent from the beginning // of the text line to the left edge of lineRect. we update this value @@ -2483,7 +1774,7 @@ void QLineEdit::paintEvent(QPaintEvent *) // (cix). int minLB = qMax(0, -fm.minLeftBearing()); int minRB = qMax(0, -fm.minRightBearing()); - int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB; + int widthUsed = d->control->width() + minRB; if ((minLB + widthUsed) <= lineRect.width()) { // text fits in lineRect; use hscroll for alignment switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { @@ -2511,7 +1802,7 @@ void QLineEdit::paintEvent(QPaintEvent *) d->hscroll = widthUsed - lineRect.width() + 1; } // the y offset is there to keep the baseline constant in case we have script changes in the text. - QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent - fm.ascent()); + QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); // draw text, selections and cursors #ifndef QT_NO_STYLE_STYLESHEET @@ -2521,33 +1812,23 @@ void QLineEdit::paintEvent(QPaintEvent *) #endif p.setPen(pal.text().color()); - QVector selections; + int flags = QLineControl::DrawText; + #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || hasEditFocus()) #endif - if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) { - QTextLayout::FormatRange o; - if (d->selstart < d->selend) { - o.start = d->selstart; - o.length = d->selend - d->selstart; - o.format.setBackground(pal.brush(QPalette::Highlight)); - o.format.setForeground(pal.brush(QPalette::HighlightedText)); - } else { - // mask selection - o.start = d->cursor; - o.length = 1; - o.format.setBackground(pal.brush(QPalette::Text)); - o.format.setForeground(pal.brush(QPalette::Window)); - } - selections.append(o); - } + if (d->control->hasSelectedText() || (d->cursorVisible && !d->control->inputMask().isEmpty() && !d->control->isReadOnly())) + flags |= QLineControl::DrawSelections; // Asian users see an IM selection text as cursor on candidate // selection phase of input method, so the ordinary cursor should be // invisible if we have a preedit string. - d->textLayout.draw(&p, topLeft, selections, r); - if (d->cursorVisible && !d->readOnly && !d->hideCursor) - d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth)); + if (d->cursorVisible && !d->control->isReadOnly()) + flags |= QLineControl::DrawCursor; + + d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth)); + d->control->draw(&p, topLeft, r, flags); + } @@ -2557,12 +1838,11 @@ void QLineEdit::paintEvent(QPaintEvent *) void QLineEdit::dragMoveEvent(QDragMoveEvent *e) { Q_D(QLineEdit); - if (!d->readOnly && e->mimeData()->hasFormat(QLatin1String("text/plain"))) { + if (!d->control->isReadOnly() && e->mimeData()->hasFormat(QLatin1String("text/plain"))) { e->acceptProposedAction(); - d->cursor = d->xToPos(e->pos().x()); + d->control->moveCursor(d->xToPos(e->pos().x()), false); d->cursorVisible = true; update(); - d->emitCursorPositionChanged(); } } @@ -2588,13 +1868,14 @@ void QLineEdit::dropEvent(QDropEvent* e) Q_D(QLineEdit); QString str = e->mimeData()->text(); - if (!str.isNull() && !d->readOnly) { + if (!str.isNull() && !d->control->isReadOnly()) { if (e->source() == this && e->dropAction() == Qt::CopyAction) deselect(); - d->cursor =d->xToPos(e->pos().x()); - int selStart = d->cursor; - int oldSelStart = d->selstart; - int oldSelEnd = d->selend; + int cursorPos = d->xToPos(e->pos().x()); + int selStart = cursorPos; + int oldSelStart = d->control->selectionStart(); + int oldSelEnd = d->control->selectionEnd(); + d->control->moveCursor(cursorPos, false); d->cursorVisible = false; e->acceptProposedAction(); insert(str); @@ -2616,22 +1897,6 @@ void QLineEdit::dropEvent(QDropEvent* e) } } -void QLineEditPrivate::drag() -{ - Q_Q(QLineEdit); - dndTimer.stop(); - QMimeData *data = new QMimeData; - data->setText(q->selectedText()); - QDrag *drag = new QDrag(q); - drag->setMimeData(data); - Qt::DropAction action = drag->start(); - if (action == Qt::MoveAction && !readOnly && drag->target() != q) { - int priorState = undoState; - removeSelectedText(); - finishChange(priorState); - } -} - #endif // QT_NO_DRAGANDDROP #ifndef QT_NO_CONTEXTMENU @@ -2676,37 +1941,37 @@ QMenu *QLineEdit::createStandardContextMenu() popup->setObjectName(QLatin1String("qt_edit_menu")); QAction *action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo)); - action->setEnabled(d->isUndoAvailable()); + action->setEnabled(d->control->isUndoAvailable()); connect(action, SIGNAL(triggered()), SLOT(undo())); action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo)); - action->setEnabled(d->isRedoAvailable()); + action->setEnabled(d->control->isRedoAvailable()); connect(action, SIGNAL(triggered()), SLOT(redo())); popup->addSeparator(); #ifndef QT_NO_CLIPBOARD action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut)); - action->setEnabled(!d->readOnly && d->hasSelectedText() && d->echoMode == QLineEdit::Normal); + action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()); connect(action, SIGNAL(triggered()), SLOT(cut())); action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy)); - action->setEnabled(d->hasSelectedText() && d->echoMode == QLineEdit::Normal); + action->setEnabled(d->control->hasSelectedText()); connect(action, SIGNAL(triggered()), SLOT(copy())); action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste)); - action->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty()); + action->setEnabled(!d->control->isReadOnly() && !QApplication::clipboard()->text().isEmpty()); connect(action, SIGNAL(triggered()), SLOT(paste())); #endif action = popup->addAction(QLineEdit::tr("Delete")); - action->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText()); + action->setEnabled(!d->control->isReadOnly() && !d->control->text().isEmpty() && d->control->hasSelectedText()); connect(action, SIGNAL(triggered()), SLOT(_q_deleteSelected())); popup->addSeparator(); action = popup->addAction(QLineEdit::tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll)); - action->setEnabled(!d->text.isEmpty() && !d->allSelected()); + action->setEnabled(!d->control->text().isEmpty() && !d->control->allSelected()); d->selectAllAction = action; connect(action, SIGNAL(triggered()), SLOT(selectAll())); @@ -2720,9 +1985,9 @@ QMenu *QLineEdit::createStandardContextMenu() #endif #if defined(Q_WS_WIN) - if (!d->readOnly && qt_use_rtl_extensions) { + if (!d->control->isReadOnly() && qt_use_rtl_extensions) { #else - if (!d->readOnly) { + if (!d->control->isReadOnly()) { #endif popup->addSeparator(); QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup); @@ -2736,806 +2001,26 @@ QMenu *QLineEdit::createStandardContextMenu() void QLineEdit::changeEvent(QEvent *ev) { Q_D(QLineEdit); - if(ev->type() == QEvent::ActivationChange) { + switch(ev->type()) + { + case QEvent::ActivationChange: if (!palette().isEqual(QPalette::Active, QPalette::Inactive)) update(); - } else if (ev->type() == QEvent::FontChange - || ev->type() == QEvent::StyleChange - || ev->type() == QEvent::LayoutDirectionChange) { - d->updateTextLayout(); - } - QWidget::changeEvent(ev); -} - -void QLineEditPrivate::_q_handleWindowActivate() -{ - Q_Q(QLineEdit); - if (!q->hasFocus() && q->hasSelectedText()) - q->deselect(); -} - -void QLineEditPrivate::_q_deleteSelected() -{ - Q_Q(QLineEdit); - if (!hasSelectedText()) - return; - - int priorState = undoState; - q->resetInputContext(); - removeSelectedText(); - separate(); - finishChange(priorState); -} - -void QLineEditPrivate::init(const QString& txt) -{ - Q_Q(QLineEdit); -#ifndef QT_NO_CURSOR - q->setCursor(Qt::IBeamCursor); -#endif - q->setFocusPolicy(Qt::StrongFocus); - q->setAttribute(Qt::WA_InputMethodEnabled); - // Specifies that this widget can use more, but is able to survive on - // less, horizontal space; and is fixed vertically. - q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit)); - q->setBackgroundRole(QPalette::Base); - q->setAttribute(Qt::WA_KeyCompression); - q->setMouseTracking(true); - q->setAcceptDrops(true); - text = txt; - updateTextLayout(); - cursor = text.length(); - - q->setAttribute(Qt::WA_MacShowFocusRect); -} - -void QLineEditPrivate::updatePasswordEchoEditing(bool editing) -{ - Q_Q(QLineEdit); - passwordEchoEditing = editing; - q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q)); - updateTextLayout(); - q->update(); -} - -void QLineEditPrivate::updateTextLayout() -{ - // replace certain non-printable characters with spaces (to avoid - // drawing boxes when using fonts that don't have glyphs for such - // characters) - Q_Q(QLineEdit); - QString str = q->displayText(); - QChar* uc = str.data(); - for (int i = 0; i < (int)str.length(); ++i) { - if ((uc[i] < 0x20 && uc[i] != 0x09) - || uc[i] == QChar::LineSeparator - || uc[i] == QChar::ParagraphSeparator - || uc[i] == QChar::ObjectReplacementCharacter) - uc[i] = QChar(0x0020); - } - textLayout.setFont(q->font()); - textLayout.setText(str); - QTextOption option; - option.setTextDirection(q->layoutDirection()); - option.setFlags(QTextOption::IncludeTrailingSpaces); - textLayout.setTextOption(option); - - textLayout.beginLayout(); - QTextLine l = textLayout.createLine(); - textLayout.endLayout(); - ascent = qRound(l.ascent()); -} - -int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const -{ - QRect cr = adjustedContentsRect(); - x-= cr.x() - hscroll + horizontalMargin; - QTextLine l = textLayout.lineAt(0); - return l.xToCursor(x, betweenOrOn); -} - -QRect QLineEditPrivate::cursorRect() const -{ - Q_Q(const QLineEdit); - QRect cr = adjustedContentsRect(); - int cix = cr.x() - hscroll + horizontalMargin; - QTextLine l = textLayout.lineAt(0); - int c = cursor; - if (preeditCursor != -1) - c += preeditCursor; - cix += qRound(l.cursorToX(c)); - int ch = qMin(cr.height(), q->fontMetrics().height() + 1); - int w = q->style()->pixelMetric(QStyle::PM_TextCursorWidth); - return QRect(cix-5, vscroll, w + 9, ch); -} - -QRect QLineEditPrivate::adjustedContentsRect() const -{ - Q_Q(const QLineEdit); - QStyleOptionFrameV2 opt; - q->initStyleOption(&opt); - QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q); - r.setX(r.x() + leftTextMargin); - r.setY(r.y() + topTextMargin); - r.setRight(r.right() - rightTextMargin); - r.setBottom(r.bottom() - bottomTextMargin); - return r; -} - -bool QLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable -{ -#ifndef QT_NO_VALIDATOR - if (validator) { - QString textCopy = text; - int cursorCopy = cursor; - validator->fixup(textCopy); - if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { - if (textCopy != text || cursorCopy != cursor) - setText(textCopy, cursorCopy); - return true; - } - } -#endif - return false; -} - -void QLineEditPrivate::moveCursor(int pos, bool mark) -{ - Q_Q(QLineEdit); - if (pos != cursor) { - separate(); - if (maskData) - pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); - } - bool fullUpdate = mark || hasSelectedText(); - if (mark) { - int anchor; - if (selend > selstart && cursor == selstart) - anchor = selend; - else if (selend > selstart && cursor == selend) - anchor = selstart; - else - anchor = cursor; - selstart = qMin(anchor, pos); - selend = qMax(anchor, pos); - updateTextLayout(); - } else { - deselect(); - } - if (fullUpdate) { - cursor = pos; - q->update(); - } else { - setCursorVisible(false); - cursor = pos; - setCursorVisible(true); - if (!adjustedContentsRect().contains(cursorRect())) - q->update(); - } - QStyleOptionFrameV2 opt; - q->initStyleOption(&opt); - if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q)) - setCursorVisible(false); - if (mark || selDirty) { - selDirty = false; - emit q->selectionChanged(); - } - emitCursorPositionChanged(); -} - -void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited) -{ - Q_Q(QLineEdit); - bool lineDirty = selDirty; - if (textDirty) { - // do validation - bool wasValidInput = validInput; - validInput = true; -#ifndef QT_NO_VALIDATOR - if (validator) { - validInput = false; - QString textCopy = text; - int cursorCopy = cursor; - validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid); - if (validInput) { - if (text != textCopy) { - setText(textCopy, cursorCopy); - return; - } - cursor = cursorCopy; - } - } -#endif - if (validateFromState >= 0 && wasValidInput && !validInput) { - undo(validateFromState); - history.resize(undoState); - if (modifiedState > undoState) - modifiedState = -1; - validInput = true; - textDirty = false; - } - updateTextLayout(); - lineDirty |= textDirty; - if (textDirty) { - textDirty = false; - QString actualText = maskData ? stripString(text) : text; - if (edited) - emit q->textEdited(actualText); - q->updateMicroFocus(); -#ifndef QT_NO_COMPLETER - if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion) - complete(-1); // update the popup on cut/paste/del -#endif - emit q->textChanged(actualText); - } -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged); -#endif - } - if (selDirty) { - selDirty = false; - emit q->selectionChanged(); - } - if (lineDirty || update) - q->update(); - emitCursorPositionChanged(); -} - -void QLineEditPrivate::emitCursorPositionChanged() -{ - Q_Q(QLineEdit); - if (cursor != lastCursorPos) { - const int oldLast = lastCursorPos; - lastCursorPos = cursor; - emit q->cursorPositionChanged(oldLast, cursor); - } -} - -void QLineEditPrivate::setText(const QString& txt, int pos, bool edited) -{ - Q_Q(QLineEdit); - q->resetInputContext(); - deselect(); - QString oldText = text; - if (maskData) { - text = maskString(0, txt, true); - text += clearString(text.length(), maxLength - text.length()); - } else { - text = txt.isEmpty() ? txt : txt.left(maxLength); - } - history.clear(); - modifiedState = undoState = 0; - cursor = (pos < 0 || pos > text.length()) ? text.length() : pos; - textDirty = (oldText != text); - finishChange(-1, true, edited); -} - - -void QLineEditPrivate::setCursorVisible(bool visible) -{ - Q_Q(QLineEdit); - if ((bool)cursorVisible == visible) - return; - if (cursorTimer) - cursorVisible = visible; - QRect r = cursorRect(); - if (maskData) - q->update(); - else - q->update(r); -} - -void QLineEditPrivate::addCommand(const Command& cmd) -{ - if (separator && undoState && history[undoState-1].type != Separator) { - history.resize(undoState + 2); - history[undoState++] = Command(Separator, cursor, 0, selstart, selend); - } else { - history.resize(undoState + 1); - } - separator = false; - history[undoState++] = cmd; -} - -void QLineEditPrivate::insert(const QString& s) -{ - if (hasSelectedText()) - addCommand(Command(SetSelection, cursor, 0, selstart, selend)); - if (maskData) { - QString ms = maskString(cursor, s); - for (int i = 0; i < (int) ms.length(); ++i) { - addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i), -1, -1)); - addCommand(Command(Insert, cursor+i, ms.at(i), -1, -1)); - } - text.replace(cursor, ms.length(), ms); - cursor += ms.length(); - cursor = nextMaskBlank(cursor); - textDirty = true; - } else { - int remaining = maxLength - text.length(); - if (remaining != 0) { - text.insert(cursor, s.left(remaining)); - for (int i = 0; i < (int) s.left(remaining).length(); ++i) - addCommand(Command(Insert, cursor++, s.at(i), -1, -1)); - textDirty = true; - } - } -} - -void QLineEditPrivate::del(bool wasBackspace) -{ - if (cursor < (int) text.length()) { - if (hasSelectedText()) - addCommand(Command(SetSelection, cursor, 0, selstart, selend)); - addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor), -1, -1)); - if (maskData) { - text.replace(cursor, 1, clearString(cursor, 1)); - addCommand(Command(Insert, cursor, text.at(cursor), -1, -1)); - } else { - text.remove(cursor, 1); - } - textDirty = true; - } -} - -void QLineEditPrivate::removeSelectedText() -{ - if (selstart < selend && selend <= (int) text.length()) { - separate(); - int i ; - addCommand(Command(SetSelection, cursor, 0, selstart, selend)); - if (selstart <= cursor && cursor < selend) { - // cursor is within the selection. Split up the commands - // to be able to restore the correct cursor position - for (i = cursor; i >= selstart; --i) - addCommand (Command(DeleteSelection, i, text.at(i), -1, 1)); - for (i = selend - 1; i > cursor; --i) - addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i), -1, -1)); - } else { - for (i = selend-1; i >= selstart; --i) - addCommand (Command(RemoveSelection, i, text.at(i), -1, -1)); - } - if (maskData) { - text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); - for (int i = 0; i < selend - selstart; ++i) - addCommand(Command(Insert, selstart + i, text.at(selstart + i), -1, -1)); - } else { - text.remove(selstart, selend - selstart); - } - if (cursor > selstart) - cursor -= qMin(cursor, selend) - selstart; - deselect(); - textDirty = true; - - // adjust hscroll to avoid gap - const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing()); - updateTextLayout(); - const QTextLine line = textLayout.lineAt(0); - const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB; - hscroll = qMin(hscroll, widthUsed); - } -} - -void QLineEditPrivate::parseInputMask(const QString &maskFields) -{ - int delimiter = maskFields.indexOf(QLatin1Char(';')); - if (maskFields.isEmpty() || delimiter == 0) { - if (maskData) { - delete [] maskData; - maskData = 0; - maxLength = 32767; - setText(QString()); - } - return; - } - - if (delimiter == -1) { - blank = QLatin1Char(' '); - inputMask = maskFields; - } else { - inputMask = maskFields.left(delimiter); - blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); - } - - // calculate maxLength / maskData length - maxLength = 0; - QChar c = 0; - for (int i=0; i 0 && inputMask.at(i-1) == QLatin1Char('\\')) { - maxLength++; - continue; - } - if (c != QLatin1Char('\\') && c != QLatin1Char('!') && - c != QLatin1Char('<') && c != QLatin1Char('>') && - c != QLatin1Char('{') && c != QLatin1Char('}') && - c != QLatin1Char('[') && c != QLatin1Char(']')) - maxLength++; - } - - delete [] maskData; - maskData = new MaskInputData[maxLength]; - - MaskInputData::Casemode m = MaskInputData::NoCaseMode; - c = 0; - bool s; - bool escape = false; - int index = 0; - for (int i = 0; i < inputMask.length(); i++) { - c = inputMask.at(i); - if (escape) { - s = true; - maskData[index].maskChar = c; - maskData[index].separator = s; - maskData[index].caseMode = m; - index++; - escape = false; - } else if (c == QLatin1Char('<')) { - m = MaskInputData::Lower; - } else if (c == QLatin1Char('>')) { - m = MaskInputData::Upper; - } else if (c == QLatin1Char('!')) { - m = MaskInputData::NoCaseMode; - } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) { - switch (c.unicode()) { - case 'A': - case 'a': - case 'N': - case 'n': - case 'X': - case 'x': - case '9': - case '0': - case 'D': - case 'd': - case '#': - case 'H': - case 'h': - case 'B': - case 'b': - s = false; - break; - case '\\': - escape = true; - default: - s = true; - break; - } - - if (!escape) { - maskData[index].maskChar = c; - maskData[index].separator = s; - maskData[index].caseMode = m; - index++; - } - } - } - setText(text); -} - - -/* checks if the key is valid compared to the inputMask */ -bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const -{ - switch (mask.unicode()) { - case 'A': - if (key.isLetter()) - return true; - break; - case 'a': - if (key.isLetter() || key == blank) - return true; - break; - case 'N': - if (key.isLetterOrNumber()) - return true; - break; - case 'n': - if (key.isLetterOrNumber() || key == blank) - return true; - break; - case 'X': - if (key.isPrint()) - return true; - break; - case 'x': - if (key.isPrint() || key == blank) - return true; - break; - case '9': - if (key.isNumber()) - return true; - break; - case '0': - if (key.isNumber() || key == blank) - return true; - break; - case 'D': - if (key.isNumber() && key.digitValue() > 0) - return true; - break; - case 'd': - if ((key.isNumber() && key.digitValue() > 0) || key == blank) - return true; - break; - case '#': - if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) - return true; break; - case 'B': - if (key == QLatin1Char('0') || key == QLatin1Char('1')) - return true; + case QEvent::FontChange: + d->control->setFont(font()); break; - case 'b': - if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) - return true; + case QEvent::StyleChange: + d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter)); + update(); break; - case 'H': - if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F'))) - return true; - break; - case 'h': - if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) - return true; + case QEvent::LayoutDirectionChange: + d->control->setLayoutDirection(layoutDirection()); break; default: break; } - return false; -} - -bool QLineEditPrivate::hasAcceptableInput(const QString &str) const -{ -#ifndef QT_NO_VALIDATOR - QString textCopy = str; - int cursorCopy = cursor; - if (validator && validator->validate(textCopy, cursorCopy) - != QValidator::Acceptable) - return false; -#endif - - if (!maskData) - return true; - - if (str.length() != maxLength) - return false; - - for (int i=0; i < maxLength; ++i) { - if (maskData[i].separator) { - if (str.at(i) != maskData[i].maskChar) - return false; - } else { - if (!isValidInput(str.at(i), maskData[i].maskChar)) - return false; - } - } - return true; -} - -/* - Applies the inputMask on \a str starting from position \a pos in the mask. \a clear - specifies from where characters should be gotten when a separator is met in \a str - true means - that blanks will be used, false that previous input is used. - Calling this when no inputMask is set is undefined. -*/ -QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const -{ - if (pos >= (uint)maxLength) - return QString::fromLatin1(""); - - QString fill; - fill = clear ? clearString(0, maxLength) : text; - - int strIndex = 0; - QString s = QString::fromLatin1(""); - int i = pos; - while (i < maxLength) { - if (strIndex < str.length()) { - if (maskData[i].separator) { - s += maskData[i].maskChar; - if (str[(int)strIndex] == maskData[i].maskChar) - strIndex++; - ++i; - } else { - if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { - switch (maskData[i].caseMode) { - case MaskInputData::Upper: - s += str[(int)strIndex].toUpper(); - break; - case MaskInputData::Lower: - s += str[(int)strIndex].toLower(); - break; - default: - s += str[(int)strIndex]; - } - ++i; - } else { - // search for separator first - int n = findInMask(i, true, true, str[(int)strIndex]); - if (n != -1) { - if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { - s += fill.mid(i, n-i+1); - i = n + 1; // update i to find + 1 - } - } else { - // search for valid blank if not - n = findInMask(i, true, false, str[(int)strIndex]); - if (n != -1) { - s += fill.mid(i, n-i); - switch (maskData[n].caseMode) { - case MaskInputData::Upper: - s += str[(int)strIndex].toUpper(); - break; - case MaskInputData::Lower: - s += str[(int)strIndex].toLower(); - break; - default: - s += str[(int)strIndex]; - } - i = n + 1; // updates i to find + 1 - } - } - } - strIndex++; - } - } else - break; - } - - return s; -} - - - -/* - Returns a "cleared" string with only separators and blank chars. - Calling this when no inputMask is set is undefined. -*/ -QString QLineEditPrivate::clearString(uint pos, uint len) const -{ - if (pos >= (uint)maxLength) - return QString(); - - QString s; - int end = qMin((uint)maxLength, pos + len); - for (int i=pos; i= maxLength || pos < 0) - return -1; - - int end = forward ? maxLength : -1; - int step = forward ? 1 : -1; - int i = pos; - - while (i != end) { - if (findSeparator) { - if (maskData[i].separator && maskData[i].maskChar == searchChar) - return i; - } else { - if (!maskData[i].separator) { - if (searchChar.isNull()) - return i; - else if (isValidInput(searchChar, maskData[i].maskChar)) - return i; - } - } - i += step; - } - return -1; -} - -void QLineEditPrivate::undo(int until) -{ - if (!isUndoAvailable()) - return; - deselect(); - while (undoState && undoState > until) { - Command& cmd = history[--undoState]; - switch (cmd.type) { - case Insert: - text.remove(cmd.pos, 1); - cursor = cmd.pos; - break; - case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - case Remove: - case RemoveSelection: - text.insert(cmd.pos, cmd.uc); - cursor = cmd.pos + 1; - break; - case Delete: - case DeleteSelection: - text.insert(cmd.pos, cmd.uc); - cursor = cmd.pos; - break; - case Separator: - continue; - } - if (until < 0 && undoState) { - Command& next = history[undoState-1]; - if (next.type != cmd.type && next.type < RemoveSelection - && (cmd.type < RemoveSelection || next.type == Separator)) - break; - } - } - textDirty = true; - emitCursorPositionChanged(); -} - -void QLineEditPrivate::redo() { - if (!isRedoAvailable()) - return; - deselect(); - while (undoState < (int)history.size()) { - Command& cmd = history[undoState++]; - switch (cmd.type) { - case Insert: - text.insert(cmd.pos, cmd.uc); - cursor = cmd.pos + 1; - break; - case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - case Remove: - case Delete: - case RemoveSelection: - case DeleteSelection: - text.remove(cmd.pos, 1); - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - case Separator: - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - } - if (undoState < (int)history.size()) { - Command& next = history[undoState]; - if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator - && (next.type < RemoveSelection || cmd.type == Separator)) - break; - } - } - textDirty = true; - emitCursorPositionChanged(); + QWidget::changeEvent(ev); } /*! diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h index a97dc9a..daac6a7 100644 --- a/src/gui/widgets/qlineedit.h +++ b/src/gui/widgets/qlineedit.h @@ -268,6 +268,8 @@ private: Q_DECLARE_PRIVATE(QLineEdit) Q_PRIVATE_SLOT(d_func(), void _q_handleWindowActivate()) Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected()) + Q_PRIVATE_SLOT(d_func(), void _q_textEdited(const QString &)) + Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged(int, int)) #ifndef QT_NO_COMPLETER Q_PRIVATE_SLOT(d_func(), void _q_completionHighlighted(QString)) #endif diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp new file mode 100644 index 0000000..0e39304 --- /dev/null +++ b/src/gui/widgets/qlineedit_p.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlineedit.h" +#include "qlineedit_p.h" + +#ifndef QT_NO_LINEEDIT + +#include "qabstractitemview.h" +#include "qclipboard.h" +#ifndef QT_NO_ACCESSIBILITY +#include "qaccessible.h" +#endif +#ifndef QT_NO_IM +#include "qinputcontext.h" +#include "qlist.h" +#endif + +QT_BEGIN_NAMESPACE + +const int QLineEditPrivate::verticalMargin(1); +const int QLineEditPrivate::horizontalMargin(2); + +int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const +{ + QRect cr = adjustedContentsRect(); + x-= cr.x() - hscroll + horizontalMargin; + return control->xToPos(x, betweenOrOn); +} + +QRect QLineEditPrivate::cursorRect() const +{ + QRect cr = adjustedContentsRect(); + int cix = cr.x() - hscroll + horizontalMargin; + QRect crect = control->cursorRect(); + crect.moveTo(crect.topLeft() + QPoint(cix, vscroll)); + return crect; +} + +#ifndef QT_NO_COMPLETER + +void QLineEditPrivate::_q_completionHighlighted(QString newText) +{ + Q_Q(QLineEdit); + if (control->completer()->completionMode() != QCompleter::InlineCompletion) { + q->setText(newText); + } else { + int c = control->cursor(); + QString text = control->text(); + q->setText(text.left(c) + newText.mid(c)); + control->moveCursor(control->end(), false); + control->moveCursor(c, true); + } +} + +#endif // QT_NO_COMPLETER + +void QLineEditPrivate::_q_clipboardChanged() +{ +} + +void QLineEditPrivate::_q_handleWindowActivate() +{ + Q_Q(QLineEdit); + if (!q->hasFocus() && control->hasSelectedText()) + control->deselect(); +} + +void QLineEditPrivate::_q_deleteSelected() +{ +} + +void QLineEditPrivate::_q_textEdited(const QString &text) +{ + Q_Q(QLineEdit); +#ifndef QT_NO_COMPLETER + if (control->completer() && + control->completer()->completionMode() != QCompleter::InlineCompletion) + control->complete(-1); // update the popup on cut/paste/del +#endif + emit q->textEdited(text); +} + +void QLineEditPrivate::_q_cursorPositionChanged(int from, int to) +{ + Q_Q(QLineEdit); + q->update(); + emit q->cursorPositionChanged(from, to); +} + +void QLineEditPrivate::init(const QString& txt) +{ + Q_Q(QLineEdit); + control = new QLineControl(txt); + QObject::connect(control, SIGNAL(textChanged(const QString &)), + q, SIGNAL(textChanged(const QString &))); + QObject::connect(control, SIGNAL(textEdited(const QString &)), + q, SLOT(_q_textEdited(const QString &))); + QObject::connect(control, SIGNAL(cursorPositionChanged(int, int)), + q, SLOT(_q_cursorPositionChanged(int, int))); + QObject::connect(control, SIGNAL(selectionChanged()), + q, SIGNAL(selectionChanged())); + QObject::connect(control, SIGNAL(accepted()), + q, SIGNAL(returnPressed())); + QObject::connect(control, SIGNAL(editingFinished()), + q, SIGNAL(editingFinished())); + + // for now, going completely overboard with updates. + QObject::connect(control, SIGNAL(selectionChanged()), + q, SLOT(update())); + + QObject::connect(control, SIGNAL(displayTextChanged(const QString &)), + q, SLOT(update())); + control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter)); +#ifndef QT_NO_CURSOR + q->setCursor(Qt::IBeamCursor); +#endif + q->setFocusPolicy(Qt::StrongFocus); + q->setAttribute(Qt::WA_InputMethodEnabled); + // Specifies that this widget can use more, but is able to survive on + // less, horizontal space; and is fixed vertically. + q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit)); + q->setBackgroundRole(QPalette::Base); + q->setAttribute(Qt::WA_KeyCompression); + q->setMouseTracking(true); + q->setAcceptDrops(true); + + q->setAttribute(Qt::WA_MacShowFocusRect); +} + +QRect QLineEditPrivate::adjustedContentsRect() const +{ + Q_Q(const QLineEdit); + QStyleOptionFrameV2 opt; + q->initStyleOption(&opt); + QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q); + r.setX(r.x() + leftTextMargin); + r.setY(r.y() + topTextMargin); + r.setRight(r.right() - rightTextMargin); + r.setBottom(r.bottom() - bottomTextMargin); + return r; +} + +void QLineEditPrivate::setCursorVisible(bool visible) +{ + Q_Q(QLineEdit); + if ((bool)cursorVisible == visible) + return; + cursorVisible = visible; + QRect r = cursorRect(); + if (control->inputMask().isEmpty()) + q->update(r); + else + q->update(); +} + +void QLineEditPrivate::updatePasswordEchoEditing(bool editing) +{ + Q_Q(QLineEdit); + control->updatePasswordEchoEditing(editing); + q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod()); +} + +/*! + This function is not intended as polymorphic usage. Just a shared code + fragment that calls QInputContext::mouseHandler for this + class. +*/ +bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e ) +{ +#if !defined QT_NO_IM + Q_Q(QLineEdit); + if ( control->composeMode() ) { + int tmp_cursor = xToPos(e->pos().x()); + int mousePos = tmp_cursor - control->cursor(); + if ( mousePos < 0 || mousePos > control->preeditAreaText().length() ) { + mousePos = -1; + // don't send move events outside the preedit area + if ( e->type() == QEvent::MouseMove ) + return true; + } + + QInputContext *qic = q->inputContext(); + if ( qic ) + // may be causing reset() in some input methods + qic->mouseHandler(mousePos, e); + if (!control->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(e); +#endif + + return false; +} + +#ifndef QT_NO_DRAGANDDROP +void QLineEditPrivate::drag() +{ + Q_Q(QLineEdit); + dndTimer.stop(); + QMimeData *data = new QMimeData; + data->setText(control->selectedText()); + QDrag *drag = new QDrag(q); + drag->setMimeData(data); + Qt::DropAction action = drag->start(); + if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q) + control->removeSelection(); +} + +#endif // QT_NO_DRAGANDDROP + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index 7a4ff26..c6d7496 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -65,6 +65,8 @@ #include "QtCore/qpointer.h" #include "QtGui/qlineedit.h" +#include "private/qlinecontrol_p.h" + QT_BEGIN_NAMESPACE class QLineEditPrivate : public QWidgetPrivate @@ -73,168 +75,66 @@ class QLineEditPrivate : public QWidgetPrivate public: QLineEditPrivate() - : cursor(0), preeditCursor(0), cursorTimer(0), frame(1), - cursorVisible(0), hideCursor(false), separator(0), readOnly(0), - dragEnabled(0), contextMenuEnabled(1), echoMode(0), textDirty(0), - selDirty(0), validInput(1), alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0), - maxLength(32767), hscroll(0), vscroll(0), lastCursorPos(-1), maskData(0), - modifiedState(0), undoState(0), selstart(0), selend(0), userInput(false), - emitingEditingFinished(false), passwordEchoEditing(false) -#ifndef QT_NO_COMPLETER - , completer(0) -#endif - , leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0) - { - } + : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0), + dragEnabled(0), hscroll(0), vscroll(0), + alignment(Qt::AlignLeading | Qt::AlignVCenter), + leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0) + { + } ~QLineEditPrivate() { - delete [] maskData; } + + QLineControl *control; + +#ifndef QT_NO_CONTEXTMENU + QPointer selectAllAction; +#endif void init(const QString&); - QString text; - int cursor; - int preeditCursor; - int cursorTimer; // -1 for non blinking cursor. + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; + QRect cursorRect() const; + void setCursorVisible(bool visible); + + void updatePasswordEchoEditing(bool); + + inline bool shouldEnableInputMethod() const + { + return !control->isReadOnly() && (control->echoMode() == QLineEdit::Normal || control->echoMode() == QLineEdit::PasswordEchoOnEdit); + } + QPoint tripleClick; QBasicTimer tripleClickTimer; uint frame : 1; + uint contextMenuEnabled : 1; uint cursorVisible : 1; - uint hideCursor : 1; // used to hide the cursor inside preedit areas - uint separator : 1; - uint readOnly : 1; uint dragEnabled : 1; - uint contextMenuEnabled : 1; - uint echoMode : 2; - uint textDirty : 1; - uint selDirty : 1; - uint validInput : 1; - uint alignment; - int ascent; - int maxLength; int hscroll; int vscroll; - int lastCursorPos; - -#ifndef QT_NO_CONTEXTMENU - QPointer selectAllAction; -#endif + uint alignment; + static const int verticalMargin; + static const int horizontalMargin; - inline void emitCursorPositionChanged(); bool sendMouseEventToInputContext(QMouseEvent *e); - void finishChange(int validateFromState = -1, bool update = false, bool edited = true); - - QPointer validator; - struct MaskInputData { - enum Casemode { NoCaseMode, Upper, Lower }; - QChar maskChar; // either the separator char or the inputmask - bool separator; - Casemode caseMode; - }; - QString inputMask; - QChar blank; - MaskInputData *maskData; - inline int nextMaskBlank(int pos) { - int c = findInMask(pos, true, false); - separator |= (c != pos); - return (c != -1 ? c : maxLength); - } - inline int prevMaskBlank(int pos) { - int c = findInMask(pos, false, false); - separator |= (c != pos); - return (c != -1 ? c : 0); - } - - void setCursorVisible(bool visible); + QRect adjustedContentsRect() const; + void _q_clipboardChanged(); + void _q_handleWindowActivate(); + void _q_deleteSelected(); + void _q_textEdited(const QString &); + void _q_cursorPositionChanged(int, int); - // undo/redo handling - enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; - struct Command { - inline Command() {} - inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} - uint type : 4; - QChar uc; - int pos, selStart, selEnd; - }; - int modifiedState; - int undoState; - QVector history; - void addCommand(const Command& cmd); - void insert(const QString& s); - void del(bool wasBackspace = false); - void remove(int pos); - - inline void separate() { separator = true; } - void undo(int until = -1); - void redo(); - inline bool isUndoAvailable() const { return !readOnly && undoState; } - inline bool isRedoAvailable() const { return !readOnly && undoState < (int)history.size(); } - - // selection - int selstart, selend; - inline bool allSelected() const { return !text.isEmpty() && selstart == 0 && selend == (int)text.length(); } - inline bool hasSelectedText() const { return !text.isEmpty() && selend > selstart; } - inline void deselect() { selDirty |= (selend > selstart); selstart = selend = 0; } - void removeSelectedText(); -#ifndef QT_NO_CLIPBOARD - void copy(bool clipboard = true) const; +#ifndef QT_NO_COMPLETER + void _q_completionHighlighted(QString); #endif - inline bool inSelection(int x) const - { if (selstart >= selend) return false; - int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; } - - // masking - void parseInputMask(const QString &maskFields); - bool isValidInput(QChar key, QChar mask) const; - bool hasAcceptableInput(const QString &text) const; - QString maskString(uint pos, const QString &str, bool clear = false) const; - QString clearString(uint pos, uint len) const; - QString stripString(const QString &str) const; - int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; - - // input methods - bool composeMode() const { return !textLayout.preeditAreaText().isEmpty(); } - - // complex text layout - QTextLayout textLayout; - void updateTextLayout(); - void moveCursor(int pos, bool mark = false); - void setText(const QString& txt, int pos = -1, bool edited = true); - int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; - QRect cursorRect() const; - bool fixup(); - - QRect adjustedContentsRect() const; - #ifndef QT_NO_DRAGANDDROP - // drag and drop QPoint dndPos; QBasicTimer dndTimer; void drag(); #endif - void _q_handleWindowActivate(); - void _q_deleteSelected(); - bool userInput; - bool emitingEditingFinished; - -#ifdef QT_KEYPAD_NAVIGATION - QBasicTimer deleteAllTimer; // keypad navigation - QString origText; -#endif - - bool passwordEchoEditing; - void updatePasswordEchoEditing(bool editing); - -#ifndef QT_NO_COMPLETER - QPointer completer; - void complete(int key = -1); - void _q_completionHighlighted(QString); - bool advanceToEnabledItem(int n); -#endif int leftTextMargin; int topTextMargin; diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h index ce78959..5ddc44e 100644 --- a/src/gui/widgets/qvalidator.h +++ b/src/gui/widgets/qvalidator.h @@ -61,7 +61,7 @@ class Q_GUI_EXPORT QValidator : public QObject { Q_OBJECT public: - explicit QValidator(QObject * parent); + explicit QValidator(QObject * parent=0); ~QValidator(); enum State { @@ -100,7 +100,7 @@ class Q_GUI_EXPORT QIntValidator : public QValidator Q_PROPERTY(int top READ top WRITE setTop) public: - explicit QIntValidator(QObject * parent); + explicit QIntValidator(QObject * parent=0); QIntValidator(int bottom, int top, QObject * parent); ~QIntValidator(); @@ -120,7 +120,7 @@ public: #endif private: - Q_DISABLE_COPY(QIntValidator) + /*Q_DISABLE_COPY(QIntValidator)*/ int b; int t; diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index 2d809a1..8f24fac 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -30,6 +30,7 @@ HEADERS += \ widgets/qlcdnumber.h \ widgets/qlineedit.h \ widgets/qlineedit_p.h \ + widgets/qlinecontrol_p.h \ widgets/qmainwindow.h \ widgets/qmainwindowlayout_p.h \ widgets/qmdiarea.h \ @@ -101,7 +102,9 @@ SOURCES += \ widgets/qgroupbox.cpp \ widgets/qlabel.cpp \ widgets/qlcdnumber.cpp \ + widgets/qlineedit_p.cpp \ widgets/qlineedit.cpp \ + widgets/qlinecontrol.cpp \ widgets/qmainwindow.cpp \ widgets/qmainwindowlayout.cpp \ widgets/qmdiarea.cpp \ -- cgit v0.12 From 043a9b2eb3dd346126cf13817b67ed0790a72f7a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 17:45:56 +1000 Subject: Manually integrate 099a32d121 to QLineControl This change to QLineEdit didn't merge, as it needs to be applied to QLineControl in this case. --- src/gui/widgets/qlinecontrol.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index b762a00..08574b5 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1685,7 +1685,8 @@ void QLineControl::processKeyEvent(QKeyEvent* event) if (unknown && !isReadOnly()) { QString t = event->text(); - if (!t.isEmpty() && t.at(0).isPrint()) { + if (!t.isEmpty() && t.at(0).isPrint() && + ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { insert(t); #ifndef QT_NO_COMPLETER complete(event->key()); -- cgit v0.12 From 96d3be9039baaebc64f5de5d6917dd56d7ed192b Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 18:13:18 +1000 Subject: Finish remaining TODOs for QLineControl Didn't notice there were still some TODO markers left. They have now all been done. --- src/gui/widgets/qlinecontrol.cpp | 16 +++++++--------- src/gui/widgets/qlinecontrol_p.h | 14 ++++++++++++++ src/gui/widgets/qlineedit.cpp | 4 ++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 08574b5..fc0a173 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1232,7 +1232,6 @@ bool QLineControl::processEvent(QEvent* ev) return true; } } - //TODO: Needs a call to processKeyEvent? } else if (e->type() == QEvent::EnterEditFocus) { end(false); int cft = QApplication::cursorFlashTime(); @@ -1450,11 +1449,10 @@ void QLineControl::processKeyEvent(QKeyEvent* event) // ### resets current content. dubious code; you can // navigate with keys up, down, back, and select(?), but if you press // "left" or "right" it clears? - updatePasswordEchoEditing(true);//TODO: used to set a WA too + updatePasswordEchoEditing(true); clear(); } - //setCursorVisible(true);TODO: Who handles this? if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput() || fixup()) { emit accepted(); @@ -1652,19 +1650,19 @@ void QLineControl::processKeyEvent(QKeyEvent* event) #endif } break; -#ifdef QT_KEYPAD_NAVIGATION//TODO: This section +#ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Back: if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() && !isReadOnly()) { if (text().length() == 0) { - setText(d->origText); + setText(m_cancelText); - if (d->passwordEchoEditing) - d->updatePasswordEchoEditing(false); + if (passwordEchoEditing) + updatePasswordEchoEditing(false); setEditFocus(false); - } else if (!d->deleteAllTimer.isActive()) { - d->deleteAllTimer.start(750, this); + } else if (!deleteAllTimer) { + deleteAllTimer = startTimer(750); } } else { unknown = true; diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index bb27778..600206d 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -217,6 +217,9 @@ public: int cursorBlinkPeriod() const; void setCursorBlinkPeriod(int msec); + QString cancelText() const; + void setCancelText(QString); + enum DrawFlags { DrawText = 0x01, DrawSelections = 0x02, @@ -265,6 +268,7 @@ private: QList transactions; QPoint m_tripleClick; int m_tripleClickTimer; + QString m_cancelText; void emitCursorPositionChanged(); @@ -706,6 +710,16 @@ inline int QLineControl::cursorBlinkPeriod() const return m_blinkPeriod; } +QString QLineControl::cancelText() const +{ + return m_cancelText; +} + +void QLineControl::setCancelText(QString s) +{ + m_cancelText = s; +} + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index baaad32..7fdda6c 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1663,7 +1663,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e) qt_mac_secure_keyboard(true); #endif #ifdef QT_KEYPAD_NAVIGATION - d->origText = d->text; + d->control->setCancelText(d->text); #endif #ifndef QT_NO_COMPLETER if (d->control->completer()) { @@ -1718,7 +1718,7 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) qt_mac_secure_keyboard(false); #endif #ifdef QT_KEYPAD_NAVIGATION - d->origText = QString(); + d->control->setCancelText(QString()); #endif #ifndef QT_NO_COMPLETER if (d->control->completer()) { -- cgit v0.12 From fe6ca9332cf4516c84d9a1b8ca9ea2846458f98f Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 18:28:54 +1000 Subject: Forgot to bring in the change to QAbstractSpinBox QAbstractSpinBox had some code using QLineEdit internals, this had to be move to use QLineControl as well. This commit also includes fixing some typos in my last commit. --- src/gui/widgets/qabstractspinbox.cpp | 2 +- src/gui/widgets/qlinecontrol_p.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index 25acd6e..1d62ab4 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -970,7 +970,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) #endif case Qt::Key_Enter: case Qt::Key_Return: - d->edit->d_func()->modifiedState = d->edit->d_func()->undoState = 0; + d->edit->d_func()->control->clearUndo(); d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged); selectAll(); event->ignore(); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 600206d..4ecedcd 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -710,12 +710,12 @@ inline int QLineControl::cursorBlinkPeriod() const return m_blinkPeriod; } -QString QLineControl::cancelText() const +inline QString QLineControl::cancelText() const { return m_cancelText; } -void QLineControl::setCancelText(QString s) +inline void QLineControl::setCancelText(QString s) { m_cancelText = s; } -- cgit v0.12 From 3528101647e7320d07623e659138005d7d603980 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 8 Jul 2009 15:54:33 +1000 Subject: Fixed one of the QT3_SUPPORT constructors. It was accidentally left commented out instead of working with QLineControl. --- src/gui/widgets/qlineedit.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 7fdda6c..8e7fdec 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -341,14 +341,9 @@ QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget* { Q_D(QLineEdit); setObjectName(QString::fromAscii(name)); - //d->control->parseInputMask(inputMask); - //if (d->control->maskData) { - // QString ms = d->control->maskString(0, contents); - // d->init(ms + d->control->clearString(ms.length(), d->control->maxLength() - ms.length())); - // d->control->moveCursor(d->control->nextMaskBlank(ms.length())); - // } else { - d->init(contents); - // } + d->init(contents); + d->control->setInputMask(inputMask); + d->control->moveCursor(d->control->nextMaskBlank(contents.length())); } #endif -- cgit v0.12 From b9fc86cd9f51c80a1103e5e896940b49bf552b07 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 9 Jul 2009 09:47:18 +1000 Subject: Accidental Behavioural changes have been identified and rectified. createStandardContextMenu should still only cut/copy in normal echo mode and the Qt3Support function validateAndSet will again only set if it is validated. --- src/gui/widgets/qlineedit.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 8e7fdec..2d6ef03 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -692,9 +692,14 @@ int QLineEdit::cursorPositionAt(const QPoint &pos) bool QLineEdit::validateAndSet(const QString &newText, int newPos, int newMarkAnchor, int newMarkDrag) { - // Note, this doesn't validate', but then neither - // does the suggested functions above in the docs. + // The suggested functions above in the docs don't seem to validate, + // below code tries to mimic previous behaviour. + QString oldText = text(); setText(newText); + if(!hasAcceptableInput()){ + setText(oldText); + return false; + } setCursorPosition(newPos); setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag)); return true; @@ -1947,11 +1952,13 @@ QMenu *QLineEdit::createStandardContextMenu() #ifndef QT_NO_CLIPBOARD action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut)); - action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()); + action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText() + && d->control->echoMode() == QLineEdit::Normal); connect(action, SIGNAL(triggered()), SLOT(cut())); action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy)); - action->setEnabled(d->control->hasSelectedText()); + action->setEnabled(d->control->hasSelectedText() + && d->control->echoMode() == QLineEdit::Normal); connect(action, SIGNAL(triggered()), SLOT(copy())); action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste)); -- cgit v0.12 From 61084f0e8dcbd9b7ecaa250c74cd53ba042210e1 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 10 Jul 2009 10:33:20 +1000 Subject: Fix some minor mistakes --- src/gui/widgets/qlineedit.cpp | 6 +++--- src/gui/widgets/qvalidator.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 2d6ef03..977d00c 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1409,7 +1409,7 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() < QApplication::startDragDistance()) { selectAll(); - return; + return; } bool mark = e->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(e->pos().x()); @@ -1593,8 +1593,6 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) clear(); } - d->control->processInputMethodEvent(e); - #ifdef QT_KEYPAD_NAVIGATION // Focus in if currently in navigation focus on the widget // Only focus in on preedits, to allow input methods to @@ -1607,6 +1605,8 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) } #endif + d->control->processInputMethodEvent(e); + #ifndef QT_NO_COMPLETER if (!e->commitString().isEmpty()) d->control->complete(Qt::Key_unknown); diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h index 5ddc44e..5c27d1d 100644 --- a/src/gui/widgets/qvalidator.h +++ b/src/gui/widgets/qvalidator.h @@ -120,7 +120,7 @@ public: #endif private: - /*Q_DISABLE_COPY(QIntValidator)*/ + Q_DISABLE_COPY(QIntValidator) int b; int t; -- cgit v0.12 From 2718577ecf7a4a5c9fc619a46ee79a468044b4d7 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 10:44:05 +1000 Subject: Move some keypad navigation code back out of QLineControl --- src/gui/widgets/qlinecontrol.cpp | 46 ----------------------------------- src/gui/widgets/qlineedit.cpp | 52 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index fc0a173..dd3c057 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1212,44 +1212,6 @@ void QLineControl::timerEvent ( QTimerEvent * event ) bool QLineControl::processEvent(QEvent* ev) { -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { - QKeyEvent *ke = (QKeyEvent *)ev; - if (ke->key() == Qt::Key_Back) { - if (ke->isAutoRepeat()) { - // Swallow it. We don't want back keys running amok. - ke->accept(); - return true; - } - if ((ev->type() == QEvent::KeyRelease) - && !isReadOnly() - && deleteAllTimer) { - killTimer(m_deleteAllTimer); - m_deleteAllTimer = 0; - backspace(); - ke->accept(); - return true; - } - } - } else if (e->type() == QEvent::EnterEditFocus) { - end(false); - int cft = QApplication::cursorFlashTime(); - control->setCursorBlinkPeriod(cft/2); - } else if (e->type() == QEvent::LeaveEditFocus) { - d->setCursorVisible(false);//!!! - control->setCursorBlinkPeriod(0); - if (!m_emitingEditingFinished) { - if (hasAcceptableInput() || fixup()) { - m_emitingEditingFinished = true; - emit editingFinished(); - m_emitingEditingFinished = false; - } - } - } - return; - } -#endif switch(ev->type()){ #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMouseMove: @@ -1332,14 +1294,6 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) } if (ev->button() == Qt::RightButton) return; -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { - setEditFocus(true); - // Get the completion list to pop up. - if (m_completer) - m_completer->complete(); - } -#endif bool mark = ev->modifiers() & Qt::ShiftModifier; int cursor = xToPos(ev->pos().x()); diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 977d00c..b0c48b0 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1361,7 +1361,45 @@ void QLineEdit::paste() bool QLineEdit::event(QEvent * e) { Q_D(QLineEdit); - if (e->type() == QEvent::Timer) { +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + } else if (e->type() == QEvent::EnterEditFocus) { + end(false); + int cft = QApplication::cursorFlashTime(); + control->setCursorBlinkPeriod(cft/2); + } else if (e->type() == QEvent::LeaveEditFocus) { + d->setCursorVisible(false);//!!! + control->setCursorBlinkPeriod(0); + if (!m_emitingEditingFinished) { + if (hasAcceptableInput() || fixup()) { + m_emitingEditingFinished = true; + emit editingFinished(); + m_emitingEditingFinished = false; + } + } + } + return; + } +#endif + if (e->type() == QEvent::Timer) { // should be timerEvent, is here for binary compatibility int timerId = ((QTimerEvent*)e)->timerId(); if (false) { @@ -1442,9 +1480,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) d->drag(); } else #endif - { d->control->moveCursor(d->xToPos(e->pos().x()), true); - } } } @@ -1463,10 +1499,18 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) d->drag(); } else #endif - { d->control->moveCursor(d->xToPos(e->pos().x()), true); + } +#ifndef QT_NO_CLIPBOARD + if (QApplication::clipboard()->supportsSelection()) { + if (e->button() == Qt::LeftButton) { + d->control->copy(QClipboard::Selection); + } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) { + deselect(); + insert(QApplication::clipboard()->text(QClipboard::Selection)); } } +#endif } /*! \reimp -- cgit v0.12 From 960332de7ae1206390169fb5ef03aa94dffb8f14 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 11:31:57 +1000 Subject: Actually, some of that can't be moved back into QLineEdit Also it should be executed a little later to avoid accidental behaviour changes. --- src/gui/widgets/qlinecontrol.cpp | 23 ++++++++++++++++ src/gui/widgets/qlineedit.cpp | 58 ++++++++++++++-------------------------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index dd3c057..e6f397a 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1212,6 +1212,29 @@ void QLineControl::timerEvent ( QTimerEvent * event ) bool QLineControl::processEvent(QEvent* ev) { +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + } + } +#endif switch(ev->type()){ #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMouseMove: diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index b0c48b0..92dcfc4 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1361,44 +1361,6 @@ void QLineEdit::paste() bool QLineEdit::event(QEvent * e) { Q_D(QLineEdit); -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { - QKeyEvent *ke = (QKeyEvent *)ev; - if (ke->key() == Qt::Key_Back) { - if (ke->isAutoRepeat()) { - // Swallow it. We don't want back keys running amok. - ke->accept(); - return true; - } - if ((ev->type() == QEvent::KeyRelease) - && !isReadOnly() - && deleteAllTimer) { - killTimer(m_deleteAllTimer); - m_deleteAllTimer = 0; - backspace(); - ke->accept(); - return true; - } - } - } else if (e->type() == QEvent::EnterEditFocus) { - end(false); - int cft = QApplication::cursorFlashTime(); - control->setCursorBlinkPeriod(cft/2); - } else if (e->type() == QEvent::LeaveEditFocus) { - d->setCursorVisible(false);//!!! - control->setCursorBlinkPeriod(0); - if (!m_emitingEditingFinished) { - if (hasAcceptableInput() || fixup()) { - m_emitingEditingFinished = true; - emit editingFinished(); - m_emitingEditingFinished = false; - } - } - } - return; - } -#endif if (e->type() == QEvent::Timer) { // should be timerEvent, is here for binary compatibility int timerId = ((QTimerEvent*)e)->timerId(); @@ -1424,6 +1386,26 @@ bool QLineEdit::event(QEvent * e) d->control->setLayoutDirection((layoutDirection())); } +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if (e->type() == QEvent::EnterEditFocus) { + end(false); + int cft = QApplication::cursorFlashTime(); + d->control->setCursorBlinkPeriod(cft/2); + } else if (e->type() == QEvent::LeaveEditFocus) { + d->setCursorVisible(false); + d->control->setCursorBlinkPeriod(0); + if (!d->control->emitingEditingFinished) { + if (d->control->hasAcceptableInput() || d->control->fixup()) { + d->control->emitingEditingFinished = true; + emit editingFinished(); + d->control->emitingEditingFinished = false; + } + } + } + return; + } +#endif return QWidget::event(e); } -- cgit v0.12 From da3b21f6cf51ef10f230f2cf86e43fe0e6314193 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 13:34:40 +1000 Subject: Replace Q_ASSERT with qWarning This is probably more correct, but is also the way it used to behave. --- src/gui/widgets/qlinecontrol.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index e6f397a..557892f 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -222,8 +222,10 @@ void QLineControl::clear() */ void QLineControl::setSelection(int start, int length) { - Q_ASSERT_X(start >= 0 && start <= (int)m_text.length(), - "QLineControl::setSelection", "Invalid start position"); + if(start < 0 || start > (int)m_text.length()){ + qWarning("QLineControl::setSelection: Invalid start position"); + return; + } if (length > 0) { selstart = start; -- cgit v0.12 From f6e0f0d549de292f0bbab98a67b035a8327175bf Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 13:47:37 +1000 Subject: qlinecontrol_p_p.h isn't actually used at all, remove file. --- src/gui/widgets/qlinecontrol_p_p.h | 105 ------------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 src/gui/widgets/qlinecontrol_p_p.h diff --git a/src/gui/widgets/qlinecontrol_p_p.h b/src/gui/widgets/qlinecontrol_p_p.h deleted file mode 100644 index e76794b..0000000 --- a/src/gui/widgets/qlinecontrol_p_p.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QLINECONTROL_P_P_H -#define QLINECONTROL_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qobject_p.h" -#include "QtGui/qtextlayout.h" - -QT_BEGIN_NAMESPACE - -class QMimeData; -class QAbstractScrollArea; -class QInputContext; - -class QLineControlPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QLineControl) -public: - QLineControlPrivate() - : cursor(0), preeditCursor(0), cursorWidth(1), cursorTimer(0), - maxLength(32767), modifiedState(0), undoState(0), - selStart(0), selEnd(0), textInteractionFlags(0), - cursorVisible(0), hideCursor(0), echoMode(0) - {} - - QPalette palette; - QVector history; - QTextLayout textLayout; // display text - QString text; - - int cursor; - int preeditCursor; - int lastCursorPos; - int cursorWidth; - int cursorTimer; - - int maxLength; - - int modifiedState; - int undoState; - - int selStart, selEnd; - - Qt::TextInteractionFlags textInteractionFlags; - - // keep together and at end - uint cursorVisible : 1; - uint hideCursor : 1; // used to hide the cursor inside preedit areas - uint echoMode : 2; -}; - -QT_END_NAMESPACE - -#endif // QLINECONTROL_P_H - -- cgit v0.12 From 291703873d208fec1eba1a039a79a61543745b35 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 14:17:28 +1000 Subject: Cleanup some incorrect changes to QLineEdit --- src/gui/widgets/qlineedit.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 92dcfc4..9252888 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1382,8 +1382,6 @@ bool QLineEdit::event(QEvent * e) QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate())); }else if(e->type() == QEvent::ShortcutOverride){ d->control->processEvent(e); - }else if(e->type() == QEvent::LayoutDirectionChange){ - d->control->setLayoutDirection((layoutDirection())); } #ifdef QT_KEYPAD_NAVIGATION @@ -1462,7 +1460,9 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) d->drag(); } else #endif + { d->control->moveCursor(d->xToPos(e->pos().x()), true); + } } } @@ -1473,16 +1473,15 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) return; - - if (e->buttons() & Qt::LeftButton) { #ifndef QT_NO_DRAGANDDROP + if (e->button() == Qt::LeftButton) { if (d->dndTimer.isActive()) { - if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) - d->drag(); - } else -#endif - d->control->moveCursor(d->xToPos(e->pos().x()), true); + d->dndTimer.stop(); + deselect(); + return; + } } +#endif #ifndef QT_NO_CLIPBOARD if (QApplication::clipboard()->supportsSelection()) { if (e->button() == Qt::LeftButton) { -- cgit v0.12 From 1bd89d1c8a9bc41f8ea76f55a2ebd17447fc2d70 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 15:05:42 +0200 Subject: Add '\internal' to the QLineControl documentation. --- src/gui/widgets/qlinecontrol.cpp | 142 ++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 40 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 557892f..9b2a47a 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -59,7 +59,9 @@ QT_BEGIN_NAMESPACE -/* +/*! + \internal + Updates the display text based of the current edit text If the text has changed will emit displayTextChanged() */ @@ -105,7 +107,9 @@ void QLineControl::updateDisplayText() } #ifndef QT_NO_CLIPBOARD -/* +/*! + \internal + Copies the currently selected text into the clipboard using the given \a mode. @@ -124,7 +128,9 @@ void QLineControl::copy(QClipboard::Mode mode) const } } -/* +/*! + \internal + Inserts the text stored in the application clipboard into the line control. @@ -137,7 +143,9 @@ void QLineControl::paste() #endif // !QT_NO_CLIPBOARD -/* +/*! + \internal + Handles the behavior for the backspace key or function. Removes the current selection if there is a selection, otherwise removes the character prior to the cursor position. @@ -168,7 +176,9 @@ void QLineControl::backspace() finishChange(priorState); } -/* +/*! + \internal + Handles the behavior for the delete key or function. Removes the current selection if there is a selection, otherwise removes the character after the cursor position. @@ -188,7 +198,9 @@ void QLineControl::del() finishChange(priorState); } -/* +/*! + \internal + Inserts the given \a newText at the current cursor position. If there is any selected text it is removed prior to insertion of the new text. @@ -201,7 +213,9 @@ void QLineControl::insert(const QString &newText) finishChange(priorState); } -/* +/*! + \internal + Clears the line control text. */ void QLineControl::clear() @@ -214,7 +228,9 @@ void QLineControl::clear() finishChange(priorState, /*update*/false, /*edited*/false); } -/* +/*! + \internal + Sets \a length characters from the given \a start position as selected. The given \a start position must be within the current text for the line control. If \a length characters cannot be selected, then @@ -254,7 +270,9 @@ void QLineControl::_q_deleteSelected() finishChange(priorState); } -/* +/*! + \internal + Initializes the line control with a starting text value of \a txt. */ void QLineControl::init(const QString& txt) @@ -264,7 +282,9 @@ void QLineControl::init(const QString& txt) m_cursor = m_text.length(); } -/* +/*! + \internal + Sets the password echo editing to \a editing. If password echo editing is true, then the text of the password is displayed even if the echo mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing @@ -276,7 +296,9 @@ void QLineControl::updatePasswordEchoEditing(bool editing) updateDisplayText(); } -/* +/*! + \internal + Returns the cursor position of the given \a x pixel value in relation to the displayed text. The given \a betweenOrOn specified what kind of cursor position is requested. @@ -286,7 +308,9 @@ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const return textLayout.lineAt(0).xToCursor(x, betweenOrOn); } -/* +/*! + \internal + Returns the bounds of the current cursor, as defined as a between characters cursor. */ @@ -303,7 +327,9 @@ QRect QLineControl::cursorRect() const return QRect(cix-5, 0, w+9, ch); } -/* +/*! + \internal + Fixes the current text so that it is valid given any set validators. Returns true if the text was changed. Otherwise returns false. @@ -325,7 +351,9 @@ bool QLineControl::fixup() // this function assumes that validate currently retu return false; } -/* +/*! + \internal + Moves the cursor to the given position \a pos. If \a mark is true will adjust the currently selected text. */ @@ -358,7 +386,9 @@ void QLineControl::moveCursor(int pos, bool mark) emitCursorPositionChanged(); } -/* +/*! + \internal + Applies the given input method event \a event to the text of the line control */ @@ -411,7 +441,9 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) finishChange(priorState); } -/* +/*! + \internal + Draws the display text for the line control using the given \a painter, \a clip, and \a offset. Which aspects of the display text are drawn is specified by the given \a flags. @@ -453,7 +485,9 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl } } -/* +/*! + \internal + Sets the selection to cover the word at the given cursor position. The word boundries is defined by the behavior of QTextLayout::SkipWords cursor mode. @@ -469,7 +503,9 @@ void QLineControl::selectWordAtPos(int cursor) moveCursor(end, true); } -/* +/*! + \internal + Completes a change to the line control text. If the change is not valid will undo the line control state back to the given \a validateFromState. @@ -479,7 +515,6 @@ void QLineControl::selectWordAtPos(int cursor) The \a update value is currently unused. */ - bool QLineControl::finishChange(int validateFromState, bool update, bool edited) { Q_UNUSED(update) @@ -531,7 +566,9 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) return true; } -/* +/*! + \internal + An internal function for setting the text of the line control. */ void QLineControl::p_setText(const QString& txt, int pos, bool edited) @@ -553,7 +590,9 @@ void QLineControl::p_setText(const QString& txt, int pos, bool edited) } -/* +/*! + \internal + Adds the given \a command to the undo history of the line control. Does not apply the command. */ @@ -569,7 +608,9 @@ void QLineControl::addCommand(const Command& cmd) history[undoState++] = cmd; } -/* +/*! + \internal + Inserts the given string \a s into the line control. @@ -602,8 +643,9 @@ void QLineControl::p_insert(const QString& s) } } -/* +/*! \internal + deletes a single character from the current text. If \a wasBackspace, the character prior to the cursor is removed. Otherwise the character after the cursor is removed. @@ -628,8 +670,9 @@ void QLineControl::p_del(bool wasBackspace) } } -/* +/*! \internal + removes the currently selected text from the line control. Also adds the appropriate commands into the undo history. @@ -667,7 +710,9 @@ void QLineControl::removeSelectedText() } } -/* +/*! + \internal + Parses the input mask specified by \a maskFields to generate the mask data used to handle input masks. */ @@ -769,7 +814,11 @@ void QLineControl::parseInputMask(const QString &maskFields) } -/* checks if the key is valid compared to the inputMask */ +/*! + \internal + + checks if the key is valid compared to the inputMask +*/ bool QLineControl::isValidInput(QChar key, QChar mask) const { switch (mask.unicode()) { @@ -839,7 +888,9 @@ bool QLineControl::isValidInput(QChar key, QChar mask) const return false; } -/* +/*! + \internal + Returns true if the given text \a str is valid for any validator or input mask set for the line control. @@ -873,11 +924,13 @@ bool QLineControl::hasAcceptableInput(const QString &str) const return true; } -/* - Applies the inputMask on \a str starting from position \a pos in the mask. \a clear - specifies from where characters should be gotten when a separator is met in \a str - true means - that blanks will be used, false that previous input is used. - Calling this when no inputMask is set is undefined. +/*! + \internal + + Applies the inputMask on \a str starting from position \a pos in the mask. \a clear + specifies from where characters should be gotten when a separator is met in \a str - true means + that blanks will be used, false that previous input is used. + Calling this when no inputMask is set is undefined. */ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const { @@ -948,9 +1001,11 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const -/* - Returns a "cleared" string with only separators and blank chars. - Calling this when no inputMask is set is undefined. +/*! + \internal + + Returns a "cleared" string with only separators and blank chars. + Calling this when no inputMask is set is undefined. */ QString QLineControl::clearString(uint pos, uint len) const { @@ -968,9 +1023,11 @@ QString QLineControl::clearString(uint pos, uint len) const return s; } -/* - Strips blank parts of the input in a QLineControl when an inputMask is set, - separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". +/*! + \internal + + Strips blank parts of the input in a QLineControl when an inputMask is set, + separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". */ QString QLineControl::stripString(const QString &str) const { @@ -989,7 +1046,10 @@ QString QLineControl::stripString(const QString &str) const return s; } -/* searches forward/backward in maskData for either a separator or a blank */ +/*! + \internal + searches forward/backward in maskData for either a separator or a blank +*/ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const { if (pos >= m_maxLength || pos < 0) @@ -1099,7 +1159,9 @@ void QLineControl::p_redo() { emitCursorPositionChanged(); } -/* +/*! + \internal + If the current cursor position differs from the last emited cursor position, emits cursorPositionChanged(). */ -- cgit v0.12 From 363221747e68b7a5930afdeef87a5454f40c5ffb Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 15:19:35 +0200 Subject: Some minor style and whitespace fixes. --- src/gui/widgets/qlinecontrol.cpp | 59 ++++++++++++++++++++-------------------- src/gui/widgets/qlinecontrol_p.h | 23 ++++++++++------ 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 9b2a47a..6d8fe06 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -275,7 +275,7 @@ void QLineControl::_q_deleteSelected() Initializes the line control with a starting text value of \a txt. */ -void QLineControl::init(const QString& txt) +void QLineControl::init(const QString &txt) { m_text = txt; updateDisplayText(); @@ -571,7 +571,7 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) An internal function for setting the text of the line control. */ -void QLineControl::p_setText(const QString& txt, int pos, bool edited) +void QLineControl::p_setText(const QString &txt, int pos, bool edited) { p_deselect(); emit resetInputContext(); @@ -596,7 +596,7 @@ void QLineControl::p_setText(const QString& txt, int pos, bool edited) Adds the given \a command to the undo history of the line control. Does not apply the command. */ -void QLineControl::addCommand(const Command& cmd) +void QLineControl::addCommand(const Command &cmd) { if (separator && undoState && history[undoState-1].type != Separator) { history.resize(undoState + 2); @@ -618,15 +618,15 @@ void QLineControl::addCommand(const Command& cmd) This function does not call finishChange(), and may leave the text in an invalid state. */ -void QLineControl::p_insert(const QString& s) +void QLineControl::p_insert(const QString &s) { if (hasSelectedText()) addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); if (maskData) { QString ms = maskString(m_cursor, s); for (int i = 0; i < (int) ms.length(); ++i) { - addCommand (Command(DeleteSelection, m_cursor+i, m_text.at(m_cursor+i), -1, -1)); - addCommand(Command(Insert, m_cursor+i, ms.at(i), -1, -1)); + addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1)); + addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1)); } m_text.replace(m_cursor, ms.length(), ms); m_cursor += ms.length(); @@ -659,7 +659,8 @@ void QLineControl::p_del(bool wasBackspace) if (m_cursor < (int) m_text.length()) { if (hasSelectedText()) addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); + addCommand(Command((CommandType)((maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), + m_cursor, m_text.at(m_cursor), -1, -1)); if (maskData) { m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); @@ -990,7 +991,7 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const } } } - strIndex++; + ++strIndex; } } else break; @@ -1014,7 +1015,7 @@ QString QLineControl::clearString(uint pos, uint len) const QString s; int end = qMin((uint)m_maxLength, pos + len); - for (int i=pos; itimerId() == m_blinkTimer) { + if (event->timerId() == m_blinkTimer) { m_blinkStatus = !m_blinkStatus; - emit updateNeeded(inputMask().isEmpty()?cursorRect():QRect()); - }else if(event->timerId() == m_deleteAllTimer){ + emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect()); + } else if (event->timerId() == m_deleteAllTimer) { killTimer(m_deleteAllTimer); m_deleteAllTimer = 0; clear(); - }else if(event->timerId() == m_tripleClickTimer){ + } else if (event->timerId() == m_tripleClickTimer) { killTimer(m_tripleClickTimer); m_tripleClickTimer = 0; } @@ -1371,11 +1372,12 @@ bool QLineControl::processEvent(QEvent* ev) void QLineControl::processMouseEvent(QMouseEvent* ev) { - switch (ev->type()){ + switch (ev->type()) { case QEvent::GraphicsSceneMousePress: case QEvent::MouseButtonPress:{ - if (m_tripleClickTimer && (ev->pos() - m_tripleClick).manhattanLength() < - QApplication::startDragDistance()) { + if (m_tripleClickTimer + && (ev->pos() - m_tripleClick).manhattanLength() + < QApplication::startDragDistance()) { selectAll(); return; } @@ -1390,7 +1392,7 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) case QEvent::MouseButtonDblClick: if (ev->button() == Qt::LeftButton) { selectWordAtPos(xToPos(ev->pos().x())); - if(m_tripleClickTimer) + if (m_tripleClickTimer) killTimer(m_tripleClickTimer); m_tripleClickTimer = startTimer(QApplication::doubleClickInterval()); m_tripleClick = ev->pos(); @@ -1412,7 +1414,7 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) case QEvent::GraphicsSceneMouseMove: case QEvent::MouseMove: if (ev->buttons() & Qt::LeftButton) { - moveCursor(xToPos(ev->pos().x()), true); + moveCursor(xToPos(ev->pos().x()), true); } break; default: @@ -1422,7 +1424,6 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) void QLineControl::processKeyEvent(QKeyEvent* event) { - bool inlineCompletionAccepted = false; #ifndef QT_NO_COMPLETER @@ -1472,8 +1473,6 @@ void QLineControl::processKeyEvent(QKeyEvent* event) } #endif // QT_NO_COMPLETER - - if (echoMode() == QLineEdit::PasswordEchoOnEdit && !passwordEchoEditing() && !isReadOnly() diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 4ecedcd..2d93e90 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -462,8 +462,10 @@ inline void QLineControl::removeSelection() inline bool QLineControl::inSelection(int x) const { - if (selstart >= selend) return false; - int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; + if (selstart >= selend) + return false; + int pos = xToPos(x, QTextLine::CursorOnCharacter); + return pos >= selstart && pos < selend; } inline int QLineControl::cursor() const @@ -557,22 +559,26 @@ inline QString QLineControl::displayText() const inline void QLineControl::deselect() { - p_deselect(); finishChange(); + p_deselect(); + finishChange(); } inline void QLineControl::selectAll() { - selstart = selend = m_cursor = 0; moveCursor(m_text.length(), true); + selstart = selend = m_cursor = 0; + moveCursor(m_text.length(), true); } inline void QLineControl::undo() { - p_undo(), finishChange(-1, true); + p_undo(); + finishChange(-1, true); } inline void QLineControl::redo() { - p_redo(), finishChange(); + p_redo(); + finishChange(); } inline uint QLineControl::echoMode() const @@ -625,7 +631,8 @@ inline void QLineControl::setCompleter(const QCompleter* c) inline void QLineControl::setCursorPosition(int pos) { - if (pos < 0) pos = 0; + if (pos < 0) + pos = 0; if (pos < m_text.length()) moveCursor(pos); } @@ -723,7 +730,7 @@ inline void QLineControl::setCancelText(QString s) QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_LINEEDIT +#endif // QT_NO_LINEEDIT #endif // QLINECONTROL_P_H -- cgit v0.12 From aec21d2255e9927689e640b36150b7c9a4e9f522 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 16:16:47 +0200 Subject: Make the member variable names in QLineControl consistent. --- src/gui/widgets/qlinecontrol.cpp | 330 +++++++++++++++++++-------------------- src/gui/widgets/qlinecontrol_p.h | 161 ++++++++++--------- src/gui/widgets/qlineedit.cpp | 6 +- src/gui/widgets/qlineedit_p.h | 1 - 4 files changed, 253 insertions(+), 245 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 6d8fe06..50ce6e6 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE */ void QLineControl::updateDisplayText() { - QString orig = textLayout.text(); + QString orig = m_textLayout.text(); QString str; if (m_echoMode == QLineEdit::NoEcho) str = QString::fromLatin1(""); @@ -90,16 +90,16 @@ void QLineControl::updateDisplayText() uc[i] = QChar(0x0020); } - textLayout.setText(str); + m_textLayout.setText(str); QTextOption option; option.setTextDirection(m_layoutDirection); option.setFlags(QTextOption::IncludeTrailingSpaces); - textLayout.setTextOption(option); + m_textLayout.setTextOption(option); - textLayout.beginLayout(); - QTextLine l = textLayout.createLine(); - textLayout.endLayout(); + m_textLayout.beginLayout(); + QTextLine l = m_textLayout.createLine(); + m_textLayout.endLayout(); m_ascent = qRound(l.ascent()); if (str != orig) @@ -154,12 +154,12 @@ void QLineControl::paste() */ void QLineControl::backspace() { - int priorState = undoState; + int priorState = m_undoState; if (hasSelectedText()) { removeSelectedText(); } else if (m_cursor) { --m_cursor; - if (maskData) + if (m_maskData) m_cursor = prevMaskBlank(m_cursor); QChar uc = m_text.at(m_cursor); if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { @@ -187,11 +187,11 @@ void QLineControl::backspace() */ void QLineControl::del() { - int priorState = undoState; + int priorState = m_undoState; if (hasSelectedText()) { removeSelectedText(); } else { - int n = textLayout.nextCursorPosition(m_cursor) - m_cursor; + int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; while (n--) p_del(); } @@ -207,7 +207,7 @@ void QLineControl::del() */ void QLineControl::insert(const QString &newText) { - int priorState = undoState; + int priorState = m_undoState; removeSelectedText(); p_insert(newText); finishChange(priorState); @@ -220,9 +220,9 @@ void QLineControl::insert(const QString &newText) */ void QLineControl::clear() { - int priorState = undoState; - selstart = 0; - selend = m_text.length(); + int priorState = m_undoState; + m_selstart = 0; + m_selend = m_text.length(); removeSelectedText(); separate(); finishChange(priorState, /*update*/false, /*edited*/false); @@ -244,13 +244,13 @@ void QLineControl::setSelection(int start, int length) } if (length > 0) { - selstart = start; - selend = qMin(start + length, (int)m_text.length()); - m_cursor = selend; + m_selstart = start; + m_selend = qMin(start + length, (int)m_text.length()); + m_cursor = m_selend; } else { - selstart = qMax(start + length, 0); - selend = start; - m_cursor = selstart; + m_selstart = qMax(start + length, 0); + m_selend = start; + m_cursor = m_selstart; } } @@ -263,7 +263,7 @@ void QLineControl::_q_deleteSelected() if (!hasSelectedText()) return; - int priorState = undoState; + int priorState = m_undoState; emit resetInputContext(); removeSelectedText(); separate(); @@ -305,7 +305,7 @@ void QLineControl::updatePasswordEchoEditing(bool editing) */ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const { - return textLayout.lineAt(0).xToCursor(x, betweenOrOn); + return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn); } /*! @@ -316,7 +316,7 @@ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const */ QRect QLineControl::cursorRect() const { - QTextLine l = textLayout.lineAt(0); + QTextLine l = m_textLayout.lineAt(0); int c = m_cursor; if (m_preeditCursor != -1) c += m_preeditCursor; @@ -361,26 +361,26 @@ void QLineControl::moveCursor(int pos, bool mark) { if (pos != m_cursor) { separate(); - if (maskData) + if (m_maskData) pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); } if (mark) { int anchor; - if (selend > selstart && m_cursor == selstart) - anchor = selend; - else if (selend > selstart && m_cursor == selend) - anchor = selstart; + if (m_selend > m_selstart && m_cursor == m_selstart) + anchor = m_selend; + else if (m_selend > m_selstart && m_cursor == m_selend) + anchor = m_selstart; else anchor = m_cursor; - selstart = qMin(anchor, pos); - selend = qMax(anchor, pos); + m_selstart = qMin(anchor, pos); + m_selend = qMax(anchor, pos); updateDisplayText(); } else { p_deselect(); } m_cursor = pos; - if (mark || selDirty) { - selDirty = false; + if (mark || m_selDirty) { + m_selDirty = false; emit selectionChanged(); } emitCursorPositionChanged(); @@ -394,7 +394,7 @@ void QLineControl::moveCursor(int pos, bool mark) */ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) { - int priorState = undoState; + int priorState = m_undoState; removeSelectedText(); int c = m_cursor; // cursor position after insertion of commit string @@ -405,8 +405,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) // insert commit string if (event->replacementLength()) { - selstart = m_cursor; - selend = selstart + event->replacementLength(); + m_selstart = m_cursor; + m_selend = m_selstart + event->replacementLength(); removeSelectedText(); } if (!event->commitString().isEmpty()) @@ -416,13 +416,13 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) setPreeditArea(m_cursor, event->preeditString()); m_preeditCursor = event->preeditString().length(); - hideCursor = false; + m_hideCursor = false; QList formats; for (int i = 0; i < event->attributes().size(); ++i) { const QInputMethodEvent::Attribute &a = event->attributes().at(i); if (a.type == QInputMethodEvent::Cursor) { m_preeditCursor = a.start; - hideCursor = !a.length; + m_hideCursor = !a.length; } else if (a.type == QInputMethodEvent::TextFormat) { QTextCharFormat f = qvariant_cast(a.value).toCharFormat(); if (f.isValid()) { @@ -434,7 +434,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) } } } - textLayout.setAdditionalFormats(formats); + m_textLayout.setAdditionalFormats(formats); updateDisplayText(); if (!event->commitString().isEmpty()) emitCursorPositionChanged(); @@ -461,9 +461,9 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl QVector selections; if (flags & DrawSelections) { QTextLayout::FormatRange o; - if (selstart < selend) { - o.start = selstart; - o.length = selend - selstart; + if (m_selstart < m_selend) { + o.start = m_selstart; + o.length = m_selend - m_selstart; o.format.setBackground(m_palette.brush(QPalette::Highlight)); o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); } else { @@ -477,11 +477,11 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl } if (flags & DrawText) - textLayout.draw(painter, offset, selections, clip); + m_textLayout.draw(painter, offset, selections, clip); if (flags & DrawCursor){ if(!m_blinkPeriod || m_blinkStatus) - textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); } } @@ -494,10 +494,10 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl */ void QLineControl::selectWordAtPos(int cursor) { - int c = textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); moveCursor(c, false); // ## text layout should support end of words. - int end = textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); while (end > cursor && m_text[end-1].isSpace()) --end; moveCursor(end, true); @@ -518,18 +518,18 @@ void QLineControl::selectWordAtPos(int cursor) bool QLineControl::finishChange(int validateFromState, bool update, bool edited) { Q_UNUSED(update) - bool lineDirty = selDirty; - if (textDirty) { + bool lineDirty = m_selDirty; + if (m_textDirty) { // do validation - bool wasValidInput = validInput; - validInput = true; + bool wasValidInput = m_validInput; + m_validInput = true; #ifndef QT_NO_VALIDATOR if (m_validator) { - validInput = false; + m_validInput = false; QString textCopy = m_text; int cursorCopy = m_cursor; - validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); - if (validInput) { + m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); + if (m_validInput) { if (m_text != textCopy) { p_setText(textCopy, cursorCopy); return true; @@ -538,28 +538,28 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) } } #endif - if (validateFromState >= 0 && wasValidInput && !validInput) { - if (transactions.count()) + if (validateFromState >= 0 && wasValidInput && !m_validInput) { + if (m_transactions.count()) return false; p_undo(validateFromState); - history.resize(undoState); - if (modifiedState > undoState) - modifiedState = -1; - validInput = true; - textDirty = false; + m_history.resize(m_undoState); + if (m_modifiedState > m_undoState) + m_modifiedState = -1; + m_validInput = true; + m_textDirty = false; } updateDisplayText(); - lineDirty |= textDirty; - if (textDirty) { - textDirty = false; + lineDirty |= m_textDirty; + if (m_textDirty) { + m_textDirty = false; QString actualText = text(); if (edited) emit textEdited(actualText); emit textChanged(actualText); } } - if (selDirty) { - selDirty = false; + if (m_selDirty) { + m_selDirty = false; emit selectionChanged(); } emitCursorPositionChanged(); @@ -576,16 +576,16 @@ void QLineControl::p_setText(const QString &txt, int pos, bool edited) p_deselect(); emit resetInputContext(); QString oldText = m_text; - if (maskData) { + if (m_maskData) { m_text = maskString(0, txt, true); m_text += clearString(m_text.length(), m_maxLength - m_text.length()); } else { m_text = txt.isEmpty() ? txt : txt.left(m_maxLength); } - history.clear(); - modifiedState = undoState = 0; + m_history.clear(); + m_modifiedState = m_undoState = 0; m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos; - textDirty = (oldText != m_text); + m_textDirty = (oldText != m_text); finishChange(-1, true, edited); } @@ -598,14 +598,14 @@ void QLineControl::p_setText(const QString &txt, int pos, bool edited) */ void QLineControl::addCommand(const Command &cmd) { - if (separator && undoState && history[undoState-1].type != Separator) { - history.resize(undoState + 2); - history[undoState++] = Command(Separator, m_cursor, 0, selstart, selend); + if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) { + m_history.resize(m_undoState + 2); + m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend); } else { - history.resize(undoState + 1); + m_history.resize(m_undoState + 1); } - separator = false; - history[undoState++] = cmd; + m_separator = false; + m_history[m_undoState++] = cmd; } /*! @@ -621,8 +621,8 @@ void QLineControl::addCommand(const Command &cmd) void QLineControl::p_insert(const QString &s) { if (hasSelectedText()) - addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - if (maskData) { + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + if (m_maskData) { QString ms = maskString(m_cursor, s); for (int i = 0; i < (int) ms.length(); ++i) { addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1)); @@ -631,14 +631,14 @@ void QLineControl::p_insert(const QString &s) m_text.replace(m_cursor, ms.length(), ms); m_cursor += ms.length(); m_cursor = nextMaskBlank(m_cursor); - textDirty = true; + m_textDirty = true; } else { int remaining = m_maxLength - m_text.length(); if (remaining != 0) { m_text.insert(m_cursor, s.left(remaining)); for (int i = 0; i < (int) s.left(remaining).length(); ++i) addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1)); - textDirty = true; + m_textDirty = true; } } } @@ -658,16 +658,16 @@ void QLineControl::p_del(bool wasBackspace) { if (m_cursor < (int) m_text.length()) { if (hasSelectedText()) - addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - addCommand(Command((CommandType)((maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); - if (maskData) { + if (m_maskData) { m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); } else { m_text.remove(m_cursor, 1); } - textDirty = true; + m_textDirty = true; } } @@ -682,32 +682,32 @@ void QLineControl::p_del(bool wasBackspace) */ void QLineControl::removeSelectedText() { - if (selstart < selend && selend <= (int) m_text.length()) { + if (m_selstart < m_selend && m_selend <= (int) m_text.length()) { separate(); int i ; - addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - if (selstart <= m_cursor && m_cursor < selend) { + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + if (m_selstart <= m_cursor && m_cursor < m_selend) { // cursor is within the selection. Split up the commands // to be able to restore the correct cursor position - for (i = m_cursor; i >= selstart; --i) + for (i = m_cursor; i >= m_selstart; --i) addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1)); - for (i = selend - 1; i > m_cursor; --i) - addCommand (Command(DeleteSelection, i - m_cursor + selstart - 1, m_text.at(i), -1, -1)); + for (i = m_selend - 1; i > m_cursor; --i) + addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1)); } else { - for (i = selend-1; i >= selstart; --i) + for (i = m_selend-1; i >= m_selstart; --i) addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1)); } - if (maskData) { - m_text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); - for (int i = 0; i < selend - selstart; ++i) - addCommand(Command(Insert, selstart + i, m_text.at(selstart + i), -1, -1)); + if (m_maskData) { + m_text.replace(m_selstart, m_selend - m_selstart, clearString(m_selstart, m_selend - m_selstart)); + for (int i = 0; i < m_selend - m_selstart; ++i) + addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1)); } else { - m_text.remove(selstart, selend - selstart); + m_text.remove(m_selstart, m_selend - m_selstart); } - if (m_cursor > selstart) - m_cursor -= qMin(m_cursor, selend) - selstart; + if (m_cursor > m_selstart) + m_cursor -= qMin(m_cursor, m_selend) - m_selstart; p_deselect(); - textDirty = true; + m_textDirty = true; } } @@ -721,9 +721,9 @@ void QLineControl::parseInputMask(const QString &maskFields) { int delimiter = maskFields.indexOf(QLatin1Char(';')); if (maskFields.isEmpty() || delimiter == 0) { - if (maskData) { - delete [] maskData; - maskData = 0; + if (m_maskData) { + delete [] m_maskData; + m_maskData = 0; m_maxLength = 32767; p_setText(QString()); } @@ -731,14 +731,14 @@ void QLineControl::parseInputMask(const QString &maskFields) } if (delimiter == -1) { - blank = QLatin1Char(' '); + m_blank = QLatin1Char(' '); m_inputMask = maskFields; } else { m_inputMask = maskFields.left(delimiter); - blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); + m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); } - // calculate m_maxLength / maskData length + // calculate m_maxLength / m_maskData length m_maxLength = 0; QChar c = 0; for (int i=0; i 0) || key == blank) + if ((key.isNumber() && key.digitValue() > 0) || key == m_blank) return true; break; case '#': - if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) + if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank) return true; break; case 'B': @@ -872,7 +872,7 @@ bool QLineControl::isValidInput(QChar key, QChar mask) const return true; break; case 'b': - if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) + if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank) return true; break; case 'H': @@ -880,7 +880,7 @@ bool QLineControl::isValidInput(QChar key, QChar mask) const return true; break; case 'h': - if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank) return true; break; default: @@ -907,18 +907,18 @@ bool QLineControl::hasAcceptableInput(const QString &str) const return false; #endif - if (!maskData) + if (!m_maskData) return true; if (str.length() != m_maxLength) return false; for (int i=0; i < m_maxLength; ++i) { - if (maskData[i].separator) { - if (str.at(i) != maskData[i].maskChar) + if (m_maskData[i].separator) { + if (str.at(i) != m_maskData[i].maskChar) return false; } else { - if (!isValidInput(str.at(i), maskData[i].maskChar)) + if (!isValidInput(str.at(i), m_maskData[i].maskChar)) return false; } } @@ -946,14 +946,14 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const int i = pos; while (i < m_maxLength) { if (strIndex < str.length()) { - if (maskData[i].separator) { - s += maskData[i].maskChar; - if (str[(int)strIndex] == maskData[i].maskChar) + if (m_maskData[i].separator) { + s += m_maskData[i].maskChar; + if (str[(int)strIndex] == m_maskData[i].maskChar) strIndex++; ++i; } else { - if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { - switch (maskData[i].caseMode) { + if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) { + switch (m_maskData[i].caseMode) { case MaskInputData::Upper: s += str[(int)strIndex].toUpper(); break; @@ -968,16 +968,16 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const // search for separator first int n = findInMask(i, true, true, str[(int)strIndex]); if (n != -1) { - if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { + if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) { s += fill.mid(i, n-i+1); i = n + 1; // update i to find + 1 } } else { - // search for valid blank if not + // search for valid m_blank if not n = findInMask(i, true, false, str[(int)strIndex]); if (n != -1) { s += fill.mid(i, n-i); - switch (maskData[n].caseMode) { + switch (m_maskData[n].caseMode) { case MaskInputData::Upper: s += str[(int)strIndex].toUpper(); break; @@ -1016,10 +1016,10 @@ QString QLineControl::clearString(uint pos, uint len) const QString s; int end = qMin((uint)m_maxLength, pos + len); for (int i = pos; i < end; ++i) - if (maskData[i].separator) - s += maskData[i].maskChar; + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; else - s += blank; + s += m_blank; return s; } @@ -1032,16 +1032,16 @@ QString QLineControl::clearString(uint pos, uint len) const */ QString QLineControl::stripString(const QString &str) const { - if (!maskData) + if (!m_maskData) return str; QString s; int end = qMin(m_maxLength, (int)str.length()); for (int i = 0; i < end; ++i) - if (maskData[i].separator) - s += maskData[i].maskChar; + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; else - if (str[i] != blank) + if (str[i] != m_blank) s += str[i]; return s; @@ -1049,7 +1049,7 @@ QString QLineControl::stripString(const QString &str) const /*! \internal - searches forward/backward in maskData for either a separator or a blank + searches forward/backward in m_maskData for either a separator or a m_blank */ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const { @@ -1062,13 +1062,13 @@ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar se while (i != end) { if (findSeparator) { - if (maskData[i].separator && maskData[i].maskChar == searchChar) + if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar) return i; } else { - if (!maskData[i].separator) { + if (!m_maskData[i].separator) { if (searchChar.isNull()) return i; - else if (isValidInput(searchChar, maskData[i].maskChar)) + else if (isValidInput(searchChar, m_maskData[i].maskChar)) return i; } } @@ -1082,16 +1082,16 @@ void QLineControl::p_undo(int until) if (!isUndoAvailable()) return; p_deselect(); - while (undoState && undoState > until) { - Command& cmd = history[--undoState]; + while (m_undoState && m_undoState > until) { + Command& cmd = m_history[--m_undoState]; switch (cmd.type) { case Insert: m_text.remove(cmd.pos, 1); m_cursor = cmd.pos; break; case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; case Remove: @@ -1107,14 +1107,14 @@ void QLineControl::p_undo(int until) case Separator: continue; } - if (until < 0 && undoState) { - Command& next = history[undoState-1]; + if (until < 0 && m_undoState) { + Command& next = m_history[m_undoState-1]; if (next.type != cmd.type && next.type < RemoveSelection && (cmd.type < RemoveSelection || next.type == Separator)) break; } } - textDirty = true; + m_textDirty = true; emitCursorPositionChanged(); } @@ -1122,16 +1122,16 @@ void QLineControl::p_redo() { if (!isRedoAvailable()) return; p_deselect(); - while (undoState < (int)history.size()) { - Command& cmd = history[undoState++]; + while (m_undoState < (int)m_history.size()) { + Command& cmd = m_history[m_undoState++]; switch (cmd.type) { case Insert: m_text.insert(cmd.pos, cmd.uc); m_cursor = cmd.pos + 1; break; case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; case Remove: @@ -1139,24 +1139,24 @@ void QLineControl::p_redo() { case RemoveSelection: case DeleteSelection: m_text.remove(cmd.pos, 1); - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; case Separator: - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; } - if (undoState < (int)history.size()) { - Command& next = history[undoState]; + if (m_undoState < (int)m_history.size()) { + Command& next = m_history[m_undoState]; if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator && (next.type < RemoveSelection || cmd.type == Separator)) break; } } - textDirty = true; + m_textDirty = true; emitCursorPositionChanged(); } @@ -1168,9 +1168,9 @@ void QLineControl::p_redo() { */ void QLineControl::emitCursorPositionChanged() { - if (m_cursor != lastCursorPos) { - const int oldLast = lastCursorPos; - lastCursorPos = m_cursor; + if (m_cursor != m_lastCursorPos) { + const int oldLast = m_lastCursorPos; + m_lastCursorPos = m_cursor; cursorPositionChanged(oldLast, m_cursor); } } @@ -1496,9 +1496,9 @@ void QLineControl::processKeyEvent(QKeyEvent* event) if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput() || fixup()) { emit accepted(); - emitingEditingFinished = true; + m_emitingEditingFinished = true; emit editingFinished(); - emitingEditingFinished = false; + m_emitingEditingFinished = false; } if (inlineCompletionAccepted) event->accept(); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 2d93e90..6029989 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -75,24 +75,24 @@ QT_MODULE(Gui) class Q_GUI_EXPORT QLineControl : public QObject { Q_OBJECT -public: +public: QLineControl(const QString &txt = QString()) - : emitingEditingFinished(0), + : m_emitingEditingFinished(0), m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), - hideCursor(false), separator(0), readOnly(0), - dragEnabled(0), m_echoMode(0), textDirty(0), selDirty(0), - validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), - m_ascent(0), m_maxLength(32767), lastCursorPos(-1), - m_tripleClickTimer(0), maskData(0), modifiedState(0), undoState(0), - selstart(0), selend(0), m_passwordEchoEditing(false) + m_hideCursor(false), m_separator(0), m_readOnly(0), + m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), + m_validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), + m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1), + m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0), + m_selstart(0), m_selend(0), m_passwordEchoEditing(false) { init(txt); } ~QLineControl() { - delete [] maskData; + delete [] m_maskData; } int nextMaskBlank(int pos); @@ -154,7 +154,7 @@ public: void setReadOnly(bool enable); QString text() const; - void setText(const QString &); + void setText(const QString &txt); QString displayText() const; @@ -218,7 +218,7 @@ public: void setCursorBlinkPeriod(int msec); QString cancelText() const; - void setCancelText(QString); + void setCancelText(const QString &text); enum DrawFlags { DrawText = 0x01, @@ -228,19 +228,26 @@ public: }; void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll); - bool processEvent(QEvent* ev); + bool processEvent(QEvent *ev); + + bool m_emitingEditingFinished; //Needed in QLineEdit FocusOut event - bool emitingEditingFinished;//Needed in QLineEdit FocusOut event private: - void init(const QString&); + void init(const QString &txt); void removeSelectedText(); - void p_setText(const QString& txt, int pos = -1, bool edited = true); + void p_setText(const QString &txt, int pos = -1, bool edited = true); void updateDisplayText(); - void p_insert(const QString& s); + void p_insert(const QString &s); void p_del(bool wasBackspace = false); void p_remove(int pos); - inline void p_deselect() { selDirty |= (selend > selstart); selstart = selend = 0; } + + inline void p_deselect() + { + m_selDirty |= (m_selend > m_selstart); + m_selstart = m_selend = 0; + } + void p_undo(int until = -1); void p_redo(); @@ -250,22 +257,22 @@ private: int m_preeditCursor; int m_cursorWidth; Qt::LayoutDirection m_layoutDirection; - uint hideCursor : 1; // used to hide the m_cursor inside preedit areas - uint separator : 1; - uint readOnly : 1; - uint dragEnabled : 1; + uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas + uint m_separator : 1; + uint m_readOnly : 1; + uint m_dragEnabled : 1; uint m_echoMode : 2; - uint textDirty : 1; - uint selDirty : 1; - uint validInput : 1; + uint m_textDirty : 1; + uint m_selDirty : 1; + uint m_validInput : 1; int m_blinkPeriod; // 0 for non-blinking cursor int m_blinkTimer; int m_deleteAllTimer; int m_blinkStatus; int m_ascent; int m_maxLength; - int lastCursorPos; - QList transactions; + int m_lastCursorPos; + QList m_transactions; QPoint m_tripleClick; int m_tripleClickTimer; QString m_cancelText; @@ -287,8 +294,8 @@ private: Casemode caseMode; }; QString m_inputMask; - QChar blank; - MaskInputData *maskData; + QChar m_blank; + MaskInputData *m_maskData; // undo/redo handling @@ -300,15 +307,16 @@ private: QChar uc; int pos, selStart, selEnd; }; - int modifiedState; - int undoState; - QVector history; + int m_modifiedState; + int m_undoState; + QVector m_history; void addCommand(const Command& cmd); - inline void separate() { separator = true; } + inline void separate() { m_separator = true; } // selection - int selstart, selend; + int m_selstart; + int m_selend; // masking void parseInputMask(const QString &maskFields); @@ -319,9 +327,8 @@ private: QString stripString(const QString &str) const; int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; - // complex text layout - QTextLayout textLayout; + QTextLayout m_textLayout; bool m_passwordEchoEditing; QChar m_passwordCharacter; @@ -339,8 +346,10 @@ Q_SIGNALS: void accepted(); void editingFinished(); void updateNeeded(const QRect &); + protected: - virtual void timerEvent ( QTimerEvent * event ); + virtual void timerEvent(QTimerEvent *event); + private slots: void _q_clipboardChanged(); void _q_deleteSelected(); @@ -350,61 +359,61 @@ private slots: inline int QLineControl::nextMaskBlank(int pos) { int c = findInMask(pos, true, false); - separator |= (c != pos); + m_separator |= (c != pos); return (c != -1 ? c : m_maxLength); } inline int QLineControl::prevMaskBlank(int pos) { int c = findInMask(pos, false, false); - separator |= (c != pos); + m_separator |= (c != pos); return (c != -1 ? c : 0); } inline bool QLineControl::isUndoAvailable() const { - return !readOnly && undoState; + return !m_readOnly && m_undoState; } inline bool QLineControl::isRedoAvailable() const { - return !readOnly && undoState < (int)history.size(); + return !m_readOnly && m_undoState < (int)m_history.size(); } inline void QLineControl::clearUndo() { - history.clear(); - modifiedState = undoState = 0; + m_history.clear(); + m_modifiedState = m_undoState = 0; } inline bool QLineControl::isModified() const { - return modifiedState != undoState; + return m_modifiedState != m_undoState; } inline void QLineControl::setModified(bool modified) { - modifiedState = modified ? -1 : undoState; + m_modifiedState = modified ? -1 : m_undoState; } inline bool QLineControl::allSelected() const { - return !m_text.isEmpty() && selstart == 0 && selend == (int)m_text.length(); + return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); } inline bool QLineControl::hasSelectedText() const { - return !m_text.isEmpty() && selend > selstart; + return !m_text.isEmpty() && m_selend > m_selstart; } inline int QLineControl::width() const { - return qRound(textLayout.lineAt(0).width()) + 1; + return qRound(m_textLayout.lineAt(0).width()) + 1; } inline int QLineControl::height() const { - return qRound(textLayout.lineAt(0).height()) + 1; + return qRound(m_textLayout.lineAt(0).height()) + 1; } inline int QLineControl::ascent() const @@ -415,32 +424,32 @@ inline int QLineControl::ascent() const inline QString QLineControl::selectedText() const { if (hasSelectedText()) - return m_text.mid(selstart, selend - selstart); + return m_text.mid(m_selstart, m_selend - m_selstart); return QString(); } inline QString QLineControl::textBeforeSelection() const { if (hasSelectedText()) - return m_text.left(selstart); + return m_text.left(m_selstart); return QString(); } inline QString QLineControl::textAfterSelection() const { if (hasSelectedText()) - return m_text.mid(selend); + return m_text.mid(m_selend); return QString(); } inline int QLineControl::selectionStart() const { - return hasSelectedText() ? selstart : -1; + return hasSelectedText() ? m_selstart : -1; } inline int QLineControl::selectionEnd() const { - return hasSelectedText() ? selend : -1; + return hasSelectedText() ? m_selend : -1; } inline int QLineControl::start() const @@ -455,17 +464,17 @@ inline int QLineControl::end() const inline void QLineControl::removeSelection() { - int priorState = undoState; + int priorState = m_undoState; removeSelectedText(); finishChange(priorState); } inline bool QLineControl::inSelection(int x) const { - if (selstart >= selend) + if (m_selstart >= m_selend) return false; int pos = xToPos(x, QTextLine::CursorOnCharacter); - return pos >= selstart && pos < selend; + return pos >= m_selstart && pos < m_selend; } inline int QLineControl::cursor() const @@ -492,18 +501,18 @@ inline void QLineControl::cursorForward(bool mark, int steps) { int c = m_cursor; if (steps > 0) { - while(steps--) - c = textLayout.nextCursorPosition(c); + while (steps--) + c = m_textLayout.nextCursorPosition(c); } else if (steps < 0) { while (steps++) - c = textLayout.previousCursorPosition(c); + c = m_textLayout.previousCursorPosition(c); } moveCursor(c, mark); } inline void QLineControl::cursorWordForward(bool mark) { - moveCursor(textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); + moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); } inline void QLineControl::home(bool mark) @@ -518,12 +527,12 @@ inline void QLineControl::end(bool mark) inline void QLineControl::cursorWordBackward(bool mark) { - moveCursor(textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); + moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); } inline qreal QLineControl::cursorToX(int cursor) const { - return textLayout.lineAt(0).cursorToX(cursor); + return m_textLayout.lineAt(0).cursorToX(cursor); } inline qreal QLineControl::cursorToX() const @@ -533,17 +542,17 @@ inline qreal QLineControl::cursorToX() const inline bool QLineControl::isReadOnly() const { - return readOnly; + return m_readOnly; } inline void QLineControl::setReadOnly(bool enable) { - readOnly = enable; + m_readOnly = enable; } inline QString QLineControl::text() const { - QString res = maskData ? stripString(m_text) : m_text; + QString res = m_maskData ? stripString(m_text) : m_text; return (res.isNull() ? QString::fromLatin1("") : res); } @@ -554,7 +563,7 @@ inline void QLineControl::setText(const QString &txt) inline QString QLineControl::displayText() const { - return textLayout.text(); + return m_textLayout.text(); } inline void QLineControl::deselect() @@ -565,7 +574,7 @@ inline void QLineControl::deselect() inline void QLineControl::selectAll() { - selstart = selend = m_cursor = 0; + m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); } @@ -595,7 +604,7 @@ inline void QLineControl::setEchoMode(uint mode) inline void QLineControl::setMaxLength(int maxLength) { - if (maskData) + if (m_maskData) return; m_maxLength = maxLength; setText(m_text); @@ -649,13 +658,13 @@ inline bool QLineControl::hasAcceptableInput() const inline QString QLineControl::inputMask() const { - return maskData ? m_inputMask + QLatin1Char(';') + blank : QString(); + return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); } inline void QLineControl::setInputMask(const QString &mask) { parseInputMask(mask); - if (maskData) + if (m_maskData) moveCursor(nextMaskBlank(0)); } @@ -663,18 +672,18 @@ inline void QLineControl::setInputMask(const QString &mask) #ifndef QT_NO_IM inline bool QLineControl::composeMode() const { - return !textLayout.preeditAreaText().isEmpty(); + return !m_textLayout.preeditAreaText().isEmpty(); } inline void QLineControl::setPreeditArea(int cursor, const QString &text) { - textLayout.setPreeditArea(cursor, text); + m_textLayout.setPreeditArea(cursor, text); } #endif inline QString QLineControl::preeditAreaText() const { - return textLayout.preeditAreaText(); + return m_textLayout.preeditAreaText(); } inline bool QLineControl::passwordEchoEditing() const @@ -708,7 +717,7 @@ inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction) inline void QLineControl::setFont(const QFont &font) { - textLayout.setFont(font); + m_textLayout.setFont(font); updateDisplayText(); } @@ -722,9 +731,9 @@ inline QString QLineControl::cancelText() const return m_cancelText; } -inline void QLineControl::setCancelText(QString s) +inline void QLineControl::setCancelText(const QString &text) { - m_cancelText = s; + m_cancelText = text; } QT_END_NAMESPACE diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 9252888..6deb196 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1727,11 +1727,11 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (!d->control->emitingEditingFinished) { + if (!d->control->m_emitingEditingFinished) { if (hasAcceptableInput() || d->control->fixup()) { - d->control->emitingEditingFinished = true; + d->control->m_emitingEditingFinished = true; emit editingFinished(); - d->control->emitingEditingFinished = false; + d->control->m_emitingEditingFinished = false; } } #ifdef QT3_SUPPORT diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index c6d7496..230023d 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -135,7 +135,6 @@ public: void drag(); #endif - int leftTextMargin; int topTextMargin; int rightTextMargin; -- cgit v0.12 From 4a2e73a06eb9cba373f9662700883bd3bd7f5047 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 16:34:13 +0200 Subject: Rename the p_foo() functions in QLineControl to internalFoo(). --- src/gui/widgets/qlinecontrol.cpp | 39 ++++++++++++++++++++------------------- src/gui/widgets/qlinecontrol_p.h | 23 +++++++++++------------ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 50ce6e6..ba85182 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -167,11 +167,11 @@ void QLineControl::backspace() // if yes delete both at once uc = m_text.at(m_cursor - 1); if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { - p_del(true); + internalDelete(true); --m_cursor; } } - p_del(true); + internalDelete(true); } finishChange(priorState); } @@ -193,7 +193,7 @@ void QLineControl::del() } else { int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; while (n--) - p_del(); + internalDelete(); } finishChange(priorState); } @@ -209,7 +209,7 @@ void QLineControl::insert(const QString &newText) { int priorState = m_undoState; removeSelectedText(); - p_insert(newText); + internalInsert(newText); finishChange(priorState); } @@ -343,7 +343,7 @@ bool QLineControl::fixup() // this function assumes that validate currently retu m_validator->fixup(textCopy); if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { if (textCopy != m_text || cursorCopy != m_cursor) - p_setText(textCopy, cursorCopy); + internalSetText(textCopy, cursorCopy); return true; } } @@ -376,7 +376,7 @@ void QLineControl::moveCursor(int pos, bool mark) m_selend = qMax(anchor, pos); updateDisplayText(); } else { - p_deselect(); + internalDeselect(); } m_cursor = pos; if (mark || m_selDirty) { @@ -531,7 +531,7 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); if (m_validInput) { if (m_text != textCopy) { - p_setText(textCopy, cursorCopy); + internalSetText(textCopy, cursorCopy); return true; } m_cursor = cursorCopy; @@ -541,7 +541,7 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) if (validateFromState >= 0 && wasValidInput && !m_validInput) { if (m_transactions.count()) return false; - p_undo(validateFromState); + internalUndo(validateFromState); m_history.resize(m_undoState); if (m_modifiedState > m_undoState) m_modifiedState = -1; @@ -571,9 +571,9 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) An internal function for setting the text of the line control. */ -void QLineControl::p_setText(const QString &txt, int pos, bool edited) +void QLineControl::internalSetText(const QString &txt, int pos, bool edited) { - p_deselect(); + internalDeselect(); emit resetInputContext(); QString oldText = m_text; if (m_maskData) { @@ -618,7 +618,7 @@ void QLineControl::addCommand(const Command &cmd) This function does not call finishChange(), and may leave the text in an invalid state. */ -void QLineControl::p_insert(const QString &s) +void QLineControl::internalInsert(const QString &s) { if (hasSelectedText()) addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); @@ -654,7 +654,7 @@ void QLineControl::p_insert(const QString &s) This function does not call finishChange(), and may leave the text in an invalid state. */ -void QLineControl::p_del(bool wasBackspace) +void QLineControl::internalDelete(bool wasBackspace) { if (m_cursor < (int) m_text.length()) { if (hasSelectedText()) @@ -706,7 +706,7 @@ void QLineControl::removeSelectedText() } if (m_cursor > m_selstart) m_cursor -= qMin(m_cursor, m_selend) - m_selstart; - p_deselect(); + internalDeselect(); m_textDirty = true; } } @@ -725,7 +725,7 @@ void QLineControl::parseInputMask(const QString &maskFields) delete [] m_maskData; m_maskData = 0; m_maxLength = 32767; - p_setText(QString()); + internalSetText(QString()); } return; } @@ -811,7 +811,7 @@ void QLineControl::parseInputMask(const QString &maskFields) } } } - p_setText(m_text); + internalSetText(m_text); } @@ -1077,11 +1077,11 @@ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar se return -1; } -void QLineControl::p_undo(int until) +void QLineControl::internalUndo(int until) { if (!isUndoAvailable()) return; - p_deselect(); + internalDeselect(); while (m_undoState && m_undoState > until) { Command& cmd = m_history[--m_undoState]; switch (cmd.type) { @@ -1118,10 +1118,11 @@ void QLineControl::p_undo(int until) emitCursorPositionChanged(); } -void QLineControl::p_redo() { +void QLineControl::internalRedo() +{ if (!isRedoAvailable()) return; - p_deselect(); + internalDeselect(); while (m_undoState < (int)m_history.size()) { Command& cmd = m_history[m_undoState++]; switch (cmd.type) { diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 6029989..68ff66b 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -235,21 +235,21 @@ public: private: void init(const QString &txt); void removeSelectedText(); - void p_setText(const QString &txt, int pos = -1, bool edited = true); + void internalSetText(const QString &txt, int pos = -1, bool edited = true); void updateDisplayText(); - void p_insert(const QString &s); - void p_del(bool wasBackspace = false); - void p_remove(int pos); + void internalInsert(const QString &s); + void internalDelete(bool wasBackspace = false); + void internalRemove(int pos); - inline void p_deselect() + inline void internalDeselect() { m_selDirty |= (m_selend > m_selstart); m_selstart = m_selend = 0; } - void p_undo(int until = -1); - void p_redo(); + void internalUndo(int until = -1); + void internalRedo(); QString m_text; QPalette m_palette; @@ -297,7 +297,6 @@ private: QChar m_blank; MaskInputData *m_maskData; - // undo/redo handling enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; struct Command { @@ -558,7 +557,7 @@ inline QString QLineControl::text() const inline void QLineControl::setText(const QString &txt) { - p_setText(txt, -1, false); + internalSetText(txt, -1, false); } inline QString QLineControl::displayText() const @@ -568,7 +567,7 @@ inline QString QLineControl::displayText() const inline void QLineControl::deselect() { - p_deselect(); + internalDeselect(); finishChange(); } @@ -580,13 +579,13 @@ inline void QLineControl::selectAll() inline void QLineControl::undo() { - p_undo(); + internalUndo(); finishChange(-1, true); } inline void QLineControl::redo() { - p_redo(); + internalRedo(); finishChange(); } -- cgit v0.12 From 6263185ab45f533efea6c8f397092afb625cd929 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 16 Jul 2009 10:07:10 +1000 Subject: Remove emitingEditingFinished from QLineControl Doesn't seem to hurt anything, and it was ugly API. --- src/gui/widgets/qlinecontrol.cpp | 2 -- src/gui/widgets/qlinecontrol_p.h | 5 +---- src/gui/widgets/qlineedit.cpp | 18 ++++-------------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index ba85182..97f4a45 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1497,9 +1497,7 @@ void QLineControl::processKeyEvent(QKeyEvent* event) if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput() || fixup()) { emit accepted(); - m_emitingEditingFinished = true; emit editingFinished(); - m_emitingEditingFinished = false; } if (inlineCompletionAccepted) event->accept(); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 68ff66b..1e5c144 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -78,8 +78,7 @@ class Q_GUI_EXPORT QLineControl : public QObject public: QLineControl(const QString &txt = QString()) - : m_emitingEditingFinished(0), - m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), + : m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), m_hideCursor(false), m_separator(0), m_readOnly(0), m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), m_validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), @@ -230,8 +229,6 @@ public: bool processEvent(QEvent *ev); - bool m_emitingEditingFinished; //Needed in QLineEdit FocusOut event - private: void init(const QString &txt); void removeSelectedText(); diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 6deb196..e0f5bc9 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1393,15 +1393,10 @@ bool QLineEdit::event(QEvent * e) } else if (e->type() == QEvent::LeaveEditFocus) { d->setCursorVisible(false); d->control->setCursorBlinkPeriod(0); - if (!d->control->emitingEditingFinished) { - if (d->control->hasAcceptableInput() || d->control->fixup()) { - d->control->emitingEditingFinished = true; - emit editingFinished(); - d->control->emitingEditingFinished = false; - } - } + if (d->control->hasAcceptableInput() || d->control->fixup()) + emit editingFinished(); } - return; + return true; } #endif return QWidget::event(e); @@ -1727,13 +1722,8 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (!d->control->m_emitingEditingFinished) { - if (hasAcceptableInput() || d->control->fixup()) { - d->control->m_emitingEditingFinished = true; + if (hasAcceptableInput() || d->control->fixup()) emit editingFinished(); - d->control->m_emitingEditingFinished = false; - } - } #ifdef QT3_SUPPORT emit lostFocus(); #endif -- cgit v0.12