1 // This file is part of Heimer.
2 // Copyright (C) 2018 Jussi Lind <jussi.lind@iki.fi>
3 //
4 // Heimer is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 // Heimer is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Heimer. If not, see <http://www.gnu.org/licenses/>.
15 
16 #ifndef EDGE_HPP
17 #define EDGE_HPP
18 
19 #include <QGraphicsLineItem>
20 #include <QTimer>
21 
22 #include <map>
23 #include <memory>
24 
25 #include "edge_point.hpp"
26 #include "edge_text_edit.hpp"
27 
28 class EdgeDot;
29 class Node;
30 class QFont;
31 class QGraphicsEllipseItem;
32 class QPropertyAnimation;
33 
34 //! A graphic representation of a graph edge between nodes.
35 class Edge : public QObject, public QGraphicsLineItem
36 {
37     Q_OBJECT
38 
39 public:
40     enum class ArrowMode
41     {
42         Single = 0,
43         Double = 1,
44         Hidden = 2
45     };
46 
47     Edge(Node & sourceNode, Node & targetNode, bool enableAnimations = true, bool enableLabel = true);
48 
49     virtual ~Edge() override;
50 
51     Node & sourceNode() const;
52 
53     Node & targetNode() const;
54 
55     void setSourceNode(Node & sourceNode);
56 
57     void setTargetNode(Node & targetNode);
58 
59     virtual void hoverEnterEvent(QGraphicsSceneHoverEvent * event) override;
60 
61     virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent * event) override;
62 
63     QString text() const;
64 
65     ArrowMode arrowMode() const;
66 
67     bool reversed() const;
68 
69 public slots:
70 
71     void updateLine();
72 
73     void setArrowMode(ArrowMode arrowMode);
74 
75     void setColor(const QColor & color);
76 
77     void setFont(const QFont & font);
78 
79     void setWidth(double width);
80 
81     void setText(const QString & text);
82 
83     void setTextSize(int textSize);
84 
85     void setReversed(bool reversed);
86 
87     void setSelected(bool selected);
88 
89 signals:
90 
91     void undoPointRequested();
92 
93 private:
94     QPen getPen() const;
95 
96     void initDots();
97 
98     void setArrowHeadPen(const QPen & pen);
99 
100     void setLabelVisible(bool visible, EdgeTextEdit::VisibilityChangeReason vcr = EdgeTextEdit::VisibilityChangeReason::Default);
101 
102     void updateArrowhead();
103 
104     void updateDots();
105 
106     enum class LabelUpdateReason
107     {
108         Default,
109         EdgeGeometryChanged
110     };
111 
112     void updateLabel(LabelUpdateReason lur = LabelUpdateReason::Default);
113 
114     Node * m_sourceNode = nullptr;
115 
116     Node * m_targetNode = nullptr;
117 
118     QString m_text;
119 
120     double m_width = 2;
121 
122     int m_textSize = 11; // Not sure if we should set yet another default value here..
123 
124     QColor m_color;
125 
126     bool m_reversed;
127 
128     bool m_selected = false;
129 
130     ArrowMode m_arrowMode;
131 
132     bool m_enableAnimations;
133 
134     bool m_enableLabel;
135 
136     EdgeDot * m_sourceDot;
137 
138     EdgeDot * m_targetDot;
139 
140     QPointF m_previousRelativeSourcePos;
141 
142     QPointF m_previousRelativeTargetPos;
143 
144     EdgeTextEdit * m_label;
145 
146     QGraphicsLineItem * m_arrowheadL0;
147 
148     QGraphicsLineItem * m_arrowheadR0;
149 
150     QGraphicsLineItem * m_arrowheadL1;
151 
152     QGraphicsLineItem * m_arrowheadR1;
153 
154     QPropertyAnimation * m_sourceDotSizeAnimation;
155 
156     QPropertyAnimation * m_targetDotSizeAnimation;
157 
158     QTimer m_labelVisibilityTimer;
159 };
160 
161 using EdgePtr = std::shared_ptr<Edge>;
162 
163 #endif // EDGE_HPP
164