diff --git a/bin/app/data/gui/code_view/code_view.css b/bin/app/data/gui/code_view/code_view.css index 9ca89eb7..803b066f 100644 --- a/bin/app/data/gui/code_view/code_view.css +++ b/bin/app/data/gui/code_view/code_view.css @@ -36,14 +36,25 @@ font-size: 14px; } -#code_area #maximize_button { - border: none; +#code_file #maximize_button { + background-color: lightgray; border-image: none; - margin: 5px; + border-radius: 8px; + margin: 1px; max-height: 16px; max-width: 16px; } +#code_file #maximize_button:enabled { + border-image: url(data/gui/code_view/images/button_maximize.png); +} + +#code_area #maximize_button { + background-color: none; + border-image: none; + margin: 5px; +} + #code_area #maximize_button:enabled { border-image: url(data/gui/code_view/images/button_maximize.png); } diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp index 6540e39c..214b6751 100644 --- a/src/app/qt/element/QtCodeFile.cpp +++ b/src/app/qt/element/QtCodeFile.cpp @@ -3,8 +3,10 @@ #include #include +#include "utility/messaging/type/MessageActivateFile.h" #include "utility/messaging/type/MessageShowFile.h" +#include "data/location/TokenLocationFile.h" #include "qt/element/QtCodeFileList.h" #include "qt/element/QtCodeSnippet.h" @@ -21,6 +23,12 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) layout->setAlignment(Qt::AlignTop); setLayout(layout); + QHBoxLayout* titleLayout = new QHBoxLayout(); + titleLayout->setMargin(0); + titleLayout->setSpacing(0); + titleLayout->setAlignment(Qt::AlignLeft); + layout->addLayout(titleLayout); + m_title = new QPushButton(filePath.fileName().c_str(), this); m_title->setObjectName("title_label"); m_title->minimumSizeHint(); // force font loading @@ -28,9 +36,33 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) m_title->setToolTip(QString::fromStdString(filePath.str())); m_title->setFixedWidth(m_title->fontMetrics().width(filePath.fileName().c_str()) + 32); m_title->setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed); - layout->addWidget(m_title); + titleLayout->addWidget(m_title); + + titleLayout->addStretch(3); + + m_minimizeButton = new QPushButton(this); + m_minimizeButton->setObjectName("maximize_button"); + m_minimizeButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac + titleLayout->addWidget(m_minimizeButton); + + m_snippetButton = new QPushButton(this); + m_snippetButton->setObjectName("maximize_button"); + m_snippetButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac + titleLayout->addWidget(m_snippetButton); + + m_maximizeButton = new QPushButton(this); + m_maximizeButton->setObjectName("maximize_button"); + m_maximizeButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac + titleLayout->addWidget(m_maximizeButton); + + m_minimizeButton->setEnabled(false); + m_snippetButton->setEnabled(false); + m_maximizeButton->setEnabled(false); connect(m_title, SIGNAL(clicked()), this, SLOT(clickedTitle())); + connect(m_minimizeButton, SIGNAL(clicked()), this, SLOT(clickedMinimizeButton())); + connect(m_snippetButton, SIGNAL(clicked()), this, SLOT(clickedSnippetButton())); + connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton())); update(); } @@ -73,14 +105,22 @@ void QtCodeFile::addCodeSnippet( std::shared_ptr snippet( new QtCodeSnippet(startLineNumber, title, code, locationFile, this)); + layout()->addWidget(snippet.get()); + + if (locationFile->isWholeCopy) + { + m_fileSnippet = snippet; + clickedMaximizeButton(); + return; + } + + m_snippets.push_back(snippet); + if (m_parent->getShowMaximizeButton()) { snippet->addMaximizeButton(); } - layout()->addWidget(snippet.get()); - m_snippets.push_back(snippet); - int maxDigits = 1; for (std::shared_ptr snippet : m_snippets) { @@ -91,6 +131,8 @@ void QtCodeFile::addCodeSnippet( { snippet->updateLineNumberAreaWidthForDigits(maxDigits); } + + clickedSnippetButton(); } void QtCodeFile::updateContent() @@ -100,10 +142,76 @@ void QtCodeFile::updateContent() snippet->updateContent(); } + if (m_fileSnippet) + { + m_fileSnippet->updateContent(); + } + m_title->setEnabled(m_parent->getShowMaximizeButton()); } void QtCodeFile::clickedTitle() { - MessageShowFile(m_filePath.absoluteStr(), 0, 0).dispatch(); + MessageActivateFile(m_filePath).dispatch(); +} + +void QtCodeFile::clickedMinimizeButton() +{ + for (std::shared_ptr snippet : m_snippets) + { + snippet->hide(); + } + + if (m_fileSnippet) + { + m_fileSnippet->hide(); + } + + m_minimizeButton->setEnabled(false); + if (m_snippets.size()) + { + m_snippetButton->setEnabled(true); + } + m_maximizeButton->setEnabled(true); +} + +void QtCodeFile::clickedSnippetButton() +{ + for (std::shared_ptr snippet : m_snippets) + { + snippet->show(); + } + + if (m_fileSnippet) + { + m_fileSnippet->hide(); + } + + m_minimizeButton->setEnabled(true); + m_snippetButton->setEnabled(false); + m_maximizeButton->setEnabled(true); +} + +void QtCodeFile::clickedMaximizeButton() +{ + for (std::shared_ptr snippet : m_snippets) + { + snippet->hide(); + } + + if (m_fileSnippet) + { + m_fileSnippet->show(); + } + else + { + MessageShowFile(m_filePath.absoluteStr(), 0, 0).dispatch(); + } + + m_minimizeButton->setEnabled(true); + if (m_snippets.size()) + { + m_snippetButton->setEnabled(true); + } + m_maximizeButton->setEnabled(false); } diff --git a/src/app/qt/element/QtCodeFile.h b/src/app/qt/element/QtCodeFile.h index f388b535..5e6730e2 100644 --- a/src/app/qt/element/QtCodeFile.h +++ b/src/app/qt/element/QtCodeFile.h @@ -41,13 +41,21 @@ public: private slots: void clickedTitle(); + void clickedMinimizeButton(); + void clickedSnippetButton(); + void clickedMaximizeButton(); private: QtCodeFileList* m_parent; QPushButton* m_title; + QPushButton* m_minimizeButton; + QPushButton* m_snippetButton; + QPushButton* m_maximizeButton; std::vector> m_snippets; + std::shared_ptr m_fileSnippet; + const FilePath m_filePath; }; diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp index 3bd76993..b826056b 100644 --- a/src/app/qt/view/QtCodeView.cpp +++ b/src/app/qt/view/QtCodeView.cpp @@ -1,7 +1,5 @@ #include "qt/view/QtCodeView.h" -#include - #include "qt/element/QtCodeFileList.h" #include "qt/view/QtViewWidgetWrapper.h" #include "utility/file/FileSystem.h" @@ -60,32 +58,12 @@ void QtCodeView::showCodeFile(const CodeSnippetParams& params) void QtCodeView::doRefreshView() { setStyleSheet(m_widget); - - clearClosedWindows(); - for (std::shared_ptr window: m_windows) - { - setStyleSheet(window.get()); - } } void QtCodeView::doShowCodeSnippets(const std::vector& snippets) { m_widget->clearCodeSnippets(); - clearClosedWindows(); - for (std::shared_ptr window: m_windows) - { - if (m_errorMessages.size()) - { - window->close(); - } - else - { - window->setActiveTokenIds(m_activeTokenIds); - window->setErrorMessages(m_errorMessages); - } - } - m_widget->setActiveTokenIds(m_activeTokenIds); m_widget->setErrorMessages(m_errorMessages); m_widget->setShowMaximizeButton(m_errorMessages.size() == 0); @@ -98,22 +76,7 @@ void QtCodeView::doShowCodeSnippets(const std::vector& snippe void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) { - std::shared_ptr ptr = createQtCodeFileList(); - m_windows.push_back(ptr); - - ptr->setShowMaximizeButton(false); - ptr->setActiveTokenIds(m_activeTokenIds); - ptr->setErrorMessages(m_errorMessages); - ptr->addCodeSnippet(1, params.title, params.code, params.locationFile); - - ptr->setWindowTitle(params.locationFile->getFilePath().fileName().c_str()); - ptr->show(); - - float percent = float(params.startLineNumber + params.endLineNumber) / float(params.lineCount) / 2; - float min = ptr->verticalScrollBar()->minimum(); - float max = ptr->verticalScrollBar()->maximum(); - - ptr->verticalScrollBar()->setValue(min + (max - min) * percent); + m_widget->addCodeSnippet(1, params.title, params.code, params.locationFile); } std::shared_ptr QtCodeView::createQtCodeFileList() const @@ -128,18 +91,6 @@ void QtCodeView::setStyleSheet(QWidget* widget) const widget->setStyleSheet(TextAccess::createFromFile("data/gui/code_view/code_view.css")->getText().c_str()); } -void QtCodeView::clearClosedWindows() -{ - for (size_t i = 0; i < m_windows.size(); i++) - { - if (!m_windows[i]->isVisible()) - { - m_windows.erase(m_windows.begin() + i); - i--; - } - } -} - void QtCodeView::focusToken(const Id tokenId) { m_focusTokenFunctor(tokenId); diff --git a/src/app/qt/view/QtCodeView.h b/src/app/qt/view/QtCodeView.h index 647a873e..ed1ab423 100644 --- a/src/app/qt/view/QtCodeView.h +++ b/src/app/qt/view/QtCodeView.h @@ -43,7 +43,6 @@ private: std::shared_ptr createQtCodeFileList() const; void setStyleSheet(QWidget* widget) const; - void clearClosedWindows(); QtThreadedFunctor<> m_refreshViewFunctor; QtThreadedFunctor&> m_showCodeSnippetsFunctor; @@ -52,7 +51,6 @@ private: QtThreadedFunctor<> m_defocusTokenFunctor; QtCodeFileList* m_widget; - std::vector> m_windows; std::vector m_activeTokenIds; std::vector m_errorMessages; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 496f43c5..550543e5 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -9,7 +9,7 @@ add_files( data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp data/parser/cxx/name_resolver/CxxTypeNameResolver.h - + data/parser/cxx/ASTAction.cpp data/parser/cxx/ASTAction.h data/parser/cxx/ASTActionFactory.cpp @@ -248,6 +248,7 @@ add_files( utility/math/Vector4.h utility/math/VectorBase.h + utility/messaging/type/MessageActivateFile.h utility/messaging/type/MessageActivateTokenLocation.h utility/messaging/type/MessageActivateTokens.h utility/messaging/type/MessageAutoRefreshChanged.h diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index bef599e5..25060453 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -23,6 +23,11 @@ CodeController::~CodeController() const uint CodeController::s_lineRadius = 2; +void CodeController::handleMessage(MessageActivateFile* message) +{ + MessageActivateTokens(std::vector(1, m_storageAccess->getTokenIdForFileNode(message->filePath))).dispatch(); +} + void CodeController::handleMessage(MessageActivateTokenLocation* message) { if (message->locationId) @@ -140,10 +145,13 @@ std::vector CodeController::getSnippetsForActiveTok { std::vector fileSnippets = getSnippetsForFile(file); - for (CodeView::CodeSnippetParams& params : fileSnippets) + if (!file->isWholeCopy) { - params.locationFile = m_storageAccess->getTokenLocationsForLinesInFile( - file->getFilePath().str(), params.startLineNumber, params.endLineNumber); + for (CodeView::CodeSnippetParams& params : fileSnippets) + { + params.locationFile = m_storageAccess->getTokenLocationsForLinesInFile( + file->getFilePath().str(), params.startLineNumber, params.endLineNumber); + } } if (declarationId != 0) @@ -214,7 +222,8 @@ std::vector CodeController::getSnippetsForFile(std: params.endLineNumber = std::min(textAccess->getLineCount(), range.end.row + (range.end.strong ? 0 : snippetExpandRange)); - std::shared_ptr tempFile = m_storageAccess->getTokenLocationsForLinesInFile(file->getFilePath().str(), params.startLineNumber, params.endLineNumber); + std::shared_ptr tempFile = + m_storageAccess->getTokenLocationsForLinesInFile(file->getFilePath().str(), params.startLineNumber, params.endLineNumber); TokenLocationLine* firstUsedLine = nullptr; for (size_t i = params.startLineNumber; i <= params.endLineNumber && firstUsedLine == nullptr; i++) { diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index faaaf50c..afd87fa8 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -5,6 +5,7 @@ #include #include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageActivateFile.h" #include "utility/messaging/type/MessageActivateTokenLocation.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageFinishedParsing.h" @@ -24,6 +25,7 @@ class TokenLocationFile; class CodeController : public Controller + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -39,6 +41,7 @@ public: private: static const uint s_lineRadius; + virtual void handleMessage(MessageActivateFile* message); virtual void handleMessage(MessageActivateTokenLocation* message); virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageFinishedParsing* message); diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 6ccea078..83a5130f 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -109,18 +109,7 @@ std::set Storage::getDependingFilePathsAndRemoveFileNodes(const std::s for (const FilePath& filePath : filePaths) { - SearchNode* searchNode = m_tokenIndex.getNode(filePath.fileName()); - if (!searchNode || searchNode->getTokenIds().size() != 1) - { - continue; - } - - Node* fileNode = m_graph.getNodeById(searchNode->getFirstTokenId()); - if (!fileNode->isType(Node::NODE_FILE)) - { - LOG_ERROR("Node is not of type file."); - continue; - } + Node* fileNode = findFileNode(filePath); if (!fileNode->getComponent() || fileNode->getComponent()->getFilePath() != filePath) @@ -956,6 +945,17 @@ std::vector Storage::getTokenIdsForQuery(std::string query) const return outGraph.getTokenIds(); } +Id Storage::getTokenIdForFileNode(const FilePath& filePath) const +{ + Node* fileNode = findFileNode(filePath); + if (fileNode) + { + return fileNode->getId(); + } + + return 0; +} + TokenLocationCollection Storage::getTokenLocationsForTokenIds(const std::vector& tokenIds) const { TokenLocationCollection ret; @@ -1006,6 +1006,7 @@ std::shared_ptr Storage::getTokenLocationsForFile(const std:: ret->addTokenLocationAsPlainCopy(tokenLocation); } ); + ret->isWholeCopy = true; return ret; } @@ -1165,6 +1166,24 @@ Node* Storage::addFileNode(const FilePath& filePath) return fileNode; } +Node* Storage::findFileNode(const FilePath& filePath) const +{ + SearchNode* searchNode = m_tokenIndex.getNode(filePath.fileName()); + if (!searchNode || searchNode->getTokenIds().size() != 1) + { + return nullptr; + } + + Node* fileNode = m_graph.getNodeById(searchNode->getFirstTokenId()); + if (!fileNode->isType(Node::NODE_FILE)) + { + LOG_ERROR("Node is not of type file."); + return nullptr; + } + + return fileNode; +} + TokenComponentAccess::AccessType Storage::convertAccessType(ParserClient::AccessType access) const { switch (access) diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index c59ddecf..e6ced56a 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -119,6 +119,7 @@ public: virtual std::vector getActiveTokenIdsForLocationId(Id locationId) const; virtual std::vector getTokenIdsForQuery(std::string query) const; + virtual Id getTokenIdForFileNode(const FilePath& filePath) const; virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector& tokenIds) const; virtual std::shared_ptr getTokenLocationsForFile(const std::string& filePath) const; @@ -140,6 +141,7 @@ private: Node* addNodeHierarchyWithDistinctSignature(Node::NodeType type, const ParseFunction& function); Node* addFileNode(const FilePath& filePath); + Node* findFileNode(const FilePath& filePath) const; TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const; TokenComponentAccess* addAccess(Node* node, ParserClient::AccessType access); diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index 10a00a6e..8c5095c3 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -6,6 +6,7 @@ #include #include "utility/types.h" +#include "utility/file/FilePath.h" #include "data/graph/Node.h" #include "data/search/SearchMatch.h" @@ -32,6 +33,7 @@ public: virtual std::vector getActiveTokenIdsForLocationId(Id locationId) const = 0; virtual std::vector getTokenIdsForQuery(std::string query) const = 0; + virtual Id getTokenIdForFileNode(const FilePath& filePath) const = 0; virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector& tokenIds) const = 0; virtual std::shared_ptr getTokenLocationsForFile(const std::string& filePath) const = 0; diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index ef38f80c..d240d9ef 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -112,6 +112,16 @@ std::vector StorageAccessProxy::getTokenIdsForQuery(std::string query) const return std::vector(); } +Id StorageAccessProxy::getTokenIdForFileNode(const FilePath& filePath) const +{ + if (hasSubject()) + { + return m_subject->getTokenIdForFileNode(filePath); + } + + return 0; +} + TokenLocationCollection StorageAccessProxy::getTokenLocationsForTokenIds(const std::vector& tokenIds) const { if (hasSubject()) diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index 1de7324e..c5d0074a 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -25,6 +25,7 @@ public: virtual std::vector getActiveTokenIdsForLocationId(Id locationId) const; virtual std::vector getTokenIdsForQuery(std::string query) const; + virtual Id getTokenIdForFileNode(const FilePath& filePath) const; virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector& tokenIds) const; virtual std::shared_ptr getTokenLocationsForFile(const std::string& filePath) const; diff --git a/src/lib/utility/messaging/type/MessageActivateFile.h b/src/lib/utility/messaging/type/MessageActivateFile.h new file mode 100644 index 00000000..ec67c82b --- /dev/null +++ b/src/lib/utility/messaging/type/MessageActivateFile.h @@ -0,0 +1,23 @@ +#ifndef MESSAGE_ACTIVATE_FILE_H +#define MESSAGE_ACTIVATE_FILE_H + +#include "utility/messaging/Message.h" +#include "utility/file/FilePath.h" + +class MessageActivateFile: public Message +{ +public: + MessageActivateFile(const FilePath& filePath) + : filePath(filePath) + { + } + + static const std::string getStaticType() + { + return "MessageActivateFile"; + } + + const FilePath filePath; +}; + +#endif // MESSAGE_ACTIVATE_FILE_H