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