This repository has been archived by the owner on Jun 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
node.cpp
143 lines (123 loc) · 3.73 KB
/
node.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "node.h"
qreal Node::minLength = 2500;
Node::Node(GraphWidget *graphWidget) : graph(graphWidget) {
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
setCacheMode(DeviceCoordinateCache);
setZValue(-1);
}
void Node::addEdge(Edge *edge) {
edgeList << edge;
edge->adjust();
}
/* Return a list of attached edges */
QVector<Edge *> Node::edges() const {
return edgeList;
}
void Node::calculateForces()
{
if (!scene() || scene()->mouseGrabberItem() == this) {
newPos = pos();
return;
}
// Sum up all forces pushing this item away
qreal xvel = 0;
qreal yvel = 0;
const QList<QGraphicsItem *> items = scene()->items();
for (QGraphicsItem *item : items) {
Node *node = qgraphicsitem_cast<Node *>(item);
if (!node)
continue;
QPointF vec = mapToItem(node, 0, 0);
qreal dx = vec.x();
qreal dy = vec.y();
double l = 2.0 * (dx * dx + dy * dy);
if (l > 0) {
xvel += (dx * minLength) / l;
yvel += (dy * minLength) / l;
}
}
// Now subtract all forces pulling items together
double weight = (edgeList.size() + 1) * 10;
for (const Edge *edge : qAsConst(edgeList)) {
QPointF vec;
if (edge->sourceNode() == this)
vec = mapToItem(edge->destNode(), 0, 0);
else
vec = mapToItem(edge->sourceNode(), 0, 0);
xvel -= vec.x() / weight;
yvel -= vec.y() / weight;
}
if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1)
xvel = yvel = 0;
QRectF sceneRect = scene()->sceneRect();
newPos = pos() + QPointF(xvel, yvel);
newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10));
newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10));
}
/* Update current position */
bool Node::advancePosition() {
if (newPos == pos())
return false;
setPos(newPos);
return true;
}
QRectF Node::boundingRect() const {
qreal adjust = 2;
return QRectF( -10 - adjust, -10 - adjust, 23 + adjust, 23 + adjust);
}
QPainterPath Node::shape() const
{
QPainterPath path;
path.addEllipse(-10, -10, 20, 20);
return path;
}
void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) {
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-7, -7, 20, 20);
QRadialGradient gradient(-3, -3, 10);
if (option->state & QStyle::State_Sunken) {
gradient.setCenter(3, 3);
gradient.setFocalPoint(3, 3);
gradient.setColorAt(1, QColor(Qt::yellow).lighter(120));
gradient.setColorAt(0, QColor(Qt::darkYellow).lighter(120));
} else {
gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::darkYellow);
}
painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 0));
painter->drawEllipse(-10, -10, 20, 20);
QFont font = painter->font();
font.setBold(true);
font.setPixelSize(100);
const QRect rectangle = QRect(-7, -7, 100, 100);
painter->drawText(rectangle, 0, label);
}
void Node::setLabel(QString label) {
this->label = label;
}
QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
{
switch (change) {
case ItemPositionHasChanged:
for (Edge *edge : qAsConst(edgeList))
edge->adjust();
graph->itemMoved();
break;
default:
break;
};
return QGraphicsItem::itemChange(change, value);
}
void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mousePressEvent(event);
}
void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mouseReleaseEvent(event);
}