##// END OF EJS Templates
Kinetic scrolling is back for legend
sauimone -
r2189:4cb139890ac2
parent child
Show More
@@ -1,199 +1,197
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include <QPainter>
22 22 #include <QGraphicsSceneEvent>
23 23 #include <QGraphicsSimpleTextItem>
24 24 #include <QDebug>
25 25
26 26 #include "qlegend.h"
27 27 #include "qlegend_p.h"
28 28 #include "qlegendmarker.h"
29 29 #include "qlegendmarker_p.h"
30 30 #include "legendmarkeritem_p.h"
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 LegendMarkerItem::LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent) :
35 35 QGraphicsObject(parent),
36 36 m_marker(marker),
37 37 m_markerRect(0,0,10.0,10.0),
38 38 m_boundingRect(0,0,0,0),
39 39 m_textItem(new QGraphicsSimpleTextItem(this)),
40 40 m_rectItem(new QGraphicsRectItem(this)),
41 41 m_margin(4),
42 m_space(4)
42 m_space(4),
43 m_pressPos(0, 0)
43 44 {
44 45 m_rectItem->setRect(m_markerRect);
45 46 }
46 47
47 48 void LegendMarkerItem::setPen(const QPen &pen)
48 49 {
49 50 m_rectItem->setPen(pen);
50 51 }
51 52
52 53 QPen LegendMarkerItem::pen() const
53 54 {
54 55 return m_rectItem->pen();
55 56 }
56 57
57 58 void LegendMarkerItem::setBrush(const QBrush &brush)
58 59 {
59 60 m_rectItem->setBrush(brush);
60 61 }
61 62
62 63 QBrush LegendMarkerItem::brush() const
63 64 {
64 65 return m_rectItem->brush();
65 66 }
66 67
67 68 void LegendMarkerItem::setFont(const QFont &font)
68 69 {
69 70 m_textItem->setFont(font);
70 71 QFontMetrics fn(font);
71 72 m_markerRect = QRectF(0,0,fn.height()/2,fn.height()/2);
72 73 updateGeometry();
73 74 }
74 75
75 76 QFont LegendMarkerItem::font() const
76 77 {
77 78 return m_textItem->font();
78 79 }
79 80
80 81 void LegendMarkerItem::setLabel(const QString label)
81 82 {
82 83 m_label = label;
83 84 updateGeometry();
84 85 }
85 86
86 87 QString LegendMarkerItem::label() const
87 88 {
88 89 return m_label;
89 90 }
90 91
91 92 void LegendMarkerItem::setLabelBrush(const QBrush &brush)
92 93 {
93 94 m_textItem->setBrush(brush);
94 95 }
95 96
96 97 QBrush LegendMarkerItem::labelBrush() const
97 98 {
98 99 return m_textItem->brush();
99 100 }
100 101
101 102 void LegendMarkerItem::setGeometry(const QRectF& rect)
102 103 {
103 104 QFontMetrics fn (m_font);
104 105
105 106 int width = rect.width();
106 107 qreal x = m_margin + m_markerRect.width() + m_space + m_margin;
107 108 qreal y = qMax(m_markerRect.height()+2*m_margin,fn.height()+2*m_margin);
108 109
109 110 if (fn.boundingRect(m_label).width() + x > width)
110 111 {
111 112 QString string = m_label + "...";
112 113 while(fn.boundingRect(string).width() + x > width && string.length() > 3)
113 114 string.remove(string.length() - 4, 1);
114 115 m_textItem->setText(string);
115 116 }
116 117 else
117 118 m_textItem->setText(m_label);
118 119
119 120 const QRectF& textRect = m_textItem->boundingRect();
120 121
121 122
122 123 m_textItem->setPos(x-m_margin,y/2 - textRect.height()/2);
123 124 m_rectItem->setRect(m_markerRect);
124 125 m_rectItem->setPos(m_margin,y/2 - m_markerRect.height()/2);
125 126
126 127 prepareGeometryChange();
127 128 m_boundingRect = QRectF(0,0,x+textRect.width()+m_margin,y);
128 129 }
129 130
130 131 QRectF LegendMarkerItem::boundingRect() const
131 132 {
132 133 return m_boundingRect;
133 134 }
134 135
135 136 void LegendMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
136 137 {
137 138 Q_UNUSED(option)
138 139 Q_UNUSED(widget)
139 140 Q_UNUSED(painter)
140 141 }
141 142
142 143 QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
143 144 {
144 145 Q_UNUSED(constraint)
145 146
146 147 QFontMetrics fn(m_textItem->font());
147 148 QSizeF sh;
148 149
149 150 switch (which) {
150 151 case Qt::MinimumSize:
151 152 sh = QSizeF(fn.boundingRect("...").width() + 2*m_margin + m_space +m_markerRect.width(),qMax(m_markerRect.height()+2*m_margin,fn.height()+2*m_margin));
152 153 break;
153 154 case Qt::PreferredSize:
154 155 sh = QSizeF(fn.boundingRect(m_label).width() + 2*m_margin + m_space +m_markerRect.width(),qMax(m_markerRect.height()+2*m_margin,fn.height()+2*m_margin));
155 156 break;
156 157 default:
157 158 break;
158 159 }
159 160
160 161 return sh;
161 162 }
162 163
163 164 void LegendMarkerItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
164 165 {
165 166 MouseEventHandler::handleMousePressEvent(event);
167 m_pressPos = event->screenPos();
166 168 }
167 169
168 170 void LegendMarkerItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
169 171 {
170 172 MouseEventHandler::handleMouseMoveEvent(event);
171 173 }
172 174
173 175 void LegendMarkerItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
174 176 {
175 177 MouseEventHandler::handleMouseReleaseEvent(event);
176 178 }
177 179
178 180 void LegendMarkerItem::mouseClicked()
179 181 {
180 182 emit m_marker->q_func()->clicked();
181 183 }
182 184
183 void LegendMarkerItem::mouseMoved(QPointF delta)
185 void LegendMarkerItem::mouseMoved(const QPointF &delta)
184 186 {
185 qreal dx = m_marker->m_legend->d_ptr->offset().x() - delta.x();
186 qreal dy = m_marker->m_legend->d_ptr->offset().y() - delta.y();
187 m_marker->m_legend->d_ptr->setOffset(dx, dy);
187 m_marker->m_legend->d_ptr->move(delta);
188 188 }
189 189
190 void LegendMarkerItem::mouseReleased(QPointF delta)
190 void LegendMarkerItem::mouseReleased(const QPointF &pos)
191 191 {
192 qreal dx = m_marker->m_legend->d_ptr->offset().x() - delta.x();
193 qreal dy = m_marker->m_legend->d_ptr->offset().y() - delta.y();
194 m_marker->m_legend->d_ptr->setOffset(dx, dy);
192 m_marker->m_legend->d_ptr->release(pos - m_pressPos);
195 193 }
196 194
197 195 #include "moc_legendmarkeritem_p.cpp"
198 196
199 197 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,110 +1,112
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef LEGENDMARKERITEM_P_H
31 31 #define LEGENDMARKERITEM_P_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include <QGraphicsObject>
35 35 #include <QFont>
36 36 #include <QBrush>
37 37 #include <QPen>
38 38 #include <QGraphicsSimpleTextItem>
39 39 #include <QGraphicsLayoutItem>
40 40 #include "mouseeventhandler_p.h"
41 41
42 42 QTCOMMERCIALCHART_BEGIN_NAMESPACE
43 43
44 44 class QLegendMarkerPrivate;
45 45
46 46 class LegendMarkerItem : public QGraphicsObject, public QGraphicsLayoutItem, public MouseEventHandler
47 47 {
48 48 Q_OBJECT
49 49 Q_INTERFACES(QGraphicsLayoutItem)
50 50 public:
51 51 explicit LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent = 0);
52 52
53 53 void setPen(const QPen &pen);
54 54 QPen pen() const;
55 55
56 56 void setBrush(const QBrush &brush);
57 57 QBrush brush() const;
58 58
59 59 void setFont(const QFont &font);
60 60 QFont font() const;
61 61
62 62 void setLabel(const QString label);
63 63 QString label() const;
64 64
65 65 void setLabelBrush(const QBrush &brush);
66 66 QBrush labelBrush() const;
67 67
68 68 void setGeometry(const QRectF& rect);
69 69
70 70 QRectF boundingRect() const;
71 71
72 72 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
73 73
74 74 QSizeF sizeHint (Qt::SizeHint which, const QSizeF& constraint) const;
75 75
76 76 // Event handlers, logic delegated to MouseEventHandler
77 77 void mousePressEvent(QGraphicsSceneMouseEvent *event);
78 78 void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
79 79 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
80 80
81 81 // Filtered callbacks from MouseEventHandler
82 82 void mouseClicked();
83 void mouseMoved(QPointF delta);
84 void mouseReleased(QPointF delta);
83 void mouseMoved(const QPointF &delta);
84 void mouseReleased(const QPointF &pos);
85 85
86 86 protected:
87 87 QLegendMarkerPrivate *m_marker; // Knows
88 88 QRectF m_markerRect;
89 89 QRectF m_boundingRect;
90 90 QGraphicsSimpleTextItem *m_textItem;
91 91 QGraphicsRectItem *m_rectItem;
92 92 qreal m_margin;
93 93 qreal m_space;
94 94 QString m_label;
95 95
96 96 QBrush m_labelBrush;
97 97 QFont m_font;
98 98 QPen m_pen;
99 99 QBrush m_brush;
100 100 bool m_visible;
101 101
102 QPointF m_pressPos;
103
102 104 friend class QLegendMarker;
103 105 friend class QLegendMarkerPrivate;
104 106 friend class LegendMarkerItem;
105 107 friend class LegendLayout;
106 108 };
107 109
108 110 QTCOMMERCIALCHART_END_NAMESPACE
109 111
110 112 #endif // LEGENDMARKERITEM_P_H
@@ -1,59 +1,52
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30
31 31 #ifndef LEGENDSCROLLER_P_H
32 32 #define LEGENDSCROLLER_P_H
33 33
34 34 #include "qlegend.h"
35 35 #include "qlegend_p.h"
36 #include "scroller_p.h"
37 36
38 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 38
40 class LegendScroller: public QLegend, public Scroller
39 class LegendScroller: public QLegend
41 40 {
42 41
43 42 public:
44 43 LegendScroller(QChart *chart): QLegend(chart) { }
45 44
46 void setOffset(const QPointF &point) { d_ptr->setOffset(point.x(), point.y()); }
45 void setOffset(const QPointF &point) { d_ptr->setOffset(point); }
47 46
48 47 QPointF offset() const { return d_ptr->offset(); }
49
50 void mousePressEvent(QGraphicsSceneMouseEvent *event) { Scroller::mousePressEvent(event); }
51
52 void mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Scroller::mouseMoveEvent(event); }
53
54 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Scroller::mouseReleaseEvent(event); }
55 48 };
56 49
57 50 QTCOMMERCIALCHART_END_NAMESPACE
58 51
59 52 #endif
@@ -1,107 +1,106
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "mouseeventhandler_p.h"
22 22 #include <QGraphicsSceneMouseEvent>
23 23
24 24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 25
26 26 MouseEventHandler::MouseEventHandler() :
27 m_lastPos(0,0),
27 m_lastPos(0, 0),
28 28 m_state(Idle),
29 29 m_treshold(10)
30 30 {
31 31 }
32 32
33 33 MouseEventHandler::~MouseEventHandler()
34 34 {
35 35 }
36 36
37 37 void MouseEventHandler::setMoveTreshold(qreal treshold)
38 38 {
39 39 m_treshold = treshold;
40 40 }
41 41
42 42 void MouseEventHandler::handleMousePressEvent(QGraphicsSceneMouseEvent* event)
43 43 {
44 44 m_lastPos = event->screenPos();
45 45 m_state = Pressed;
46 46 event->accept();
47 47 }
48 48
49 49 void MouseEventHandler::handleMouseMoveEvent(QGraphicsSceneMouseEvent* event)
50 50 {
51 51 QPointF delta = event->screenPos() - m_lastPos;
52 52
53 53 switch (m_state) {
54 54 case Pressed: {
55 55 // calculate treshold. If enough, change to move state and send out move deltas.
56 56 if (qAbs(delta.x()) > m_treshold || qAbs(delta.y()) > m_treshold) {
57 57 m_state = Moved;
58 58 m_lastPos = event->screenPos();
59 59 mouseMoved(delta);
60 60 }
61 61 event->accept();
62 62 break;
63 63 }
64 64 case Moved: {
65 65 m_lastPos = event->screenPos();
66 66 mouseMoved(delta);
67 67 event->accept();
68 68 break;
69 69 }
70 70 case Idle:
71 71 default: {
72 72 event->ignore();
73 73 break;
74 74 }
75 75 }
76 76 }
77 77
78 78 void MouseEventHandler::handleMouseReleaseEvent(QGraphicsSceneMouseEvent* event)
79 79 {
80 QPointF delta = event->screenPos() - m_lastPos;
81 80 m_lastPos = event->screenPos();
82 81
83 82 switch (m_state) {
84 83 case Pressed:
85 84 {
86 85 m_state = Idle;
87 86 mouseClicked();
88 87 event->accept();
89 88 break;
90 89 }
91 90 case Moved:
92 91 {
93 92 m_state = Idle;
94 mouseReleased(delta);
93 mouseReleased(m_lastPos);
95 94 event->accept();
96 95 break;
97 96 }
98 97 default:
99 98 {
100 99 m_state = Idle;
101 100 event->ignore();
102 101 break;
103 102 }
104 103 }
105 104 }
106 105
107 106 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,89 +1,89
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 /*
31 31 Purpose of this class is to resolve what happens during MousePress - MouseMove - MouseRelease event chain.
32 32 Threre can be many MouseMove events and if they all are below our treshold, the result is clicked call.
33 33 If any move event goes over treshold, result will be many moved(QPointF delta) calls,
34 34 where delta is calculated from original position.
35 35
36 36 Reason for this is, that legend marker don't know when it should emit clicked and when it should
37 37 allow legend to scroll. We only get this information when some move goes beyond treshold, but
38 38 then it will be too late to let the scroller handle events, because marker is already handling.
39 39
40 40 By handling clicked calls in markers and moved calls in scroller, the problem is solved.
41 41 Derived class descides, should the virtual method be implemented as signal or not.
42 42
43 43 This could be implemented in LegendMarkerItem, but this way the code is reusable and in one place only.
44 44 */
45 45
46 46 #ifndef MOUSEEVENTHANDLER_H
47 47 #define MOUSEEVENTHANDLER_H
48 48
49 49 #include "qchartglobal.h"
50 50 #include <QBasicTimer>
51 51 #include <QTime>
52 52 #include <QPointF>
53 53
54 54 class QGraphicsSceneMouseEvent;
55 55
56 56 QTCOMMERCIALCHART_BEGIN_NAMESPACE
57 57
58 58 class MouseEventHandler
59 59 {
60 60 public:
61 61 enum State {
62 62 Idle,
63 63 Pressed,
64 64 Moved,
65 65 Released
66 66 };
67 67
68 68 MouseEventHandler();
69 69 virtual ~MouseEventHandler();
70 70
71 71 void setMoveTreshold(qreal treshold);
72 72
73 73 virtual void mouseClicked() = 0;
74 virtual void mouseMoved(QPointF delta) = 0;
75 virtual void mouseReleased(QPointF delta) = 0;
74 virtual void mouseMoved(const QPointF &delta) = 0;
75 virtual void mouseReleased(const QPointF &pos) = 0;
76 76
77 77 void handleMousePressEvent(QGraphicsSceneMouseEvent* event);
78 78 void handleMouseMoveEvent(QGraphicsSceneMouseEvent* event);
79 79 void handleMouseReleaseEvent(QGraphicsSceneMouseEvent* event);
80 80
81 81 private:
82 82 QPointF m_lastPos;
83 83 State m_state;
84 84 qreal m_treshold;
85 85 };
86 86
87 87 QTCOMMERCIALCHART_END_NAMESPACE
88 88
89 89 #endif // MOUSEEVENTHANDLER_H
@@ -1,669 +1,669
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qlegend.h"
22 22 #include "qlegend_p.h"
23 23 #include "qabstractseries.h"
24 24 #include "qabstractseries_p.h"
25 25 #include "qchart_p.h"
26 26 #include "legendlayout_p.h"
27 27 #include "qxyseries.h"
28 28 #include "qlineseries.h"
29 29 #include "qareaseries.h"
30 30 #include "qscatterseries.h"
31 31 #include "qsplineseries.h"
32 32 #include "qabstractbarseries.h"
33 33 #include "qstackedbarseries.h"
34 34 #include "qpercentbarseries.h"
35 35 #include "qbarset.h"
36 36 #include "qpieseries.h"
37 37 #include "qpieseries_p.h"
38 38 #include "qpieslice.h"
39 39 #include "chartpresenter_p.h"
40 40 #include "chartlayout_p.h"
41 41 #include <QPainter>
42 42 #include <QPen>
43 43 #include <QTimer>
44 44 #include <QGraphicsSceneEvent>
45 45 #include <QGraphicsItemGroup>
46 46
47 47 #include "qlegendmarker.h"
48 48 #include "qlegendmarker_p.h"
49 49 #include "legendmarkeritem_p.h"
50 50
51 51 QTCOMMERCIALCHART_BEGIN_NAMESPACE
52 52
53 53 /*!
54 54 \class QLegend
55 55 \brief Legend object
56 56 \mainclass
57 57
58 58 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
59 59 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
60 60 handle the drawing manually.
61 61 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
62 62
63 63 \image examples_percentbarchart_legend.png
64 64
65 65 \sa QChart
66 66 */
67 67 /*!
68 68 \qmlclass Legend QLegend
69 69 \brief Legend is part of QtCommercial Chart QML API.
70 70
71 71 Legend is a graphical object, whics displays legend of the chart. Legend state is updated by ChartView, when
72 72 series have been changed. Legend is used via ChartView class. For example:
73 73 \code
74 74 ChartView {
75 75 legend.visible: true
76 76 legend.alignment: Qt.AlignBottom
77 77 // Add a few series...
78 78 }
79 79 \endcode
80 80
81 81 \image examples_percentbarchart_legend.png
82 82 */
83 83
84 84 /*!
85 85 \property QLegend::alignment
86 86 \brief The alignment of the legend.
87 87
88 88 Legend paints on the defined position in the chart. The following alignments are supported:
89 89 Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result is undefined.
90 90 */
91 91 /*!
92 92 \qmlproperty Qt.Alignment Legend::alignment
93 93 \brief The alignment of the legend.
94 94
95 95 Legend paints on the defined position in the chart. The following alignments are supported:
96 96 Qt.AlignTop, Qt.AlignBottom, Qt.AlignLeft, Qt.AlignRight. If you set more than one flag the result is undefined.
97 97 */
98 98
99 99 /*!
100 100 \property QLegend::backgroundVisible
101 101 Whether the legend background is visible or not.
102 102 */
103 103 /*!
104 104 \qmlproperty bool Legend::backgroundVisible
105 105 Whether the legend background is visible or not.
106 106 */
107 107
108 108 /*!
109 109 \property QLegend::color
110 110 The color of the legend, i.e. the background (brush) color. Note that if you change the color
111 111 of the legend, the style of the legend brush is set to Qt::SolidPattern.
112 112 */
113 113 /*!
114 114 \qmlproperty color Legend::color
115 115 The color of the legend, i.e. the background (brush) color.
116 116 */
117 117
118 118 /*!
119 119 \property QLegend::borderColor
120 120 The border color of the legend, i.e. the line color.
121 121 */
122 122 /*!
123 123 \qmlproperty color Legend::borderColor
124 124 The border color of the legend, i.e. the line color.
125 125 */
126 126
127 127 /*!
128 128 \property QLegend::font
129 129 The font of markers used by legend
130 130 */
131 131 /*!
132 132 \qmlproperty Font Legend::font
133 133 The font of markers used by legend
134 134 */
135 135
136 136 /*!
137 137 \property QLegend::labelColor
138 138 The color of brush used to draw labels.
139 139 */
140 140 /*!
141 141 \qmlproperty color QLegend::labelColor
142 142 The color of brush used to draw labels.
143 143 */
144 144
145 145 /*!
146 146 \fn void QLegend::backgroundVisibleChanged(bool)
147 147 The visibility of the legend background changed to \a visible.
148 148 */
149 149
150 150 /*!
151 151 \fn void QLegend::colorChanged(QColor)
152 152 The color of the legend background changed to \a color.
153 153 */
154 154
155 155 /*!
156 156 \fn void QLegend::borderColorChanged(QColor)
157 157 The border color of the legend background changed to \a color.
158 158 */
159 159
160 160 /*!
161 161 \fn void QLegend::fontChanged(QFont)
162 162 The font of markers of the legend changed to \a font.
163 163 */
164 164
165 165 /*!
166 166 \fn void QLegend::labelColorChanged(QColor color)
167 167 This signal is emitted when the color of brush used to draw labels has changed to \a color.
168 168 */
169 169
170 170 /*!
171 171 Constructs the legend object and sets the parent to \a parent
172 172 */
173 173
174 174 QLegend::QLegend(QChart *chart): QGraphicsWidget(chart),
175 175 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter, chart, this))
176 176 {
177 177 setZValue(ChartPresenter::LegendZValue);
178 178 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
179 179 QObject::connect(chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*,Domain*)), d_ptr.data(), SLOT(handleSeriesAdded(QAbstractSeries*)));
180 180 QObject::connect(chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), d_ptr.data(), SLOT(handleSeriesRemoved(QAbstractSeries*)));
181 181 // QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleCountChanged(QAbstractSeries*)));
182 182 setLayout(d_ptr->m_layout);
183 183 }
184 184
185 185 /*!
186 186 Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
187 187 */
188 188 QLegend::~QLegend()
189 189 {
190 190 }
191 191
192 192 /*!
193 193 \internal
194 194 */
195 195 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
196 196 {
197 197 Q_UNUSED(option)
198 198 Q_UNUSED(widget)
199 199
200 200 if (!d_ptr->m_backgroundVisible)
201 201 return;
202 202
203 203 painter->setOpacity(opacity());
204 204 painter->setPen(d_ptr->m_pen);
205 205 painter->setBrush(d_ptr->m_brush);
206 206 painter->drawRoundRect(rect(), d_ptr->roundness(rect().width()), d_ptr->roundness(rect().height()));
207 207 }
208 208
209 209
210 210 /*!
211 211 Sets the \a brush of legend. Brush affects the background of legend.
212 212 */
213 213 void QLegend::setBrush(const QBrush &brush)
214 214 {
215 215 if (d_ptr->m_brush != brush) {
216 216 d_ptr->m_brush = brush;
217 217 update();
218 218 emit colorChanged(brush.color());
219 219 }
220 220 }
221 221
222 222 /*!
223 223 Returns the brush used by legend.
224 224 */
225 225 QBrush QLegend::brush() const
226 226 {
227 227 return d_ptr->m_brush;
228 228 }
229 229
230 230 void QLegend::setColor(QColor color)
231 231 {
232 232 QBrush b = d_ptr->m_brush;
233 233 if (b.style() != Qt::SolidPattern || b.color() != color) {
234 234 b.setStyle(Qt::SolidPattern);
235 235 b.setColor(color);
236 236 setBrush(b);
237 237 }
238 238 }
239 239
240 240 QColor QLegend::color()
241 241 {
242 242 return d_ptr->m_brush.color();
243 243 }
244 244
245 245 /*!
246 246 Sets the \a pen of legend. Pen affects the legend borders.
247 247 */
248 248 void QLegend::setPen(const QPen &pen)
249 249 {
250 250 if (d_ptr->m_pen != pen) {
251 251 d_ptr->m_pen = pen;
252 252 update();
253 253 emit borderColorChanged(pen.color());
254 254 }
255 255 }
256 256
257 257 /*!
258 258 Returns the pen used by legend
259 259 */
260 260
261 261 QPen QLegend::pen() const
262 262 {
263 263 return d_ptr->m_pen;
264 264 }
265 265
266 266 void QLegend::setFont(const QFont &font)
267 267 {
268 268 if (d_ptr->m_font != font)
269 269 d_ptr->m_font = font;
270 270
271 271 foreach (QLegendMarker *marker, d_ptr->markers()) {
272 272 marker->setFont(d_ptr->m_font);
273 273 }
274 274 layout()->invalidate();
275 275 emit fontChanged(font);
276 276 }
277 277
278 278 QFont QLegend::font() const
279 279 {
280 280 return d_ptr->m_font;
281 281 }
282 282
283 283 void QLegend::setBorderColor(QColor color)
284 284 {
285 285 QPen p = d_ptr->m_pen;
286 286 if (p.color() != color) {
287 287 p.setColor(color);
288 288 setPen(p);
289 289 }
290 290 }
291 291
292 292 QColor QLegend::borderColor()
293 293 {
294 294 return d_ptr->m_pen.color();
295 295 }
296 296
297 297 /*!
298 298 Set brush used to draw labels to \a brush.
299 299 */
300 300 void QLegend::setLabelBrush(const QBrush &brush)
301 301 {
302 302 if (d_ptr->m_labelBrush != brush) {
303 303 d_ptr->m_labelBrush = brush;
304 304 foreach (QLegendMarker *marker, d_ptr->markers()) {
305 305 marker->setLabelBrush(d_ptr->m_labelBrush);
306 306 // Note: The pen of the marker rectangle could be exposed in the public QLegend API
307 307 // instead of mapping it from label brush color
308 308 marker->setPen(brush.color());
309 309 }
310 310 emit labelColorChanged(brush.color());
311 311 }
312 312 }
313 313
314 314 /*!
315 315 Brush used to draw labels.
316 316 */
317 317 QBrush QLegend::labelBrush() const
318 318 {
319 319 return d_ptr->m_labelBrush;
320 320 }
321 321
322 322 void QLegend::setLabelColor(QColor color)
323 323 {
324 324 QBrush b = d_ptr->m_labelBrush;
325 325 if (b.style() != Qt::SolidPattern || b.color() != color) {
326 326 b.setStyle(Qt::SolidPattern);
327 327 b.setColor(color);
328 328 setLabelBrush(b);
329 329 }
330 330 }
331 331
332 332 QColor QLegend::labelColor() const
333 333 {
334 334 return d_ptr->m_labelBrush.color();
335 335 }
336 336
337 337
338 338 void QLegend::setAlignment(Qt::Alignment alignment)
339 339 {
340 340 if (d_ptr->m_alignment != alignment) {
341 341 d_ptr->m_alignment = alignment;
342 342 layout()->invalidate();
343 343 }
344 344 }
345 345
346 346 Qt::Alignment QLegend::alignment() const
347 347 {
348 348 return d_ptr->m_alignment;
349 349 }
350 350
351 351 /*!
352 352 Detaches the legend from chart. Chart won't change layout of the legend.
353 353 */
354 354 void QLegend::detachFromChart()
355 355 {
356 356 d_ptr->m_attachedToChart = false;
357 357 layout()->invalidate();
358 358 setParent(0);
359 359
360 360 }
361 361
362 362 /*!
363 363 Attaches the legend to chart. Chart may change layout of the legend.
364 364 */
365 365 void QLegend::attachToChart()
366 366 {
367 367 d_ptr->m_attachedToChart = true;
368 368 layout()->invalidate();
369 369 setParent(d_ptr->m_chart);
370 370 }
371 371
372 372 /*!
373 373 Returns true, if legend is attached to chart.
374 374 */
375 375 bool QLegend::isAttachedToChart()
376 376 {
377 377 return d_ptr->m_attachedToChart;
378 378 }
379 379
380 380 /*!
381 381 Sets the visibility of legend background to \a visible
382 382 */
383 383 void QLegend::setBackgroundVisible(bool visible)
384 384 {
385 385 if (d_ptr->m_backgroundVisible != visible) {
386 386 d_ptr->m_backgroundVisible = visible;
387 387 update();
388 388 emit backgroundVisibleChanged(visible);
389 389 }
390 390 }
391 391
392 392 /*!
393 393 Returns the visibility of legend background
394 394 */
395 395 bool QLegend::isBackgroundVisible() const
396 396 {
397 397 return d_ptr->m_backgroundVisible;
398 398 }
399 399
400 400 QList<QLegendMarker*> QLegend::markers() const
401 401 {
402 402 return d_ptr->markers();
403 403 }
404 404
405 405 void QLegend::addSeries(QAbstractSeries* series)
406 406 {
407 407 d_ptr->addSeries(series);
408 408 }
409 409
410 410 void QLegend::removeSeries(QAbstractSeries* series)
411 411 {
412 412 d_ptr->removeSeries(series);
413 413 }
414 414
415 415 /*!
416 416 \internal \a event see QGraphicsWidget for details
417 417 */
418 418 void QLegend::hideEvent(QHideEvent *event)
419 419 {
420 420 if (isAttachedToChart())
421 421 d_ptr->m_presenter->layout()->invalidate();
422 422 QGraphicsWidget::hideEvent(event);
423 423 }
424 424 /*!
425 425 \internal \a event see QGraphicsWidget for details
426 426 */
427 427 void QLegend::showEvent(QShowEvent *event)
428 428 {
429 429 if (isAttachedToChart()) {
430 430 d_ptr->items()->setVisible(false);
431 431 layout()->invalidate();
432 432 }
433 433 QGraphicsWidget::showEvent(event);
434 434 //layout activation will show the items
435 435 }
436 436
437 437 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
438 438
439 439 QLegendPrivate::QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q)
440 440 : q_ptr(q),
441 441 m_presenter(presenter),
442 442 m_layout(new LegendLayout(q)),
443 443 m_chart(chart),
444 444 m_items(new QGraphicsItemGroup(q)),
445 445 m_alignment(Qt::AlignTop),
446 446 m_brush(QBrush()),
447 447 m_pen(QPen()),
448 448 m_labelBrush(QBrush()),
449 449 m_diameter(5),
450 450 m_attachedToChart(true),
451 451 m_backgroundVisible(false)
452 452 {
453 453 m_items->setHandlesChildEvents(false);
454 454 }
455 455
456 456 QLegendPrivate::~QLegendPrivate()
457 457 {
458 458
459 459 }
460 460
461 void QLegendPrivate::setOffset(qreal x, qreal y)
461 void QLegendPrivate::setOffset(const QPointF &offset)
462 462 {
463 m_layout->setOffset(x, y);
463 m_layout->setOffset(offset.x(), offset.y());
464 464 }
465 465
466 466 QPointF QLegendPrivate::offset() const
467 467 {
468 468 return m_layout->offset();
469 469 }
470 470
471 471 int QLegendPrivate::roundness(qreal size)
472 472 {
473 473 return 100 * m_diameter / int(size);
474 474 }
475 475
476 476 void QLegendPrivate::addSeries(QAbstractSeries* series)
477 477 {
478 478 // Only allow one instance of series
479 479 if (m_series.contains(series)) {
480 480 qDebug() << "series already added" << series;
481 481 return;
482 482 }
483 483
484 484 QList<QLegendMarker*> newMarkers = series->d_ptr->createLegendMarkers(q_ptr);
485 485 decorateMarkers(newMarkers);
486 486 addMarkers(newMarkers);
487 487
488 488 // TODO: This is the part I don't like. There should be better solution.
489 489 // On the other hand. It is only one switch case for appending and another for removing series
490 490 // If countChanged signal were on QAbstractSeries, there would be no need for switch at all.
491 491 switch (series->type())
492 492 {
493 493 case QAbstractSeries::SeriesTypePie: {
494 494 QPieSeries *s = qobject_cast<QPieSeries *> (series);
495 495 QObject::connect(s, SIGNAL(countChanged()), this, SLOT(handleCountChanged()));
496 496 break;
497 497 }
498 498 case QAbstractSeries::SeriesTypeBar:
499 499 case QAbstractSeries::SeriesTypeStackedBar:
500 500 case QAbstractSeries::SeriesTypePercentBar:
501 501 case QAbstractSeries::SeriesTypeHorizontalBar:
502 502 case QAbstractSeries::SeriesTypeHorizontalStackedBar:
503 503 case QAbstractSeries::SeriesTypeHorizontalPercentBar: {
504 504 QAbstractBarSeries *s = qobject_cast<QAbstractBarSeries *> (series);
505 505 QObject::connect(s, SIGNAL(countChanged()), this, SLOT(handleCountChanged()));
506 506 break;
507 507 }
508 508 case QAbstractSeries::SeriesTypeLine:
509 509 case QAbstractSeries::SeriesTypeArea:
510 510 case QAbstractSeries::SeriesTypeScatter:
511 511 case QAbstractSeries::SeriesTypeSpline:
512 512 default: {
513 513 // No need to connect any series related signals. We have no series level
514 514 // changes, that would generate or delete markers
515 515 }
516 516 }
517 517
518 518 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
519 519
520 520 m_series.append(series);
521 521 m_items->setVisible(false);
522 522 m_layout->invalidate();
523 523 }
524 524
525 525 void QLegendPrivate::removeSeries(QAbstractSeries* series)
526 526 {
527 527 if (m_series.contains(series)) {
528 528 m_series.removeOne(series);
529 529 }
530 530
531 531 // Find out, which markers to remove
532 532 QList<QLegendMarker *> removed;
533 533 foreach (QLegendMarker *m, m_markers) {
534 534 if (m->series() == series) {
535 535 removed << m;
536 536 }
537 537 }
538 538 removeMarkers(removed);
539 539
540 540 switch (series->type())
541 541 {
542 542 case QAbstractSeries::SeriesTypePie: {
543 543 QPieSeries *s = qobject_cast<QPieSeries *> (series);
544 544 QObject::disconnect(s, SIGNAL(countChanged()), this, SLOT(handleCountChanged()));
545 545 break;
546 546 }
547 547 case QAbstractSeries::SeriesTypeBar:
548 548 case QAbstractSeries::SeriesTypeStackedBar:
549 549 case QAbstractSeries::SeriesTypePercentBar:
550 550 case QAbstractSeries::SeriesTypeHorizontalBar:
551 551 case QAbstractSeries::SeriesTypeHorizontalStackedBar:
552 552 case QAbstractSeries::SeriesTypeHorizontalPercentBar: {
553 553 QAbstractBarSeries *s = qobject_cast<QAbstractBarSeries *> (series);
554 554 QObject::disconnect(s, SIGNAL(countChanged()), this, SLOT(handleCountChanged()));
555 555 break;
556 556 }
557 557 // TODO:
558 558 case QAbstractSeries::SeriesTypeLine:
559 559 case QAbstractSeries::SeriesTypeArea:
560 560 case QAbstractSeries::SeriesTypeScatter:
561 561 case QAbstractSeries::SeriesTypeSpline:
562 562 default: {
563 563 // No need to disconnect any series related signals
564 564 break;
565 565 }
566 566 }
567 567
568 568 QObject::disconnect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
569 569
570 570 m_layout->invalidate();
571 571 // q_ptr->layout()->activate();
572 572 }
573 573
574 574 void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series)
575 575 {
576 576 // Moved to appendSeries
577 577 // This slot is just to make old code work for now.
578 578 addSeries(series);
579 579 }
580 580
581 581 void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
582 582 {
583 583 // Moved to removeSeries
584 584 // This slot is just to make old code work for now.
585 585 removeSeries(series);
586 586 }
587 587
588 588 void QLegendPrivate::handleSeriesVisibleChanged()
589 589 {
590 590 QAbstractSeries *series = qobject_cast<QAbstractSeries *> (sender());
591 591 Q_ASSERT(series);
592 592
593 593 foreach (QLegendMarker* marker, m_markers) {
594 594 if (marker->series() == series) {
595 595 marker->setVisible(series->isVisible());
596 596 }
597 597 }
598 598 m_layout->invalidate();
599 599 }
600 600
601 601 void QLegendPrivate::handleCountChanged()
602 602 {
603 603 // Here we handle the changes in marker count.
604 604 // Can happen for example when pieslice(s) have been added to or removed from pieseries.
605 605
606 606 QAbstractSeries *series = qobject_cast<QAbstractSeries *> (sender());
607 607 QList<QLegendMarker *> createdMarkers = series->d_ptr->createLegendMarkers(q_ptr);
608 608
609 609 // Find out removed markers and created markers
610 610 QList<QLegendMarker *> removedMarkers;
611 611 foreach (QLegendMarker *oldMarker, m_markers) {
612 612 // we have marker, which is related to sender.
613 613 if (oldMarker->series() == series) {
614 614 bool found = false;
615 615 foreach(QLegendMarker *newMarker, createdMarkers) {
616 616 // New marker considered existing if:
617 617 // - d_ptr->relatedObject() is same for both markers.
618 618 if (newMarker->d_ptr->relatedObject() == oldMarker->d_ptr->relatedObject()) {
619 619 // Delete the new marker, since we already have existing marker, that might be connected on user side.
620 620 found = true;
621 621 createdMarkers.removeOne(newMarker);
622 622 delete newMarker;
623 623 }
624 624 }
625 625 if (!found) {
626 626 // No related object found for marker, add to removedMarkers list
627 627 removedMarkers << oldMarker;
628 628 }
629 629 }
630 630 }
631 631
632 632 removeMarkers(removedMarkers);
633 633 decorateMarkers(createdMarkers);
634 634 addMarkers(createdMarkers);
635 635
636 636 q_ptr->layout()->invalidate();
637 637 }
638 638
639 639 void QLegendPrivate::addMarkers(QList<QLegendMarker *> markers)
640 640 {
641 641 foreach (QLegendMarker* marker, markers) {
642 642 m_items->addToGroup(marker->d_ptr.data()->item());
643 643 m_markers << marker;
644 644 }
645 645 }
646 646
647 647 void QLegendPrivate::removeMarkers(QList<QLegendMarker *> markers)
648 648 {
649 649 foreach (QLegendMarker *marker, markers) {
650 650 marker->d_ptr->item()->setVisible(false);
651 651 m_items->removeFromGroup(marker->d_ptr->item());
652 652 delete marker;
653 653 m_markers.removeOne(marker);
654 654 }
655 655 }
656 656
657 657 void QLegendPrivate::decorateMarkers(QList<QLegendMarker *> markers)
658 658 {
659 659 foreach (QLegendMarker* marker, markers) {
660 660 marker->setFont(m_font);
661 661 marker->setLabelBrush(m_labelBrush);
662 662 }
663 663 }
664 664
665 665
666 666 #include "moc_qlegend.cpp"
667 667 #include "moc_qlegend_p.cpp"
668 668
669 669 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,101 +1,102
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef QLEGEND_P_H
31 31 #define QLEGEND_P_H
32 32
33 33 #include "qlegend.h"
34 #include "scroller_p.h"
34 35
35 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 37
37 38 class QChart;
38 39 class ChartPresenter;
39 40 class QAbstractSeries;
40 41 class LegendLayout;
41 42 class Domain;
42 43 class QLegendMarker;
43 44
44 class QLegendPrivate : public QObject
45 class QLegendPrivate : public QObject, public Scroller
45 46 {
46 47 Q_OBJECT
47 48 public:
48 49 QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
49 50 ~QLegendPrivate();
50 51
51 void setOffset(qreal x, qreal y);
52 void setOffset(const QPointF &offset);
52 53 QPointF offset() const;
53 54 int roundness(qreal size);
54 55
55 56 QGraphicsItemGroup* items() { return m_items; }
56 57
57 58 // New stuff:
58 59 QList<QLegendMarker*> markers() { return m_markers; }
59 60 void addSeries(QAbstractSeries* series);
60 61 void removeSeries(QAbstractSeries* series);
61 62
62 63 public Q_SLOTS:
63 64 void handleSeriesAdded(QAbstractSeries *series);
64 65 void handleSeriesRemoved(QAbstractSeries *series);
65 66 void handleSeriesVisibleChanged();
66 67 void handleCountChanged();
67 68
68 69 private:
69 70 // Internal helpers
70 71 void addMarkers(QList<QLegendMarker *> markers);
71 72 void removeMarkers(QList<QLegendMarker *> markers);
72 73 void decorateMarkers(QList<QLegendMarker *> markers);
73 74
74 75 private:
75 76 QLegend *q_ptr;
76 77 ChartPresenter *m_presenter;
77 78 LegendLayout *m_layout;
78 79 QChart* m_chart;
79 80 QGraphicsItemGroup* m_items;
80 81 Qt::Alignment m_alignment;
81 82 QBrush m_brush;
82 83 QPen m_pen;
83 84 QFont m_font;
84 85 QBrush m_labelBrush;
85 86
86 87 qreal m_diameter;
87 88 bool m_attachedToChart;
88 89 bool m_backgroundVisible;
89 90
90 91 friend class QLegend;
91 92 friend class LegendLayout;
92 93 QList<QLegendMarker*> m_markers;
93 94 QList<QAbstractSeries*> m_series;
94 95
95 96 friend class QLegend;
96 97 friend class LegendMarkerItem;
97 98 };
98 99
99 100 QTCOMMERCIALCHART_END_NAMESPACE
100 101
101 102 #endif
@@ -1,247 +1,159
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "scroller_p.h"
22 22 #include "qlegend.h"
23 23 #include <QGraphicsSceneMouseEvent>
24 24 #include <QDebug>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 Scroller::Scroller()
29 29 : m_ticker(this),
30 m_state(Idle),
31 m_moveThreshold(10),
32 m_timeTreshold(50)
30 m_timeTresholdMin(50),
31 m_timeTresholdMax(300),
32 m_state(Idle)
33 33 {
34 34
35 35 }
36 36
37 37 Scroller::~Scroller()
38 38 {
39 39 }
40 40
41 void Scroller::mousePressEvent(QGraphicsSceneMouseEvent *event)
41 void Scroller::move(const QPointF &delta)
42 42 {
43 if (event->button() == Qt::LeftButton) {
44 switch (m_state) {
45 case Idle:
46 m_state = Pressed;
47 m_offset = offset();
48 m_press = event->pos();
49 m_timeStamp = QTime::currentTime();
50 event->accept();
51 break;
52 case Scroll:
53 m_state = Stop;
54 m_speed = QPointF(0, 0);
55 m_offset = offset();
56 m_press = event->pos();
57 event->accept();
58 break;
59 case Pressed:
60 case Move:
61 case Stop:
62 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
63 event->ignore();
64 break;
65 }
66 }
67 }
68
69 void Scroller::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
70 {
71 QPointF delta = event->pos() - m_press;
72
73 43 switch (m_state) {
74 case Pressed:
75 case Stop:
76 if (qAbs(delta.x()) > m_moveThreshold || qAbs(delta.y()) > m_moveThreshold) {
77 m_state = Move;
78 m_timeStamp = QTime::currentTime();
79 m_distance = QPointF(0, 0);
80 m_press = event->pos();
81 event->accept();
82 } else {
83 event->ignore();
84 }
85 break;
86 case Move:
87 setOffset(m_offset - delta);
88 calculateSpeed(event->pos());
89 event->accept();
90 break;
91 44 case Idle:
45 m_timeStamp = QTime::currentTime();
46 m_state = Move;
47 break;
92 48 case Scroll:
93 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
94 event->ignore();
49 stopTicker();
50 m_timeStamp = QTime::currentTime();
51 m_state = Move;
52 break;
53 default:
95 54 break;
96 55 }
56 setOffset(offset() - delta);
97 57 }
98 58
99 void Scroller::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
59 void Scroller::release(const QPointF &delta)
100 60 {
101 if (event->button() == Qt::LeftButton) {
61 // Starts scrolling, if at least m_timeTresholdMin msecs has gone since timestamp
62 // current time is no more than m_timeTresholdMax from timestamp
102 63
103 switch (m_state) {
64 if ((m_timeStamp.elapsed() > m_timeTresholdMin) && (m_timeStamp.msecsTo(QTime::currentTime()) < m_timeTresholdMax)) {
65 // Release was quick enough. Start scrolling.
66 // Magic number is to make scroll bit slower (the resolution of screen may affect this)
67 m_speed = delta / 5;
104 68
105 case Scroll:
106 m_state = Stop;
107 m_speed = QPointF(0, 0);
108 m_offset = offset();
109 event->accept();
110 break;
111 case Pressed:
112 m_state = Idle;
113 //if (m_timeStamp.elapsed() < m_clickedPressDelay) {
114 //emit clicked(m_offset.toPoint());
115 //}
116 event->accept();
117 break;
118 case Move:
119 calculateSpeed(event->pos());
120 m_offset = offset();
121 m_press = event->pos();
122 if (m_speed == QPointF(0, 0)) {
123 m_state = Idle;
124 } else {
125 m_speed /= 3.75;
126 m_state = Scroll;
127 m_ticker.start(25);
128 }
129 event->accept();
130 break;
131 case Stop:
132 case Idle:
133 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
134 event->ignore();
135 break;
69 qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
70
71 if (!qFuzzyIsNull(fraction)) {
72 m_fraction.setX(qAbs(m_speed.x() / fraction));
73 m_fraction.setY(qAbs(m_speed.y() / fraction));
74 } else {
75 m_fraction.setX(1);
76 m_fraction.setY(1);
136 77 }
78 startTicker(25);
79 m_state = Scroll;
80 } else {
81 stopTicker(); // Stop ticker, if one is running.
82 m_state = Idle;
137 83 }
138 84 }
139 85
140 void Scroller::scroll(const QPointF &velocity)
86 void Scroller::startTicker(int interval)
141 87 {
142 Q_UNUSED(velocity);
143 // TODO:
144 /*
145 m_offset = offset();
146 m_speed = velocity;
147 if (m_speed == QPointF(0, 0)) {
148 m_state = Idle;
149 }
150 else {
151 m_speed /= 3.75;
152 m_state = Scroll;
153 m_ticker.start(25);
154 }
155 */
88 m_state = Scroll;
89 m_ticker.start(interval);
156 90 }
157 91
92 void Scroller::stopTicker()
93 {
94 m_state = Idle;
95 m_ticker.stop();
96 }
158 97
159 98 void Scroller::scrollTick()
160 99 {
161 100 switch (m_state) {
162 101 case Scroll:
163 102 lowerSpeed(m_speed);
164 setOffset(m_offset - m_speed);
165 m_offset = offset();
103 setOffset(offset() - m_speed);
166 104 if (m_speed == QPointF(0, 0)) {
167 105 m_state = Idle;
168 106 m_ticker.stop();
169 107 }
170 108 break;
171 case Stop:
172 m_ticker.stop();
173 break;
174 109 case Idle:
175 110 case Move:
176 case Pressed:
177 111 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
178 112 m_ticker.stop();
113 m_state = Idle;
179 114 break;
180
181 115 }
182 116 }
183 117
184 118 void Scroller::lowerSpeed(QPointF &speed, qreal maxSpeed)
185 119 {
186 120 qreal x = qBound(-maxSpeed, speed.x(), maxSpeed);
187 121 qreal y = qBound(-maxSpeed, speed.y(), maxSpeed);
188 122
189 123 x = (x == 0) ? x :
190 124 (x > 0) ? qMax(qreal(0), x - m_fraction.x()) : qMin(qreal(0), x + m_fraction.x());
191 125 y = (y == 0) ? y :
192 126 (y > 0) ? qMax(qreal(0), y - m_fraction.y()) : qMin(qreal(0), y + m_fraction.y());
193 127 speed.setX(x);
194 128 speed.setY(y);
195 129 }
196 130
197 void Scroller::calculateSpeed(const QPointF &position)
198 {
199 if (m_timeStamp.elapsed() > m_timeTreshold) {
200
201 QPointF distance = position - m_press;
202
203 m_timeStamp = QTime::currentTime();
204 m_speed = distance - m_distance;
205 m_distance = distance;
206
207 qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
208
209 if (fraction != 0) {
210 m_fraction.setX(qAbs(m_speed.x() / fraction));
211 m_fraction.setY(qAbs(m_speed.y() / fraction));
212 } else {
213 m_fraction.setX(1);
214 m_fraction.setY(1);
215 }
216 }
217 }
218
219 131 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
220 132
221 133 ScrollTicker::ScrollTicker(Scroller *scroller, QObject *parent)
222 134 : QObject(parent),
223 135 m_scroller(scroller)
224 136 {
225 137
226 138 }
227 139
228 140 void ScrollTicker::start(int interval)
229 141 {
230 142 if (!m_timer.isActive())
231 143 m_timer.start(interval, this);
232 144 }
233 145
234 146 void ScrollTicker::stop()
235 147 {
236 148 m_timer.stop();
237 149 }
238 150
239 151 void ScrollTicker::timerEvent(QTimerEvent *event)
240 152 {
241 153 Q_UNUSED(event);
242 154 m_scroller->scrollTick();
243 155 }
244 156
245 157 #include "moc_scroller_p.cpp"
246 158
247 159 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,106 +1,102
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef SCROLLER_P_H
31 31 #define SCROLLER_P_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include <QBasicTimer>
35 35 #include <QTime>
36 36 #include <QPointF>
37 37
38 38 class QGraphicsSceneMouseEvent;
39 39
40 40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41 41
42 42 class Scroller;
43 43 class QLegend;
44 44
45 45 class ScrollTicker : public QObject
46 46 {
47 47 Q_OBJECT
48 48 public:
49 49 explicit ScrollTicker(Scroller *scroller, QObject *parent = 0);
50 50 void start(int interval);
51 51 void stop();
52 52 protected:
53 53 void timerEvent(QTimerEvent *event);
54 54
55 55 private:
56 56 QBasicTimer m_timer;
57 57 Scroller *m_scroller;
58 58 };
59 59
60 60 class Scroller
61 61 {
62 62 public:
63 63 enum State {
64 64 Idle,
65 Pressed,
66 65 Move,
67 Scroll,
68 Stop
66 Scroll
69 67 };
70 68
71 69 Scroller();
72 70 virtual ~Scroller();
73 71
74 72 virtual void setOffset(const QPointF &point) = 0;
75 73 virtual QPointF offset() const = 0;
76 74
77 void scroll(const QPointF& velocity);
75 void move(const QPointF &delta);
76 void release(const QPointF &delta);
78 77
79 public:
80 78 void scrollTick();
81 79
82 public:
83 void mousePressEvent(QGraphicsSceneMouseEvent *event);
84 void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
85 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
80 private:
81 void startTicker(int interval);
82 void stopTicker();
83
86 84
87 85 private:
88 86 void calculateSpeed(const QPointF &position);
89 87 void lowerSpeed(QPointF &speed, qreal maxSpeed = 100);
90 88
91 89 private:
92 90 ScrollTicker m_ticker;
93 State m_state;
94 91 QTime m_timeStamp;
95 QPointF m_press;
96 QPointF m_offset;
97 92 QPointF m_speed;
98 QPointF m_distance;
99 93 QPointF m_fraction;
100 int m_moveThreshold;
101 int m_timeTreshold;
94 int m_timeTresholdMin;
95 int m_timeTresholdMax;
96
97 State m_state;
102 98 };
103 99
104 100 QTCOMMERCIALCHART_END_NAMESPACE
105 101
106 102 #endif /* SCROLLER_P_H */
General Comments 0
You need to be logged in to leave comments. Login now