logic: Improved code view performance

* Don't set stylesheet for every token activation
* Streamlined code area creation steps
* Delay most syntax highlighting until lines become visible
This commit is contained in:
Eberhard Graether
2017-06-05 23:34:20 +02:00
parent 30e6512d71
commit 71b3bdb26b
12 changed files with 217 additions and 123 deletions
+42 -39
View File
@@ -9,6 +9,7 @@
#include <QPainter>
#include <QPushButton>
#include <QScrollBar>
#include <QTextBlock>
#include <QToolTip>
#include "utility/messaging/type/MessageActivateLocalSymbols.h"
@@ -110,22 +111,7 @@ QtCodeArea::QtCodeArea(
viewport()->setCursor(Qt::ArrowCursor);
FilePath path = m_locationFile->getFilePath();
LanguageType language = LANGUAGE_UNKNOWN;
if (!path.empty())
{
if (path.extension() == ".java")
{
language = LANGUAGE_JAVA;
}
else
{
language = LANGUAGE_CPP;
}
}
m_lineNumberArea = new LineNumberArea(this);
m_highlighter = new QtHighlighter(document(), language);
std::string displayCode = m_code;
if (!displayCode.empty() && *displayCode.rbegin() == '\n')
@@ -149,10 +135,18 @@ QtCodeArea::QtCodeArea(
m_scrollSpeedChangeListener.setScrollBar(horizontalScrollBar());
createActions();
m_highlighter->highlightDocument();
createAnnotations(locationFile);
FilePath path = m_locationFile->getFilePath();
LanguageType language = LANGUAGE_UNKNOWN;
if (!path.empty())
{
language = (path.extension() == ".java" ? LANGUAGE_JAVA : LANGUAGE_CPP);
}
m_highlighter = new QtHighlighter(document(), language);
m_highlighter->highlightDocument();
}
QtCodeArea::~QtCodeArea()
@@ -406,15 +400,25 @@ void QtCodeArea::paintEvent(QPaintEvent* event)
{
if (firstVisibleLine < 0 && bottom >= event->rect().top())
{
firstVisibleLine = block.blockNumber();;
firstVisibleLine = block.blockNumber();
}
lastVisibleLine = block.blockNumber();;
lastVisibleLine = block.blockNumber();
}
block = block.next();
top = bottom;
bottom = top + static_cast<int>(blockBoundingRect(block).height());
}
std::vector<std::pair<int, int>> ranges;
for (size_t i : m_colorChangedAnnotationIndices)
{
Annotation& annotation = m_annotations[i];
ranges.push_back(std::pair<int, int>(annotation.start, annotation.end));
}
m_highlighter->highlightRange(firstVisibleLine, lastVisibleLine, ranges);
firstVisibleLine += m_startLineNumber;
lastVisibleLine += m_startLineNumber;
@@ -834,9 +838,13 @@ void QtCodeArea::annotateText()
const std::set<Id>& activeLocalSymbolIds = m_navigator->getActiveLocalSymbolIds();
const std::set<Id>& focusIds = m_navigator->getFocusedTokenIds();
std::vector<int> linesToRehighlight;
bool needsUpdate = false;
for (Annotation& annotation: m_annotations)
for (size_t i = 0; i < m_annotations.size(); i++)
{
Annotation& annotation = m_annotations[i];
bool wasActive = annotation.isActive;
bool wasFocused = annotation.isFocused;
const AnnotationColor& oldColor = getAnnotationColorForAnnotation(annotation);
@@ -860,31 +868,21 @@ void QtCodeArea::annotateText()
{
if (newColor.text.size() > 0 && newColor.text != "transparent")
{
bool isDuplicateAnnotation = false;
for (Annotation* a : m_colorChangedAnnotations)
if (!annotation.oldTextColor.isValid())
{
if (a->start == annotation.start && a->end == annotation.end && a->locationId != annotation.locationId)
{
isDuplicateAnnotation = true;
break;
}
annotation.oldTextColor = m_highlighter->getFormat(annotation.start, annotation.end).foreground().color();
}
if (!isDuplicateAnnotation)
{
if (!annotation.oldTextColor.isValid())
{
annotation.oldTextColor = m_highlighter->getFormat(annotation.start, annotation.end).foreground().color();
}
setTextColorForAnnotation(annotation, QColor(newColor.text.c_str()));
m_colorChangedAnnotations.push_back(&annotation);
}
setTextColorForAnnotation(annotation, QColor(newColor.text.c_str()));
m_colorChangedAnnotationIndices.insert(i);
}
else if (annotation.oldTextColor.isValid())
{
setTextColorForAnnotation(annotation, annotation.oldTextColor);
annotation.oldTextColor = QColor();
m_colorChangedAnnotationIndices.erase(i);
linesToRehighlight.push_back(annotation.startLine - 1);
}
}
@@ -894,7 +892,12 @@ void QtCodeArea::annotateText()
}
}
if (needsUpdate)
if (linesToRehighlight.size())
{
m_highlighter->rehighlightLines(linesToRehighlight);
}
if (m_wasAnnotated && needsUpdate)
{
m_lineNumberArea->update();
viewport()->update();
+1 -2
View File
@@ -188,8 +188,7 @@ private:
std::vector<Annotation> m_annotations;
std::vector<const Annotation*> m_hoveredAnnotations;
// Remove when annotations become unique regarding start and end, and store multiple tokenIds
std::vector<Annotation*> m_colorChangedAnnotations;
std::set<size_t> m_colorChangedAnnotationIndices;
int m_digits;
+12 -6
View File
@@ -30,6 +30,7 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
m_titleBar = new QPushButton(this);
m_titleBar->setObjectName("title_widget");
m_titleBar->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
layout->addWidget(m_titleBar);
QHBoxLayout* titleLayout = new QHBoxLayout();
@@ -83,6 +84,8 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton()));
m_snippetLayout = new QVBoxLayout();
m_snippetLayout->setContentsMargins(0, 0, 0, 0);
m_snippetLayout->setSpacing(0);
layout->addLayout(m_snippetLayout);
update();
@@ -122,8 +125,7 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
if (params.locationFile->isWhole())
{
snippet->setProperty("isFirst", true);
snippet->setProperty("isLast", true);
snippet->setStyleSheet("#code_snippet { border: none; }");
m_fileSnippet = snippet;
if (!m_snippets.size())
@@ -359,8 +361,10 @@ void QtCodeFile::updateSnippets()
int maxDigits = 1;
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
{
snippet->setProperty("isFirst", false);
snippet->setProperty("isLast", false);
if (snippet != m_snippets.front() && snippet->styleSheet().size())
{
snippet->setStyleSheet("");
}
maxDigits = qMax(maxDigits, snippet->lineNumberDigits());
}
@@ -370,8 +374,10 @@ void QtCodeFile::updateSnippets()
snippet->updateLineNumberAreaWidthForDigits(maxDigits);
}
m_snippets.front()->setProperty("isFirst", true);
m_snippets.back()->setProperty("isLast", true);
if (!m_snippets.front()->styleSheet().size())
{
m_snippets.front()->setStyleSheet("#code_snippet { border: none; }");
}
}
void QtCodeFile::updateTitleBar()
+22 -14
View File
@@ -29,15 +29,19 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
if (rect.height() > 0)
{
focusRect = QRect(childWidget->mapTo(parentWidget, rect.topLeft().toPoint()), rect.size().toSize());
focusRect.adjust(0, 0, 0, 100);
if (focusRect.height() < 100)
{
focusRect.adjust(0, 0, 0, 100);
}
}
QScrollBar* scrollBar = area->verticalScrollBar();
int value = focusRect.center().y() - visibleRect.center().y();
if (onTop)
if (onTop || focusRect.height() > visibleRect.height())
{
value = focusRect.top() - visibleRect.top();
value = focusRect.top() - visibleRect.top() - 20;
}
if (scrollBar && (value > 50 || value < -50))
@@ -113,17 +117,21 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe
int value = scrollHeight * scrollFactor;
if (animated && ApplicationSettings::getInstance()->getUseAnimations())
int diff = value - scrollBar->value();
if (diff > 5 || diff < -5)
{
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
anim->setDuration(300);
anim->setStartValue(scrollBar->value());
anim->setEndValue(value);
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->start();
}
else
{
scrollBar->setValue(value);
if (animated && ApplicationSettings::getInstance()->getUseAnimations())
{
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
anim->setDuration(300);
anim->setStartValue(scrollBar->value());
anim->setEndValue(value);
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->start();
}
else
{
scrollBar->setValue(value);
}
}
}
+1 -3
View File
@@ -20,7 +20,6 @@
#include "qt/utility/utilityQt.h"
#include "settings/ApplicationSettings.h"
QtCodeNavigator::QtCodeNavigator(QWidget* parent)
: QWidget(parent)
, m_mode(MODE_NONE)
@@ -586,7 +585,7 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
if (!m_activeTokenId)
{
if (m_mode == MODE_SINGLE && m_references.size() && m_references.front().locationType != LOCATION_TOKEN)
if (m_references.size() && m_references.front().locationType != LOCATION_TOKEN)
{
requestScroll(m_references.front().filePath, 0, m_references.front().locationId, false, false);
emit scrollRequest();
@@ -596,7 +595,6 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
if (m_mode == MODE_LIST)
{
std::cout << animated << std::endl;
std::pair<QtCodeSnippet*, Id> result = m_list->getFirstSnippetWithActiveLocationId(m_activeTokenId);
if (result.first != nullptr)
{
+2 -1
View File
@@ -19,7 +19,8 @@ std::shared_ptr<QtCodeSnippet> QtCodeSnippet::merged(
SourceLocationFile* aFile = a->m_codeArea->getSourceLocationFile().get();
SourceLocationFile* bFile = b->m_codeArea->getSourceLocationFile().get();
std::shared_ptr<SourceLocationFile> locationFile = std::make_shared<SourceLocationFile>(aFile->getFilePath(), aFile->isWhole(), aFile->isWhole());
std::shared_ptr<SourceLocationFile> locationFile =
std::make_shared<SourceLocationFile>(aFile->getFilePath(), aFile->isWhole(), aFile->isWhole());
aFile->forEachSourceLocation(
[&locationFile](SourceLocation* loc)