forked from qt-creator/qt-creator
Editor: Blockselection rewrite.
Also adding the possibility to insert text into the blockselection. Task-number: QTCREATORBUG-7773 Change-Id: I7a47a1d630f769a8253ee1a2f21057820ea170d5 Reviewed-by: Lukas Holecek <hluk@email.cz> Reviewed-by: Christian Stenger <christian.stenger@digia.com> Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -1800,12 +1800,19 @@ public:
|
||||
}
|
||||
// Set cursor in text editor widget.
|
||||
void commitCursor() {
|
||||
if (isVisualBlockMode()) {
|
||||
emit q->requestSetBlockSelection(m_cursor);
|
||||
} else {
|
||||
emit q->requestDisableBlockSelection();
|
||||
if (editor())
|
||||
EDITOR(setTextCursor(m_cursor));
|
||||
}
|
||||
}
|
||||
// Restore cursor from editor widget.
|
||||
void pullCursor() {
|
||||
if (editor())
|
||||
if (isVisualBlockMode())
|
||||
q->requestBlockSelection(&m_cursor);
|
||||
else if (editor())
|
||||
m_cursor = EDITOR(textCursor());
|
||||
}
|
||||
|
||||
@@ -2500,14 +2507,12 @@ void FakeVimHandler::Private::exportSelection()
|
||||
const int col2 = pos - document()->findBlock(pos).position();
|
||||
if (col1 > col2)
|
||||
++anc;
|
||||
else if (!atEndOfLine())
|
||||
else if (!atBlockEnd())
|
||||
++pos;
|
||||
// FIXME: After '$' command (i.e. m_visualTargetColumn == -1), end of selected lines
|
||||
// should be selected.
|
||||
setAnchorAndPosition(anc, pos);
|
||||
commitCursor();
|
||||
emit q->requestSetBlockSelection(false);
|
||||
emit q->requestSetBlockSelection(true);
|
||||
} else if (g.visualMode == VisualLineMode) {
|
||||
const int posLine = lineForPosition(pos);
|
||||
const int ancLine = lineForPosition(anc);
|
||||
@@ -2642,9 +2647,6 @@ void FakeVimHandler::Private::ensureCursorVisible()
|
||||
|
||||
void FakeVimHandler::Private::importSelection()
|
||||
{
|
||||
bool hasBlock = false;
|
||||
emit q->requestHasBlockSelection(&hasBlock);
|
||||
|
||||
if (position() == m_oldExternalPosition
|
||||
&& anchor() == m_oldExternalAnchor) {
|
||||
// Undo drawing correction.
|
||||
@@ -6867,8 +6869,6 @@ void FakeVimHandler::Private::scrollToLine(int line)
|
||||
EDITOR(ensureCursorVisible());
|
||||
|
||||
EDITOR(setTextCursor(tc));
|
||||
if (isVisualBlockMode())
|
||||
emit q->requestSetBlockSelection(true);
|
||||
|
||||
m_firstVisibleLine = line;
|
||||
}
|
||||
@@ -7388,15 +7388,11 @@ bool FakeVimHandler::Private::passEventToEditor(QEvent &event)
|
||||
{
|
||||
removeEventFilter();
|
||||
|
||||
commitCursor();
|
||||
|
||||
EDITOR(setOverwriteMode(false));
|
||||
emit q->requestSetBlockSelection(false);
|
||||
commitCursor();
|
||||
bool accepted = QApplication::sendEvent(editor(), &event);
|
||||
if (!m_textedit && !m_plaintextedit)
|
||||
return false;
|
||||
if (isVisualBlockMode())
|
||||
emit q->requestSetBlockSelection(true);
|
||||
updateCursorShape();
|
||||
|
||||
if (accepted)
|
||||
@@ -7567,7 +7563,6 @@ void FakeVimHandler::Private::toggleVisualMode(VisualMode visualMode)
|
||||
if (visualMode == g.visualMode) {
|
||||
leaveVisualMode();
|
||||
} else {
|
||||
emit q->requestSetBlockSelection(false);
|
||||
m_positionPastEnd = false;
|
||||
m_anchorPastEnd = false;
|
||||
g.visualMode = visualMode;
|
||||
|
||||
@@ -148,7 +148,9 @@ signals:
|
||||
void findRequested(bool reverse);
|
||||
void findNextRequested(bool reverse);
|
||||
void handleExCommandRequested(bool *handled, const ExCommand &cmd);
|
||||
void requestSetBlockSelection(bool on);
|
||||
void requestDisableBlockSelection();
|
||||
void requestSetBlockSelection(const QTextCursor&);
|
||||
void requestBlockSelection(QTextCursor*);
|
||||
void requestHasBlockSelection(bool *on);
|
||||
void foldToggle(int depth);
|
||||
void foldAll(bool fold);
|
||||
|
||||
@@ -1018,7 +1018,9 @@ private slots:
|
||||
void jumpToGlobalMark(QChar mark, bool backTickMode, const QString &fileName);
|
||||
void showSettingsDialog();
|
||||
void maybeReadVimRc();
|
||||
void setBlockSelection(bool);
|
||||
void disableBlockSelection();
|
||||
void setBlockSelection(const QTextCursor&);
|
||||
void blockSelection(QTextCursor *);
|
||||
void hasBlockSelection(bool*);
|
||||
void setShowRelativeLineNumbers(const QVariant &value);
|
||||
|
||||
@@ -1767,8 +1769,12 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
||||
SLOT(indentRegion(int,int,QChar)));
|
||||
connect(handler, SIGNAL(checkForElectricCharacter(bool*,QChar)),
|
||||
SLOT(checkForElectricCharacter(bool*,QChar)), Qt::DirectConnection);
|
||||
connect(handler, SIGNAL(requestSetBlockSelection(bool)),
|
||||
SLOT(setBlockSelection(bool)));
|
||||
connect(handler, SIGNAL(requestDisableBlockSelection()),
|
||||
SLOT(disableBlockSelection()));
|
||||
connect(handler, SIGNAL(requestSetBlockSelection(QTextCursor)),
|
||||
SLOT(setBlockSelection(QTextCursor)));
|
||||
connect(handler, SIGNAL(requestBlockSelection(QTextCursor*)),
|
||||
SLOT(blockSelection(QTextCursor*)), Qt::DirectConnection);
|
||||
connect(handler, SIGNAL(requestHasBlockSelection(bool*)),
|
||||
SLOT(hasBlockSelection(bool*)), Qt::DirectConnection);
|
||||
connect(handler, SIGNAL(completionRequested()),
|
||||
@@ -1864,13 +1870,32 @@ void FakeVimPluginPrivate::triggerSimpleCompletions(const QString &needle, bool
|
||||
m_wordProvider->setActive(needle, forward, qobject_cast<FakeVimHandler *>(sender()));
|
||||
}
|
||||
|
||||
void FakeVimPluginPrivate::setBlockSelection(bool on)
|
||||
void FakeVimPluginPrivate::disableBlockSelection()
|
||||
{
|
||||
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
|
||||
if (!handler)
|
||||
return;
|
||||
if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
|
||||
bt->setBlockSelection(on);
|
||||
bt->setBlockSelection(false);
|
||||
}
|
||||
|
||||
void FakeVimPluginPrivate::setBlockSelection(const QTextCursor &cursor)
|
||||
{
|
||||
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
|
||||
if (!handler)
|
||||
return;
|
||||
if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
|
||||
bt->setBlockSelection(cursor);
|
||||
}
|
||||
|
||||
void FakeVimPluginPrivate::blockSelection(QTextCursor *cursor)
|
||||
{
|
||||
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
|
||||
if (!handler)
|
||||
return;
|
||||
if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
|
||||
if (cursor)
|
||||
*cursor = bt->blockSelection();
|
||||
}
|
||||
|
||||
void FakeVimPluginPrivate::hasBlockSelection(bool *on)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -206,11 +206,16 @@ public:
|
||||
|
||||
void setReadOnly(bool b);
|
||||
|
||||
void setTextCursor(const QTextCursor &cursor, bool keepBlockSelection);
|
||||
void setTextCursor(const QTextCursor &cursor);
|
||||
|
||||
void insertCodeSnippet(const QTextCursor &cursor, const QString &snippet);
|
||||
|
||||
void setBlockSelection(bool on);
|
||||
void setBlockSelection(int positionBlock, int positionColumn, int anchhorBlock,
|
||||
int anchorColumn);
|
||||
void setBlockSelection(const QTextCursor &cursor);
|
||||
QTextCursor blockSelection() const;
|
||||
bool hasBlockSelection() const;
|
||||
|
||||
int verticalBlockSelectionFirstColumn() const;
|
||||
@@ -231,6 +236,9 @@ public:
|
||||
|
||||
static QString msgTextTooLarge(quint64 size);
|
||||
|
||||
void insertPlainText(const QString &text);
|
||||
QString selectedText() const;
|
||||
|
||||
public slots:
|
||||
virtual void copy();
|
||||
virtual void paste();
|
||||
@@ -310,6 +318,9 @@ public slots:
|
||||
void indent();
|
||||
void unindent();
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
void openLinkUnderCursor();
|
||||
void openLinkUnderCursorInNextSplit();
|
||||
|
||||
@@ -322,6 +333,7 @@ signals:
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e);
|
||||
void inputMethodEvent(QInputMethodEvent *e);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void wheelEvent(QWheelEvent *e);
|
||||
void changeEvent(QEvent *e);
|
||||
@@ -549,7 +561,6 @@ private:
|
||||
void transformBlockSelection(Internal::TransformationMethod method);
|
||||
|
||||
private slots:
|
||||
void handleBlockSelection(int diff_row, int diff_col);
|
||||
void updateTabStops();
|
||||
void applyFontSettingsDelayed();
|
||||
|
||||
|
||||
@@ -59,23 +59,34 @@ class ClipboardAssistProvider;
|
||||
class TEXTEDITOR_EXPORT BaseTextBlockSelection
|
||||
{
|
||||
public:
|
||||
BaseTextBlockSelection()
|
||||
: positionBlock(0), positionColumn(0)
|
||||
, anchorBlock(0) , anchorColumn(0){}
|
||||
BaseTextBlockSelection(const BaseTextBlockSelection &other);
|
||||
|
||||
bool isValid() const{ return !firstBlock.isNull() && !lastBlock.isNull(); }
|
||||
void clear() { firstBlock = lastBlock = QTextCursor(); }
|
||||
void clear();
|
||||
QTextCursor selection(const BaseTextDocument *baseTextDocument) const;
|
||||
QTextCursor cursor(const BaseTextDocument *baseTextDocument) const;
|
||||
void fromPostition(int positionBlock, int positionColumn, int anchorBlock, int anchorColumn);
|
||||
bool hasSelection() { return !(positionBlock == anchorBlock && positionColumn == anchorColumn); }
|
||||
|
||||
QTextCursor firstBlock; // defines the first block
|
||||
QTextCursor lastBlock; // defines the last block
|
||||
int firstVisualColumn; // defines the first visual column of the selection
|
||||
int lastVisualColumn; // defines the last visual column of the selection
|
||||
enum Anchor {TopLeft = 0, TopRight, BottomLeft, BottomRight} anchor;
|
||||
BaseTextBlockSelection():firstVisualColumn(0), lastVisualColumn(0), anchor(BottomRight){}
|
||||
void moveAnchor(int blockNumber, int visualColumn);
|
||||
int position(const TabSettings &ts) const;
|
||||
inline int anchorColumnNumber() const { return (anchor % 2) ? lastVisualColumn : firstVisualColumn; }
|
||||
inline int anchorBlockNumber() const {
|
||||
return (anchor <= TopRight ? firstBlock.blockNumber() : lastBlock.blockNumber()); }
|
||||
QTextCursor selection(const TabSettings &ts) const;
|
||||
void fromSelection(const TabSettings &ts, const QTextCursor &selection);
|
||||
// defines the first block
|
||||
inline int firstBlockNumber() const { return qMin(positionBlock, anchorBlock); }
|
||||
// defines the last block
|
||||
inline int lastBlockNumber() const { return qMax(positionBlock, anchorBlock); }
|
||||
// defines the first visual column of the selection
|
||||
inline int firstVisualColumn() const { return qMin(positionColumn, anchorColumn); }
|
||||
// defines the last visual column of the selection
|
||||
inline int lastVisualColumn() const { return qMax(positionColumn, anchorColumn); }
|
||||
|
||||
public:
|
||||
int positionBlock;
|
||||
int positionColumn;
|
||||
int anchorBlock;
|
||||
int anchorColumn;
|
||||
|
||||
private:
|
||||
QTextCursor cursor(const BaseTextDocument *baseTextDocument, bool fullSelection) const;
|
||||
};
|
||||
|
||||
//================BaseTextEditorPrivate==============
|
||||
@@ -180,9 +191,18 @@ public:
|
||||
|
||||
// block selection mode
|
||||
bool m_inBlockSelectionMode;
|
||||
void clearBlockSelection();
|
||||
QString copyBlockSelection();
|
||||
void removeBlockSelection(const QString &text = QString());
|
||||
void insertIntoBlockSelection(const QString &text = QString());
|
||||
void setCursorToColumn(QTextCursor &cursor, int column,
|
||||
QTextCursor::MoveMode moveMode = QTextCursor::MoveAnchor);
|
||||
void removeBlockSelection();
|
||||
void enableBlockSelection(const QTextCursor &cursor);
|
||||
void enableBlockSelection(int positionBlock, int positionColumn,
|
||||
int anchorBlock, int anchorColumn);
|
||||
void disableBlockSelection(bool keepSelection = true);
|
||||
void resetCursorFlashTimer();
|
||||
QBasicTimer m_cursorFlashTimer;
|
||||
bool m_cursorVisible;
|
||||
bool m_moveLineUndoHack;
|
||||
|
||||
QTextCursor m_findScopeStart;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QString>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
@@ -42,80 +43,99 @@ using namespace TextEditor;
|
||||
|
||||
enum TransFormationType { Uppercase, Lowercase };
|
||||
|
||||
struct TestBlockSelection
|
||||
{
|
||||
int positionBlock;
|
||||
int positionColumn;
|
||||
int anchorBlock;
|
||||
int anchorColumn;
|
||||
TestBlockSelection(int positionBlock, int positionColumn, int anchorBlock, int anchorColumn)
|
||||
: positionBlock(positionBlock), positionColumn(positionColumn)
|
||||
, anchorBlock(anchorBlock), anchorColumn(anchorColumn) {}
|
||||
TestBlockSelection() {}
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(TransFormationType)
|
||||
Q_DECLARE_METATYPE(TestBlockSelection)
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionTransformation_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("input");
|
||||
QTest::addColumn<QByteArray>("transformedText");
|
||||
QTest::addColumn<int>("position");
|
||||
QTest::addColumn<int>("anchor");
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<QString>("transformedText");
|
||||
QTest::addColumn<TestBlockSelection>("selection");
|
||||
QTest::addColumn<TransFormationType>("type");
|
||||
|
||||
QTest::newRow("uppercase")
|
||||
<< QByteArray("aaa\nbbb\nccc\n")
|
||||
<< QByteArray("aAa\nbBb\ncCc\n")
|
||||
<< 10 << 1 << Uppercase;
|
||||
<< QString::fromLatin1("aaa\nbbb\nccc\n")
|
||||
<< QString::fromLatin1("aAa\nbBb\ncCc\n")
|
||||
<< TestBlockSelection(0, 1, 2, 2)
|
||||
<< Uppercase;
|
||||
QTest::newRow("lowercase")
|
||||
<< QByteArray("AAA\nBBB\nCCC\n")
|
||||
<< QByteArray("AaA\nBbB\nCcC\n")
|
||||
<< 10 << 1 << Lowercase;
|
||||
<< QString::fromLatin1("AAA\nBBB\nCCC\n")
|
||||
<< QString::fromLatin1("AaA\nBbB\nCcC\n")
|
||||
<< TestBlockSelection(0, 1, 2, 2)
|
||||
<< Lowercase;
|
||||
QTest::newRow("uppercase_leading_tabs")
|
||||
<< QByteArray("\taaa\n\tbbb\n\tccc\n")
|
||||
<< QByteArray("\taAa\n\tbBb\n\tcCc\n")
|
||||
<< 13 << 2 << Uppercase;
|
||||
<< QString::fromLatin1("\taaa\n" "\tbbb\n" "\tccc\n")
|
||||
<< QString::fromLatin1("\taAa\n" "\tbBb\n" "\tcCc\n")
|
||||
<< TestBlockSelection(0, 9, 2, 10)
|
||||
<< Uppercase;
|
||||
QTest::newRow("lowercase_leading_tabs")
|
||||
<< QByteArray("\tAAA\n\tBBB\n\tCCC\n")
|
||||
<< QByteArray("\tAaA\n\tBbB\n\tCcC\n")
|
||||
<< 13 << 2 << Lowercase;
|
||||
<< QString::fromLatin1("\tAAA\n\tBBB\n\tCCC\n")
|
||||
<< QString::fromLatin1("\tAaA\n\tBbB\n\tCcC\n")
|
||||
<< TestBlockSelection(0, 9, 2, 10)
|
||||
<< Lowercase;
|
||||
QTest::newRow("uppercase_mixed_leading_whitespace")
|
||||
<< QByteArray("\taaa\n bbbbb\n ccccc\n")
|
||||
<< QByteArray("\tAaa\n bbbbB\n ccccC\n")
|
||||
<< 24 << 1 << Uppercase;
|
||||
<< QString::fromLatin1("\taaa\n bbbbb\n ccccc\n")
|
||||
<< QString::fromLatin1("\tAaa\n bbbbB\n ccccC\n")
|
||||
<< TestBlockSelection(0, 8, 2, 9)
|
||||
<< Uppercase;
|
||||
QTest::newRow("lowercase_mixed_leading_whitespace")
|
||||
<< QByteArray("\tAAA\n BBBBB\n CCCCC\n")
|
||||
<< QByteArray("\taAA\n BBBBb\n CCCCc\n")
|
||||
<< 24 << 1 << Lowercase;
|
||||
<< QString::fromLatin1("\tAAA\n BBBBB\n CCCCC\n")
|
||||
<< QString::fromLatin1("\taAA\n BBBBb\n CCCCc\n")
|
||||
<< TestBlockSelection(0, 8, 2, 9)
|
||||
<< Lowercase;
|
||||
QTest::newRow("uppercase_mid_tabs1")
|
||||
<< QByteArray("a\ta\nbbbbbbbbb\nccccccccc\n")
|
||||
<< QByteArray("a\ta\nbBBBBBbbb\ncCCCCCccc\n")
|
||||
<< 20 << 1 << Uppercase;
|
||||
<< QString::fromLatin1("a\ta\nbbbbbbbbb\nccccccccc\n")
|
||||
<< QString::fromLatin1("a\ta\nbBBBBBbbb\ncCCCCCccc\n")
|
||||
<< TestBlockSelection(0, 1, 2, 6)
|
||||
<< Uppercase;
|
||||
QTest::newRow("lowercase_mid_tabs2")
|
||||
<< QByteArray("AA\taa\n\t\t\nccccCCCCCC\n")
|
||||
<< QByteArray("Aa\taa\n\t\t\ncccccccccC\n")
|
||||
<< 18 << 1 << Lowercase;
|
||||
<< QString::fromLatin1("AA\taa\n\t\t\nccccCCCCCC\n")
|
||||
<< QString::fromLatin1("Aa\taa\n\t\t\ncccccccccC\n")
|
||||
<< TestBlockSelection(0, 1, 2, 9)
|
||||
<< Lowercase;
|
||||
QTest::newRow("uppercase_over_line_ending")
|
||||
<< QByteArray("aaaaa\nbbb\nccccc\n")
|
||||
<< QByteArray("aAAAa\nbBB\ncCCCc\n")
|
||||
<< 14 << 1 << Uppercase;
|
||||
<< QString::fromLatin1("aaaaa\nbbb\nccccc\n")
|
||||
<< QString::fromLatin1("aAAAa\nbBB\ncCCCc\n")
|
||||
<< TestBlockSelection(0, 1, 2, 4)
|
||||
<< Uppercase;
|
||||
QTest::newRow("lowercase_over_line_ending")
|
||||
<< QByteArray("AAAAA\nBBB\nCCCCC\n")
|
||||
<< QByteArray("AaaaA\nBbb\nCcccC\n")
|
||||
<< 14 << 1 << Lowercase;
|
||||
<< QString::fromLatin1("AAAAA\nBBB\nCCCCC\n")
|
||||
<< QString::fromLatin1("AaaaA\nBbb\nCcccC\n")
|
||||
<< TestBlockSelection(0, 1, 2, 4)
|
||||
<< Lowercase;
|
||||
}
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionTransformation()
|
||||
{
|
||||
// fetch test data
|
||||
QFETCH(QByteArray, input);
|
||||
QFETCH(QByteArray, transformedText);
|
||||
QFETCH(int, position);
|
||||
QFETCH(int, anchor);
|
||||
QFETCH(QString, input);
|
||||
QFETCH(QString, transformedText);
|
||||
QFETCH(TestBlockSelection, selection);
|
||||
QFETCH(TransFormationType, type);
|
||||
|
||||
// open editor
|
||||
Core::IEditor *editor = Core::EditorManager::openEditorWithContents(
|
||||
Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, 0, input);
|
||||
Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, 0, input.toLatin1());
|
||||
QVERIFY(editor);
|
||||
if (BaseTextEditor *textEditor = qobject_cast<BaseTextEditor*>(editor)) {
|
||||
|
||||
// place cursor and enable block selection
|
||||
BaseTextEditorWidget *editorWidget = textEditor->editorWidget();
|
||||
QTextCursor cursor = editorWidget->textCursor();
|
||||
cursor.setPosition(anchor);
|
||||
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
||||
editorWidget->setTextCursor(cursor);
|
||||
editorWidget->setBlockSelection(true);
|
||||
editorWidget->setBlockSelection(selection.positionBlock,
|
||||
selection.positionColumn,
|
||||
selection.anchorBlock,
|
||||
selection.anchorColumn);
|
||||
editorWidget->update();
|
||||
|
||||
// transform blockselection
|
||||
switch (type) {
|
||||
@@ -126,9 +146,355 @@ void Internal::TextEditorPlugin::testBlockSelectionTransformation()
|
||||
editorWidget->lowercaseSelection();
|
||||
break;
|
||||
}
|
||||
QCOMPARE(textEditor->baseTextDocument()->plainText().toLatin1(), transformedText);
|
||||
} else {
|
||||
QCOMPARE(textEditor->baseTextDocument()->plainText(), transformedText);
|
||||
}
|
||||
Core::EditorManager::closeEditor(editor, false);
|
||||
}
|
||||
|
||||
static const char text[] =
|
||||
"first line\n"
|
||||
"second line\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n";
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionInsert_data()
|
||||
{
|
||||
QTest::addColumn<QString>("transformedText");
|
||||
QTest::addColumn<TestBlockSelection>("selection");
|
||||
QTest::addColumn<QString>("insertText");
|
||||
|
||||
QTest::newRow("insert")
|
||||
<< QString::fromLatin1(".first line\n"
|
||||
".second line\n"
|
||||
".third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 2, 0)
|
||||
<< QString::fromLatin1(".");
|
||||
QTest::newRow("insert after line end 1")
|
||||
<< QString::fromLatin1("first line\n"
|
||||
"second line\n"
|
||||
"third. line\n"
|
||||
" .\n"
|
||||
"longe.st line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(2, 5, 4, 5)
|
||||
<< QString::fromLatin1(".");
|
||||
QTest::newRow("insert after line end 2")
|
||||
<< QString::fromLatin1("first line .\n"
|
||||
"second line .\n"
|
||||
"third line .\n"
|
||||
" .\n"
|
||||
"longest line in this text .\n"
|
||||
" leading space .\n"
|
||||
"" "\tleading tab .\n"
|
||||
"mid\t" "tab .\n"
|
||||
"endtab\t .\n")
|
||||
<< TestBlockSelection(0, 32, 8, 32)
|
||||
<< QString::fromLatin1(".");
|
||||
QTest::newRow("insert in leading tab")
|
||||
<< QString::fromLatin1("first line\n"
|
||||
"second line\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"lo.ngest line in this text\n"
|
||||
" . leading space\n"
|
||||
" . leading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(4, 2, 6, 2)
|
||||
<< QString::fromLatin1(".");
|
||||
QTest::newRow("insert in middle tab")
|
||||
<< QString::fromLatin1("first line\n"
|
||||
"second line\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
" . leading tab\n"
|
||||
"mid . tab\n"
|
||||
"endta.b\t\n")
|
||||
|
||||
<< TestBlockSelection(6, 5, 8, 5)
|
||||
<< QString::fromLatin1(".");
|
||||
QTest::newRow("insert same block count with all blocks same length")
|
||||
<< QString::fromLatin1(".first line\n"
|
||||
".second line\n"
|
||||
".third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 2, 0)
|
||||
<< QString::fromLatin1(".\n.\n.");
|
||||
QTest::newRow("insert same block count with all blocks different length")
|
||||
<< QString::fromLatin1(". first line\n"
|
||||
".. second line\n"
|
||||
"...third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 2, 0)
|
||||
<< QString::fromLatin1(".\n..\n...");
|
||||
QTest::newRow("insert same block count with some blocks containing tabs")
|
||||
<< QString::fromLatin1(". first line\n"
|
||||
".\t second line\n"
|
||||
".\t.third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 2, 0)
|
||||
<< QString::fromLatin1(".\n.\t\n.\t.");
|
||||
QTest::newRow("insert same block count with some blocks containing tabs in mid line")
|
||||
<< QString::fromLatin1("fi. rst line\n"
|
||||
"se.\t cond line\n"
|
||||
"th.\t.ird line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 2, 2, 2)
|
||||
<< QString::fromLatin1(".\n.\t\n.\t.");
|
||||
QTest::newRow("insert different block count with all blocks same length")
|
||||
<< QString::fromLatin1(".first line\n"
|
||||
".\n"
|
||||
".second line\n"
|
||||
".\n"
|
||||
".third line\n"
|
||||
".\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 2, 0)
|
||||
<< QString::fromLatin1(".\n.");
|
||||
QTest::newRow("insert different block count with all blocks different length")
|
||||
<< QString::fromLatin1(". first line\n"
|
||||
"..\n"
|
||||
". second line\n"
|
||||
"..\n"
|
||||
". third line\n"
|
||||
"..\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 2, 0)
|
||||
<< QString::fromLatin1(".\n..");
|
||||
QTest::newRow("insert different block count with some blocks containing tabs")
|
||||
<< QString::fromLatin1(". first line\n"
|
||||
".\t \n"
|
||||
".\t.\n"
|
||||
". second line\n"
|
||||
".\t \n"
|
||||
".\t.\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 0, 1, 0)
|
||||
<< QString::fromLatin1(".\n.\t\n.\t.");
|
||||
QTest::newRow("insert different block count with some blocks containing tabs in mid line")
|
||||
<< QString::fromLatin1("fi. rst line\n"
|
||||
" .\t \n"
|
||||
" .\t.\n"
|
||||
"se. cond line\n"
|
||||
" .\t \n"
|
||||
" .\t.\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 2, 1, 2)
|
||||
<< QString::fromLatin1(".\n.\t\n.\t.");
|
||||
}
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionInsert()
|
||||
{
|
||||
// fetch test data
|
||||
QFETCH(QString, transformedText);
|
||||
QFETCH(TestBlockSelection, selection);
|
||||
QFETCH(QString, insertText);
|
||||
|
||||
// open editor
|
||||
Core::IEditor *editor = Core::EditorManager::openEditorWithContents(
|
||||
Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, 0, text);
|
||||
QVERIFY(editor);
|
||||
if (BaseTextEditor *textEditor = qobject_cast<BaseTextEditor*>(editor)) {
|
||||
BaseTextEditorWidget *editorWidget = textEditor->editorWidget();
|
||||
editorWidget->setBlockSelection(selection.positionBlock,
|
||||
selection.positionColumn,
|
||||
selection.anchorBlock,
|
||||
selection.anchorColumn);
|
||||
editorWidget->update();
|
||||
editorWidget->insertPlainText(insertText);
|
||||
|
||||
QCOMPARE(textEditor->baseTextDocument()->plainText(), transformedText);
|
||||
}
|
||||
Core::EditorManager::closeEditor(editor, false);
|
||||
}
|
||||
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionRemove_data()
|
||||
{
|
||||
QTest::addColumn<QString>("transformedText");
|
||||
QTest::addColumn<TestBlockSelection>("selection");
|
||||
QTest::newRow("Delete")
|
||||
<< QString::fromLatin1("first ine\n"
|
||||
"second ine\n"
|
||||
"third ine\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 7, 2, 8);
|
||||
QTest::newRow("Delete All")
|
||||
<< QString::fromLatin1("\n\n\n\n\n\n\n\n\n")
|
||||
<< TestBlockSelection(0, 0, 8, 30);
|
||||
QTest::newRow("Delete Inside Tab")
|
||||
<< QString::fromLatin1("first line\n"
|
||||
"second line\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
" leading tab\n"
|
||||
"mi\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(5, 2, 7, 3);
|
||||
QTest::newRow("Delete around Tab")
|
||||
<< QString::fromLatin1("first line\n"
|
||||
"second line\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" ng space\n"
|
||||
" eading tab\n"
|
||||
"miab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(5, 2, 7, 9);
|
||||
QTest::newRow("Delete behind text")
|
||||
<< QString::fromLatin1("first line\n"
|
||||
"second line\n"
|
||||
"third line\n"
|
||||
"\n"
|
||||
"longest line in this text\n"
|
||||
" leading space\n"
|
||||
"" "\tleading tab\n"
|
||||
"mid\t" "tab\n"
|
||||
"endtab\t\n")
|
||||
<< TestBlockSelection(0, 30, 8, 35);
|
||||
}
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionRemove()
|
||||
{
|
||||
// fetch test data
|
||||
QFETCH(QString, transformedText);
|
||||
QFETCH(TestBlockSelection, selection);
|
||||
|
||||
// open editor
|
||||
Core::IEditor *editor = Core::EditorManager::openEditorWithContents(
|
||||
Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, 0, text);
|
||||
QVERIFY(editor);
|
||||
if (BaseTextEditor *textEditor = qobject_cast<BaseTextEditor*>(editor)) {
|
||||
BaseTextEditorWidget *editorWidget = textEditor->editorWidget();
|
||||
editorWidget->setBlockSelection(selection.positionBlock,
|
||||
selection.positionColumn,
|
||||
selection.anchorBlock,
|
||||
selection.anchorColumn);
|
||||
editorWidget->update();
|
||||
editorWidget->insertPlainText(QString());
|
||||
|
||||
QCOMPARE(textEditor->baseTextDocument()->plainText(), transformedText);
|
||||
}
|
||||
Core::EditorManager::closeEditor(editor, false);
|
||||
}
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionCopy_data()
|
||||
{
|
||||
QTest::addColumn<QString>("copiedText");
|
||||
QTest::addColumn<TestBlockSelection>("selection");
|
||||
QTest::newRow("copy")
|
||||
<< QString::fromLatin1("lin\n"
|
||||
"lin\n"
|
||||
"lin")
|
||||
<< TestBlockSelection(0, 7, 2, 10);
|
||||
QTest::newRow("copy over line end")
|
||||
<< QString::fromLatin1("ond line \n"
|
||||
"rd line \n"
|
||||
" ")
|
||||
<< TestBlockSelection(1, 3, 3, 15);
|
||||
QTest::newRow("copy inside tab")
|
||||
<< QString::fromLatin1("ond line \n"
|
||||
"rd line \n"
|
||||
" ")
|
||||
<< TestBlockSelection(1, 3, 3, 15);
|
||||
QTest::newRow("copy start in tab")
|
||||
<< QString::fromLatin1("gest lin\n"
|
||||
" leading\n"
|
||||
" lea")
|
||||
<< TestBlockSelection(4, 3, 6, 11);
|
||||
QTest::newRow("copy around tab")
|
||||
<< QString::fromLatin1(" leadin\n"
|
||||
" le\n"
|
||||
"d\tta")
|
||||
<< TestBlockSelection(5, 2, 7, 10);
|
||||
}
|
||||
|
||||
void Internal::TextEditorPlugin::testBlockSelectionCopy()
|
||||
{
|
||||
// fetch test data
|
||||
QFETCH(QString, copiedText);
|
||||
QFETCH(TestBlockSelection, selection);
|
||||
|
||||
// open editor
|
||||
Core::IEditor *editor = Core::EditorManager::openEditorWithContents(
|
||||
Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, 0, text);
|
||||
QVERIFY(editor);
|
||||
if (BaseTextEditor *textEditor = qobject_cast<BaseTextEditor*>(editor)) {
|
||||
BaseTextEditorWidget *editorWidget = textEditor->editorWidget();
|
||||
editorWidget->setBlockSelection(selection.positionBlock,
|
||||
selection.positionColumn,
|
||||
selection.anchorBlock,
|
||||
selection.anchorColumn);
|
||||
editorWidget->update();
|
||||
editorWidget->copy();
|
||||
|
||||
QCOMPARE(qApp->clipboard()->text(), copiedText);
|
||||
}
|
||||
Core::EditorManager::closeEditor(editor, false);
|
||||
}
|
||||
|
||||
@@ -248,6 +248,9 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
|
||||
{
|
||||
QTC_ASSERT(!isWaitingForProposal(), return);
|
||||
|
||||
if (m_textEditor->editorWidget()->hasBlockSelection())
|
||||
return; // TODO
|
||||
|
||||
if (!provider) {
|
||||
if (kind == Completion)
|
||||
provider = m_completionProvider;
|
||||
|
||||
@@ -213,6 +213,18 @@ int TabSettings::positionAtColumn(const QString &text, int column, int *offset)
|
||||
return i;
|
||||
}
|
||||
|
||||
int TabSettings::columnCountForText(const QString &text, int startColumn) const
|
||||
{
|
||||
int column = startColumn;
|
||||
for (int i = 0; i < text.size(); ++i) {
|
||||
if (text.at(i) == QLatin1Char('\t'))
|
||||
column = column - (column % m_tabSize) + m_tabSize;
|
||||
else
|
||||
++column;
|
||||
}
|
||||
return column - startColumn;
|
||||
}
|
||||
|
||||
int TabSettings::spacesLeftFromPosition(const QString &text, int position)
|
||||
{
|
||||
int i = position;
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
int lineIndentPosition(const QString &text) const;
|
||||
int columnAt(const QString &text, int position) const;
|
||||
int positionAtColumn(const QString &text, int column, int *offset = 0) const;
|
||||
int columnCountForText(const QString &text, int startColumn = 0) const;
|
||||
int indentedColumn(int column, bool doIndent = true) const;
|
||||
QString indentationString(int startColumn, int targetColumn, const QTextBlock ¤tBlock = QTextBlock()) const;
|
||||
QString indentationString(const QString &text) const;
|
||||
|
||||
@@ -73,14 +73,6 @@ private slots:
|
||||
void updateVariable(const QByteArray &variable);
|
||||
void updateCurrentSelection(const QString &text);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
void testSnippetParsing_data();
|
||||
void testSnippetParsing();
|
||||
|
||||
void testBlockSelectionTransformation_data();
|
||||
void testBlockSelectionTransformation();
|
||||
#endif
|
||||
|
||||
private:
|
||||
static TextEditorPlugin *m_instance;
|
||||
TextEditorSettings *m_settings;
|
||||
@@ -89,6 +81,23 @@ private:
|
||||
Core::SearchResultWindow *m_searchResultWindow;
|
||||
OutlineFactory *m_outlineFactory;
|
||||
BaseTextMarkRegistry *m_baseTextMarkRegistry;
|
||||
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
private slots:
|
||||
void testSnippetParsing_data();
|
||||
void testSnippetParsing();
|
||||
|
||||
void testBlockSelectionTransformation_data();
|
||||
void testBlockSelectionTransformation();
|
||||
void testBlockSelectionInsert_data();
|
||||
void testBlockSelectionInsert();
|
||||
void testBlockSelectionRemove_data();
|
||||
void testBlockSelectionRemove();
|
||||
void testBlockSelectionCopy_data();
|
||||
void testBlockSelectionCopy();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user