##// END OF EJS Templates
Added clicked signal to scatter...
Tero Ahola -
r316:101197172c50
parent child
Show More
@@ -1,282 +1,283
1 1 #include "qchart.h"
2 2 #include "qchartaxis.h"
3 3 #include "chartpresenter_p.h"
4 4 #include "chartdataset_p.h"
5 5 #include "charttheme_p.h"
6 6 //series
7 7 #include "qbarchartseries.h"
8 8 #include "qstackedbarchartseries.h"
9 9 #include "qpercentbarchartseries.h"
10 10 #include "qlinechartseries.h"
11 11 #include "qpieseries.h"
12 12 #include "qscatterseries.h"
13 13 //items
14 14 #include "axisitem_p.h"
15 15 #include "axisanimationitem_p.h"
16 16 #include "barpresenter.h"
17 17 #include "stackedbarpresenter.h"
18 18 #include "linechartitem_p.h"
19 19 #include "percentbarpresenter.h"
20 20 #include "linechartanimationitem_p.h"
21 21 #include "piepresenter.h"
22 22 #include "scatterpresenter_p.h"
23 23
24 24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 25
26 26 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
27 27 m_chart(chart),
28 28 m_dataset(dataset),
29 29 m_chartTheme(0),
30 30 m_marginSize(0),
31 31 m_rect(QRectF(QPoint(0,0),m_chart->size())),
32 32 m_options(0)
33 33 {
34 34 createConnections();
35 35 setChartTheme(QChart::ChartThemeDefault);
36 36
37 37 }
38 38
39 39 ChartPresenter::~ChartPresenter()
40 40 {
41 41 }
42 42
43 43 void ChartPresenter::createConnections()
44 44 {
45 45 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
46 46 QObject::connect(m_dataset,SIGNAL(seriesAdded(QChartSeries*)),this,SLOT(handleSeriesAdded(QChartSeries*)));
47 47 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QChartSeries*)),this,SLOT(handleSeriesRemoved(QChartSeries*)));
48 48 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*)),this,SLOT(handleAxisAdded(QChartAxis*)));
49 49 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
50 50 QObject::connect(m_dataset,SIGNAL(seriesDomainChanged(QChartSeries*,const Domain&)),this,SLOT(handleSeriesDomainChanged(QChartSeries*,const Domain&)));
51 51 QObject::connect(m_dataset,SIGNAL(axisLabelsChanged(QChartAxis*,const QStringList&)),this,SLOT(handleAxisLabelsChanged(QChartAxis*,const QStringList&)));
52 52 }
53 53
54 54
55 55 QRectF ChartPresenter::geometry() const
56 56 {
57 57 return m_rect;
58 58 }
59 59
60 60 void ChartPresenter::handleGeometryChanged()
61 61 {
62 62 m_rect = QRectF(QPoint(0,0),m_chart->size());
63 63 m_rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
64 64 Q_ASSERT(m_rect.isValid());
65 65 emit geometryChanged(m_rect);
66 66 }
67 67
68 68 int ChartPresenter::margin() const
69 69 {
70 70 return m_marginSize;
71 71 }
72 72
73 73 void ChartPresenter::setMargin(int margin)
74 74 {
75 75 m_marginSize = margin;
76 76 }
77 77
78 78 void ChartPresenter::handleAxisAdded(QChartAxis* axis)
79 79 {
80 80
81 81 AxisItem* item ;
82 82
83 83 if(!m_options.testFlag(QChart::GridAxisAnimations))
84 84 {
85 85 item = new AxisItem(axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
86 86 }else{
87 87 item = new AxisAnimationItem(axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
88 88 }
89 89
90 90 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
91 91 QObject::connect(axis,SIGNAL(update(QChartAxis*)),item,SLOT(handleAxisUpdate(QChartAxis*)));
92 92
93 93 item->handleAxisUpdate(axis);
94 94 item->handleGeometryChanged(m_rect);
95 95 m_chartTheme->decorate(axis,item);
96 96 m_axisItems.insert(axis,item);
97 97 }
98 98
99 99 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
100 100 {
101 101 AxisItem* item = m_axisItems.take(axis);
102 102 Q_ASSERT(item);
103 103 delete item;
104 104 }
105 105
106 106
107 107 void ChartPresenter::handleSeriesAdded(QChartSeries* series)
108 108 {
109 109 switch(series->type())
110 110 {
111 111 case QChartSeries::SeriesTypeLine: {
112 112 QLineChartSeries* lineSeries = static_cast<QLineChartSeries*>(series);
113 113 LineChartItem* item;
114 114 if(m_options.testFlag(QChart::SeriesAnimations)){
115 115 item = new LineChartAnimationItem(this,lineSeries,m_chart);
116 116 }else{
117 117 item = new LineChartItem(this,lineSeries,m_chart);
118 118 }
119 119 m_chartTheme->decorate(item,lineSeries,m_chartItems.count());
120 120 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
121 121 QObject::connect(lineSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
122 122 m_chartItems.insert(series,item);
123 123 break;
124 124 }
125 125
126 126 case QChartSeries::SeriesTypeBar: {
127 127 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
128 128 BarPresenter* item = new BarPresenter(barSeries,m_chart);
129 129 m_chartTheme->decorate(item,barSeries,m_chartItems.count());
130 130 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
131 131 QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
132 132 m_chartItems.insert(series,item);
133 133 // m_axisXItem->setVisible(false);
134 134 break;
135 135 }
136 136
137 137 case QChartSeries::SeriesTypeStackedBar: {
138 138
139 139 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
140 140 StackedBarPresenter* item = new StackedBarPresenter(stackedBarSeries,m_chart);
141 141 m_chartTheme->decorate(item,stackedBarSeries,m_chartItems.count());
142 142 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
143 143 QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
144 144 m_chartItems.insert(series,item);
145 145 break;
146 146 }
147 147
148 148 case QChartSeries::SeriesTypePercentBar: {
149 149
150 150 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
151 151 PercentBarPresenter* item = new PercentBarPresenter(percentBarSeries,m_chart);
152 152 m_chartTheme->decorate(item,percentBarSeries ,m_chartItems.count());
153 153 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
154 154 QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
155 155 m_chartItems.insert(series,item);
156 156 break;
157 157 }
158 158 case QChartSeries::SeriesTypeScatter: {
159 159 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
160 160 ScatterPresenter *scatterPresenter = new ScatterPresenter(scatterSeries, m_chart);
161 QObject::connect(scatterPresenter, SIGNAL(clicked()), scatterSeries, SIGNAL(clicked()));
161 162 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)),
162 163 scatterPresenter, SLOT(handleGeometryChanged(const QRectF&)));
163 164 m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
164 165 m_chartItems.insert(scatterSeries, scatterPresenter);
165 166 break;
166 167 }
167 168 case QChartSeries::SeriesTypePie: {
168 169 QPieSeries *s = qobject_cast<QPieSeries *>(series);
169 170 PiePresenter* pie = new PiePresenter(m_chart, s);
170 171 m_chartTheme->decorate(pie, s, m_chartItems.count());
171 172 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), pie, SLOT(handleGeometryChanged(const QRectF&)));
172 173
173 174 // Hide all from background when there is only piechart
174 175 // TODO: refactor this ugly code... should be one setting for this
175 176 if (m_chartItems.count() == 0) {
176 177 m_chart->axisX()->setAxisVisible(false);
177 178 m_chart->axisY()->setAxisVisible(false);
178 179 m_chart->axisX()->setGridVisible(false);
179 180 m_chart->axisY()->setGridVisible(false);
180 181 m_chart->axisX()->setLabelsVisible(false);
181 182 m_chart->axisY()->setLabelsVisible(false);
182 183 m_chart->axisX()->setShadesVisible(false);
183 184 m_chart->axisY()->setShadesVisible(false);
184 185 m_chart->setChartBackgroundBrush(Qt::transparent);
185 186 }
186 187
187 188 m_chartItems.insert(series, pie);
188 189 break;
189 190 }
190 191 default: {
191 192 qDebug()<< "Series type" << series->type() << "not implemented.";
192 193 break;
193 194 }
194 195 }
195 196
196 197 if(m_rect.isValid()) emit geometryChanged(m_rect);
197 198 }
198 199
199 200 void ChartPresenter::handleSeriesRemoved(QChartSeries* series)
200 201 {
201 202 ChartItem* item = m_chartItems.take(series);
202 203 delete item;
203 204 }
204 205
205 206 void ChartPresenter::handleSeriesChanged(QChartSeries* series)
206 207 {
207 208 //TODO:
208 209 }
209 210
210 211 void ChartPresenter::handleSeriesDomainChanged(QChartSeries* series, const Domain& domain)
211 212 {
212 213 m_chartItems.value(series)->handleDomainChanged(domain);
213 214 }
214 215
215 216 void ChartPresenter::handleAxisLabelsChanged(QChartAxis* axis,const QStringList& labels)
216 217 {
217 218 m_axisItems.value(axis)->handleLabelsChanged(axis,labels);
218 219 }
219 220
220 221 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
221 222 {
222 223 delete m_chartTheme;
223 224
224 225 m_chartTheme = ChartTheme::createTheme(theme);
225 226
226 227 m_chartTheme->decorate(m_chart);
227 228 QMapIterator<QChartSeries*,ChartItem*> i(m_chartItems);
228 229
229 230 int index=0;
230 231 while (i.hasNext()) {
231 232 i.next();
232 233 m_chartTheme->decorate(i.value(),i.key(),index);
233 234 index++;
234 235 }
235 236
236 237 QMapIterator<QChartAxis*,AxisItem*> j(m_axisItems);
237 238 while (j.hasNext()) {
238 239 j.next();
239 240 m_chartTheme->decorate(j.key(),j.value());
240 241 }
241 242 }
242 243
243 244 QChart::ChartTheme ChartPresenter::chartTheme()
244 245 {
245 246 return m_chartTheme->id();
246 247 }
247 248
248 249 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
249 250 {
250 251 if(m_options!=options) {
251 252
252 253 m_options=options;
253 254
254 255 //recreate elements
255 256
256 257 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
257 258 QList<QChartSeries*> seriesList = m_chartItems.uniqueKeys();
258 259
259 260 foreach(QChartAxis* axis, axisList) {
260 261 handleAxisRemoved(axis);
261 262 handleAxisAdded(axis);
262 263 }
263 264 foreach(QChartSeries* series, seriesList) {
264 265 handleSeriesRemoved(series);
265 266 handleSeriesAdded(series);
266 267 }
267 268
268 269 //now reintialize view data
269 270 //TODO: make it more nice
270 271 m_dataset->setDomain(m_dataset->domainIndex());
271 272 }
272 273 }
273 274
274 275 QChart::AnimationOptions ChartPresenter::animationOptions() const
275 276 {
276 277 return m_options;
277 278 }
278 279
279 280
280 281 #include "moc_chartpresenter_p.cpp"
281 282
282 283 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,162 +1,134
1 1 #include "scatterpresenter_p.h"
2 2 #include "qscatterseries.h"
3 3 #include <QPen>
4 4 #include <QPainter>
5 5 #include <QGraphicsScene>
6 #include <QGraphicsSceneMouseEvent>
6 7 #include <QDebug>
7 8 #include <QTime>
8 9
9 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 11
11 12 ScatterPresenter::ScatterPresenter(QScatterSeries *series, QGraphicsObject *parent) :
12 13 ChartItem(parent),
13 14 m_series(series),
14 15 m_boundingRect(),
15 16 //m_markerColor(QColor()),
16 17 // m_markerColor(QColor(255, 0, 0)),
17 18 m_visibleChartArea()
18 19 {
19 20 if (parent)
20 21 m_boundingRect = parent->boundingRect();
21 22
22 23 if (series) {
23 24 connect(series, SIGNAL(changed()), this, SLOT(handleModelChanged()));
24 25 }
25 26 }
26 27
27 28 void ScatterPresenter::handleDomainChanged(const Domain& domain)
28 29 {
29 30 m_visibleChartArea = domain;
30 31 changeGeometry();
31 32 }
32 33
33 34 void ScatterPresenter::handleGeometryChanged(const QRectF& rect)
34 35 {
35 36 m_boundingRect = rect;
36 37 changeGeometry();
37 38 }
38 39
39 40 void ScatterPresenter::handleModelChanged()
40 41 {
41 42 // TODO: more fine grained modelChanged signaling
42 43 changeGeometry();
43 44 }
44 45
45 46 void ScatterPresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
46 47 {
47 // TODO: Optimization: avoid setting on every paint method call?
48 // The custom settings in series override those defined by the theme
49 int shape = m_series->markerShape();
50
51 48 painter->save();
52 49 painter->setClipRect(m_boundingRect);
53 50
54 // Paint dropshadow
55 QPen dropShadowPen(QColor(0, 0, 0, 70));
56 dropShadowPen.setWidth(3);
57 painter->setPen(dropShadowPen);
58 painter->setBrush(Qt::NoBrush);
59 painter->setRenderHint(QPainter::Antialiasing);
60 for (int i(0); i < m_scenex.count() && i < m_sceney.count(); i++) {
61 if (scene()->width() > m_scenex.at(i) && scene()->height() > m_sceney.at(i))
62 switch (shape) {
63 case QScatterSeries::MarkerShapeDefault:
64 // Fallthrough, defaults to circle
65 case QScatterSeries::MarkerShapeCircle:
66 painter->drawChord(m_scenex.at(i) + 2, m_sceney.at(i) + 2, 9, 9, 0, 5760);
67 break;
68 case QScatterSeries::MarkerShapePoint:
69 //painter->drawPoint(m_scenex.at(i), m_sceney.at(i));
70 break;
71 case QScatterSeries::MarkerShapeRectangle:
72 painter->drawRect(m_scenex.at(i) + 2, m_sceney.at(i) + 2, 8, 8);
73 break;
74 case QScatterSeries::MarkerShapeTiltedRectangle: {
75 // TODO:
76 static const QPointF points[4] = {
77 QPointF(-1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
78 QPointF(0.0 + m_scenex.at(i), 1.0 + m_sceney.at(i)),
79 QPointF(1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
80 QPointF(0.0 + m_scenex.at(i), -1.0 + m_sceney.at(i))
81 };
82 painter->drawPolygon(points, 4);
83 break;
84 }
85 default:
86 // TODO: implement the rest of the shapes
87 Q_ASSERT(false);
88 break;
89 }
90 }
91
92 51 // Paint the shape
52 // The custom settings in series override those defined by the theme
93 53 QPen pen = m_markerPen;
94 54 if (m_series->markerPen().color().isValid())
95 55 pen = m_series->markerPen();
96 56 if (m_series->markerBrush().color().isValid())
97 57 painter->setBrush(m_series->markerBrush());
98 58 else
99 59 painter->setBrush(m_markerBrush);
100 60 painter->setPen(pen);
101 painter->setRenderHint(QPainter::Antialiasing, false);
102 for (int i(0); i < m_scenex.count() && i < m_sceney.count(); i++) {
103 if (scene()->width() > m_scenex.at(i) && scene()->height() > m_sceney.at(i))
104 switch (shape) {
105 case QScatterSeries::MarkerShapeDefault:
106 // Fallthrough, defaults to circle
107 case QScatterSeries::MarkerShapeCircle:
108 painter->drawChord(m_scenex.at(i), m_sceney.at(i), 9, 9, 0, 5760);
109 break;
110 case QScatterSeries::MarkerShapePoint:
111 painter->drawPoint(m_scenex.at(i), m_sceney.at(i));
112 break;
113 case QScatterSeries::MarkerShapeRectangle:
114 painter->drawRect(m_scenex.at(i), m_sceney.at(i), 9, 9);
115 break;
116 case QScatterSeries::MarkerShapeTiltedRectangle: {
117 // TODO:
118 static const QPointF points[4] = {
119 QPointF(-1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
120 QPointF(0.0 + m_scenex.at(i), 1.0 + m_sceney.at(i)),
121 QPointF(1.0 + m_scenex.at(i), 0.0 + m_sceney.at(i)),
122 QPointF(0.0 + m_scenex.at(i), -1.0 + m_sceney.at(i))
123 };
124 painter->drawPolygon(points, 4);
125 break;
126 }
127 default:
128 // TODO: implement the rest of the shapes
129 Q_ASSERT(false);
130 break;
131 }
132 }
61 painter->drawPath(m_path);
62
63 // TODO: how to draw a drop shadow?
64 QPen dropShadowPen(QColor(0, 0, 0, 70));
65 dropShadowPen.setWidth(3);
66 painter->setPen(dropShadowPen);
67 painter->setBrush(Qt::NoBrush);
68 painter->setRenderHint(QPainter::Antialiasing);
69 painter->drawPath(m_path.translated(2, 2));
133 70
134 71 painter->restore();
135 72 }
136 73
137 74 void ScatterPresenter::mousePressEvent(QGraphicsSceneMouseEvent *event)
138 75 {
139 qDebug() << "ScatterPresenter::mousePressEvent" << event;
76 qDebug() << "ScatterPresenter::mousePressEvent" << event << " cont: "
77 << m_path.contains(event->lastPos());
78
79 if (m_path.contains(event->lastPos()))
80 emit clicked();
140 81 }
141 82
142 83 void ScatterPresenter::changeGeometry()
143 84 {
144 85 if (m_boundingRect.isValid()) {
145
146 86 prepareGeometryChange();
147 87 qreal scalex = m_boundingRect.width() / m_visibleChartArea.spanX();
148 88 qreal scaley = m_boundingRect.height() / m_visibleChartArea.spanY();
149 m_scenex.clear();
150 m_sceney.clear();
151 89
152 // Convert relative coordinates to absolute pixel coordinates that can be used for drawing
90 int shape = m_series->markerShape();
91 m_path = QPainterPath();
92
153 93 foreach (QPointF point, m_series->data()) {
154 m_scenex.append(m_boundingRect.left() + point.x() * scalex - m_visibleChartArea.m_minX * scalex);
155 m_sceney.append(m_boundingRect.bottom() - point.y() * scaley + m_visibleChartArea.m_minY * scaley);
94 // Convert relative coordinates to absolute pixel coordinates that can be used for drawing
95 qreal x = m_boundingRect.left() + point.x() * scalex - m_visibleChartArea.m_minX * scalex;
96 qreal y = m_boundingRect.bottom() - point.y() * scaley + m_visibleChartArea.m_minY * scaley;
97
98 if (scene()->width() > x && scene()->height() > y) {
99 switch (shape) {
100 case QScatterSeries::MarkerShapeDefault:
101 // Fallthrough, defaults to circle
102 case QScatterSeries::MarkerShapeCircle:
103 m_path.addEllipse(x, y, 9, 9);
104 break;
105 case QScatterSeries::MarkerShapePoint:
106 m_path.addEllipse(x, y, 2, 2);
107 break;
108 case QScatterSeries::MarkerShapeRectangle:
109 m_path.addRect(x, y, 9, 9);
110 break;
111 case QScatterSeries::MarkerShapeTiltedRectangle: {
112 // TODO:
113 // static const QPointF points[4] = {
114 // QPointF(-1.0 + x, 0.0 + y),
115 // QPointF(0.0 + x, 1.0 + y),
116 // QPointF(1.0 + x, 0.0 + y),
117 // QPointF(0.0 + x, -1.0 + y)
118 // };
119 //m_path.addPolygon(QPolygon(4, &points));
120 break;
121 }
122 default:
123 // TODO: implement the rest of the shapes
124 Q_ASSERT(false);
125 break;
126 }
127 }
156 128 }
157 129 }
158 130 }
159 131
160 132 #include "moc_scatterpresenter_p.cpp"
161 133
162 134 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,49 +1,50
1 1 #ifndef SCATTERPRESENTER_H
2 2 #define SCATTERPRESENTER_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "chartitem_p.h"
6 6 #include <QObject>
7 7 #include <QPen>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class QScatterSeries;
12 12
13 13 /*!
14 14 * The "business logic" of scatter series. This is a QObject that does not have a parent QObject.
15 15 * The QGraphicsItem parent owns the object instead.
16 16 */
17 17 class ScatterPresenter : public QObject, public ChartItem
18 18 {
19 19 Q_OBJECT
20 20 public:
21 21 explicit ScatterPresenter(QScatterSeries *series, QGraphicsObject *parent = 0);
22 22
23 23 public: // from ChartItem
24 QRectF boundingRect() const { return m_boundingRect; }
24 QRectF boundingRect() const { return m_path.boundingRect(); }
25 QPainterPath shape() const { return m_path; }
25 26 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
26 27 void mousePressEvent (QGraphicsSceneMouseEvent * event);
27 28
28 signals:
29 Q_SIGNALS:
30 void clicked();
29 31
30 32 public Q_SLOTS:
31 33 void handleDomainChanged(const Domain& domain);
32 34 void handleGeometryChanged(const QRectF& rect);
33 35 void handleModelChanged();
34 36
35 37 public:
36 38 void changeGeometry();
37 39
38 40 QScatterSeries *m_series;
39 41 QRectF m_boundingRect;
40 QList<qreal> m_scenex;
41 QList<qreal> m_sceney;
42 42 Domain m_visibleChartArea;
43 43 QPen m_markerPen;
44 44 QBrush m_markerBrush;
45 QPainterPath m_path;
45 46 };
46 47
47 48 QTCOMMERCIALCHART_END_NAMESPACE
48 49
49 50 #endif // SCATTERPRESENTER_H
General Comments 0
You need to be logged in to leave comments. Login now