ui: styled nodes in graph view

This change styles the nodes in the QtGraphView. Since Stylesheets can't be applied to QGraphicsItems, the style
implementation was done in the source files. The containers for public/protected/private nodes are now subclassed from
QtGraphNode as QtGraphNodeAccess, including a helper class QtAccessArrow for indicating the opened/colapsed state.
This commit is contained in:
Eberhard Graether
2014-11-12 01:42:49 +01:00
parent 5b230cefa0
commit 72c5847d75
24 changed files with 731 additions and 344 deletions
+283 -177
View File
@@ -1,46 +1,50 @@
#include "qt/view/graphElements/QtGraphNode.h"
#include <sstream>
#include <QBrush>
#include <QFontMetrics>
#include <QGraphicsScene>
#include <QGraphicsSceneEvent>
#include <QPen>
#include "qt/view/graphElements/QtGraphEdge.h"
#include "utility/messaging/type/MessageActivateToken.h"
#include "qt/graphics/QtGraphicsRoundedRectItem.h"
#include "qt/utility/QtDeviceScaledPixmap.h"
#include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h"
#include "qt/view/graphElements/QtGraphEdge.h"
QtGraphNode::QtGraphNode(const Node* data, TokenComponentAccess::AccessType accessType)
: GraphNode(data)
QtGraphNode::QtGraphNode()
: GraphNode(nullptr)
, m_undefinedRect(nullptr)
, m_padding(0, 0, 0, 0)
, m_spacing(8)
, m_isActive(false)
, m_padding(10, 10)
, m_contentHidden(false)
, m_isHovering(false)
{
m_text = new QGraphicsTextItem(this);
m_text->setPos(0, 0);
this->setPen(QPen(Qt::transparent));
std::stringstream text;
QBrush brush(Qt::white);
m_rect = new QtGraphicsRoundedRectItem(this);
m_text = new QGraphicsSimpleTextItem(this);
}
if (data)
{
text << data->getId() << ": " << data->getName();
brush.setColor(Qt::lightGray);
}
else
{
text << TokenComponentAccess::getAccessString(accessType);
}
QtGraphNode::QtGraphNode(const Node* data)
: GraphNode(data)
, m_undefinedRect(nullptr)
, m_padding(0, 0, 0, 0)
, m_spacing(8)
, m_isActive(false)
, m_isHovering(false)
{
this->setPen(QPen(Qt::transparent));
m_text->setPlainText(QString(text.str().c_str()));
this->setBrush(brush);
m_rect = new QtGraphicsRoundedRectItem(this);
m_text = new QGraphicsSimpleTextItem(this);
m_baseSize.x = QFontMetrics(m_text->font()).width(m_text->toPlainText()) + 10;
m_baseSize.y = 25;
m_currentSize = m_baseSize;
this->setRect(0, 0, m_baseSize.x, m_baseSize.y);
this->setAcceptHoverEvents(true);
this->setName(data->getName());
this->setStyle();
this->setSize(m_baseSize);
}
QtGraphNode::~QtGraphNode()
@@ -57,7 +61,12 @@ QtGraphNode::~QtGraphNode()
std::string QtGraphNode::getName() const
{
return m_text->toPlainText().toStdString();
return m_text->text().toStdString();
}
void QtGraphNode::setName(const std::string& name)
{
m_text->setText(QString::fromStdString(name));
}
Vec2i QtGraphNode::getPosition() const
@@ -82,46 +91,17 @@ Vec2i QtGraphNode::getSize() const
return m_currentSize;
}
bool QtGraphNode::getIsActive() const
void QtGraphNode::setSize(Vec2i size)
{
return m_isActive;
}
m_currentSize = size;
void QtGraphNode::setIsActive(bool isActive)
{
m_isActive = isActive;
this->setRect(0, 0, size.x, size.y);
m_rect->setRect(0, 0, size.x, size.y);
QPen p = this->pen();
if (isActive)
if (m_undefinedRect)
{
p.setWidth(2);
m_undefinedRect->setRect(1, 1, size.x - 2, size.y - 2);
}
else
{
p.setWidth(1);
}
this->setPen(p);
}
QtGraphNode* QtGraphNode::getParent() const
{
return m_parentNode.lock().get();
}
void QtGraphNode::setParent(std::weak_ptr<QtGraphNode> parentNode)
{
m_parentNode = parentNode;
std::shared_ptr<QtGraphNode> parent = parentNode.lock();
if (parent != NULL)
{
QGraphicsRectItem::setParentItem(parent.get());
}
}
void QtGraphNode::addComponent(const std::shared_ptr<QtGraphNodeComponent>& component)
{
m_components.push_back(component);
}
bool QtGraphNode::addOutEdge(const std::shared_ptr<GraphEdge>& edge)
@@ -173,72 +153,6 @@ void QtGraphNode::removeOutEdge(GraphEdge* edge)
}
}
std::list<std::shared_ptr<GraphNode>> QtGraphNode::getSubNodes() const
{
return m_subNodes;
}
void QtGraphNode::addSubNode(const std::shared_ptr<GraphNode>& node)
{
m_subNodes.push_back(node);
rebuildLayout();
}
void QtGraphNode::notifyParentMoved()
{
notifyEdgesAfterMove();
}
void QtGraphNode::hideContent()
{
for (std::shared_ptr<GraphNode> node : m_subNodes)
{
node->hideContent();
if (node->getTokenId() && node->getEdgeAndActiveCountRecursive() <= 0)
{
node->hide();
}
}
m_contentHidden = true;
onChildSizeChanged();
}
void QtGraphNode::showContent()
{
for (std::shared_ptr<GraphNode> node : m_subNodes)
{
node->show();
}
m_contentHidden = false;
onChildSizeChanged();
}
void QtGraphNode::hide()
{
QGraphicsRectItem::hide();
}
void QtGraphNode::show()
{
QGraphicsRectItem::show();
}
bool QtGraphNode::isHidden()
{
return !QGraphicsRectItem::isVisible();
}
bool QtGraphNode::contentIsHidden()
{
return m_contentHidden;
}
unsigned int QtGraphNode::getOutEdgeCount() const
{
return m_outEdges.size();
@@ -249,6 +163,49 @@ unsigned int QtGraphNode::getInEdgeCount() const
return m_inEdges.size();
}
bool QtGraphNode::getIsActive() const
{
return m_isActive;
}
void QtGraphNode::setIsActive(bool isActive)
{
m_isActive = isActive;
setStyle();
}
QtGraphNode* QtGraphNode::getParent() const
{
return m_parentNode.lock().get();
}
void QtGraphNode::setParent(std::weak_ptr<QtGraphNode> parentNode)
{
m_parentNode = parentNode;
std::shared_ptr<QtGraphNode> parent = parentNode.lock();
if (parent != NULL)
{
QGraphicsRectItem::setParentItem(parent.get());
}
}
void QtGraphNode::addComponent(const std::shared_ptr<QtGraphNodeComponent>& component)
{
m_components.push_back(component);
}
std::list<std::shared_ptr<QtGraphNode>> QtGraphNode::getSubNodes() const
{
return m_subNodes;
}
void QtGraphNode::addSubNode(const std::shared_ptr<QtGraphNode>& node)
{
m_subNodes.push_back(node);
}
unsigned int QtGraphNode::getEdgeAndActiveCountRecursive() const
{
unsigned int result = 0;
@@ -258,7 +215,7 @@ unsigned int QtGraphNode::getEdgeAndActiveCountRecursive() const
result++;
}
for (std::shared_ptr<GraphNode> node : m_subNodes)
for (std::shared_ptr<QtGraphNode> node : m_subNodes)
{
result += node->getEdgeAndActiveCountRecursive();
}
@@ -268,9 +225,24 @@ unsigned int QtGraphNode::getEdgeAndActiveCountRecursive() const
return result;
}
void QtGraphNode::hideContent()
{
for (std::shared_ptr<QtGraphNode> node : m_subNodes)
{
node->hideContent();
if (node->getTokenId() && node->getEdgeAndActiveCountRecursive() <= 0)
{
node->hide();
}
}
rebuildLayout();
}
void QtGraphNode::onClick()
{
if (m_data)
if (m_data && !m_data->isType(Node::NODE_UNDEFINED | Node::NODE_NAMESPACE))
{
MessageActivateToken(m_data->getId()).dispatch();
}
@@ -335,87 +307,221 @@ void QtGraphNode::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
void QtGraphNode::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
if (m_data)
{
bool isActive = m_isActive;
this->setIsActive(true);
m_isActive = isActive;
}
m_isHovering = true;
setStyle();
}
void QtGraphNode::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
this->setIsActive(m_isActive);
m_isHovering = false;
setStyle();
}
void QtGraphNode::notifyEdgesAfterMove()
{
for (std::list<std::shared_ptr<GraphEdge>>::iterator it = m_outEdges.begin(); it != m_outEdges.end(); it++)
for (const std::shared_ptr<GraphEdge>& edge : m_outEdges)
{
(*it)->ownerMoved();
edge->ownerMoved();
}
std::list<std::weak_ptr<GraphEdge>>::iterator it2 = m_inEdges.begin();
while (it2 != m_inEdges.end())
for (const std::weak_ptr<GraphEdge>& e : m_inEdges)
{
std::shared_ptr<GraphEdge> edge = it2->lock();
if (edge.get() != NULL)
{
edge->targetMoved();
++it2;
}
else
{
m_inEdges.erase(it2++);
}
std::shared_ptr<GraphEdge> edge = e.lock();
if (edge)
{
edge->targetMoved();
}
}
for (std::list<std::shared_ptr<GraphNode>>::iterator it3 = m_subNodes.begin(); it3 != m_subNodes.end(); it3++)
for (const std::shared_ptr<QtGraphNode>& node : m_subNodes)
{
(*it3)->notifyParentMoved();
node->notifyEdgesAfterMove();
}
}
void QtGraphNode::notifyParentNodeAfterSizeChanged()
void QtGraphNode::onSizeChanged()
{
rebuildLayout();
std::shared_ptr<QtGraphNode> parentNode = m_parentNode.lock();
if (parentNode != NULL)
{
parentNode->onChildSizeChanged();
parentNode->onSizeChanged();
}
}
void QtGraphNode::onChildSizeChanged()
{
rebuildLayout();
notifyParentNodeAfterSizeChanged();
}
void QtGraphNode::rebuildLayout()
{
int nextYPos = m_baseSize.y;
int newWidth = m_baseSize.x;
setStyle();
for (const std::shared_ptr<GraphNode>& node : m_subNodes)
Vec2i newSize(m_baseSize);
newSize.y = newSize.y - m_padding.w;
for (const std::shared_ptr<QtGraphNode>& node : m_subNodes)
{
if (!node->isHidden())
if (node->isVisible())
{
node->setPosition(this->getPosition() + Vec2i(m_padding.x, nextYPos));
nextYPos += node->getSize().y + m_padding.y;
node->setPosition(this->getPosition() + Vec2i(m_padding.x, m_spacing + newSize.y));
newSize.y = newSize.y + m_spacing + node->getSize().y;
int tmpWidth = (node->getPosition().x - getPosition().x) + node->getSize().x + m_padding.x;
int tmpWidth = node->getSize().x + m_padding.x + m_padding.z;
if (tmpWidth > newWidth)
if (tmpWidth > newSize.x)
{
newWidth = tmpWidth;
newSize.x = tmpWidth;
}
}
}
m_currentSize.x = newWidth;
m_currentSize.y = nextYPos;
newSize.y = newSize.y + m_padding.w;
setSize(newSize);
}
this->setRect(0, 0, m_currentSize.x, m_currentSize.y);
void QtGraphNode::setStyle()
{
if (!m_data)
{
return;
}
QColor color = Qt::lightGray;
qreal radius = 0.0f;
QFont font("Source Code Pro");
QPen p(Qt::transparent);
bool undefined = false;
bool useUndefinedColor = false;
switch (m_data->getType())
{
case Node::NODE_UNDEFINED:
undefined = true;
case Node::NODE_NAMESPACE:
color = Qt::white;
p.setColor("#cc8d91");
p.setWidth(1);
font.setPointSize(12);
radius = 20.0f;
m_padding.x = m_padding.z = 15;
m_padding.y = 6;
m_padding.w = 15;
break;
case Node::NODE_UNDEFINED_TYPE:
undefined = true;
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_ENUM:
case Node::NODE_TYPEDEF:
if (m_isHovering)
{
m_rect->setShadow(QColor(0, 0, 0, 255), 5);
}
else
{
m_rect->setShadow(QColor(0, 0, 0, 128), 5);
}
font.setPointSize(14);
color = "#ededed";
if (m_subNodes.size())
{
radius = 20.0f;
m_padding.x = m_padding.z = 15;
m_padding.y = m_padding.w = 10;
}
else
{
radius = 10.0f;
m_padding.x = m_padding.z = 8;
m_padding.y = m_padding.w = 5;
}
break;
case Node::NODE_UNDEFINED_FUNCTION:
undefined = true;
useUndefinedColor = true;
case Node::NODE_FUNCTION:
case Node::NODE_METHOD:
if (m_isActive || m_isHovering)
{
color = "#ffcc00";
font.setWeight(QFont::Bold);
}
else
{
color = "#ffe47a";
}
font.setPointSize(11);
radius = 8.0f;
m_padding.x = m_padding.z = 5;
m_padding.y = m_padding.w = 3;
break;
case Node::NODE_UNDEFINED_VARIABLE:
undefined = true;
useUndefinedColor = true;
case Node::NODE_GLOBAL_VARIABLE:
case Node::NODE_FIELD:
if (m_isActive || m_isHovering)
{
color = "#62b29d";
font.setWeight(QFont::Bold);
}
else
{
color = "#9ab4ad";
}
font.setPointSize(11);
radius = 8.0f;
m_padding.x = m_padding.z = 5;
m_padding.y = m_padding.w = 3;
break;
}
if (m_isActive)
{
p.setWidthF(1.5f);
p.setColor("#3c3c3c");
}
m_rect->setPen(p);
m_rect->setBrush(QBrush(color));
m_rect->setRadius(radius);
if (undefined)
{
QtDeviceScaledPixmap pixmap("data/gui/graph_view/images/pattern.png");
pixmap.scaleToHeight(10);
if (!m_undefinedRect)
{
m_undefinedRect = new QtGraphicsRoundedRectItem(this);
}
p.setWidth(1);
p.setColor(Qt::transparent);
if (useUndefinedColor && !m_isActive)
{
p.setColor(color);
}
m_undefinedRect->setPen(p);
m_undefinedRect->setBrush(QBrush(pixmap.pixmap()));
m_undefinedRect->setRadius(radius);
}
m_text->setFont(font);
m_text->setPos(m_padding.x, m_padding.y);
m_baseSize.x = QFontMetrics(m_text->font()).width(m_text->text()) + m_padding.x + m_padding.z;
m_baseSize.y = QFontMetrics(m_text->font()).height() + m_padding.y + m_padding.w;
}