From 0d5c19db0009eae8f47918d336092dfe399fac3f Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Sun, 26 Nov 2017 12:54:42 +0100 Subject: [PATCH] ui: Hide nodes and edges from graph via context menu action or Alt + Click (issue #472) * show all context menu actions, but disable unavailable * added hide action to undo redo stack --- src/lib/CMakeLists.txt | 3 +- .../component/controller/GraphController.cpp | 210 ++++++++++++++---- .../component/controller/GraphController.h | 6 + .../controller/UndoRedoController.cpp | 6 + .../component/controller/UndoRedoController.h | 3 + .../component/controller/helper/DummyEdge.h | 3 + .../component/controller/helper/DummyNode.h | 2 + .../controller/helper/TrailLayouter.cpp | 9 +- src/lib/data/graph/Graph.cpp | 10 + src/lib/data/graph/Graph.h | 4 + .../messaging/type/MessageGraphNodeHide.h | 29 +++ src/lib_gui/qt/element/QtCodeArea.cpp | 13 +- .../qt/element/QtCodeFileTitleButton.cpp | 15 +- src/lib_gui/qt/graphics/QtGraphicsView.cpp | 107 ++++++--- src/lib_gui/qt/graphics/QtGraphicsView.h | 8 + src/lib_gui/qt/utility/QtContextMenu.cpp | 3 + .../qt/view/graphElements/QtGraphEdge.cpp | 30 ++- .../qt/view/graphElements/QtGraphEdge.h | 3 + .../qt/view/graphElements/QtGraphNode.cpp | 15 ++ .../qt/view/graphElements/QtGraphNode.h | 1 + .../QtGraphNodeComponentClickable.cpp | 9 +- 21 files changed, 402 insertions(+), 87 deletions(-) create mode 100644 src/lib/utility/messaging/type/MessageGraphNodeHide.h diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index ec0d113e..1a654c6d 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -243,7 +243,7 @@ add_files( data/storage/type/StorageOccurrence.h data/storage/type/StorageSourceLocation.h data/storage/type/StorageSymbol.h - + data/storage/IntermediateStorage.cpp data/storage/IntermediateStorage.h data/storage/PersistentStorage.cpp @@ -413,6 +413,7 @@ add_files( utility/messaging/type/MessageForceEnterLicense.h utility/messaging/type/MessageGraphNodeBundleSplit.h utility/messaging/type/MessageGraphNodeExpand.h + utility/messaging/type/MessageGraphNodeHide.h utility/messaging/type/MessageGraphNodeMove.h utility/messaging/type/MessageIDECreateCDB.h utility/messaging/type/MessageInterruptTasks.h diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 0cc7fe5d..fa169417 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -160,39 +160,14 @@ void GraphController::handleMessage(MessageActivateTrail* message) createDummyGraph(graph); m_graph->setTrailMode(message->horizontalLayout ? Graph::TRAIL_HORIZONTAL : Graph::TRAIL_VERTICAL); + m_graph->setHasTrailOrigin(message->originId); setVisibility(setActive(m_activeNodeIds, true)); - layoutNesting(); - - TrailLayouter::LayoutDirection direction; - if (message->horizontalLayout) - { - if (message->originId) - { - direction = TrailLayouter::LAYOUT_LEFT_RIGHT; - } - else - { - direction = TrailLayouter::LAYOUT_RIGHT_LEFT; - } - } - else - { - if (message->originId) - { - direction = TrailLayouter::LAYOUT_TOP_BOTTOM; - } - else - { - direction = TrailLayouter::LAYOUT_BOTTOM_TOP; - } - } - MessageStatus("Layouting graph", false, true).dispatch(); - TrailLayouter layout(direction); - layout.layoutGraph(m_dummyNodes, m_dummyEdges, m_topLevelAncestorIds); + layoutNesting(); + layoutTrail(message->horizontalLayout, message->originId); MessageStatus("Displaying graph", false, true).dispatch(); @@ -384,6 +359,73 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message) } } +void GraphController::handleMessage(MessageGraphNodeHide* message) +{ + DummyNode* node = getDummyGraphNodeById(message->tokenId); + DummyEdge* edge = nullptr; + if (node) + { + if (node->active || node->hasActiveSubNode()) + { + MessageStatus("Can't hide active node or node with active children", true).dispatch(); + return; + } + + node->hidden = true; + } + else + { + edge = getDummyGraphEdgeById(message->tokenId); + if (edge) + { + edge->hidden = true; + edge->visible = false; + + DummyNode* from = getDummyGraphNodeById(edge->ownerId); + DummyNode* to = getDummyGraphNodeById(edge->targetId); + + if (from) + { + from->connected = false; + } + + if (to) + { + to->connected = false; + } + } + } + + if (node || edge) + { + bool showsTrail = m_graph->getTrailMode() != Graph::TRAIL_NONE; + + setVisibility(setActive(utility::concat(m_activeNodeIds, m_activeEdgeIds), showsTrail)); + + if (hasCharacterIndex()) + { + addCharacterIndex(); + layoutNesting(); + layoutList(); + } + else + { + layoutNesting(); + + if (showsTrail) + { + layoutTrail(m_graph->getTrailMode() == Graph::TRAIL_HORIZONTAL, m_graph->hasTrailOrigin()); + } + else + { + layoutGraph(); + } + } + + buildGraph(message, false, true, false); + } +} + void GraphController::handleMessage(MessageGraphNodeMove* message) { DummyNode* node = getDummyGraphNodeById(message->tokenId); @@ -674,7 +716,8 @@ bool GraphController::setActive(const std::vector& activeTokenIds, bool show DummyNode* to = getDummyGraphNodeById(edge->targetId); bool isInheritance = edge->data->isType(Edge::EDGE_INHERITANCE); - if (from && to && (showAllEdges || noActive || from->active || to->active || edge->active || isInheritance)) + if (from && to && !edge->hidden && + (showAllEdges || noActive || from->active || to->active || edge->active || isInheritance)) { edge->visible = true; from->connected = true; @@ -727,7 +770,11 @@ bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode* node, bool n node->visible = false; node->childVisible = false; - if (node->isExpandToggleNode()) + if (node->hidden) + { + return false; + } + else if (node->isExpandToggleNode()) { node->visible = true; return false; @@ -765,10 +812,9 @@ bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode* node, bool n void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode* node, bool parentExpanded) const { - node->visible = true; - if (node->isGraphNode() && node->data->getType().getType() == NodeType::NODE_ENUM && !node->isExpanded()) { + node->visible = true; return; } @@ -777,13 +823,18 @@ void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode* node, bool pa { for (const std::shared_ptr& subNode : node->subNodes) { - if (!subNode->isQualifierNode()) + if (!subNode->isQualifierNode() && !subNode->isExpandToggleNode() && !subNode->hidden) { - node->childVisible = true; setNodeVisibilityRecursiveTopDown(subNode.get(), node->isExpanded()); + node->childVisible |= subNode->visible; } } } + + if (!node->isAccessNode() || node->childVisible) + { + node->visible = true; + } } void GraphController::hideBuiltinTypes() @@ -1276,7 +1327,7 @@ void GraphController::addCharacterIndex() char character = 0; for (size_t i = 0; i < m_dummyNodes.size(); i++) { - if (!m_dummyNodes[i]->name.size()) + if (!m_dummyNodes[i]->visible || !m_dummyNodes[i]->name.size()) { continue; } @@ -1295,6 +1346,18 @@ void GraphController::addCharacterIndex() } } +bool GraphController::hasCharacterIndex() const +{ + for (const std::shared_ptr& node : m_dummyNodes) + { + if (node->isTextNode()) + { + return true; + } + } + return false; +} + void GraphController::layoutNesting() { TRACE(); @@ -1493,7 +1556,8 @@ void GraphController::addExpandToggleNode(DummyNode* node) const for (const std::shared_ptr& subSubNode : subNode->subNodes) { - if (subSubNode->visible && (!subSubNode->isGraphNode() || !subSubNode->data->isImplicit() || node->data->isImplicit())) + if ((subSubNode->visible || subSubNode->hidden) && + (!subSubNode->isGraphNode() || !subSubNode->data->isImplicit() || node->data->isImplicit())) { visibleSubNodeCount++; } @@ -1562,8 +1626,17 @@ void GraphController::layoutGraph(bool getSortedNodes) { TRACE(); + std::vector> visibleNodes; + for (auto node : m_dummyNodes) + { + if (node->visible) + { + visibleNodes.push_back(node); + } + } + BucketLayouter grid(getView()->getViewSize()); - grid.createBuckets(m_dummyNodes, m_dummyEdges); + grid.createBuckets(visibleNodes, m_dummyEdges); grid.layoutBuckets(); if (getSortedNodes) @@ -1576,8 +1649,56 @@ void GraphController::layoutList() { TRACE(); + std::vector> visibleNodes; + for (auto node : m_dummyNodes) + { + if (node->visible) + { + visibleNodes.push_back(node); + } + } + ListLayouter layouter(getView()->getViewSize()); - layouter.layoutList(m_dummyNodes); + layouter.layoutList(visibleNodes); +} + +void GraphController::layoutTrail(bool horizontal, bool hasOrigin) +{ + TrailLayouter::LayoutDirection direction; + if (horizontal) + { + if (hasOrigin) + { + direction = TrailLayouter::LAYOUT_LEFT_RIGHT; + } + else + { + direction = TrailLayouter::LAYOUT_RIGHT_LEFT; + } + } + else + { + if (hasOrigin) + { + direction = TrailLayouter::LAYOUT_TOP_BOTTOM; + } + else + { + direction = TrailLayouter::LAYOUT_BOTTOM_TOP; + } + } + + std::vector> visibleNodes; + for (auto node : m_dummyNodes) + { + if (node->visible) + { + visibleNodes.push_back(node); + } + } + + TrailLayouter layout(direction); + layout.layoutGraph(visibleNodes, m_dummyEdges, m_topLevelAncestorIds); } void GraphController::assignBundleIds() @@ -1608,6 +1729,19 @@ DummyNode* GraphController::getDummyGraphNodeById(Id tokenId) const return nullptr; } +DummyEdge* GraphController::getDummyGraphEdgeById(Id tokenId) const +{ + for (const std::shared_ptr& edge : m_dummyEdges) + { + if (edge->data && edge->data->getId() == tokenId) + { + return edge.get(); + } + } + + return nullptr; +} + void GraphController::buildGraph( MessageBase* message, bool centerActiveNode, bool animatedTransition, bool scrollToTop) { diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 56e47efb..8ee8c850 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -15,6 +15,7 @@ #include "utility/messaging/type/MessageFocusOut.h" #include "utility/messaging/type/MessageGraphNodeBundleSplit.h" #include "utility/messaging/type/MessageGraphNodeExpand.h" +#include "utility/messaging/type/MessageGraphNodeHide.h" #include "utility/messaging/type/MessageGraphNodeMove.h" #include "utility/messaging/type/MessageScrollGraph.h" #include "utility/messaging/type/MessageSearchFullText.h" @@ -42,6 +43,7 @@ class GraphController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -62,6 +64,7 @@ private: virtual void handleMessage(MessageFocusOut* message); virtual void handleMessage(MessageGraphNodeBundleSplit* message); virtual void handleMessage(MessageGraphNodeExpand* message); + virtual void handleMessage(MessageGraphNodeHide* message); virtual void handleMessage(MessageGraphNodeMove* message); virtual void handleMessage(MessageScrollGraph* message); virtual void handleMessage(MessageSearchFullText* message); @@ -100,6 +103,7 @@ private: void bundleNodesByType(); void addCharacterIndex(); + bool hasCharacterIndex() const; void layoutNesting(); void layoutNestingRecursive(DummyNode* node) const; @@ -108,10 +112,12 @@ private: void layoutGraph(bool getSortedNodes = false); void layoutList(); + void layoutTrail(bool horizontal, bool hasOrigin); void assignBundleIds(); DummyNode* getDummyGraphNodeById(Id tokenId) const; + DummyEdge* getDummyGraphEdgeById(Id tokenId) const; void buildGraph(MessageBase* message, bool centerActiveNode, bool animatedTransition, bool scrollToTop); diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index 63a175df..f5e5664b 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -174,6 +174,12 @@ void UndoRedoController::handleMessage(MessageGraphNodeExpand* message) processCommand(command); } +void UndoRedoController::handleMessage(MessageGraphNodeHide* message) +{ + Command command(std::make_shared(*message), Command::ORDER_ADAPT); + processCommand(command); +} + void UndoRedoController::handleMessage(MessageGraphNodeMove* message) { Command command(std::make_shared(*message), Command::ORDER_VIEW); diff --git a/src/lib/component/controller/UndoRedoController.h b/src/lib/component/controller/UndoRedoController.h index 33d7b25f..01670821 100644 --- a/src/lib/component/controller/UndoRedoController.h +++ b/src/lib/component/controller/UndoRedoController.h @@ -15,6 +15,7 @@ #include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageGraphNodeBundleSplit.h" #include "utility/messaging/type/MessageGraphNodeExpand.h" +#include "utility/messaging/type/MessageGraphNodeHide.h" #include "utility/messaging/type/MessageGraphNodeMove.h" #include "utility/messaging/type/MessageRedo.h" #include "utility/messaging/type/MessageRefresh.h" @@ -44,6 +45,7 @@ class UndoRedoController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -91,6 +93,7 @@ private: virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageGraphNodeBundleSplit* message); virtual void handleMessage(MessageGraphNodeExpand* message); + virtual void handleMessage(MessageGraphNodeHide* message); virtual void handleMessage(MessageGraphNodeMove* message); virtual void handleMessage(MessageRedo* message); virtual void handleMessage(MessageRefresh* message); diff --git a/src/lib/component/controller/helper/DummyEdge.h b/src/lib/component/controller/helper/DummyEdge.h index ef5075b0..80edd5f9 100644 --- a/src/lib/component/controller/helper/DummyEdge.h +++ b/src/lib/component/controller/helper/DummyEdge.h @@ -17,6 +17,7 @@ struct DummyEdge , targetId(0) , data(nullptr) , visible(false) + , hidden(false) , active(false) , weight(0) , direction(TokenComponentAggregation::DIRECTION_INVALID) @@ -28,6 +29,7 @@ struct DummyEdge , targetId(targetId) , data(data) , visible(false) + , hidden(false) , active(false) , weight(0) , direction(TokenComponentAggregation::DIRECTION_INVALID) @@ -85,6 +87,7 @@ struct DummyEdge const Edge* data; bool visible; + bool hidden; bool active; std::vector path; diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index bdce4c3f..1c96851b 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -52,6 +52,7 @@ public: DummyNode() : visible(false) + , hidden(false) , childVisible(false) , tokenId(0) , data(nullptr) @@ -342,6 +343,7 @@ public: Vec2i size; bool visible; + bool hidden; bool childVisible; Id tokenId; diff --git a/src/lib/component/controller/helper/TrailLayouter.cpp b/src/lib/component/controller/helper/TrailLayouter.cpp index 2f94bd45..7453fbc8 100644 --- a/src/lib/component/controller/helper/TrailLayouter.cpp +++ b/src/lib/component/controller/helper/TrailLayouter.cpp @@ -588,7 +588,14 @@ void TrailLayouter::retrievePositions(const std::map& topLevelAncestorId { if (node->dummyNode) { - node->dummyNode->position = node->pos; + if (node->level != -1) + { + node->dummyNode->position = node->pos; + } + else + { + node->dummyNode->visible = false; + } } } diff --git a/src/lib/data/graph/Graph.cpp b/src/lib/data/graph/Graph.cpp index a1d755bf..fe6cc671 100644 --- a/src/lib/data/graph/Graph.cpp +++ b/src/lib/data/graph/Graph.cpp @@ -296,6 +296,16 @@ void Graph::setTrailMode(TrailMode trailMode) m_trailMode = trailMode; } +bool Graph::hasTrailOrigin() const +{ + return m_hasTrailOrigin; +} + +void Graph::setHasTrailOrigin(bool hasOrigin) +{ + m_hasTrailOrigin = hasOrigin; +} + void Graph::print(std::ostream& ostream) const { ostream << "Graph:\n"; diff --git a/src/lib/data/graph/Graph.h b/src/lib/data/graph/Graph.h index 4d353a28..d8d1dbdb 100644 --- a/src/lib/data/graph/Graph.h +++ b/src/lib/data/graph/Graph.h @@ -59,6 +59,9 @@ public: TrailMode getTrailMode() const; void setTrailMode(TrailMode trailMode); + bool hasTrailOrigin() const; + void setHasTrailOrigin(bool hasOrigin); + void print(std::ostream& ostream) const; void printBasic(std::ostream& ostream) const; @@ -72,6 +75,7 @@ private: std::map> m_edges; TrailMode m_trailMode; + bool m_hasTrailOrigin; }; std::ostream& operator<<(std::ostream& ostream, const Graph& graph); diff --git a/src/lib/utility/messaging/type/MessageGraphNodeHide.h b/src/lib/utility/messaging/type/MessageGraphNodeHide.h new file mode 100644 index 00000000..b400317e --- /dev/null +++ b/src/lib/utility/messaging/type/MessageGraphNodeHide.h @@ -0,0 +1,29 @@ +#ifndef MESSAGE_GRAPH_NODE_HIDE_H +#define MESSAGE_GRAPH_NODE_HIDE_H + +#include "utility/messaging/Message.h" +#include "utility/types.h" + +class MessageGraphNodeHide + : public Message +{ +public: + MessageGraphNodeHide(Id tokenId) + : tokenId(tokenId) + { + } + + static const std::string getStaticType() + { + return "MessageGraphNodeHide"; + } + + virtual void print(std::ostream& os) const + { + os << tokenId; + } + + const Id tokenId; +}; + +#endif // MESSAGE_GRAPH_NODE_HIDE_H diff --git a/src/lib_gui/qt/element/QtCodeArea.cpp b/src/lib_gui/qt/element/QtCodeArea.cpp index 162c3557..e1a5d2e5 100644 --- a/src/lib_gui/qt/element/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/QtCodeArea.cpp @@ -581,14 +581,13 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event) { m_eventPosition = event->pos(); + m_setIDECursorPositionAction->setEnabled(!getSourceLocationFile()->getFilePath().empty()); + QtContextMenu menu(event, this); - if (!getSourceLocationFile()->getFilePath().empty()) - { - menu.addSeparator(); - menu.addFileActions(getSourceLocationFile()->getFilePath()); - menu.addSeparator(); - menu.addAction(m_setIDECursorPositionAction); - } + menu.addSeparator(); + menu.addFileActions(getSourceLocationFile()->getFilePath()); + menu.addSeparator(); + menu.addAction(m_setIDECursorPositionAction); menu.show(); } } diff --git a/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp b/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp index 991d9a14..c9a6aa52 100644 --- a/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp +++ b/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp @@ -128,14 +128,8 @@ void QtCodeFileTitleButton::updateTexts() void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event) { - QtContextMenu menu(event, this); - menu.addSeparator(); - - if (!m_filePath.empty()) - { - menu.addFileActions(m_filePath); - } - else if (text().size()) + FilePath path = m_filePath; + if (text().size()) { Project* currentProject = Application::getInstance()->getCurrentProject().get(); if (!currentProject) @@ -143,9 +137,12 @@ void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event) return; } - menu.addFileActions(currentProject->getProjectSettingsFilePath()); + path = currentProject->getProjectSettingsFilePath(); } + QtContextMenu menu(event, this); + menu.addSeparator(); + menu.addFileActions(path); menu.show(); } diff --git a/src/lib_gui/qt/graphics/QtGraphicsView.cpp b/src/lib_gui/qt/graphics/QtGraphicsView.cpp index d97eaf44..a6194dd2 100644 --- a/src/lib_gui/qt/graphics/QtGraphicsView.cpp +++ b/src/lib_gui/qt/graphics/QtGraphicsView.cpp @@ -10,6 +10,7 @@ #include #include +#include "qt/view/graphElements/QtGraphEdge.h" #include "qt/view/graphElements/QtGraphNode.h" #include "qt/view/graphElements/QtGraphNodeData.h" #include "qt/view/graphElements/QtGraphNodeBundle.h" @@ -18,6 +19,7 @@ #include "qt/utility/utilityQt.h" #include "settings/ApplicationSettings.h" #include "utility/messaging/type/MessageDisplayBookmarkCreator.h" +#include "utility/messaging/type/MessageGraphNodeHide.h" #include "utility/utilityApp.h" #include "utility/ResourcePaths.h" @@ -57,6 +59,16 @@ QtGraphicsView::QtGraphicsView(QWidget* parent) m_copyNodeNameAction->setToolTip(tr("Copies the name of this node to the clipboard")); connect(m_copyNodeNameAction, &QAction::triggered, this, &QtGraphicsView::copyNodeName); + m_hideNodeAction = new QAction(tr("Hide Node (Alt + Left Click)"), this); + m_hideNodeAction->setStatusTip(tr("Hide the node from this graph")); + m_hideNodeAction->setToolTip(tr("Hide the node from this graph")); + connect(m_hideNodeAction, &QAction::triggered, this, &QtGraphicsView::hideNode); + + m_hideEdgeAction = new QAction(tr("Hide Edge (Alt + Left Click)"), this); + m_hideEdgeAction->setStatusTip(tr("Hide the edge from this graph")); + m_hideEdgeAction->setToolTip(tr("Hide the edge from this graph")); + connect(m_hideEdgeAction, &QAction::triggered, this, &QtGraphicsView::hideEdge); + m_bookmarkNodeAction = new QAction(tr("Bookmark Node"), this); m_bookmarkNodeAction->setStatusTip(tr("Create a bookmark for this node")); m_bookmarkNodeAction->setToolTip(tr("Create a bookmark for this node")); @@ -113,6 +125,20 @@ QtGraphNode* QtGraphicsView::getNodeAtCursorPosition() const return node; } +QtGraphEdge* QtGraphicsView::getEdgeAtCursorPosition() const +{ + QtGraphEdge* edge = nullptr; + + QPointF point = mapToScene(mapFromGlobal(QCursor::pos())); + QGraphicsItem* item = scene()->itemAt(point, QTransform()); + if (item) + { + edge = dynamic_cast(item->parentItem()); + } + + return edge; +} + void QtGraphicsView::ensureVisibleAnimated(const QRectF& rect, int xmargin, int ymargin) { int xval = horizontalScrollBar()->value(); @@ -302,51 +328,64 @@ void QtGraphicsView::wheelEvent(QWheelEvent* event) void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) { m_clipboardNodeName = ""; + m_hideNodeId = 0; + m_hideEdgeId = 0; m_bookmarkNodeId = 0; FilePath clipboardFilePath; QtGraphNode* node = getNodeAtCursorPosition(); - while (node) + if (node) { - QtGraphNodeData* dataNode = dynamic_cast(node); - if (dataNode) + while (node) { - m_clipboardNodeName = dataNode->getName(); - m_bookmarkNodeId = dataNode->getTokenId(); - clipboardFilePath = dataNode->getFilePath(); + m_hideNodeId = node->getTokenId(); + + QtGraphNodeData* dataNode = dynamic_cast(node); + if (dataNode) + { + m_clipboardNodeName = dataNode->getName(); + m_bookmarkNodeId = dataNode->getTokenId(); + clipboardFilePath = dataNode->getFilePath(); + break; + } + else if (dynamic_cast(node)) + { + m_clipboardNodeName = node->getName(); + break; + } + + node = node->getParent(); } - else if (dynamic_cast(node)) + } + else + { + QtGraphEdge* edge = getEdgeAtCursorPosition(); + if (edge) { - m_clipboardNodeName = node->getName(); - break; + m_hideEdgeId = edge->getTokenId(); } - node = node->getParent(); } + m_hideNodeAction->setEnabled(m_hideNodeId); + m_hideEdgeAction->setEnabled(m_hideEdgeId); + m_bookmarkNodeAction->setEnabled(m_bookmarkNodeId); + + m_copyNodeNameAction->setEnabled(m_clipboardNodeName.size()); + + QtContextMenu menu(event, this); + menu.addSeparator(); menu.addAction(m_exportGraphAction); - if (m_bookmarkNodeId) - { - menu.addSeparator(); - menu.addAction(m_bookmarkNodeAction); - } + menu.addSeparator(); + menu.addAction(m_hideEdgeAction); + menu.addAction(m_hideNodeAction); + menu.addAction(m_bookmarkNodeAction); - if (!m_clipboardNodeName.empty() || !clipboardFilePath.empty()) - { - menu.addSeparator(); - } - - if (!m_clipboardNodeName.empty()) - { - menu.addAction(m_copyNodeNameAction); - } - - if (!clipboardFilePath.empty()) - { - menu.addFileActions(clipboardFilePath); - } + menu.addSeparator(); + menu.addAction(m_copyNodeNameAction); + menu.addFileActions(clipboardFilePath); menu.show(); } @@ -439,6 +478,16 @@ void QtGraphicsView::copyNodeName() QApplication::clipboard()->setText(m_clipboardNodeName.c_str()); } +void QtGraphicsView::hideNode() +{ + MessageGraphNodeHide(m_hideNodeId).dispatch(); +} + +void QtGraphicsView::hideEdge() +{ + MessageGraphNodeHide(m_hideEdgeId).dispatch(); +} + void QtGraphicsView::bookmarkNode() { MessageDisplayBookmarkCreator(m_bookmarkNodeId).dispatch(); diff --git a/src/lib_gui/qt/graphics/QtGraphicsView.h b/src/lib_gui/qt/graphics/QtGraphicsView.h index 6dca13a2..5ed10023 100644 --- a/src/lib_gui/qt/graphics/QtGraphicsView.h +++ b/src/lib_gui/qt/graphics/QtGraphicsView.h @@ -9,6 +9,7 @@ #include "utility/types.h" class QTimer; +class QtGraphEdge; class QtGraphNode; class QtGraphicsView @@ -25,6 +26,7 @@ public: void setSceneRect(const QRectF& rect); QtGraphNode* getNodeAtCursorPosition() const; + QtGraphEdge* getEdgeAtCursorPosition() const; void ensureVisibleAnimated(const QRectF& rect, int xmargin = 50, int ymargin = 50); @@ -56,6 +58,8 @@ private slots: void exportGraph(); void copyNodeName(); + void hideNode(); + void hideEdge(); void bookmarkNode(); void zoomInPressed(); @@ -81,6 +85,8 @@ private: bool m_shift; std::string m_clipboardNodeName; + Id m_hideNodeId; + Id m_hideEdgeId; Id m_bookmarkNodeId; std::shared_ptr m_timer; @@ -89,6 +95,8 @@ private: QAction* m_exportGraphAction; QAction* m_copyNodeNameAction; + QAction* m_hideNodeAction; + QAction* m_hideEdgeAction; QAction* m_bookmarkNodeAction; QPushButton* m_zoomState; diff --git a/src/lib_gui/qt/utility/QtContextMenu.cpp b/src/lib_gui/qt/utility/QtContextMenu.cpp index 7a4b2777..874db54d 100644 --- a/src/lib_gui/qt/utility/QtContextMenu.cpp +++ b/src/lib_gui/qt/utility/QtContextMenu.cpp @@ -54,6 +54,9 @@ void QtContextMenu::addFileActions(FilePath filePath) { s_filePath = filePath; + s_copyFullPathAction->setEnabled(!s_filePath.empty()); + s_openContainingFolderAction->setEnabled(!s_filePath.empty()); + addAction(s_copyFullPathAction); addAction(s_openContainingFolderAction); } diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp index 084de497..8637c0b4 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.cpp @@ -16,6 +16,7 @@ #include "utility/messaging/type/MessageFocusIn.h" #include "utility/messaging/type/MessageFocusOut.h" #include "utility/messaging/type/MessageGraphNodeBundleSplit.h" +#include "utility/messaging/type/MessageGraphNodeHide.h" #include "utility/messaging/type/MessageTooltipShow.h" #include "utility/messaging/type/MessageTooltipHide.h" #include "utility/utility.h" @@ -80,6 +81,16 @@ QtGraphNode* QtGraphEdge::getTarget() return m_target; } +Id QtGraphEdge::getTokenId() const +{ + if (getData()) + { + return getData()->getId(); + } + + return 0; +} + void QtGraphEdge::updateLine() { QtGraphNode* owner = m_owner; @@ -269,6 +280,16 @@ void QtGraphEdge::onClick() } } +void QtGraphEdge::onHide() +{ + Id tokenId = getTokenId(); + + if (tokenId) + { + MessageGraphNodeHide(tokenId).dispatch(); + } +} + void QtGraphEdge::focusIn() { if (!m_isFocused) @@ -328,7 +349,14 @@ void QtGraphEdge::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { if (!m_mouseMoved) { - this->onClick(); + if (event->modifiers() & Qt::AltModifier) + { + this->onHide(); + } + else + { + this->onClick(); + } } } diff --git a/src/lib_gui/qt/view/graphElements/QtGraphEdge.h b/src/lib_gui/qt/view/graphElements/QtGraphEdge.h index a84f21fb..14a19129 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphEdge.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphEdge.h @@ -35,6 +35,8 @@ public: QtGraphNode* getOwner(); QtGraphNode* getTarget(); + Id getTokenId() const; + void updateLine(); bool getIsActive() const; @@ -44,6 +46,7 @@ public: void setIsFocused(bool isFocused); void onClick(); + void onHide(); void focusIn(); void focusOut(); diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp index 8dda80fa..1aeca187 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp @@ -11,6 +11,7 @@ #include "qt/utility/utilityQt.h" #include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h" #include "qt/view/graphElements/QtGraphEdge.h" +#include "utility/messaging/type/MessageGraphNodeHide.h" #include "utility/ResourcePaths.h" #include "utility/utilityString.h" @@ -345,6 +346,20 @@ void QtGraphNode::onClick() { } +void QtGraphNode::onHide() +{ + Id tokenId = getTokenId(); + + if (tokenId) + { + MessageGraphNodeHide(tokenId).dispatch(); + } + else if (getParent()) + { + getParent()->onHide(); + } +} + void QtGraphNode::mousePressEvent(QGraphicsSceneMouseEvent* event) { event->ignore(); diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNode.h b/src/lib_gui/qt/view/graphElements/QtGraphNode.h index 3ce19a67..8a64cdca 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNode.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphNode.h @@ -92,6 +92,7 @@ public: virtual void addSubNode(QtGraphNode* node); virtual void onClick(); + virtual void onHide(); virtual void moved(const Vec2i& oldPosition); virtual void updateStyle() = 0; diff --git a/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp b/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp index e53369bd..83c6b1dc 100644 --- a/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp +++ b/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp @@ -35,7 +35,14 @@ void QtGraphNodeComponentClickable::nodeMouseReleaseEvent(QGraphicsSceneMouseEve { if (!m_mouseMoved) { - m_graphNode->onClick(); + if (event->modifiers() & Qt::AltModifier) + { + m_graphNode->onHide(); + } + else + { + m_graphNode->onClick(); + } event->accept(); } }