diff options
| author | Andre Hartmann <aha_1980@gmx.de> | 2017-07-30 21:39:50 +0200 |
|---|---|---|
| committer | André Hartmann <aha_1980@gmx.de> | 2019-08-02 06:40:56 +0000 |
| commit | 839f45faa91bc3a1743c24c3f9f5ee619de9da09 (patch) | |
| tree | 00c9f2f514cc64d2f43a8c7a24e4ce766da28aac /src/libs/utils/camelcasecursor.cpp | |
| parent | 71e9e3832af3b4201c440c704159c3d42e5ff12d (diff) | |
| download | qt-creator-839f45faa91bc3a1743c24c3f9f5ee619de9da09.tar.gz | |
FancyLineEdit: Add camel case navigation
Use it for search and replace functions as well as for Locator.
The camel case navigation can be switched on / off with
the existing menu Options > Text Editor > Behavior >
Enable Build-in camel case navigation.
Fixes: QTCREATORBUG-21140
Change-Id: I3f2dcafff231366b3c8f08c14514dd8940cca2a0
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Diffstat (limited to 'src/libs/utils/camelcasecursor.cpp')
| -rw-r--r-- | src/libs/utils/camelcasecursor.cpp | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/src/libs/utils/camelcasecursor.cpp b/src/libs/utils/camelcasecursor.cpp new file mode 100644 index 0000000000..65e69bd70b --- /dev/null +++ b/src/libs/utils/camelcasecursor.cpp @@ -0,0 +1,341 @@ +/************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "camelcasecursor.h" + +#include <QLineEdit> +#include <QPlainTextEdit> + +template<typename C, typename E> +bool moveCursor(C *cursor, E *edit, QTextCursor::MoveOperation direction, QTextCursor::MoveMode mode); + +template<> +bool moveCursor(QTextCursor *cursor, QPlainTextEdit *, QTextCursor::MoveOperation direction, + QTextCursor::MoveMode mode) +{ + return cursor->movePosition(direction, mode); +} + +template<typename C> +bool moveCursor(C *, QLineEdit *edit, QTextCursor::MoveOperation direction, QTextCursor::MoveMode mode) +{ + bool mark = (mode == QTextCursor::KeepAnchor); + switch (direction) { + case QTextCursor::Left: + edit->cursorBackward(mark); + break; + case QTextCursor::WordLeft: + edit->cursorWordBackward(mark); + break; + case QTextCursor::Right: + edit->cursorForward(mark); + break; + case QTextCursor::WordRight: + edit->cursorWordForward(mark); + break; + default: + return false; + } + return edit->cursorPosition() > 0 && edit->cursorPosition() < edit->text().size(); +} + +template<typename C, typename E> +QChar charUnderCursor(C *cursor, E *edit); + +template<> +QChar charUnderCursor(QTextCursor *cursor, QPlainTextEdit *edit) +{ + return edit->document()->characterAt(cursor->position()); +} + +template<typename C> +QChar charUnderCursor(C *, QLineEdit *edit) +{ + const int pos = edit->cursorPosition(); + if (pos < 0 || pos >= edit->text().length()) + return QChar::Null; + + return edit->text().at(pos); +}; + +template<typename C, typename E> +int position(C *cursor, E *edit); + +template<> +int position(QTextCursor *cursor, QPlainTextEdit *) +{ + return cursor->position(); +} + +template<typename C> +int position(C *, QLineEdit *edit) +{ + return edit->cursorPosition(); +} + +enum class Input { + Upper, + Lower, + Underscore, + Space, + Other +}; + +template<typename C, typename E> +bool camelCaseLeft(C *cursor, E *edit, QTextCursor::MoveMode mode) +{ + int state = 0; + + if (!moveCursor(cursor, edit, QTextCursor::Left, mode)) + return false; + + for (;;) { + QChar c = charUnderCursor(cursor, edit); + Input input = Input::Other; + if (c.isUpper()) + input = Input::Upper; + else if (c.isLower() || c.isDigit()) + input = Input::Lower; + else if (c == '_') + input = Input::Underscore; + else if (c.isSpace() && c != QChar::ParagraphSeparator) + input = Input::Space; + else + input = Input::Other; + + switch (state) { + case 0: + switch (input) { + case Input::Upper: + state = 1; + break; + case Input::Lower: + state = 2; + break; + case Input::Underscore: + state = 3; + break; + case Input::Space: + state = 4; + break; + default: + moveCursor(cursor, edit, QTextCursor::Right, mode); + return moveCursor(cursor, edit, QTextCursor::WordLeft, mode); + } + break; + case 1: + switch (input) { + case Input::Upper: + break; + default: + return moveCursor(cursor, edit, QTextCursor::Right, mode); + return true; + } + break; + case 2: + switch (input) { + case Input::Upper: + return true; + case Input::Lower: + break; + default: + return moveCursor(cursor, edit, QTextCursor::Right, mode); + return true; + } + break; + case 3: + switch (input) { + case Input::Underscore: + break; + case Input::Upper: + state = 1; + break; + case Input::Lower: + state = 2; + break; + default: + moveCursor(cursor, edit, QTextCursor::Right, mode); + return true; + } + break; + case 4: + switch (input) { + case Input::Space: + break; + case Input::Upper: + state = 1; + break; + case Input::Lower: + state = 2; + break; + case Input::Underscore: + state = 3; + break; + default: + return moveCursor(cursor, edit, QTextCursor::Right, mode); + if (position(cursor, edit) == 0) + return true; + return moveCursor(cursor, edit, QTextCursor::WordLeft, mode); + } + } + + if (!moveCursor(cursor, edit, QTextCursor::Left, mode)) + return true; + } +} + +template<typename C, typename E> +bool camelCaseRight(C *cursor, E *edit, QTextCursor::MoveMode mark) +{ + int state = 0; + + for (;;) { + QChar c = charUnderCursor(cursor, edit); + Input input = Input::Other; + if (c.isUpper()) + input = Input::Upper; + else if (c.isLower() || c.isDigit()) + input = Input::Lower; + else if (c == '_') + input = Input::Underscore; + else if (c.isSpace() && c != QChar::ParagraphSeparator) + input = Input::Space; + else + input = Input::Other; + + switch (state) { + case 0: + switch (input) { + case Input::Upper: + state = 4; + break; + case Input::Lower: + state = 1; + break; + case Input::Underscore: + state = 6; + break; + default: + return moveCursor(cursor, edit, QTextCursor::WordRight, mark); + } + break; + case 1: + switch (input) { + case Input::Upper: + return true; + case Input::Lower: + break; + case Input::Underscore: + state = 6; + break; + case Input::Space: + state = 7; + break; + default: + return true; + } + break; + case 2: + switch (input) { + case Input::Upper: + break; + case Input::Lower: + moveCursor(cursor, edit, QTextCursor::Left, mark); + return true; + case Input::Underscore: + state = 6; + break; + case Input::Space: + state = 7; + break; + default: + return true; + } + break; + case 4: + switch (input) { + case Input::Upper: + state = 2; + break; + case Input::Lower: + state = 1; + break; + case Input::Underscore: + state = 6; + break; + case Input::Space: + state = 7; + break; + default: + return true; + } + break; + case 6: + switch (input) { + case Input::Underscore: + break; + case Input::Space: + state = 7; + break; + default: + return true; + } + break; + case 7: + switch (input) { + case Input::Space: + break; + default: + return true; + } + break; + } + if (!moveCursor(cursor, edit, QTextCursor::Right, mark)) + return false; + } +} + +bool CamelCaseCursor::left(QTextCursor *cursor, QPlainTextEdit *edit, QTextCursor::MoveMode mode) +{ + return camelCaseLeft(cursor, edit, mode); +} + +bool CamelCaseCursor::left(QLineEdit *edit, QTextCursor::MoveMode mode) +{ + QTextCursor temp; + return camelCaseLeft(&temp, edit, mode); +} + +bool CamelCaseCursor::right(QTextCursor *cursor, QPlainTextEdit *edit, QTextCursor::MoveMode mode) +{ + return camelCaseRight(cursor, edit, mode); +} + +bool CamelCaseCursor::right(QLineEdit *edit, QTextCursor::MoveMode mode) +{ + QTextCursor temp; + return camelCaseRight(&temp, edit, mode); +} |
