forked from qt-creator/qt-creator
TextEditor: Add insertWidget function
Allows to embed a widget into a line that will do its best to stay in position. Change-Id: I72590814057eb92bd17978a63bb4f7132410212f Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -77,6 +77,7 @@ local function setup()
|
||||
script()()
|
||||
end,
|
||||
})
|
||||
require 'tst_texteditor'.setup()
|
||||
end
|
||||
|
||||
return { setup = setup }
|
||||
|
61
share/qtcreator/lua-plugins/luatests/tst_texteditor.lua
Normal file
61
share/qtcreator/lua-plugins/luatests/tst_texteditor.lua
Normal file
@@ -0,0 +1,61 @@
|
||||
local function tst_embedWidget()
|
||||
T = require 'TextEditor'
|
||||
G = require 'Gui'
|
||||
|
||||
local editor = T.currentEditor()
|
||||
if not editor then
|
||||
print("No editor found")
|
||||
return
|
||||
end
|
||||
|
||||
local cursor = editor:cursor()
|
||||
|
||||
local embed
|
||||
local optionals = G.Group {
|
||||
visible = false,
|
||||
G.Row {
|
||||
G.Label {
|
||||
text = "Optional 1",
|
||||
},
|
||||
G.Label {
|
||||
text = "Optional 2",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
local layout = G.Group {
|
||||
G.Column {
|
||||
"Hello", G.br,
|
||||
"World",
|
||||
G.br,
|
||||
G.PushButton {
|
||||
text = "Show optionals",
|
||||
onClicked = function()
|
||||
optionals.visible = not optionals.visible
|
||||
embed:resize()
|
||||
end,
|
||||
},
|
||||
optionals,
|
||||
G.PushButton {
|
||||
text = "Close",
|
||||
onClicked = function()
|
||||
embed:close()
|
||||
end,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
embed = editor:addEmbeddedWidget(layout, cursor:mainCursor():position())
|
||||
end
|
||||
|
||||
local function setup()
|
||||
Action = require 'Action'
|
||||
Action.create("LuaTests.textEditorEmbedDemo", {
|
||||
text = "Lua TextEditor Embed Demo",
|
||||
onTrigger = tst_embedWidget,
|
||||
})
|
||||
end
|
||||
|
||||
return {
|
||||
setup = setup,
|
||||
}
|
@@ -46,65 +46,14 @@ TextEditor::TextEditorWidget *getSuggestionReadyEditorWidget(TextEditor::TextDoc
|
||||
return widget;
|
||||
}
|
||||
|
||||
void fillRemainingViewportWidth(QWidget *widget, const QSize &viewportSize, const QMargins &margins)
|
||||
std::unique_ptr<EmbeddedWidgetInterface> addEmbeddedWidget(
|
||||
BaseTextEditor *editor, QWidget *widget, int cursorPosition)
|
||||
{
|
||||
int maxWidth = viewportSize.width() - margins.right() - widget->x();
|
||||
widget->setFixedWidth(maxWidth);
|
||||
}
|
||||
|
||||
QPoint getPositionOnViewport(const BaseTextEditor * const editor, const QWidget * const widget,
|
||||
int basePos, int xPos, const QSize &viewportSize,
|
||||
const QMargins &margins)
|
||||
{
|
||||
QTextCursor cursor = QTextCursor(editor->textDocument()->document());
|
||||
cursor.setPosition(basePos);
|
||||
|
||||
const QRect cursorRect = editor->editorWidget()->cursorRect(cursor);
|
||||
QPoint widgetPosDefault = cursorRect.bottomLeft();
|
||||
|
||||
widgetPosDefault.ry() += (cursorRect.top() - cursorRect.bottom()) / 2;
|
||||
|
||||
int fontSize = editor->textDocument()->fontSettings().fontSize();
|
||||
int maxX = viewportSize.width() - margins.right() - widget->width();
|
||||
int maxY = viewportSize.height() - widget->height() - fontSize;
|
||||
|
||||
if (maxX < 0) {
|
||||
qWarning() << QStringLiteral("Floating Widget positioning: x (%1) < 0. Widget will not "
|
||||
"fit in the viewport. Viewport.width (%2), widget.width (%3), "
|
||||
"widget margin.right (%4). Setting x to 0.")
|
||||
.arg(maxX).arg(viewportSize.width()).arg(widget->width()).arg(margins.right());
|
||||
maxX = 0;
|
||||
}
|
||||
|
||||
if (maxY < 0) {
|
||||
qWarning() << QStringLiteral("Floating Widget positioning: y (%1) < 0. Widget is too big"
|
||||
"for the viewport. Viewport.height (%2), widget.height (%3)."
|
||||
"Setting y to 0.")
|
||||
.arg(maxY).arg(viewportSize.height()).arg(widget->height());
|
||||
maxY = 0;
|
||||
}
|
||||
|
||||
int x = xPos != -1 ? xPos : std::min(widgetPosDefault.x(), maxX);
|
||||
int y = widgetPosDefault.y() + fontSize;
|
||||
y = std::min(y, maxY);
|
||||
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
void addFloatingWidget(BaseTextEditor *editor, QWidget *widget, int yPos, int xPos,
|
||||
const QRect &margins, bool fillWidth = false)
|
||||
{
|
||||
QMargins widgetMargins{margins.left(), margins.top(), margins.width(), margins.height()};
|
||||
|
||||
widget->setParent(editor->editorWidget()->viewport());
|
||||
TextEditorWidget *editorWidget = editor->editorWidget();
|
||||
const QSize viewportSize = editorWidget->viewport()->size();
|
||||
|
||||
widget->move(getPositionOnViewport(editor, widget, yPos, xPos, viewportSize, widgetMargins));
|
||||
if (fillWidth)
|
||||
fillRemainingViewportWidth(widget, viewportSize, widgetMargins);
|
||||
|
||||
widget->show();
|
||||
std::unique_ptr<EmbeddedWidgetInterface> embed
|
||||
= editorWidget->insertWidget(widget, cursorPosition);
|
||||
return embed;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -213,9 +162,7 @@ void setupTextEditorModule()
|
||||
"cursors",
|
||||
[](MultiTextCursor *self) { return sol::as_table(self->cursors()); },
|
||||
"insertText",
|
||||
[](MultiTextCursor *self, const QString &text) {
|
||||
self->insertText(text);
|
||||
});
|
||||
[](MultiTextCursor *self, const QString &text) { self->insertText(text); });
|
||||
|
||||
result.new_usertype<Position>(
|
||||
"Position",
|
||||
@@ -273,9 +220,33 @@ void setupTextEditorModule()
|
||||
return ret;
|
||||
},
|
||||
"insertText",
|
||||
[](QTextCursor *textCursor, const QString &text) {
|
||||
textCursor->insertText(text);
|
||||
});
|
||||
[](QTextCursor *textCursor, const QString &text) { textCursor->insertText(text); });
|
||||
|
||||
using LayoutOrWidget = std::variant<Layouting::Layout *, Layouting::Widget *, QWidget *>;
|
||||
|
||||
static auto toWidget = [](LayoutOrWidget &arg) {
|
||||
return std::visit(
|
||||
[](auto &&arg) -> QWidget * {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, Layouting::Widget *>)
|
||||
return arg->emerge();
|
||||
else if constexpr (std::is_same_v<T, QWidget *>)
|
||||
return arg;
|
||||
else if constexpr (std::is_same_v<T, Layouting::Layout *>)
|
||||
return arg->emerge();
|
||||
else
|
||||
return nullptr;
|
||||
},
|
||||
arg);
|
||||
};
|
||||
|
||||
result.new_usertype<EmbeddedWidgetInterface>(
|
||||
"EmbeddedWidgetInterface",
|
||||
sol::no_constructor,
|
||||
"resize",
|
||||
&EmbeddedWidgetInterface::resize,
|
||||
"close",
|
||||
&EmbeddedWidgetInterface::close);
|
||||
|
||||
result.new_usertype<BaseTextEditor>(
|
||||
"TextEditor",
|
||||
@@ -285,23 +256,11 @@ void setupTextEditorModule()
|
||||
QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid"));
|
||||
return textEditor->textDocument();
|
||||
},
|
||||
"addFloatingWidget",
|
||||
sol::overload(
|
||||
[](const TextEditorPtr &textEditor, QWidget *widget, int yPos, int xPos,
|
||||
const QRect &margins, bool fillWidth) {
|
||||
QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid"));
|
||||
addFloatingWidget(textEditor, widget, yPos, xPos, margins, fillWidth);
|
||||
},
|
||||
[](const TextEditorPtr &textEditor, Layouting::Widget *widget, int yPos, int xPos,
|
||||
const QRect &margins, bool fillWidth) {
|
||||
QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid"));
|
||||
addFloatingWidget(textEditor, widget->emerge(), yPos, xPos, margins, fillWidth);
|
||||
},
|
||||
[](const TextEditorPtr &textEditor, Layouting::Layout *layout, int yPos, int xPos,
|
||||
const QRect &margins, bool fillWidth = false) {
|
||||
QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid"));
|
||||
addFloatingWidget(textEditor, layout->emerge(), yPos, xPos, margins, fillWidth);
|
||||
}),
|
||||
"addEmbeddedWidget",
|
||||
[](const TextEditorPtr &textEditor, LayoutOrWidget widget, int position) {
|
||||
QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid"));
|
||||
return addEmbeddedWidget(textEditor, toWidget(widget), position);
|
||||
},
|
||||
"cursor",
|
||||
[](const TextEditorPtr &textEditor) {
|
||||
QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid"));
|
||||
|
@@ -12,8 +12,8 @@ gui.layout = {}
|
||||
|
||||
---The base class of all widget classes, an empty widget itself.
|
||||
---@class Widget : Object
|
||||
---@field visible bool Whether the widget is visible or not.
|
||||
---@field enabled bool Whether the widget is enabled or not.
|
||||
---@field visible boolean Whether the widget is visible or not.
|
||||
---@field enabled boolean Whether the widget is enabled or not.
|
||||
gui.widget = {}
|
||||
|
||||
---@alias LayoutChild string|BaseAspect|Layout|Widget|function
|
||||
@@ -168,7 +168,7 @@ local label = {}
|
||||
---@class (exact) LabelOptions : BaseWidgetOptions
|
||||
---@param interactionFlags? TextInteractionFlag[]
|
||||
---@param textFormat? TextFormat The text format enum
|
||||
---@param wordWrap? bool
|
||||
---@param wordWrap? boolean
|
||||
|
||||
gui.labelOptions = {}
|
||||
|
||||
@@ -220,8 +220,8 @@ function gui.TabWidget(options) end
|
||||
function gui.TabWidget(name, child) end
|
||||
|
||||
---@class Spinner : Widget
|
||||
---@field running bool Set spinner visible and display spinning animation
|
||||
---@field decorated bool Display spinner with custom styleSheet defined inside control (default true)
|
||||
---@field running boolean Set spinner visible and display spinning animation
|
||||
---@field decorated boolean Display spinner with custom styleSheet defined inside control (default true)
|
||||
local spinner = {}
|
||||
|
||||
---@class IconDisplay : Widget
|
||||
|
@@ -107,15 +107,20 @@ function TextEditor:document() end
|
||||
---@return MultiTextCursor cursor The cursor of the editor.
|
||||
function TextEditor:cursor() end
|
||||
|
||||
---Adds a floating widget at the specified position in the text editor.
|
||||
---The widget will be positioned at the location corresponding to the given position in the
|
||||
---text document and will be automatically managed to stay pined to that position.
|
||||
---@class EmbeddedWidget
|
||||
local EmbeddedWidget = {}
|
||||
|
||||
---Closes the floating widget.
|
||||
function EmbeddedWidget:close() end
|
||||
|
||||
---Resizes the floating widget according to its layout.
|
||||
function EmbeddedWidget:resize() end
|
||||
|
||||
---Embeds a widget at the specified cursor position in the text editor.
|
||||
---@param widget Widget|Layout The widget to be added as a floating widget.
|
||||
---@param position integer The position in the document where the widget should appear.
|
||||
---@param margins integer[] Four integers, representing left, top, right, bottom margins
|
||||
---@param xPos integer Sets widget to fixed x position if x != -1, otherwise automatic x position calculation is done
|
||||
---@param fillWidth boolean If true, the widget will fill remaining space from its x position to size of the TextEditor viewport
|
||||
function TextEditor:addFloatingWidget(widget, position, xPos, margins, fillWidth) end
|
||||
---@return EmbeddedWidget interface An interface to control the floating widget.
|
||||
function TextEditor:addEmbeddedWidget(widget, position) end
|
||||
|
||||
---Checks if the current suggestion is locked. The suggestion is locked when the user can use it.
|
||||
---@return boolean True if the suggestion is locked, false otherwise.
|
||||
@@ -129,5 +134,4 @@ function TextEditor:insertText(text) end
|
||||
---@return TextEditor|nil editor The currently active editor or nil if there is none.
|
||||
function textEditor.currentEditor() end
|
||||
|
||||
|
||||
return textEditor
|
||||
|
@@ -777,9 +777,14 @@ QRectF TextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
|
||||
boundingRect.setHeight(TextEditorSettings::fontSettings().lineSpacing());
|
||||
}
|
||||
|
||||
if (TextBlockUserData *userData = textUserData(block))
|
||||
boundingRect.adjust(
|
||||
0, 0, 0, userData->additionalAnnotationHeight() + userData->additionalLineHeight());
|
||||
if (TextBlockUserData *userData = textUserData(block)) {
|
||||
int additionalHeight = 0;
|
||||
for (const QPointer<QWidget> &wdgt : userData->embeddedWidgets()) {
|
||||
if (wdgt && wdgt->isVisible())
|
||||
additionalHeight += wdgt->height();
|
||||
}
|
||||
boundingRect.adjust(0, 0, 0, userData->additionalAnnotationHeight() + additionalHeight);
|
||||
}
|
||||
|
||||
return boundingRect;
|
||||
}
|
||||
|
@@ -119,9 +119,9 @@ public:
|
||||
{ m_additionalAnnotationHeight = annotationHeight; }
|
||||
inline int additionalAnnotationHeight() const { return m_additionalAnnotationHeight; }
|
||||
|
||||
inline void setAdditionalLineHeight(int additionalLineHeight)
|
||||
{ m_additionalLineHeight = additionalLineHeight; }
|
||||
inline int additionalLineHeight() const { return m_additionalLineHeight; }
|
||||
inline void addEmbeddedWidget(QWidget *widget) { m_embeddedWidgets.append(widget); }
|
||||
inline void removeEmbeddedWidget(QWidget *widget) { m_embeddedWidgets.removeAll(widget); }
|
||||
inline QList<QPointer<QWidget>> embeddedWidgets() const { return m_embeddedWidgets; }
|
||||
|
||||
CodeFormatterData *codeFormatterData() const { return m_codeFormatterData; }
|
||||
void setCodeFormatterData(CodeFormatterData *data);
|
||||
@@ -148,13 +148,13 @@ private:
|
||||
uint m_foldingStartIncluded : 1;
|
||||
uint m_foldingEndIncluded : 1;
|
||||
int m_additionalAnnotationHeight = 0;
|
||||
int m_additionalLineHeight = 0;
|
||||
Parentheses m_parentheses;
|
||||
CodeFormatterData *m_codeFormatterData;
|
||||
KSyntaxHighlighting::State m_syntaxState;
|
||||
QByteArray m_expectedRawStringSuffix; // A bit C++-specific, but let's be pragmatic.
|
||||
std::unique_ptr<QTextDocument> m_replacement;
|
||||
std::unique_ptr<TextSuggestion> m_suggestion;
|
||||
QList<QPointer<QWidget>> m_embeddedWidgets;
|
||||
quint8 m_attrState = 0;
|
||||
};
|
||||
|
||||
|
@@ -749,6 +749,8 @@ public:
|
||||
void openTypeUnderCursor(bool openInNextSplit);
|
||||
qreal charWidth() const;
|
||||
|
||||
std::unique_ptr<EmbeddedWidgetInterface> insertWidget(QWidget *widget, int line);
|
||||
|
||||
// actions
|
||||
void registerActions();
|
||||
void updateActions();
|
||||
@@ -3919,6 +3921,131 @@ qreal TextEditorWidgetPrivate::charWidth() const
|
||||
return QFontMetricsF(q->font()).horizontalAdvance(QLatin1Char('x'));
|
||||
}
|
||||
|
||||
class CarrierWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CarrierWidget(TextEditorWidget *textEditorWidget, QWidget *embed)
|
||||
: QWidget(textEditorWidget->viewport())
|
||||
, m_embed(embed)
|
||||
, m_textEditorWidget(textEditorWidget)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(m_embed);
|
||||
|
||||
setFixedWidth(m_textEditorWidget->width() - m_textEditorWidget->extraAreaWidth());
|
||||
setFixedHeight(m_embed->minimumSizeHint().height());
|
||||
|
||||
connect(m_textEditorWidget, &TextEditorWidget::resized, this, [this] {
|
||||
setFixedWidth(m_textEditorWidget->width() - m_textEditorWidget->extraAreaWidth());
|
||||
});
|
||||
}
|
||||
|
||||
int embedHeight() { return m_embed->minimumSizeHint().height(); }
|
||||
|
||||
private:
|
||||
QWidget *m_embed;
|
||||
TextEditorWidget *m_textEditorWidget;
|
||||
};
|
||||
|
||||
EmbeddedWidgetInterface::~EmbeddedWidgetInterface()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void EmbeddedWidgetInterface::resize()
|
||||
{
|
||||
emit resized();
|
||||
}
|
||||
|
||||
void EmbeddedWidgetInterface::close()
|
||||
{
|
||||
emit closed();
|
||||
}
|
||||
|
||||
std::unique_ptr<EmbeddedWidgetInterface> TextEditorWidgetPrivate::insertWidget(
|
||||
QWidget *widget, int line)
|
||||
{
|
||||
QPointer<CarrierWidget> carrier = new CarrierWidget(q, widget);
|
||||
std::unique_ptr<EmbeddedWidgetInterface> result(new EmbeddedWidgetInterface());
|
||||
|
||||
struct State
|
||||
{
|
||||
int height = 0;
|
||||
QTextCursor cursor;
|
||||
QTextBlock block;
|
||||
};
|
||||
|
||||
std::shared_ptr<State> pState = std::make_shared<State>();
|
||||
pState->cursor = QTextCursor(q->document());
|
||||
pState->cursor.setPosition(line);
|
||||
pState->cursor.movePosition(QTextCursor::StartOfBlock);
|
||||
|
||||
auto position = [this, pState, carrier] {
|
||||
QTextBlock block = pState->cursor.block();
|
||||
QTC_ASSERT(block.isValid(), return);
|
||||
|
||||
TextBlockUserData *userData = TextDocumentLayout::userData(block);
|
||||
if (block != pState->block) {
|
||||
TextBlockUserData *previousUserData = TextDocumentLayout::userData(pState->block);
|
||||
if (previousUserData && userData != previousUserData) {
|
||||
// We have swapped into a different block, remove it from the previous block
|
||||
previousUserData->removeEmbeddedWidget(carrier);
|
||||
}
|
||||
userData->addEmbeddedWidget(carrier);
|
||||
pState->block = block;
|
||||
pState->height = 0;
|
||||
}
|
||||
|
||||
QRectF r = cursorBlockRect(m_document->document(), block, block.position());
|
||||
|
||||
int y = 0;
|
||||
for (const auto &wdgt : userData->embeddedWidgets()) {
|
||||
if (wdgt == carrier)
|
||||
break;
|
||||
y += wdgt->height();
|
||||
}
|
||||
|
||||
QPoint pos = r.topLeft().toPoint()
|
||||
+ QPoint(0, TextEditorSettings::fontSettings().lineSpacing() + y);
|
||||
|
||||
int h = carrier->embedHeight();
|
||||
if (h == pState->height && pos == carrier->pos())
|
||||
return;
|
||||
|
||||
carrier->move(pos);
|
||||
carrier->setFixedHeight(h);
|
||||
|
||||
pState->height = h;
|
||||
|
||||
qobject_cast<TextDocumentLayout *>(q->document()->documentLayout())->scheduleUpdate();
|
||||
};
|
||||
|
||||
position();
|
||||
|
||||
connect(widget, &QWidget::destroyed, this, [pState, carrier, this] {
|
||||
if (carrier)
|
||||
carrier->deleteLater();
|
||||
if (!q->document())
|
||||
return;
|
||||
QTextBlock block = pState->cursor.block();
|
||||
auto userData = TextDocumentLayout::userData(block);
|
||||
userData->removeEmbeddedWidget(carrier);
|
||||
});
|
||||
connect(q->document()->documentLayout(), &QAbstractTextDocumentLayout::update, carrier, position);
|
||||
connect(result.get(), &EmbeddedWidgetInterface::resized, carrier, position);
|
||||
connect(result.get(), &EmbeddedWidgetInterface::closed, this, [this, carrier] {
|
||||
if (carrier)
|
||||
carrier->deleteLater();
|
||||
QAbstractTextDocumentLayout *layout = q->document()->documentLayout();
|
||||
QTimer::singleShot(0, layout, [layout] { layout->update(); });
|
||||
});
|
||||
|
||||
carrier->show();
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextEditorWidgetPrivate::registerActions()
|
||||
{
|
||||
using namespace Core::Constants;
|
||||
@@ -4696,6 +4823,7 @@ void TextEditorWidget::resizeEvent(QResizeEvent *e)
|
||||
extraAreaWidth(), cr.height() - 2 * frameWidth())));
|
||||
d->adjustScrollBarRanges();
|
||||
d->updateCurrentLineInScrollbar();
|
||||
emit resized();
|
||||
}
|
||||
|
||||
QRect TextEditorWidgetPrivate::foldBox()
|
||||
@@ -5459,7 +5587,10 @@ QRectF TextEditorWidgetPrivate::cursorBlockRect(const QTextDocument *doc,
|
||||
{
|
||||
const qreal space = charWidth();
|
||||
int relativePos = cursorPosition - block.position();
|
||||
qobject_cast<TextDocumentLayout *>(m_document->document()->documentLayout())
|
||||
->ensureBlockLayout(block);
|
||||
QTextLine line = block.layout()->lineForTextPosition(relativePos);
|
||||
QTC_ASSERT(line.isValid(), return {});
|
||||
qreal x = line.cursorToX(relativePos);
|
||||
qreal w = 0;
|
||||
if (relativePos < line.textLength() - line.textStart()) {
|
||||
@@ -7100,6 +7231,11 @@ TextEditorWidget::SuggestionBlocker TextEditorWidget::blockSuggestions()
|
||||
return d->m_suggestionBlocker;
|
||||
}
|
||||
|
||||
std::unique_ptr<EmbeddedWidgetInterface> TextEditorWidget::insertWidget(QWidget *widget, int line)
|
||||
{
|
||||
return d->insertWidget(widget, line);
|
||||
}
|
||||
|
||||
QList<QTextCursor> TextEditorWidget::autoCompleteHighlightPositions() const
|
||||
{
|
||||
return d->m_autoCompleteHighlightPos;
|
||||
|
@@ -102,6 +102,19 @@ enum Mask {
|
||||
};
|
||||
} // namespace OptionalActions
|
||||
|
||||
class TEXTEDITOR_EXPORT EmbeddedWidgetInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
~EmbeddedWidgetInterface() override;
|
||||
void resize();
|
||||
void close();
|
||||
|
||||
signals:
|
||||
void resized();
|
||||
void closed();
|
||||
};
|
||||
|
||||
class TEXTEDITOR_EXPORT BaseTextEditor : public Core::IEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -520,6 +533,8 @@ public:
|
||||
// Returns an object that blocks suggestions until it is destroyed.
|
||||
SuggestionBlocker blockSuggestions();
|
||||
|
||||
std::unique_ptr<EmbeddedWidgetInterface> insertWidget(QWidget *widget, int line);
|
||||
|
||||
QList<QTextCursor> autoCompleteHighlightPositions() const;
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
@@ -545,6 +560,8 @@ signals:
|
||||
void addSavedStateToNavigationHistory();
|
||||
void addCurrentStateToNavigationHistory();
|
||||
|
||||
void resized();
|
||||
|
||||
protected:
|
||||
QTextBlock blockForVisibleRow(int row) const;
|
||||
QTextBlock blockForVerticalOffset(int offset) const;
|
||||
|
Reference in New Issue
Block a user