Don't store ExtraSelection but always recreate it
MODIFY
src/editor/highlightabletextedit.cpp
src/editor/highlightabletextedit.cpp
@@ -43,7 +43,10 @@ void HighlightableTextEdit::paintEvent(QPaintEvent* event) {
void HighlightableTextEdit::applyHighlighting() {
QList<QTextEdit::ExtraSelection> selections;
- llvm::transform(m_blockHighlights, std::back_inserter(selections), [](const auto& bh) { return bh.selection; });
+ for (auto& bh : m_blockHighlights) {
+ if (auto selection = getExtraSelection(bh); selection.has_value())
+ selections.push_back(selection.value());
+ }
setExtraSelections(selections);
// The block text is drawn on the viewport itself, which is not automatically redrawn when the extra selections
@@ -64,24 +67,8 @@ void HighlightableTextEdit::clearBlockHighlights() {
update();
}
-void HighlightableTextEdit::setBlockGradient(BlockHighlight& highlight) {
- auto block = highlight.selection.cursor.block();
- if (!block.isValid())
- return;
- const auto bbr = blockBoundingRect(block);
- QLinearGradient grad(bbr.topLeft(), bbr.bottomRight());
- grad.setColorAt(0, palette().base().color());
- grad.setColorAt(1, highlight.color);
- highlight.selection.format.setBackground(grad);
-}
-
void HighlightableTextEdit::resizeEvent(QResizeEvent* e) {
QPlainTextEdit::resizeEvent(e);
-
- // we need to update the highlighted lines whenever resizing the window to recalculate the highlighting gradient,
- // reflecting the new widget size
- for (auto& highlight : m_blockHighlights)
- setBlockGradient(highlight);
applyHighlighting();
}
@@ -94,14 +81,28 @@ void HighlightableTextEdit::highlightBlock(const QTextBlock& block, const QColor
// Check if we're already highlighting the block. If this is the case, do not set an additional highlight on it.
if (m_highlightedBlocks.count(block))
return;
-
m_blockHighlights.push_back({});
auto& highlight = m_blockHighlights.back();
- highlight.selection.cursor = QTextCursor(block);
- highlight.selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+ highlight.blockNumber = block.blockNumber();
highlight.color = color;
- setBlockGradient(highlight);
applyHighlighting();
}
+std::optional<QTextEdit::ExtraSelection>
+HighlightableTextEdit::getExtraSelection(const HighlightableTextEdit::BlockHighlight& highlighting) {
+ auto block = document()->findBlockByNumber(highlighting.blockNumber);
+ if (!block.isValid())
+ return {};
+
+ QTextEdit::ExtraSelection selection;
+ selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+ selection.cursor = QTextCursor(block);
+ const auto bbr = blockBoundingRect(block);
+ QLinearGradient grad(bbr.topLeft(), bbr.bottomRight());
+ grad.setColorAt(0, palette().base().color());
+ grad.setColorAt(1, highlighting.color);
+ selection.format.setBackground(grad);
+ return {selection};
+}
+
} // namespace Ripes

MODIFY
src/editor/highlightabletextedit.h
src/editor/highlightabletextedit.h
#include <QScrollBar>
#include <QTimer>
+#include <optional>
#include <set>
namespace Ripes {
@@ -18,7 +19,10 @@ class HighlightableTextEdit : public QPlainTextEdit {
struct BlockHighlight {
// Store the color which the block is highlighted with so that we can rehighlight a selection.
QColor color;
- QTextEdit::ExtraSelection selection;
+ // Only store the block number, not the block itself nor a ExtraSelection. After countless of hours of
+ // debugging, it's deemed that all of this is very unsafe to store outside of the QPlainTextEdit itself, and so
+ // we just rebuild all of this info whenever needed.
+ int blockNumber;
};
public:
@@ -34,7 +38,9 @@ protected:
void resizeEvent(QResizeEvent* event) override;
private:
- void setBlockGradient(BlockHighlight& highlight);
+ /// Creates a new ExtraSelection formatting from the information stored in BlockHighlighting.
+ std::optional<QTextEdit::ExtraSelection>
+ getExtraSelection(const HighlightableTextEdit::BlockHighlight& highlighting);
void applyHighlighting();
/// A list of strings which will be printed at the right-hand side of each block

Don't store ExtraSelection but always recreate it