diff options
author | Andrew den Exter <andrew.den-exter@nokia.com> | 2012-07-06 16:05:33 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-07-24 07:53:05 +0200 |
commit | 919b60b4fcc72fdcd5dc0e80e642f922da17cd96 (patch) | |
tree | a76188afdfa613a1199e8650354578f1027714e6 /src/quick | |
parent | dbe4d2010816f1f22f48f3f5bce0d15d3ad7a7e2 (diff) |
Fix restoration of cursor position and selection after undo/redo.
If a text selection was deleted, the selection should be restored by an
undo, but not if the selection was part of an atomic operation like
the DeleteStartOfWord key sequence.
Change-Id: Ia37f29c78f6367c60377c539c4e394e014485a49
Reviewed-by: Yann Bodson <yann.bodson@nokia.com>
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquicktextinput.cpp | 133 | ||||
-rw-r--r-- | src/quick/items/qquicktextinput_p_p.h | 5 |
2 files changed, 103 insertions, 35 deletions
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index bb38e516e0..4dbd39e826 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -2815,7 +2815,7 @@ void QQuickTextInputPrivate::cancelPreedit() void QQuickTextInputPrivate::backspace() { int priorState = m_undoState; - if (hasSelectedText()) { + if (separateSelection()) { removeSelectedText(); } else if (m_cursor) { --m_cursor; @@ -2848,7 +2848,7 @@ void QQuickTextInputPrivate::backspace() void QQuickTextInputPrivate::del() { int priorState = m_undoState; - if (hasSelectedText()) { + if (separateSelection()) { removeSelectedText(); } else { int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; @@ -2868,7 +2868,8 @@ void QQuickTextInputPrivate::del() void QQuickTextInputPrivate::insert(const QString &newText) { int priorState = m_undoState; - removeSelectedText(); + if (separateSelection()) + removeSelectedText(); internalInsert(newText); finishChange(priorState); } @@ -2881,6 +2882,7 @@ void QQuickTextInputPrivate::insert(const QString &newText) void QQuickTextInputPrivate::clear() { int priorState = m_undoState; + separateSelection(); m_selstart = 0; m_selend = m_text.length(); removeSelectedText(); @@ -3031,6 +3033,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event) if (isGettingInput) { // If any text is being input, remove selected text. priorState = m_undoState; + separateSelection(); if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing) { updatePasswordEchoEditing(true); m_selstart = 0; @@ -3303,8 +3306,7 @@ void QQuickTextInputPrivate::internalInsert(const QString &s) if (delay > 0) m_passwordEchoTimer.start(delay, q); } - if (hasSelectedText()) - addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + Q_ASSERT(!hasSelectedText()); // insert(), processInputMethodEvent() call removeSelectedText() first. if (m_maskData) { QString ms = maskString(m_cursor, s); for (int i = 0; i < (int) ms.length(); ++i) { @@ -3341,8 +3343,7 @@ void QQuickTextInputPrivate::internalDelete(bool wasBackspace) { if (m_cursor < (int) m_text.length()) { cancelPasswordEchoTimer(); - if (hasSelectedText()) - addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + Q_ASSERT(!hasSelectedText()); // del(), backspace() call removeSelectedText() first. addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); if (m_maskData) { @@ -3368,9 +3369,7 @@ void QQuickTextInputPrivate::removeSelectedText() { if (m_selstart < m_selend && m_selend <= (int) m_text.length()) { cancelPasswordEchoTimer(); - separate(); int i ; - 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 @@ -3399,6 +3398,25 @@ void QQuickTextInputPrivate::removeSelectedText() /*! \internal + Adds the current selection to the undo history. + + Returns true if there is a current selection and false otherwise. +*/ + +bool QQuickTextInputPrivate::separateSelection() +{ + if (hasSelectedText()) { + separate(); + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + return true; + } else { + return false; + } +} + +/*! + \internal + Parses the input mask specified by \a maskFields to generate the mask data used to handle input masks. */ @@ -3797,11 +3815,14 @@ void QQuickTextInputPrivate::internalUndo(int until) } 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)) + if (next.type != cmd.type + && next.type < RemoveSelection + && (cmd.type < RemoveSelection || next.type == Separator)) { break; + } } } + separate(); m_textDirty = true; } @@ -3839,9 +3860,12 @@ void QQuickTextInputPrivate::internalRedo() } 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)) + if (next.type != cmd.type + && cmd.type < RemoveSelection + && next.type != Separator + && (next.type < RemoveSelection || cmd.type == Separator)) { break; + } } } m_textDirty = true; @@ -3937,16 +3961,12 @@ void QQuickTextInput::timerEvent(QTimerEvent *event) void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) { Q_Q(QQuickTextInput); - bool inlineCompletionAccepted = false; if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput(m_text) || fixup()) { emit q->accepted(); } - if (inlineCompletionAccepted) - event->accept(); - else - event->ignore(); + event->ignore(); return; } @@ -3996,11 +4016,8 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) } } else if (event == QKeySequence::DeleteEndOfLine) { - if (!m_readOnly) { - setSelection(m_cursor, end()); - copy(); - del(); - } + if (!m_readOnly) + deleteEndOfLine(); } #endif //QT_NO_CLIPBOARD else if (event == QKeySequence::MoveToStartOfLine || event == QKeySequence::MoveToStartOfBlock) { @@ -4065,16 +4082,12 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) del(); } else if (event == QKeySequence::DeleteEndOfWord) { - if (!m_readOnly) { - cursorWordForward(true); - del(); - } + if (!m_readOnly) + deleteEndOfWord(); } else if (event == QKeySequence::DeleteStartOfWord) { - if (!m_readOnly) { - cursorWordBackward(true); - del(); - } + if (!m_readOnly) + deleteStartOfWord(); } #endif // QT_NO_SHORTCUT else { @@ -4082,10 +4095,8 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) if (event->modifiers() & Qt::ControlModifier) { switch (event->key()) { case Qt::Key_Backspace: - if (!m_readOnly) { - cursorWordBackward(true); - del(); - } + if (!m_readOnly) + deleteStartOfWord(); break; default: if (!handled) @@ -4125,6 +4136,58 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) event->accept(); } +/*! + \internal + + Deletes the portion of the word before the current cursor position. +*/ + +void QQuickTextInputPrivate::deleteStartOfWord() +{ + int priorState = m_undoState; + Command cmd(SetSelection, m_cursor, 0, m_selstart, m_selend); + separate(); + cursorWordBackward(true); + addCommand(cmd); + removeSelectedText(); + finishChange(priorState); +} + +/*! + \internal + + Deletes the portion of the word after the current cursor position. +*/ + +void QQuickTextInputPrivate::deleteEndOfWord() +{ + int priorState = m_undoState; + Command cmd(SetSelection, m_cursor, 0, m_selstart, m_selend); + separate(); + cursorWordForward(true); + // moveCursor (sometimes) calls separate() so we need to add the command after that so the + // cursor position and selection are restored in the same undo operation as the remove. + addCommand(cmd); + removeSelectedText(); + finishChange(priorState); +} + +/*! + \internal + + Deletes all text from the cursor position to the end of the line. +*/ + +void QQuickTextInputPrivate::deleteEndOfLine() +{ + int priorState = m_undoState; + Command cmd(SetSelection, m_cursor, 0, m_selstart, m_selend); + separate(); + setSelection(m_cursor, end()); + addCommand(cmd); + removeSelectedText(); + finishChange(priorState); +} QT_END_NAMESPACE diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 0cc0846a5e..e147c17d96 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -435,6 +435,11 @@ private: inline void separate() { m_separator = true; } + bool separateSelection(); + void deleteStartOfWord(); + void deleteEndOfWord(); + void deleteEndOfLine(); + enum ValidatorState { #ifndef QT_NO_VALIDATOR InvalidInput = QValidator::Invalid, |