diff --git a/bin/app/user/projects/tictactoe_cpp/src/tictactoe.cpp b/bin/app/user/projects/tictactoe_cpp/src/tictactoe.cpp index b4ba8ef1..d21a1025 100644 --- a/bin/app/user/projects/tictactoe_cpp/src/tictactoe.cpp +++ b/bin/app/user/projects/tictactoe_cpp/src/tictactoe.cpp @@ -13,7 +13,6 @@ TicTacToe::~TicTacToe() { Reset(); } - bool TicTacToe::Start() { Reset(); io::stringOut("Tic Tac Toe\n\n[1] Human\n[2] Computer\n[3] Quit\n\n"); diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index afdc962f..b04419a4 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -65,6 +65,7 @@ add_files( component/controller/UndoRedoController.cpp component/controller/UndoRedoController.h + component/view/helper/CodeScrollParams.h component/view/helper/CodeSnippetParams.cpp component/view/helper/CodeSnippetParams.h component/view/BookmarkButtonsView.cpp diff --git a/src/lib/component/controller/ActivationController.cpp b/src/lib/component/controller/ActivationController.cpp index 2b26791d..a7756d68 100644 --- a/src/lib/component/controller/ActivationController.cpp +++ b/src/lib/component/controller/ActivationController.cpp @@ -60,8 +60,7 @@ void ActivationController::handleMessage(MessageActivateFile* message) message->filePath, MessageChangeFileView::FILE_MAXIMIZED, MessageChangeFileView::VIEW_CURRENT, - true, - true + CodeScrollParams::toFile(message->filePath, CodeScrollParams::Target::VISIBLE) ); msg.setSchedulerId(message->getSchedulerId()); msg.dispatchImmediately(); diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 9a7b5ac0..5d9c3a3b 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -7,6 +7,7 @@ #include "FileInfo.h" #include "logging.h" #include "MessageMoveIDECursor.h" +#include "MessageShowError.h" #include "MessageStatus.h" #include "StorageAccess.h" #include "SourceLocation.h" @@ -35,9 +36,6 @@ void CodeController::handleMessage(MessageActivateErrors* message) CodeView* view = getView(); - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); - view->scrollTo(scrollParams); - std::vector errors; if (message->file.empty()) { @@ -49,17 +47,18 @@ void CodeController::handleMessage(MessageActivateErrors* message) } m_collection = m_storageAccess->getErrorSourceLocations(errors); - std::vector snippets = getSnippetsForCollection(m_collection); - std::sort(snippets.begin(), snippets.end(), CodeSnippetParams::sortById); + m_files = getFilesForCollection(m_collection); + std::sort(m_files.begin(), m_files.end(), CodeFileParams::sortById); CodeView::CodeParams params; params.clearSnippets = true; - params.errorInfos = errors; - params.showContents = !message->isReplayed(); params.useSingleFileCache = false; + params.errorInfos = errors; - showCodeSnippets(snippets, params, false); + createReferences(); + expandVisibleFiles(params.useSingleFileCache); + showFiles(params, firstReferenceScrollParams(), !message->isReplayed()); } void CodeController::handleMessage(MessageActivateFullTextSearch* message) @@ -70,15 +69,14 @@ void CodeController::handleMessage(MessageActivateFullTextSearch* message) m_collection = m_storageAccess->getFullTextSearchLocations(message->searchTerm, message->caseSensitive); - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); - getView()->scrollTo(scrollParams); - CodeView::CodeParams params; params.clearSnippets = true; - params.showContents = !message->isReplayed(); params.useSingleFileCache = false; - showCodeSnippets(getSnippetsForCollection(m_collection), params); + m_files = getFilesForCollection(m_collection); + createReferences(); + expandVisibleFiles(params.useSingleFileCache); + showFiles(params, firstReferenceScrollParams(), !message->isReplayed()); } void CodeController::handleMessage(MessageActivateLegend* message) @@ -88,8 +86,11 @@ void CodeController::handleMessage(MessageActivateLegend* message) void CodeController::handleMessage(MessageActivateLocalSymbols* message) { - CodeView* view = getView(); - view->showActiveLocalSymbolIds(message->symbolIds); + createLocalReferences(utility::toSet(message->symbolIds)); + m_codeParams.activeLocalSymbolIds = message->symbolIds; + m_codeParams.activeLocalSymbolType = LOCATION_LOCAL_SYMBOL; + m_codeParams.currentActiveLocalLocationIds.clear(); + showFiles(m_codeParams, CodeScrollParams(), !message->isReplayed()); } void CodeController::handleMessage(MessageActivateOverview* message) @@ -97,6 +98,7 @@ void CodeController::handleMessage(MessageActivateOverview* message) TRACE("code all"); saveOrRestoreViewMode(message); + clearReferences(); std::shared_ptr currentProject = Application::getInstance()->getCurrentProject(); if (!currentProject || message->acceptedNodeTypes != NodeTypeSet::all()) @@ -106,13 +108,13 @@ void CodeController::handleMessage(MessageActivateOverview* message) } CodeSnippetParams statsSnippet; + statsSnippet.hasAllSourceLocations = true; statsSnippet.title = currentProject->getProjectSettingsFilePath().withoutExtension().fileName(); + statsSnippet.isOverview = true; statsSnippet.startLineNumber = 1; statsSnippet.endLineNumber = 1; - statsSnippet.reduced = true; - statsSnippet.locationFile = std::make_shared(FilePath(), L"", true, true, true); std::vector description = getProjectDescription(statsSnippet.locationFile.get()); @@ -158,10 +160,20 @@ void CodeController::handleMessage(MessageActivateOverview* message) statsSnippet.code = ss.str(); + CodeFileParams file; + file.isMinimized = false; + file.locationFile = statsSnippet.locationFile; + file.snippetParams.push_back(statsSnippet); + file.fileParams = std::make_shared(statsSnippet); + + m_currentFilePath = file.locationFile->getFilePath(); + m_files = { file }; + CodeView::CodeParams params; params.clearSnippets = true; - params.showContents = !message->isReplayed(); - showCodeSnippets({ statsSnippet }, params); + params.useSingleFileCache = false; + + showFiles(params, CodeScrollParams(), !message->isReplayed()); } void CodeController::handleMessage(MessageActivateTokens* message) @@ -171,17 +183,15 @@ void CodeController::handleMessage(MessageActivateTokens* message) saveOrRestoreViewMode(message); CodeView* view = getView(); - - CodeView::CodeParams params; - params.activeTokenIds = message->tokenIds; - if (!params.activeTokenIds.size()) + if (!message->tokenIds.size()) { view->clear(); return; } - params.clearSnippets = !message->keepContent(); - params.showContents = !message->isReplayed(); + CodeView::CodeParams params; + params.activeTokenIds = message->tokenIds; + params.clearSnippets = true; Id declarationId = 0; // 0 means that no token is found. if (!message->isAggregation) @@ -194,50 +204,56 @@ void CodeController::handleMessage(MessageActivateTokens* message) params.activeTokenIds = activeTokenIds; } - if (message->isEdge) + if (message->isEdge && params.activeTokenIds.size() == 1) { - std::shared_ptr collection = - m_storageAccess->getSourceLocationsForTokenIds(params.activeTokenIds); - view->showActiveSnippet(params.activeTokenIds, collection, message->isLast()); + showFirstActiveReference(params.activeTokenIds[0], !message->isReplayed()); return; } - if (message->keepContent()) + if (message->keepContent()) // deactivating an edge { - view->showActiveTokenIds(params.activeTokenIds); + m_codeParams.activeTokenIds = params.activeTokenIds; + m_codeParams.activeLocationIds.clear(); + m_codeParams.activeLocalSymbolIds.clear(); + m_codeParams.currentActiveLocalLocationIds.clear(); + clearLocalReferences(); + + showFiles(m_codeParams, CodeScrollParams(), !message->isReplayed()); return; } - 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); + m_files = getFilesForActiveSourceLocations(m_collection.get(), declarationId); + createReferences(); + expandVisibleFiles(params.useSingleFileCache); + showFiles(params, definitionReferenceScrollParams(params.activeTokenIds), !message->isReplayed()); - size_t fileCount = m_collection->getSourceLocationFileCount(); - size_t referenceCount = m_collection->getSourceLocationCount(); - - std::wstring status; - for (const SearchMatch& match : message->getSearchMatches()) + // send status message { - status += L"Activate \"" + match.name + L"\": "; - break; + size_t fileCount = m_collection->getSourceLocationFileCount(); + size_t referenceCount = m_collection->getSourceLocationCount(); + + std::wstring status; + for (const SearchMatch& match : message->getSearchMatches()) + { + status += L"Activate \"" + match.name + L"\": "; + break; + } + + 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 += 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(MessageActivateTrail* message) @@ -257,55 +273,53 @@ void CodeController::handleMessage(MessageActivateTrailEdge* message) saveOrRestoreViewMode(message); - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); - getView()->scrollTo(scrollParams); + m_codeParams.activeTokenIds = message->edgeIds; - CodeView::CodeParams params; - params.clearSnippets = true; - params.showContents = !message->isReplayed(); - params.activeTokenIds = message->edgeIds; + m_collection = m_storageAccess->getSourceLocationsForTokenIds(m_codeParams.activeTokenIds); - m_collection = m_storageAccess->getSourceLocationsForTokenIds(params.activeTokenIds); - showCodeSnippets(getSnippetsForActiveSourceLocations(m_collection.get(), 0), params); + m_files = getFilesForActiveSourceLocations(m_collection.get(), 0); + createReferences(); + expandVisibleFiles(m_codeParams.useSingleFileCache); + showFiles(m_codeParams, firstReferenceScrollParams(), !message->isReplayed()); } void CodeController::handleMessage(MessageChangeFileView* message) { TRACE("code change file"); - CodeView::FileState state; - switch (message->state) + saveOrRestoreViewMode(message); + + for (CodeFileParams& file : m_files) { - case MessageChangeFileView::FILE_MINIMIZED: - state = CodeView::FILE_MINIMIZED; - break; + if (file.locationFile->getFilePath() == message->filePath) + { + setFileState(file, message->state, m_codeParams.useSingleFileCache); - case MessageChangeFileView::FILE_SNIPPETS: - state = CodeView::FILE_SNIPPETS; - break; + // maximize within snippet list + if (message->viewMode == MessageChangeFileView::VIEW_LIST && message->state == MessageChangeFileView::FILE_MAXIMIZED) + { + file.snippetParams = { *file.fileParams.get() }; + } - case MessageChangeFileView::FILE_MAXIMIZED: - state = CodeView::FILE_MAXIMIZED; - break; + break; + } } - CodeView* view = getView(); - if (message->viewMode != MessageChangeFileView::VIEW_CURRENT) + showFiles(m_codeParams, message->scrollParams, !message->isReplayed()); +} + +void CodeController::handleMessage(MessageCodeReference* message) +{ + bool next = (message->type == MessageCodeReference::REFERENCE_NEXT); + bool local = message->localReference; + + if (local) { - view->setMode(message->viewMode == MessageChangeFileView::VIEW_LIST); + iterateLocalReference(next, true); } - - if (message->needsData && !message->filePath.empty()) + else { - view->scrollTo(CodeView::ScrollParams()); - showCodeSnippets(getSnippetsForFileWithState(message->filePath, state), CodeView::CodeParams(), !message->showErrors); - } - - view->setFileState(message->filePath, state); - - if (!message->isReplayed()) - { - view->showContents(); + iterateReference(next); } } @@ -378,44 +392,32 @@ void CodeController::handleMessage(MessageCodeShowDefinition* message) return; } - std::vector snippets = getSnippetsForFile(collection->getSourceLocationFiles().begin()->second); - if (snippets.size() != 1) + CodeFileParams* file = addSourceLocations(collection->getSourceLocationFiles().begin()->second); + if (!file) { - LOG_ERROR("MessageCodeShowDefinition snippet count is not 1"); + LOG_ERROR("MessageCodeShowDefinition did not create a file"); return; } - snippets[0].insertSnippet = true; - - if (!m_collection) - { - m_collection = std::make_shared(); - } - m_collection->addSourceLocationCopies(collection.get()); - saveOrRestoreViewMode(message); - CodeView* view = getView(); - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_LINE); - scrollParams.filePath = filePath; - scrollParams.line = lineNumber; - view->scrollTo(scrollParams); - - CodeView::CodeParams params; - params.showContents = !message->isReplayed(); - - addAllSourceLocations(&snippets); - getView()->showCodeSnippets(snippets, params); + showFiles(m_codeParams, CodeScrollParams::toLine(filePath, lineNumber, CodeScrollParams::Target::TOP), !message->isReplayed()); } void CodeController::handleMessage(MessageDeactivateEdge* message) { if (message->scrollToDefinition) { - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); - scrollParams.animated = true; - scrollParams.ignoreActiveReference = true; - getView()->scrollTo(scrollParams); + CodeScrollParams scrollParams = definitionReferenceScrollParams(m_codeParams.activeTokenIds); + + if (message->isReplayed()) + { + m_scrollParams = scrollParams; + } + else + { + getView()->scrollTo(scrollParams, true); + } } } @@ -429,7 +431,7 @@ void CodeController::handleMessage(MessageErrorCountClear* message) void CodeController::handleMessage(MessageFlushUpdates* message) { - getView()->showContents(); + showFiles(m_codeParams, m_scrollParams, true); } void CodeController::handleMessage(MessageFocusIn* message) @@ -444,12 +446,7 @@ void CodeController::handleMessage(MessageFocusOut* message) void CodeController::handleMessage(MessageScrollToLine* message) { - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_LINE); - scrollParams.filePath = message->filePath; - scrollParams.line = message->line; - getView()->scrollTo(scrollParams); - - getView()->showContents(); + getView()->scrollTo(CodeScrollParams::toLine(message->filePath, message->line, CodeScrollParams::Target::TOP), false); MessageStatus( L"Showing source location: " + message->filePath.wstr() + L" : " + std::to_wstring(message->line) @@ -460,10 +457,7 @@ void CodeController::handleMessage(MessageScrollCode* message) { if (message->isReplayed()) { - CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_VALUE); - scrollParams.value = message->value; - scrollParams.inListMode = message->inListMode; - getView()->scrollTo(scrollParams); + m_scrollParams = CodeScrollParams::toValue(message->value, message->inListMode); } } @@ -472,7 +466,32 @@ void CodeController::handleMessage(MessageShowError* message) CodeView* view = getView(); if (view->showsErrors()) { - view->showActiveSnippet({ message->errorId }, m_collection, message->isLast()); + showFirstActiveReference(message->errorId, !message->isReplayed()); + } +} + +void CodeController::handleMessage(MessageShowReference* message) +{ + m_referenceIndex = message->refIndex; + bool replayed = message->isReplayed(); + + if (m_referenceIndex >= 0 && m_referenceIndex < m_references.size()) + { + const Reference& ref = m_references[m_referenceIndex]; + m_codeParams.activeLocationIds = { ref.locationId }; + + setFileState( + ref.filePath, + getView()->isInListMode() ? MessageChangeFileView::FILE_SNIPPETS : MessageChangeFileView::FILE_MAXIMIZED, + m_codeParams.useSingleFileCache + ); + + showFiles(m_codeParams, toReferenceScrollParams(ref), !message->isReplayed()); + + if (ref.locationType == LOCATION_ERROR) + { + MessageShowError(ref.tokenId).dispatch(); + } } } @@ -490,20 +509,16 @@ void CodeController::handleMessage(MessageShowScope* message) return; } - std::vector snippets = getSnippetsForFile(collection->getSourceLocationFiles().begin()->second); - if (snippets.size() != 1) + addSourceLocations(collection->getSourceLocationFiles().begin()->second); + + if (m_localReferences.size()) { - LOG_ERROR("MessageShowScope didn't result in one single snippet to be created"); - return; + addAllSourceLocations(); + createLocalReferences(utility::toSet(m_codeParams.activeLocalSymbolIds)); + m_codeParams.currentActiveLocalLocationIds.clear(); } - snippets[0].insertSnippet = true; - - CodeView::CodeParams params; - params.showContents = !message->isReplayed(); - - addAllSourceLocations(&snippets); - getView()->showCodeSnippets(snippets, params); + showFiles(m_codeParams, CodeScrollParams(), !message->isReplayed()); } CodeView* CodeController::getView() const @@ -516,70 +531,16 @@ void CodeController::clear() getView()->clear(); m_collection = std::make_shared(); + m_currentFilePath = FilePath(); + clearReferences(); } -std::vector CodeController::getSnippetsForFileWithState( - const FilePath& filePath, CodeView::FileState state) const -{ - TRACE(); - - std::shared_ptr file = m_collection->getSourceLocationFileByPath(filePath); - if (!file) - { - return {}; - } - - std::vector snippets; - - switch (state) - { - case CodeView::FILE_SNIPPETS: - snippets = getSnippetsForFile(file); - break; - - case CodeView::FILE_MAXIMIZED: - { - CodeSnippetParams params; - params.startLineNumber = 1; - params.refCount = -1; - - bool showsErrors = false; - if (m_collection->getSourceLocationFiles().size()) - { - std::shared_ptr file = m_collection->getSourceLocationFiles().begin()->second; - if (file->getSourceLocations().size()) - { - showsErrors = (*file->getSourceLocations().begin())->getType() == LOCATION_ERROR; - } - } - - std::shared_ptr textAccess = m_storageAccess->getFileContent(filePath, showsErrors); - params.code = textAccess->getText(); - - params.modificationTime = m_storageAccess->getFileInfoForFilePath(filePath).lastWriteTime; - - // make a copy of SourceLocationFile so that isWhole flag is different for first snippet adding the file - // and second snippet adding the content - params.locationFile = std::make_shared(*file.get()); - params.locationFile->setIsWhole(true); - - snippets.push_back(params); - } - break; - - default: - break; - } - - return snippets; -} - -std::vector CodeController::getSnippetsForActiveSourceLocations( +std::vector CodeController::getFilesForActiveSourceLocations( const SourceLocationCollection* collection, Id declarationId ) const { TRACE(); - std::vector snippets; + std::vector files; collection->forEachSourceLocationFile( [&](std::shared_ptr file) -> void { @@ -605,52 +566,73 @@ std::vector CodeController::getSnippetsForActiveSourceLocatio } ); - CodeSnippetParams params; + CodeFileParams params; params.locationFile = file; - params.refCount = file->getUnscopedStartLocationCount(); - params.isDeclaration = isDeclarationFile; params.isDefinition = isDefinitionFile; - - params.isCollapsed = true; - snippets.push_back(params); + files.push_back(params); } ); - std::sort(snippets.begin(), snippets.end(), CodeSnippetParams::sort); + std::sort(files.begin(), files.end(), CodeFileParams::sort); - addModificationTimes(&snippets); - - return snippets; + return files; } -std::vector CodeController::getSnippetsForCollection( - std::shared_ptr collection -) const +std::vector CodeController::getFilesForCollection(std::shared_ptr collection) const { TRACE(); - std::vector snippets; + std::vector files; collection->forEachSourceLocationFile( [&](std::shared_ptr file) -> void { - CodeSnippetParams params; + CodeFileParams params; params.locationFile = file; - params.refCount = file->getUnscopedStartLocationCount(); - - params.isCollapsed = true; - snippets.push_back(params); + files.push_back(params); } ); - addModificationTimes(&snippets); + return files; +} - return snippets; + +CodeSnippetParams CodeController::getSnippetParamsForWholeFile( + std::shared_ptr locationFile, bool useSingleFileCache) const +{ + CodeSnippetParams snippet; + snippet.startLineNumber = 1; + + if (useSingleFileCache && !getView()->isInListMode() && getView()->hasSingleFileCached(locationFile->getFilePath())) + { + snippet.locationFile = locationFile; + return snippet; + } + + bool showsErrors = false; + if (m_collection->getSourceLocationFiles().size()) + { + std::shared_ptr file = m_collection->getSourceLocationFiles().begin()->second; + if (file->getSourceLocations().size()) + { + showsErrors = (*file->getSourceLocations().begin())->getType() == LOCATION_ERROR; + } + } + + std::shared_ptr textAccess = m_storageAccess->getFileContent(locationFile->getFilePath(), showsErrors); + snippet.code = textAccess->getText(); + + // make a copy of SourceLocationFile so that isWhole flag is different for first snippet adding the file + // and second snippet adding the content + snippet.locationFile = std::make_shared(*locationFile.get()); + snippet.locationFile->setIsWhole(true); + + return snippet; } std::vector CodeController::getSnippetsForFile( - std::shared_ptr activeSourceLocations + std::shared_ptr activeSourceLocations ) const { TRACE(); @@ -699,8 +681,6 @@ std::vector CodeController::getSnippetsForFile( for (const SnippetMerger::Range& range: ranges) { CodeSnippetParams params; - params.refCount = activeSourceLocations->getUnscopedStartLocationCount(); - params.startLineNumber = std::max(1, range.start.row - (range.start.strong ? 0 : snippetExpandRange)); params.endLineNumber = std::min(lineCount, range.end.row + (range.end.strong ? 0 : snippetExpandRange)); @@ -867,93 +847,429 @@ std::vector CodeController::getProjectDescription(SourceLocationFil return lines; } -void CodeController::expandVisibleSnippets(std::vector* snippets, bool useSingleFileCache) const +void CodeController::clearReferences() +{ + m_references.clear(); + m_referenceIndex = -1; + + clearLocalReferences(); +} + +void CodeController::createReferences() +{ + clearReferences(); + + for (CodeFileParams& file : m_files) + { + size_t referenceCountBefore = m_references.size(); + + if (file.locationFile->isWhole()) + { + Reference ref; + ref.filePath = file.locationFile->getFilePath(); + m_references.push_back(ref); + } + else + { + std::map scopeLocationIds; + + file.locationFile->forEachStartSourceLocation( + [&](SourceLocation* location) + { + if (location->isScopeLocation()) + { + for (Id tokenId : location->getTokenIds()) + { + scopeLocationIds.emplace(tokenId, location->getLocationId()); + } + } + } + ); + + file.locationFile->forEachStartSourceLocation( + [&](SourceLocation* location) + { + if (location->isScopeLocation() || location->getType() == LOCATION_SIGNATURE || + location->getType() == LOCATION_COMMENT || location->getType() == LOCATION_QUALIFIER) + { + return; + } + + if (!location->getTokenIds().size()) + { + Reference ref; + ref.filePath = location->getFilePath(); + ref.tokenId = 0; + ref.locationId = location->getLocationId(); + ref.locationType = location->getType(); + m_references.push_back(ref); + return; + } + + for (Id i : location->getTokenIds()) + { + Reference ref; + ref.filePath = location->getFilePath(); + ref.tokenId = i; + ref.locationId = location->getLocationId(); + ref.locationType = location->getType(); + + std::map::const_iterator it = scopeLocationIds.find(i); + if (it != scopeLocationIds.end()) + { + ref.scopeLocationId = it->second; + } + + m_references.push_back(ref); + } + } + ); + } + + file.referenceCount = m_references.size() - referenceCountBefore; + } +} + +void CodeController::clearLocalReferences() +{ + m_localReferences.clear(); + m_localReferenceIndex = -1; +} + +void CodeController::createLocalReferences(const std::set& localSymbolIds) +{ + clearLocalReferences(); + + if (localSymbolIds.size()) + { + auto func = [&localSymbolIds, this](const SourceLocation* location) + { + for (Id tokenId : location->getTokenIds()) + { + if (localSymbolIds.find(tokenId) != localSymbolIds.end()) + { + Reference ref; + ref.filePath = location->getFilePath(); + ref.locationId = location->getLocationId(); + ref.locationType = location->getType(); + m_localReferences.push_back(ref); + return; + } + } + }; + + bool inListMode = getView()->isInListMode(); + for (const CodeFileParams& file : m_files) + { + if (inListMode) + { + for (const CodeSnippetParams& snippet : file.snippetParams) + { + snippet.locationFile->forEachStartSourceLocation(func); + } + } + else if (file.fileParams) + { + file.fileParams->locationFile->forEachStartSourceLocation(func); + } + } + } +} + +void CodeController::iterateReference(bool next) +{ + if (!m_references.size()) + { + return; + } + + if (next) + { + m_referenceIndex++; + + if (m_referenceIndex == m_references.size()) + { + m_referenceIndex = 0; + } + } + else + { + if (m_referenceIndex < 1) + { + m_referenceIndex = m_references.size() - 1; + } + else + { + m_referenceIndex--; + } + } + + const Reference& ref = m_references[m_referenceIndex - 1]; + MessageShowReference(m_referenceIndex, ref.tokenId, ref.locationId, true).dispatch(); +} + +void CodeController::iterateLocalReference(bool next, bool updateView) +{ + if (!m_localReferences.size()) + { + return; + } + + if (next) + { + m_localReferenceIndex++; + + if (m_localReferenceIndex == m_localReferences.size()) + { + m_localReferenceIndex = 0; + } + } + else + { + if (m_localReferenceIndex < 1) + { + m_localReferenceIndex = m_localReferences.size() - 1; + } + else + { + m_localReferenceIndex--; + } + } + + const Reference& ref = m_localReferences[m_localReferenceIndex]; + m_codeParams.currentActiveLocalLocationIds = { ref.locationId }; + + // synchronise reference navigation with local reference navigation + if (ref.locationType == LOCATION_TOKEN) + { + for (size_t i = 0; i < m_references.size(); i++) + { + if (m_references[i].locationId == ref.locationId) + { + m_referenceIndex = i; + } + } + } + + showFiles(m_codeParams, toReferenceScrollParams(ref), updateView); +} + +void CodeController::expandVisibleFiles(bool useSingleFileCache) { TRACE(); - if (!snippets->size()) + if (!m_files.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; + size_t filesToExpand = inListMode ? std::min(int(m_files.size()), 3) : 1; + MessageChangeFileView::FileState state = + inListMode ? MessageChangeFileView::FILE_SNIPPETS : MessageChangeFileView::FILE_MAXIMIZED; for (size_t i = 0; i < filesToExpand; i++) { - CodeSnippetParams& oldSnippet = snippets->at(i); - if (!oldSnippet.isCollapsed || oldSnippet.reduced) - { - continue; - } - - if (useSingleFileCache && !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()); + setFileState(m_files[i], state, useSingleFileCache); } } -void CodeController::addAllSourceLocations(std::vector* snippets) const +CodeFileParams* CodeController::addSourceLocations(std::shared_ptr locationFile) +{ + if (!m_collection) + { + m_collection = std::make_shared(); + } + m_collection->addSourceLocationCopies(locationFile.get()); + + CodeFileParams* file = nullptr; + for (CodeFileParams& f : m_files) + { + if (f.locationFile->getFilePath() == locationFile->getFilePath()) + { + file = &f; + break; + } + } + + if (!file) + { + CodeFileParams f; + f.locationFile = locationFile; + m_files.push_back(f); + file = &m_files.back(); + } + + if (file->snippetParams.size()) + { + std::vector snippets = getSnippetsForFile(locationFile); + if (snippets.size() != 1) + { + LOG_ERROR("addSourceLocations() didn't result in one single snippet to be created"); + return nullptr; + } + + CodeSnippetParams newSnippet = snippets[0]; + + size_t i = 0; + while (i < file->snippetParams.size()) + { + size_t start = newSnippet.startLineNumber; + size_t end = newSnippet.endLineNumber; + + const CodeSnippetParams& oldSnippet = file->snippetParams[i]; + + if (oldSnippet.endLineNumber + 1 < start) // before + { + i++; + continue; + } + else if (oldSnippet.startLineNumber > end + 1) // after + { + break; + } + else if (oldSnippet.startLineNumber <= start && oldSnippet.endLineNumber >= end) // containing + { + return nullptr; + } + else if (oldSnippet.startLineNumber < start || oldSnippet.endLineNumber > end) // overlaping + { + newSnippet = CodeSnippetParams::merge(newSnippet, oldSnippet); + } + else if (oldSnippet.startLineNumber >= start && oldSnippet.endLineNumber <= end) // enclosing + { + // copy all source locations from old to new snippet: fulltext locations got lost + newSnippet.locationFile->copySourceLocations(oldSnippet.locationFile); + } + + file->snippetParams.erase(file->snippetParams.begin() + i); + } + + file->snippetParams.insert(file->snippetParams.begin() + i, newSnippet); + } + + setFileState(*file, getView()->isInListMode() ? MessageChangeFileView::FILE_SNIPPETS : MessageChangeFileView::FILE_MAXIMIZED, m_codeParams.useSingleFileCache); + return file; +} + +void CodeController::setFileState(const FilePath& filePath, MessageChangeFileView::FileState state, bool useSingleFileCache) +{ + for (CodeFileParams& file : m_files) + { + if (file.locationFile->getFilePath() == filePath) + { + setFileState(file, state, useSingleFileCache); + return; + } + } +} + +void CodeController::setFileState(CodeFileParams& file, MessageChangeFileView::FileState state, bool useSingleFileCache) { TRACE(); - for (CodeSnippetParams& snippet : *snippets) + switch (state) { - if (!snippet.locationFile || snippet.isCollapsed || snippet.reduced) + case MessageChangeFileView::FILE_MINIMIZED: + file.isMinimized = true; + break; + + case MessageChangeFileView::FILE_SNIPPETS: + file.isMinimized = false; + if (!file.snippetParams.size()) { - continue; + if (file.locationFile->isWhole()) + { + file.snippetParams = { getSnippetParamsForWholeFile(file.locationFile, useSingleFileCache) }; + } + else + { + file.snippetParams = getSnippetsForFile(file.locationFile); + } + } + break; + + case MessageChangeFileView::FILE_MAXIMIZED: + if (!file.fileParams) + { + file.fileParams = std::make_shared(getSnippetParamsForWholeFile(file.locationFile, useSingleFileCache)); } - std::shared_ptr file; - - if (snippet.locationFile->isWhole()) + if (file.locationFile) { - 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; + m_currentFilePath = file.locationFile->getFilePath(); } + break; } } -void CodeController::addModificationTimes(std::vector* snippets) const +bool CodeController::addAllSourceLocations() +{ + TRACE(); + + bool addedNewLocations = false; + + for (CodeFileParams& file : m_files) + { + for (CodeSnippetParams& snippet : file.snippetParams) + { + if (snippet.hasAllSourceLocations) + { + continue; + } + + if (snippet.locationFile->isWhole()) + { + snippet.locationFile = m_storageAccess->getSourceLocationsForFile(snippet.locationFile->getFilePath()); + if (snippet.locationFile) + { + snippet.locationFile->copySourceLocations(file.locationFile); + } + } + else + { + std::shared_ptr file = m_storageAccess->getSourceLocationsForLinesInFile( + snippet.locationFile->getFilePath(), snippet.startLineNumber, snippet.endLineNumber); + if (file) + { + file->copySourceLocations(snippet.locationFile); + snippet.locationFile = file; + } + } + + addedNewLocations = true; + snippet.hasAllSourceLocations = true; + } + + if (file.fileParams) + { + if (file.fileParams->hasAllSourceLocations) + { + continue; + } + + file.fileParams->locationFile = m_storageAccess->getSourceLocationsForFile(file.locationFile->getFilePath()); + if (file.fileParams->locationFile) + { + file.fileParams->locationFile->copySourceLocations(file.locationFile); + } + + addedNewLocations = true; + file.fileParams->hasAllSourceLocations = true; + } + } + + return addedNewLocations; +} + +void CodeController::addModificationTimes() { TRACE(); std::vector filePaths; - for (const CodeSnippetParams& snippet : *snippets) + for (const CodeFileParams& file : m_files) { - filePaths.push_back(snippet.locationFile->getFilePath()); + filePaths.push_back(file.locationFile->getFilePath()); } std::vector fileInfos = m_storageAccess->getFileInfosForFilePaths(filePaths); @@ -963,12 +1279,70 @@ void CodeController::addModificationTimes(std::vector* snippe fileInfoMap.emplace(fileInfo.path, fileInfo); } - for (CodeSnippetParams& snippet : *snippets) + for (CodeFileParams& file : m_files) { - snippet.modificationTime = fileInfoMap[snippet.locationFile->getFilePath()].lastWriteTime; + file.modificationTime = fileInfoMap[file.locationFile->getFilePath()].lastWriteTime; } } +CodeScrollParams CodeController::firstReferenceScrollParams() const +{ + if (m_references.size()) + { + const Reference& ref = m_references.front(); + + return CodeScrollParams::toReference( + ref.filePath, + ref.scopeLocationId ? ref.scopeLocationId : ref.locationId, + CodeScrollParams::Target::TOP + ); + } + + return CodeScrollParams(); +} + +CodeScrollParams CodeController::definitionReferenceScrollParams(const std::vector& activeTokenIds) const +{ + Id activeTokenId = activeTokenIds.size() ? activeTokenIds.front() : 0; + if (activeTokenId) + { + for (const Reference& ref : m_references) + { + if (ref.scopeLocationId && ref.tokenId == activeTokenId) + { + return CodeScrollParams::toReference( + ref.filePath, + ref.scopeLocationId, + CodeScrollParams::Target::TOP + ); + } + } + + for (const Reference& ref : m_references) + { + if (ref.tokenId == activeTokenId) + { + return CodeScrollParams::toReference( + ref.filePath, + ref.locationId, + CodeScrollParams::Target::TOP + ); + } + } + } + + return firstReferenceScrollParams(); +} + +CodeScrollParams CodeController::toReferenceScrollParams(const Reference& ref) const +{ + return CodeScrollParams::toReference( + ref.filePath, + ref.scopeLocationId ? ref.scopeLocationId : ref.locationId, + CodeScrollParams::Target::CENTER + ); +} + void CodeController::saveOrRestoreViewMode(MessageBase* message) { if (message->isReplayed()) @@ -985,17 +1359,146 @@ void CodeController::saveOrRestoreViewMode(MessageBase* message) } } -void CodeController::showCodeSnippets( - std::vector snippets, const CodeView::CodeParams params, bool addSourceLocations) +void CodeController::showFirstActiveReference(Id tokenId, bool updateView) { - expandVisibleSnippets(&snippets, params.useSingleFileCache); - - CodeView* view = getView(); - view->showCodeSnippets(snippets, params); - - if (addSourceLocations) + // iterate local references when same tokenId get reactivated (consecutive edge clicks) + if (m_codeParams.activeLocalSymbolIds.size() == 1 && m_codeParams.activeLocalSymbolIds[0] == tokenId && m_localReferences.size()) { - addAllSourceLocations(&snippets); - view->updateCodeSnippets(snippets); + iterateLocalReference(true, updateView); + return; + } + + std::vector locationIds; + int referenceIndex = -1; + Reference firstReference; + + std::set filePathsToExpand; + std::map filePathOrder; + + for (size_t i = 0; i < m_references.size(); i++) + { + const Reference& ref = m_references[i]; + if (ref.tokenId == tokenId) + { + filePathsToExpand.insert(ref.filePath); + locationIds.push_back(ref.locationId); + + if (!firstReference.tokenId) + { + firstReference = ref; + referenceIndex = i; + } + } + + filePathOrder.emplace(ref.filePath, filePathOrder.size()); + } + + if (!locationIds.size()) + { + std::shared_ptr collection = m_storageAccess->getSourceLocationsForTokenIds({ tokenId }); + collection->forEachSourceLocation( + [&](SourceLocation* location) + { + if (!location->isStartLocation()) + { + return; + } + + for (Id i : location->getTokenIds()) + { + if (i == tokenId) + { + locationIds.push_back(location->getLocationId()); + filePathsToExpand.insert(location->getFilePath()); + + if (!firstReference.tokenId || filePathOrder[location->getFilePath()] < filePathOrder[firstReference.filePath]) + { + firstReference.tokenId = tokenId; + firstReference.locationId = location->getLocationId(); + firstReference.filePath = location->getFilePath(); + } + return; + } + } + } + ); + } + + if (getView()->isInListMode()) + { + for (const FilePath& filePath : filePathsToExpand) + { + setFileState(filePath, MessageChangeFileView::FILE_SNIPPETS, m_codeParams.useSingleFileCache); + } + } + else if (firstReference.tokenId) + { + setFileState(firstReference.filePath, MessageChangeFileView::FILE_MAXIMIZED, m_codeParams.useSingleFileCache); + } + + createLocalReferences({ tokenId }); + m_codeParams.activeLocalSymbolIds = { tokenId }; + m_codeParams.activeLocalSymbolType = LOCATION_TOKEN; + m_codeParams.currentActiveLocalLocationIds.clear(); + + CodeScrollParams scrollParams; + + if (firstReference.tokenId) + { + scrollParams = toReferenceScrollParams(firstReference); + m_referenceIndex = referenceIndex; + } + + showFiles(m_codeParams, scrollParams, updateView); +} + +void CodeController::showFiles(CodeView::CodeParams params, CodeScrollParams scrollParams, bool updateView) +{ + if (updateView) + { + addModificationTimes(); + + params.referenceCount = m_references.size(); + params.referenceIndex = m_referenceIndex >= 0 ? m_referenceIndex : m_references.size(); + + params.localReferenceCount = m_localReferences.size(); + params.localReferenceIndex = m_localReferenceIndex >= 0 ? m_localReferenceIndex : m_localReferences.size(); + + if (getView()->isInListMode()) + { + getView()->showSnippets(m_files, params, scrollParams); + } + else + { + bool updated = false; + for (const CodeFileParams& file : m_files) + { + if (file.locationFile->getFilePath() == m_currentFilePath) + { + getView()->showSingleFile(file, params, scrollParams); + updated = true; + break; + } + } + + if (!updated) + { + getView()->showSingleFile(CodeFileParams(), params, scrollParams); + } + } + + params.clearSnippets = false; + m_scrollParams = CodeScrollParams(); + } + else if (scrollParams.type != CodeScrollParams::Type::NONE) + { + m_scrollParams = scrollParams; + } + + m_codeParams = params; + + if (addAllSourceLocations() && updateView) + { + getView()->updateSourceLocations(m_files); } } diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index 552f5c0f..9ff2dcde 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -5,8 +5,10 @@ #include #include "FilePath.h" +#include "LocationType.h" #include "MessageListener.h" #include "MessageActivateLegend.h" +#include "MessageCodeReference.h" #include "MessageCodeShowDefinition.h" #include "MessageActivateErrors.h" #include "MessageErrorCountClear.h" @@ -24,6 +26,7 @@ #include "MessageFocusOut.h" #include "MessageScrollCode.h" #include "MessageScrollToLine.h" +#include "MessageShowReference.h" #include "MessageShowScope.h" #include "types.h" @@ -47,6 +50,7 @@ class CodeController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -56,6 +60,7 @@ class CodeController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener { public: @@ -65,6 +70,15 @@ public: Id getSchedulerId() const override; private: + struct Reference + { + FilePath filePath; + Id tokenId = 0; + Id locationId = 0; + Id scopeLocationId = 0; + LocationType locationType = LOCATION_TOKEN; + }; + void handleMessage(MessageActivateErrors* message) override; void handleMessage(MessageActivateFullTextSearch* message) override; void handleMessage(MessageActivateLegend* message) override; @@ -74,6 +88,7 @@ private: void handleMessage(MessageActivateTrail* message) override; void handleMessage(MessageActivateTrailEdge* message) override; void handleMessage(MessageChangeFileView* message) override; + void handleMessage(MessageCodeReference* message) override; void handleMessage(MessageCodeShowDefinition* message) override; void handleMessage(MessageDeactivateEdge* message) override; void handleMessage(MessageErrorCountClear* message) override; @@ -83,17 +98,18 @@ private: void handleMessage(MessageScrollCode* message) override; void handleMessage(MessageScrollToLine* message) override; void handleMessage(MessageShowError* message) override; + void handleMessage(MessageShowReference* message) override; void handleMessage(MessageShowScope* message) override; CodeView* getView() const; void clear() override; - std::vector getSnippetsForFileWithState(const FilePath& filePath, CodeView::FileState state) const; - std::vector getSnippetsForActiveSourceLocations( + std::vector getFilesForActiveSourceLocations( const SourceLocationCollection* collection, Id declarationId) const; - std::vector getSnippetsForCollection(std::shared_ptr collection) const; - std::vector getSnippetsForFile(std::shared_ptr file) const; + std::vector getFilesForCollection(std::shared_ptr collection) const; + CodeSnippetParams getSnippetParamsForWholeFile(std::shared_ptr locationFile, bool useSingleFileCache) const; + std::vector getSnippetsForFile(std::shared_ptr activeSourceLocations) const; std::shared_ptr buildMergerHierarchy( const SourceLocation* location, const SourceLocationFile* scopeLocations, SnippetMerger& fileScopedMerger, @@ -103,19 +119,48 @@ private: std::vector getProjectDescription(SourceLocationFile* locationFile) const; - void expandVisibleSnippets(std::vector* snippets, bool useSingleFileCache) const; - void addAllSourceLocations(std::vector* snippets) const; - void addModificationTimes(std::vector* snippets) const; + void clearReferences(); + void createReferences(); + + void clearLocalReferences(); + void createLocalReferences(const std::set& localSymbolIds); + + void iterateReference(bool next); + void iterateLocalReference(bool next, bool updateView); + + void expandVisibleFiles(bool useSingleFileCache); + CodeFileParams* addSourceLocations(std::shared_ptr locationFile); + void setFileState(const FilePath& filePath, MessageChangeFileView::FileState state, bool useSingleFileCache); + void setFileState(CodeFileParams& file, MessageChangeFileView::FileState state, bool useSingleFileCache); + bool addAllSourceLocations(); + void addModificationTimes(); + + CodeScrollParams firstReferenceScrollParams() const; + CodeScrollParams definitionReferenceScrollParams(const std::vector& activeTokenIds) const; + CodeScrollParams toReferenceScrollParams(const Reference& ref) const; void saveOrRestoreViewMode(MessageBase* message); - void showCodeSnippets( - std::vector snippets, const CodeView::CodeParams params, bool addSourceLocations = true); + void showFirstActiveReference(Id tokenId, bool updateView); + void showFiles(CodeView::CodeParams params, CodeScrollParams scrollParams, bool updateView); StorageAccess* m_storageAccess; - mutable std::shared_ptr m_collection; + + std::shared_ptr m_collection; + + std::vector m_files; + FilePath m_currentFilePath; + + CodeView::CodeParams m_codeParams; + CodeScrollParams m_scrollParams; std::map m_messageIdToViewModeMap; + + std::vector m_references; + int m_referenceIndex = -1; + + std::vector m_localReferences; + int m_localReferenceIndex = -1; }; #endif // CODE_CONTROLLER_H diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 52110fc2..89df8ded 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -4,9 +4,10 @@ #include #include "ErrorInfo.h" - -#include "ScreenSearchInterfaces.h" +#include "LocationType.h" +#include "CodeScrollParams.h" #include "CodeSnippetParams.h" +#include "ScreenSearchInterfaces.h" #include "View.h" class CodeController; @@ -30,42 +31,22 @@ public: struct CodeParams { bool clearSnippets = false; - bool showContents = false; bool useSingleFileCache = true; + size_t referenceCount = 0; + size_t referenceIndex = 0; + size_t localReferenceCount = 0; + size_t localReferenceIndex = 0; + std::vector activeTokenIds; + std::vector activeLocationIds; + std::vector activeLocalSymbolIds; + LocationType activeLocalSymbolType = LOCATION_TOKEN; + std::vector currentActiveLocalLocationIds; + std::vector errorInfos; }; - struct ScrollParams - { - enum ScrollType - { - SCROLL_NONE, - SCROLL_TO_DEFINITION, - SCROLL_TO_LINE, - SCROLL_TO_VALUE - } type; - - ScrollParams(ScrollType type = SCROLL_NONE) - : type(type) - , line(0) - , value(0) - , animated(false) - , ignoreActiveReference(false) - , inListMode(false) - {} - - FilePath filePath; - size_t line; - - size_t value; - - bool animated; - bool ignoreActiveReference; - bool inListMode; - }; - CodeView(ViewLayout* viewLayout); virtual ~CodeView(); @@ -73,24 +54,21 @@ 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 void showSnippets( + const std::vector files, const CodeParams params, const CodeScrollParams scrollParams) = 0; + + virtual void showSingleFile( + const CodeFileParams file, const CodeParams params, const CodeScrollParams scrollParams) = 0; + + virtual void updateSourceLocations(const std::vector files) = 0; + + virtual void scrollTo(const CodeScrollParams params, bool animated) = 0; virtual bool showsErrors() const = 0; - virtual void setFileState(const FilePath filePath, FileState state) = 0; - - virtual void showActiveSnippet( - const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo) = 0; - virtual void showActiveTokenIds(const std::vector& activeTokenIds) = 0; - virtual void showActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds) = 0; - virtual void focusTokenIds(const std::vector& focusedTokenIds) = 0; virtual void defocusTokenIds() = 0; - virtual void showContents() = 0; - virtual bool isInListMode() const = 0; virtual void setMode(bool listMode) = 0; diff --git a/src/lib/component/view/helper/CodeScrollParams.h b/src/lib/component/view/helper/CodeScrollParams.h new file mode 100644 index 00000000..23089dc3 --- /dev/null +++ b/src/lib/component/view/helper/CodeScrollParams.h @@ -0,0 +1,61 @@ +#ifndef CODE_SCROLL_PARAMS_H +#define CODE_SCROLL_PARAMS_H + +#include "FilePath.h" +#include "types.h" + +struct CodeScrollParams +{ + enum class Type + { + NONE, + TO_REFERENCE, + TO_FILE, + TO_LINE, + TO_VALUE + }; + + enum class Target + { + VISIBLE, + CENTER, + TOP + }; + + static CodeScrollParams toReference(const FilePath& filePath, Id locationId, Target target) + { + return CodeScrollParams { Type::TO_REFERENCE, target, filePath, locationId, 0, 0, false }; + } + + static CodeScrollParams toFile(const FilePath& filePath, Target target) + { + return CodeScrollParams { Type::TO_LINE, target, filePath, 0, 0, 0, false }; + } + + static CodeScrollParams toLine(const FilePath& filePath, size_t line, Target target) + { + return CodeScrollParams { Type::TO_LINE, target, filePath, 0, line, 0, false }; + } + + static CodeScrollParams toValue(size_t value, bool inListMode) + { + return CodeScrollParams { Type::TO_VALUE, Target::VISIBLE, FilePath(), 0, 0, value, inListMode }; + } + + Type type = Type::NONE; + Target target = Target::VISIBLE; + + FilePath filePath; + + // Reference + Id locationId = 0; + + // Line + size_t line = 0; + + // Value + size_t value = 0; + bool inListMode = false; +}; + +#endif // CODE_SCROLL_PARAMS_H diff --git a/src/lib/component/view/helper/CodeSnippetParams.cpp b/src/lib/component/view/helper/CodeSnippetParams.cpp index be05fa89..e2928907 100644 --- a/src/lib/component/view/helper/CodeSnippetParams.cpp +++ b/src/lib/component/view/helper/CodeSnippetParams.cpp @@ -2,21 +2,55 @@ #include "SourceLocationFile.h" -CodeSnippetParams::CodeSnippetParams() - : startLineNumber(0) - , endLineNumber(0) - , titleId(0) - , footerId(0) - , refCount(0) - , isCollapsed(false) - , isDeclaration(false) - , isDefinition(false) - , insertSnippet(false) - , reduced(false) +CodeSnippetParams CodeSnippetParams::merge(const CodeSnippetParams& a, const CodeSnippetParams& b) { + const CodeSnippetParams* first = a.startLineNumber < b.startLineNumber ? &a : &b; + const CodeSnippetParams* second = a.startLineNumber > b.startLineNumber ? &a : &b; + + SourceLocationFile* aFile = a.locationFile.get(); + SourceLocationFile* bFile = b.locationFile.get(); + + std::shared_ptr locationFile = std::make_shared( + aFile->getFilePath(), aFile->getLanguage(), aFile->isWhole(), aFile->isComplete(), aFile->isIndexed()); + + aFile->forEachSourceLocation( + [&locationFile](SourceLocation* loc) + { + locationFile->addSourceLocationCopy(loc); + } + ); + + bFile->forEachSourceLocation( + [&locationFile](SourceLocation* loc) + { + locationFile->addSourceLocationCopy(loc); + } + ); + + std::string code = first->code; + + std::string secondCode = second->code; + int secondCodeStartIndex = 0; + for (size_t i = second->startLineNumber; i <= first->endLineNumber; i++) + { + secondCodeStartIndex = secondCode.find("\n", secondCodeStartIndex) + 1; + } + code += secondCode.substr(secondCodeStartIndex, secondCode.npos); + + CodeSnippetParams params; + params.startLineNumber = first->startLineNumber; + params.endLineNumber = second->endLineNumber; + params.title = first->title; + params.titleId = first->titleId; + params.footer = second->footer; + params.footerId = second->footerId; + params.code = code; + params.locationFile = locationFile; + + return params; } -bool CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSnippetParams& b) +bool CodeFileParams::sort(const CodeFileParams& a, const CodeFileParams& b) { // sort definitions if (a.isDefinition && !b.isDefinition) @@ -51,25 +85,19 @@ bool CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSnippetParams const FilePath& aFilePath = a.locationFile->getFilePath(); const FilePath& bFilePath = b.locationFile->getFilePath(); - // different files - if (aFilePath != bFilePath) + // first header + if (aFilePath.withoutExtension() == bFilePath.withoutExtension()) { - // first header - if (aFilePath.withoutExtension() == bFilePath.withoutExtension()) - { - return aFilePath.extension() > bFilePath.extension(); - } - // alphabetical filepath without extension - else - { - return aFilePath.withoutExtension() < bFilePath.withoutExtension(); - } + return aFilePath.extension() > bFilePath.extension(); + } + // alphabetical filepath without extension + else + { + return aFilePath.withoutExtension() < bFilePath.withoutExtension(); } - - return a.startLineNumber < b.startLineNumber; } -bool CodeSnippetParams::sortById(const CodeSnippetParams& a, const CodeSnippetParams& b) +bool CodeFileParams::sortById(const CodeFileParams& a, const CodeFileParams& b) { return a.locationFile->getSourceLocations().begin()->get()->getLocationId() < b.locationFile->getSourceLocations().begin()->get()->getLocationId(); diff --git a/src/lib/component/view/helper/CodeSnippetParams.h b/src/lib/component/view/helper/CodeSnippetParams.h index cb966234..aee0ed8f 100644 --- a/src/lib/component/view/helper/CodeSnippetParams.h +++ b/src/lib/component/view/helper/CodeSnippetParams.h @@ -10,34 +10,38 @@ class SourceLocationFile; struct CodeSnippetParams { - CodeSnippetParams(); + static CodeSnippetParams merge(const CodeSnippetParams& a, const CodeSnippetParams& b); - // comparefunction for snippetsorting - static bool sort(const CodeSnippetParams& a, const CodeSnippetParams& b); - static bool sortById(const CodeSnippetParams& a, const CodeSnippetParams& b); - - size_t startLineNumber; - size_t endLineNumber; + size_t startLineNumber = 0; + size_t endLineNumber = 0; std::wstring title; std::wstring footer; std::string code; - Id titleId; - Id footerId; - TimeStamp modificationTime; + Id titleId = 0; + Id footerId = 0; std::shared_ptr locationFile; + bool hasAllSourceLocations = false; + bool isOverview = false; +}; - int refCount; +struct CodeFileParams +{ + static bool sort(const CodeFileParams& a, const CodeFileParams& b); + static bool sortById(const CodeFileParams& a, const CodeFileParams& b); - bool isCollapsed; + std::shared_ptr locationFile; + TimeStamp modificationTime; + size_t referenceCount = 0; - bool isDeclaration; - bool isDefinition; + bool isMinimized = true; + bool isDeclaration = false; + bool isDefinition = false; - bool insertSnippet; - bool reduced; + std::vector snippetParams; + std::shared_ptr fileParams; // TODO: replace with std::optional }; #endif // CODE_SNIPPET_PARAMS_H diff --git a/src/lib/data/location/SourceLocationCollection.cpp b/src/lib/data/location/SourceLocationCollection.cpp index 447b8556..430514bc 100644 --- a/src/lib/data/location/SourceLocationCollection.cpp +++ b/src/lib/data/location/SourceLocationCollection.cpp @@ -91,16 +91,21 @@ void SourceLocationCollection::addSourceLocationCopies(const SourceLocationColle other->forEachSourceLocationFile( [this](std::shared_ptr otherFile) { - SourceLocationFile* file = createSourceLocationFile( - otherFile->getFilePath(), otherFile->getLanguage(), otherFile->isWhole(), otherFile->isComplete(), - otherFile->isIndexed()); + addSourceLocationCopies(otherFile.get()); + } + ); +} - otherFile->forEachSourceLocation( - [file](SourceLocation* otherLocation) - { - file->addSourceLocationCopy(otherLocation); - } - ); +void SourceLocationCollection::addSourceLocationCopies(const SourceLocationFile* otherFile) +{ + SourceLocationFile* file = createSourceLocationFile( + otherFile->getFilePath(), otherFile->getLanguage(), otherFile->isWhole(), otherFile->isComplete(), + otherFile->isIndexed()); + + otherFile->forEachSourceLocation( + [file](SourceLocation* otherLocation) + { + file->addSourceLocationCopy(otherLocation); } ); } diff --git a/src/lib/data/location/SourceLocationCollection.h b/src/lib/data/location/SourceLocationCollection.h index ab2d5dbd..d39ee41a 100644 --- a/src/lib/data/location/SourceLocationCollection.h +++ b/src/lib/data/location/SourceLocationCollection.h @@ -35,6 +35,7 @@ public: SourceLocation* addSourceLocationCopy(const SourceLocation* location); void addSourceLocationCopies(const SourceLocationCollection* other); + void addSourceLocationCopies(const SourceLocationFile* otherFile); void addSourceLocationFile(std::shared_ptr file); diff --git a/src/lib/data/location/SourceLocationFile.cpp b/src/lib/data/location/SourceLocationFile.cpp index c9bca811..53290e11 100644 --- a/src/lib/data/location/SourceLocationFile.cpp +++ b/src/lib/data/location/SourceLocationFile.cpp @@ -233,7 +233,7 @@ std::shared_ptr SourceLocationFile::getFilteredByTypes(const } std::shared_ptr ret = - std::make_shared(getFilePath(), getLanguage(), false, isComplete(), isIndexed()); + std::make_shared(getFilePath(), getLanguage(), isWhole(), isComplete(), isIndexed()); for (const std::shared_ptr& location : m_locations) { diff --git a/src/lib/utility/messaging/type/code/MessageChangeFileView.h b/src/lib/utility/messaging/type/code/MessageChangeFileView.h index aa2fad22..d93c98c9 100644 --- a/src/lib/utility/messaging/type/code/MessageChangeFileView.h +++ b/src/lib/utility/messaging/type/code/MessageChangeFileView.h @@ -1,6 +1,8 @@ #ifndef MESSAGE_CHANGE_FILE_VIEW_H #define MESSAGE_CHANGE_FILE_VIEW_H +#include "CodeScrollParams.h" +#include "CodeSnippetParams.h" #include "FilePath.h" #include "Message.h" #include "TabId.h" @@ -27,15 +29,13 @@ public: const FilePath& filePath, FileState state, ViewMode viewMode, - bool needsData, - bool showErrors, + CodeScrollParams scrollParams, bool switchesViewMode = false ) : filePath(filePath) , state(state) , viewMode(viewMode) - , needsData(needsData) - , showErrors(showErrors) + , scrollParams(scrollParams) , switchesViewMode(switchesViewMode) { setSchedulerId(TabId::currentTab()); @@ -63,18 +63,12 @@ public: case VIEW_SINGLE: os << L", single"; break; case VIEW_CURRENT: os << L", current"; break; } - - if (needsData) - { - os << L", needs data"; - } } const FilePath filePath; const FileState state; const ViewMode viewMode; - const bool needsData; - const bool showErrors; + const CodeScrollParams scrollParams; const bool switchesViewMode; }; diff --git a/src/lib/utility/messaging/type/code/MessageScrollToLine.h b/src/lib/utility/messaging/type/code/MessageScrollToLine.h index 9fe33588..2512d08f 100644 --- a/src/lib/utility/messaging/type/code/MessageScrollToLine.h +++ b/src/lib/utility/messaging/type/code/MessageScrollToLine.h @@ -21,6 +21,11 @@ public: return "MessageScrollToLine"; } + void print(std::wostream& os) const override + { + os << filePath.wstr() << L":" << line; + } + const FilePath filePath; size_t line; }; diff --git a/src/lib_gui/qt/element/code/QtCodeArea.cpp b/src/lib_gui/qt/element/code/QtCodeArea.cpp index 5360816d..ef38fa49 100644 --- a/src/lib_gui/qt/element/code/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/code/QtCodeArea.cpp @@ -388,19 +388,6 @@ Id QtCodeArea::getLocationIdOfFirstHighlightedLocation() const return 0; } -std::vector QtCodeArea::getLocationIdsForTokenIds(const std::set& tokenIds) const -{ - std::vector locationIds; - for (const Annotation& annotation : m_annotations) - { - if (utility::shareElement(annotation.tokenIds, tokenIds)) - { - locationIds.push_back(annotation.locationId); - } - } - return locationIds; -} - size_t QtCodeArea::getActiveLocationCount() const { size_t count = 0; @@ -639,14 +626,7 @@ void QtCodeArea::mouseReleaseEvent(QMouseEvent* event) std::vector annotations = getInteractiveAnnotationsForPosition(event->pos()); if (annotations.size()) { - if (m_navigator->hasErrors()) - { - activateErrors(annotations); - } - else - { - activateAnnotations(annotations); - } + activateAnnotationsOrErrors(annotations); } else if (m_navigator->getActiveLocalTokenIds().size()) { @@ -700,15 +680,25 @@ void QtCodeArea::mouseMoveEvent(QMouseEvent* event) if (!same) { + if (m_navigator->hasErrors()) + { + for (const Annotation* annotation : annotations) + { + if (annotation->locationType == LOCATION_ERROR && annotation->tokenIds.size()) + { + std::wstring errorMessage = m_navigator->getErrorMessageForId(*annotation->tokenIds.begin()); + QToolTip::showText(event->globalPos(), QString::fromStdWString(errorMessage), this); + + QtCodeField::focusTokenIds({ *annotation->tokenIds.begin() }); + viewport()->setCursor(Qt::PointingHandCursor); + return; + } + } + } + QToolTip::hideText(); setHoveredAnnotations(annotations); - - 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), this); - } } } @@ -748,23 +738,11 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event) void QtCodeArea::focusTokenIds(const std::vector& tokenIds) { - if (m_navigator->hasErrors() && tokenIds.size() == 1) - { - QtCodeField::focusTokenIds(tokenIds); - return; - } - MessageFocusIn(tokenIds, TOOLTIP_ORIGIN_CODE).dispatch(); } void QtCodeArea::defocusTokenIds(const std::vector& tokenIds) { - if (m_navigator->hasErrors() && tokenIds.size() == 1) - { - annotateText(); - return; - } - MessageFocusOut(tokenIds).dispatch(); } @@ -821,21 +799,27 @@ void QtCodeArea::setNewTextCursor(const QTextCursor& cursor) verticalScrollBar()->setValue(verticalValue); } -void QtCodeArea::activateErrors(const std::vector& annotations) +void QtCodeArea::activateAnnotationsOrErrors(const std::vector& annotations) { - std::vector errorIds; - for (const Annotation* annotation : annotations) + if (m_navigator->hasErrors()) { - if (annotation->locationType == LOCATION_ERROR && annotation->tokenIds.size()) + std::vector errorIds; + for (const Annotation* annotation : annotations) { - errorIds.insert(errorIds.end(), annotation->tokenIds.begin(), annotation->tokenIds.end()); + if (annotation->locationType == LOCATION_ERROR && annotation->tokenIds.size()) + { + errorIds.insert(errorIds.end(), annotation->tokenIds.begin(), annotation->tokenIds.end()); + } + } + + if (errorIds.size() == 1) + { + MessageShowError(errorIds[0]).dispatch(); + return; } } - if (errorIds.size() == 1) - { - MessageShowError(errorIds[0]).dispatch(); - } + activateAnnotations(annotations); } void QtCodeArea::annotateText() diff --git a/src/lib_gui/qt/element/code/QtCodeArea.h b/src/lib_gui/qt/element/code/QtCodeArea.h index 355fb44c..00f04ee1 100644 --- a/src/lib_gui/qt/element/code/QtCodeArea.h +++ b/src/lib_gui/qt/element/code/QtCodeArea.h @@ -81,8 +81,6 @@ public: Id getLocationIdOfFirstActiveScopeLocation(Id tokenId) const; Id getLocationIdOfFirstHighlightedLocation() const; - std::vector getLocationIdsForTokenIds(const std::set& tokenIds) const; - size_t getActiveLocationCount() const; QRectF getLineRectForLineNumber(size_t lineNumber) const; @@ -114,7 +112,7 @@ private: void clearSelection(); void setNewTextCursor(const QTextCursor& cursor); - void activateErrors(const std::vector& annotations); + void activateAnnotationsOrErrors(const std::vector& annotations); void annotateText(); diff --git a/src/lib_gui/qt/element/code/QtCodeFile.cpp b/src/lib_gui/qt/element/code/QtCodeFile.cpp index d99af6c7..86431558 100644 --- a/src/lib_gui/qt/element/code/QtCodeFile.cpp +++ b/src/lib_gui/qt/element/code/QtCodeFile.cpp @@ -15,7 +15,6 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator, boo , m_navigator(navigator) , m_filePath(filePath) , m_isWholeFile(false) - , m_contentRequested(false) { setObjectName("code_file"); setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); @@ -43,6 +42,7 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator, boo m_snippetLayout->setSpacing(0); layout->addLayout(m_snippetLayout); + setMinimized(); update(); } @@ -67,118 +67,30 @@ 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 && - snippet->getEndLineNumber() == params.endLineNumber) - { - return snippet; - } - } - QtCodeSnippet* snippet = new QtCodeSnippet(params, m_navigator, this); - if (params.reduced) + if (params.isOverview) { m_titleBar->getTitleButton()->setProject(params.title); - m_isWholeFile = true; } if (params.locationFile->isWhole() || m_isWholeFile) { m_isWholeFile = true; - snippet->setIsActiveFile(true); - - if (params.refCount != -1) - { - updateRefCount(0); - } - - for (QtCodeSnippet* oldSnippet : m_snippets) - { - oldSnippet->hide(); - } - m_snippets.clear(); - } - else - { - updateRefCount(params.refCount); } m_snippetLayout->addWidget(snippet); m_snippets.push_back(snippet); - setSnippets(); - return snippet; } -QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params) -{ - QtCodeSnippet* newSnippet = new QtCodeSnippet(params, m_navigator, this); - - size_t i = 0; - while (i < m_snippets.size()) - { - size_t start = newSnippet->getStartLineNumber(); - size_t end = newSnippet->getEndLineNumber(); - - QtCodeSnippet* oldSnippet = m_snippets[i]; - - if (oldSnippet->getEndLineNumber() + 1 < start) // before - { - i++; - continue; - } - else if (oldSnippet->getStartLineNumber() > end + 1) // after - { - break; - } - else if (oldSnippet->getStartLineNumber() <= start && oldSnippet->getEndLineNumber() >= end) // containing - { - newSnippet->deleteLater(); - return oldSnippet; - } - else if (oldSnippet->getStartLineNumber() < start || oldSnippet->getEndLineNumber() > end) // overlaping - { - newSnippet = QtCodeSnippet::merged(newSnippet, oldSnippet, m_navigator, this); - } - else if (oldSnippet->getStartLineNumber() >= start && oldSnippet->getEndLineNumber() <= end) // enclosing - { - // copy all source locations from old to new snippet: fulltext locations got lost - oldSnippet->getArea()->getSourceLocationFile()->copySourceLocations( - newSnippet->getArea()->getSourceLocationFile()); - newSnippet->getArea()->updateSourceLocations(oldSnippet->getArea()->getSourceLocationFile()); - } - - m_navigator->clearSnippetReferences(); - - oldSnippet->hide(); - m_snippetLayout->removeWidget(oldSnippet); - oldSnippet->deleteLater(); - - m_snippets.erase(m_snippets.begin() + i); - } - - m_snippetLayout->insertWidget(i, newSnippet); - m_snippets.insert(m_snippets.begin() + i, newSnippet); - - setSnippets(); - - return newSnippet; -} - -void QtCodeFile::updateCodeSnippet(const CodeSnippetParams& params) +void QtCodeFile::updateSourceLocations(const CodeSnippetParams& params) { if (m_isWholeFile && m_snippets.size() == 1) { - m_snippets[0]->updateCodeSnippet(params); + m_snippets[0]->updateSourceLocations(params); return; } @@ -187,11 +99,16 @@ void QtCodeFile::updateCodeSnippet(const CodeSnippetParams& params) if (snippet->getStartLineNumber() == params.startLineNumber && snippet->getEndLineNumber() == params.endLineNumber) { - snippet->updateCodeSnippet(params); + snippet->updateSourceLocations(params); } } } +const std::vector& QtCodeFile::getSnippets() const +{ + return m_snippets; +} + std::vector QtCodeFile::getVisibleSnippets() const { std::vector snippets; @@ -251,32 +168,7 @@ std::pair QtCodeFile::getFirstSnippetWithActiveLocationId(Id return result; } -bool QtCodeFile::isCollapsed() const -{ - return !m_snippets.size(); -} - -void QtCodeFile::requestContent() -{ - if (!isCollapsed() || m_contentRequested) - { - updateContent(); - return; - } - - m_contentRequested = true; - - MessageChangeFileView::FileState state = - m_isWholeFile ? MessageChangeFileView::FILE_MAXIMIZED : MessageChangeFileView::FILE_SNIPPETS; - - bool needsData = (m_snippets.size() == 0); - - MessageChangeFileView msg(m_filePath, state, MessageChangeFileView::VIEW_LIST, needsData, m_navigator->hasErrors()); - msg.setSchedulerId(m_navigator->getSchedulerId()); - msg.dispatch(); -} - -void QtCodeFile::requestWholeFileContent() +void QtCodeFile::requestWholeFileContent(size_t targetLineNumber) { if (!m_isWholeFile) { @@ -284,8 +176,7 @@ void QtCodeFile::requestWholeFileContent() m_filePath, MessageChangeFileView::FILE_MAXIMIZED, MessageChangeFileView::VIEW_LIST, - true, - m_navigator->hasErrors() + CodeScrollParams::toLine(m_filePath, targetLineNumber, CodeScrollParams::Target::VISIBLE) ); msg.setSchedulerId(m_navigator->getSchedulerId()); msg.dispatch(); @@ -309,7 +200,6 @@ void QtCodeFile::updateContent() void QtCodeFile::setWholeFile(bool isWholeFile, int refCount) { m_isWholeFile = isWholeFile; - setMinimized(); updateRefCount(isWholeFile ? 0 : refCount); } @@ -344,16 +234,28 @@ void QtCodeFile::setSnippets() m_titleBar->setSnippets(); } -void QtCodeFile::setMaximized() -{ - setSnippets(); -} - bool QtCodeFile::hasSnippets() const { return m_snippets.size() > 0; } +void QtCodeFile::clearSnippets() +{ + for (QtCodeSnippet* snippet : m_snippets) + { + m_snippetLayout->removeWidget(snippet); + snippet->hide(); + snippet->deleteLater(); + } + + if (m_snippets.size()) + { + m_navigator->clearSnippetReferences(); + } + + m_snippets.clear(); +} + void QtCodeFile::updateSnippets() { if (m_snippets.size() == 0) @@ -391,27 +293,13 @@ void QtCodeFile::findScreenMatches(const std::wstring& query, std::vector> QtCodeFile::getLocationIdsForTokenIds(const std::set& tokenIds) const -{ - std::vector> locationIds; - for (QtCodeSnippet* snippet : m_snippets) - { - for (Id locationId : snippet->getLocationIdsForTokenIds(tokenIds)) - { - locationIds.push_back(std::make_pair(m_filePath, locationId)); - } - } - return locationIds; -} - void QtCodeFile::clickedMinimizeButton() { MessageChangeFileView msg( m_filePath, MessageChangeFileView::FILE_MINIMIZED, MessageChangeFileView::VIEW_LIST, - false, - m_navigator->hasErrors() + CodeScrollParams::toFile(m_filePath, CodeScrollParams::Target::VISIBLE) ); msg.setSchedulerId(m_navigator->getSchedulerId()); msg.dispatch(); @@ -419,14 +307,11 @@ void QtCodeFile::clickedMinimizeButton() void QtCodeFile::clickedSnippetButton() { - m_navigator->requestScroll(m_filePath, 0, 0, false, QtCodeNavigateable::SCROLL_VISIBLE); - MessageChangeFileView msg( m_filePath, MessageChangeFileView::FILE_SNIPPETS, MessageChangeFileView::VIEW_LIST, - isCollapsed(), - m_navigator->hasErrors() + CodeScrollParams::toFile(m_filePath, CodeScrollParams::Target::VISIBLE) ); msg.setSchedulerId(m_navigator->getSchedulerId()); msg.dispatch(); @@ -453,14 +338,17 @@ void QtCodeFile::clickedMaximizeButton() } } - m_navigator->requestScroll(m_filePath, lineNumber, locationId, false, QtCodeNavigateable::SCROLL_CENTER); + m_navigator->setMode(QtCodeNavigator::MODE_SINGLE); + + CodeScrollParams scrollParams = locationId ? + CodeScrollParams::toReference(m_filePath, locationId, CodeScrollParams::Target::CENTER) : + CodeScrollParams::toLine(m_filePath, lineNumber, CodeScrollParams::Target::CENTER); MessageChangeFileView msg( m_filePath, MessageChangeFileView::FILE_MAXIMIZED, MessageChangeFileView::VIEW_SINGLE, - true, // TODO: check if data is really needed - m_navigator->hasErrors(), + scrollParams, true ); msg.setSchedulerId(m_navigator->getSchedulerId()); diff --git a/src/lib_gui/qt/element/code/QtCodeFile.h b/src/lib_gui/qt/element/code/QtCodeFile.h index 4d75fe47..eb0e297e 100644 --- a/src/lib_gui/qt/element/code/QtCodeFile.h +++ b/src/lib_gui/qt/element/code/QtCodeFile.h @@ -35,19 +35,16 @@ public: const QtCodeFileTitleBar* getTitleBar() const; QtCodeSnippet* addCodeSnippet(const CodeSnippetParams& params); - QtCodeSnippet* insertCodeSnippet(const CodeSnippetParams& params); - void updateCodeSnippet(const CodeSnippetParams& params); + void updateSourceLocations(const CodeSnippetParams& params); + const std::vector& getSnippets() const; std::vector getVisibleSnippets() const; QtCodeSnippet* getSnippetForLocationId(Id locationId) const; QtCodeSnippet* getSnippetForLine(unsigned int line) const; std::pair getFirstSnippetWithActiveLocationId(Id tokenId) const; - bool isCollapsed() const; - - void requestContent(); - void requestWholeFileContent(); + void requestWholeFileContent(size_t targetLineNumber); void updateContent(); void setWholeFile(bool isWholeFile, int refCount); @@ -56,16 +53,14 @@ public: void setMinimized(); void setSnippets(); - void setMaximized(); bool hasSnippets() const; + void clearSnippets(); void updateSnippets(); void updateTitleBar(); void findScreenMatches(const std::wstring& query, std::vector>* screenMatches); - std::vector> getLocationIdsForTokenIds(const std::set& tokenIds) const; - public slots: void clickedMinimizeButton(); void clickedSnippetButton(); @@ -83,8 +78,6 @@ private: const FilePath m_filePath; bool m_isWholeFile; - - mutable bool m_contentRequested; }; #endif // QT_CODE_FILE_H diff --git a/src/lib_gui/qt/element/code/QtCodeFileList.cpp b/src/lib_gui/qt/element/code/QtCodeFileList.cpp index 9805187a..673fae5b 100644 --- a/src/lib_gui/qt/element/code/QtCodeFileList.cpp +++ b/src/lib_gui/qt/element/code/QtCodeFileList.cpp @@ -115,13 +115,51 @@ QtCodeFile* QtCodeFileList::getFile(const FilePath filePath) return file; } -void QtCodeFileList::addFile(std::shared_ptr locationFile, int refCount, TimeStamp modificationTime) +void QtCodeFileList::addFile(const CodeFileParams& params) { - QtCodeFile* file = getFile(locationFile->getFilePath()); - file->setWholeFile(locationFile->isWhole(), refCount); - file->setModificationTime(modificationTime); - file->setIsComplete(locationFile->isComplete()); - file->setIsIndexed(locationFile->isIndexed()); + QtCodeFile* file = getFile(params.locationFile->getFilePath()); + file->setWholeFile(params.locationFile->isWhole(), params.referenceCount); + file->setModificationTime(params.modificationTime); + file->setIsComplete(params.locationFile->isComplete()); + file->setIsIndexed(params.locationFile->isIndexed()); + + if (params.isMinimized) + { + file->setMinimized(); + } + else + { + bool same = true; + const std::vector snippets = file->getSnippets(); + if (params.snippetParams.size() != snippets.size()) + { + same = false; + } + else + { + for (size_t i = 0; i < snippets.size(); i++) + { + if (params.snippetParams[i].startLineNumber != snippets[i]->getStartLineNumber() || + params.snippetParams[i].endLineNumber != snippets[i]->getEndLineNumber()) + { + same = false; + break; + } + } + } + + if (!same) + { + file->clearSnippets(); + + for (const CodeSnippetParams& snippetParams : params.snippetParams) + { + file->addCodeSnippet(snippetParams); + } + } + + file->setSnippets(); + } } QScrollArea* QtCodeFileList::getScrollArea() @@ -129,47 +167,36 @@ QScrollArea* QtCodeFileList::getScrollArea() return m_scrollArea; } -void QtCodeFileList::addCodeSnippet(const CodeSnippetParams& params) +void QtCodeFileList::updateSourceLocations(const CodeSnippetParams& params) { QtCodeFile* file = getFile(params.locationFile->getFilePath()); - - if (params.insertSnippet) + if (file) { - file->insertCodeSnippet(params); + file->updateSourceLocations(params); } - else +} + +void QtCodeFileList::updateFiles() +{ + for (QtCodeFile* file : m_files) { - file->addCodeSnippet(params); + file->setProperty("last", file == m_files.back()); + file->updateContent(); + file->updateTitleBar(); + file->show(); } - file->setModificationTime(params.modificationTime); - file->setIsComplete(params.locationFile->isComplete()); - file->setIsIndexed(params.locationFile->isIndexed()); + // Perform delayed so all widgets are already visible + QTimer::singleShot(100, this, &QtCodeFileList::updateSnippetTitleAndScrollBarSlot); } -void QtCodeFileList::updateCodeSnippet(const CodeSnippetParams& params) -{ - QtCodeFile* file = getFile(params.locationFile->getFilePath()); - file->updateCodeSnippet(params); -} - -void QtCodeFileList::requestFileContent(const FilePath& filePath) -{ - getFile(filePath)->requestContent(); -} - -bool QtCodeFileList::requestScroll(const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, ScrollTarget target) +void QtCodeFileList::scrollTo( + const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, CodeScrollParams::Target target) { QtCodeFile* file = getFile(filePath); if (!file) { - return true; - } - - if (file->isCollapsed()) - { - file->requestContent(); - return false; + return; } QtCodeSnippet* snippet = nullptr; @@ -187,16 +214,10 @@ bool QtCodeFileList::requestScroll(const FilePath& filePath, size_t lineNumber, snippet = file->getSnippetForLine(1); } - if (!snippet) + if (!snippet || !snippet->isVisible()) { ensureWidgetVisibleAnimated(m_filesArea, file->getTitleBar(), QRect(), animated, target); - return true; - } - - if (!snippet->isVisible()) - { - file->setSnippets(); - return true; + return; } size_t endLineNumber = 0; @@ -228,29 +249,6 @@ bool QtCodeFileList::requestScroll(const FilePath& filePath, size_t lineNumber, ensureWidgetVisibleAnimated(m_filesArea, snippet, lineRect, animated, target); snippet->ensureLocationIdVisible(locationId, animated); - - return true; -} - -void QtCodeFileList::updateFiles() -{ - for (QtCodeFile* file : m_files) - { - file->setProperty("last", file == m_files.back()); - file->updateContent(); - } - - // Perform delayed so all widgets are already visible - QTimer::singleShot(100, this, &QtCodeFileList::updateSnippetTitleAndScrollBarSlot); -} - -void QtCodeFileList::showContents() -{ - for (QtCodeFile* file : m_files) - { - file->updateTitleBar(); - file->show(); - } } void QtCodeFileList::onWindowFocus() @@ -274,67 +272,6 @@ void QtCodeFileList::findScreenMatches(const std::wstring& query, std::vector> QtCodeFileList::getLocationIdsForTokenIds(const std::set& tokenIds) const -{ - std::vector> locationIds; - for (QtCodeFile* file : m_files) - { - utility::append(locationIds, file->getLocationIdsForTokenIds(tokenIds)); - } - return locationIds; -} - -void QtCodeFileList::setFileMinimized(const FilePath path) -{ - if (path.empty()) - { - if (m_files.size()) - { - m_files[0]->setMinimized(); - } - } - else - { - QtCodeFile* file = getFile(path); - file->setMinimized(); - - if (m_firstSnippetTitleBar->isVisible()) - { - ensureWidgetVisibleAnimated(m_filesArea, file->getTitleBar(), QRect(), false, SCROLL_TOP); - } - } -} - -void QtCodeFileList::setFileSnippets(const FilePath path) -{ - if (path.empty()) - { - if (m_files.size()) - { - m_files[0]->setSnippets(); - } - } - else - { - getFile(path)->setSnippets(); - } -} - -void QtCodeFileList::setFileMaximized(const FilePath path) -{ - if (path.empty()) - { - if (m_files.size()) - { - m_files[0]->setMaximized(); - } - } - else - { - getFile(path)->setMaximized(); - } -} - void QtCodeFileList::maximizeFirstFile() { if (m_files.size()) @@ -347,11 +284,6 @@ std::pair QtCodeFileList::getFirstFileWithActiveLocationId() co { for (QtCodeFile* file : m_files) { - if (file->isCollapsed()) - { - continue; - } - std::pair snippet = file->getFirstSnippetWithActiveLocationId(0); if (snippet.first != nullptr) { @@ -368,11 +300,6 @@ std::pair QtCodeFileList::getFirstSnippetWithActiveLocationI for (QtCodeFile* file : m_files) { - if (file->isCollapsed()) - { - continue; - } - result = file->getFirstSnippetWithActiveLocationId(tokenId); if (result.first != nullptr) { diff --git a/src/lib_gui/qt/element/code/QtCodeFileList.h b/src/lib_gui/qt/element/code/QtCodeFileList.h index 754d975b..ec686e94 100644 --- a/src/lib_gui/qt/element/code/QtCodeFileList.h +++ b/src/lib_gui/qt/element/code/QtCodeFileList.h @@ -29,30 +29,21 @@ public: void clearSnippetTitleAndScrollBar(); QtCodeFile* getFile(const FilePath filePath); - void addFile(std::shared_ptr locationFile, int refCount, TimeStamp modificationTime); + + void addFile(const CodeFileParams& params); // QtCodeNaviatebale implementation QScrollArea* getScrollArea() override; - void addCodeSnippet(const CodeSnippetParams& params) override; - void updateCodeSnippet(const CodeSnippetParams& params) override; - - void requestFileContent(const FilePath& filePath) override; - bool requestScroll(const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, ScrollTarget target) override; - + void updateSourceLocations(const CodeSnippetParams& params) override; void updateFiles() override; - void showContents() override; + + void scrollTo(const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, CodeScrollParams::Target target) override; void onWindowFocus() override; void findScreenMatches(const std::wstring& query, std::vector>* screenMatches) override; - std::vector> getLocationIdsForTokenIds(const std::set& tokenIds) const override; - - void setFileMinimized(const FilePath path); - void setFileSnippets(const FilePath path); - void setFileMaximized(const FilePath path); - void maximizeFirstFile(); std::pair getFirstFileWithActiveLocationId() const; @@ -64,6 +55,7 @@ protected: private slots: void updateSnippetTitleAndScrollBarSlot(); void updateSnippetTitleAndScrollBar(int value = 0); + void scrollLastSnippet(int value); void scrollLastSnippetScrollBar(int value); diff --git a/src/lib_gui/qt/element/code/QtCodeFileSingle.cpp b/src/lib_gui/qt/element/code/QtCodeFileSingle.cpp index 6f717348..b4731c72 100644 --- a/src/lib_gui/qt/element/code/QtCodeFileSingle.cpp +++ b/src/lib_gui/qt/element/code/QtCodeFileSingle.cpp @@ -9,7 +9,6 @@ #include "FilePath.h" #include "logging.h" #include "MessageChangeFileView.h" - #include "SourceLocationFile.h" #include "QtCodeArea.h" #include "QtCodeFileTitleBar.h" @@ -20,8 +19,6 @@ QtCodeFileSingle::QtCodeFileSingle(QtCodeNavigator* navigator, QWidget* parent) : m_navigator(navigator) , m_area(nullptr) - , m_contentRequested(false) - , m_scrollRequested(false) { setObjectName("code_container"); @@ -44,11 +41,6 @@ QtCodeFileSingle::QtCodeFileSingle(QtCodeNavigator* navigator, QWidget* parent) layout()->addWidget(m_areaWrapper); } -QAbstractScrollArea* QtCodeFileSingle::getScrollArea() -{ - return m_area; -} - void QtCodeFileSingle::clearFile() { setFileData(FileData()); @@ -65,110 +57,115 @@ void QtCodeFileSingle::clearCache() m_fileDatas.clear(); m_filePaths.clear(); + + m_lastLocationFile.reset(); } -void QtCodeFileSingle::addCodeSnippet(const CodeSnippetParams& params) +bool QtCodeFileSingle::addFile(const CodeFileParams& params, bool useSingleFileCache) { - if (!params.locationFile->isWhole()) + if (!params.fileParams) { - LOG_ERROR("Snippet params passed are not for whole file."); - return; - } - - FileData file = getFileData(params.locationFile->getFilePath()); - if (file.area) - { - setFileData(file); - return; - } - - file.filePath = params.locationFile->getFilePath(); - file.modificationTime = params.modificationTime; - file.isComplete = params.locationFile->isComplete(); - file.isIndexed = params.locationFile->isIndexed(); - - if (params.reduced) - { - file.title = params.title; - } - - file.area = new QtCodeArea(1, params.code, params.locationFile, m_navigator, !params.reduced, this); - connect(file.area->verticalScrollBar(), &QScrollBar::valueChanged, m_navigator, &QtCodeNavigator::scrolled); - - m_fileDatas.emplace(file.filePath, file); - m_filePaths.push_back(file.filePath); - - setFileData(file); - - m_contentRequested = false; - - if (m_filePaths.size() > 100) - { - FilePath toDelete = m_filePaths.front(); - m_filePaths.pop_front(); - - auto it = m_fileDatas.find(toDelete); - if (it != m_fileDatas.end()) - { - it->second.area->deleteLater(); - m_fileDatas.erase(it); - } - } -} - -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) - { - return; - } - - FileData file = getFileData(filePath); - if (file.area) - { - setFileData(file); - return; - } - - m_contentRequested = true; - - MessageChangeFileView msg( - filePath, - MessageChangeFileView::FILE_MAXIMIZED, - MessageChangeFileView::VIEW_SINGLE, - true, - m_navigator->hasErrors() - ); - msg.setSchedulerId(m_navigator->getSchedulerId()); - msg.dispatch(); -} - -bool QtCodeFileSingle::requestScroll( - const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, ScrollTarget target) -{ - FileData file = getFileData(filePath); - if (file.area) - { - setFileData(file); - } - else - { - requestFileContent(filePath); + LOG_ERROR("File params have missing information."); return false; } - if (!m_scrollRequested) + std::shared_ptr locationFile = params.fileParams->locationFile; + + FileData file = useSingleFileCache ? getFileData(locationFile->getFilePath()) : FileData(); + if (file.area) { - animated = false; + if (file.area == m_area) + { + return false; + } + + setFileData(file); + return true; + } + + if (!locationFile->isWhole()) + { + LOG_ERROR("Snippet params passed are not for whole file."); + return false; + } + + // prevent non cached file from being created again when currently displayed + if (locationFile == m_lastLocationFile && locationFile->getFilePath() == m_currentFilePath) + { + return false; + } + m_lastLocationFile = locationFile; + + file.filePath = locationFile->getFilePath(); + file.isComplete = locationFile->isComplete(); + file.isIndexed = locationFile->isIndexed(); + file.modificationTime = params.modificationTime; + + if (params.fileParams->isOverview) + { + file.title = params.fileParams->title; + } + + file.area = new QtCodeArea(1, params.fileParams->code, locationFile, m_navigator, !params.fileParams->isOverview, this); + connect(file.area->verticalScrollBar(), &QScrollBar::valueChanged, m_navigator, &QtCodeNavigator::scrolled); + + setFileData(file); + updateRefCount(params.referenceCount); + + if (useSingleFileCache) + { + m_fileDatas.emplace(file.filePath, file); + m_filePaths.push_back(file.filePath); + + if (m_filePaths.size() > 100) + { + // TODO: don't delete files that were added multiple times + FilePath toDelete = m_filePaths.front(); + m_filePaths.pop_front(); + + auto it = m_fileDatas.find(toDelete); + if (it != m_fileDatas.end()) + { + it->second.area->deleteLater(); + m_fileDatas.erase(it); + } + } + } + + return true; +} + +QAbstractScrollArea* QtCodeFileSingle::getScrollArea() +{ + return m_area; +} + +void QtCodeFileSingle::updateSourceLocations(const CodeSnippetParams& params) +{ + if (m_currentFilePath == params.locationFile->getFilePath()) + { + m_area->updateSourceLocations(params.locationFile); + } +} + +void QtCodeFileSingle::updateFiles() +{ + if (m_area) + { + m_area->updateContent(); + m_area->show(); + + // Resizes the area to fix a bug where the area could be scrolled below the last line. + m_area->updateGeometry(); + } +} + +void QtCodeFileSingle::scrollTo( + const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, CodeScrollParams::Target target) +{ + if (m_currentFilePath != filePath) + { + return; } size_t endLineNumber = 0; @@ -196,30 +193,6 @@ bool QtCodeFileSingle::requestScroll( ensurePercentVisibleAnimated(percentA, percentB, animated, target); m_area->ensureLocationIdVisible(locationId, width(), animated); - - m_scrollRequested = true; - - return true; -} - -void QtCodeFileSingle::updateFiles() -{ - if (m_area) - { - m_area->updateContent(); - } -} - -void QtCodeFileSingle::showContents() -{ - if (m_area) - { - m_area->show(); - updateRefCount(m_area->getActiveLocationCount()); - - // Resizes the area to fix a bug where the area could be scrolled below the last line. - m_area->updateGeometry(); - } } void QtCodeFileSingle::onWindowFocus() @@ -235,21 +208,6 @@ void QtCodeFileSingle::findScreenMatches(const std::wstring& query, std::vector< } } -std::vector> QtCodeFileSingle::getLocationIdsForTokenIds(const std::set& tokenIds) const -{ - if (m_area) - { - std::vector> locationIds; - for (Id locationId : m_area->getLocationIdsForTokenIds(tokenIds)) - { - locationIds.push_back(std::make_pair(getCurrentFilePath(), locationId)); - } - return locationIds; - } - - return { }; -} - const FilePath& QtCodeFileSingle::getCurrentFilePath() const { return m_currentFilePath; @@ -278,14 +236,13 @@ Id QtCodeFileSingle::getLocationIdOfFirstActiveLocationOfTokenId(Id tokenId) con void QtCodeFileSingle::clickedSnippetButton() { - m_navigator->requestScroll(m_currentFilePath, 0, 0, false, QtCodeNavigateable::SCROLL_TOP); + m_navigator->setMode(QtCodeNavigator::MODE_LIST); MessageChangeFileView( m_currentFilePath, MessageChangeFileView::FILE_SNIPPETS, MessageChangeFileView::VIEW_LIST, - true, // TODO: check if data is really needed - m_navigator->hasErrors(), + CodeScrollParams::toFile(m_currentFilePath, CodeScrollParams::Target::TOP), true ).dispatch(); } @@ -350,8 +307,6 @@ void QtCodeFileSingle::setFileData(const FileData& file) // Resizes the area to fix a bug where the area could be scrolled below the last line. m_area->updateGeometry(); - - m_scrollRequested = false; } else { diff --git a/src/lib_gui/qt/element/code/QtCodeFileSingle.h b/src/lib_gui/qt/element/code/QtCodeFileSingle.h index 48fd55fe..db70fdea 100644 --- a/src/lib_gui/qt/element/code/QtCodeFileSingle.h +++ b/src/lib_gui/qt/element/code/QtCodeFileSingle.h @@ -30,26 +30,21 @@ public: void clearFile(); void clearCache(); + bool addFile(const CodeFileParams& params, bool useSingleFileCache); + // QtCodeNavigateable implementation QAbstractScrollArea* getScrollArea() override; - void addCodeSnippet(const CodeSnippetParams& params) override; - void updateCodeSnippet(const CodeSnippetParams& params) override; - - void requestFileContent(const FilePath& filePath) override; - bool requestScroll( - const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, ScrollTarget target) override; - + void updateSourceLocations(const CodeSnippetParams& params) override; void updateFiles() override; - void showContents() override; + + void scrollTo(const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, CodeScrollParams::Target target) override; void onWindowFocus() override; void findScreenMatches( const std::wstring& query, std::vector>* screenMatches) override; - std::vector> getLocationIdsForTokenIds(const std::set& tokenIds) const override; - const FilePath& getCurrentFilePath() const; bool hasFileCached(const FilePath& filePath) const; @@ -86,8 +81,7 @@ private: std::map m_fileDatas; std::deque m_filePaths; - bool m_contentRequested; - bool m_scrollRequested; + std::shared_ptr m_lastLocationFile; }; #endif // QT_CODE_FILE_SINGLE_H diff --git a/src/lib_gui/qt/element/code/QtCodeNavigateable.cpp b/src/lib_gui/qt/element/code/QtCodeNavigateable.cpp index 99f8628a..0387e1d8 100644 --- a/src/lib_gui/qt/element/code/QtCodeNavigateable.cpp +++ b/src/lib_gui/qt/element/code/QtCodeNavigateable.cpp @@ -11,7 +11,7 @@ QtCodeNavigateable::~QtCodeNavigateable() } void QtCodeNavigateable::ensureWidgetVisibleAnimated( - const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, ScrollTarget target) + const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, CodeScrollParams::Target target) { QAbstractScrollArea* area = getScrollArea(); if (!area || !parentWidget->isAncestorOf(childWidget)) @@ -36,19 +36,28 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated( // scroll to top if widget is bigger than view if (focusRect.height() > visibleRect.height()) { - target = SCROLL_TOP; + target = CodeScrollParams::Target::TOP; } int value = 0; switch (target) { - case SCROLL_VISIBLE: + case CodeScrollParams::Target::VISIBLE: if (focusRect.top() > visibleRect.top() && focusRect.bottom() < visibleRect.bottom()) { return; } + else if (focusRect.top() < visibleRect.top()) + { + value = focusRect.top() - visibleRect.top() - 50; + } + else + { + value = focusRect.bottom() - visibleRect.bottom() + 50; + } + break; - case SCROLL_CENTER: + case CodeScrollParams::Target::CENTER: value = focusRect.center().y() - visibleRect.center().y(); if (abs(value) < 50) { @@ -56,8 +65,12 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated( } break; - case SCROLL_TOP: + case CodeScrollParams::Target::TOP: value = focusRect.top() - visibleRect.top() - 50; + if (value > 0 && value < 150) + { + value = 0; + } break; } @@ -80,7 +93,8 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated( } } -void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, ScrollTarget target) +void QtCodeNavigateable::ensurePercentVisibleAnimated( + double percentA, double percentB, bool animated, CodeScrollParams::Target target) { QAbstractScrollArea* area = getScrollArea(); if (!area) @@ -105,18 +119,18 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe if (rectHeight > visibleHeight) { - target = SCROLL_TOP; + target = CodeScrollParams::Target::TOP; } switch (target) { - case SCROLL_VISIBLE: + case CodeScrollParams::Target::VISIBLE: if (scrollY > visibleY && scrollY + rectHeight < visibleY + scrollableHeight) { return; } - case SCROLL_CENTER: + case CodeScrollParams::Target::CENTER: if (rectHeight < visibleHeight / 2) { scrollY -= visibleHeight / 4; @@ -127,8 +141,8 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe } break; - case SCROLL_TOP: - scrollY -= 20; + case CodeScrollParams::Target::TOP: + scrollY -= 100; break; } diff --git a/src/lib_gui/qt/element/code/QtCodeNavigateable.h b/src/lib_gui/qt/element/code/QtCodeNavigateable.h index a59908da..0b30d795 100644 --- a/src/lib_gui/qt/element/code/QtCodeNavigateable.h +++ b/src/lib_gui/qt/element/code/QtCodeNavigateable.h @@ -3,9 +3,9 @@ #include -#include "types.h" - +#include "CodeScrollParams.h" #include "CodeSnippetParams.h" +#include "types.h" class FilePath; class QRectF; @@ -17,35 +17,24 @@ class QWidget; class QtCodeNavigateable { public: - enum ScrollTarget - { - SCROLL_VISIBLE, - SCROLL_CENTER, - SCROLL_TOP - }; - virtual ~QtCodeNavigateable(); 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, size_t lineNumber, Id locationId, bool animated, ScrollTarget target) = 0; - + virtual void updateSourceLocations(const CodeSnippetParams& params) = 0; virtual void updateFiles() = 0; - virtual void showContents() = 0; + + virtual void scrollTo( + const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, CodeScrollParams::Target target) = 0; virtual void onWindowFocus() = 0; virtual void findScreenMatches(const std::wstring& query, std::vector>* screenMatches) = 0; - virtual std::vector> getLocationIdsForTokenIds(const std::set& tokenIds) const = 0; - protected: - void ensureWidgetVisibleAnimated(const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, ScrollTarget target); - void ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, ScrollTarget target); + void ensureWidgetVisibleAnimated( + const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, CodeScrollParams::Target target); + void ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, CodeScrollParams::Target target); QRect getFocusRectForWidget(const QWidget* childWidget, const QWidget* parentWidget) const; }; diff --git a/src/lib_gui/qt/element/code/QtCodeNavigator.cpp b/src/lib_gui/qt/element/code/QtCodeNavigator.cpp index 79736f6f..021b09d7 100644 --- a/src/lib_gui/qt/element/code/QtCodeNavigator.cpp +++ b/src/lib_gui/qt/element/code/QtCodeNavigator.cpp @@ -7,33 +7,28 @@ #include #include +#include "ApplicationSettings.h" #include "logging.h" -#include "MessageShowError.h" +#include "MessageCodeReference.h" #include "MessageScrollCode.h" -#include "ResourcePaths.h" -#include "TabId.h" -#include "utility.h" - -#include "SourceLocation.h" -#include "SourceLocationCollection.h" -#include "SourceLocationFile.h" +#include "MessageShowError.h" #include "QtCodeArea.h" #include "QtCodeFile.h" #include "QtCodeSnippet.h" #include "QtSearchBarButton.h" +#include "ResourcePaths.h" +#include "SourceLocation.h" +#include "SourceLocationCollection.h" +#include "SourceLocationFile.h" +#include "TabId.h" +#include "utility.h" #include "utilityQt.h" -#include "ApplicationSettings.h" QtCodeNavigator::QtCodeNavigator(QWidget* parent) : QWidget(parent) , m_mode(MODE_NONE) , m_oldMode(MODE_NONE) , m_schedulerId(TabId::ignore()) - , m_activeTokenId(0) - , m_value(0) - , m_refIndex(0) - , m_singleHasNewFile(false) - , m_useSingleFileCache(false) { QVBoxLayout* layout = new QVBoxLayout(); layout->setSpacing(0); @@ -50,40 +45,23 @@ QtCodeNavigator::QtCodeNavigator(QWidget* parent) navLayout->setContentsMargins(7, 7, 7, 6); { - m_prevFileButton = - new QtSearchBarButton(ResourcePaths::getGuiPath().concatenate(L"code_view/images/arrow_left.png"), true); - m_nextFileButton = - new QtSearchBarButton(ResourcePaths::getGuiPath().concatenate(L"code_view/images/arrow_right.png"), true); m_prevReferenceButton = new QtSearchBarButton(ResourcePaths::getGuiPath().concatenate(L"code_view/images/arrow_up.png"), true); m_nextReferenceButton = new QtSearchBarButton(ResourcePaths::getGuiPath().concatenate(L"code_view/images/arrow_down.png"), true); - m_prevFileButton->setObjectName("file_button_previous"); - m_nextFileButton->setObjectName("file_button_next"); m_prevReferenceButton->setObjectName("reference_button_previous"); m_nextReferenceButton->setObjectName("reference_button_next"); - m_prevFileButton->setToolTip("previous file"); - m_nextFileButton->setToolTip("next file"); m_prevReferenceButton->setToolTip("previous reference"); m_nextReferenceButton->setToolTip("next reference"); - m_prevFileButton->setIconSize(QSize(12, 12)); - m_nextFileButton->setIconSize(QSize(12, 12)); m_prevReferenceButton->setIconSize(QSize(12, 12)); m_nextReferenceButton->setIconSize(QSize(12, 12)); - m_prevFileButton->hide(); - m_nextFileButton->hide(); - - navLayout->addWidget(m_prevFileButton); navLayout->addWidget(m_prevReferenceButton); navLayout->addWidget(m_nextReferenceButton); - navLayout->addWidget(m_nextFileButton); - connect(m_prevFileButton, &QPushButton::clicked, this, &QtCodeNavigator::previousFile); - connect(m_nextFileButton, &QPushButton::clicked, this, &QtCodeNavigator::nextFile); connect(m_prevReferenceButton, &QPushButton::clicked, this, &QtCodeNavigator::previousReference); connect(m_nextReferenceButton, &QPushButton::clicked, this, &QtCodeNavigator::nextReference); @@ -175,121 +153,69 @@ QtCodeNavigator::QtCodeNavigator(QWidget* parent) layout->addWidget(m_single); setMode(ApplicationSettings::getInstance()->getCodeViewModeSingle() ? MODE_SINGLE : MODE_LIST); - showContents(); - - connect(this, &QtCodeNavigator::scrollRequest, this, &QtCodeNavigator::handleScrollRequest, Qt::QueuedConnection); + updateFiles(); } QtCodeNavigator::~QtCodeNavigator() { } -void QtCodeNavigator::addCodeSnippet(const CodeSnippetParams& params) +void QtCodeNavigator::addSnippetFile(const CodeFileParams& params) { - FilePath currentPath = m_single->getCurrentFilePath(); + m_list->addFile(params); +} - if (params.reduced) +bool QtCodeNavigator::addSingleFile(const CodeFileParams& params, bool useSingleFileCache) +{ + return m_single->addFile(params, useSingleFileCache); +} + +void QtCodeNavigator::updateSourceLocations(const CodeSnippetParams& params) +{ + m_current->updateSourceLocations(params); +} + +void QtCodeNavigator::updateReferenceCount( + size_t referenceCount, size_t referenceIndex, size_t localReferenceCount, size_t localReferenceIndex) +{ + if (referenceIndex != referenceCount) { - m_list->addCodeSnippet(params); - m_single->addCodeSnippet(params); + m_refLabel->setText(QString::number(referenceIndex + 1) + "/" + QString::number(referenceCount) + " references"); } else { - m_current->addCodeSnippet(params); + m_refLabel->setText(QString::number(referenceCount) + " references"); } - if (currentPath != m_single->getCurrentFilePath()) + m_refLabel->setMinimumWidth( + m_refLabel->fontMetrics().width(QString(QString::number(referenceCount).size() * 2, 'a') + "/ references") + 30); + + m_prevReferenceButton->setEnabled(referenceCount > 1); + m_nextReferenceButton->setEnabled(referenceCount > 1); + + + if (localReferenceIndex != localReferenceCount) { - m_singleHasNewFile = true; - } - - // refresh local reference count when visible code changes - if (m_localReferences.size() && m_localReferences[0].locationType == LOCATION_LOCAL_SYMBOL) - { - setActiveLocalTokenIds(utility::toVector(m_activeLocalTokenIds), LOCATION_LOCAL_SYMBOL); - } -} - -void QtCodeNavigator::updateCodeSnippet(const CodeSnippetParams& params) -{ - m_current->updateCodeSnippet(params); -} - -void QtCodeNavigator::addFile(std::shared_ptr locationFile, int refCount, TimeStamp modificationTime) -{ - m_list->addFile(locationFile, refCount, modificationTime); - - if (locationFile->isWhole()) - { - Reference ref; - ref.filePath = locationFile->getFilePath(); - m_references.push_back(ref); + m_localRefLabel->setText(QString::number(localReferenceIndex + 1) + "/" + QString::number(localReferenceCount) + " local references"); } else { - locationFile->forEachStartSourceLocation( - [&](SourceLocation* location) - { - if (location->isScopeLocation() || location->getType() == LOCATION_SIGNATURE || - location->getType() == LOCATION_COMMENT || location->getType() == LOCATION_QUALIFIER) - { - return; - } - - if (!location->getTokenIds().size()) - { - Reference ref; - ref.filePath = location->getFilePath(); - ref.tokenId = 0; - ref.locationId = location->getLocationId(); - ref.locationType = location->getType(); - - m_references.push_back(ref); - return; - } - - for (Id i : location->getTokenIds()) - { - Reference ref; - ref.filePath = location->getFilePath(); - ref.tokenId = i; - ref.locationId = location->getLocationId(); - ref.locationType = location->getType(); - - m_references.push_back(ref); - } - } - ); - } -} - -void QtCodeNavigator::addedFiles() -{ - if (m_mode == MODE_SINGLE && m_references.size()) - { - if (!m_refIndex || !m_activeReference.tokenId) - { - m_single->requestFileContent(m_references.front().filePath); - } + m_localRefLabel->setText(QString::number(localReferenceCount) + " local references"); } - if (m_refIndex == 0) - { - updateRefLabels(); - } + m_localRefLabel->setMinimumWidth( + m_localRefLabel->fontMetrics().width(QString(QString::number(localReferenceCount).size() * 2, 'a') + "/ local references") + 30); + + m_nextLocalReferenceButton->setVisible(localReferenceCount > 1); + m_prevLocalReferenceButton->setVisible(localReferenceCount > 1); + m_localRefLabel->setVisible(localReferenceCount > 1); } void QtCodeNavigator::clear() { - clearCodeSnippets(false); - clearCaches(); - - updateRefLabels(); -} - -void QtCodeNavigator::clearCodeSnippets(bool useSingleFileCache) -{ - m_list->clear(); + clearSnippets(); + clearFile(); + clearCache(); m_currentActiveTokenIds.clear(); m_activeTokenIds.clear(); @@ -297,31 +223,22 @@ void QtCodeNavigator::clearCodeSnippets(bool useSingleFileCache) m_focusedTokenIds.clear(); m_errorInfos.clear(); - m_activeTokenId = 0; - - if (!m_useSingleFileCache || !useSingleFileCache) - { - clearCaches(); - } - m_useSingleFileCache = useSingleFileCache; - - m_references.clear(); - m_activeReference = Reference(); - m_refIndex = 0; - - m_singleHasNewFile = false; + updateReferenceCount(0, 0, 0, 0); +} +void QtCodeNavigator::clearSnippets() +{ clearScreenMatches(); + m_list->clear(); } void QtCodeNavigator::clearFile() { + clearScreenMatches(); m_single->clearFile(); - - updateRefLabels(); } -void QtCodeNavigator::clearCaches() +void QtCodeNavigator::clearCache() { m_single->clearCache(); } @@ -400,7 +317,6 @@ void QtCodeNavigator::setActiveTokenIds(const std::vector& activeTokenIds) setCurrentActiveTokenIds(activeTokenIds); m_activeTokenIds = std::set(activeTokenIds.begin(), activeTokenIds.end()); - m_activeTokenId = activeTokenIds.size() ? activeTokenIds[0] : 0; } const std::set& QtCodeNavigator::getActiveLocalTokenIds() const @@ -410,26 +326,9 @@ const std::set& QtCodeNavigator::getActiveLocalTokenIds() const void QtCodeNavigator::setActiveLocalTokenIds(const std::vector& activeLocalTokenIds, LocationType locationType) { - setCurrentActiveTokenIds(locationType == LOCATION_TOKEN ? activeLocalTokenIds : std::vector()); setCurrentActiveLocalLocationIds({ }); - m_activeLocalTokenIds.clear(); - m_activeLocalTokenIds.insert(activeLocalTokenIds.begin(), activeLocalTokenIds.end()); - - m_localReferences.clear(); - m_localRefIndex = 0; - - if (m_activeLocalTokenIds.size()) - { - for (std::pair p : m_current->getLocationIdsForTokenIds(m_activeLocalTokenIds)) - { - Reference ref; - ref.filePath = p.first; - ref.locationId = p.second; - ref.locationType = locationType; - m_localReferences.push_back(ref); - } - } + m_activeLocalTokenIds = std::set(activeLocalTokenIds.begin(), activeLocalTokenIds.end()); } const std::set& QtCodeNavigator::getFocusedTokenIds() const @@ -490,116 +389,7 @@ bool QtCodeNavigator::isInListMode() const bool QtCodeNavigator::hasSingleFileCached(const FilePath& filePath) const { - return m_useSingleFileCache && m_single->hasFileCached(filePath); -} - -void QtCodeNavigator::showActiveSnippet( - const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo) -{ - if (activeTokenIds.size() != 1) - { - LOG_ERROR("Number of requested token ids to show is not 1."); - return; - } - - m_activeReference = Reference(); - Id tokenId = activeTokenIds[0]; - - // iterate local references when same tokenId get reactivated (consecutive edge clicks) - if (m_activeLocalTokenIds.size() == 1 && *m_activeLocalTokenIds.begin() == tokenId && m_localReferences.size()) - { - nextLocalReference(); - return; - } - - std::vector locationIds; - size_t refIndex = 0; - Reference firstReference; - - std::map filePathOrder; - - for (size_t i = 0; i < m_references.size(); i++) - { - const Reference& ref = m_references[i]; - if (ref.tokenId == tokenId) - { - locationIds.push_back(ref.locationId); - - if (!firstReference.tokenId) - { - firstReference = ref; - refIndex = i + 1; - } - } - - filePathOrder.emplace(ref.filePath, filePathOrder.size()); - } - - std::set filePathsToExpand; - if (!locationIds.size()) - { - collection->forEachSourceLocation( - [&](SourceLocation* location) - { - bool foundId = false; - for (Id i : location->getTokenIds()) - { - if (i == tokenId) - { - foundId = true; - break; - } - } - - if (!foundId) - { - return; - } - - locationIds.push_back(location->getLocationId()); - filePathsToExpand.insert(location->getFilePath()); - - if (!firstReference.tokenId || filePathOrder[location->getFilePath()] < filePathOrder[firstReference.filePath]) - { - firstReference.tokenId = tokenId; - firstReference.locationId = location->getLocationId(); - firstReference.filePath = location->getFilePath(); - } - } - ); - } - - if (m_mode == MODE_LIST) - { - for (const FilePath& filePath : filePathsToExpand) - { - m_list->requestFileContent(filePath); - } - } - else if (firstReference.tokenId) - { - m_single->requestFileContent(firstReference.filePath); - } - - setActiveLocalTokenIds({ tokenId }, LOCATION_TOKEN); - updateFiles(); - - if (firstReference.tokenId) - { - if (scrollTo) - { - requestScroll(firstReference.filePath, 0, firstReference.locationId, true, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - } - - m_refIndex = refIndex; - updateRefLabels(); - - if (!refIndex) - { - m_activeReference = firstReference; - } - } + return m_single->hasFileCached(filePath); } void QtCodeNavigator::focusTokenIds(const std::vector& focusedTokenIds) @@ -610,42 +400,14 @@ void QtCodeNavigator::focusTokenIds(const std::vector& focusedTokenIds) void QtCodeNavigator::defocusTokenIds() { - setFocusedTokenIds(std::vector()); + setFocusedTokenIds({ }); updateFiles(); } -void QtCodeNavigator::setFileMinimized(const FilePath path) -{ - if (m_mode == MODE_LIST) - { - m_list->setFileMinimized(path); - } -} - -void QtCodeNavigator::setFileSnippets(const FilePath path) -{ - if (m_mode == MODE_LIST) - { - m_list->setFileSnippets(path); - } -} - -void QtCodeNavigator::setFileMaximized(const FilePath path) -{ - if (m_mode == MODE_LIST) - { - m_list->setFileMaximized(path); - } -} - void QtCodeNavigator::updateFiles() { m_current->updateFiles(); - updateRefLabels(); -} -void QtCodeNavigator::showContents() -{ if (m_oldMode != m_mode) { m_listButton->setChecked(m_mode == MODE_LIST); @@ -675,15 +437,6 @@ void QtCodeNavigator::showContents() m_oldMode = m_mode; } - - m_current->showContents(); - - // look for local references again, in case file content was not present when local symbols were activated - if (m_activeLocalTokenIds.size() && !m_localReferences.size()) - { - setActiveLocalTokenIds(utility::toVector(m_activeLocalTokenIds), LOCATION_TOKEN); - updateRefLabels(); - } } size_t QtCodeNavigator::findScreenMatches(const std::wstring& query) @@ -707,9 +460,8 @@ void QtCodeNavigator::activateScreenMatch(size_t matchIndex) m_currentActiveLocationIds.insert(m_activeScreenMatchId); p.first->updateContent(); - requestScroll( - p.first->getSourceLocationFile()->getFilePath(), 0, m_activeScreenMatchId, true, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); + scrollTo(CodeScrollParams::toReference( + p.first->getSourceLocationFile()->getFilePath(),m_activeScreenMatchId, CodeScrollParams::Target::CENTER), true); } void QtCodeNavigator::deactivateScreenMatch(size_t matchIndex) @@ -746,146 +498,63 @@ void QtCodeNavigator::clearScreenMatches() m_screenMatches.clear(); } -void QtCodeNavigator::scrollToValue(int value, bool inListMode) +void QtCodeNavigator::scrollTo(const CodeScrollParams& params, bool animated) { - if ((m_mode == MODE_LIST) == inListMode) + if (!isVisible()) { - m_value = value; - QTimer::singleShot(100, this, &QtCodeNavigator::setValue); - m_scrollRequest = ScrollRequest(); - } -} - -void QtCodeNavigator::scrollToLine(const FilePath& filePath, unsigned int line) -{ - requestScroll(filePath, line, 0, false, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); -} - -void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReference) -{ - if (ignoreActiveReference) - { - m_activeReference = Reference(); - m_refIndex = 0; - updateRefLabels(); + m_scrollParams = params; + return; } - if (m_activeReference.tokenId) + std::function func = [=](){}; + + switch (params.type) { - if (m_mode == MODE_LIST) + case CodeScrollParams::Type::TO_REFERENCE: + func = [=]() { - m_list->requestFileContent(m_activeReference.filePath); - } - - requestScroll(m_activeReference.filePath, 0, m_activeReference.locationId, true, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - - updateRefLabels(); - return; - } - - if (m_refIndex != 0) - { - showCurrentReference(false); - return; - } - - if (!m_activeTokenId) - { - if (m_references.size() && m_references.front().locationType != LOCATION_TOKEN) + m_current->scrollTo(params.filePath, 0, params.locationId, animated, params.target); + }; + break; + case CodeScrollParams::Type::TO_FILE: + func = [=]() { - requestScroll( - m_references.front().filePath, 0, m_references.front().locationId, false, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); + m_current->scrollTo(params.filePath, 0, 0, animated, params.target); + }; + break; + case CodeScrollParams::Type::TO_LINE: + func = [=]() + { + m_current->scrollTo(params.filePath, params.line, 0, animated, params.target); + }; + break; + case CodeScrollParams::Type::TO_VALUE: + if ((m_mode == MODE_LIST) == params.inListMode) + { + func = [=]() + { + QAbstractScrollArea* area = m_current->getScrollArea(); + if (area) + { + area->verticalScrollBar()->setValue(params.value); + } + }; } - return; + break; + default: + break; } if (m_mode == MODE_LIST) { - std::pair result = m_list->getFirstSnippetWithActiveLocationId(m_activeTokenId); - if (result.first != nullptr) - { - requestScroll( - result.first->getFile()->getFilePath(), 0, result.second, animated, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - return; - } + QTimer::singleShot(100, func); } else { - Id locationId = m_single->getLocationIdOfFirstActiveLocationOfTokenId(m_activeTokenId); - if (locationId) - { - requestScroll(m_single->getCurrentFilePath(), 0, locationId, true, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - return; - } + func(); } - if (m_references.size()) - { - m_current->requestFileContent(m_references.front().filePath); - requestScroll(m_references.front().filePath, 0, m_references.front().locationId, false, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - } -} - -void QtCodeNavigator::scrollToSnippetIfRequested() -{ - emit scrollRequest(); -} - -void QtCodeNavigator::requestScroll( - const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, QtCodeNavigateable::ScrollTarget target) -{ - ScrollRequest req; - req.filePath = filePath; - req.lineNumber = lineNumber; - req.locationId = locationId; - req.animated = animated; - req.target = target; - - if (m_mode == MODE_SINGLE) - { - if (req.lineNumber || m_singleHasNewFile) - { - req.animated = false; - } - } - - // std::cout << "scroll request: " << req.filePath.str() << " " << req.lineNumber << " " << req.locationId; - // std::cout << " " << req.animated << " " << req.target << std::endl; - - if ((!m_scrollRequest.lineNumber && !m_scrollRequest.locationId) && !req.filePath.empty()) - { - m_scrollRequest = req; - } - - m_singleHasNewFile = false; -} - -void QtCodeNavigator::handleScrollRequest() -{ - const ScrollRequest& req = m_scrollRequest; - if (req.filePath.empty() || !isVisible()) - { - return; - } - - // std::cout << "handle scroll request: " << req.filePath.str() << " " << req.lineNumber << " " << req.locationId; - // std::cout << " " << req.animated << " " << req.target << std::endl; - - bool done = m_current->requestScroll(req.filePath, req.lineNumber, req.locationId, req.animated, req.target); - if (done) - { - m_scrollRequest = ScrollRequest(); - } - else if (m_mode == MODE_SINGLE) - { - m_scrollRequest.animated = false; - } + m_scrollParams = CodeScrollParams(); } void QtCodeNavigator::scrolled(int value) @@ -895,153 +564,27 @@ void QtCodeNavigator::scrolled(int value) void QtCodeNavigator::showEvent(QShowEvent* event) { - emit scrollRequest(); + scrollTo(m_scrollParams, false); } -void QtCodeNavigator::setValue() +void QtCodeNavigator::previousReference() { - QAbstractScrollArea* area = m_current->getScrollArea(); - - if (area) - { - area->verticalScrollBar()->setValue(m_value); - } + MessageCodeReference(MessageCodeReference::REFERENCE_PREVIOUS, false).dispatch(); } -void QtCodeNavigator::previousFile(bool fromUI) +void QtCodeNavigator::nextReference() { - if (!m_references.size()) - { - return; - } - - if (m_refIndex == 0) - { - m_refIndex = m_references.size(); - } - else - { - const Reference& ref = m_references[m_refIndex - 1]; - do - { - m_refIndex--; - if (m_refIndex == 0) - { - m_refIndex = m_references.size(); - } - } - while (&ref != &m_references[m_refIndex - 1] && ref.filePath == m_references[m_refIndex - 1].filePath); - } - - m_activeReference = Reference(); - - showCurrentReference(fromUI); + MessageCodeReference(MessageCodeReference::REFERENCE_NEXT, false).dispatch(); } -void QtCodeNavigator::nextFile(bool fromUI) +void QtCodeNavigator::previousLocalReference() { - if (!m_references.size()) - { - return; - } - - if (m_refIndex == 0) - { - m_refIndex++; - } - else - { - const Reference& ref = m_references[m_refIndex - 1]; - do - { - if (m_refIndex == m_references.size()) - { - m_refIndex = 0; - } - m_refIndex++; - } - while (&ref != &m_references[m_refIndex - 1] && ref.filePath == m_references[m_refIndex - 1].filePath); - } - - m_activeReference = Reference(); - - showCurrentReference(fromUI); + MessageCodeReference(MessageCodeReference::REFERENCE_PREVIOUS, true).dispatch(); } -void QtCodeNavigator::previousReference(bool fromUI) +void QtCodeNavigator::nextLocalReference() { - if (!m_references.size()) - { - return; - } - - if (m_refIndex < 2) - { - m_refIndex = m_references.size(); - } - else - { - m_refIndex--; - } - - m_activeReference = Reference(); - - showCurrentReference(fromUI); -} - -void QtCodeNavigator::nextReference(bool fromUI) -{ - if (!m_references.size()) - { - return; - } - - m_refIndex++; - - if (m_refIndex == m_references.size() + 1) - { - m_refIndex = 1; - } - - m_activeReference = Reference(); - - showCurrentReference(fromUI); -} - -void QtCodeNavigator::previousLocalReference(bool fromUI) -{ - if (!m_localReferences.size()) - { - return; - } - - if (m_localRefIndex < 2) - { - m_localRefIndex = m_localReferences.size(); - } - else - { - m_localRefIndex--; - } - - showCurrentLocalReference(); -} - -void QtCodeNavigator::nextLocalReference(bool fromUI) -{ - if (!m_localReferences.size()) - { - return; - } - - m_localRefIndex++; - - if (m_localRefIndex == m_localReferences.size() + 1) - { - m_localRefIndex = 1; - } - - showCurrentLocalReference(); + MessageCodeReference(MessageCodeReference::REFERENCE_NEXT, true).dispatch(); } void QtCodeNavigator::setModeList() @@ -1072,169 +615,12 @@ void QtCodeNavigator::setModeSingle() } } -void QtCodeNavigator::showCurrentReference(bool fromUI) -{ - const Reference& ref = m_references[m_refIndex - 1]; - MessageShowReference(m_refIndex, ref.tokenId, ref.locationId, fromUI).dispatch(); -} - - -void QtCodeNavigator::showCurrentLocalReference() -{ - if (m_localRefIndex > 0) - { - const Reference& ref = m_localReferences[m_localRefIndex - 1]; - setCurrentActiveLocalLocationIds({ ref.locationId }); - - if (ref.locationType == LOCATION_TOKEN) - { - setCurrentActiveTokenIds({ }); - - // synchronise reference navigation with local reference navigation - for (size_t i = 0; i < m_references.size(); i++) - { - if (m_references[i].locationId == ref.locationId) - { - m_refIndex = i + 1; - } - } - } - - updateFiles(); - - requestScroll(ref.filePath, 0, ref.locationId, true, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - } -} - -void QtCodeNavigator::updateRefLabels() -{ - size_t refCount = m_references.size(); - - // std::set files; - // size_t fileIndex = 0; - // for (size_t i = 0; i < m_references.size(); i++) - // { - // const Reference& ref = m_references[i]; - // files.insert(ref.filePath); - // if (i == m_refIndex - 1) - // { - // fileIndex = files.size(); - // } - // } - - if (m_refIndex) - { - m_refLabel->setText(QString::number(m_refIndex) + "/" + QString::number(refCount) + " references"); - // m_refLabel->setText( - // QString::number(fileIndex) + "/" + QString::number(files.size()) + " files | " + - // QString::number(m_refIndex) + "/" + QString::number(refCount) + " references" - // ); - } - else - { - m_refLabel->setText(QString::number(refCount) + " references"); - // m_refLabel->setText(QString::number(files.size()) + " files | " + QString::number(refCount) + " references"); - } - - m_refLabel->setMinimumWidth( - m_refLabel->fontMetrics().width(QString(QString::number(refCount).size() * 2, 'a') + "/ references") + 30); - - m_prevFileButton->setEnabled(refCount > 1); - m_nextFileButton->setEnabled(refCount > 1); - m_prevReferenceButton->setEnabled(refCount > 1); - m_nextReferenceButton->setEnabled(refCount > 1); - - - size_t localRefCount = m_localReferences.size(); - if (m_localRefIndex) - { - m_localRefLabel->setText(QString::number(m_localRefIndex) + "/" + QString::number(localRefCount) + " local references"); - } - else - { - m_localRefLabel->setText(QString::number(localRefCount) + " local references"); - } - - m_localRefLabel->setMinimumWidth( - m_localRefLabel->fontMetrics().width(QString(QString::number(localRefCount).size() * 2, 'a') + "/ local references") + 30); - - m_nextLocalReferenceButton->setVisible(localRefCount > 1); - m_prevLocalReferenceButton->setVisible(localRefCount > 1); - m_localRefLabel->setVisible(localRefCount > 1); -} - -void QtCodeNavigator::handleMessage(MessageCodeReference* message) -{ - bool next = (message->type == MessageCodeReference::REFERENCE_NEXT); - bool local = message->localReference; - - m_onQtThread( - [=]() - { - if (next && local) - { - nextLocalReference(); - } - else if (next) - { - nextReference(); - } - else if (local) - { - previousLocalReference(); - } - else - { - previousReference(); - } - } - ); -} - void QtCodeNavigator::handleMessage(MessageIndexingFinished* message) { m_onQtThread( [=]() { - clearCaches(); - } - ); -} - -void QtCodeNavigator::handleMessage(MessageShowReference* message) -{ - size_t refIndex = message->refIndex; - bool replayed = message->isReplayed(); - - m_onQtThread( - [=]() - { - m_refIndex = refIndex; - - if (m_refIndex > 0) - { - const Reference& ref = m_references[m_refIndex - 1]; - setCurrentActiveLocationIds({ ref.locationId }); - - if (!replayed) - { - updateFiles(); - } - - requestScroll(ref.filePath, 0, ref.locationId, true, QtCodeNavigateable::SCROLL_CENTER); - emit scrollRequest(); - - if (ref.locationType == LOCATION_ERROR) - { - MessageShowError(ref.tokenId).dispatch(); - } - } - - if (!replayed) - { - updateRefLabels(); - } + clearCache(); } ); } @@ -1244,7 +630,7 @@ void QtCodeNavigator::handleMessage(MessageSwitchColorScheme* message) m_onQtThread( [=]() { - clearCaches(); + clearCache(); } ); } diff --git a/src/lib_gui/qt/element/code/QtCodeNavigator.h b/src/lib_gui/qt/element/code/QtCodeNavigator.h index 0768cbcd..26eeaac5 100644 --- a/src/lib_gui/qt/element/code/QtCodeNavigator.h +++ b/src/lib_gui/qt/element/code/QtCodeNavigator.h @@ -10,8 +10,6 @@ #include "QtThreadedFunctor.h" #include "MessageListener.h" #include "MessageIndexingFinished.h" -#include "MessageCodeReference.h" -#include "MessageShowReference.h" #include "MessageSwitchColorScheme.h" #include "MessageWindowFocus.h" @@ -23,9 +21,7 @@ class SourceLocationFile; class QtCodeNavigator : public QWidget - , public MessageListener , public MessageListener - , public MessageListener , public MessageListener , public MessageListener { @@ -42,16 +38,16 @@ public: QtCodeNavigator(QWidget* parent = nullptr); virtual ~QtCodeNavigator(); - void addCodeSnippet(const CodeSnippetParams& params); - void updateCodeSnippet(const CodeSnippetParams& params); - void addFile(std::shared_ptr locationFile, int refCount, TimeStamp modificationTime); - - void addedFiles(); + void addSnippetFile(const CodeFileParams& params); + bool addSingleFile(const CodeFileParams& params, bool useSingleFileCache); + void updateSourceLocations(const CodeSnippetParams& params); + void updateReferenceCount( + size_t referenceCount, size_t referenceIndex, size_t localReferenceCount, size_t localReferenceIndex); void clear(); - void clearCodeSnippets(bool useSingleFileCache); + void clearSnippets(); void clearFile(); - void clearCaches(); + void clearCache(); void clearSnippetReferences(); void setMode(Mode mode); @@ -86,18 +82,10 @@ public: bool isInListMode() const; bool hasSingleFileCached(const FilePath& filePath) const; - void showActiveSnippet( - const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo); - void focusTokenIds(const std::vector& focusedTokenIds); void defocusTokenIds(); - void setFileMinimized(const FilePath path); - void setFileSnippets(const FilePath path); - void setFileMaximized(const FilePath path); - void updateFiles(); - void showContents(); void refreshStyle(); @@ -107,17 +95,7 @@ public: bool hasScreenMatches() const; void clearScreenMatches(); - void scrollToValue(int value, bool inListMode); - void scrollToLine(const FilePath& filePath, unsigned int line); - void scrollToDefinition(bool animated, bool ignoreActiveReference); - - void scrollToSnippetIfRequested(); - - void requestScroll( - const FilePath& filePath, size_t lineNumber, Id locationId, bool animated, QtCodeNavigateable::ScrollTarget target); - -signals: - void scrollRequest(); + void scrollTo(const CodeScrollParams& params, bool animated); public slots: void scrolled(int value); @@ -126,62 +104,17 @@ protected: void showEvent(QShowEvent* event) override; private slots: - void handleScrollRequest(); - void setValue(); + void previousReference(); + void nextReference(); - void previousFile(bool fromUI = true); - void nextFile(bool fromUI = true); - - void previousReference(bool fromUI = true); - void nextReference(bool fromUI = true); - - void previousLocalReference(bool fromUI = true); - void nextLocalReference(bool fromUI = true); + void previousLocalReference(); + void nextLocalReference(); void setModeList(); void setModeSingle(); private: - struct Reference - { - Reference() - : tokenId(0) - , locationId(0) - , locationType(LOCATION_TOKEN) - { - } - - FilePath filePath; - Id tokenId; - Id locationId; - LocationType locationType; - }; - - void showCurrentReference(bool fromUI); - void showCurrentLocalReference(); - void updateRefLabels(); - - struct ScrollRequest - { - ScrollRequest() - : lineNumber(0) - , locationId(0) - , animated(false) - , target(QtCodeNavigateable::SCROLL_VISIBLE) - { - } - - FilePath filePath; - size_t lineNumber; - Id locationId; - - bool animated; - QtCodeNavigateable::ScrollTarget target; - }; - - void handleMessage(MessageCodeReference* message) override; void handleMessage(MessageIndexingFinished* message) override; - void handleMessage(MessageShowReference* message) override; void handleMessage(MessageSwitchColorScheme* message) override; void handleMessage(MessageWindowFocus* message) override; @@ -205,12 +138,6 @@ private: std::set m_focusedTokenIds; std::map m_errorInfos; - Id m_activeTokenId; - - int m_value; - - QtSearchBarButton* m_prevFileButton; - QtSearchBarButton* m_nextFileButton; QtSearchBarButton* m_prevReferenceButton; QtSearchBarButton* m_nextReferenceButton; QLabel* m_refLabel; @@ -224,16 +151,7 @@ private: QFrame* m_separatorLine; - std::vector m_references; - Reference m_activeReference; - size_t m_refIndex; - - std::vector m_localReferences; - size_t m_localRefIndex; - - ScrollRequest m_scrollRequest; - bool m_singleHasNewFile; - bool m_useSingleFileCache; + CodeScrollParams m_scrollParams; std::vector> m_screenMatches; Id m_activeScreenMatchId = 0; diff --git a/src/lib_gui/qt/element/code/QtCodeSnippet.cpp b/src/lib_gui/qt/element/code/QtCodeSnippet.cpp index dbf1b6e7..73688c10 100644 --- a/src/lib_gui/qt/element/code/QtCodeSnippet.cpp +++ b/src/lib_gui/qt/element/code/QtCodeSnippet.cpp @@ -10,54 +10,6 @@ #include "QtCodeNavigator.h" #include "QtCodeFile.h" -QtCodeSnippet* QtCodeSnippet::merged( - const QtCodeSnippet* a, const QtCodeSnippet* b, QtCodeNavigator* navigator, QtCodeFile* file) -{ - const QtCodeSnippet* first = a->getStartLineNumber() < b->getStartLineNumber() ? a : b; - const QtCodeSnippet* second = a->getStartLineNumber() > b->getStartLineNumber() ? a : b; - - SourceLocationFile* aFile = a->m_codeArea->getSourceLocationFile().get(); - SourceLocationFile* bFile = b->m_codeArea->getSourceLocationFile().get(); - - std::shared_ptr locationFile = std::make_shared( - aFile->getFilePath(), aFile->getLanguage(), aFile->isWhole(), aFile->isComplete(), aFile->isIndexed()); - - aFile->forEachSourceLocation( - [&locationFile](SourceLocation* loc) - { - locationFile->addSourceLocationCopy(loc); - } - ); - - bFile->forEachSourceLocation( - [&locationFile](SourceLocation* loc) - { - locationFile->addSourceLocationCopy(loc); - } - ); - - std::string code = first->getCode(); - - std::string secondCode = second->getCode(); - int secondCodeStartIndex = 0; - for (size_t i = second->getStartLineNumber(); i <= first->getEndLineNumber(); i++) - { - secondCodeStartIndex = secondCode.find("\n", secondCodeStartIndex) + 1; - } - code += secondCode.substr(secondCodeStartIndex, secondCode.npos); - - CodeSnippetParams params; - params.startLineNumber = first->getStartLineNumber(); - params.title = first->m_titleString; - params.titleId = first->m_titleId; - params.footer = second->m_footerString; - params.footerId = second->m_footerId; - params.code = code; - params.locationFile = locationFile; - - return new QtCodeSnippet(params, navigator, file); -} - QtCodeSnippet::QtCodeSnippet(const CodeSnippetParams& params, QtCodeNavigator* navigator, QtCodeFile* file) : QFrame(file) , m_navigator(navigator) @@ -78,7 +30,7 @@ QtCodeSnippet::QtCodeSnippet(const CodeSnippetParams& params, QtCodeNavigator* n layout->setAlignment(Qt::AlignTop); setLayout(layout); - if (!m_titleString.empty() && !params.reduced) + if (!m_titleString.empty() && !params.isOverview) { m_title = createScopeLine(layout); if (m_titleId == 0) // title is a file path @@ -92,7 +44,7 @@ QtCodeSnippet::QtCodeSnippet(const CodeSnippetParams& params, QtCodeNavigator* n connect(m_title, &QPushButton::clicked, this, &QtCodeSnippet::clickedTitle); } - m_codeArea = new QtCodeArea(params.startLineNumber, params.code, params.locationFile, navigator, !params.reduced, this); + m_codeArea = new QtCodeArea(params.startLineNumber, params.code, params.locationFile, navigator, !params.isOverview, this); layout->addWidget(m_codeArea); if (!m_footerString.empty()) @@ -139,7 +91,7 @@ int QtCodeSnippet::lineNumberDigits() const return m_codeArea->lineNumberDigits(); } -void QtCodeSnippet::updateCodeSnippet(const CodeSnippetParams& params) +void QtCodeSnippet::updateSourceLocations(const CodeSnippetParams& params) { m_codeArea->updateSourceLocations(params.locationFile); @@ -199,11 +151,6 @@ void QtCodeSnippet::findScreenMatches(const std::wstring& query, std::vectorfindScreenMatches(query, screenMatches); } -std::vector QtCodeSnippet::getLocationIdsForTokenIds(const std::set& tokenIds) const -{ - return m_codeArea->getLocationIdsForTokenIds(tokenIds); -} - void QtCodeSnippet::ensureLocationIdVisible(Id locationId, bool animated) { m_codeArea->ensureLocationIdVisible(locationId, width(), animated); @@ -217,10 +164,8 @@ void QtCodeSnippet::clickedTitle() } else { - getFile()->requestWholeFileContent(); + getFile()->requestWholeFileContent(getStartLineNumber()); } - - m_navigator->requestScroll(getFile()->getFilePath(), getStartLineNumber(), 0, true, QtCodeNavigateable::SCROLL_VISIBLE); } void QtCodeSnippet::clickedFooter() @@ -231,10 +176,8 @@ void QtCodeSnippet::clickedFooter() } else { - getFile()->requestWholeFileContent(); + getFile()->requestWholeFileContent(getEndLineNumber()); } - - m_navigator->requestScroll(getFile()->getFilePath(), getEndLineNumber(), 0, true, QtCodeNavigateable::SCROLL_CENTER); } QPushButton* QtCodeSnippet::createScopeLine(QBoxLayout* layout) diff --git a/src/lib_gui/qt/element/code/QtCodeSnippet.h b/src/lib_gui/qt/element/code/QtCodeSnippet.h index cba6aa87..ef00b48e 100644 --- a/src/lib_gui/qt/element/code/QtCodeSnippet.h +++ b/src/lib_gui/qt/element/code/QtCodeSnippet.h @@ -23,9 +23,6 @@ class QtCodeSnippet Q_OBJECT public: - static QtCodeSnippet* merged( - const QtCodeSnippet* a, const QtCodeSnippet* b, QtCodeNavigator* navigator, QtCodeFile* file); - QtCodeSnippet(const CodeSnippetParams& params, QtCodeNavigator* navigator, QtCodeFile* file); virtual ~QtCodeSnippet(); @@ -37,7 +34,7 @@ public: int lineNumberDigits() const; - void updateCodeSnippet(const CodeSnippetParams& params); + void updateSourceLocations(const CodeSnippetParams& params); void updateLineNumberAreaWidthForDigits(int digits); void updateContent(); @@ -54,8 +51,6 @@ public: void findScreenMatches(const std::wstring& query, std::vector>* screenMatches); - std::vector getLocationIdsForTokenIds(const std::set& tokenIds) const; - void ensureLocationIdVisible(Id locationId, bool animated); private slots: diff --git a/src/lib_gui/qt/view/QtCodeView.cpp b/src/lib_gui/qt/view/QtCodeView.cpp index e7b361cf..cd301974 100644 --- a/src/lib_gui/qt/view/QtCodeView.cpp +++ b/src/lib_gui/qt/view/QtCodeView.cpp @@ -35,7 +35,7 @@ void QtCodeView::refreshView() setStyleSheet(); - m_widget->clearCaches(); + m_widget->clearCache(); QtCodeArea::clearAnnotationColors(); QtHighlighter::clearHighlightingRules(); @@ -99,8 +99,6 @@ void QtCodeView::clear() { m_widget->clear(); }); - - m_scrollParams = ScrollParams(); } bool QtCodeView::showsErrors() const @@ -108,123 +106,97 @@ bool QtCodeView::showsErrors() const return m_widget->hasErrors(); } -void QtCodeView::showCodeSnippets(const std::vector& snippets, const CodeParams params) +void QtCodeView::showSnippets( + const std::vector files, const CodeParams params, const CodeScrollParams scrollParams) { m_onQtThread([=]() { - TRACE("show code snippets"); + TRACE("show snippets"); + + m_widget->setMode(QtCodeNavigator::MODE_LIST); if (params.clearSnippets) { - m_widget->clearCodeSnippets(params.useSingleFileCache); - - m_widget->setActiveTokenIds(params.activeTokenIds); - m_widget->setErrorInfos(params.errorInfos); - - if (!snippets.size()) - { - m_widget->clearFile(); - } + m_widget->clearSnippets(); } - bool addedFiles = false; + setNavigationState(params); - for (const CodeSnippetParams& snippet : snippets) + for (const CodeFileParams& file : files) { - if (snippet.isCollapsed) - { - m_widget->addFile(snippet.locationFile, snippet.refCount, snippet.modificationTime); - addedFiles = true; - } - else - { - m_widget->addCodeSnippet(snippet); - } + m_widget->addSnippetFile(file); } - if (addedFiles) + m_widget->updateFiles(); + + m_widget->scrollTo(scrollParams, !params.clearSnippets); + }); +} + +void QtCodeView::showSingleFile( + const CodeFileParams file, const CodeParams params, const CodeScrollParams scrollParams) +{ + m_onQtThread([=]() + { + TRACE("show single file"); + + bool animatedScroll = !m_widget->isInListMode(); + + m_widget->setMode(QtCodeNavigator::MODE_SINGLE); + + if (params.clearSnippets) { - m_widget->addedFiles(); + m_widget->clearSnippets(); } - if (params.showContents) + setNavigationState(params); + + if (file.locationFile) { + if (m_widget->addSingleFile(file, params.useSingleFileCache)) + { + animatedScroll = false; + } + m_widget->updateFiles(); - m_widget->showContents(); - performScroll(); + m_widget->scrollTo(scrollParams, animatedScroll); + } + else + { + m_widget->clearFile(); } }); } -void QtCodeView::updateCodeSnippets(const std::vector& snippets) +void QtCodeView::updateSourceLocations(const std::vector files) { m_onQtThread([=]() { - TRACE("update code snippets"); + TRACE("update source locations"); - for (const CodeSnippetParams& snippet : snippets) + for (const CodeFileParams& file : files) { - if (!snippet.locationFile || snippet.isCollapsed || snippet.reduced) + for (const CodeSnippetParams& snippet : file.snippetParams) { - continue; + if (snippet.hasAllSourceLocations) + { + m_widget->updateSourceLocations(snippet); + } } - m_widget->updateCodeSnippet(snippet); + if (file.fileParams && file.fileParams->hasAllSourceLocations) + { + m_widget->updateSourceLocations(*file.fileParams.get()); + } } }); } -void QtCodeView::scrollTo(const ScrollParams params) -{ - m_scrollParams = params; -} - -void QtCodeView::setFileState(const FilePath filePath, FileState state) +void QtCodeView::scrollTo(const CodeScrollParams params, bool animated) { m_onQtThread([=]() { - switch (state) - { - case FILE_MINIMIZED: - m_widget->setFileMinimized(filePath); - break; - case FILE_SNIPPETS: - m_widget->setFileSnippets(filePath); - break; - case FILE_MAXIMIZED: - m_widget->setFileMaximized(filePath); - break; - } - }); -} - -void QtCodeView::showActiveSnippet( - const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo) -{ - m_onQtThread([=]() - { - TRACE("show active snippet"); - m_widget->showActiveSnippet(activeTokenIds, collection, scrollTo); - }); -} - -void QtCodeView::showActiveTokenIds(const std::vector& activeTokenIds) -{ - m_onQtThread([=]() - { - m_widget->setActiveTokenIds(activeTokenIds); - m_widget->updateFiles(); - - performScroll(); - }); -} - -void QtCodeView::showActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds) -{ - m_onQtThread([=]() - { - m_widget->setActiveLocalTokenIds(activeLocalSymbolIds, LOCATION_LOCAL_SYMBOL); - m_widget->updateFiles(); + m_widget->scrollTo(params, animated); }); } @@ -244,17 +216,6 @@ void QtCodeView::defocusTokenIds() }); } -void QtCodeView::showContents() -{ - m_onQtThread([=]() - { - TRACE("show contents"); - m_widget->updateFiles(); - m_widget->showContents(); - performScroll(); - }); -} - bool QtCodeView::isInListMode() const { return m_widget->isInListMode(); @@ -262,15 +223,7 @@ bool QtCodeView::isInListMode() const void QtCodeView::setMode(bool listMode) { - if (isInListMode() == listMode) - { - return; - } - - m_onQtThread([=]() - { - m_widget->setMode(listMode ? QtCodeNavigator::MODE_LIST : QtCodeNavigator::MODE_SINGLE); - }); + m_widget->setMode(listMode ? QtCodeNavigator::MODE_LIST : QtCodeNavigator::MODE_SINGLE); } bool QtCodeView::hasSingleFileCached(const FilePath& filePath) const @@ -278,26 +231,34 @@ bool QtCodeView::hasSingleFileCached(const FilePath& filePath) const return m_widget->hasSingleFileCached(filePath); } -void QtCodeView::performScroll() +void QtCodeView::setNavigationState(const CodeParams& params) { - switch (m_scrollParams.type) + m_widget->setActiveTokenIds(params.activeTokenIds); + m_widget->setErrorInfos(params.errorInfos); + + if (params.activeLocationIds.size()) { - case ScrollParams::SCROLL_TO_DEFINITION: - m_widget->scrollToDefinition(m_scrollParams.animated, m_scrollParams.ignoreActiveReference); - break; - case ScrollParams::SCROLL_TO_LINE: - m_widget->scrollToLine(m_scrollParams.filePath, m_scrollParams.line); - break; - case ScrollParams::SCROLL_TO_VALUE: - m_widget->scrollToValue(m_scrollParams.value, m_scrollParams.inListMode); - break; - default: - break; + m_widget->setCurrentActiveLocationIds(params.activeLocationIds); } - m_widget->scrollToSnippetIfRequested(); + if (params.activeLocalSymbolIds.size()) + { + if (params.activeLocalSymbolType == LOCATION_TOKEN) + { + m_widget->setCurrentActiveTokenIds( + params.currentActiveLocalLocationIds.size() ? std::vector() : params.activeLocalSymbolIds); + } - m_scrollParams = ScrollParams(); + m_widget->setActiveLocalTokenIds(params.activeLocalSymbolIds, params.activeLocalSymbolType); + } + + if (params.currentActiveLocalLocationIds.size()) + { + m_widget->setCurrentActiveLocalLocationIds(params.currentActiveLocalLocationIds); + } + + m_widget->updateReferenceCount( + params.referenceCount, params.referenceIndex, params.localReferenceCount, params.localReferenceIndex); } void QtCodeView::setStyleSheet() const diff --git a/src/lib_gui/qt/view/QtCodeView.h b/src/lib_gui/qt/view/QtCodeView.h index cf2122a0..158f80de 100644 --- a/src/lib_gui/qt/view/QtCodeView.h +++ b/src/lib_gui/qt/view/QtCodeView.h @@ -27,38 +27,35 @@ public: // CodeView implementation void clear() override; - void showCodeSnippets(const std::vector& snippets, const CodeParams params) override; - void updateCodeSnippets(const std::vector& snippets) override; - void scrollTo(const ScrollParams params) override; + void showSnippets( + const std::vector files, const CodeParams params, const CodeScrollParams scrollParams) override; + + void showSingleFile( + const CodeFileParams file, const CodeParams params, const CodeScrollParams scrollParams) override; + + void updateSourceLocations(const std::vector files) override; + + void scrollTo(const CodeScrollParams params, bool animated) override; bool showsErrors() const override; - void setFileState(const FilePath filePath, FileState state) override; - - void showActiveSnippet( - const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo) override; - void showActiveTokenIds(const std::vector& activeTokenIds) override; - void showActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds) override; - void focusTokenIds(const std::vector& focusedTokenIds) override; void defocusTokenIds() override; - void showContents() override; - bool isInListMode() const override; void setMode(bool listMode) override; bool hasSingleFileCached(const FilePath& filePath) const override; private: - void performScroll(); + void setNavigationState(const CodeParams& params); + + // void performScroll(const CodeScrollParams& scrollParams); void setStyleSheet() const; QtThreadedLambdaFunctor m_onQtThread; QtCodeNavigator* m_widget; - - ScrollParams m_scrollParams; }; # endif // QT_CODE_VIEW_H diff --git a/testing/code_view/code_view_tests.srctrlprj b/testing/code_view/code_view_tests.srctrlprj index 5dbac82d..8eb9db52 100644 --- a/testing/code_view/code_view_tests.srctrlprj +++ b/testing/code_view/code_view_tests.srctrlprj @@ -39,5 +39,5 @@ Test Suites:\n\n C++ Source Group - 7 + 8 diff --git a/testing/history/history_tests.srctrlprj b/testing/history/history_tests.srctrlprj index 07739fe8..5dacecb6 100644 --- a/testing/history/history_tests.srctrlprj +++ b/testing/history/history_tests.srctrlprj @@ -29,5 +29,5 @@ C++ Source Group - 7 + 8