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:
David Schulz
2014-06-16 14:20:36 +02:00
committed by hjk
parent ce324b8d28
commit 6e9b724006
11 changed files with 1066 additions and 415 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 &currentBlock = QTextBlock()) const;
QString indentationString(const QString &text) const;

View File

@@ -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