diff --git a/bin/app/data/color_schemes/bad_rainbow.xml b/bin/app/data/color_schemes/bad_rainbow.xml index 4fcae1e7..465028bb 100644 --- a/bin/app/data/color_schemes/bad_rainbow.xml +++ b/bin/app/data/color_schemes/bad_rainbow.xml @@ -284,13 +284,18 @@ - #EE7326 - #EE8A4C + #873E3E #80FFFFFF #FFFFFF + + #FFFFFF + + + #FFFFFF + namespace @@ -347,6 +352,17 @@ #CCCCCC + + + #873E3E + + + #FFFFFF + + + #FFFFFF + + diff --git a/bin/app/data/color_schemes/bright.xml b/bin/app/data/color_schemes/bright.xml index 47735a52..72bd0995 100644 --- a/bin/app/data/color_schemes/bright.xml +++ b/bin/app/data/color_schemes/bright.xml @@ -270,12 +270,15 @@ - #CC8D91 + #EFC5C5 - #803C3C3C - #3C3C3C + #3D3D3D + black + + #3D3D3D + namespace @@ -320,6 +323,17 @@ #5C5C5C + + + #EFC5C5 + + + #3D3D3D + + + black + + diff --git a/bin/app/data/color_schemes/dark.xml b/bin/app/data/color_schemes/dark.xml index 4f902c0b..a8aee78a 100644 --- a/bin/app/data/color_schemes/dark.xml +++ b/bin/app/data/color_schemes/dark.xml @@ -26,25 +26,6 @@ #444444 - - - - - - - - - - - - - - - - - - - @@ -298,6 +279,9 @@ #80C3C3C3 #C3C3C3 + + #C3C3C3 + namespace @@ -342,6 +326,17 @@ #F7F7F7 + + + #78282D + + + #C3C3C3 + + + #F7F7F7 + + diff --git a/bin/app/data/gui/graph_view/images/namespace.png b/bin/app/data/gui/graph_view/images/namespace.png new file mode 100644 index 00000000..f12ba7df Binary files /dev/null and b/bin/app/data/gui/graph_view/images/namespace.png differ diff --git a/src/lib/component/controller/FeatureController.cpp b/src/lib/component/controller/FeatureController.cpp index f5f1bb01..eef4eefc 100644 --- a/src/lib/component/controller/FeatureController.cpp +++ b/src/lib/component/controller/FeatureController.cpp @@ -88,16 +88,14 @@ void FeatureController::handleMessage(MessageActivateFile* message) void FeatureController::handleMessage(MessageActivateNodes* message) { std::vector nodeIds; - if (!message->isReplayed()) + + for (const MessageActivateNodes::ActiveNode& node : message->nodes) { - for (const MessageActivateNodes::ActiveNode& node : message->nodes) + if (!message->isReplayed() && node.nodeId) { nodeIds.push_back(node.nodeId); } - } - else - { - for (const MessageActivateNodes::ActiveNode& node : message->nodes) + else { Id nodeId = m_storageAccess->getIdForNodeWithNameHierarchy(node.nameHierarchy); if (nodeId > 0) @@ -107,7 +105,6 @@ void FeatureController::handleMessage(MessageActivateNodes* message) } } - MessageActivateTokens m(message, nodeIds); for (const MessageActivateNodes::ActiveNode& node : message->nodes) { diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 08436751..eb661f94 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -262,15 +262,26 @@ void GraphController::createDummyGraphForTokenIds(const std::vector& tokenId { node->hasParent = false; - // we remove the name qualifier for java projects. - // TODO: get rid of this distinction once we implemented better namespace/package display in graph. - if (Application::getInstance()->getCurrentProject()->getLanguage() == LANGUAGE_JAVA && !node->data->isType(Node::NODE_PACKAGE)) + if (node->data->isType(Node::NODE_UNDEFINED | Node::NODE_NAMESPACE | Node::NODE_PACKAGE)) { - node->name = node->data->getName(); + node->name = node->data->getFullName(); } else { - node->name = node->data->getFullName(); + node->name = node->data->getName(); + + NameHierarchy qualifier = node->data->getNameHierarchy(); + qualifier.pop(); + + if (qualifier.size()) + { + std::shared_ptr qualifierNode = std::make_shared(); + qualifierNode->visible = true; + qualifierNode->qualifierName = qualifier; + + node->subNodes.push_back(qualifierNode); + node->hasQualifier = true; + } } } @@ -516,6 +527,11 @@ bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode* node, bool n node->visible = true; return true; } + else if (node->isQualifierNode()) + { + node->visible = true; + return false; + } for (std::shared_ptr subNode : node->subNodes) { @@ -543,8 +559,11 @@ void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode* node, bool pa { for (std::shared_ptr subNode : node->subNodes) { - node->childVisible = true; - setNodeVisibilityRecursiveTopDown(subNode.get(), node->isExpanded()); + if (!subNode->isQualifierNode()) + { + node->childVisible = true; + setNodeVisibilityRecursiveTopDown(subNode.get(), node->isExpanded()); + } } } } @@ -985,6 +1004,10 @@ void GraphController::layoutNestingRecursive(DummyNode* node) const { margins = GraphViewStyle::getMarginsOfBundleNode(); } + else if (node->isQualifierNode()) + { + return; + } int y = 0; int x = 0; @@ -1038,9 +1061,15 @@ void GraphController::layoutNestingRecursive(DummyNode* node) const { continue; } + else if (subNode->isQualifierNode()) + { + subNode->position.y = margins.top + margins.charHeight / 2; + width += 5; + continue; + } subNode->position.x = margins.left + x; - subNode->position.y = margins.top + margins.charHeight + y; + subNode->position.y = margins.top + margins.charHeight + margins.spacingA + y; if (layoutHorizontal) { @@ -1075,7 +1104,7 @@ void GraphController::layoutNestingRecursive(DummyNode* node) const } node->size.x = margins.left + width + margins.right; - node->size.y = margins.top + margins.charHeight + y + height + margins.bottom; + node->size.y = margins.top + margins.charHeight + margins.spacingA + y + height + margins.bottom; for (std::shared_ptr subNode : node->subNodes) { diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index e6c6312b..e7e0d397 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -7,6 +7,7 @@ #include "utility/utilityString.h" #include "data/graph/token_component/TokenComponentAccess.h" +#include "data/name/NameHierarchy.h" class Node; @@ -42,6 +43,7 @@ public: , expanded(false) , autoExpanded(false) , hasParent(true) + , hasQualifier(false) , accessKind(ACCESS_NONE) , invisibleSubNodeCount(0) , layoutBucket(0, 0) @@ -61,7 +63,7 @@ public: bool isExpandToggleNode() const { - return !isGraphNode() && !isAccessNode() && !isBundleNode(); + return !isGraphNode() && !isAccessNode() && !isBundleNode() && !isQualifierNode(); } bool isBundleNode() const @@ -69,6 +71,11 @@ public: return bundledNodes.size() > 0; } + bool isQualifierNode() const + { + return qualifierName.size(); + } + bool isExpanded() const { return expanded; @@ -222,6 +229,7 @@ public: bool expanded; bool autoExpanded; bool hasParent; + bool hasQualifier; // AccessNode AccessKind accessKind; @@ -238,6 +246,9 @@ public: // BundleNode std::vector> bundledNodes; size_t bundledNodeCount; + + // QualifierNode + NameHierarchy qualifierName; }; #endif // DUMMY_NODE_H diff --git a/src/lib/component/view/GraphViewStyle.cpp b/src/lib/component/view/GraphViewStyle.cpp index 6d30ab84..262c893c 100644 --- a/src/lib/component/view/GraphViewStyle.cpp +++ b/src/lib/component/view/GraphViewStyle.cpp @@ -30,6 +30,7 @@ GraphViewStyle::NodeMargins::NodeMargins() , bottom(0) , spacingX(0) , spacingY(0) + , spacingA(0) , minWidth(0) , charWidth(0.0f) , charHeight(0.0f) @@ -128,9 +129,11 @@ size_t GraphViewStyle::getFontSizeForNodeType(Node::NodeType type) { switch (type) { - case Node::NODE_UNDEFINED: case Node::NODE_NAMESPACE: case Node::NODE_PACKAGE: + return s_fontSize - 2; + + case Node::NODE_UNDEFINED: case Node::NODE_TYPE: case Node::NODE_BUILTIN_TYPE: case Node::NODE_STRUCT: @@ -168,6 +171,11 @@ size_t GraphViewStyle::getFontSizeOfCountCircle() return s_fontSize - 3; } +size_t GraphViewStyle::getFontSizeOfQualifier() +{ + return s_fontSize - 3; +} + std::string GraphViewStyle::getFontNameForNodeType(Node::NodeType type) { return s_fontName; @@ -191,14 +199,19 @@ GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType switch (type) { + case Node::NODE_NAMESPACE: + case Node::NODE_PACKAGE: + margins.left = margins.right = 5; + margins.top = margins.bottom = 3; + margins.iconWidth = s_fontSize - 3; + break; + case Node::NODE_ENUM: case Node::NODE_TYPEDEF: case Node::NODE_FILE: case Node::NODE_MACRO: margins.iconWidth = s_fontSize + 11; case Node::NODE_UNDEFINED: - case Node::NODE_NAMESPACE: - case Node::NODE_PACKAGE: case Node::NODE_TYPE: case Node::NODE_BUILTIN_TYPE: case Node::NODE_STRUCT: @@ -209,8 +222,8 @@ GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType if (hasChildren) { margins.left = margins.right = 10; - margins.top = 15; - margins.bottom = 10; + margins.top = margins.bottom = 10; + margins.spacingA = 5; } else { @@ -226,9 +239,9 @@ GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType case Node::NODE_ENUM_CONSTANT: if (hasChildren) { - margins.top = 8; - margins.bottom = 5; + margins.top = margins.bottom = 5; margins.spacingY = 4; + margins.spacingA = 3; } else { @@ -296,7 +309,7 @@ GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfBundleNode() } GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType( - Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren + Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren, bool hasQualifier ){ NodeStyle style; @@ -305,11 +318,30 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType( style.fontName = getFontNameForNodeType(type); style.fontSize = getFontSizeForNodeType(type); + if (isActive || isFocused) + { + style.fontBold = true; + } + + if (isActive) + { + style.borderWidth = 2; + } + else + { + style.borderWidth = 1; + } + switch (type) { - case Node::NODE_UNDEFINED: case Node::NODE_NAMESPACE: case Node::NODE_PACKAGE: + style.cornerRadius = 0; + style.textOffset.x = 5; + style.textOffset.y = 3; + break; + + case Node::NODE_UNDEFINED: case Node::NODE_TYPE: case Node::NODE_BUILTIN_TYPE: case Node::NODE_STRUCT: @@ -346,24 +378,22 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType( break; } - if (isActive) - { - style.borderWidth = 2; - } - else - { - style.borderWidth = 1; - } - - if (isActive || isFocused) - { - style.fontBold = true; - } - style.hasHatching = !defined; addIcon(type, hasChildren, &style); + if (hasQualifier) + { + if (style.iconPath.size()) + { + style.iconOffset.x = style.iconOffset.x + 5; + } + else + { + style.textOffset.x = style.textOffset.x + 5; + } + } + return style; } @@ -413,7 +443,7 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfCountCircle() GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfBundleNode(bool isFocused) { - NodeStyle style = getStyleForNodeType(Node::NODE_CLASS, true, false, isFocused, false); + NodeStyle style = getStyleForNodeType(Node::NODE_CLASS, true, false, isFocused, false, false); style.color = getNodeColor("bundle", isFocused); @@ -423,6 +453,16 @@ GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfBundleNode(bool isFocused) return style; } +GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfQualifier() +{ + NodeStyle style; + + style.color = getNodeColor("qualifier", false); + style.borderWidth = 2; + + return style; +} + GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused) { EdgeStyle style; @@ -571,6 +611,14 @@ void GraphViewStyle::addIcon(Node::NodeType type, bool hasChildren, NodeStyle* s { switch (type) { + case Node::NODE_NAMESPACE: + case Node::NODE_PACKAGE: + style->iconPath = ResourcePaths::getGuiPath() + "graph_view/images/namespace.png"; + style->iconSize = s_fontSize - 4; + style->iconOffset.x = -1; + style->iconOffset.y = 5; + return; + case Node::NODE_ENUM: style->iconPath = ResourcePaths::getGuiPath() + "graph_view/images/enum_1.png"; break; diff --git a/src/lib/component/view/GraphViewStyle.h b/src/lib/component/view/GraphViewStyle.h index 8440edac..c4a01bb8 100644 --- a/src/lib/component/view/GraphViewStyle.h +++ b/src/lib/component/view/GraphViewStyle.h @@ -26,6 +26,7 @@ public: int spacingX; int spacingY; + int spacingA; int minWidth; @@ -102,6 +103,7 @@ public: static size_t getFontSizeOfAccessNode(); static size_t getFontSizeOfExpandToggleNode(); static size_t getFontSizeOfCountCircle(); + static size_t getFontSizeOfQualifier(); static std::string getFontNameForNodeType(Node::NodeType type); static std::string getFontNameOfAccessNode(); @@ -112,11 +114,13 @@ public: static NodeMargins getMarginsOfExpandToggleNode(); static NodeMargins getMarginsOfBundleNode(); - static NodeStyle getStyleForNodeType(Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren); + static NodeStyle getStyleForNodeType( + Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren, bool hasQualifier); static NodeStyle getStyleOfAccessNode(); static NodeStyle getStyleOfExpandToggleNode(); static NodeStyle getStyleOfCountCircle(); static NodeStyle getStyleOfBundleNode(bool isFocused); + static NodeStyle getStyleOfQualifier(); static EdgeStyle getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused); diff --git a/src/lib/utility/messaging/type/MessageActivateNodes.h b/src/lib/utility/messaging/type/MessageActivateNodes.h index 0dbcb5bb..4cc070ec 100644 --- a/src/lib/utility/messaging/type/MessageActivateNodes.h +++ b/src/lib/utility/messaging/type/MessageActivateNodes.h @@ -31,6 +31,16 @@ public: nodes.push_back(node); } + void addNode(const NameHierarchy& nameHierarchy) + { + ActiveNode node; + node.nodeId = 0; + node.type = Node::NODE_UNDEFINED; + node.nameHierarchy = nameHierarchy; + + nodes.push_back(node); + } + static const std::string getStaticType() { return "MessageActivateNodes"; diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index 47e25f35..d8961b19 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -90,6 +90,8 @@ add_files( qt/view/graphElements/QtGraphNodeData.h qt/view/graphElements/QtGraphNodeExpandToggle.cpp qt/view/graphElements/QtGraphNodeExpandToggle.h + qt/view/graphElements/QtGraphNodeQualifier.cpp + qt/view/graphElements/QtGraphNodeQualifier.h qt/view/QtCodeView.cpp qt/view/QtCodeView.h diff --git a/src/lib_gui/qt/view/QtGraphView.cpp b/src/lib_gui/qt/view/QtGraphView.cpp index 123c747e..f0f6f594 100644 --- a/src/lib_gui/qt/view/QtGraphView.cpp +++ b/src/lib_gui/qt/view/QtGraphView.cpp @@ -27,6 +27,7 @@ #include "qt/view/graphElements/QtGraphNodeBundle.h" #include "qt/view/graphElements/QtGraphNodeData.h" #include "qt/view/graphElements/QtGraphNodeExpandToggle.h" +#include "qt/view/graphElements/QtGraphNodeQualifier.h" QtGraphView::QtGraphView(ViewLayout* viewLayout) : GraphView(viewLayout) @@ -344,7 +345,7 @@ std::shared_ptr QtGraphView::createNodeRecursive( std::shared_ptr newNode; if (node->isGraphNode()) { - newNode = std::make_shared(node->data, node->name, node->hasParent, node->childVisible); + newNode = std::make_shared(node->data, node->name, node->hasParent, node->childVisible, node->hasQualifier); } else if (node->isAccessNode()) { @@ -358,6 +359,10 @@ std::shared_ptr QtGraphView::createNodeRecursive( { newNode = std::make_shared(node->tokenId, node->getBundledNodeCount(), node->name); } + else if (node->isQualifierNode()) + { + newNode = std::make_shared(node->qualifierName); + } newNode->setPosition(node->position); newNode->setSize(node->size); diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp index 1ebdf2eb..19f317ab 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp @@ -183,8 +183,6 @@ bool QtGraphNode::getIsActive() const void QtGraphNode::setIsActive(bool isActive) { m_isActive = isActive; - - updateStyle(); } void QtGraphNode::setMultipleActive(bool multipleActive) @@ -250,6 +248,11 @@ bool QtGraphNode::isBundleNode() const return false; } +bool QtGraphNode::isQualifierNode() const +{ + return false; +} + Id QtGraphNode::getTokenId() const { return 0; diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNode.h b/src/lib_gui/qt/view/graphElements/QtGraphNode.h index 312ac7d0..ed2fb95f 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNode.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphNode.h @@ -41,7 +41,7 @@ public: std::list> getSubNodes() const; Vec2i getPosition() const; - bool setPosition(const Vec2i& position); + virtual bool setPosition(const Vec2i& position); Vec2i getSize() const; void setSize(const Vec2i& size); @@ -76,6 +76,7 @@ public: virtual bool isAccessNode() const; virtual bool isExpandToggleNode() const; virtual bool isBundleNode() const; + virtual bool isQualifierNode() const; virtual Id getTokenId() const; diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp index e327c817..de5d55b2 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp @@ -8,9 +8,10 @@ #include "data/graph/token_component/TokenComponentSignature.h" -QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible) +QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible, bool hasQualifier) : m_data(data) , m_childVisible(childVisible) + , m_hasQualifier(hasQualifier) { this->setAcceptHoverEvents(true); @@ -80,7 +81,7 @@ void QtGraphNodeData::moved(const Vec2i& oldPosition) void QtGraphNodeData::updateStyle() { GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleForNodeType( - m_data->getType(), m_data->isExplicit(), m_isActive, m_isHovering, m_childVisible); + m_data->getType(), m_data->isExplicit(), m_isActive, m_isHovering, m_childVisible, m_hasQualifier); setStyle(style); } diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h index 34c23c23..b92f3b95 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h @@ -7,7 +7,7 @@ class QtGraphNodeData : public QtGraphNode { public: - QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible); + QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible, bool hasQualifier); virtual ~QtGraphNodeData(); const Node* getData() const; @@ -28,6 +28,7 @@ protected: private: const Node* m_data; bool m_childVisible; + bool m_hasQualifier; }; #endif // QT_GRAPH_NODE_DATA_H diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeQualifier.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNodeQualifier.cpp new file mode 100644 index 00000000..44c158c3 --- /dev/null +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeQualifier.cpp @@ -0,0 +1,147 @@ +#include "qt/view/graphElements/QtGraphNodeQualifier.h" + +#include +#include +#include + +#include "utility/messaging/type/MessageActivateNodes.h" + +#include "data/name/NameHierarchy.h" + +QtGraphNodeQualifier::QtGraphNodeQualifier(const NameHierarchy& name) + : m_qualifierName(name) +{ + this->setAcceptHoverEvents(true); + + m_background = new QGraphicsRectItem(this); + m_leftBorder = new QGraphicsRectItem(this); + m_rightArrow = new QGraphicsPolygonItem(this); + m_rightArrowSmall = new QGraphicsPolygonItem(this); + + QFont font; + font.setFamily(GraphViewStyle::getFontNameForNodeType(Node::NODE_UNDEFINED).c_str()); + font.setPixelSize(GraphViewStyle::getFontSizeOfQualifier()); + font.setWeight(QFont::Normal); + + m_name = new QGraphicsSimpleTextItem(this); + m_name->setFont(font); + m_name->setText(QString::fromStdString(name.getQualifiedName())); +} + +QtGraphNodeQualifier::~QtGraphNodeQualifier() +{ +} + +bool QtGraphNodeQualifier::isQualifierNode() const +{ + return true; +} + +bool QtGraphNodeQualifier::setPosition(const Vec2i& pos) +{ + int width = QFontMetrics(m_name->font()).width(m_name->text()) + 10; + int height = QFontMetrics(m_name->font()).height() + 2; + int arrowWidth = height * 0.85; + + float smallFactor = 0.5f; + int arrowOffset = arrowWidth * smallFactor; + + m_background->setRect(pos.x - width - arrowWidth + arrowOffset, pos.y - height / 2, width, height); + + m_name->setPos(pos.x - width - arrowWidth + arrowOffset + 6, pos.y - height / 2 + 1); + m_leftBorder->setRect(pos.x - width - arrowWidth + arrowOffset, pos.y - height / 2, 2, height); + + QPolygonF poly; + poly.append(QPointF(-arrowWidth, -height / 2 - 0.5)); + poly.append(QPointF(-arrowWidth, height / 2 + 0.5)); + poly.append(QPointF(0, 0)); + m_rightArrow->setPolygon(poly); + m_rightArrow->setPos(pos.x + arrowOffset, pos.y); + + QPolygonF polySmall; + polySmall.append(QPointF(-arrowWidth * smallFactor, -height * smallFactor / 2)); + polySmall.append(QPointF(-arrowWidth * smallFactor, height * smallFactor / 2)); + polySmall.append(QPointF(0, 0)); + m_rightArrowSmall->setPolygon(polySmall); + m_rightArrowSmall->setPos(pos.x + arrowOffset + 1, pos.y); + + m_pos = pos; + + return true; +} + +void QtGraphNodeQualifier::onClick() +{ + MessageActivateNodes msg; + msg.addNode(m_qualifierName); + msg.dispatch(); +} + +void QtGraphNodeQualifier::updateStyle() +{ + GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleOfQualifier(); + + this->setBrush(Qt::transparent); + this->setPen(QPen(Qt::transparent)); + + m_background->setBrush(QColor(style.color.fill.c_str())); + m_background->setPen(QPen(QColor(style.color.border.c_str()), 1)); + + m_name->setBrush(QColor(style.color.text.c_str())); + + QRectF rect = m_leftBorder->rect(); + rect.setWidth(style.borderWidth); + m_leftBorder->setRect(rect); + + m_leftBorder->setBrush(QColor(style.color.border.c_str())); + m_leftBorder->setPen(QPen(Qt::transparent)); + + m_rightArrow->setBrush(QColor(style.color.border.c_str())); + m_rightArrow->setPen(QPen(Qt::transparent)); + + m_rightArrowSmall->setBrush(QColor(style.color.border.c_str())); + m_rightArrowSmall->setPen(QPen(Qt::transparent)); + + hoverLeaveEvent(nullptr); +} + +void QtGraphNodeQualifier::hoverEnterEvent(QGraphicsSceneHoverEvent* event) +{ + int width = QFontMetrics(m_name->font()).width(m_name->text()) + 10; + int height = QFontMetrics(m_name->font()).height() + 2; + int arrowWidth = height * 0.85; + float smallFactor = 0.5f; + int arrowOffset = arrowWidth * smallFactor; + + setRect(m_pos.x - width - arrowWidth + arrowOffset, m_pos.y - height / 2, width + arrowWidth, height); + + m_background->show(); + m_name->show(); + m_leftBorder->show(); + m_rightArrow->show(); + m_rightArrowSmall->hide(); + + QPointF p = mapToScene(pos()); + this->setParentItem(nullptr); + this->setPos(p); + this->setZValue(100); +} + +void QtGraphNodeQualifier::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) +{ + int height = QFontMetrics(m_name->font()).height() + 2; + int arrowWidth = height * 0.85; + float smallFactor = 0.5f; + int arrowOffset = arrowWidth * smallFactor; + + setRect(m_pos.x - arrowWidth + arrowOffset, m_pos.y - height / 2, arrowWidth, height); + + m_background->hide(); + m_name->hide(); + m_leftBorder->hide(); + m_rightArrow->hide(); + m_rightArrowSmall->show(); + + this->setParentItem(m_parentNode.lock().get()); + this->setPos(QPointF(0, 0)); +} diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeQualifier.h b/src/lib_gui/qt/view/graphElements/QtGraphNodeQualifier.h new file mode 100644 index 00000000..f5787b80 --- /dev/null +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeQualifier.h @@ -0,0 +1,40 @@ +#ifndef QT_GRAPH_NODE_QUALIFIER_H +#define QT_GRAPH_NODE_QUALIFIER_H + +#include +#include + +#include "qt/view/graphElements/QtGraphNode.h" + +class QtGraphNodeQualifier + : public QtGraphNode +{ +public: + QtGraphNodeQualifier(const NameHierarchy& name); + virtual ~QtGraphNodeQualifier(); + + // QtGraphNode implementation + virtual bool isQualifierNode() const; + + virtual bool setPosition(const Vec2i& pos); + + virtual void onClick(); + virtual void updateStyle(); + +protected: + virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event); + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event); + +private: + const NameHierarchy m_qualifierName; + + QGraphicsRectItem* m_background; + QGraphicsRectItem* m_leftBorder; + QGraphicsPolygonItem* m_rightArrow; + QGraphicsPolygonItem* m_rightArrowSmall; + QGraphicsSimpleTextItem* m_name; + + Vec2i m_pos; +}; + +#endif // QT_GRAPH_NODE_QUALIFIER_H