diff --git a/doc/src/editors/creator-editors.qdoc b/doc/src/editors/creator-editors.qdoc
index a69785a5b96..79742e736f1 100644
--- a/doc/src/editors/creator-editors.qdoc
+++ b/doc/src/editors/creator-editors.qdoc
@@ -204,9 +204,11 @@
To specify the position where the annotations are displayed, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
- \uicontrol Display > \uicontrol {Annotations next to lines}, and then
+ \uicontrol Display > \uicontrol {Line annotations}, and then
select whether to display the annotations directly next to the code,
- aligned to the right of the code, or in the right margin.
+ aligned to the right of the code, or in the right margin. Showing annotations
+ between lines can be useful if there is usually not enough space to
+ display annotations next to the text.
If you hide the annotations by deselecting the check box, you can move the
mouse pointer over an icon to view them.
diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h
index 41cebc0c6a3..73114e6538d 100644
--- a/src/plugins/texteditor/displaysettings.h
+++ b/src/plugins/texteditor/displaysettings.h
@@ -40,7 +40,8 @@ enum class AnnotationAlignment
{
NextToContent,
NextToMargin,
- RightSide
+ RightSide,
+ BetweenLines
};
class TEXTEDITOR_EXPORT DisplaySettings
diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp
index 2289ba2135a..07b535f59a4 100644
--- a/src/plugins/texteditor/displaysettingspage.cpp
+++ b/src/plugins/texteditor/displaysettingspage.cpp
@@ -126,6 +126,8 @@ void DisplaySettingsPage::settingsFromUI(DisplaySettings &displaySettings,
displaySettings.m_annotationAlignment = AnnotationAlignment::NextToMargin;
else if (d->m_page->rightAligned->isChecked())
displaySettings.m_annotationAlignment = AnnotationAlignment::RightSide;
+ else if (d->m_page->betweenLines->isChecked())
+ displaySettings.m_annotationAlignment = AnnotationAlignment::BetweenLines;
}
void DisplaySettingsPage::settingsToUI()
@@ -154,6 +156,7 @@ void DisplaySettingsPage::settingsToUI()
case AnnotationAlignment::NextToContent: d->m_page->leftAligned->setChecked(true); break;
case AnnotationAlignment::NextToMargin: d->m_page->atMargin->setChecked(true); break;
case AnnotationAlignment::RightSide: d->m_page->rightAligned->setChecked(true); break;
+ case AnnotationAlignment::BetweenLines: d->m_page->betweenLines->setChecked(true); break;
}
}
diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui
index aa8dd2cd446..8fb605ab7eb 100644
--- a/src/plugins/texteditor/displaysettingspage.ui
+++ b/src/plugins/texteditor/displaysettingspage.ui
@@ -187,7 +187,7 @@
-
- Annotations next to lines
+ Line annotations
true
@@ -217,6 +217,13 @@
+ -
+
+
+ Between lines
+
+
+
diff --git a/src/plugins/texteditor/textdocumentlayout.cpp b/src/plugins/texteditor/textdocumentlayout.cpp
index 454819294da..9ddb752ba5e 100644
--- a/src/plugins/texteditor/textdocumentlayout.cpp
+++ b/src/plugins/texteditor/textdocumentlayout.cpp
@@ -634,6 +634,14 @@ void TextDocumentLayout::updateMarksBlock(const QTextBlock &block)
mrk->updateBlock(block);
}
+QRectF TextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
+{
+ QRectF boundingRect = QPlainTextDocumentLayout::blockBoundingRect(block);
+ if (TextBlockUserData *userData = testUserData(block))
+ boundingRect.adjust(0, 0, 0, userData->additionalAnnotationHeight());
+ return boundingRect;
+}
+
TextDocumentLayout::FoldValidator::FoldValidator()
: m_layout(0)
, m_requestDocUpdate(false)
diff --git a/src/plugins/texteditor/textdocumentlayout.h b/src/plugins/texteditor/textdocumentlayout.h
index 737566ab181..17a3a781f63 100644
--- a/src/plugins/texteditor/textdocumentlayout.h
+++ b/src/plugins/texteditor/textdocumentlayout.h
@@ -126,6 +126,9 @@ public:
inline int lexerState() const { return m_lexerState; }
inline void setLexerState(int state) {m_lexerState = state; }
+ inline void setAdditionalAnnotationHeight(int annotationHeight)
+ { m_additionalAnnotationHeight = annotationHeight; }
+ inline int additionalAnnotationHeight() const { return m_additionalAnnotationHeight; }
CodeFormatterData *codeFormatterData() const { return m_codeFormatterData; }
void setCodeFormatterData(CodeFormatterData *data);
@@ -138,6 +141,7 @@ private:
uint m_lexerState : 8;
uint m_foldingStartIncluded : 1;
uint m_foldingEndIncluded : 1;
+ int m_additionalAnnotationHeight = 0;
Parentheses m_parentheses;
CodeFormatterData *m_codeFormatterData;
};
@@ -210,7 +214,8 @@ public:
void setRequiredWidth(int width);
- QSizeF documentSize() const;
+ QSizeF documentSize() const override;
+ QRectF blockBoundingRect(const QTextBlock &block) const override;
TextMarks documentClosing();
void documentReloaded(TextMarks marks, TextDocument *baseextDocument);
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 13e5b824235..3a561f18d4d 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -459,7 +459,9 @@ public:
bool expanded,
bool active,
bool hovered) const;
- void updateLineAnnotation(const PaintEventData &data, QPainter &painter);
+ bool updateAnnotationBounds(TextBlockUserData *blockUserData, bool annotationsVisible);
+ void updateLineAnnotation(const PaintEventData &data, const PaintEventBlockData &blockData,
+ QPainter &painter);
void paintRightMarginArea(PaintEventData &data, QPainter &painter) const;
void paintRightMarginLine(const PaintEventData &data, QPainter &painter) const;
void paintBlockHighlight(const PaintEventData &data, QPainter &painter) const;
@@ -3965,7 +3967,20 @@ QRectF TextEditorWidgetPrivate::getLastLineLineRect(const QTextBlock &block)
return line.naturalTextRect().translated(contentOffset.x(), top).adjusted(0, 0, -1, -1);
}
+bool TextEditorWidgetPrivate::updateAnnotationBounds(TextBlockUserData *blockUserData, bool annotationsVisible)
+{
+ const bool additionalHeightNeeded = annotationsVisible
+ && m_displaySettings.m_annotationAlignment == AnnotationAlignment::BetweenLines;
+ const int additionalHeight = additionalHeightNeeded ? q->fontMetrics().lineSpacing() : 0;
+ if (blockUserData->additionalAnnotationHeight() == additionalHeight)
+ return false;
+ blockUserData->setAdditionalAnnotationHeight(additionalHeight);
+ q->viewport()->update();
+ return true;
+}
+
void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data,
+ const PaintEventBlockData &blockData,
QPainter &painter)
{
m_annotationRects.remove(data.block.blockNumber());
@@ -3978,7 +3993,12 @@ void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data,
return;
TextMarks marks = blockUserData->marks();
- if (marks.isEmpty())
+
+ const bool annotationsVisible = Utils::anyOf(marks, [](const TextMark* mark) {
+ return !mark->lineAnnotation().isEmpty();
+ });
+
+ if (updateAnnotationBounds(blockUserData, annotationsVisible) || !annotationsVisible)
return;
const QRectF lineRect = getLastLineLineRect(data.block);
@@ -3990,27 +4010,33 @@ void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data,
});
const qreal itemOffset = q->fontMetrics().lineSpacing();
- const qreal initialOffset = itemOffset * 2;
+ const qreal initialOffset = m_displaySettings.m_annotationAlignment == AnnotationAlignment::BetweenLines ? itemOffset / 2 : itemOffset * 2;
const qreal minimalContentWidth = q->fontMetrics().width('X')
* m_displaySettings.m_minimalAnnotationContent;
- QRectF boundingRect(lineRect.topLeft().x(), lineRect.topLeft().y(),
- q->viewport()->width() - lineRect.right(), lineRect.height());
qreal offset = initialOffset;
+ qreal x = 0;
if (marks.isEmpty())
return;
- if (m_displaySettings.m_annotationAlignment == AnnotationAlignment::NextToMargin
- && data.rightMargin > lineRect.right() + offset
- && q->viewport()->width() > data.rightMargin + minimalContentWidth) {
+ QRectF boundingRect;
+ if (m_displaySettings.m_annotationAlignment == AnnotationAlignment::BetweenLines) {
+ boundingRect = QRectF(lineRect.bottomLeft(), blockData.boundingRect.bottomRight());
+ } else {
+ boundingRect = QRectF(lineRect.topLeft().x(), lineRect.topLeft().y(),
+ q->viewport()->width() - lineRect.right(), lineRect.height());
+ x = lineRect.right();
+ if (m_displaySettings.m_annotationAlignment == AnnotationAlignment::NextToMargin
+ && data.rightMargin > lineRect.right() + offset
+ && q->viewport()->width() > data.rightMargin + minimalContentWidth) {
offset = data.rightMargin - lineRect.right();
- } else if (m_displaySettings.m_annotationAlignment != AnnotationAlignment::NextToContent) {
- marks = availableMarks(marks, boundingRect, q->fontMetrics(), itemOffset);
- if (boundingRect.width() > 0)
- offset = qMax(boundingRect.width(), initialOffset);
+ } else if (m_displaySettings.m_annotationAlignment != AnnotationAlignment::NextToContent) {
+ marks = availableMarks(marks, boundingRect, q->fontMetrics(), itemOffset);
+ if (boundingRect.width() > 0)
+ offset = qMax(boundingRect.width(), initialOffset);
+ }
}
- qreal x = lineRect.right();
for (const TextMark *mark : marks) {
- boundingRect = QRectF(x, lineRect.top(), q->viewport()->width() - x, lineRect.height());
+ boundingRect = QRectF(x, boundingRect.top(), q->viewport()->width() - x, boundingRect.height());
if (boundingRect.isEmpty())
break;
if (data.eventRect.intersects(boundingRect.toRect()))
@@ -4715,7 +4741,7 @@ void TextEditorWidget::paintEvent(QPaintEvent *e)
d->paintAdditionalVisualWhitespaces(data, painter, blockData.boundingRect.top());
d->paintReplacement(data, painter, blockData.boundingRect.top());
}
- d->updateLineAnnotation(data, painter);
+ d->updateLineAnnotation(data, blockData, painter);
data.offset.ry() += blockData.boundingRect.height();