logic: lazy load code annotations

* code annotations are loaded after showing the code file
* added traces
* refactored highlighter
* fixed error tooltip style in codeview

fortune cookie message = It's not the time that counts, but what you do with it.
This commit is contained in:
Eberhard Graether
2018-03-24 13:19:49 +01:00
parent 0d79639c96
commit aed783f5ca
24 changed files with 405 additions and 361 deletions
+16 -1
View File
@@ -294,6 +294,21 @@ void QtCodeArea::updateLineNumberAreaWidthForDigits(int digits)
updateLineNumberAreaWidth();
}
void QtCodeArea::updateSourceLocations(std::shared_ptr<SourceLocationFile> locationFile)
{
if (locationFile->getSourceLocationCount() > getSourceLocationFile()->getSourceLocationCount())
{
if (m_hoveredAnnotations.size())
{
setHoveredAnnotations({});
}
createAnnotations(locationFile);
annotateText();
}
}
void QtCodeArea::updateContent()
{
annotateText();
@@ -582,7 +597,7 @@ void QtCodeArea::mouseMoveEvent(QMouseEvent* event)
if (m_navigator->hasErrors() && annotations.size() == 1 && annotations[0]->tokenIds.size())
{
std::wstring errorMessage = m_navigator->getErrorMessageForId(*annotations[0]->tokenIds.begin());
QToolTip::showText(event->globalPos(), QString::fromStdWString(errorMessage));
QToolTip::showText(event->globalPos(), QString::fromStdWString(errorMessage), this);
}
}
}
+1
View File
@@ -69,6 +69,7 @@ public:
int lineNumberAreaWidth() const;
void updateLineNumberAreaWidthForDigits(int digits);
void updateSourceLocations(std::shared_ptr<SourceLocationFile> locationFile);
void updateContent();
void setIsActiveFile(bool isActiveFile);
+14 -7
View File
@@ -14,6 +14,7 @@
#include "utility/messaging/type/MessageActivateTokenIds.h"
#include "utility/messaging/type/MessageTooltipShow.h"
#include "utility/TextCodec.h"
#include "utility/tracing.h"
#include "utility/utility.h"
std::vector<QtCodeField::AnnotationColor> QtCodeField::s_annotationColors;
@@ -33,19 +34,21 @@ QtCodeField::QtCodeField(
: QPlainTextEdit(parent)
, m_startLineNumber(startLineNumber)
, m_code(code)
, m_locationFile(locationFile)
, m_endTextEditPosition(0)
{
TRACE();
setObjectName("code_area");
setReadOnly(true);
setFrameStyle(QFrame::NoFrame);
setLineWrapMode(QPlainTextEdit::NoWrap);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
setMouseTracking(true);
viewport()->setCursor(Qt::ArrowCursor);
std::string displayCode = m_code;
if (!m_locationFile->isWhole() && !displayCode.empty() && *displayCode.rbegin() == '\n')
if (!locationFile->isWhole() && !displayCode.empty() && *displayCode.rbegin() == '\n')
{
displayCode.pop_back();
}
@@ -57,7 +60,8 @@ QtCodeField::QtCodeField(
setPlainText(convertedDisplayCode);
if (displayCode.size() != size_t(convertedDisplayCode.length()))
{
LOG_INFO("Converting displayed code to " + codec.getName() + " resulted in offset of source locations. Correcting this now.");
LOG_INFO("Converting displayed code to " + codec.getName() +
" resulted in offset of source locations. Correcting this now.");
createMultibyteCharacterLocationCache(convertedDisplayCode);
}
}
@@ -68,18 +72,16 @@ QtCodeField::QtCodeField(
createLineLengthCache();
this->setMouseTracking(true);
createAnnotations(locationFile);
FilePath path = m_locationFile->getFilePath();
FilePath path = locationFile->getFilePath();
LanguageType language = LANGUAGE_UNKNOWN;
if (!path.empty())
{
language = (path.extension() == L".java" ? LANGUAGE_JAVA : LANGUAGE_CPP);
}
m_highlighter = new QtHighlighter(document(), language);
m_highlighter = std::make_shared<QtHighlighter>(document(), language);
m_highlighter->highlightDocument();
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
@@ -328,6 +330,11 @@ bool QtCodeField::annotateText(
void QtCodeField::createAnnotations(std::shared_ptr<SourceLocationFile> locationFile)
{
TRACE();
m_locationFile = locationFile;
m_annotations.clear();
uint endLineNumber = getEndLineNumber();
std::set<Id> locationIds;
+3 -3
View File
@@ -25,8 +25,8 @@ public:
uint startLineNumber,
const std::string& code,
std::shared_ptr<SourceLocationFile> locationFile,
bool convertLocationsOnDemand = true,
QWidget* parent = nullptr);
bool convertLocationsOnDemand = true,
QWidget* parent = nullptr);
~QtCodeField();
@@ -115,7 +115,7 @@ private:
std::shared_ptr<SourceLocationFile> m_locationFile;
QtHighlighter* m_highlighter;
std::shared_ptr<QtHighlighter> m_highlighter;
std::vector<int> m_lineLengths;
std::vector<std::vector<std::pair<int, int>>> m_multibyteCharacterLocations;
+38 -68
View File
@@ -12,7 +12,6 @@
QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
: QFrame()
, m_navigator(navigator)
, m_fileSnippet(nullptr)
, m_filePath(filePath)
, m_isWholeFile(false)
, m_contentRequested(false)
@@ -67,6 +66,11 @@ const QtCodeFileTitleBar* QtCodeFile::getTitleBar() const
QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
{
if (m_isWholeFile && m_snippets.size() == 1)
{
return m_snippets[0];
}
for (QtCodeSnippet* snippet : m_snippets)
{
if (snippet->getStartLineNumber() == params.startLineNumber &&
@@ -76,11 +80,6 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
}
}
if (params.locationFile->isWhole() && m_fileSnippet)
{
return m_fileSnippet;
}
QtCodeSnippet* snippet = new QtCodeSnippet(params, m_navigator, this);
if (params.reduced)
@@ -89,31 +88,32 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
m_isWholeFile = true;
}
m_snippetLayout->addWidget(snippet);
if (params.locationFile->isWhole() || m_isWholeFile)
{
snippet->setStyleSheet("#code_snippet { border: none; }");
m_isWholeFile = true;
m_fileSnippet = snippet;
if (!m_snippets.size())
{
m_fileSnippet->setIsActiveFile(true);
}
snippet->setIsActiveFile(true);
setSnippets();
if (params.refCount != -1)
{
updateRefCount(0);
}
return m_fileSnippet;
for (QtCodeSnippet* oldSnippet : m_snippets)
{
oldSnippet->hide();
}
m_snippets.clear();
}
else
{
updateRefCount(params.refCount);
}
m_snippetLayout->addWidget(snippet);
m_snippets.push_back(snippet);
setSnippets();
updateRefCount(params.refCount);
return snippet;
}
@@ -160,13 +160,26 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params)
return snippet;
}
std::vector<QtCodeSnippet*> QtCodeFile::getVisibleSnippets() const
void QtCodeFile::updateCodeSnippet(const CodeSnippetParams& params)
{
if (m_fileSnippet && m_fileSnippet->isVisible())
if (m_isWholeFile && m_snippets.size() == 1)
{
return { m_fileSnippet };
m_snippets[0]->updateCodeSnippet(params);
return;
}
for (QtCodeSnippet* snippet : m_snippets)
{
if (snippet->getStartLineNumber() == params.startLineNumber &&
snippet->getEndLineNumber() == params.endLineNumber)
{
snippet->updateCodeSnippet(params);
}
}
}
std::vector<QtCodeSnippet*> QtCodeFile::getVisibleSnippets() const
{
std::vector<QtCodeSnippet*> snippets;
for (QtCodeSnippet* snippet : m_snippets)
@@ -182,11 +195,6 @@ std::vector<QtCodeSnippet*> QtCodeFile::getVisibleSnippets() const
QtCodeSnippet* QtCodeFile::getSnippetForLocationId(Id locationId) const
{
if (m_fileSnippet && m_fileSnippet->isVisible() && m_fileSnippet->getLineNumberForLocationId(locationId))
{
return m_fileSnippet;
}
for (QtCodeSnippet* snippet : m_snippets)
{
if (snippet->getLineNumberForLocationId(locationId))
@@ -200,11 +208,6 @@ QtCodeSnippet* QtCodeFile::getSnippetForLocationId(Id locationId) const
QtCodeSnippet* QtCodeFile::getSnippetForLine(unsigned int line) const
{
if (m_fileSnippet && m_fileSnippet->isVisible())
{
return m_fileSnippet;
}
for (QtCodeSnippet* snippet : m_snippets)
{
if (snippet->getStartLineNumber() <= line && line <= snippet->getEndLineNumber())
@@ -216,11 +219,6 @@ QtCodeSnippet* QtCodeFile::getSnippetForLine(unsigned int line) const
return nullptr;
}
QtCodeSnippet* QtCodeFile::getFileSnippet() const
{
return m_fileSnippet;
}
std::pair<QtCodeSnippet*, Id> QtCodeFile::getFirstSnippetWithActiveLocationId(Id tokenId) const
{
std::pair<QtCodeSnippet*, Id> result(nullptr, 0);
@@ -241,7 +239,7 @@ std::pair<QtCodeSnippet*, Id> QtCodeFile::getFirstSnippetWithActiveLocationId(Id
bool QtCodeFile::isCollapsed() const
{
return !getFileSnippet() && !m_snippets.size();
return !m_snippets.size();
}
void QtCodeFile::requestContent()
@@ -257,14 +255,14 @@ void QtCodeFile::requestContent()
MessageChangeFileView::FileState state =
m_isWholeFile ? MessageChangeFileView::FILE_MAXIMIZED : MessageChangeFileView::FILE_SNIPPETS;
bool needsData = (state == MessageChangeFileView::FILE_MAXIMIZED) ? (getFileSnippet() == nullptr) : (m_snippets.size() == 0);
bool needsData = (m_snippets.size() == 0);
MessageChangeFileView(m_filePath, state, MessageChangeFileView::VIEW_LIST, needsData, m_navigator->hasErrors()).dispatch();
}
void QtCodeFile::requestWholeFileContent()
{
if (!getFileSnippet())
if (!m_isWholeFile)
{
MessageChangeFileView(
m_filePath,
@@ -288,11 +286,6 @@ void QtCodeFile::updateContent()
{
snippet->updateContent();
}
if (m_fileSnippet)
{
m_fileSnippet->updateContent();
}
}
void QtCodeFile::setWholeFile(bool isWholeFile, int refCount)
@@ -315,11 +308,6 @@ void QtCodeFile::setMinimized()
snippet->hide();
}
if (m_fileSnippet)
{
m_fileSnippet->hide();
}
m_titleBar->setMinimized();
setStyleSheet("#code_file { padding-bottom: 0; } #code_file #title_bar { border-radius: 7px; }");
@@ -327,21 +315,9 @@ void QtCodeFile::setMinimized()
void QtCodeFile::setSnippets()
{
if (m_fileSnippet)
for (QtCodeSnippet* snippet : m_snippets)
{
m_fileSnippet->show();
for (QtCodeSnippet* snippet : m_snippets)
{
snippet->hide();
}
}
else
{
for (QtCodeSnippet* snippet : m_snippets)
{
snippet->show();
}
snippet->show();
}
m_titleBar->setSnippets();
@@ -395,12 +371,6 @@ void QtCodeFile::updateTitleBar()
void QtCodeFile::findScreenMatches(const std::wstring& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
{
if (m_fileSnippet && m_fileSnippet->isVisible())
{
m_fileSnippet->findScreenMatches(query, screenMatches);
return;
}
for (QtCodeSnippet* snippet : m_snippets)
{
if (snippet->isVisible())
+1 -2
View File
@@ -35,11 +35,11 @@ public:
QtCodeSnippet* addCodeSnippet(const CodeSnippetParams& params);
QtCodeSnippet* insertCodeSnippet(const CodeSnippetParams& params);
void updateCodeSnippet(const CodeSnippetParams& params);
std::vector<QtCodeSnippet*> getVisibleSnippets() const;
QtCodeSnippet* getSnippetForLocationId(Id locationId) const;
QtCodeSnippet* getSnippetForLine(unsigned int line) const;
QtCodeSnippet* getFileSnippet() const;
std::pair<QtCodeSnippet*, Id> getFirstSnippetWithActiveLocationId(Id tokenId) const;
@@ -76,7 +76,6 @@ private:
QVBoxLayout* m_snippetLayout;
std::vector<QtCodeSnippet*> m_snippets;
QtCodeSnippet* m_fileSnippet;
const FilePath m_filePath;
bool m_isWholeFile;
+8 -2
View File
@@ -137,6 +137,12 @@ void QtCodeFileList::addCodeSnippet(const CodeSnippetParams& params)
file->setIsComplete(params.locationFile->isComplete());
}
void QtCodeFileList::updateCodeSnippet(const CodeSnippetParams& params)
{
QtCodeFile* file = getFile(params.locationFile->getFilePath());
file->updateCodeSnippet(params);
}
void QtCodeFileList::requestFileContent(const FilePath& filePath)
{
getFile(filePath)->requestContent();
@@ -166,9 +172,9 @@ bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id
{
snippet = file->getSnippetForLine(lineNumber);
}
else if (file->getFileSnippet() && file->getFileSnippet()->isVisible())
else
{
snippet = file->getFileSnippet();
snippet = file->getSnippetForLine(1);
}
if (!snippet)
+1
View File
@@ -35,6 +35,7 @@ public:
virtual QScrollArea* getScrollArea();
virtual void addCodeSnippet(const CodeSnippetParams& params);
virtual void updateCodeSnippet(const CodeSnippetParams& params);
virtual void requestFileContent(const FilePath& filePath);
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target);
@@ -119,6 +119,15 @@ void QtCodeFileSingle::addCodeSnippet(const CodeSnippetParams& params)
}
}
void QtCodeFileSingle::updateCodeSnippet(const CodeSnippetParams& params)
{
auto it = m_fileDatas.find(params.locationFile->getFilePath());
if (it != m_fileDatas.end())
{
it->second.area->updateSourceLocations(params.locationFile);
}
}
void QtCodeFileSingle::requestFileContent(const FilePath& filePath)
{
if (m_contentRequested)
@@ -34,6 +34,7 @@ public:
virtual QAbstractScrollArea* getScrollArea() override;
virtual void addCodeSnippet(const CodeSnippetParams& params) override;
virtual void updateCodeSnippet(const CodeSnippetParams& params) override;
virtual void requestFileContent(const FilePath& filePath) override;
virtual bool requestScroll(
@@ -29,6 +29,7 @@ public:
virtual QAbstractScrollArea* getScrollArea() = 0;
virtual void addCodeSnippet(const CodeSnippetParams& params) = 0;
virtual void updateCodeSnippet(const CodeSnippetParams& params) = 0;
virtual void requestFileContent(const FilePath& filePath) = 0;
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target) = 0;
@@ -140,6 +140,11 @@ void QtCodeNavigator::addCodeSnippet(const CodeSnippetParams& params)
}
}
void QtCodeNavigator::updateCodeSnippet(const CodeSnippetParams& params)
{
m_current->updateCodeSnippet(params);
}
void QtCodeNavigator::addFile(std::shared_ptr<SourceLocationFile> locationFile, int refCount, TimeStamp modificationTime)
{
bool firstFile = m_references.size() == 0;
+1
View File
@@ -43,6 +43,7 @@ public:
virtual ~QtCodeNavigator();
void addCodeSnippet(const CodeSnippetParams& params);
void updateCodeSnippet(const CodeSnippetParams& params);
void addFile(std::shared_ptr<SourceLocationFile> locationFile, int refCount, TimeStamp modificationTime);
void addedFiles();
+5
View File
@@ -139,6 +139,11 @@ int QtCodeSnippet::lineNumberDigits() const
return m_codeArea->lineNumberDigits();
}
void QtCodeSnippet::updateCodeSnippet(const CodeSnippetParams& params)
{
m_codeArea->updateSourceLocations(params.locationFile);
}
void QtCodeSnippet::updateLineNumberAreaWidthForDigits(int digits)
{
m_codeArea->updateLineNumberAreaWidthForDigits(digits);
+2
View File
@@ -37,6 +37,8 @@ public:
int lineNumberDigits() const;
void updateCodeSnippet(const CodeSnippetParams& params);
void updateLineNumberAreaWidthForDigits(int digits);
void updateContent();
+56 -26
View File
@@ -5,6 +5,7 @@
#include <QTextDocument>
#include "settings/ColorScheme.h"
#include "utility/tracing.h"
#include "utility/utility.h"
QVector<QtHighlighter::HighlightingRule> QtHighlighter::s_highlightingRules;
@@ -138,15 +139,22 @@ QtHighlighter::QtHighlighter(QTextDocument *document, LanguageType language)
void QtHighlighter::highlightDocument()
{
TRACE();
QTextDocument* doc = document();
int docStart = 0;
int docEnd = 0;
size_t docStart = 0;
size_t docEnd = 0;
for (int i = 0; i < doc->blockCount(); i++)
{
docEnd += doc->findBlockByLineNumber(i).length();
}
docEnd -= 1;
if (docEnd > 0)
{
docEnd -= 1;
}
applyFormat(docStart, docEnd, s_textFormat);
m_highlightedLines.clear();
@@ -157,18 +165,7 @@ void QtHighlighter::highlightDocument()
return;
}
m_quotationRanges.clear();
m_multiLineCommentRanges.clear();
std::vector<std::pair<int, int>> ranges;
ranges.push_back(std::pair<int, int>(docStart, docEnd));
for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next())
{
utility::append(m_quotationRanges, formatBlockForRule(it, s_stringQuotationRule, &ranges));
utility::append(m_quotationRanges, formatBlockForRule(it, s_charQuotationRule, &ranges));
}
highlightMultiLineComments();
createRanges(doc, s_stringQuotationRule, s_charQuotationRule);
}
void QtHighlighter::highlightRange(int startLine, int endLine)
@@ -252,16 +249,32 @@ QTextCharFormat QtHighlighter::getFormat(int startPosition, int endPosition) con
return cursor.charFormat();
}
void QtHighlighter::highlightMultiLineComments()
void QtHighlighter::createRanges(
QTextDocument* doc, const HighlightingRule& stringRule, const HighlightingRule& charRule)
{
QTextDocument* doc = document();
m_quotationRanges.clear();
m_multiLineCommentRanges.clear();
for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next())
{
utility::append(m_quotationRanges, getRangesForRule(it, stringRule));
utility::append(m_quotationRanges, getRangesForRule(it, charRule));
}
m_multiLineCommentRanges = createMultiLineCommentRanges(doc, &m_quotationRanges);
}
std::vector<std::pair<int, int>> QtHighlighter::createMultiLineCommentRanges(
QTextDocument* doc, std::vector<std::pair<int, int>>* ranges)
{
QRegExp commentStartExpression = QRegExp("(^([^/]|/[^/])*)/\\*");
QRegExp commentEndExpression = QRegExp("\\*/");
QTextCursor cursorStart(doc);
QTextCursor cursorEnd(doc);
std::vector<std::pair<int, int>> multiLineCommentRanges;
while (true)
{
do
@@ -272,7 +285,7 @@ void QtHighlighter::highlightMultiLineComments()
cursorStart.setPosition(cursorStart.selectionEnd() - 2);
}
}
while (isInRange(cursorStart.position(), m_quotationRanges));
while (isInRange(cursorStart.selectionEnd(), *ranges));
if (cursorStart.isNull())
{
@@ -285,9 +298,11 @@ void QtHighlighter::highlightMultiLineComments()
break;
}
m_multiLineCommentRanges.push_back(std::pair<int, int>(cursorStart.selectionStart(), cursorEnd.position()));
multiLineCommentRanges.push_back(std::pair<int, int>(cursorStart.position(), cursorEnd.position()));
cursorStart = cursorEnd;
}
return multiLineCommentRanges;
}
QtHighlighter::HighlightingRule::HighlightingRule()
@@ -313,15 +328,34 @@ bool QtHighlighter::isInRange(int pos, const std::vector<std::pair<int, int>>& r
return false;
}
std::vector<std::pair<int, int>> QtHighlighter::formatBlockForRule(
std::vector<std::pair<int, int>> QtHighlighter::getRangesForRule(
const QTextBlock& block, const HighlightingRule& rule) const
{
QRegExp expression(rule.pattern);
int pos = block.position();
int index = expression.indexIn(block.text());
std::vector<std::pair<int, int>> ranges;
while (index >= 0)
{
int length = expression.matchedLength();
ranges.push_back(std::pair<int, int>(pos + index, pos + index + length));
index = expression.indexIn(block.text(), index + length);
}
return ranges;
}
void QtHighlighter::formatBlockForRule(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges
){
QRegExp expression(rule.pattern);
int pos = block.position();
int index = expression.indexIn(block.text());
std::vector<std::pair<int, int>> newRanges;
while (index >= 0)
{
int length = expression.matchedLength();
@@ -331,12 +365,8 @@ std::vector<std::pair<int, int>> QtHighlighter::formatBlockForRule(
applyFormat(pos + index, pos + index + length, rule.format);
}
newRanges.push_back(std::pair<int, int>(pos + index, pos + index + length));
index = expression.indexIn(block.text(), index + length);
}
return newRanges;
}
void QtHighlighter::formatBlockIfInRange(
+8 -2
View File
@@ -15,6 +15,8 @@ public:
static void clearHighlightingRules();
QtHighlighter(QTextDocument *parent, LanguageType language);
~QtHighlighter() = default;
void highlightDocument();
void highlightRange(int startLine, int endLine);
@@ -34,10 +36,14 @@ private:
QTextCharFormat format;
};
void highlightMultiLineComments();
void createRanges(QTextDocument* doc, const HighlightingRule& stringRule, const HighlightingRule& charRule);
std::vector<std::pair<int, int>> createMultiLineCommentRanges(
QTextDocument* doc, std::vector<std::pair<int, int>>* ranges);
bool isInRange(int index, const std::vector<std::pair<int, int>>& ranges) const;
std::vector<std::pair<int, int>> formatBlockForRule(
std::vector<std::pair<int, int>> getRangesForRule(const QTextBlock& block, const HighlightingRule& rule) const;
void formatBlockForRule(
const QTextBlock& block, const HighlightingRule& rule, std::vector<std::pair<int, int>>* ranges = nullptr);
void formatBlockIfInRange(
const QTextBlock& block, const QTextCharFormat& format, std::vector<std::pair<int, int>>* ranges);
+13
View File
@@ -154,6 +154,19 @@ void QtCodeView::showCodeSnippets(const std::vector<CodeSnippetParams>& snippets
});
}
void QtCodeView::updateCodeSnippets(const std::vector<CodeSnippetParams>& snippets)
{
m_onQtThread([=]()
{
TRACE("update code snippets");
for (const CodeSnippetParams& snippet : snippets)
{
m_widget->updateCodeSnippet(snippet);
}
});
}
void QtCodeView::scrollTo(const ScrollParams params)
{
m_scrollParams = params;
+1
View File
@@ -29,6 +29,7 @@ public:
virtual void clear();
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets, const CodeParams params);
virtual void updateCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
virtual void scrollTo(const ScrollParams params);
virtual bool showsErrors() const;