Commit 6e9b7240 authored by David Schulz's avatar David Schulz Committed by hjk
Browse files

Editor: Blockselection rewrite.



Also adding the possibility to insert text into the blockselection.

Task-number: QTCREATORBUG-7773
Change-Id: I7a47a1d630f769a8253ee1a2f21057820ea170d5
Reviewed-by: default avatarLukas Holecek <hluk@email.cz>
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent ce324b8d
......@@ -1800,12 +1800,19 @@ public:
}
// Set cursor in text editor widget.
void commitCursor() {
if (editor())
EDITOR(setTextCursor(m_cursor));
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)
......
This diff is collapsed.
......@@ -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);
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); }
// 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); }
bool isValid() const{ return !firstBlock.isNull() && !lastBlock.isNull(); }
void clear() { firstBlock = lastBlock = QTextCursor(); }
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);
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;
......
......@@ -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 &currentBlock = 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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment