2 #include <QGraphicsSceneMouseEvent>
7 GraphItem::GraphItem(const Graph
&graph
, GraphType type
, int width
,
8 const QColor
&color
, Qt::PenStyle style
, QGraphicsItem
*parent
)
9 : GraphicsItem(parent
), _graph(graph
), _type(type
), _secondaryGraph(0)
15 _pen
= QPen(GraphItem::color(), width
, style
, Qt::FlatCap
);
17 _time
= _graph
.hasTime();
19 setAcceptHoverEvents(true);
24 void GraphItem::updateShape()
26 QPainterPathStroker s
;
27 s
.setWidth(_pen
.width() + 1);
28 _shape
= s
.createStroke(_path
);
31 void GraphItem::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
,
37 painter
->setPen(_pen
);
38 painter
->drawPath(_path
);
40 //painter->setPen(Qt::red);
41 //painter->drawRect(boundingRect());
44 void GraphItem::setGraphType(GraphType type
)
49 prepareGeometryChange();
56 const QColor
&GraphItem::color() const
58 return (_useStyle
&& _graph
.color().isValid())
59 ? _graph
.color() : _color
;
62 void GraphItem::setColor(const QColor
&color
)
68 void GraphItem::updateColor()
70 _pen
.setColor(color());
74 void GraphItem::setWidth(int width
)
76 if (width
== _pen
.width())
79 prepareGeometryChange();
86 void GraphItem::updateStyle()
90 _secondaryGraph
->updateStyle();
93 const GraphSegment
*GraphItem::segment(qreal x
, GraphType type
) const
96 int high
= _graph
.size() - 1;
100 mid
= (high
+ low
) / 2;
101 const GraphPoint
&p
= _graph
.at(mid
).last();
104 else if (p
.x(_type
) < x
)
107 return &(_graph
.at(mid
));
110 if (_graph
.at(mid
).last().x(type
) < x
)
111 return (mid
== _graph
.size() - 1) ? 0 : &(_graph
.at(mid
+1));
113 return &(_graph
.at(mid
));
116 qreal
GraphItem::yAtX(qreal x
) const
118 const GraphSegment
*seg
= segment(x
, _type
);
123 int high
= seg
->count() - 1;
126 if (!(x
>= seg
->at(low
).x(_type
) && x
<= seg
->at(high
).x(_type
)))
129 while (low
<= high
) {
130 mid
= (high
+ low
) / 2;
131 const GraphPoint
&p
= seg
->at(mid
);
134 else if (p
.x(_type
) < x
)
141 if (seg
->at(mid
).x(_type
) < x
)
142 l
= QLineF(seg
->at(mid
).x(_type
), seg
->at(mid
).y(),
143 seg
->at(mid
+1).x(_type
), seg
->at(mid
+1).y());
145 l
= QLineF(seg
->at(mid
-1).x(_type
), seg
->at(mid
-1).y(),
146 seg
->at(mid
).x(_type
), seg
->at(mid
).y());
148 return l
.pointAt((x
- l
.p1().x()) / (l
.p2().x() - l
.p1().x())).y();
151 qreal
GraphItem::distanceAtTime(qreal time
) const
156 const GraphSegment
*seg
= segment(time
, Time
);
161 int high
= seg
->count() - 1;
164 if (!(time
>= seg
->at(low
).t() && time
<= seg
->at(high
).t()))
167 while (low
<= high
) {
168 mid
= (high
+ low
) / 2;
169 const GraphPoint
&p
= seg
->at(mid
);
172 else if (p
.t() < time
)
175 return seg
->at(mid
).s();
179 if (seg
->at(mid
).t() < time
)
180 l
= QLineF(seg
->at(mid
).t(), seg
->at(mid
).s(), seg
->at(mid
+1).t(),
183 l
= QLineF(seg
->at(mid
-1).t(), seg
->at(mid
-1).s(),
184 seg
->at(mid
).t(), seg
->at(mid
).s());
186 return l
.pointAt((time
- l
.p1().x()) / (l
.p2().x() - l
.p1().x())).y();
189 qreal
GraphItem::timeAtDistance(qreal distance
) const
194 const GraphSegment
*seg
= segment(distance
, Distance
);
199 int high
= seg
->count() - 1;
202 if (!(distance
>= seg
->at(low
).s() && distance
<= seg
->at(high
).s()))
205 while (low
<= high
) {
206 mid
= (high
+ low
) / 2;
207 const GraphPoint
&p
= seg
->at(mid
);
208 if (p
.s() > distance
)
210 else if (p
.s() < distance
)
213 return seg
->at(mid
).t();
217 if (seg
->at(mid
).s() < distance
)
218 l
= QLineF(seg
->at(mid
).s(), seg
->at(mid
).t(), seg
->at(mid
+1).s(),
221 l
= QLineF(seg
->at(mid
-1).s(), seg
->at(mid
-1).t(),
222 seg
->at(mid
).s(), seg
->at(mid
).t());
224 return l
.pointAt((distance
- l
.p1().x()) / (l
.p2().x() - l
.p1().x())).y();
227 GraphItem::SegmentTime
GraphItem::date(qreal x
)
229 const GraphSegment
*seg
= segment(x
, _type
);
230 return seg
? SegmentTime(seg
->start(), seg
->first().t()) : SegmentTime();
233 void GraphItem::hover(bool hover
)
236 _pen
.setWidth(_pen
.width() + 1);
237 setZValue(zValue() + 1.0);
239 _pen
.setWidth(_pen
.width() - 1);
240 setZValue(zValue() - 1.0);
246 void GraphItem::setScale(qreal sx
, qreal sy
)
248 if (_sx
== sx
&& _sy
== sy
)
251 prepareGeometryChange();
257 void GraphItem::updatePath()
259 if (_sx
== 0 && _sy
== 0)
262 prepareGeometryChange();
264 _path
= QPainterPath();
266 if (!(_type
== Time
&& !_time
)) {
267 for (int i
= 0; i
< _graph
.size(); i
++) {
268 const GraphSegment
&segment
= _graph
.at(i
);
270 _path
.moveTo(segment
.first().x(_type
) * _sx
, -segment
.first().y()
272 for (int i
= 1; i
< segment
.size(); i
++)
273 _path
.lineTo(segment
.at(i
).x(_type
) * _sx
, -segment
.at(i
).y()
281 void GraphItem::updateBounds()
283 if (_type
== Time
&& !_time
) {
288 qreal bottom
, top
, left
, right
;
290 QPointF p
= QPointF(_graph
.first().first().x(_type
),
291 -_graph
.first().first().y());
292 bottom
= p
.y(); top
= p
.y(); left
= p
.x(); right
= p
.x();
294 for (int i
= 0; i
< _graph
.size(); i
++) {
295 const GraphSegment
&segment
= _graph
.at(i
);
297 for (int j
= 0; j
< segment
.size(); j
++) {
298 p
= QPointF(segment
.at(j
).x(_type
), -segment
.at(j
).y());
299 bottom
= qMax(bottom
, p
.y()); top
= qMin(top
, p
.y());
300 right
= qMax(right
, p
.x()); left
= qMin(left
, p
.x());
307 _bounds
= QRectF(QPointF(left
, top
), QPointF(right
, bottom
));
310 qreal
GraphItem::max() const
312 qreal ret
= _graph
.first().first().y();
314 for (int i
= 0; i
< _graph
.size(); i
++) {
315 const GraphSegment
&segment
= _graph
.at(i
);
317 for (int j
= 0; j
< segment
.size(); j
++) {
318 qreal y
= segment
.at(j
).y();
327 qreal
GraphItem::min() const
329 qreal ret
= _graph
.first().first().y();
331 for (int i
= 0; i
< _graph
.size(); i
++) {
332 const GraphSegment
&segment
= _graph
.at(i
);
334 for (int j
= 0; j
< segment
.size(); j
++) {
335 qreal y
= segment
.at(j
).y();
344 qreal
GraphItem::avg() const
348 for (int i
= 0; i
< _graph
.size(); i
++) {
349 const GraphSegment
&segment
= _graph
.at(i
);
351 for (int j
= 1; j
< segment
.size(); j
++)
352 sum
+= segment
.at(j
).y() * (segment
.at(j
).s() - segment
.at(j
-1).s());
355 return sum
/_graph
.last().last().s();
358 void GraphItem::hoverEnterEvent(QGraphicsSceneHoverEvent
*event
)
362 _pen
.setWidth(_pen
.width() + 1);
363 setZValue(zValue() + 1.0);
369 void GraphItem::hoverLeaveEvent(QGraphicsSceneHoverEvent
*event
)
373 _pen
.setWidth(_pen
.width() - 1);
374 setZValue(zValue() - 1.0);
377 emit
selected(false);
380 void GraphItem::mousePressEvent(QGraphicsSceneMouseEvent
*event
)
382 Popup::show(event
->screenPos(), info(), event
->widget());
383 GraphicsItem::mousePressEvent(event
);