From d0a063a3b6e50cab29ec1490b5b239fcf1b8b885 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Tue, 9 Aug 2016 13:29:14 +0200 Subject: [PATCH] ui: Added shortcuts for navigating to next and previous reference in code view * Added new class QtCodeNavigator between QtCodeView and QtCodeFileList that handles active ids and navigation * Pass all files as initially collapsed to code view and decide in QtCodeNavigator which ones show content * Rewrote requesting of active snippet display to top down approach * Display other locations focused when active location changes * Show corresponding edges when navigating references --- bin/app/data/color_schemes/bad_rainbow.xml | 3 + bin/app/data/color_schemes/bright.xml | 3 + bin/app/data/color_schemes/dark.xml | 4 + bin/app/data/gui/code_view/code_view.css | 2 +- bin/test/data/log/test_log.txt | 1 + src/lib/CMakeLists.txt | 6 +- .../component/controller/CodeController.cpp | 61 +-- .../component/controller/GraphController.cpp | 12 + .../component/controller/GraphController.h | 3 + src/lib/component/view/CodeView.h | 5 +- .../view/helper/CodeSnippetParams.cpp | 11 - .../component/view/helper/CodeSnippetParams.h | 1 - src/lib/data/PersistentStorage.cpp | 10 +- .../messaging/type/MessageCodeReference.h | 41 ++ src/lib/utility/messaging/type/MessageRedo.h | 4 +- .../messaging/type/MessageShowReference.h | 33 ++ src/lib/utility/messaging/type/MessageUndo.h | 4 +- src/lib_gui/CMakeLists.txt | 2 + src/lib_gui/qt/element/QtCodeArea.cpp | 55 +- src/lib_gui/qt/element/QtCodeArea.h | 14 +- src/lib_gui/qt/element/QtCodeFile.cpp | 256 ++++----- src/lib_gui/qt/element/QtCodeFile.h | 23 +- src/lib_gui/qt/element/QtCodeFileList.cpp | 295 +++------- src/lib_gui/qt/element/QtCodeFileList.h | 49 +- src/lib_gui/qt/element/QtCodeNavigator.cpp | 512 ++++++++++++++++++ src/lib_gui/qt/element/QtCodeNavigator.h | 118 ++++ src/lib_gui/qt/element/QtCodeSnippet.cpp | 27 +- src/lib_gui/qt/element/QtCodeSnippet.h | 13 +- src/lib_gui/qt/view/QtCodeView.cpp | 36 +- src/lib_gui/qt/view/QtCodeView.h | 14 +- src/lib_gui/qt/window/QtMainWindow.cpp | 16 + src/lib_gui/qt/window/QtMainWindow.h | 2 + 32 files changed, 1037 insertions(+), 599 deletions(-) create mode 100644 src/lib/utility/messaging/type/MessageCodeReference.h create mode 100644 src/lib/utility/messaging/type/MessageShowReference.h create mode 100644 src/lib_gui/qt/element/QtCodeNavigator.cpp create mode 100644 src/lib_gui/qt/element/QtCodeNavigator.h diff --git a/bin/app/data/color_schemes/bad_rainbow.xml b/bin/app/data/color_schemes/bad_rainbow.xml index ceee8eac..813b020b 100644 --- a/bin/app/data/color_schemes/bad_rainbow.xml +++ b/bin/app/data/color_schemes/bad_rainbow.xml @@ -167,6 +167,9 @@ #C2AFEF #3D3D3D + + #987CEA + diff --git a/bin/app/data/color_schemes/bright.xml b/bin/app/data/color_schemes/bright.xml index f29f5add..cb63e02a 100644 --- a/bin/app/data/color_schemes/bright.xml +++ b/bin/app/data/color_schemes/bright.xml @@ -165,6 +165,9 @@ #C7C7E2 #000000 + + #ABABDD + diff --git a/bin/app/data/color_schemes/dark.xml b/bin/app/data/color_schemes/dark.xml index 22cbf179..e5858f3a 100644 --- a/bin/app/data/color_schemes/dark.xml +++ b/bin/app/data/color_schemes/dark.xml @@ -186,6 +186,10 @@ #207EA8 #F7F7F7 + + #006D93 + #134B63 + diff --git a/bin/app/data/gui/code_view/code_view.css b/bin/app/data/gui/code_view/code_view.css index 1889048f..bb5aa60e 100644 --- a/bin/app/data/gui/code_view/code_view.css +++ b/bin/app/data/gui/code_view/code_view.css @@ -1,4 +1,4 @@ -#code_file_list_base, #code_file_list { +#code_container, #code_file_list { background-color: ; } diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 5e4e1ebd..0799c370 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -1,3 +1,4 @@ +Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml Token.cpp ERROR: Location Id was not referenced by this Token. Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class Edge.cpp ERROR: Nodes are not plain copies. diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 26f54186..aded41e6 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -128,13 +128,13 @@ add_files( data/parser/cxx/TaskParseCxx.h data/parser/cxx/TaskParseWrapper.h - + data/parser/java/JavaEnvironment.cpp data/parser/java/JavaEnvironment.h data/parser/java/JavaEnvironmentFactory.cpp data/parser/java/JavaEnvironmentFactory.h data/parser/java/TaskParseJava.h - + data/parser/AccessKind.cpp data/parser/AccessKind.h data/parser/ParseLocation.cpp @@ -245,6 +245,7 @@ add_files( utility/messaging/type/MessageAutoRefreshChanged.h utility/messaging/type/MessageChangeFileView.h utility/messaging/type/MessageClearErrorCount.h + utility/messaging/type/MessageCodeReference.h utility/messaging/type/MessageColorSchemeTest.h utility/messaging/type/MessageDeactivateEdge.h utility/messaging/type/MessageDispatchWhenLicenseValid.h @@ -272,6 +273,7 @@ add_files( utility/messaging/type/MessageSearchAutocomplete.h utility/messaging/type/MessageSearchFullText.h utility/messaging/type/MessageShowErrors.h + utility/messaging/type/MessageShowReference.h utility/messaging/type/MessageShowScope.h utility/messaging/type/MessageShowStartScreen.h utility/messaging/type/MessageStatus.h diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 821fa7d2..f7d0ec89 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -122,7 +122,8 @@ void CodeController::handleMessage(MessageActivateTokens* message) if (message->isEdge) { - view->showFirstActiveSnippet(activeTokenIds, message->isLast()); + std::shared_ptr collection = m_storageAccess->getTokenLocationsForTokenIds(activeTokenIds); + view->showActiveSnippet(activeTokenIds, collection, message->isLast()); } else if (message->keepContent()) { @@ -365,9 +366,6 @@ std::vector CodeController::getSnippetsForActiveTokenLocation TRACE(); std::vector snippets; - size_t definitionFileCount = 0; - size_t declarationFileCount = 0; - collection->forEachTokenLocationFile( [&](std::shared_ptr file) -> void { @@ -388,38 +386,15 @@ std::vector CodeController::getSnippetsForActiveTokenLocation } ); - if (collection->getTokenLocationFileCount() < 5 || file->isWholeCopy || - (isDefinitionFile && definitionFileCount < 3) || - (!isDefinitionFile && isDeclarationFile && declarationFileCount < 3)) - { - std::vector fileSnippets = getSnippetsForFile(file, true); + CodeSnippetParams params; + params.locationFile = file; + params.refCount = file->getUnscopedStartTokenLocationCount(); - for (CodeSnippetParams& snippet : fileSnippets) - { - snippet.isDeclaration = isDeclarationFile; - snippet.isDefinition = isDefinitionFile; - } + params.isDeclaration = isDeclarationFile; + params.isDefinition = isDefinitionFile; - utility::append(snippets, fileSnippets); - } - else - { - CodeSnippetParams params; - params.locationFile = file; - params.refCount = file->getUnscopedStartTokenLocationCount(); - - params.isCollapsed = true; - snippets.push_back(params); - } - - if (isDefinitionFile) - { - definitionFileCount++; - } - else if (isDeclarationFile) - { - declarationFileCount++; - } + params.isCollapsed = true; + snippets.push_back(params); } ); @@ -439,20 +414,12 @@ std::vector CodeController::getSnippetsForCollection( collection->forEachTokenLocationFile( [&](std::shared_ptr file) -> void { - if (snippets.size() < 10) - { - std::vector fileSnippets = getSnippetsForFile(file, addTokenLocations); - snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end()); - } - else - { - CodeSnippetParams params; - params.locationFile = file; - params.refCount = file->getUnscopedStartTokenLocationCount(); + CodeSnippetParams params; + params.locationFile = file; + params.refCount = file->getUnscopedStartTokenLocationCount(); - params.isCollapsed = true; - snippets.push_back(params); - } + params.isCollapsed = true; + snippets.push_back(params); } ); diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 3979353a..93a31413 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -176,6 +176,18 @@ void GraphController::handleMessage(MessageShowErrors* message) clear(); } +void GraphController::handleMessage(MessageShowReference* message) +{ + if (!message->tokenId) + { + return; + } + + m_activeEdgeIds = std::vector(1, message->tokenId); + setActiveAndVisibility(utility::concat(m_activeNodeIds, m_activeEdgeIds)); + buildGraph(message, false); +} + GraphView* GraphController::getView() const { return Controller::getView(); diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 76a7dc43..3a9021c0 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -16,6 +16,7 @@ #include "utility/messaging/type/MessageGraphNodeMove.h" #include "utility/messaging/type/MessageSearchFullText.h" #include "utility/messaging/type/MessageShowErrors.h" +#include "utility/messaging/type/MessageShowReference.h" #include "component/controller/Controller.h" #include "component/controller/helper/DummyEdge.h" @@ -41,6 +42,7 @@ class GraphController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener { public: GraphController(StorageAccess* storageAccess); @@ -57,6 +59,7 @@ private: virtual void handleMessage(MessageGraphNodeMove* message); virtual void handleMessage(MessageSearchFullText* message); virtual void handleMessage(MessageShowErrors* message); + virtual void handleMessage(MessageShowReference* message); GraphView* getView() const; diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 9b58d830..fa59ffe8 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -10,6 +10,7 @@ #include "component/view/View.h" class CodeController; +class TokenLocationCollection; class CodeView : public View @@ -29,7 +30,6 @@ public: virtual void clear() = 0; - virtual void setActiveTokenIds(const std::vector& activeTokenIds) = 0; virtual void setErrorInfos(const std::vector& errorInfos) = 0; virtual void showCodeSnippets(const std::vector& snippets, const std::vector& activeTokenIds) = 0; @@ -38,7 +38,8 @@ public: virtual void setFileState(const FilePath filePath, FileState state) = 0; - virtual void showFirstActiveSnippet(const std::vector& activeTokenIds, bool scrollTo) = 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; diff --git a/src/lib/component/view/helper/CodeSnippetParams.cpp b/src/lib/component/view/helper/CodeSnippetParams.cpp index ffa08cc2..f556e301 100644 --- a/src/lib/component/view/helper/CodeSnippetParams.cpp +++ b/src/lib/component/view/helper/CodeSnippetParams.cpp @@ -9,7 +9,6 @@ CodeSnippetParams::CodeSnippetParams() , footerId(0) , locationFile() , refCount(0) - , isActive(false) , isCollapsed(false) , isDeclaration(false) , isDefinition(false) @@ -19,16 +18,6 @@ CodeSnippetParams::CodeSnippetParams() bool CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSnippetParams& b) { - // sort active snippet first - if (a.isActive && !b.isActive) - { - return true; - } - else if (!a.isActive && b.isActive) - { - return false; - } - // sort definitions if (a.isDefinition && !b.isDefinition) { diff --git a/src/lib/component/view/helper/CodeSnippetParams.h b/src/lib/component/view/helper/CodeSnippetParams.h index aadb6502..8f42d9c8 100644 --- a/src/lib/component/view/helper/CodeSnippetParams.h +++ b/src/lib/component/view/helper/CodeSnippetParams.h @@ -30,7 +30,6 @@ struct CodeSnippetParams int refCount; - bool isActive; bool isCollapsed; bool isDeclaration; diff --git a/src/lib/data/PersistentStorage.cpp b/src/lib/data/PersistentStorage.cpp index 37f51e3c..e67b167c 100644 --- a/src/lib/data/PersistentStorage.cpp +++ b/src/lib/data/PersistentStorage.cpp @@ -480,8 +480,11 @@ std::shared_ptr PersistentStorage::getFullTextSearchLoc if ( addHit ) { + // Set first bit to 1 to avoid collisions + Id locationId = ~(~size_t(0) >> 1) + collection->getTokenLocationCount(); + collection->addTokenLocation( - collection->getTokenLocationCount(), + locationId, 0, filepath, location.startLineNumber, @@ -1012,8 +1015,11 @@ std::shared_ptr PersistentStorage::getErrorTokenLocatio const StorageError& error = storageErrors[i]; if (error.fatal || error.indexed || showExternalNonFatalErrors) { + // Set first bit to 1 to avoid collisions + Id locationId = ~(~size_t(0) >> 1) + i; + errorCollection->addTokenLocation( - i, i, error.filePath, error.lineNumber, error.columnNumber, error.lineNumber, error.columnNumber + locationId, i, error.filePath, error.lineNumber, error.columnNumber, error.lineNumber, error.columnNumber )->setType(LOCATION_ERROR); errors->push_back(ErrorInfo(error.message, error.filePath, i, error.fatal)); } diff --git a/src/lib/utility/messaging/type/MessageCodeReference.h b/src/lib/utility/messaging/type/MessageCodeReference.h new file mode 100644 index 00000000..82c5c088 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageCodeReference.h @@ -0,0 +1,41 @@ +#ifndef MESSAGE_CODE_REFERENCE_H +#define MESSAGE_CODE_REFERENCE_H + +#include "utility/messaging/Message.h" + +class MessageCodeReference + : public Message +{ +public: + enum ReferenceType + { + REFERENCE_PREVIOUS, + REFERENCE_NEXT + }; + + MessageCodeReference(ReferenceType type) + : type(type) + { + } + + static const std::string getStaticType() + { + return "MessageCodeReference"; + } + + virtual void print(std::ostream& os) const + { + if (type == REFERENCE_PREVIOUS) + { + os << "previous"; + } + else + { + os << "next"; + } + } + + const ReferenceType type; +}; + +#endif // MESSAGE_CODE_REFERENCE_H diff --git a/src/lib/utility/messaging/type/MessageRedo.h b/src/lib/utility/messaging/type/MessageRedo.h index 78761ac4..aa2f9152 100644 --- a/src/lib/utility/messaging/type/MessageRedo.h +++ b/src/lib/utility/messaging/type/MessageRedo.h @@ -2,9 +2,9 @@ #define MESSAGE_REDO_H #include "utility/messaging/Message.h" -#include "utility/types.h" -class MessageRedo: public Message +class MessageRedo + : public Message { public: MessageRedo() diff --git a/src/lib/utility/messaging/type/MessageShowReference.h b/src/lib/utility/messaging/type/MessageShowReference.h new file mode 100644 index 00000000..5af069f9 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageShowReference.h @@ -0,0 +1,33 @@ +#ifndef MESSAGE_SHOW_REFERENCE_H +#define MESSAGE_SHOW_REFERENCE_H + +#include "utility/messaging/Message.h" +#include "utility/types.h" + +class MessageShowReference + : public Message +{ +public: + MessageShowReference(size_t refIndex, Id tokenId, Id locationId) + : refIndex(refIndex) + , tokenId(tokenId) + , locationId(locationId) + { + } + + static const std::string getStaticType() + { + return "MessageShowReference"; + } + + virtual void print(std::ostream& os) const + { + os << "index: " << refIndex << " token: " << tokenId << " location: " << locationId; + } + + const size_t refIndex; + const Id tokenId; + const Id locationId; +}; + +#endif // MESSAGE_SHOW_REFERENCE_H diff --git a/src/lib/utility/messaging/type/MessageUndo.h b/src/lib/utility/messaging/type/MessageUndo.h index cc2994dd..aeedb6e4 100644 --- a/src/lib/utility/messaging/type/MessageUndo.h +++ b/src/lib/utility/messaging/type/MessageUndo.h @@ -2,9 +2,9 @@ #define MESSAGE_UNDO_H #include "utility/messaging/Message.h" -#include "utility/types.h" -class MessageUndo: public Message +class MessageUndo + : public Message { public: MessageUndo() diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index c6d02708..3f06252b 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -14,6 +14,8 @@ add_files( qt/element/QtCodeFile.h qt/element/QtCodeFileList.cpp qt/element/QtCodeFileList.h + qt/element/QtCodeNavigator.cpp + qt/element/QtCodeNavigator.h qt/element/QtCodeSnippet.cpp qt/element/QtCodeSnippet.h qt/element/QtDirectoryListBox.cpp diff --git a/src/lib_gui/qt/element/QtCodeArea.cpp b/src/lib_gui/qt/element/QtCodeArea.cpp index 11a09c80..ced20938 100644 --- a/src/lib_gui/qt/element/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/QtCodeArea.cpp @@ -19,8 +19,7 @@ #include "data/location/TokenLocation.h" #include "data/location/TokenLocationFile.h" -#include "qt/element/QtCodeFile.h" -#include "qt/element/QtCodeSnippet.h" +#include "qt/element/QtCodeNavigator.h" #include "qt/utility/QtContextMenu.h" #include "qt/utility/QtHighlighter.h" #include "settings/ApplicationSettings.h" @@ -83,11 +82,11 @@ QtCodeArea::QtCodeArea( uint startLineNumber, const std::string& code, std::shared_ptr locationFile, - QtCodeFile* file, - QtCodeSnippet* parent + QtCodeNavigator* navigator, + QWidget* parent ) : QPlainTextEdit(parent) - , m_fileWidget(file) + , m_navigator(navigator) , m_startLineNumber(startLineNumber) , m_code(code) , m_locationFile(locationFile) @@ -183,11 +182,6 @@ std::shared_ptr QtCodeArea::getTokenLocationFile() const return m_locationFile; } -QtCodeFile* QtCodeArea::getFile() const -{ - return m_fileWidget; -} - void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event) { QPainter painter(m_lineNumberArea); @@ -250,31 +244,16 @@ void QtCodeArea::updateContent() annotateText(); } -bool QtCodeArea::isActive() const -{ - const std::vector& ids = m_fileWidget->getActiveTokenIds(); - - for (const Annotation& annotation: m_annotations) - { - if (std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end()) - { - return true; - } - } - - return false; -} - void QtCodeArea::setIsActiveFile(bool isActiveFile) { m_isActiveFile = isActiveFile; } -uint QtCodeArea::getFirstActiveLineNumber() const +uint QtCodeArea::getLineNumberForLocationId(Id locationId) const { for (const Annotation& annotation : m_annotations) { - if (annotation.isActive) + if (annotation.locationId == locationId) { return annotation.startLine; } @@ -488,7 +467,7 @@ void QtCodeArea::mouseMoveEvent(QMouseEvent* event) setHoveredAnnotations(annotations); - std::vector errorMessages = m_fileWidget->getErrorMessages(); + std::vector errorMessages = m_navigator->getErrorMessages(); if (annotations.size() == 1 && errorMessages.size() > annotations[0]->tokenId) { QToolTip::showText(event->globalPos(), QString::fromStdString(errorMessages[annotations[0]->tokenId])); @@ -687,9 +666,12 @@ void QtCodeArea::createAnnotations(std::shared_ptr locationFi void QtCodeArea::annotateText() { - const std::vector& activeTokenIds = m_fileWidget->getActiveTokenIds(); - const std::vector& activeLocalSymbolIds = m_fileWidget->getActiveLocalSymbolIds(); - const std::vector& focusIds = m_fileWidget->getFocusedTokenIds(); + const std::vector& currentActiveTokenIds = m_navigator->getCurrentActiveTokenIds(); + const std::vector& currentActiveLocationIds = m_navigator->getCurrentActiveLocationIds(); + + const std::vector& activeTokenIds = m_navigator->getActiveTokenIds(); + const std::vector& activeLocalSymbolIds = m_navigator->getActiveLocalSymbolIds(); + const std::vector& focusIds = m_navigator->getFocusedTokenIds(); bool needsUpdate = false; for (Annotation& annotation: m_annotations) @@ -699,10 +681,17 @@ void QtCodeArea::annotateText() const AnnotationColor& oldColor = getAnnotationColorForAnnotation(annotation); annotation.isActive = ( - std::find(activeTokenIds.begin(), activeTokenIds.end(), annotation.tokenId) != activeTokenIds.end() || + std::find(currentActiveTokenIds.begin(), currentActiveTokenIds.end(), annotation.tokenId) != currentActiveTokenIds.end() || + std::find(currentActiveLocationIds.begin(), currentActiveLocationIds.end(), annotation.locationId) != currentActiveLocationIds.end() || std::find(activeLocalSymbolIds.begin(), activeLocalSymbolIds.end(), annotation.tokenId) != activeLocalSymbolIds.end() ); - annotation.isFocused = std::find(focusIds.begin(), focusIds.end(), annotation.tokenId) != focusIds.end(); + if (!annotation.isActive) + { + annotation.isFocused = ( + std::find(focusIds.begin(), focusIds.end(), annotation.tokenId) != focusIds.end() || + std::find(activeTokenIds.begin(), activeTokenIds.end(), annotation.tokenId) != activeTokenIds.end() + ); + } const AnnotationColor& newColor = getAnnotationColorForAnnotation(annotation); if ((newColor.text != oldColor.text || !m_wasAnnotated)) diff --git a/src/lib_gui/qt/element/QtCodeArea.h b/src/lib_gui/qt/element/QtCodeArea.h index 299a247c..2b4389c7 100644 --- a/src/lib_gui/qt/element/QtCodeArea.h +++ b/src/lib_gui/qt/element/QtCodeArea.h @@ -14,8 +14,7 @@ class QDragMoveEvent; class QPaintEvent; class QResizeEvent; class QSize; -class QtCodeFile; -class QtCodeSnippet; +class QtCodeNavigator; class QtHighlighter; class QWidget; class TokenLocation; @@ -61,8 +60,8 @@ public: uint startLineNumber, const std::string& code, std::shared_ptr locationFile, - QtCodeFile* file, - QtCodeSnippet* parent + QtCodeNavigator* navigator, + QWidget* parent = nullptr ); virtual ~QtCodeArea(); @@ -72,7 +71,6 @@ public: uint getEndLineNumber() const; std::shared_ptr getTokenLocationFile() const; - QtCodeFile* getFile() const; void lineNumberAreaPaintEvent(QPaintEvent* event); int lineNumberDigits() const; @@ -81,11 +79,9 @@ public: void updateContent(); - bool isActive() const; - void setIsActiveFile(bool isActiveFile); - uint getFirstActiveLineNumber() const; + uint getLineNumberForLocationId(Id locationId) const; QRectF getLineRectForLineNumber(uint lineNumber) const; std::string getCode() const; @@ -166,7 +162,7 @@ private: static std::vector s_annotationColors; - QtCodeFile* m_fileWidget; + QtCodeNavigator* m_navigator; QWidget* m_lineNumberArea; QtHighlighter* m_highlighter; diff --git a/src/lib_gui/qt/element/QtCodeFile.cpp b/src/lib_gui/qt/element/QtCodeFile.cpp index dca00832..af1cc04d 100644 --- a/src/lib_gui/qt/element/QtCodeFile.cpp +++ b/src/lib_gui/qt/element/QtCodeFile.cpp @@ -14,17 +14,17 @@ #include "data/location/TokenLocation.h" #include "data/location/TokenLocationFile.h" #include "isTrial.h" -#include "qt/element/QtCodeFileList.h" +#include "qt/element/QtCodeNavigator.h" #include "qt/element/QtCodeSnippet.h" #include "qt/utility/utilityQt.h" #include "settings/ColorScheme.h" -QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) - : QFrame(parent) +QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator) + : QFrame() , m_updateTitleBarFunctor(std::bind(&QtCodeFile::doUpdateTitleBar, this)) - , m_parent(parent) + , m_navigator(navigator) , m_filePath(filePath) - , m_snippetsRequested(false) + , m_contentRequested(false) , m_scrollToLine(0) { setObjectName("code_file"); @@ -129,36 +129,11 @@ std::string QtCodeFile::getFileName() const return m_filePath.fileName(); } -const std::vector& QtCodeFile::getActiveTokenIds() const -{ - return m_parent->getActiveTokenIds(); -} - -const std::vector& QtCodeFile::getActiveLocalSymbolIds() const -{ - return m_parent->getActiveLocalSymbolIds(); -} - -const std::vector& QtCodeFile::getFocusedTokenIds() const -{ - return m_parent->getFocusedTokenIds(); -} - -std::vector QtCodeFile::getErrorMessages() const -{ - return m_parent->getErrorMessages(); -} - -bool QtCodeFile::hasErrors() const -{ - return m_parent->hasErrors();; -} - QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params) { m_locationFile.reset(); - std::shared_ptr snippet(new QtCodeSnippet(params, this)); + std::shared_ptr snippet(new QtCodeSnippet(params, m_navigator, this)); if (params.reduced) { @@ -225,7 +200,7 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params) { m_locationFile.reset(); - std::shared_ptr snippet(new QtCodeSnippet(params, this)); + std::shared_ptr snippet(new QtCodeSnippet(params, m_navigator, this)); size_t i = 0; while (i < m_snippets.size()) @@ -246,7 +221,7 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params) } else if (s->getStartLineNumber() < start || s->getEndLineNumber() > end) { - snippet = QtCodeSnippet::merged(snippet.get(), s.get(), this); + snippet = QtCodeSnippet::merged(snippet.get(), s.get(), m_navigator, this); } s->hide(); @@ -264,58 +239,47 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params) return snippet.get(); } -QtCodeSnippet* QtCodeFile::getFileSnippet() const +QtCodeSnippet* QtCodeFile::getSnippetForLocationId(Id locationId) const { - return m_fileSnippet.get(); -} - -QtCodeSnippet* QtCodeFile::findFirstActiveSnippet() const -{ - if (m_locationFile) + for (std::shared_ptr snippet : m_snippets) { - return nullptr; - } - - if (m_maximizeButton->isEnabled()) - { - for (std::shared_ptr snippet : m_snippets) + if (snippet->getLineNumberForLocationId(locationId)) { - if (snippet->isActive()) - { - return snippet.get(); - } - } - } - else - { - if (m_fileSnippet->isActive()) - { - return m_fileSnippet.get(); + return snippet.get(); } } return nullptr; } -bool QtCodeFile::isCollapsedActiveFile() const +QtCodeSnippet* QtCodeFile::getFileSnippet() const { - bool isActiveFile = false; - if (m_locationFile) - { - std::vector ids = getActiveTokenIds(); + return m_fileSnippet.get(); +} - m_locationFile->forEachTokenLocation( - [&](TokenLocation* location) - { - if (std::find(ids.begin(), ids.end(), location->getTokenId()) != ids.end()) - { - isActiveFile = true; - } - } - ); +bool QtCodeFile::isCollapsed() const +{ + return m_locationFile != nullptr; +} + +void QtCodeFile::requestContent() const +{ + if (!isCollapsed() || m_contentRequested) + { + return; } - return isActiveFile; + m_contentRequested = true; + + MessageChangeFileView msg( + m_filePath, + m_locationFile->isWholeCopy ? MessageChangeFileView::FILE_MAXIMIZED : MessageChangeFileView::FILE_SNIPPETS, + isCollapsed(), + m_navigator->hasErrors() + ); + + msg.setIsReplayed(true); + msg.dispatch(); } void QtCodeFile::updateContent() @@ -338,7 +302,7 @@ void QtCodeFile::setLocationFile(std::shared_ptr locationFile m_locationFile = locationFile; setMinimized(); - updateRefCount(refCount); + updateRefCount(locationFile->isWholeCopy ? 0 : refCount); } void QtCodeFile::setMinimized() @@ -354,10 +318,7 @@ void QtCodeFile::setMinimized() } m_minimizeButton->setEnabled(false); - if (m_snippets.size() || m_locationFile) - { - m_snippetButton->setEnabled(true); - } + m_snippetButton->setEnabled(m_snippets.size() || (isCollapsed() && !m_locationFile->isWholeCopy)); m_maximizeButton->setEnabled(true); } @@ -391,89 +352,10 @@ void QtCodeFile::setMaximized() } m_minimizeButton->setEnabled(true); - if (m_snippets.size()) - { - m_snippetButton->setEnabled(true); - } + m_snippetButton->setEnabled(m_snippets.size()); m_maximizeButton->setEnabled(false); } -void QtCodeFile::clickedTitleBar() -{ - if (m_minimizeButton->isEnabled()) - { - clickedMinimizeButton(); - } - else if (m_snippetButton->isEnabled()) - { - clickedSnippetButton(); - } - else - { - clickedMaximizeButton(); - } -} - -void QtCodeFile::clickedTitle() -{ - MessageActivateFile(m_filePath).dispatch(); -} - -void QtCodeFile::editProject() -{ - MessageProjectEdit().dispatch(); -} - -void QtCodeFile::clickedMinimizeButton() const -{ - MessageChangeFileView( - m_filePath, - MessageChangeFileView::FILE_MINIMIZED, - false, - hasErrors() - ).dispatch(); -} - -void QtCodeFile::clickedSnippetButton() const -{ - MessageChangeFileView( - m_filePath, - MessageChangeFileView::FILE_SNIPPETS, - (m_locationFile != nullptr), - hasErrors() - ).dispatch(); -} - -void QtCodeFile::clickedMaximizeButton() const -{ - MessageChangeFileView( - m_filePath, - MessageChangeFileView::FILE_MAXIMIZED, - (m_fileSnippet == nullptr), - hasErrors() - ).dispatch(); -} - -void QtCodeFile::requestSnippets() const -{ - if (m_snippetsRequested) - { - return; - } - - m_snippetsRequested = true; - - MessageChangeFileView msg( - m_filePath, - MessageChangeFileView::FILE_SNIPPETS, - (m_locationFile != nullptr), - hasErrors() - ); - - msg.setIsReplayed(true); - msg.dispatch(); -} - bool QtCodeFile::hasSnippets() const { return m_snippets.size() > 0; @@ -514,6 +396,62 @@ void QtCodeFile::setScrollToLine(uint line) m_scrollToLine = line; } +void QtCodeFile::clickedMinimizeButton() const +{ + MessageChangeFileView( + m_filePath, + MessageChangeFileView::FILE_MINIMIZED, + false, + m_navigator->hasErrors() + ).dispatch(); +} + +void QtCodeFile::clickedSnippetButton() const +{ + MessageChangeFileView( + m_filePath, + MessageChangeFileView::FILE_SNIPPETS, + isCollapsed(), + m_navigator->hasErrors() + ).dispatch(); +} + +void QtCodeFile::clickedMaximizeButton() const +{ + MessageChangeFileView( + m_filePath, + MessageChangeFileView::FILE_MAXIMIZED, + !isCollapsed(), + m_navigator->hasErrors() + ).dispatch(); +} + +void QtCodeFile::clickedTitleBar() +{ + if (m_minimizeButton->isEnabled()) + { + clickedMinimizeButton(); + } + else if (m_snippetButton->isEnabled()) + { + clickedSnippetButton(); + } + else + { + clickedMaximizeButton(); + } +} + +void QtCodeFile::clickedTitle() +{ + MessageActivateFile(m_filePath).dispatch(); +} + +void QtCodeFile::editProject() +{ + MessageProjectEdit().dispatch(); +} + void QtCodeFile::handleMessage(MessageWindowFocus* message) { updateTitleBar(); @@ -523,13 +461,13 @@ void QtCodeFile::updateRefCount(int refCount) { if (refCount > 0) { - QString label = hasErrors() ? "error" : "reference"; + QString label = m_navigator->hasErrors() ? "error" : "reference"; if (refCount > 1) { label += "s"; } - size_t fatalErrorCount = m_parent->getFatalErrorCountForFile(m_filePath); + size_t fatalErrorCount = m_navigator->getFatalErrorCountForFile(m_filePath); if (fatalErrorCount > 0) { label += " (" + QString::number(fatalErrorCount) + " fatal)"; diff --git a/src/lib_gui/qt/element/QtCodeFile.h b/src/lib_gui/qt/element/QtCodeFile.h index 3b9f20d2..85bbd6b3 100644 --- a/src/lib_gui/qt/element/QtCodeFile.h +++ b/src/lib_gui/qt/element/QtCodeFile.h @@ -19,7 +19,7 @@ class QLabel; class QPushButton; -class QtCodeFileList; +class QtCodeNavigator; class QtCodeSnippet; class QVBoxLayout; class TokenLocationFile; @@ -31,7 +31,7 @@ class QtCodeFile Q_OBJECT public: - QtCodeFile(const FilePath& filePath, QtCodeFileList* parent); + QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator); virtual ~QtCodeFile(); void setModificationTime(TimePoint modificationTime); @@ -39,20 +39,15 @@ public: const FilePath& getFilePath() const; std::string getFileName() const; - const std::vector& getActiveTokenIds() const; - const std::vector& getActiveLocalSymbolIds() const; - const std::vector& getFocusedTokenIds() const; - - std::vector getErrorMessages() const; - bool hasErrors() const; - QtCodeSnippet* addCodeSnippet(const CodeSnippetParams& params); QtCodeSnippet* insertCodeSnippet(const CodeSnippetParams& params); - QtCodeSnippet* findFirstActiveSnippet() const; + QtCodeSnippet* getSnippetForLocationId(Id locationId) const; QtCodeSnippet* getFileSnippet() const; - bool isCollapsedActiveFile() const; + bool isCollapsed() const; + + void requestContent() const; void updateContent(); void setLocationFile(std::shared_ptr locationFile, int refCount); @@ -61,9 +56,7 @@ public: void setSnippets(); void setMaximized(); - void requestSnippets() const; bool hasSnippets() const; - void updateSnippets(); uint getScrollToLine() const; @@ -88,7 +81,7 @@ private: QtThreadedFunctor<> m_updateTitleBarFunctor; - QtCodeFileList* m_parent; + QtCodeNavigator* m_navigator; QPushButton* m_titleBar; QPushButton* m_title; @@ -106,7 +99,7 @@ private: TimePoint m_modificationTime; std::shared_ptr m_locationFile; - mutable bool m_snippetsRequested; + mutable bool m_contentRequested; uint m_scrollToLine; }; diff --git a/src/lib_gui/qt/element/QtCodeFileList.cpp b/src/lib_gui/qt/element/QtCodeFileList.cpp index c54f2748..85a33896 100644 --- a/src/lib_gui/qt/element/QtCodeFileList.cpp +++ b/src/lib_gui/qt/element/QtCodeFileList.cpp @@ -1,39 +1,27 @@ #include "qt/element/QtCodeFileList.h" -#include -#include -#include -#include #include #include "utility/file/FileSystem.h" -#include "utility/messaging/type/MessageScrollCode.h" #include "data/location/TokenLocationFile.h" #include "qt/element/QtCodeFile.h" +#include "qt/element/QtCodeNavigator.h" #include "qt/element/QtCodeSnippet.h" -QtCodeFileList::QtCodeFileList(QWidget* parent) - : QScrollArea(parent) +QtCodeFileList::QtCodeFileList(QtCodeNavigator* navigator) + : QFrame() + , m_navigator(navigator) , m_scrollToFile(nullptr) - , m_value(0) + , m_scrollToLocationId(0) { - setObjectName("code_file_list_base"); + setObjectName("code_file_list"); - m_frame = std::make_shared(this); - m_frame->setObjectName("code_file_list"); - - QVBoxLayout* layout = new QVBoxLayout(m_frame.get()); + QVBoxLayout* layout = new QVBoxLayout(); layout->setSpacing(8); layout->setContentsMargins(8, 8, 8, 8); layout->setAlignment(Qt::AlignTop); - m_frame->setLayout(layout); - - setWidgetResizable(true); - setWidget(m_frame.get()); - - connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled(int))); - connect(this, SIGNAL(shouldScrollToSnippet(QtCodeSnippet*, uint)), this, SLOT(scrollToSnippet(QtCodeSnippet*, uint)), Qt::QueuedConnection); + setLayout(layout); } QtCodeFileList::~QtCodeFileList() @@ -75,143 +63,53 @@ void QtCodeFileList::addFile(std::shared_ptr locationFile, in void QtCodeFileList::clearCodeSnippets() { m_files.clear(); - this->verticalScrollBar()->setValue(0); } -const std::vector& QtCodeFileList::getActiveTokenIds() const +void QtCodeFileList::showLocation(const FilePath& filePath, Id locationId, bool scrollTo) { - return m_activeTokenIds; -} + updateFiles(); -void QtCodeFileList::setActiveTokenIds(const std::vector& activeTokenIds) -{ - m_activeTokenIds = activeTokenIds; - m_activeLocalSymbolIds.clear(); -} + QtCodeFile* file = getFile(filePath); -const std::vector& QtCodeFileList::getActiveLocalSymbolIds() const -{ - return m_activeLocalSymbolIds; -} - -void QtCodeFileList::setActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds) -{ - m_activeLocalSymbolIds = activeLocalSymbolIds; -} - -const std::vector& QtCodeFileList::getFocusedTokenIds() const -{ - return m_focusedTokenIds; -} - -void QtCodeFileList::setFocusedTokenIds(const std::vector& focusedTokenIds) -{ - m_focusedTokenIds = focusedTokenIds; -} - -std::vector QtCodeFileList::getErrorMessages() const -{ - std::vector errorMessages; - for (const ErrorInfo& error : m_errorInfos) + if (file->isCollapsed()) { - errorMessages.push_back(error.message); - } - return errorMessages; -} + file->requestContent(); -void QtCodeFileList::setErrorInfos(const std::vector& errorInfos) -{ - m_errorInfos = errorInfos; -} - -bool QtCodeFileList::hasErrors() const -{ - return m_errorInfos.size() > 0; -} - -size_t QtCodeFileList::getFatalErrorCountForFile(const FilePath& filePath) const -{ - size_t fatalErrorCount = 0; - for (const ErrorInfo& error : m_errorInfos) - { - if (error.filePath == filePath && error.isFatal) + if (scrollTo) { - fatalErrorCount++; + m_scrollToFile = file; + m_scrollToLocationId = locationId; } } - return fatalErrorCount; -} - -void QtCodeFileList::showActiveTokenIds() -{ - updateFiles(); -} - -void QtCodeFileList::showFirstActiveSnippet(bool scrollTo) -{ - updateFiles(); - - QtCodeSnippet* snippet = getFirstActiveSnippet(); - - if (!snippet) + else { - expandActiveSnippetFile(scrollTo); - return; - } - - if (!snippet->isVisible()) - { - snippet->getFile()->setSnippets(); - } - - if (scrollTo) - { - emit shouldScrollToSnippet(snippet, 0); + scrollToLocation(file, locationId, scrollTo); } } -void QtCodeFileList::focusTokenIds(const std::vector& focusedTokenIds) +void QtCodeFileList::requestFileContent(const FilePath& filePath) { - setFocusedTokenIds(focusedTokenIds); - updateFiles(); -} - -void QtCodeFileList::defocusTokenIds() -{ - setFocusedTokenIds(std::vector()); - updateFiles(); + getFile(filePath)->requestContent(); } void QtCodeFileList::setFileMinimized(const FilePath path) { - QtCodeFile* file = getFile(path); - if (file) - { - file->setMinimized(); - } + getFile(path)->setMinimized(); } void QtCodeFileList::setFileSnippets(const FilePath path) { - QtCodeFile* file = getFile(path); - if (file) - { - file->setSnippets(); - } + getFile(path)->setSnippets(); } void QtCodeFileList::setFileMaximized(const FilePath path) { - QtCodeFile* file = getFile(path); - if (file) - { - file->setMaximized(); - } + getFile(path)->setMaximized(); } void QtCodeFileList::updateFiles() { - for (std::shared_ptr file: m_files) + for (std::shared_ptr file : m_files) { file->updateContent(); } @@ -225,57 +123,65 @@ void QtCodeFileList::showContents() } } +void QtCodeFileList::scrollToLocation(QtCodeFile* file, Id locationId, bool scrollTo) +{ + QtCodeSnippet* snippet = nullptr; + + if (locationId) + { + snippet = file->getSnippetForLocationId(locationId); + } + else + { + snippet = file->getFileSnippet(); + } + + if (!snippet) + { + return; + } + + if (!snippet->isVisible()) + { + file->setSnippets(); + } + + if (scrollTo) + { + if (locationId) + { + emit shouldScrollToSnippet(snippet, snippet->getLineNumberForLocationId(locationId)); + } + else + { + emit shouldScrollToSnippet(snippet, 1); + } + } +} + void QtCodeFileList::scrollToLine(std::string filename, unsigned int line) { for (std::shared_ptr file: m_files) { - if( filename == file->getFilePath().str() ) + if (filename == file->getFilePath().str()) { emit shouldScrollToSnippet(file->getFileSnippet(), line); return; } } - } -void QtCodeFileList::scrollToValue(int value) -{ - m_value = value; - QTimer::singleShot(100, this, SLOT(setValue())); -} - -void QtCodeFileList::scrollToActiveFileIfRequested() +void QtCodeFileList::scrollToSnippetIfRequested() { if (m_scrollToFile && m_scrollToFile->hasSnippets()) { - showFirstActiveSnippet(true); + scrollToLocation(m_scrollToFile, m_scrollToLocationId, true); + m_scrollToFile = nullptr; + m_scrollToLocationId = 0; } } -void QtCodeFileList::scrolled(int value) -{ - MessageScrollCode(value).dispatch(); -} - -void QtCodeFileList::scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber) -{ - if (lineNumber == 0) - { - lineNumber = snippet->getFirstActiveLineNumber(); - } - - if (lineNumber) - { - this->ensureWidgetVisibleAnimated(snippet, snippet->getLineRectForLineNumber(lineNumber)); - } -} - -void QtCodeFileList::setValue() -{ - this->verticalScrollBar()->setValue(m_value); -} - QtCodeFile* QtCodeFileList::getFile(const FilePath filePath) { QtCodeFile* file = nullptr; @@ -291,81 +197,14 @@ QtCodeFile* QtCodeFileList::getFile(const FilePath filePath) if (!file) { - std::shared_ptr filePtr = std::make_shared(filePath, this); + std::shared_ptr filePtr = std::make_shared(filePath, m_navigator); m_files.push_back(filePtr); file = filePtr.get(); - m_frame->layout()->addWidget(file); + layout()->addWidget(file); file->hide(); } return file; } - -QtCodeSnippet* QtCodeFileList::getFirstActiveSnippet() const -{ - QtCodeSnippet* snippet = nullptr; - for (std::shared_ptr file: m_files) - { - snippet = file->findFirstActiveSnippet(); - if (snippet) - { - break; - } - } - - return snippet; -} - -void QtCodeFileList::expandActiveSnippetFile(bool scrollTo) -{ - for (std::shared_ptr file: m_files) - { - if (file->isCollapsedActiveFile()) - { - file->requestSnippets(); - - if (scrollTo) - { - m_scrollToFile = file.get(); - } - - return; - } - } -} - -void QtCodeFileList::ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect) -{ - if (!widget()->isAncestorOf(childWidget)) - { - return; - } - - const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect(); - const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect(); - QRect focusRect = (microFocus != defaultMicroFocus) - ? QRect(childWidget->mapTo(widget(), microFocus.topLeft()), microFocus.size()) - : QRect(childWidget->mapTo(widget(), QPoint(0, 0)), childWidget->size()); - const QRect visibleRect(-widget()->pos(), viewport()->size()); - - if (rect.height() > 0) - { - focusRect = QRect(childWidget->mapTo(widget(), rect.topLeft().toPoint()), rect.size().toSize()); - focusRect.adjust(0, 0, 0, 100); - } - - QScrollBar* scrollBar = verticalScrollBar(); - int value = focusRect.center().y() - visibleRect.center().y(); - - if (scrollBar && value != 0) - { - QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value"); - anim->setDuration(300); - anim->setStartValue(scrollBar->value()); - anim->setEndValue(scrollBar->value() + value); - anim->setEasingCurve(QEasingCurve::InOutQuad); - anim->start(); - } -} diff --git a/src/lib_gui/qt/element/QtCodeFileList.h b/src/lib_gui/qt/element/QtCodeFileList.h index 46032d72..e385cdc3 100644 --- a/src/lib_gui/qt/element/QtCodeFileList.h +++ b/src/lib_gui/qt/element/QtCodeFileList.h @@ -5,7 +5,6 @@ #include #include -#include #include "utility/file/FilePath.h" #include "utility/TimePoint.h" @@ -15,11 +14,12 @@ #include "component/view/helper/CodeSnippetParams.h" class QtCodeFile; +class QtCodeNavigator; class QtCodeSnippet; class TokenLocationFile; class QtCodeFileList - : public QScrollArea + : public QFrame { Q_OBJECT @@ -27,7 +27,7 @@ signals: void shouldScrollToSnippet(QtCodeSnippet* widget, uint lineNumber); public: - QtCodeFileList(QWidget* parent = 0); + QtCodeFileList(QtCodeNavigator* navigator); virtual ~QtCodeFileList(); void addCodeSnippet(const CodeSnippetParams& params, bool insert = false); @@ -35,27 +35,9 @@ public: void clearCodeSnippets(); - const std::vector& getActiveTokenIds() const; - void setActiveTokenIds(const std::vector& activeTokenIds); + void showLocation(const FilePath& filePath, Id locationId, bool scrollTo); - const std::vector& getActiveLocalSymbolIds() const; - void setActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds); - - const std::vector& getFocusedTokenIds() const; - void setFocusedTokenIds(const std::vector& focusedTokenIds); - - std::vector getErrorMessages() const; - void setErrorInfos(const std::vector& errorInfos); - - bool hasErrors() const; - size_t getFatalErrorCountForFile(const FilePath& filePath) const; - - void showActiveTokenIds(); - - void showFirstActiveSnippet(bool scrollTo); - - void focusTokenIds(const std::vector& focusedTokenIds); - void defocusTokenIds(); + void requestFileContent(const FilePath& filePath); void setFileMinimized(const FilePath path); void setFileSnippets(const FilePath path); @@ -63,32 +45,23 @@ public: void updateFiles(); void showContents(); - void scrollToValue(int value); - void scrollToLine(std::string, unsigned int line); - void scrollToActiveFileIfRequested(); -private slots: - void scrolled(int value); - void scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber); - void setValue(); + void scrollToLocation(QtCodeFile* file, Id locationId, bool scrollTo); + void scrollToLine(std::string filename, unsigned int line); + void scrollToSnippetIfRequested(); private: QtCodeFile* getFile(const FilePath filePath); QtCodeSnippet* getFirstActiveSnippet() const; void expandActiveSnippetFile(bool scrollTo); - void ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect); - std::shared_ptr m_frame; + QtCodeNavigator* m_navigator; + std::vector> m_files; - std::vector m_activeTokenIds; - std::vector m_activeLocalSymbolIds; - std::vector m_focusedTokenIds; - std::vector m_errorInfos; - QtCodeFile* m_scrollToFile; - int m_value; + Id m_scrollToLocationId; }; #endif // QT_CODE_FILE_LIST diff --git a/src/lib_gui/qt/element/QtCodeNavigator.cpp b/src/lib_gui/qt/element/QtCodeNavigator.cpp new file mode 100644 index 00000000..364ff05b --- /dev/null +++ b/src/lib_gui/qt/element/QtCodeNavigator.cpp @@ -0,0 +1,512 @@ +#include "qt/element/QtCodeNavigator.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "data/location/TokenLocation.h" +#include "data/location/TokenLocationCollection.h" +#include "data/location/TokenLocationFile.h" +#include "utility/logging/logging.h" +#include "utility/messaging/type/MessageScrollCode.h" +#include "utility/messaging/type/MessageShowReference.h" + +#include "qt/element/QtCodeSnippet.h" + +QtCodeNavigator::QtCodeNavigator(QWidget* parent) + : QWidget(parent) + , m_switchReferenceFunctor(std::bind(&QtCodeNavigator::doSwitchReference, this, std::placeholders::_1)) + , m_value(0) + , m_refIndex(0) +{ + QVBoxLayout* layout = new QVBoxLayout(); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + { + QWidget* navigation = new QWidget(); + QHBoxLayout* navLayout = new QHBoxLayout(); + navLayout->setSpacing(3); + navLayout->setContentsMargins(7, 7, 7, 7); + + QPushButton* listButton = new QPushButton("list"); + navLayout->addWidget(listButton); + + QPushButton* fileButton = new QPushButton("file"); + fileButton->setEnabled(false); + navLayout->addWidget(fileButton); + + navLayout->addStretch(); + + m_refLabel = new QLabel("0/0 references"); + navLayout->addWidget(m_refLabel); + + navLayout->addStretch(); + + m_prevButton = new QPushButton("<"); + m_nextButton = new QPushButton(">"); + + m_prevButton->setToolTip("previous reference"); + m_nextButton->setToolTip("next reference"); + + navLayout->addWidget(m_prevButton); + navLayout->addWidget(m_nextButton); + + connect(m_prevButton, SIGNAL(clicked()), this, SLOT(previousReference())); + connect(m_nextButton, SIGNAL(clicked()), this, SLOT(nextReference())); + + navigation->setLayout(navLayout); + layout->addWidget(navigation); + + navigation->hide(); + } + + m_scrollArea = new QScrollArea(this); + m_scrollArea->setObjectName("code_container"); + + m_list = new QtCodeFileList(this); + layout->addWidget(m_scrollArea); + + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setWidget(m_list); + + connect(m_scrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled(int))); + connect(m_list, SIGNAL(shouldScrollToSnippet(QtCodeSnippet*, uint)), + this, SLOT(scrollToSnippet(QtCodeSnippet*, uint)), Qt::QueuedConnection); +} + +QtCodeNavigator::~QtCodeNavigator() +{ +} + +void QtCodeNavigator::addCodeSnippet(const CodeSnippetParams& params, bool insert) +{ + m_list->addCodeSnippet(params, insert); +} + +void QtCodeNavigator::addFile(std::shared_ptr locationFile, int refCount, TimePoint modificationTime) +{ + m_list->addFile(locationFile, refCount, modificationTime); + + if (locationFile->isWholeCopy) + { + Reference ref; + ref.filePath = locationFile->getFilePath(); + ref.tokenId = 0; + ref.locationId = 0; + + m_references.push_back(ref); + } + else + { + locationFile->forEachStartTokenLocation( + [&](TokenLocation* location) + { + if (!location->isScopeTokenLocation()) + { + Reference ref; + ref.filePath = location->getFilePath(); + ref.tokenId = location->getTokenId(); + ref.locationId = location->getId(); + + m_references.push_back(ref); + } + } + ); + } +} + +void QtCodeNavigator::clearCodeSnippets() +{ + m_list->clearCodeSnippets(); + m_scrollArea->verticalScrollBar()->setValue(0); + + m_currentActiveTokenIds.clear(); + m_activeTokenIds.clear(); + m_activeLocalSymbolIds.clear(); + m_focusedTokenIds.clear(); + m_errorInfos.clear(); + + m_references.clear(); + m_refIndex = 0; +} + +const std::vector& QtCodeNavigator::getCurrentActiveTokenIds() const +{ + return m_currentActiveTokenIds; +} + +void QtCodeNavigator::setCurrentActiveTokenIds(const std::vector& currentActiveTokenIds) +{ + m_currentActiveTokenIds = currentActiveTokenIds; + m_currentActiveLocationIds.clear(); +} + +const std::vector& QtCodeNavigator::getCurrentActiveLocationIds() const +{ + return m_currentActiveLocationIds; +} + +void QtCodeNavigator::setCurrentActiveLocationIds(const std::vector& currentActiveLocationIds) +{ + m_currentActiveLocationIds = currentActiveLocationIds; + m_currentActiveTokenIds.clear(); +} + +const std::vector& QtCodeNavigator::getActiveTokenIds() const +{ + return m_activeTokenIds; +} + +void QtCodeNavigator::setActiveTokenIds(const std::vector& activeTokenIds) +{ + setCurrentActiveTokenIds(activeTokenIds); + + m_activeTokenIds = activeTokenIds; + m_activeLocalSymbolIds.clear(); +} + +const std::vector& QtCodeNavigator::getActiveLocalSymbolIds() const +{ + return m_activeLocalSymbolIds; +} + +void QtCodeNavigator::setActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds) +{ + m_activeLocalSymbolIds = activeLocalSymbolIds; +} + +const std::vector& QtCodeNavigator::getFocusedTokenIds() const +{ + return m_focusedTokenIds; +} + +void QtCodeNavigator::setFocusedTokenIds(const std::vector& focusedTokenIds) +{ + m_focusedTokenIds = focusedTokenIds; +} + +std::vector QtCodeNavigator::getErrorMessages() const +{ + std::vector errorMessages; + for (const ErrorInfo& error : m_errorInfos) + { + errorMessages.push_back(error.message); + } + return errorMessages; +} + +void QtCodeNavigator::setErrorInfos(const std::vector& errorInfos) +{ + m_errorInfos = errorInfos; +} + +bool QtCodeNavigator::hasErrors() const +{ + return m_errorInfos.size() > 0; +} + +size_t QtCodeNavigator::getFatalErrorCountForFile(const FilePath& filePath) const +{ + size_t fatalErrorCount = 0; + for (const ErrorInfo& error : m_errorInfos) + { + if (error.filePath == filePath && error.isFatal) + { + fatalErrorCount++; + } + } + return fatalErrorCount; +} + +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; + } + + Id tokenId = activeTokenIds[0]; + + std::vector locationIds; + + Id firstLocationId = 0; + FilePath firstFilePath; + 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) + { + locationIds.push_back(ref.locationId); + + if (!firstLocationId) + { + firstLocationId = ref.locationId; + firstFilePath = ref.filePath; + } + } + + filePathOrder.emplace(ref.filePath, filePathOrder.size()); + } + + if (!locationIds.size()) + { + collection->forEachTokenLocation( + [&](TokenLocation* location) + { + if (location->getTokenId() != tokenId) + { + return; + } + + locationIds.push_back(location->getId()); + filePathsToExpand.insert(location->getFilePath()); + + if (firstFilePath.empty() || filePathOrder[location->getFilePath()] < filePathOrder[firstFilePath]) + { + firstFilePath = location->getFilePath(); + firstLocationId = location->getId(); + } + } + ); + } + + setCurrentActiveLocationIds(locationIds); + updateFiles(); + + for (const FilePath& filePath : filePathsToExpand) + { + m_list->requestFileContent(filePath); + } + + if (firstLocationId) + { + m_list->showLocation(firstFilePath, firstLocationId, scrollTo); + + m_refIndex = 0; + updateRefLabel(); + } +} + +void QtCodeNavigator::focusTokenIds(const std::vector& focusedTokenIds) +{ + setFocusedTokenIds(focusedTokenIds); + updateFiles(); +} + +void QtCodeNavigator::defocusTokenIds() +{ + setFocusedTokenIds(std::vector()); + updateFiles(); +} + +void QtCodeNavigator::setFileMinimized(const FilePath path) +{ + m_list->setFileMinimized(path); +} + +void QtCodeNavigator::setFileSnippets(const FilePath path) +{ + m_list->setFileSnippets(path); +} + +void QtCodeNavigator::setFileMaximized(const FilePath path) +{ + m_list->setFileMaximized(path); +} + +void QtCodeNavigator::setupFiles() +{ + std::set filePathsToExpand; + for (const Reference& ref : m_references) + { + if (filePathsToExpand.find(ref.filePath) == filePathsToExpand.end()) + { + m_list->requestFileContent(ref.filePath); + filePathsToExpand.insert(ref.filePath); + + if (filePathsToExpand.size() >= 3) + { + break; + } + } + } + + m_refIndex = 0; + updateRefLabel(); +} + +void QtCodeNavigator::updateFiles() +{ + m_list->updateFiles(); +} + +void QtCodeNavigator::showContents() +{ + m_list->showContents(); +} + +void QtCodeNavigator::scrollToValue(int value) +{ + m_value = value; + QTimer::singleShot(100, this, SLOT(setValue())); +} + +void QtCodeNavigator::scrollToLine(std::string filename, unsigned int line) +{ + m_list->scrollToLine(filename, line); +} + +void QtCodeNavigator::scrollToSnippetIfRequested() +{ + m_list->scrollToSnippetIfRequested(); +} + +void QtCodeNavigator::scrolled(int value) +{ + MessageScrollCode(value).dispatch(); +} + +void QtCodeNavigator::scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber) +{ + if (lineNumber) + { + this->ensureWidgetVisibleAnimated(snippet, snippet->getLineRectForLineNumber(lineNumber)); + } +} + +void QtCodeNavigator::setValue() +{ + m_scrollArea->verticalScrollBar()->setValue(m_value); +} + +void QtCodeNavigator::previousReference() +{ + if (!m_references.size()) + { + return; + } + + if (m_refIndex < 2) + { + m_refIndex = m_references.size(); + } + else + { + m_refIndex--; + } + + showCurrentReference(); +} + +void QtCodeNavigator::nextReference() +{ + if (!m_references.size()) + { + return; + } + + m_refIndex++; + + if (m_refIndex == m_references.size() + 1) + { + m_refIndex = 1; + } + + showCurrentReference(); +} + +void QtCodeNavigator::showCurrentReference() +{ + const Reference& ref = m_references[m_refIndex - 1]; + + setCurrentActiveLocationIds(std::vector(1, ref.locationId)); + m_list->showLocation(ref.filePath, ref.locationId, true); + + updateRefLabel(); + + MessageShowReference(m_refIndex, ref.tokenId, ref.locationId).dispatch(); +} + +void QtCodeNavigator::updateRefLabel() +{ + size_t n = m_references.size(); + size_t t = m_refIndex; + + if (t) + { + m_refLabel->setText(QString::number(t) + "/" + QString::number(n) + " references"); + } + else + { + m_refLabel->setText(QString::number(n) + " references"); + } + + m_prevButton->setEnabled(n > 1); + m_nextButton->setEnabled(n > 1); +} + +void QtCodeNavigator::ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect) +{ + QScrollArea* area = m_scrollArea; + + if (!area->widget()->isAncestorOf(childWidget)) + { + return; + } + + const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect(); + const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect(); + QRect focusRect = (microFocus != defaultMicroFocus) + ? QRect(childWidget->mapTo(area->widget(), microFocus.topLeft()), microFocus.size()) + : QRect(childWidget->mapTo(area->widget(), QPoint(0, 0)), childWidget->size()); + const QRect visibleRect(-area->widget()->pos(), area->viewport()->size()); + + if (rect.height() > 0) + { + focusRect = QRect(childWidget->mapTo(area->widget(), rect.topLeft().toPoint()), rect.size().toSize()); + focusRect.adjust(0, 0, 0, 100); + } + + QScrollBar* scrollBar = area->verticalScrollBar(); + int value = focusRect.center().y() - visibleRect.center().y(); + + if (scrollBar && value != 0) + { + QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value"); + anim->setDuration(300); + anim->setStartValue(scrollBar->value()); + anim->setEndValue(scrollBar->value() + value); + anim->setEasingCurve(QEasingCurve::InOutQuad); + anim->start(); + } +} + +void QtCodeNavigator::handleMessage(MessageCodeReference* message) +{ + m_switchReferenceFunctor(message->type); +} + +void QtCodeNavigator::doSwitchReference(MessageCodeReference::ReferenceType type) +{ + if (type == MessageCodeReference::REFERENCE_PREVIOUS) + { + previousReference(); + } + else if (type == MessageCodeReference::REFERENCE_NEXT) + { + nextReference(); + } +} diff --git a/src/lib_gui/qt/element/QtCodeNavigator.h b/src/lib_gui/qt/element/QtCodeNavigator.h new file mode 100644 index 00000000..08ad2829 --- /dev/null +++ b/src/lib_gui/qt/element/QtCodeNavigator.h @@ -0,0 +1,118 @@ +#ifndef QT_CODE_NAVIGATOR_H +#define QT_CODE_NAVIGATOR_H + +#include +#include + +#include "qt/element/QtCodeFileList.h" +#include "qt/utility/QtThreadedFunctor.h" +#include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageCodeReference.h" + +class QLabel; +class QPushButton; +class TokenLocationCollection; +class TokenLocationFile; + +class QtCodeNavigator + : public QWidget + , public MessageListener +{ + Q_OBJECT + +public: + QtCodeNavigator(QWidget* parent = nullptr); + virtual ~QtCodeNavigator(); + + void addCodeSnippet(const CodeSnippetParams& params, bool insert = false); + void addFile(std::shared_ptr locationFile, int refCount, TimePoint modificationTime); + + void clearCodeSnippets(); + + const std::vector& getCurrentActiveTokenIds() const; + void setCurrentActiveTokenIds(const std::vector& currentActiveTokenIds); + + const std::vector& getCurrentActiveLocationIds() const; + void setCurrentActiveLocationIds(const std::vector& currentActiveLocationIds); + + const std::vector& getActiveTokenIds() const; + void setActiveTokenIds(const std::vector& activeTokenIds); + + const std::vector& getActiveLocalSymbolIds() const; + void setActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds); + + const std::vector& getFocusedTokenIds() const; + void setFocusedTokenIds(const std::vector& focusedTokenIds); + + std::vector getErrorMessages() const; + void setErrorInfos(const std::vector& errorInfos); + + bool hasErrors() const; + size_t getFatalErrorCountForFile(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 setupFiles(); + void updateFiles(); + void showContents(); + + void scrollToValue(int value); + void scrollToLine(std::string filename, unsigned int line); + void scrollToSnippetIfRequested(); + +private slots: + void scrolled(int value); + void scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber); + void setValue(); + + void previousReference(); + void nextReference(); + +private: + struct Reference + { + FilePath filePath; + Id tokenId; + Id locationId; + }; + + void showCurrentReference(); + void updateRefLabel(); + + void ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect); + + void handleMessage(MessageCodeReference* message); + void doSwitchReference(MessageCodeReference::ReferenceType type); + + QtThreadedFunctor m_switchReferenceFunctor; + + QScrollArea* m_scrollArea; + QtCodeFileList* m_list; + + std::vector m_currentActiveTokenIds; + std::vector m_currentActiveLocationIds; + + std::vector m_activeTokenIds; + std::vector m_activeLocalSymbolIds; + std::vector m_focusedTokenIds; + std::vector m_errorInfos; + + int m_value; + + QLabel* m_refLabel; + QPushButton* m_prevButton; + QPushButton* m_nextButton; + + std::vector m_references; + size_t m_refIndex; +}; + +#endif // QT_CODE_NAVIGATOR_H diff --git a/src/lib_gui/qt/element/QtCodeSnippet.cpp b/src/lib_gui/qt/element/QtCodeSnippet.cpp index 9ac6d165..b77e4c0c 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.cpp +++ b/src/lib_gui/qt/element/QtCodeSnippet.cpp @@ -8,9 +8,11 @@ #include "utility/text/TextAccess.h" #include "data/location/TokenLocationFile.h" +#include "qt/element/QtCodeNavigator.h" #include "qt/element/QtCodeFile.h" -std::shared_ptr QtCodeSnippet::merged(QtCodeSnippet* a, QtCodeSnippet* b, QtCodeFile* file) +std::shared_ptr QtCodeSnippet::merged( + QtCodeSnippet* a, QtCodeSnippet* b, QtCodeNavigator* navigator, QtCodeFile* file) { QtCodeSnippet* first = a->getStartLineNumber() < b->getStartLineNumber() ? a : b; QtCodeSnippet* second = a->getStartLineNumber() > b->getStartLineNumber() ? a : b; @@ -53,18 +55,20 @@ std::shared_ptr QtCodeSnippet::merged(QtCodeSnippet* a, QtCodeSni params.code = code; params.locationFile = locationFile; - return std::shared_ptr(new QtCodeSnippet(params, file)); + return std::shared_ptr(new QtCodeSnippet(params, navigator, file)); } -QtCodeSnippet::QtCodeSnippet(const CodeSnippetParams& params, QtCodeFile* file) +QtCodeSnippet::QtCodeSnippet(const CodeSnippetParams& params, QtCodeNavigator* navigator, QtCodeFile* file) : QFrame(file) + , m_navigator(navigator) + , m_file(file) , m_titleId(params.titleId) , m_titleString(params.title) , m_footerId(params.footerId) , m_footerString(params.footer) , m_title(nullptr) , m_footer(nullptr) - , m_codeArea(std::make_shared(params.startLineNumber, params.code, params.locationFile, file, this)) + , m_codeArea(std::make_shared(params.startLineNumber, params.code, params.locationFile, navigator, this)) { setObjectName("code_snippet"); @@ -116,7 +120,7 @@ QtCodeSnippet::~QtCodeSnippet() QtCodeFile* QtCodeSnippet::getFile() const { - return m_codeArea->getFile(); + return m_file; } uint QtCodeSnippet::getStartLineNumber() const @@ -146,19 +150,14 @@ void QtCodeSnippet::updateContent() updateDots(); } -bool QtCodeSnippet::isActive() const -{ - return m_codeArea->isActive(); -} - void QtCodeSnippet::setIsActiveFile(bool isActiveFile) { m_codeArea->setIsActiveFile(isActiveFile); } -uint QtCodeSnippet::getFirstActiveLineNumber() const +uint QtCodeSnippet::getLineNumberForLocationId(Id locationId) const { - return m_codeArea->getFirstActiveLineNumber(); + return m_codeArea->getLineNumberForLocationId(locationId); } QRectF QtCodeSnippet::getLineRectForLineNumber(uint lineNumber) const @@ -177,7 +176,7 @@ void QtCodeSnippet::clickedTitle() if (m_titleId > 0) { - MessageShowScope(m_titleId, getFile()->hasErrors()).dispatch(); + MessageShowScope(m_titleId, m_navigator->hasErrors()).dispatch(); } else { @@ -190,7 +189,7 @@ void QtCodeSnippet::clickedFooter() if (m_footerId > 0) { getFile()->setScrollToLine(getEndLineNumber()); - MessageShowScope(m_footerId, getFile()->hasErrors()).dispatch(); + MessageShowScope(m_footerId, m_navigator->hasErrors()).dispatch(); } } diff --git a/src/lib_gui/qt/element/QtCodeSnippet.h b/src/lib_gui/qt/element/QtCodeSnippet.h index 97c3bd42..9b8414f6 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.h +++ b/src/lib_gui/qt/element/QtCodeSnippet.h @@ -15,6 +15,7 @@ class QBoxLayout; class QPushButton; class QtCodeFile; +class QtCodeNavigator; class TokenLocationFile; class QtCodeSnippet @@ -23,9 +24,10 @@ class QtCodeSnippet Q_OBJECT public: - static std::shared_ptr merged(QtCodeSnippet* a, QtCodeSnippet* b, QtCodeFile* file); + static std::shared_ptr merged( + QtCodeSnippet* a, QtCodeSnippet* b, QtCodeNavigator* navigator, QtCodeFile* file); - QtCodeSnippet(const CodeSnippetParams& params, QtCodeFile* file); + QtCodeSnippet(const CodeSnippetParams& params, QtCodeNavigator* navigator, QtCodeFile* file); virtual ~QtCodeSnippet(); QtCodeFile* getFile() const; @@ -38,11 +40,9 @@ public: void updateLineNumberAreaWidthForDigits(int digits); void updateContent(); - bool isActive() const; - void setIsActiveFile(bool isActiveFile); - uint getFirstActiveLineNumber() const; + uint getLineNumberForLocationId(Id locationId) const; QRectF getLineRectForLineNumber(uint lineNumber) const; std::string getCode() const; @@ -55,6 +55,9 @@ private: QPushButton* createScopeLine(QBoxLayout* layout); void updateDots(); + QtCodeNavigator* m_navigator; + QtCodeFile* m_file; + Id m_titleId; std::string m_titleString; diff --git a/src/lib_gui/qt/view/QtCodeView.cpp b/src/lib_gui/qt/view/QtCodeView.cpp index b89cd2a0..79c15d3b 100644 --- a/src/lib_gui/qt/view/QtCodeView.cpp +++ b/src/lib_gui/qt/view/QtCodeView.cpp @@ -5,7 +5,7 @@ #include "qt/utility/utilityQt.h" #include "qt/element/QtCodeArea.h" -#include "qt/element/QtCodeFileList.h" +#include "qt/element/QtCodeNavigator.h" #include "qt/utility/QtHighlighter.h" #include "qt/view/QtViewWidgetWrapper.h" #include "settings/ColorScheme.h" @@ -18,7 +18,8 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout) , m_addCodeSnippetsFunctor(std::bind(&QtCodeView::doAddCodeSnippets, this, std::placeholders::_1, std::placeholders::_2)) , m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1)) , m_setFileStateFunctor(std::bind(&QtCodeView::doSetFileState, this, std::placeholders::_1, std::placeholders::_2)) - , m_doShowFirstActiveSnippetFunctor(std::bind(&QtCodeView::doShowFirstActiveSnippet, this, std::placeholders::_1, std::placeholders::_2)) + , m_doShowActiveSnippetFunctor( + std::bind(&QtCodeView::doShowActiveSnippet, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) , m_doShowActiveTokenIdsFunctor(std::bind(&QtCodeView::doShowActiveTokenIds, this, std::placeholders::_1)) , m_doShowActiveLocalSymbolIdsFunctor(std::bind(&QtCodeView::doShowActiveLocalSymbolIds, this, std::placeholders::_1)) , m_focusTokenIdsFunctor(std::bind(&QtCodeView::doFocusTokenIds, this, std::placeholders::_1)) @@ -27,7 +28,7 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout) , m_scrollToValueFunctor(std::bind(&QtCodeView::doScrollToValue, this, std::placeholders::_1)) , m_scrollToLineFunctor(std::bind(&QtCodeView::doScrollToLine, this, std::placeholders::_1, std::placeholders::_2)) { - m_widget = new QtCodeFileList(); + m_widget = new QtCodeNavigator(); setStyleSheet(); } @@ -54,12 +55,6 @@ void QtCodeView::clear() m_clearFunctor(); m_errorInfos.clear(); - m_activeTokenIds.clear(); -} - -void QtCodeView::setActiveTokenIds(const std::vector& activeTokenIds) -{ - m_activeTokenIds = activeTokenIds; } void QtCodeView::setErrorInfos(const std::vector& errorInfos) @@ -87,9 +82,10 @@ void QtCodeView::setFileState(const FilePath filePath, FileState state) m_setFileStateFunctor(filePath, state); } -void QtCodeView::showFirstActiveSnippet(const std::vector& activeTokenIds, bool scrollTo) +void QtCodeView::showActiveSnippet( + const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo) { - m_doShowFirstActiveSnippetFunctor(activeTokenIds, scrollTo); + m_doShowActiveSnippetFunctor(activeTokenIds, collection, scrollTo); } void QtCodeView::showActiveTokenIds(const std::vector& activeTokenIds) @@ -143,9 +139,7 @@ void QtCodeView::doClear() void QtCodeView::doShowCodeSnippets(const std::vector& snippets, const std::vector& activeTokenIds) { - setActiveTokenIds(activeTokenIds); - - m_widget->setActiveTokenIds(m_activeTokenIds); + m_widget->setActiveTokenIds(activeTokenIds); m_widget->setErrorInfos(m_errorInfos); for (const CodeSnippetParams& params : snippets) @@ -160,7 +154,7 @@ void QtCodeView::doShowCodeSnippets(const std::vector& snippe } } - m_widget->updateFiles(); + m_widget->setupFiles(); setStyleSheet(); // so property "isLast" of QtCodeSnippet is computed correctly } @@ -176,7 +170,7 @@ void QtCodeView::doAddCodeSnippets(const std::vector& snippet setStyleSheet(); // so property "isLast" of QtCodeSnippet is computed correctly - m_widget->scrollToActiveFileIfRequested(); + m_widget->scrollToSnippetIfRequested(); } void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) @@ -200,22 +194,22 @@ void QtCodeView::doSetFileState(const FilePath filePath, FileState state) } } -void QtCodeView::doShowFirstActiveSnippet(const std::vector& activeTokenIds, bool scrollTo) +void QtCodeView::doShowActiveSnippet( + const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo) { - m_widget->setActiveTokenIds(activeTokenIds); - m_widget->showFirstActiveSnippet(scrollTo); + m_widget->showActiveSnippet(activeTokenIds, collection, scrollTo); } void QtCodeView::doShowActiveTokenIds(const std::vector& activeTokenIds) { m_widget->setActiveTokenIds(activeTokenIds); - m_widget->showActiveTokenIds(); + m_widget->updateFiles(); } void QtCodeView::doShowActiveLocalSymbolIds(const std::vector& localSymbolIds) { m_widget->setActiveLocalSymbolIds(localSymbolIds); - m_widget->showActiveTokenIds(); + m_widget->updateFiles(); } void QtCodeView::doFocusTokenIds(const std::vector& focusedTokenIds) diff --git a/src/lib_gui/qt/view/QtCodeView.h b/src/lib_gui/qt/view/QtCodeView.h index a2a7bf35..198ff595 100644 --- a/src/lib_gui/qt/view/QtCodeView.h +++ b/src/lib_gui/qt/view/QtCodeView.h @@ -10,7 +10,7 @@ #include "qt/utility/QtThreadedFunctor.h" class QFrame; -class QtCodeFileList; +class QtCodeNavigator; class QWidget; class QtCodeView @@ -28,7 +28,6 @@ public: // CodeView implementation virtual void clear(); - virtual void setActiveTokenIds(const std::vector& activeTokenIds); virtual void setErrorInfos(const std::vector& errorInfos); virtual void showCodeSnippets(const std::vector& snippets, const std::vector& activeTokenIds); @@ -37,7 +36,8 @@ public: virtual void setFileState(const FilePath filePath, FileState state); - virtual void showFirstActiveSnippet(const std::vector& activeTokenIds, bool scrollTo); + virtual void showActiveSnippet( + const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo); virtual void showActiveTokenIds(const std::vector& activeTokenIds); virtual void showActiveLocalSymbolIds(const std::vector& activeLocalSymbolIds); @@ -59,7 +59,8 @@ private: void doSetFileState(const FilePath filePath, FileState state); - void doShowFirstActiveSnippet(const std::vector& activeTokenIds, bool scrollTo); + void doShowActiveSnippet( + const std::vector& activeTokenIds, std::shared_ptr collection, bool scrollTo); void doShowActiveTokenIds(const std::vector& activeTokenIds); void doShowActiveLocalSymbolIds(const std::vector& localSymbolIds); @@ -79,7 +80,7 @@ private: QtThreadedFunctor&, bool> m_addCodeSnippetsFunctor; QtThreadedFunctor m_showCodeFileFunctor; QtThreadedFunctor m_setFileStateFunctor; - QtThreadedFunctor&, bool> m_doShowFirstActiveSnippetFunctor; + QtThreadedFunctor&, std::shared_ptr, bool> m_doShowActiveSnippetFunctor; QtThreadedFunctor&> m_doShowActiveTokenIdsFunctor; QtThreadedFunctor&> m_doShowActiveLocalSymbolIdsFunctor; QtThreadedFunctor&> m_focusTokenIdsFunctor; @@ -88,9 +89,8 @@ private: QtThreadedFunctor m_scrollToValueFunctor; QtThreadedFunctor m_scrollToLineFunctor; - QtCodeFileList* m_widget; + QtCodeNavigator* m_widget; - std::vector m_activeTokenIds; std::vector m_errorInfos; }; diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp index 992e5b24..d4f5fc2a 100644 --- a/src/lib_gui/qt/window/QtMainWindow.cpp +++ b/src/lib_gui/qt/window/QtMainWindow.cpp @@ -24,6 +24,7 @@ #include "settings/ProjectSettings.h" #include "utility/file/FileSystem.h" #include "utility/logging/logging.h" +#include "utility/messaging/type/MessageCodeReference.h" #include "utility/messaging/type/MessageDispatchWhenLicenseValid.h" #include "utility/messaging/type/MessageFind.h" #include "utility/messaging/type/MessageInterruptTasks.h" @@ -432,6 +433,16 @@ void QtMainWindow::findFulltext() MessageFind(true).dispatch(); } +void QtMainWindow::codeReferencePrevious() +{ + MessageCodeReference(MessageCodeReference::REFERENCE_PREVIOUS).dispatch(); +} + +void QtMainWindow::codeReferenceNext() +{ + MessageCodeReference(MessageCodeReference::REFERENCE_NEXT).dispatch(); +} + void QtMainWindow::overview() { MessageSearch(std::vector(1, SearchMatch::createCommand(SearchMatch::COMMAND_ALL))).dispatch(); @@ -602,6 +613,11 @@ void QtMainWindow::setupEditMenu() menu->addSeparator(); + menu->addAction(tr("Code Reference Next"), this, SLOT(codeReferenceNext()), QKeySequence(Qt::CTRL + Qt::Key_G)); + menu->addAction(tr("Code Reference Previous"), this, SLOT(codeReferencePrevious()), QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_G)); + + menu->addSeparator(); + menu->addAction(tr("&To overview"), this, SLOT(overview()), QKeySequence::MoveToStartOfDocument); menu->addSeparator(); diff --git a/src/lib_gui/qt/window/QtMainWindow.h b/src/lib_gui/qt/window/QtMainWindow.h index 4795f0fc..ff383b69 100644 --- a/src/lib_gui/qt/window/QtMainWindow.h +++ b/src/lib_gui/qt/window/QtMainWindow.h @@ -115,6 +115,8 @@ public slots: void find(); void findFulltext(); + void codeReferencePrevious(); + void codeReferenceNext(); void overview(); void closeWindow();