diff options
author | David Schulz <david.schulz@qt.io> | 2016-06-01 10:19:59 +0200 |
---|---|---|
committer | David Schulz <david.schulz@theqtcompany.com> | 2016-06-13 05:08:07 +0000 |
commit | 9bacb3e33e46b3a15ab3c803eb014e85d91c97b9 (patch) | |
tree | 54e0bcadbf697f7e3ea3771847b9d373086ef851 /src/plugins | |
parent | 6a2e9a1f0654ed0acdb459501f28b829e43c7473 (diff) |
Editor: Highlight automatically inserted text
Keep the highlight as long as the cursor is directly behind the closing
character and the editor is the focus widget.
Change-Id: Ic1d4bac263e9d2f395791dad7ecdceb9d69635c5
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/texteditor/codeassist/codeassistant.cpp | 2 | ||||
-rw-r--r-- | src/plugins/texteditor/completionsettings.cpp | 5 | ||||
-rw-r--r-- | src/plugins/texteditor/completionsettings.h | 1 | ||||
-rw-r--r-- | src/plugins/texteditor/completionsettingspage.cpp | 2 | ||||
-rw-r--r-- | src/plugins/texteditor/completionsettingspage.ui | 10 | ||||
-rw-r--r-- | src/plugins/texteditor/texteditor.cpp | 71 | ||||
-rw-r--r-- | src/plugins/texteditor/texteditor.h | 4 |
7 files changed, 79 insertions, 16 deletions
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index a21cf7c46c6..8af30428e07 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -307,6 +307,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR if (m_proposal->isCorrective()) m_proposal->makeCorrection(m_editorWidget); + m_editorWidget->keepAutoCompletionHighlight(true); basePosition = m_proposal->basePosition(); m_proposalWidget = m_proposal->createWidget(); connect(m_proposalWidget, &QObject::destroyed, @@ -421,6 +422,7 @@ void CodeAssistantPrivate::destroyContext() if (isWaitingForProposal()) { cancelCurrentRequest(); } else if (isDisplayingProposal()) { + m_editorWidget->keepAutoCompletionHighlight(false); m_proposalWidget->closeProposal(); disconnect(m_proposalWidget, &QObject::destroyed, this, &CodeAssistantPrivate::finalizeProposal); diff --git a/src/plugins/texteditor/completionsettings.cpp b/src/plugins/texteditor/completionsettings.cpp index 325b7580282..8bdcbded959 100644 --- a/src/plugins/texteditor/completionsettings.cpp +++ b/src/plugins/texteditor/completionsettings.cpp @@ -39,6 +39,7 @@ static const char partiallyCompleteKey[] = "PartiallyComplete"; static const char spaceAfterFunctionNameKey[] = "SpaceAfterFunctionName"; static const char autoSplitStringsKey[] = "AutoSplitStrings"; static const char animateAutoCompleteKey[] = "AnimateAutoComplete"; +static const char highlightAutoCompleteKey[] = "HighlightAutoComplete"; using namespace TextEditor; @@ -56,6 +57,7 @@ void CompletionSettings::toSettings(QSettings *s) const s->setValue(spaceAfterFunctionNameKey, m_spaceAfterFunctionName); s->setValue(autoSplitStringsKey, m_autoSplitStrings); s->setValue(animateAutoCompleteKey, m_animateAutoComplete); + s->setValue(highlightAutoCompleteKey, m_highlightAutoComplete); s->endGroup(); } @@ -86,6 +88,8 @@ void CompletionSettings::fromSettings(QSettings *s) s->value(autoSplitStringsKey, m_autoSplitStrings).toBool(); m_animateAutoComplete = s->value(animateAutoCompleteKey, m_animateAutoComplete).toBool(); + m_highlightAutoComplete = + s->value(highlightAutoCompleteKey, m_highlightAutoComplete).toBool(); s->endGroup(); } @@ -102,5 +106,6 @@ bool CompletionSettings::equals(const CompletionSettings &cs) const && m_spaceAfterFunctionName == cs.m_spaceAfterFunctionName && m_autoSplitStrings == cs.m_autoSplitStrings && m_animateAutoComplete == cs.m_animateAutoComplete + && m_highlightAutoComplete == cs.m_highlightAutoComplete ; } diff --git a/src/plugins/texteditor/completionsettings.h b/src/plugins/texteditor/completionsettings.h index 5dfb172eb27..0b466718f97 100644 --- a/src/plugins/texteditor/completionsettings.h +++ b/src/plugins/texteditor/completionsettings.h @@ -67,6 +67,7 @@ public: bool m_spaceAfterFunctionName = false; bool m_autoSplitStrings = true; bool m_animateAutoComplete = true; + bool m_highlightAutoComplete = false; }; inline bool operator==(const CompletionSettings &t1, const CompletionSettings &t2) { return t1.equals(t2); } diff --git a/src/plugins/texteditor/completionsettingspage.cpp b/src/plugins/texteditor/completionsettingspage.cpp index b505eb65661..fce419b422d 100644 --- a/src/plugins/texteditor/completionsettingspage.cpp +++ b/src/plugins/texteditor/completionsettingspage.cpp @@ -103,6 +103,7 @@ QWidget *CompletionSettingsPage::widget() m_page->spaceAfterFunctionName->setChecked(m_completionSettings.m_spaceAfterFunctionName); m_page->autoSplitStrings->setChecked(m_completionSettings.m_autoSplitStrings); m_page->animateAutoComplete->setChecked(m_completionSettings.m_animateAutoComplete); + m_page->highlightAutoComplete->setChecked(m_completionSettings.m_highlightAutoComplete); m_page->enableDoxygenCheckBox->setChecked(m_commentsSettings.m_enableDoxygen); m_page->generateBriefCheckBox->setChecked(m_commentsSettings.m_generateBrief); @@ -177,6 +178,7 @@ void CompletionSettingsPage::settingsFromUi(CompletionSettings &completion, Comm completion.m_spaceAfterFunctionName = m_page->spaceAfterFunctionName->isChecked(); completion.m_autoSplitStrings = m_page->autoSplitStrings->isChecked(); completion.m_animateAutoComplete = m_page->animateAutoComplete->isChecked(); + completion.m_highlightAutoComplete = m_page->highlightAutoComplete->isChecked(); comment.m_enableDoxygen = m_page->enableDoxygenCheckBox->isChecked(); comment.m_generateBrief = m_page->generateBriefCheckBox->isChecked(); diff --git a/src/plugins/texteditor/completionsettingspage.ui b/src/plugins/texteditor/completionsettingspage.ui index d91caeda947..23e61d22be4 100644 --- a/src/plugins/texteditor/completionsettingspage.ui +++ b/src/plugins/texteditor/completionsettingspage.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>511</width> - <height>420</height> + <height>437</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_2"> @@ -227,6 +227,13 @@ In addition, Shift+Enter inserts an escape character at the cursor position and </property> </widget> </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="highlightAutoComplete"> + <property name="text"> + <string>Highlight automatically inserted text</string> + </property> + </widget> + </item> </layout> </widget> </item> @@ -316,6 +323,7 @@ In addition, Shift+Enter inserts an escape character at the cursor position and <tabstop>surroundQuotes</tabstop> <tabstop>spaceAfterFunctionName</tabstop> <tabstop>animateAutoComplete</tabstop> + <tabstop>highlightAutoComplete</tabstop> <tabstop>enableDoxygenCheckBox</tabstop> <tabstop>generateBriefCheckBox</tabstop> <tabstop>leadingAsterisksCheckBox</tabstop> diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index f2cb276008c..d5f50ec4b8a 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -329,7 +329,7 @@ public: // parentheses matcher void _q_matchParentheses(); void _q_highlightBlocks(); - void _q_autocompleterHighlight(const QTextCursor &cursor = QTextCursor()); + void autocompleterHighlight(const QTextCursor &cursor = QTextCursor()); void updateAnimator(QPointer<TextEditorAnimator> animator, QPainter &painter); void cancelCurrentAnimations(); void slotSelectionChanged(); @@ -452,8 +452,14 @@ public: QList<BaseHoverHandler *> m_hoverHandlers; // Not owned QPointer<TextEditorAnimator> m_bracketsAnimator; + + // Animation and highlighting of auto completed text QPointer<TextEditorAnimator> m_autocompleteAnimator; bool m_animateAutoComplete = true; + bool m_highlightAutoComplete = true; + bool m_keepAutoCompletionHighlight = false; + QTextCursor m_autoCompleteHighlightPos; + int m_cursorBlockNumber; int m_blockCount; @@ -629,6 +635,7 @@ static const char kTextBlockMimeType[] = "application/vnd.qtcreator.blocktext"; Id TextEditorWidget::SnippetPlaceholderSelection("TextEdit.SnippetPlaceHolderSelection"); Id TextEditorWidget::CurrentLineSelection("TextEdit.CurrentLineSelection"); Id TextEditorWidget::ParenthesesMatchingSelection("TextEdit.ParenthesesMatchingSelection"); +Id TextEditorWidget::AutoCompleteSelection("TextEdit.AutoCompleteSelection"); Id TextEditorWidget::CodeWarningsSelection("TextEdit.CodeWarningsSelection"); Id TextEditorWidget::CodeSemanticsSelection("TextEdit.CodeSemanticsSelection"); Id TextEditorWidget::UndefinedSymbolSelection("TextEdit.UndefinedSymbolSelection"); @@ -2156,12 +2163,12 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e) d->m_document->autoIndent(ensureVisible); else if (!previousIndentationString.isEmpty()) ensureVisible.insertText(previousIndentationString); - if (d->m_animateAutoComplete) { + if (d->m_animateAutoComplete || d->m_highlightAutoComplete) { QTextCursor tc = ensureVisible; tc.movePosition(QTextCursor::EndOfBlock); tc.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); tc.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor); - d->_q_autocompleterHighlight(tc); + d->autocompleterHighlight(tc); } } setTextCursor(ensureVisible); @@ -2422,9 +2429,10 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e) if (!autoText.isEmpty()) { int pos = cursor.position(); cursor.insertText(autoText); + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + d->autocompleterHighlight(cursor); //Select the inserted text, to be able to re-indent the inserted text cursor.setPosition(pos, QTextCursor::KeepAnchor); - d->_q_autocompleterHighlight(cursor); } if (!electricChar.isNull() && d->m_autoCompleter->contextAllowsElectricCharacters(cursor)) d->m_document->autoIndent(cursor, electricChar); @@ -4705,6 +4713,17 @@ void TextEditorWidgetPrivate::updateHighlights() } } + if (m_highlightAutoComplete && !m_autoCompleteHighlightPos.isNull()) { + QTimer::singleShot(0, this, [this](){ + if ((!m_keepAutoCompletionHighlight && !q->hasFocus()) + || m_autoCompleteHighlightPos != q->textCursor()) { + q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, + QList<QTextEdit::ExtraSelection>()); // clear + m_autoCompleteHighlightPos = QTextCursor(); + } + }); + } + updateCurrentLineHighlight(); if (m_displaySettings.m_highlightBlocks) { @@ -6026,23 +6045,38 @@ void TextEditorWidgetPrivate::_q_highlightBlocks() } } -void TextEditorWidgetPrivate::_q_autocompleterHighlight(const QTextCursor &cursor) +void TextEditorWidgetPrivate::autocompleterHighlight(const QTextCursor &cursor) { - if (!m_animateAutoComplete || q->isReadOnly() || !cursor.hasSelection()) + QList<QTextEdit::ExtraSelection> extraSelections; + if ((!m_animateAutoComplete && !m_highlightAutoComplete) + || q->isReadOnly() || !cursor.hasSelection()) { + q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, extraSelections); // clear return; + } const QTextCharFormat &matchFormat = q->textDocument()->fontSettings().toTextCharFormat(C_AUTOCOMPLETE); - cancelCurrentAnimations();// one animation is enough - m_autocompleteAnimator = new TextEditorAnimator(this); - m_autocompleteAnimator->setPosition(cursor.selectionStart()); - QPalette pal; - pal.setBrush(QPalette::Text, matchFormat.foreground()); - pal.setBrush(QPalette::Base, matchFormat.background()); - m_autocompleteAnimator->setData(q->font(), pal, cursor.selectedText()); - connect(m_autocompleteAnimator.data(), &TextEditorAnimator::updateRequest, - this, &TextEditorWidgetPrivate::_q_animateUpdate); + if (m_highlightAutoComplete) { + QTextEdit::ExtraSelection sel; + sel.cursor = cursor; + sel.format.setBackground(matchFormat.background()); + extraSelections.append(sel); + m_autoCompleteHighlightPos = cursor; + m_autoCompleteHighlightPos.movePosition(QTextCursor::PreviousCharacter); + } + if (m_animateAutoComplete) { + cancelCurrentAnimations();// one animation is enough + m_autocompleteAnimator = new TextEditorAnimator(this); + m_autocompleteAnimator->setPosition(cursor.selectionStart()); + QPalette pal; + pal.setBrush(QPalette::Text, matchFormat.foreground()); + pal.setBrush(QPalette::Base, matchFormat.background()); + m_autocompleteAnimator->setData(q->font(), pal, cursor.selectedText()); + connect(m_autocompleteAnimator.data(), &TextEditorAnimator::updateRequest, + this, &TextEditorWidgetPrivate::_q_animateUpdate); + } + q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, extraSelections); } void TextEditorWidgetPrivate::updateAnimator(QPointer<TextEditorAnimator> animator, @@ -6089,6 +6123,7 @@ void TextEditorWidget::focusOutEvent(QFocusEvent *e) QPlainTextEdit::focusOutEvent(e); if (viewport()->cursor().shape() == Qt::BlankCursor) viewport()->setCursor(Qt::IBeamCursor); + d->updateHighlights(); } @@ -6542,6 +6577,7 @@ void TextEditorWidget::setCompletionSettings(const CompletionSettings &completio d->m_autoCompleter->setAutoInsertQuotesEnabled(completionSettings.m_autoInsertQuotes); d->m_autoCompleter->setSurroundWithQuotesEnabled(completionSettings.m_surroundingAutoQuotes); d->m_animateAutoComplete = completionSettings.m_animateAutoComplete; + d->m_highlightAutoComplete = completionSettings.m_highlightAutoComplete; } void TextEditorWidget::setExtraEncodingSettings(const ExtraEncodingSettings &extraEncodingSettings) @@ -7003,6 +7039,11 @@ void TextEditorWidget::insertExtraToolBarWidget(TextEditorWidget::Side side, d->m_toolBar->insertWidget(d->m_toolBar->actions().first(), widget); } +void TextEditorWidget::keepAutoCompletionHighlight(bool keepHighlight) +{ + d->m_keepAutoCompletionHighlight = keepHighlight; +} + int BaseTextEditor::currentLine() const { return editorWidget()->textCursor().blockNumber() + 1; diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index ce896250e1c..87182f18cf3 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -301,6 +301,7 @@ public: static Core::Id SnippetPlaceholderSelection; static Core::Id CurrentLineSelection; static Core::Id ParenthesesMatchingSelection; + static Core::Id AutoCompleteSelection; static Core::Id CodeWarningsSelection; static Core::Id CodeSemanticsSelection; static Core::Id UndefinedSymbolSelection; @@ -323,6 +324,9 @@ public: enum Side { Left, Right }; void insertExtraToolBarWidget(Side side, QWidget *widget); + // keep the auto completion even if the focus is lost + void keepAutoCompletionHighlight(bool keepHighlight); + virtual void copy(); virtual void paste(); virtual void cut(); |