From aed783f5ca59f1c2d018f5b92c57849f6d61d66e Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Sat, 24 Mar 2018 13:19:49 +0100 Subject: [PATCH] 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. --- .../component/controller/CodeController.cpp | 432 ++++++++---------- src/lib/component/controller/CodeController.h | 26 +- src/lib/component/view/CodeView.h | 1 + src/lib/data/location/SourceLocationFile.cpp | 10 + src/lib/data/location/SourceLocationFile.h | 2 + src/lib_gui/qt/element/QtCodeArea.cpp | 17 +- src/lib_gui/qt/element/QtCodeArea.h | 1 + src/lib_gui/qt/element/QtCodeField.cpp | 21 +- src/lib_gui/qt/element/QtCodeField.h | 6 +- src/lib_gui/qt/element/QtCodeFile.cpp | 106 ++--- src/lib_gui/qt/element/QtCodeFile.h | 3 +- src/lib_gui/qt/element/QtCodeFileList.cpp | 10 +- src/lib_gui/qt/element/QtCodeFileList.h | 1 + src/lib_gui/qt/element/QtCodeFileSingle.cpp | 9 + src/lib_gui/qt/element/QtCodeFileSingle.h | 1 + src/lib_gui/qt/element/QtCodeNavigateable.h | 1 + src/lib_gui/qt/element/QtCodeNavigator.cpp | 5 + src/lib_gui/qt/element/QtCodeNavigator.h | 1 + src/lib_gui/qt/element/QtCodeSnippet.cpp | 5 + src/lib_gui/qt/element/QtCodeSnippet.h | 2 + src/lib_gui/qt/utility/QtHighlighter.cpp | 82 ++-- src/lib_gui/qt/utility/QtHighlighter.h | 10 +- src/lib_gui/qt/view/QtCodeView.cpp | 13 + src/lib_gui/qt/view/QtCodeView.h | 1 + 24 files changed, 405 insertions(+), 361 deletions(-) diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index ac802506..ffcae343 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -93,7 +93,7 @@ void CodeController::handleMessage(MessageActivateAll* message) CodeView::CodeParams params; params.clearSnippets = true; params.showContents = !message->isReplayed(); - getView()->showCodeSnippets(std::vector(1, statsSnippet), params); + showCodeSnippets({ statsSnippet }, params); } void CodeController::handleMessage(MessageActivateLocalSymbols* message) @@ -138,43 +138,39 @@ void CodeController::handleMessage(MessageActivateTokens* message) if (message->keepContent()) { view->showActiveTokenIds(params.activeTokenIds); + return; } - else + + CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); + scrollParams.ignoreActiveReference = true; + view->scrollTo(scrollParams); + + m_collection = m_storageAccess->getSourceLocationsForTokenIds(params.activeTokenIds); + showCodeSnippets(getSnippetsForActiveSourceLocations(m_collection.get(), declarationId), params); + + + size_t fileCount = m_collection->getSourceLocationFileCount(); + size_t referenceCount = m_collection->getSourceLocationCount(); + + std::wstring status = L""; + + if (message->tokenNames.size()) { - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); - scrollParams.ignoreActiveReference = true; - view->scrollTo(scrollParams); - - m_collection = m_storageAccess->getSourceLocationsForTokenIds(params.activeTokenIds); - - std::vector snippets = getSnippetsForActiveSourceLocations(m_collection.get(), declarationId); - expandVisibleSnippets(&snippets, true); - - view->showCodeSnippets(snippets, params); - - size_t fileCount = m_collection->getSourceLocationFileCount(); - size_t referenceCount = m_collection->getSourceLocationCount(); - - std::wstring status = L""; - - if (message->tokenNames.size()) - { - status += L"Activate \"" + message->tokenNames[0].getQualifiedName() + L"\": "; - } - - status += std::to_wstring(message->tokenIds.size()) + L" "; - status += (message->tokenIds.size() == 1 ? L"result" : L"results"); - - if (fileCount > 0) - { - status += L" with " + std::to_wstring(referenceCount) + L" "; - status += (referenceCount == 1 ? L"reference" : L"references"); - status += L" in " + std::to_wstring(fileCount) + L" "; - status += (fileCount == 1 ? L"file" : L"files"); - } - - MessageStatus(status).dispatch(); + status += L"Activate \"" + message->tokenNames[0].getQualifiedName() + L"\": "; } + + status += std::to_wstring(message->tokenIds.size()) + L" "; + status += (message->tokenIds.size() == 1 ? L"result" : L"results"); + + if (fileCount > 0) + { + status += L" with " + std::to_wstring(referenceCount) + L" "; + status += (referenceCount == 1 ? L"reference" : L"references"); + status += L" in " + std::to_wstring(fileCount) + L" "; + status += (fileCount == 1 ? L"file" : L"files"); + } + + MessageStatus(status).dispatch(); } void CodeController::handleMessage(MessageActivateTrailEdge* message) @@ -192,8 +188,7 @@ void CodeController::handleMessage(MessageActivateTrailEdge* message) params.activeTokenIds.push_back(message->tokenId); m_collection = m_storageAccess->getSourceLocationsForTokenIds(params.activeTokenIds); - - getView()->showCodeSnippets(getSnippetsForActiveSourceLocations(m_collection.get(), 0), params); + showCodeSnippets(getSnippetsForActiveSourceLocations(m_collection.get(), 0), params); } void CodeController::handleMessage(MessageChangeFileView* message) @@ -224,8 +219,7 @@ void CodeController::handleMessage(MessageChangeFileView* message) if (message->needsData && !message->filePath.empty()) { - CodeView::CodeParams params; - view->showCodeSnippets(getSnippetsForFileWithState(message->filePath, state, !message->showErrors), params); + showCodeSnippets(getSnippetsForFileWithState(message->filePath, state), CodeView::CodeParams()); } view->setFileState(message->filePath, state); @@ -318,17 +312,12 @@ void CodeController::handleMessage(MessageShowErrors* message) std::sort(snippets.begin(), snippets.end(), CodeSnippetParams::sortById); - if (view->isInListMode()) - { - expandVisibleSnippets(&snippets, false); - } - CodeView::CodeParams params; params.clearSnippets = true; params.errorInfos = errors; params.showContents = !message->isReplayed(); - view->showCodeSnippets(snippets, params); + showCodeSnippets(snippets, params, false); } if (message->errorId) @@ -348,13 +337,11 @@ void CodeController::handleMessage(MessageSearchFullText* message) CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); getView()->scrollTo(scrollParams); - std::vector snippets = getSnippetsForCollection(m_collection, true); - expandVisibleSnippets(&snippets, true); - CodeView::CodeParams params; params.clearSnippets = true; params.showContents = !message->isReplayed(); - getView()->showCodeSnippets(snippets, params); + + showCodeSnippets(getSnippetsForCollection(m_collection), params); } void CodeController::handleMessage(MessageShowScope* message) @@ -362,7 +349,7 @@ void CodeController::handleMessage(MessageShowScope* message) TRACE("code scope"); std::shared_ptr collection = - m_storageAccess->getSourceLocationsForLocationIds({message->scopeLocationId}); + m_storageAccess->getSourceLocationsForLocationIds({ message->scopeLocationId }); SourceLocation* location = collection->getSourceLocationById(message->scopeLocationId); if (!location || !location->isScopeLocation() || !location->getOtherLocation()) @@ -371,8 +358,7 @@ void CodeController::handleMessage(MessageShowScope* message) return; } - std::vector snippets = - getSnippetsForFile(collection->getSourceLocationFiles().begin()->second, true); + std::vector snippets = getSnippetsForFile(collection->getSourceLocationFiles().begin()->second); if (snippets.size() != 1) { LOG_ERROR("MessageShowScope didn't result in one single snippet to be created"); @@ -381,17 +367,10 @@ void CodeController::handleMessage(MessageShowScope* message) snippets[0].insertSnippet = true; - if (message->showErrors) - { - snippets[0].locationFile = m_collection->getSourceLocationFileByPath(snippets[0].locationFile->getFilePath()); - } - else - { - addActiveSourceLocations(snippets[0].locationFile); - } - CodeView::CodeParams params; params.showContents = !message->isReplayed(); + + addAllSourceLocations(&snippets); getView()->showCodeSnippets(snippets, params); } @@ -407,52 +386,8 @@ void CodeController::clear() m_collection.reset(); } -void CodeController::expandVisibleSnippets(std::vector* snippets, bool addSourceLocations) const -{ - TRACE(); - - if (!snippets->size()) - { - return; - } - - bool inListMode = getView()->isInListMode(); - - size_t filesToExpand = inListMode ? std::min(int(snippets->size()), 3) : 1; - CodeView::FileState state = inListMode ? CodeView::FILE_SNIPPETS : CodeView::FILE_MAXIMIZED; - - for (size_t i = 0; i < filesToExpand; i++) - { - CodeSnippetParams& oldSnippet = snippets->at(i); - - if (!inListMode && getView()->hasSingleFileCached(oldSnippet.locationFile->getFilePath())) - { - continue; - } - - CodeView::FileState fileState = oldSnippet.locationFile->isWhole() ? CodeView::FILE_MAXIMIZED : state; - - std::vector newSnippets = - getSnippetsForFileWithState(oldSnippet.locationFile->getFilePath(), fileState, addSourceLocations); - if (!newSnippets.size()) - { - continue; - } - - for (CodeSnippetParams& newSnippet : newSnippets) - { - newSnippet.isDeclaration = oldSnippet.isDeclaration; - newSnippet.isDefinition = oldSnippet.isDefinition; - - newSnippet.isCollapsed = false; - } - - snippets->insert(snippets->end(), newSnippets.begin(), newSnippets.end()); - } -} - std::vector CodeController::getSnippetsForFileWithState( - const FilePath& filePath, CodeView::FileState state, bool addSourceLocations) const + const FilePath& filePath, CodeView::FileState state) const { TRACE(); @@ -468,7 +403,7 @@ std::vector CodeController::getSnippetsForFileWithState( return snippets; } - snippets = getSnippetsForFile(file, addSourceLocations); + snippets = getSnippetsForFile(file); } break; @@ -483,24 +418,16 @@ std::vector CodeController::getSnippetsForFileWithState( params.modificationTime = m_storageAccess->getFileInfoForFilePath(filePath).lastWriteTime; - if (!addSourceLocations) + params.locationFile = m_collection->getSourceLocationFileByPath(filePath); + if (params.locationFile) { - params.locationFile = m_collection->getSourceLocationFileByPath(filePath); - if (!params.locationFile) - { - break; - } params.locationFile->setIsWhole(true); } - else - { - params.locationFile = m_storageAccess->getSourceLocationsForFile(filePath); - addActiveSourceLocations(params.locationFile); - } snippets.push_back(params); } break; + default: break; } @@ -553,13 +480,13 @@ std::vector CodeController::getSnippetsForActiveSourceLocatio std::sort(snippets.begin(), snippets.end(), CodeSnippetParams::sort); - addModificationTimes(snippets); + addModificationTimes(&snippets); return snippets; } std::vector CodeController::getSnippetsForCollection( - std::shared_ptr collection, bool addSourceLocations + std::shared_ptr collection ) const { TRACE(); @@ -578,20 +505,21 @@ std::vector CodeController::getSnippetsForCollection( } ); - addModificationTimes(snippets); + addModificationTimes(&snippets); return snippets; } std::vector CodeController::getSnippetsForFile( - std::shared_ptr activeSourceLocations, bool addSourceLocations + std::shared_ptr activeSourceLocations ) const { TRACE(); std::shared_ptr textAccess = m_storageAccess->getFileContent(activeSourceLocations->getFilePath()); + size_t lineCount = textAccess->getLineCount(); - SnippetMerger fileScopedMerger(1, textAccess->getLineCount()); + SnippetMerger fileScopedMerger(1, lineCount); std::map> mergers; std::shared_ptr scopeLocations = @@ -599,7 +527,7 @@ std::vector CodeController::getSnippetsForFile( activeSourceLocations->forEachStartSourceLocation( [&](SourceLocation* location) { - buildMergerHierarchy(location, scopeLocations, fileScopedMerger, mergers); + buildMergerHierarchy(location, scopeLocations.get(), fileScopedMerger, mergers); } ); @@ -613,8 +541,8 @@ std::vector CodeController::getSnippetsForFile( )); } ); - atomicRanges = SnippetMerger::Range::mergeAdjacent(atomicRanges); + atomicRanges = SnippetMerger::Range::mergeAdjacent(atomicRanges); std::deque ranges = fileScopedMerger.merge(atomicRanges); const int snippetExpandRange = ApplicationSettings::getInstance()->getCodeSnippetExpandRange(); @@ -626,54 +554,39 @@ std::vector CodeController::getSnippetsForFile( params.refCount = activeSourceLocations->getUnscopedStartLocationCount(); params.startLineNumber = std::max(1, range.start.row - (range.start.strong ? 0 : snippetExpandRange)); - params.endLineNumber = - std::min(textAccess->getLineCount(), range.end.row + (range.end.strong ? 0 : snippetExpandRange)); + params.endLineNumber = std::min(lineCount, range.end.row + (range.end.strong ? 0 : snippetExpandRange)); params.locationFile = activeSourceLocations->getFilteredByLines(params.startLineNumber, params.endLineNumber); - params.titleId = 0; - params.footerId = 0; - std::shared_ptr tempFile = m_storageAccess->getSourceLocationsForLinesInFile( - activeSourceLocations->getFilePath(), params.startLineNumber, params.endLineNumber); - - const SourceLocation* firstSourceLocation = - tempFile->getSourceLocations().size() ? tempFile->getSourceLocations().begin()->get() : nullptr; - - if (firstSourceLocation) + if (params.startLineNumber > 1) { - // this SourceLocationFile only contains a single StartSourceLocation. - getSourceLocationOfParentScope(firstSourceLocation, scopeLocations)->forEachStartSourceLocation( - [&](SourceLocation* location) - { - if (location->getTokenIds().size()) - { - params.title = m_storageAccess->getNameHierarchyForNodeId(location->getTokenIds()[0]).getQualifiedName(); - params.titleId = location->getLocationId(); - } - } - ); + const SourceLocation* location = + getSourceLocationOfParentScope(params.startLineNumber, scopeLocations.get()); + if (location && location->getTokenIds().size()) + { + params.title = m_storageAccess->getNameHierarchyForNodeId(location->getTokenIds()[0]).getQualifiedName(); + params.titleId = location->getLocationId(); + } } - if (params.titleId == 0) + if (params.endLineNumber < lineCount) + { + const SourceLocation* location = + getSourceLocationOfParentScope(params.endLineNumber + 1, scopeLocations.get()); + if (location && location->getTokenIds().size()) + { + params.footer = m_storageAccess->getNameHierarchyForNodeId(location->getTokenIds()[0]).getQualifiedName(); + params.footerId = location->getLocationId(); + } + } + + if (params.titleId == 0 && params.startLineNumber > 1) { params.title = activeSourceLocations->getFilePath().wstr(); } - - const SourceLocation* lastSourceLocation = - tempFile->getSourceLocations().size() ? tempFile->getSourceLocations().rbegin()->get() : nullptr; - if (lastSourceLocation) + else if (params.footerId == 0 && params.endLineNumber < lineCount) { - // this SourceLocationFile only contains a single StartSourceLocation. - getSourceLocationOfParentScope(lastSourceLocation, scopeLocations)->forEachStartSourceLocation( - [&](SourceLocation* location) - { - if (location->getTokenIds().size()) - { - params.footer = m_storageAccess->getNameHierarchyForNodeId(location->getTokenIds()[0]).getQualifiedName(); - params.footerId = location->getLocationId(); - } - } - ); + params.footer = activeSourceLocations->getFilePath().wstr(); } for (const std::string& line: textAccess->getLines(params.startLineNumber, params.endLineNumber)) @@ -681,18 +594,6 @@ std::vector CodeController::getSnippetsForFile( params.code += line; } - if (addSourceLocations) - { - params.locationFile->forEachSourceLocation( - [&tempFile](SourceLocation* location) - { - tempFile->addSourceLocationCopy(location); - } - ); - - params.locationFile = tempFile; - } - snippets.push_back(params); } @@ -700,8 +601,8 @@ std::vector CodeController::getSnippetsForFile( } std::shared_ptr CodeController::buildMergerHierarchy( - SourceLocation* location, - std::shared_ptr scopeLocations, + const SourceLocation* location, + const SourceLocationFile* scopeLocations, SnippetMerger& fileScopedMerger, std::map>& mergers ) const @@ -711,67 +612,46 @@ std::shared_ptr CodeController::buildMergerHierarchy( location->getEndLocation()->getLineNumber() ); - std::shared_ptr locationFile = getSourceLocationOfParentScope(location, scopeLocations); - if (locationFile->getSourceLocationCount() == 0) + const SourceLocation* scopeLocation = getSourceLocationOfParentScope(location->getLineNumber(), scopeLocations); + if (!scopeLocation) { fileScopedMerger.addChild(currentMerger); return currentMerger; } std::shared_ptr nextMerger; - locationFile->forEachStartSourceLocation( // contains just 1 start location - [&](SourceLocation* scopeLocation) - { - std::map>::iterator it = mergers.find(scopeLocation->getLocationId()); - if (it == mergers.end()) - { - nextMerger = buildMergerHierarchy(scopeLocation, scopeLocations, fileScopedMerger, mergers); - mergers[scopeLocation->getLocationId()] = nextMerger; - } - else - { - nextMerger = it->second; - } - } - ); + std::map>::iterator it = mergers.find(scopeLocation->getLocationId()); + if (it == mergers.end()) + { + nextMerger = buildMergerHierarchy(scopeLocation, scopeLocations, fileScopedMerger, mergers); + mergers[scopeLocation->getLocationId()] = nextMerger; + } + else + { + nextMerger = it->second; + } nextMerger->addChild(currentMerger); return currentMerger; } -std::shared_ptr CodeController::getSourceLocationOfParentScope( - const SourceLocation* location, - std::shared_ptr scopeLocations -) const +const SourceLocation* CodeController::getSourceLocationOfParentScope( + size_t lineNumber, const SourceLocationFile* scopeLocations) const { - const SourceLocation* parent = nullptr; + const SourceLocation* location = nullptr; scopeLocations->forEachStartSourceLocation( - [&](SourceLocation* scopeLocation) -> void + [&location, lineNumber](SourceLocation* scopeLocation) { - if (location->getStartLocation() && *scopeLocation == *location->getStartLocation() && - location->getEndLocation() && *scopeLocation->getEndLocation() == *location->getEndLocation()) + if (scopeLocation->getLineNumber() < lineNumber && + scopeLocation->getEndLocation()->getLineNumber() >= lineNumber && + (!location || *location < *scopeLocation)) { - return; - } - - if (!(*scopeLocation > *location) && - !(*scopeLocation->getEndLocation() < *location) && - // since scopeLocation is a start location the > location indicates the scope - // that is closer to the child. - (!parent || *scopeLocation > *parent)) - { - parent = scopeLocation; + location = scopeLocation; } } ); - std::shared_ptr file = std::make_shared(location->getFilePath(), false, false); - if (parent) - { - file->addSourceLocationCopy(parent); - file->addSourceLocationCopy(parent->getOtherLocation()); - } - return file; + return location; } std::vector CodeController::getProjectDescription(SourceLocationFile* locationFile) const @@ -839,12 +719,91 @@ std::vector CodeController::getProjectDescription(SourceLocationFil return lines; } -void CodeController::addModificationTimes(std::vector& snippets) const +void CodeController::expandVisibleSnippets(std::vector* snippets) const +{ + TRACE(); + + if (!snippets->size()) + { + return; + } + + bool inListMode = getView()->isInListMode(); + + size_t filesToExpand = inListMode ? std::min(int(snippets->size()), 3) : 1; + CodeView::FileState state = inListMode ? CodeView::FILE_SNIPPETS : CodeView::FILE_MAXIMIZED; + + for (size_t i = 0; i < filesToExpand; i++) + { + CodeSnippetParams& oldSnippet = snippets->at(i); + if (!oldSnippet.isCollapsed || oldSnippet.reduced) + { + continue; + } + + if (!inListMode && getView()->hasSingleFileCached(oldSnippet.locationFile->getFilePath())) + { + continue; + } + + CodeView::FileState fileState = oldSnippet.locationFile->isWhole() ? CodeView::FILE_MAXIMIZED : state; + + std::vector newSnippets = + getSnippetsForFileWithState(oldSnippet.locationFile->getFilePath(), fileState); + if (!newSnippets.size()) + { + continue; + } + + for (CodeSnippetParams& newSnippet : newSnippets) + { + newSnippet.isDeclaration = oldSnippet.isDeclaration; + newSnippet.isDefinition = oldSnippet.isDefinition; + + newSnippet.isCollapsed = false; + } + + snippets->insert(snippets->end(), newSnippets.begin(), newSnippets.end()); + } +} + +void CodeController::addAllSourceLocations(std::vector* snippets) const +{ + TRACE(); + + for (CodeSnippetParams& snippet : *snippets) + { + if (!snippet.locationFile || snippet.isCollapsed || snippet.reduced) + { + continue; + } + + std::shared_ptr file; + + if (snippet.locationFile->isWhole()) + { + file = m_storageAccess->getSourceLocationsForFile(snippet.locationFile->getFilePath()); + } + else + { + file = m_storageAccess->getSourceLocationsForLinesInFile( + snippet.locationFile->getFilePath(), snippet.startLineNumber, snippet.endLineNumber); + } + + if (file) + { + file->copySourceLocations(snippet.locationFile); + snippet.locationFile = file; + } + } +} + +void CodeController::addModificationTimes(std::vector* snippets) const { TRACE(); std::vector filePaths; - for (const CodeSnippetParams& snippet : snippets) + for (const CodeSnippetParams& snippet : *snippets) { filePaths.push_back(snippet.locationFile->getFilePath()); } @@ -856,26 +815,12 @@ void CodeController::addModificationTimes(std::vector& snippe fileInfoMap.emplace(fileInfo.path, fileInfo); } - for (CodeSnippetParams& snippet : snippets) + for (CodeSnippetParams& snippet : *snippets) { snippet.modificationTime = fileInfoMap[snippet.locationFile->getFilePath()].lastWriteTime; } } -void CodeController::addActiveSourceLocations(std::shared_ptr locationFile) const -{ - SourceLocationFile* activeLocations = m_collection->getSourceLocationFileByPath(locationFile->getFilePath()).get(); - if (activeLocations) - { - activeLocations->forEachSourceLocation( - [&locationFile](SourceLocation* location) - { - locationFile->addSourceLocationCopy(location); - } - ); - } -} - void CodeController::saveOrRestoreViewMode(MessageBase* message) { if (message->isReplayed()) @@ -891,3 +836,18 @@ void CodeController::saveOrRestoreViewMode(MessageBase* message) m_messageIdToViewModeMap.emplace(message->getId(), getView()->isInListMode()); } } + +void CodeController::showCodeSnippets( + std::vector snippets, const CodeView::CodeParams params, bool addSourceLocations) +{ + expandVisibleSnippets(&snippets); + + CodeView* view = getView(); + view->showCodeSnippets(snippets, params); + + if (addSourceLocations) + { + addAllSourceLocations(&snippets); + view->updateCodeSnippets(snippets); + } +} diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index 6a05b3cd..b97ad6d8 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -77,31 +77,29 @@ private: virtual void clear(); - void expandVisibleSnippets(std::vector* snippets, bool addSourceLocations) const; - - std::vector getSnippetsForFileWithState( - const FilePath& filePath, CodeView::FileState state, bool addSourceLocations) const; - + std::vector getSnippetsForFileWithState(const FilePath& filePath, CodeView::FileState state) const; std::vector getSnippetsForActiveSourceLocations( const SourceLocationCollection* collection, Id declarationId) const; - std::vector getSnippetsForCollection( - std::shared_ptr collection, bool addSourceLocations = false) const; - std::vector getSnippetsForFile( - std::shared_ptr file, bool addSourceLocations = false) const; + std::vector getSnippetsForCollection(std::shared_ptr collection) const; + std::vector getSnippetsForFile(std::shared_ptr file) const; std::shared_ptr buildMergerHierarchy( - SourceLocation* location, std::shared_ptr context, SnippetMerger& fileScopedMerger, + const SourceLocation* location, const SourceLocationFile* scopeLocations, SnippetMerger& fileScopedMerger, std::map>& mergers) const; - std::shared_ptr getSourceLocationOfParentScope( - const SourceLocation* location, std::shared_ptr context) const; + const SourceLocation* getSourceLocationOfParentScope( + size_t lineNumber, const SourceLocationFile* scopeLocations) const; std::vector getProjectDescription(SourceLocationFile* locationFile) const; - void addModificationTimes(std::vector& snippets) const; - void addActiveSourceLocations(std::shared_ptr locationFile) const; + void expandVisibleSnippets(std::vector* snippets) const; + void addAllSourceLocations(std::vector* snippets) const; + void addModificationTimes(std::vector* snippets) const; void saveOrRestoreViewMode(MessageBase* message); + void showCodeSnippets( + std::vector snippets, const CodeView::CodeParams params, bool addSourceLocations = true); + StorageAccess* m_storageAccess; mutable std::shared_ptr m_collection; diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index efd4f932..a7f82132 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -77,6 +77,7 @@ public: virtual void clear() = 0; virtual void showCodeSnippets(const std::vector& snippets, const CodeParams params) = 0; + virtual void updateCodeSnippets(const std::vector& snippets) = 0; virtual void scrollTo(const ScrollParams params) = 0; virtual bool showsErrors() const = 0; diff --git a/src/lib/data/location/SourceLocationFile.cpp b/src/lib/data/location/SourceLocationFile.cpp index 9e9b5e39..3c67f848 100644 --- a/src/lib/data/location/SourceLocationFile.cpp +++ b/src/lib/data/location/SourceLocationFile.cpp @@ -115,6 +115,16 @@ SourceLocation* SourceLocationFile::addSourceLocationCopy(const SourceLocation* return copy.get(); } +void SourceLocationFile::copySourceLocations(std::shared_ptr file) +{ + file->forEachSourceLocation( + [this](SourceLocation* location) + { + addSourceLocationCopy(location); + } + ); +} + SourceLocation* SourceLocationFile::getSourceLocationById(Id locationId) const { std::map::const_iterator it = m_locationIndex.find(locationId); diff --git a/src/lib/data/location/SourceLocationFile.h b/src/lib/data/location/SourceLocationFile.h index 38adc32a..4d55a457 100644 --- a/src/lib/data/location/SourceLocationFile.h +++ b/src/lib/data/location/SourceLocationFile.h @@ -45,6 +45,8 @@ public: size_t endLineNumber, size_t endColumnNumber); SourceLocation* addSourceLocationCopy(const SourceLocation* location); + void copySourceLocations(std::shared_ptr file); + SourceLocation* getSourceLocationById(Id locationId) const; void forEachSourceLocation(std::function func) const; diff --git a/src/lib_gui/qt/element/QtCodeArea.cpp b/src/lib_gui/qt/element/QtCodeArea.cpp index bf3eba3e..de942823 100644 --- a/src/lib_gui/qt/element/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/QtCodeArea.cpp @@ -294,6 +294,21 @@ void QtCodeArea::updateLineNumberAreaWidthForDigits(int digits) updateLineNumberAreaWidth(); } +void QtCodeArea::updateSourceLocations(std::shared_ptr 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); } } } diff --git a/src/lib_gui/qt/element/QtCodeArea.h b/src/lib_gui/qt/element/QtCodeArea.h index 2fd66529..b39766f7 100644 --- a/src/lib_gui/qt/element/QtCodeArea.h +++ b/src/lib_gui/qt/element/QtCodeArea.h @@ -69,6 +69,7 @@ public: int lineNumberAreaWidth() const; void updateLineNumberAreaWidthForDigits(int digits); + void updateSourceLocations(std::shared_ptr locationFile); void updateContent(); void setIsActiveFile(bool isActiveFile); diff --git a/src/lib_gui/qt/element/QtCodeField.cpp b/src/lib_gui/qt/element/QtCodeField.cpp index 788a02f5..963591cb 100644 --- a/src/lib_gui/qt/element/QtCodeField.cpp +++ b/src/lib_gui/qt/element/QtCodeField.cpp @@ -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::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(document(), language); m_highlighter->highlightDocument(); ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); @@ -328,6 +330,11 @@ bool QtCodeField::annotateText( void QtCodeField::createAnnotations(std::shared_ptr locationFile) { + TRACE(); + + m_locationFile = locationFile; + m_annotations.clear(); + uint endLineNumber = getEndLineNumber(); std::set locationIds; diff --git a/src/lib_gui/qt/element/QtCodeField.h b/src/lib_gui/qt/element/QtCodeField.h index 72993b4f..4e72027d 100644 --- a/src/lib_gui/qt/element/QtCodeField.h +++ b/src/lib_gui/qt/element/QtCodeField.h @@ -25,8 +25,8 @@ public: uint startLineNumber, const std::string& code, std::shared_ptr locationFile, - bool convertLocationsOnDemand = true, - QWidget* parent = nullptr); + bool convertLocationsOnDemand = true, + QWidget* parent = nullptr); ~QtCodeField(); @@ -115,7 +115,7 @@ private: std::shared_ptr m_locationFile; - QtHighlighter* m_highlighter; + std::shared_ptr m_highlighter; std::vector m_lineLengths; std::vector>> m_multibyteCharacterLocations; diff --git a/src/lib_gui/qt/element/QtCodeFile.cpp b/src/lib_gui/qt/element/QtCodeFile.cpp index 10a2d303..c55ad649 100644 --- a/src/lib_gui/qt/element/QtCodeFile.cpp +++ b/src/lib_gui/qt/element/QtCodeFile.cpp @@ -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 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 QtCodeFile::getVisibleSnippets() const +{ std::vector snippets; for (QtCodeSnippet* snippet : m_snippets) @@ -182,11 +195,6 @@ std::vector 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 QtCodeFile::getFirstSnippetWithActiveLocationId(Id tokenId) const { std::pair result(nullptr, 0); @@ -241,7 +239,7 @@ std::pair 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>* screenMatches) { - if (m_fileSnippet && m_fileSnippet->isVisible()) - { - m_fileSnippet->findScreenMatches(query, screenMatches); - return; - } - for (QtCodeSnippet* snippet : m_snippets) { if (snippet->isVisible()) diff --git a/src/lib_gui/qt/element/QtCodeFile.h b/src/lib_gui/qt/element/QtCodeFile.h index 66b39584..2d497ea5 100644 --- a/src/lib_gui/qt/element/QtCodeFile.h +++ b/src/lib_gui/qt/element/QtCodeFile.h @@ -35,11 +35,11 @@ public: QtCodeSnippet* addCodeSnippet(const CodeSnippetParams& params); QtCodeSnippet* insertCodeSnippet(const CodeSnippetParams& params); + void updateCodeSnippet(const CodeSnippetParams& params); std::vector getVisibleSnippets() const; QtCodeSnippet* getSnippetForLocationId(Id locationId) const; QtCodeSnippet* getSnippetForLine(unsigned int line) const; - QtCodeSnippet* getFileSnippet() const; std::pair getFirstSnippetWithActiveLocationId(Id tokenId) const; @@ -76,7 +76,6 @@ private: QVBoxLayout* m_snippetLayout; std::vector m_snippets; - QtCodeSnippet* m_fileSnippet; const FilePath m_filePath; bool m_isWholeFile; diff --git a/src/lib_gui/qt/element/QtCodeFileList.cpp b/src/lib_gui/qt/element/QtCodeFileList.cpp index 4af39e12..47757864 100644 --- a/src/lib_gui/qt/element/QtCodeFileList.cpp +++ b/src/lib_gui/qt/element/QtCodeFileList.cpp @@ -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) diff --git a/src/lib_gui/qt/element/QtCodeFileList.h b/src/lib_gui/qt/element/QtCodeFileList.h index 7db3620c..87dcba99 100644 --- a/src/lib_gui/qt/element/QtCodeFileList.h +++ b/src/lib_gui/qt/element/QtCodeFileList.h @@ -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); diff --git a/src/lib_gui/qt/element/QtCodeFileSingle.cpp b/src/lib_gui/qt/element/QtCodeFileSingle.cpp index e1b51b3f..2ef8e18f 100644 --- a/src/lib_gui/qt/element/QtCodeFileSingle.cpp +++ b/src/lib_gui/qt/element/QtCodeFileSingle.cpp @@ -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) diff --git a/src/lib_gui/qt/element/QtCodeFileSingle.h b/src/lib_gui/qt/element/QtCodeFileSingle.h index 1efb8823..570093ce 100644 --- a/src/lib_gui/qt/element/QtCodeFileSingle.h +++ b/src/lib_gui/qt/element/QtCodeFileSingle.h @@ -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( diff --git a/src/lib_gui/qt/element/QtCodeNavigateable.h b/src/lib_gui/qt/element/QtCodeNavigateable.h index bc6fd496..9a55d1c1 100644 --- a/src/lib_gui/qt/element/QtCodeNavigateable.h +++ b/src/lib_gui/qt/element/QtCodeNavigateable.h @@ -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; diff --git a/src/lib_gui/qt/element/QtCodeNavigator.cpp b/src/lib_gui/qt/element/QtCodeNavigator.cpp index 80afd37d..e27dba00 100644 --- a/src/lib_gui/qt/element/QtCodeNavigator.cpp +++ b/src/lib_gui/qt/element/QtCodeNavigator.cpp @@ -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 locationFile, int refCount, TimeStamp modificationTime) { bool firstFile = m_references.size() == 0; diff --git a/src/lib_gui/qt/element/QtCodeNavigator.h b/src/lib_gui/qt/element/QtCodeNavigator.h index d3b6022a..e8be49c9 100644 --- a/src/lib_gui/qt/element/QtCodeNavigator.h +++ b/src/lib_gui/qt/element/QtCodeNavigator.h @@ -43,6 +43,7 @@ public: virtual ~QtCodeNavigator(); void addCodeSnippet(const CodeSnippetParams& params); + void updateCodeSnippet(const CodeSnippetParams& params); void addFile(std::shared_ptr locationFile, int refCount, TimeStamp modificationTime); void addedFiles(); diff --git a/src/lib_gui/qt/element/QtCodeSnippet.cpp b/src/lib_gui/qt/element/QtCodeSnippet.cpp index e9a7c5bf..f0adf591 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.cpp +++ b/src/lib_gui/qt/element/QtCodeSnippet.cpp @@ -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); diff --git a/src/lib_gui/qt/element/QtCodeSnippet.h b/src/lib_gui/qt/element/QtCodeSnippet.h index 86ff4be9..a7c5bc46 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.h +++ b/src/lib_gui/qt/element/QtCodeSnippet.h @@ -37,6 +37,8 @@ public: int lineNumberDigits() const; + void updateCodeSnippet(const CodeSnippetParams& params); + void updateLineNumberAreaWidthForDigits(int digits); void updateContent(); diff --git a/src/lib_gui/qt/utility/QtHighlighter.cpp b/src/lib_gui/qt/utility/QtHighlighter.cpp index 9a06bfd6..b8b66ba0 100644 --- a/src/lib_gui/qt/utility/QtHighlighter.cpp +++ b/src/lib_gui/qt/utility/QtHighlighter.cpp @@ -5,6 +5,7 @@ #include #include "settings/ColorScheme.h" +#include "utility/tracing.h" #include "utility/utility.h" QVector 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> ranges; - ranges.push_back(std::pair(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> QtHighlighter::createMultiLineCommentRanges( + QTextDocument* doc, std::vector>* ranges) +{ QRegExp commentStartExpression = QRegExp("(^([^/]|/[^/])*)/\\*"); QRegExp commentEndExpression = QRegExp("\\*/"); QTextCursor cursorStart(doc); QTextCursor cursorEnd(doc); + std::vector> 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(cursorStart.selectionStart(), cursorEnd.position())); + multiLineCommentRanges.push_back(std::pair(cursorStart.position(), cursorEnd.position())); cursorStart = cursorEnd; } + + return multiLineCommentRanges; } QtHighlighter::HighlightingRule::HighlightingRule() @@ -313,15 +328,34 @@ bool QtHighlighter::isInRange(int pos, const std::vector>& r return false; } -std::vector> QtHighlighter::formatBlockForRule( +std::vector> 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> ranges; + + while (index >= 0) + { + int length = expression.matchedLength(); + + ranges.push_back(std::pair(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>* ranges ){ QRegExp expression(rule.pattern); int pos = block.position(); int index = expression.indexIn(block.text()); - std::vector> newRanges; - while (index >= 0) { int length = expression.matchedLength(); @@ -331,12 +365,8 @@ std::vector> QtHighlighter::formatBlockForRule( applyFormat(pos + index, pos + index + length, rule.format); } - newRanges.push_back(std::pair(pos + index, pos + index + length)); - index = expression.indexIn(block.text(), index + length); } - - return newRanges; } void QtHighlighter::formatBlockIfInRange( diff --git a/src/lib_gui/qt/utility/QtHighlighter.h b/src/lib_gui/qt/utility/QtHighlighter.h index 1eb23fb2..f7e62fb6 100644 --- a/src/lib_gui/qt/utility/QtHighlighter.h +++ b/src/lib_gui/qt/utility/QtHighlighter.h @@ -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> createMultiLineCommentRanges( + QTextDocument* doc, std::vector>* ranges); bool isInRange(int index, const std::vector>& ranges) const; - std::vector> formatBlockForRule( + std::vector> getRangesForRule(const QTextBlock& block, const HighlightingRule& rule) const; + + void formatBlockForRule( const QTextBlock& block, const HighlightingRule& rule, std::vector>* ranges = nullptr); void formatBlockIfInRange( const QTextBlock& block, const QTextCharFormat& format, std::vector>* ranges); diff --git a/src/lib_gui/qt/view/QtCodeView.cpp b/src/lib_gui/qt/view/QtCodeView.cpp index 406e845d..6723306d 100644 --- a/src/lib_gui/qt/view/QtCodeView.cpp +++ b/src/lib_gui/qt/view/QtCodeView.cpp @@ -154,6 +154,19 @@ void QtCodeView::showCodeSnippets(const std::vector& snippets }); } +void QtCodeView::updateCodeSnippets(const std::vector& 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; diff --git a/src/lib_gui/qt/view/QtCodeView.h b/src/lib_gui/qt/view/QtCodeView.h index 13e6c014..e6117632 100644 --- a/src/lib_gui/qt/view/QtCodeView.h +++ b/src/lib_gui/qt/view/QtCodeView.h @@ -29,6 +29,7 @@ public: virtual void clear(); virtual void showCodeSnippets(const std::vector& snippets, const CodeParams params); + virtual void updateCodeSnippets(const std::vector& snippets); virtual void scrollTo(const ScrollParams params); virtual bool showsErrors() const;