Optimize painting after changing marks

Change-Id: Ib9e225bc063df82fcb351ff1e2572aa2d663b8a7
Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
This commit is contained in:
Daniel Teske
2012-02-17 14:59:14 +01:00
parent 9483408fec
commit 4083c11002
4 changed files with 63 additions and 31 deletions

View File

@@ -30,6 +30,7 @@
#include "basetextdocumentlayout.h"
#include <utils/qtcassert.h>
#include <QDebug>
using namespace TextEditor;
@@ -53,8 +54,6 @@ public:
void removeMarkFromMarksCache(TextEditor::ITextMark *mark);
private:
double recalculateMaxMarkWidthFactor() const;
TextMarks m_marksCache; // not owned
QTextDocument *document;
};
@@ -87,24 +86,23 @@ bool DocumentMarker::addMark(TextEditor::ITextMark *mark)
mark->updateLineNumber(blockNumber + 1);
QTC_CHECK(mark->lineNumber() == blockNumber + 1); // Checks that the base class is called
mark->updateBlock(block);
if (!mark->visible())
return true;
// Update document layout
double newMaxWidthFactor = qMax(mark->widthFactor(), documentLayout->maxMarkWidthFactor);
bool fullUpdate = newMaxWidthFactor > documentLayout->maxMarkWidthFactor || !documentLayout->hasMarks;
documentLayout->hasMarks = true;
documentLayout->maxMarkWidthFactor = qMax(mark->widthFactor(),
documentLayout->maxMarkWidthFactor);
documentLayout->requestUpdate();
documentLayout->maxMarkWidthFactor = newMaxWidthFactor;
if (fullUpdate)
documentLayout->requestUpdate();
else
documentLayout->requestExtraAreaUpdate();
mark->setMarkableInterface(this);
return true;
}
return false;
}
double DocumentMarker::recalculateMaxMarkWidthFactor() const
{
double maxWidthFactor = 1.0;
foreach (const ITextMark *mark, marks())
maxWidthFactor = qMax(mark->widthFactor(), maxWidthFactor);
return maxWidthFactor;
}
TextEditor::TextMarks DocumentMarker::marksAt(int line) const
{
QTC_ASSERT(line >= 1, return TextMarks());
@@ -123,31 +121,50 @@ void DocumentMarker::removeMarkFromMarksCache(TextEditor::ITextMark *mark)
BaseTextDocumentLayout *documentLayout =
qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
QTC_ASSERT(documentLayout, return);
bool needUpdate = m_marksCache.removeOne(mark);
m_marksCache.removeAll(mark);
if (m_marksCache.isEmpty()) {
documentLayout->hasMarks = false;
needUpdate = true;
documentLayout->maxMarkWidthFactor = 1.0;
documentLayout->requestUpdate();
return;
}
if (needUpdate) {
documentLayout->maxMarkWidthFactor = recalculateMaxMarkWidthFactor();
updateMark(0);
if (!mark->visible())
return;
if (documentLayout->maxMarkWidthFactor == 1.0
|| mark->widthFactor() == 1.0
|| mark->widthFactor() < documentLayout->maxMarkWidthFactor) {
// No change in width possible
documentLayout->requestExtraAreaUpdate();
} else {
double maxWidthFactor = 1.0;
foreach (const ITextMark *mark, marks()) {
if (!mark->visible())
continue;
maxWidthFactor = qMax(mark->widthFactor(), maxWidthFactor);
if (maxWidthFactor == documentLayout->maxMarkWidthFactor)
break; // Still a mark with the maxMarkWidthFactor
}
if (maxWidthFactor != documentLayout->maxMarkWidthFactor) {
documentLayout->maxMarkWidthFactor = maxWidthFactor;
documentLayout->requestUpdate();
} else {
documentLayout->requestExtraAreaUpdate();
}
}
}
void DocumentMarker::removeMark(TextEditor::ITextMark *mark)
{
BaseTextDocumentLayout *documentLayout =
qobject_cast<BaseTextDocumentLayout*>(document->documentLayout());
QTC_ASSERT(documentLayout, return);
QTextBlock block = document->begin();
while (block.isValid()) {
if (TextBlockUserData *data = static_cast<TextBlockUserData *>(block.userData())) {
data->removeMark(mark);
}
block = block.next();
QTextBlock block = document->findBlockByNumber(mark->lineNumber() - 1);
if (TextBlockUserData *data = static_cast<TextBlockUserData *>(block.userData())) {
if (!data->removeMark(mark))
qDebug() << "Could not find mark" << mark << "on line" << mark->lineNumber();
}
removeMarkFromMarksCache(mark);
mark->setMarkableInterface(0);
}
@@ -170,9 +187,7 @@ CodeFormatterData::~CodeFormatterData()
TextBlockUserData::~TextBlockUserData()
{
TextMarks marks = m_marks;
m_marks.clear();
foreach (ITextMark *mrk, marks) {
foreach (ITextMark *mrk, m_marks) {
TextEditor::Internal::DocumentMarker *documentMarker
= static_cast<TextEditor::Internal::DocumentMarker *>(mrk->markableInterface());
documentMarker->removeMarkFromMarksCache(mrk);
@@ -675,6 +690,11 @@ void BaseTextDocumentLayout::setFolded(const QTextBlock &block, bool folded)
}
}
void BaseTextDocumentLayout::requestExtraAreaUpdate()
{
emit updateExtraArea();
}
ITextMarkable *BaseTextDocumentLayout::markableInterface()
{
return m_documentMarker;
@@ -748,6 +768,7 @@ void BaseTextDocumentLayout::documentReloaded(TextMarks marks)
= static_cast<TextEditor::Internal::DocumentMarker *>(m_documentMarker);
documentMarker->removeMarkFromMarksCache(mark);
mark->removedFromEditor();
mark->setMarkableInterface(0);
}
}
requestUpdate();

View File

@@ -203,6 +203,7 @@ public:
return data;
}
void requestExtraAreaUpdate();
void emitDocumentSizeChanged() { emit documentSizeChanged(documentSize()); }
ITextMarkable *markableInterface();
@@ -222,6 +223,9 @@ public:
void documentReloaded(TextMarks marks);
void updateMarksLineNumber();
void updateMarksBlock(const QTextBlock &block);
signals:
void updateExtraArea();
};
} // namespace TextEditor

View File

@@ -2529,6 +2529,7 @@ void BaseTextEditorWidgetPrivate::setupDocumentSignals(BaseTextDocument *documen
q->setCursorWidth(2); // Applies to the document layout
QObject::connect(documentLayout, SIGNAL(updateBlock(QTextBlock)), q, SLOT(slotUpdateBlockNotify(QTextBlock)));
QObject::connect(documentLayout, SIGNAL(updateExtraArea()), q, SLOT(slotUpdateExtraArea()));
QObject::connect(q, SIGNAL(requestBlockUpdate(QTextBlock)), documentLayout, SIGNAL(updateBlock(QTextBlock)));
QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(changed()));
QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q,
@@ -4113,6 +4114,11 @@ void BaseTextEditorWidget::slotUpdateBlockNotify(const QTextBlock &block)
blockRecursion = false;
}
void BaseTextEditorWidget::slotUpdateExtraArea()
{
d->m_extraArea->update();
}
void BaseTextEditorWidget::timerEvent(QTimerEvent *e)
{
if (e->timerId() == d->autoScrollTimer.timerId()) {

View File

@@ -525,6 +525,7 @@ protected:
virtual QString foldReplacementText(const QTextBlock &block) const;
protected slots:
virtual void slotUpdateExtraArea();
virtual void slotUpdateExtraAreaWidth();
virtual void slotModificationChanged(bool);
virtual void slotUpdateRequest(const QRect &r, int dy);