##// END OF EJS Templates
Refactor scatter chart to fit the other classes...
Michal Klocek -
r470:5c708e3e7c7c
parent child
Show More
@@ -0,0 +1,178
1 #include "scatterchartitem_p.h"
2 #include "qscatterseries.h"
3 #include "chartpresenter_p.h"
4 #include <QPainter>
5 #include <QGraphicsScene>
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 ScatterChartItem::ScatterChartItem(QScatterSeries *series, QGraphicsObject *parent) :
10 XYChartItem(series,parent),
11 m_series(series),
12 m_items(this),
13 m_shape(QScatterSeries::MarkerShapeRectangle),
14 m_size(10)
15
16 {
17 Q_ASSERT(parent);
18 Q_ASSERT(series);
19
20 connect(m_series,SIGNAL(updated()), this, SLOT(handleUpdated()));
21
22 setZValue(ChartPresenter::ScatterSeriesZValue);
23 setFlags(QGraphicsItem::ItemHasNoContents);
24 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
25
26 handleUpdated();
27
28 // TODO: how to draw a drop shadow?
29 // QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect();
30 // dropShadow->setOffset(2.0);
31 // dropShadow->setBlurRadius(2.0);
32 // setGraphicsEffect(dropShadow);
33 }
34
35
36 QRectF ScatterChartItem::boundingRect() const
37 {
38 return m_rect;
39 }
40
41 void ScatterChartItem::createPoints(int count)
42 {
43 for (int i = 0; i < count; ++i) {
44
45 QGraphicsItem *item;
46
47 switch (m_shape) {
48 case QScatterSeries::MarkerShapeDefault:
49 // Fallthrough, defaults to circle
50 case QScatterSeries::MarkerShapeCircle:
51 item = new QGraphicsEllipseItem(0,0,m_size,m_size);
52 break;
53 case QScatterSeries::MarkerShapeRectangle:
54 item = new QGraphicsRectItem(0,0,m_size,m_size);
55 break;
56 case QScatterSeries::MarkerShapeRoundedRectangle:
57 //m_path.addRoundedRect(x, y, size, size, size / 4.0, size / 4.0);
58 break;
59 case QScatterSeries::MarkerShapeTiltedRectangle:
60 // TODO: tilt the rectangle
61 //m_path.addRect(x, y, size, size);
62 //break;
63 case QScatterSeries::MarkerShapeTriangle:
64 //QPolygonF polygon;
65 //polygon << QPointF(0.0, -size) << QPointF(size / 2.0, 0.0) << QPointF(-size / 2, 0.0);
66 // TODO: the position is not exactly right...
67 //m_path.addPolygon(polygon.translated(x + size / 2.0, y + size));
68 break;
69 }
70 m_items.addToGroup(item);
71 }
72 }
73
74 void ScatterChartItem::deletePoints(int count)
75 {
76 QList<QGraphicsItem *> items = m_items.childItems();
77
78 for (int i = 0; i < count; ++i) {
79 delete(items.takeLast());
80 }
81 }
82
83 /*
84
85 void ScatterChartItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
86 {
87
88 QPointF clickedPoint(
89 m_minX + (event->lastPos().x() / m_clippingRect.width()) * (m_maxX-m_minX),
90 m_maxY - (event->lastPos().y() / m_clippingRect.height()) * (m_maxY-m_minY));
91 emit clicked(clickedPoint);
92
93 }
94 */
95
96 void ScatterChartItem::setGeometry(QVector<QPointF>& points)
97 {
98 if(points.size()==0) return;
99
100 int diff = XYChartItem::points().size() - points.size();
101
102 if(diff>0) {
103 deletePoints(diff);
104 }
105 else if(diff<0) {
106 createPoints(-diff);
107 }
108
109 if(diff!=0) handleUpdated();
110
111 QList<QGraphicsItem*> items = m_items.childItems();
112
113 for(int i=0; i< points.size();i++) {
114 QGraphicsItem* item = items.at(i);
115 const QPointF& point = points.at(i);
116 item->setPos(point.x()-1,point.y()-1);
117 if(!clipRect().contains(point)) {
118 item->setVisible(false);
119 }
120 else {
121 item->setVisible(true);
122 }
123 }
124
125 prepareGeometryChange();
126 m_rect = clipRect();
127 XYChartItem::setGeometry(points);
128 }
129
130
131 void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
132 {
133 Q_UNUSED(painter);
134 Q_UNUSED(option);
135 Q_UNUSED(widget);
136 }
137
138 void ScatterChartItem::setPen(const QPen& pen)
139 {
140 foreach(QGraphicsItem* item , m_items.childItems()) {
141 static_cast<QAbstractGraphicsShapeItem*>(item)->setPen(pen);
142 }
143 }
144
145 void ScatterChartItem::setBrush(const QBrush& brush)
146 {
147 foreach(QGraphicsItem* item , m_items.childItems()) {
148 static_cast<QAbstractGraphicsShapeItem*>(item)->setBrush(brush);
149 }
150 }
151
152 void ScatterChartItem::handleUpdated()
153 {
154
155 int count = m_items.childItems().count();
156
157 if(count==0) return;
158
159 bool recreate = m_size != m_series->size() || m_shape != m_series->shape();
160
161 //TODO: only rewrite on size change
162
163 m_size = m_series->size();
164 m_shape = m_series->shape();
165
166 if(recreate){
167 deletePoints(count);
168 createPoints(count);
169 }
170
171 setPen(m_series->pen());
172 setBrush(m_series->brush());
173
174 }
175
176 #include "moc_scatterchartitem_p.cpp"
177
178 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,50
1 #ifndef SCATTERPRESENTER_H
2 #define SCATTERPRESENTER_H
3
4 #include "qchartglobal.h"
5 #include "xychartitem_p.h"
6 #include <QObject>
7 #include <QPen>
8
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10
11 class QScatterSeries;
12
13 class ScatterChartItem : public XYChartItem
14 {
15 Q_OBJECT
16 public:
17 explicit ScatterChartItem(QScatterSeries *series, QGraphicsObject *parent = 0);
18
19 public:
20 //from QGraphicsItem
21 QRectF boundingRect() const;
22 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
23
24 void setPen(const QPen& pen);
25 void setBrush(const QBrush& brush);
26
27 signals:
28 void clicked(QPointF coordinates);
29
30 public slots:
31 void handleUpdated();
32
33 private:
34 void createPoints(int count);
35 void deletePoints(int count);
36
37 protected:
38 virtual void setGeometry(QVector<QPointF>& points);
39
40 private:
41 QScatterSeries *m_series;
42 QGraphicsItemGroup m_items;
43 int m_shape;
44 int m_size;
45 QRectF m_rect;
46 };
47
48 QTCOMMERCIALCHART_END_NAMESPACE
49
50 #endif // SCATTERPRESENTER_H
@@ -1,50 +1,51
1 1 #include <QtGui/QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartglobal.h>
4 4 #include <qchartview.h>
5 5 #include <qscatterseries.h>
6 6
7 7 QTCOMMERCIALCHART_USE_NAMESPACE
8 8
9 9 int main(int argc, char *argv[])
10 10 {
11 11 QApplication a(argc, argv);
12 12
13 13 //! [1]
14 14 // Create chart view
15 15 QChartView *chartView = new QChartView();
16 16 chartView->setRenderHint(QPainter::Antialiasing);
17 17 // Add scatter series with linear test data with random "noise"
18 18 QScatterSeries *scatter = new QScatterSeries();
19 19 for (qreal i(0.0); i < 20; i += 0.5) {
20 20 qreal x = i + (qreal)(rand() % 100) / 100.0;
21 21 qreal y = i + (qreal)(rand() % 100) / 100.0;
22 22 (*scatter) << QPointF(x, y);
23 23 }
24 24 // Chart takes ownership
25 25 chartView->addSeries(scatter);
26 26 //! [1]
27 27
28 28 // And more
29 29 //! [2]
30 *scatter << QPointF(2.0, 5.5) << QPointF(2.2, 5.4);
30 // *scatter << QPointF(2.0, 5.5) << QPointF(2.2, 5.4);
31 31 //! [2]
32 32
33 33 //! [3]
34 QBrush brush(QColor(255, 0, 0, 80), Qt::SolidPattern);
34 QBrush brush(Qt::red);
35 35 scatter->setBrush(brush);
36 QPen pen(QColor(0, 255, 0, 60), 3);
36 QPen pen(Qt::black);
37 pen.setWidth(3);
37 38 scatter->setPen(pen);
38 scatter->setShape(QScatterSeries::MarkerShapeRectangle);
39 scatter->setShape(QScatterSeries::MarkerShapeCircle);
39 40 scatter->setSize(25.0);
40 41 //! [3]
41 42
42 43 // Use the chart widget as the central widget
43 44 QMainWindow w;
44 45 w.resize(400, 300);
45 46 w.setCentralWidget(chartView);
46 w.setWindowFlags(Qt::FramelessWindowHint);
47 // w.setWindowFlags(Qt::FramelessWindowHint);
47 48 w.show();
48 49
49 50 return a.exec();
50 51 }
@@ -1,51 +1,54
1 1 #include "mainwindow.h"
2 2 #include <qchartglobal.h>
3 3 #include <qchartview.h>
4 4 #include <QDebug>
5 5
6 6 QTCOMMERCIALCHART_USE_NAMESPACE
7 7
8 8 MainWindow::MainWindow(QWidget *parent)
9 9 : QMainWindow(parent)
10 10 {
11 11 resize(400, 300);
12 12 setWindowFlags(Qt::FramelessWindowHint);
13 13
14 14 QChartView *chartView = new QChartView(this);
15 15 chartView->setChartTitle("Click to play with points");
16 16 chartView->setRenderHint(QPainter::Antialiasing);
17 17 setCentralWidget(chartView);
18 18
19 19 m_scatter = new QScatterSeries();
20 20 for(qreal x(0.5); x <= 5.0; x += 0.5) {
21 21 for(qreal y(0.5); y <= 5.0; y += 0.5) {
22 22 *m_scatter << QPointF(x, y);
23 23 }
24 24 }
25 25 chartView->addSeries(m_scatter);
26 26
27 27 // Add two more series
28 28 m_scatter2 = new QScatterSeries();
29 29 chartView->addSeries(m_scatter2);
30 30 m_scatter3 = new QScatterSeries();
31 31 chartView->addSeries(m_scatter3);
32 32
33 33 connect(m_scatter, SIGNAL(clicked(QPointF)), this, SLOT(clickPoint(QPointF)));
34 34 }
35 35
36 36 MainWindow::~MainWindow()
37 37 {
38 38 }
39 39
40 40 void MainWindow::clickPoint(QPointF coordinate)
41 41 {
42 42 // Remove the clicked point from the series and add points to the two other series we have
43 //TODO: fix me
44 /*
43 45 int index = m_scatter->closestPoint(coordinate);
44 46 QPointF point = m_scatter->data().at(index);
45 47 Q_ASSERT(m_scatter->removeAt(index));
46 48 point.rx() += 0.25;
47 49 point.ry() += 0.25;
48 50 *m_scatter2 << point;
49 51 point.ry() -= 0.25;
50 52 *m_scatter3 << point;
53 */
51 54 }
@@ -1,307 +1,285
1 1 #include "chartdataset_p.h"
2 2 #include "qchartaxis.h"
3 3 //series
4 4 #include "qlineseries.h"
5 5 #include "qareaseries.h"
6 6 #include "qbarseries.h"
7 7 #include "qstackedbarseries.h"
8 8 #include "qpercentbarseries.h"
9 9 #include "qpieseries.h"
10 10 #include "qscatterseries.h"
11 11 #include "qsplineseries.h"
12 12
13 13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 14
15 15 ChartDataSet::ChartDataSet(QObject *parent):QObject(parent),
16 16 m_axisX(new QChartAxis(this)),
17 17 m_axisY(new QChartAxis(this)),
18 18 m_domainIndex(0),
19 19 m_axisXInitialized(false)
20 20 {
21 21 }
22 22
23 23 ChartDataSet::~ChartDataSet()
24 24 {
25 25 }
26 26
27 27 void ChartDataSet::addSeries(QSeries* series, QChartAxis *axisY)
28 28 {
29 29 if(axisY==0) axisY = m_axisY;
30 30
31 31 QChartAxis* axis = m_seriesAxisMap.value(series);
32 32
33 33 if(axis) {
34 34 qWarning() << "Can not add series. Series already on the chart";
35 35 return;
36 36 }
37 37
38 38 if(!series->parent()){
39 39 series->setParent(this); // take ownership
40 40 };
41 41
42 42 if(!axisY->parent()){
43 43 axisY->setParent(this); // take ownership
44 44 }
45 45
46 46 Domain* domain = m_axisDomainMap.value(axisY);
47 47
48 48 if(!domain) {
49 49 domain = new Domain();
50 50
51 51 QObject::connect(axisY,SIGNAL(rangeChanged(qreal,qreal)),domain,SLOT(handleAxisRangeYChanged(qreal,qreal)));
52 52 QObject::connect(axisX(),SIGNAL(rangeChanged(qreal,qreal)),domain,SLOT(handleAxisRangeXChanged(qreal,qreal)));
53 53 //initialize
54 54 m_axisDomainMap.insert(axisY,domain);
55 55 emit axisAdded(axisY,domain);
56 56 }
57 57
58 58 if(!m_axisXInitialized){
59 59 emit axisAdded(axisX(),domain);
60 60 m_axisXInitialized=true;
61 61 }
62 62
63 63 calculateDomain(series,domain);
64 64
65 65 m_seriesAxisMap.insert(series,axisY);
66 66 emit seriesAdded(series,domain);
67 67
68 68 }
69 69
70 70 void ChartDataSet::removeSeries(QSeries* series)
71 71 {
72 72
73 73 QChartAxis* axis = m_seriesAxisMap.value(series);
74 74
75 75 if(!axis){
76 76 qWarning()<<"Can not remove series. Series not found on the chart.";
77 77 return;
78 78 }
79 79 emit seriesRemoved(series);
80 80 m_seriesAxisMap.remove(series);
81 81
82 82 if(series->parent()==this){
83 83 delete series;
84 84 series=0;
85 85 }
86 86
87 87 QList<QChartAxis*> axes = m_seriesAxisMap.values();
88 88
89 89 int i = axes.indexOf(axis);
90 90
91 91 if(i==-1){
92 92 Domain* domain = m_axisDomainMap.take(axis);
93 93 emit axisRemoved(axis);
94 94 if(axis!=axisY()){
95 95 if(axis->parent()==this){
96 96 delete axis;
97 97 axis=0;
98 98 }
99 99 }
100 100 delete domain;
101 101 }
102 102
103 103 if(m_seriesAxisMap.values().size()==0)
104 104 {
105 105 m_axisXInitialized=false;
106 106 emit axisRemoved(axisX());
107 107 }
108 108 }
109 109
110 110 void ChartDataSet::removeAllSeries()
111 111 {
112 112
113 113 QList<QSeries*> series = m_seriesAxisMap.keys();
114 114
115 115 foreach(QSeries* s , series) {
116 116 removeSeries(s);
117 117 }
118 118
119 119 Q_ASSERT(m_seriesAxisMap.count()==0);
120 120 Q_ASSERT(m_axisDomainMap.count()==0);
121 121
122 122 }
123 123
124 124 //to be removed with PIMPL
125 125 void ChartDataSet::calculateDomain(QSeries* series,Domain* domain) const
126 126 {
127 127 switch(series->type())
128 128 {
129 case QSeries::SeriesTypeLine: {
129 case QSeries::SeriesTypeLine:
130 case QSeries::SeriesTypeSpline:
131 case QSeries::SeriesTypeScatter:
132 {
130 133
131 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
134 QXYSeries* xySeries = static_cast<QXYSeries*>(series);
132 135
133 for (int i = 0; i < lineSeries->count(); i++)
136 qreal minX(domain->minX());
137 qreal minY(domain->minY());
138 qreal maxX(domain->maxX());
139 qreal maxY(domain->maxY());
140
141 for (int i = 0; i < xySeries->count(); i++)
134 142 {
135 qreal x = lineSeries->x(i);
136 qreal y = lineSeries->y(i);
143 qreal x = xySeries->x(i);
144 qreal y = xySeries->y(i);
145 minX = qMin(minX, x);
146 minY = qMin(minY, y);
147 maxX = qMax(maxX, x);
148 maxY = qMax(maxY, y);
137 149 domain->setMinX(qMin(domain->minX(),x));
138 150 domain->setMinY(qMin(domain->minY(),y));
139 151 domain->setMaxX(qMax(domain->maxX(),x));
140 152 domain->setMaxY(qMax(domain->maxY(),y));
141 153 }
142 154 break;
143 155 }
144 156 case QSeries::SeriesTypeArea: {
145 157
146 158 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
147 159
148 160 QLineSeries* upperSeries = areaSeries->upperSeries();
149 161 QLineSeries* lowerSeries = areaSeries->lowerSeries();
150 162
151 163 for (int i = 0; i < upperSeries->count(); i++)
152 164 {
153 165 qreal x = upperSeries->x(i);
154 166 qreal y = upperSeries->y(i);
155 167 domain->setMinX(qMin(domain->minX(),x));
156 168 domain->setMinY(qMin(domain->minY(),y));
157 169 domain->setMaxX(qMax(domain->maxX(),x));
158 170 domain->setMaxY(qMax(domain->maxY(),y));
159 171 }
160 172 if(lowerSeries) {
161 173 for (int i = 0; i < lowerSeries->count(); i++)
162 174 {
163 175 qreal x = lowerSeries->x(i);
164 176 qreal y = lowerSeries->y(i);
165 177 domain->setMinX(qMin(domain->minX(),x));
166 178 domain->setMinY(qMin(domain->minY(),y));
167 179 domain->setMaxX(qMax(domain->maxX(),x));
168 180 domain->setMaxY(qMax(domain->maxY(),y));
169 181 }}
170 182 break;
171 183 }
172 184 case QSeries::SeriesTypeBar: {
173 185 qDebug() << "QChartSeries::SeriesTypeBar";
174 186 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
175 187 qreal x = barSeries->categoryCount();
176 188 qreal y = barSeries->max();
177 189 domain->setMinX(qMin(domain->minX(),x));
178 190 domain->setMinY(qMin(domain->minY(),y));
179 191 domain->setMaxX(qMax(domain->maxX(),x));
180 192 domain->setMaxY(qMax(domain->maxY(),y));
181 193 break;
182 194 }
183 195 case QSeries::SeriesTypeStackedBar: {
184 196 qDebug() << "QChartSeries::SeriesTypeStackedBar";
185 197
186 198 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
187 199 qreal x = stackedBarSeries->categoryCount();
188 200 qreal y = stackedBarSeries->maxCategorySum();
189 201 domain->setMinX(qMin(domain->minX(),x));
190 202 domain->setMinY(qMin(domain->minY(),y));
191 203 domain->setMaxX(qMax(domain->maxX(),x));
192 204 domain->setMaxY(qMax(domain->maxY(),y));
193 205 break;
194 206 }
195 207 case QSeries::SeriesTypePercentBar: {
196 208 qDebug() << "QChartSeries::SeriesTypePercentBar";
197 209
198 210 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
199 211 qreal x = percentBarSeries->categoryCount();
200 212 domain->setMinX(qMin(domain->minX(),x));
201 213 domain->setMinY(0);
202 214 domain->setMaxX(qMax(domain->maxX(),x));
203 215 domain->setMaxY(100);
204 216 break;
205 217 }
206 218
207 219 case QSeries::SeriesTypePie: {
208 220 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
209 221 // TODO: domain stuff
210 222 break;
211 223 }
212 224
213 case QSeries::SeriesTypeScatter: {
214 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
215 Q_ASSERT(scatterSeries);
216 qreal minX(domain->minX());
217 qreal minY(domain->minY());
218 qreal maxX(domain->maxX());
219 qreal maxY(domain->maxY());
220 foreach (QPointF point, scatterSeries->data()) {
221 minX = qMin(minX, point.x());
222 minY = qMin(minY, point.y());
223 maxX = qMax(maxX, point.x());
224 maxY = qMax(maxY, point.y());
225 }
226 domain->setMinX(minX);
227 domain->setMinY(minY);
228 domain->setMaxX(maxX);
229 domain->setMaxY(maxY);
230 break;
231 }
232
233 case QSeries::SeriesTypeSpline: {
234 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
235
236 for (int i = 0; i < splineSeries->count(); i++)
237 {
238 qreal x = splineSeries->x(i);
239 qreal y = splineSeries->y(i);
240 domain->setMinX(qMin(domain->minX(),x));
241 domain->setMinY(qMin(domain->minY(),y));
242 domain->setMaxX(qMax(domain->maxX(),x));
243 domain->setMaxY(qMax(domain->maxY(),y));
244 }
245 break;
246 }
247 225
248 226 default: {
249 227 qDebug()<<__FUNCTION__<<"type" << series->type()<<"not supported";
250 228 return;
251 229 break;
252 230 }
253 231
254 232 }
255 233 }
256 234
257 235 void ChartDataSet::zoomInDomain(const QRectF& rect, const QSizeF& size)
258 236 {
259 237 QMapIterator<QChartAxis*, Domain*> i( m_axisDomainMap);
260 238 while (i.hasNext()) {
261 239 i.next();
262 240 i.value()->zoomIn(rect,size);
263 241 }
264 242 }
265 243
266 244 void ChartDataSet::zoomOutDomain(const QRectF& rect, const QSizeF& size)
267 245 {
268 246 QMapIterator<QChartAxis*, Domain*> i( m_axisDomainMap);
269 247 while (i.hasNext()) {
270 248 i.next();
271 249 i.value()->zoomOut(rect,size);
272 250 }
273 251 }
274 252
275 253 QChartAxis* ChartDataSet::axisY(QSeries* series) const
276 254 {
277 255 if(series == 0) return m_axisY;
278 256 return m_seriesAxisMap.value(series);
279 257 }
280 258
281 259 Domain* ChartDataSet::domain(QSeries* series) const
282 260 {
283 261 QChartAxis* axis = m_seriesAxisMap.value(series);
284 262 if(axis){
285 263 return m_axisDomainMap.value(axis);
286 264 }else
287 265 return 0;
288 266 }
289 267
290 268 Domain* ChartDataSet::domain(QChartAxis* axis) const
291 269 {
292 270 if(axis==axisX()) {
293 271 return m_axisDomainMap.value(axisY());
294 272 }
295 273 else {
296 274 return m_axisDomainMap.value(axis);
297 275 }
298 276 }
299 277
300 278 QChartAxis* ChartDataSet::axis(QSeries* series) const
301 279 {
302 280 return m_seriesAxisMap.value(series);
303 281 }
304 282
305 283 #include "moc_chartdataset_p.cpp"
306 284
307 285 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,371 +1,371
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 "qbarseries.h"
8 8 #include "qstackedbarseries.h"
9 9 #include "qpercentbarseries.h"
10 10 #include "qlineseries.h"
11 11 #include "qareaseries.h"
12 12 #include "qpieseries.h"
13 13 #include "qscatterseries.h"
14 14 #include "qsplineseries.h"
15 15 //items
16 16 #include "axisitem_p.h"
17 17 #include "axisanimationitem_p.h"
18 18 #include "areachartitem_p.h"
19 19 #include "barpresenter_p.h"
20 20 #include "stackedbarpresenter_p.h"
21 21 #include "percentbarpresenter_p.h"
22 22 #include "linechartitem_p.h"
23 23 #include "linechartanimationitem_p.h"
24 24 #include "piepresenter_p.h"
25 #include "scatterpresenter_p.h"
25 #include "scatterchartitem_p.h"
26 26 #include "splinechartitem_p.h"
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
31 31 m_chart(chart),
32 32 m_dataset(dataset),
33 33 m_chartTheme(0),
34 34 m_zoomIndex(0),
35 35 m_marginSize(0),
36 36 m_rect(QRectF(QPoint(0,0),m_chart->size())),
37 37 m_options(QChart::NoAnimation)
38 38 {
39 39 createConnections();
40 40 setChartTheme(QChart::ChartThemeDefault);
41 41 }
42 42
43 43 ChartPresenter::~ChartPresenter()
44 44 {
45 45 }
46 46
47 47 void ChartPresenter::createConnections()
48 48 {
49 49 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
50 50 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
51 51 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
52 52 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
53 53 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
54 54 }
55 55
56 56
57 57 QRectF ChartPresenter::geometry() const
58 58 {
59 59 return m_rect;
60 60 }
61 61
62 62 void ChartPresenter::handleGeometryChanged()
63 63 {
64 64 QRectF rect(QPoint(0,0),m_chart->size());
65 65 rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
66 66
67 67 //rewrite zoom stack
68 68 for(int i=0;i<m_zoomStack.count();i++){
69 69 QRectF r = m_zoomStack[i];
70 70 qreal w = rect.width()/m_rect.width();
71 71 qreal h = rect.height()/m_rect.height();
72 72 QPointF tl = r.topLeft();
73 73 tl.setX(tl.x()*w);
74 74 tl.setY(tl.y()*h);
75 75 QPointF br = r.bottomRight();
76 76 br.setX(br.x()*w);
77 77 br.setY(br.y()*h);
78 78 r.setTopLeft(tl);
79 79 r.setBottomRight(br);
80 80 m_zoomStack[i]=r;
81 81 }
82 82
83 83 m_rect = rect;
84 84 Q_ASSERT(m_rect.isValid());
85 85 emit geometryChanged(m_rect);
86 86 }
87 87
88 88 int ChartPresenter::margin() const
89 89 {
90 90 return m_marginSize;
91 91 }
92 92
93 93 void ChartPresenter::setMargin(int margin)
94 94 {
95 95 m_marginSize = margin;
96 96 }
97 97
98 98 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
99 99 {
100 100
101 101 AxisItem* item ;
102 102
103 103 if(!m_options.testFlag(QChart::GridAxisAnimations))
104 104 {
105 105 item = new AxisItem(axis,axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
106 106 }else{
107 107 item = new AxisAnimationItem(axis,axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
108 108 }
109 109 if(axis==m_dataset->axisX()){
110 110 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal)),item,SLOT(handleRangeChanged(qreal,qreal)));
111 111 //initialize
112 112 item->handleRangeChanged(domain->minX(),domain->maxX());
113 113 item->handleTicksCountChanged(4);
114 114 }
115 115 else{
116 116 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal)),item,SLOT(handleRangeChanged(qreal,qreal)));
117 117 //initialize
118 118 item->handleRangeChanged(domain->minY(),domain->maxY());
119 119 item->handleTicksCountChanged(4);
120 120 }
121 121
122 122 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
123 123 //initialize
124 124 item->handleGeometryChanged(m_rect);
125 125 m_chartTheme->decorate(axis,item);
126 126 m_axisItems.insert(axis,item);
127 127 }
128 128
129 129 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
130 130 {
131 131 AxisItem* item = m_axisItems.take(axis);
132 132 Q_ASSERT(item);
133 133 delete item;
134 134 }
135 135
136 136
137 137 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
138 138 {
139 139 switch(series->type())
140 140 {
141 141 case QSeries::SeriesTypeLine: {
142 142
143 143 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
144 144 LineChartItem* item;
145 145 if(m_options.testFlag(QChart::SeriesAnimations)){
146 146 item = new LineChartAnimationItem(lineSeries,m_chart);
147 147 }else{
148 148 item = new LineChartItem(lineSeries,m_chart);
149 149 }
150 150 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
151 151 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),item,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
152 152 //initialize
153 153 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
154 154 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
155 155 //decorate
156 156 m_chartTheme->decorate(item,lineSeries,m_chartItems.count());
157 157 m_chartItems.insert(series,item);
158 158 break;
159 159 }
160 160
161 161 case QSeries::SeriesTypeArea: {
162 162
163 163 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
164 164 AreaChartItem* item;
165 165 if(m_options.testFlag(QChart::SeriesAnimations)) {
166 166 item = new AreaChartItem(areaSeries,m_chart);
167 167 }
168 168 else {
169 169 item = new AreaChartItem(areaSeries,m_chart);
170 170 }
171 171 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
172 172 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),item,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
173 173 //initialize
174 174 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
175 175 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
176 176 //decorate
177 177 m_chartTheme->decorate(item,areaSeries,m_chartItems.count());
178 178 m_chartItems.insert(series,item);
179 179 break;
180 180 }
181 181
182 182 case QSeries::SeriesTypeBar: {
183 183 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
184 184 BarPresenter* item = new BarPresenter(barSeries,m_chart);
185 185 m_chartTheme->decorate(item,barSeries,m_chartItems.count());
186 186 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
187 187 // QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
188 188 m_chartItems.insert(series,item);
189 189 // m_axisXItem->setVisible(false);
190 190 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
191 191 break;
192 192 }
193 193
194 194 case QSeries::SeriesTypeStackedBar: {
195 195
196 196 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
197 197 StackedBarPresenter* item = new StackedBarPresenter(stackedBarSeries,m_chart);
198 198 m_chartTheme->decorate(item,stackedBarSeries,m_chartItems.count());
199 199 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
200 200 // QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
201 201 m_chartItems.insert(series,item);
202 202 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
203 203 break;
204 204 }
205 205
206 206 case QSeries::SeriesTypePercentBar: {
207 207
208 208 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
209 209 PercentBarPresenter* item = new PercentBarPresenter(percentBarSeries,m_chart);
210 210 m_chartTheme->decorate(item,percentBarSeries ,m_chartItems.count());
211 211 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
212 212 // QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
213 213 m_chartItems.insert(series,item);
214 214 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
215 215 break;
216 216 }
217 217 case QSeries::SeriesTypeScatter: {
218 218 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
219 ScatterPresenter *scatterPresenter = new ScatterPresenter(scatterSeries, m_chart);
219 ScatterChartItem *scatterPresenter = new ScatterChartItem(scatterSeries, m_chart);
220 220 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)),
221 221 scatterPresenter, SLOT(handleGeometryChanged(const QRectF&)));
222 222 QObject::connect(domain, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),
223 223 scatterPresenter, SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
224 224 m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
225 225 m_chartItems.insert(scatterSeries, scatterPresenter);
226 226 if (m_rect.isValid())
227 227 scatterPresenter->handleGeometryChanged(m_rect);
228 228 scatterPresenter->handleDomainChanged(domain->minX(), domain->maxX(), domain->minY(), domain->maxY());
229 229 break;
230 230 }
231 231 case QSeries::SeriesTypePie: {
232 232 QPieSeries *s = qobject_cast<QPieSeries *>(series);
233 233 PiePresenter* pie = new PiePresenter(m_chart, s);
234 234 m_chartTheme->decorate(pie, s, m_chartItems.count());
235 235 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), pie, SLOT(handleGeometryChanged(const QRectF&)));
236 236
237 237 // Hide all from background when there is only piechart
238 238 // TODO: refactor this ugly code... should be one setting for this
239 239 if (m_chartItems.count() == 0) {
240 240 m_chart->axisX()->setAxisVisible(false);
241 241 m_chart->axisY()->setAxisVisible(false);
242 242 m_chart->axisX()->setGridVisible(false);
243 243 m_chart->axisY()->setGridVisible(false);
244 244 m_chart->axisX()->setLabelsVisible(false);
245 245 m_chart->axisY()->setLabelsVisible(false);
246 246 m_chart->axisX()->setShadesVisible(false);
247 247 m_chart->axisY()->setShadesVisible(false);
248 248 m_chart->setChartBackgroundBrush(Qt::transparent);
249 249 }
250 250
251 251 m_chartItems.insert(series, pie);
252 252 pie->handleGeometryChanged(m_rect);
253 253 break;
254 254 }
255 255
256 256 case QSeries::SeriesTypeSpline: {
257 257 QSplineSeries* splineSeries = qobject_cast<QSplineSeries*>(series);
258 258 SplineChartItem* splinePresenter = new SplineChartItem(splineSeries, m_chart);
259 259 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), splinePresenter, SLOT(handleGeometryChanged(const QRectF&)));
260 260 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),splinePresenter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
261 261 //initialize
262 262 splinePresenter->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
263 263 m_chartTheme->decorate(splinePresenter, splineSeries, m_chartItems.count());
264 264 m_chartItems.insert(splineSeries, splinePresenter);
265 265 break;
266 266 }
267 267 default: {
268 268 qDebug()<< "Series type" << series->type() << "not implemented.";
269 269 break;
270 270 }
271 271 }
272 272
273 273 zoomReset();
274 274 }
275 275
276 276 void ChartPresenter::handleSeriesRemoved(QSeries* series)
277 277 {
278 278 ChartItem* item = m_chartItems.take(series);
279 279 delete item;
280 280 }
281 281
282 282 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
283 283 {
284 284 delete m_chartTheme;
285 285
286 286 m_chartTheme = ChartTheme::createTheme(theme);
287 287
288 288 m_chartTheme->decorate(m_chart);
289 289 QMapIterator<QSeries*,ChartItem*> i(m_chartItems);
290 290
291 291 int index=0;
292 292 while (i.hasNext()) {
293 293 i.next();
294 294 m_chartTheme->decorate(i.value(),i.key(),index);
295 295 index++;
296 296 }
297 297
298 298 QMapIterator<QChartAxis*,AxisItem*> j(m_axisItems);
299 299 while (j.hasNext()) {
300 300 j.next();
301 301 m_chartTheme->decorate(j.key(),j.value());
302 302 }
303 303 }
304 304
305 305 QChart::ChartTheme ChartPresenter::chartTheme()
306 306 {
307 307 return m_chartTheme->id();
308 308 }
309 309
310 310 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
311 311 {
312 312 if(m_options!=options) {
313 313
314 314 m_options=options;
315 315
316 316 //recreate elements
317 317 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
318 318 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
319 319
320 320 foreach(QChartAxis* axis, axisList) {
321 321 handleAxisRemoved(axis);
322 322 handleAxisAdded(axis,m_dataset->domain(axis));
323 323 }
324 324 foreach(QSeries* series, seriesList) {
325 325 handleSeriesRemoved(series);
326 326 handleSeriesAdded(series,m_dataset->domain(series));
327 327 }
328 328 }
329 329 }
330 330
331 331 void ChartPresenter::zoomIn()
332 332 {
333 333 QRectF rect = geometry();
334 334 rect.setWidth(rect.width()/2);
335 335 rect.setHeight(rect.height()/2);
336 336 rect.moveCenter(geometry().center());
337 337 zoomIn(rect);
338 338 }
339 339
340 340 void ChartPresenter::zoomIn(const QRectF& rect)
341 341 {
342 342 QRectF r = rect.normalized();
343 343 r.translate(-m_marginSize, -m_marginSize);
344 344 m_dataset->zoomInDomain(r,geometry().size());
345 345 m_zoomStack<<r;
346 346 m_zoomIndex++;
347 347 }
348 348
349 349 void ChartPresenter::zoomOut()
350 350 {
351 351 if(m_zoomIndex==0) return;
352 352 m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
353 353 m_zoomIndex--;
354 354 m_zoomStack.resize(m_zoomIndex);
355 355 }
356 356
357 357 void ChartPresenter::zoomReset()
358 358 {
359 359 m_zoomIndex=0;
360 360 m_zoomStack.resize(m_zoomIndex);
361 361 }
362 362
363 363 QChart::AnimationOptions ChartPresenter::animationOptions() const
364 364 {
365 365 return m_options;
366 366 }
367 367
368 368
369 369 #include "moc_chartpresenter_p.cpp"
370 370
371 371 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,328 +1,328
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 3 #include "qchartaxis.h"
4 4 #include <QTime>
5 5
6 6 //series
7 7 #include "qbarset.h"
8 8 #include "qbarseries.h"
9 9 #include "qstackedbarseries.h"
10 10 #include "qpercentbarseries.h"
11 11 #include "qlineseries.h"
12 12 #include "qareaseries.h"
13 13 #include "qscatterseries.h"
14 14 #include "qpieseries.h"
15 15 #include "qpieslice.h"
16 16 #include "qsplineseries.h"
17 17
18 18 //items
19 19 #include "axisitem_p.h"
20 20 #include "barpresenter_p.h"
21 21 #include "stackedbarpresenter_p.h"
22 22 #include "percentbarpresenter_p.h"
23 23 #include "linechartitem_p.h"
24 24 #include "areachartitem_p.h"
25 #include "scatterpresenter_p.h"
25 #include "scatterchartitem_p.h"
26 26 #include "piepresenter_p.h"
27 27 #include "splinechartitem_p.h"
28 28
29 29 //themes
30 30 #include "chartthemevanilla_p.h"
31 31 #include "chartthemeicy_p.h"
32 32 #include "chartthemegrayscale_p.h"
33 33 #include "chartthemescientific_p.h"
34 34
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 /* TODO
39 39 case QChart::ChartThemeUnnamed1:
40 40 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff3fa9f5)), 2));
41 41 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff7AC943)), 2));
42 42 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF931E)), 2));
43 43 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF1D25)), 2));
44 44 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF7BAC)), 2));
45 45
46 46 m_gradientStartColor = QColor(QRgb(0xfff3dc9e));
47 47 m_gradientEndColor = QColor(QRgb(0xffafafaf));
48 48 */
49 49
50 50 ChartTheme::ChartTheme(QChart::ChartTheme id)
51 51 {
52 52 m_id = id;
53 53 m_seriesColor.append(QRgb(0xff000000));
54 54 m_seriesColor.append(QRgb(0xff707070));
55 55 m_gradientStartColor = QColor(QRgb(0xffffffff));
56 56 m_gradientEndColor = QColor(QRgb(0xffafafaf));
57 57
58 58 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
59 59 }
60 60
61 61
62 62 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
63 63 {
64 64 switch(theme) {
65 65 case QChart::ChartThemeDefault:
66 66 return new ChartTheme();
67 67 case QChart::ChartThemeVanilla:
68 68 return new ChartThemeVanilla();
69 69 case QChart::ChartThemeIcy:
70 70 return new ChartThemeIcy();
71 71 case QChart::ChartThemeGrayscale:
72 72 return new ChartThemeGrayscale();
73 73 case QChart::ChartThemeScientific:
74 74 return new ChartThemeScientific();
75 75 }
76 76 }
77 77
78 78 void ChartTheme::decorate(QChart* chart)
79 79 {
80 80 QLinearGradient backgroundGradient;
81 81 backgroundGradient.setColorAt(0.0, m_gradientStartColor);
82 82 backgroundGradient.setColorAt(1.0, m_gradientEndColor);
83 83 backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
84 84 chart->setChartBackgroundBrush(backgroundGradient);
85 85 }
86 86 //TODO helper to by removed later
87 87 void ChartTheme::decorate(ChartItem* item, QSeries* series,int count)
88 88 {
89 89 switch(series->type())
90 90 {
91 91 case QSeries::SeriesTypeLine: {
92 92 QLineSeries* s = static_cast<QLineSeries*>(series);
93 93 LineChartItem* i = static_cast<LineChartItem*>(item);
94 94 decorate(i,s,count);
95 95 break;
96 96 }
97 97 case QSeries::SeriesTypeArea: {
98 98 QAreaSeries* s = static_cast<QAreaSeries*>(series);
99 99 AreaChartItem* i = static_cast<AreaChartItem*>(item);
100 100 decorate(i,s,count);
101 101 break;
102 102 }
103 103 case QSeries::SeriesTypeBar: {
104 104 QBarSeries* b = static_cast<QBarSeries*>(series);
105 105 BarPresenter* i = static_cast<BarPresenter*>(item);
106 106 decorate(i,b,count);
107 107 break;
108 108 }
109 109 case QSeries::SeriesTypeStackedBar: {
110 110 QStackedBarSeries* s = static_cast<QStackedBarSeries*>(series);
111 111 StackedBarPresenter* i = static_cast<StackedBarPresenter*>(item);
112 112 decorate(i,s,count);
113 113 break;
114 114 }
115 115 case QSeries::SeriesTypePercentBar: {
116 116 QPercentBarSeries* s = static_cast<QPercentBarSeries*>(series);
117 117 PercentBarPresenter* i = static_cast<PercentBarPresenter*>(item);
118 118 decorate(i,s,count);
119 119 break;
120 120 }
121 121 case QSeries::SeriesTypeScatter: {
122 122 QScatterSeries* s = qobject_cast<QScatterSeries*>(series);
123 123 Q_ASSERT(s);
124 ScatterPresenter* i = static_cast<ScatterPresenter*>(item);
124 ScatterChartItem* i = static_cast<ScatterChartItem*>(item);
125 125 Q_ASSERT(i);
126 126 decorate(i, s, count);
127 127 break;
128 128 }
129 129 case QSeries::SeriesTypePie: {
130 130 QPieSeries* s = static_cast<QPieSeries*>(series);
131 131 PiePresenter* i = static_cast<PiePresenter*>(item);
132 132 decorate(i,s,count);
133 133 break;
134 134 }
135 135 default:
136 136 qDebug()<<"Wrong item to be decorated by theme";
137 137 break;
138 138 }
139 139
140 140 }
141 141
142 142 void ChartTheme::decorate(AreaChartItem* item, QAreaSeries* series,int count)
143 143 {
144 144 QPen pen;
145 145 QBrush brush;
146 146
147 147 if(pen != series->pen()){
148 148 item->setPen(series->pen());
149 149 }else{
150 150 pen.setColor(m_seriesColor.at(count%m_seriesColor.size()));
151 151 pen.setWidthF(2);
152 152 item->setPen(pen);
153 153 }
154 154
155 155 if(brush != series->brush()){
156 156 item->setBrush(series->brush());
157 157 }else{
158 158 QBrush brush(m_seriesColor.at(count%m_seriesColor.size()));
159 159 item->setBrush(brush);
160 160 }
161 161 }
162 162
163 163
164 164 void ChartTheme::decorate(LineChartItem* item, QLineSeries* series,int count)
165 165 {
166 166 QPen pen;
167 167 if(pen != series->pen()){
168 168 item->setPen(series->pen());
169 169 return;
170 170 }
171 171 pen.setColor(m_seriesColor.at(count%m_seriesColor.size()));
172 172 pen.setWidthF(2);
173 173 item->setPen(pen);
174 174 }
175 175
176 176 void ChartTheme::decorate(BarPresenter* item, QBarSeries* series,int count)
177 177 {
178 178 QList<QBarSet*> sets = series->barSets();
179 179 for (int i=0; i<series->barsetCount(); i++) {
180 180 sets.at(i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
181 181 }
182 182 }
183 183
184 184 void ChartTheme::decorate(StackedBarPresenter* item, QStackedBarSeries* series,int count)
185 185 {
186 186 QList<QBarSet*> sets = series->barSets();
187 187 for (int i=0; i<series->barsetCount(); i++) {
188 188 sets.at(i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
189 189 }
190 190 }
191 191
192 192 void ChartTheme::decorate(PercentBarPresenter* item, QPercentBarSeries* series,int count)
193 193 {
194 194 QList<QBarSet*> sets = series->barSets();
195 195 for (int i=0; i<series->barsetCount(); i++) {
196 196 sets.at(i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
197 197 }
198 198 }
199 199
200 void ChartTheme::decorate(ScatterPresenter* presenter, QScatterSeries* series, int count)
200 void ChartTheme::decorate(ScatterChartItem* item, QScatterSeries* series, int count)
201 201 {
202 Q_ASSERT(presenter);
202 Q_ASSERT(item);
203 203 Q_ASSERT(series);
204 204
205 205 QColor color = m_seriesColor.at(count % m_seriesColor.size());
206 206 // TODO: define alpha in the theme? or in the series?
207 207 //color.setAlpha(120);
208 208
209 209 QBrush brush(color, Qt::SolidPattern);
210 presenter->m_markerBrush = brush;
210 item->setBrush(Qt::blue);
211 211
212 212 QPen pen(brush, 3);
213 213 pen.setColor(color);
214 presenter->m_markerPen = pen;
214 item->setPen(pen);
215 215 }
216 216
217 217 void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int /*count*/)
218 218 {
219 219 // create a list of slice colors based on current theme
220 220 int i = 0;
221 221 QList<QColor> colors;
222 222 while (colors.count() < series->count()) {
223 223
224 224 // get base color
225 225 QColor c = m_seriesColor[i++];
226 226 i = i % m_seriesColor.count();
227 227
228 228 // dont use black colors... looks bad
229 229 if (c == Qt::black)
230 230 continue;
231 231
232 232 // by default use the "raw" theme color
233 233 if (!colors.contains(c)) {
234 234 colors << c;
235 235 continue;
236 236 }
237 237 // ...ok we need to generate something that looks like the same color
238 238 // but different lightness
239 239
240 240 int tryCount = 0;
241 241 while (tryCount++ < 100) {
242 242
243 243 // find maximum value we can raise the lightness
244 244 int lMax = 255;
245 245 if (lMax > 255 - c.red())
246 246 lMax = 255 - c.red();
247 247 if (lMax > 255 - c.green())
248 248 lMax = 255 - c.green();
249 249 if (lMax > 255 - c.blue())
250 250 lMax = 255 - c.blue();
251 251
252 252 // find maximum value we can make it darker
253 253 int dMax = 255;
254 254 if (dMax > c.red())
255 255 dMax = c.red();
256 256 if (dMax > c.green())
257 257 dMax = c.green();
258 258 if (dMax > c.blue())
259 259 dMax = c.blue();
260 260
261 261 int max = dMax + lMax;
262 262 if (max == 0) {
263 263 // no room to make color lighter or darker...
264 264 qDebug() << "cannot generate a color for pie!";
265 265 break;
266 266 }
267 267
268 268 // generate random color
269 269 int r = c.red() - dMax;
270 270 int g = c.green() - dMax;
271 271 int b = c.blue() - dMax;
272 272 int d = qrand() % max;
273 273 c.setRgb(r+d, g+d, b+d);
274 274
275 275 // found a unique color?
276 276 if (!colors.contains(c))
277 277 break;
278 278 }
279 279
280 280 qDebug() << "generated a color for pie" << c;
281 281 colors << c;
282 282 }
283 283
284 284 // finally update colors
285 285 foreach (QPieSlice* s, series->slices()) {
286 286 QColor c = colors.takeFirst();
287 287 s->setSlicePen(c);
288 288 s->setSliceBrush(c);
289 289 }
290 290 }
291 291
292 292
293 293 void ChartTheme::decorate(QChartAxis* axis,AxisItem* item)
294 294 {
295 295 //TODO: dummy defults for now
296 296 axis->setLabelsBrush(Qt::black);
297 297 axis->setLabelsPen(Qt::NoPen);
298 298 axis->setShadesPen(Qt::NoPen);
299 299 axis->setShadesOpacity(0.5);
300 300 }
301 301
302 302 void ChartTheme::decorate(SplineChartItem* item, QSplineSeries* series, int count)
303 303 {
304 304 Q_ASSERT(item);
305 305 Q_ASSERT(series);
306 306
307 307 QPen pen;
308 308 if(pen != series->pen()){
309 309 item->setPen(series->pen());
310 310 return;
311 311 }
312 312 pen.setColor(m_seriesColor.at(count%m_seriesColor.size()));
313 313 pen.setWidthF(series->pen().widthF());
314 314 item->setPen(pen);
315 315
316 316 // QColor color = m_seriesColor.at(count % m_seriesColor.size());
317 317 // TODO: define alpha in the theme? or in the series?
318 318 //color.setAlpha(120);
319 319
320 320 // QBrush brush(color, Qt::SolidPattern);
321 321 // presenter->m_markerBrush = brush;
322 322
323 323 // QPen pen(brush, 3);
324 324 // pen.setColor(color);
325 325 // presenter->m_markerPen = pen;
326 326 }
327 327
328 328 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,58 +1,58
1 1 #ifndef CHARTTHEME_H
2 2 #define CHARTTHEME_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qchart.h"
6 6 #include <QColor>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 10 class ChartItem;
11 11 class QSeries;
12 12 class LineChartItem;
13 13 class QLineSeries;
14 14 class BarPresenter;
15 15 class QBarSeries;
16 16 class StackedBarPresenter;
17 17 class QStackedBarSeries;
18 18 class QPercentBarSeries;
19 19 class PercentBarPresenter;
20 20 class QScatterSeries;
21 class ScatterPresenter;
21 class ScatterChartItem;
22 22 class PiePresenter;
23 23 class QPieSeries;
24 24 class SplineChartItem;
25 25 class QSplineSeries;
26 26 class AreaChartItem;
27 27 class QAreaSeries;
28 28
29 29 class ChartTheme
30 30 {
31 31 protected:
32 32 explicit ChartTheme(QChart::ChartTheme id = QChart::ChartThemeDefault);
33 33 public:
34 34 static ChartTheme* createTheme(QChart::ChartTheme theme);
35 35 QChart::ChartTheme id() const {return m_id;}
36 36 void decorate(QChart* chart);
37 37 void decorate(ChartItem* item, QSeries* series,int count);
38 38 void decorate(BarPresenter* item, QBarSeries* series,int count);
39 39 void decorate(StackedBarPresenter* item, QStackedBarSeries* series,int count);
40 40 void decorate(PercentBarPresenter* item, QPercentBarSeries* series,int count);
41 41 void decorate(LineChartItem* item, QLineSeries* series,int count);
42 42 void decorate(AreaChartItem* item, QAreaSeries* series,int count);
43 void decorate(ScatterPresenter* presenter, QScatterSeries* series, int count);
43 void decorate(ScatterChartItem* presenter, QScatterSeries* series, int count);
44 44 void decorate(PiePresenter* item, QPieSeries* series, int count);
45 45 void decorate(QChartAxis* axis,AxisItem* item);
46 46 void decorate(SplineChartItem* presenter, QSplineSeries* series, int count);
47 47
48 48 protected:
49 49 QChart::ChartTheme m_id;
50 50 QColor m_gradientStartColor;
51 51 QColor m_gradientEndColor;
52 52 QList<QColor> m_seriesColor;
53 53
54 54 };
55 55
56 56 QTCOMMERCIALCHART_END_NAMESPACE
57 57
58 58 #endif // CHARTTHEME_H
@@ -1,50 +1,51
1 1 #ifndef LINECHARTITEM_H
2 2 #define LINECHARTITEM_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "xychartitem_p.h"
6 6 #include <QPen>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 10 class ChartPresenter;
11 11 class QLineSeries;
12 12
13 13 class LineChartItem : public XYChartItem
14 14 {
15 15 Q_OBJECT
16 16 public:
17 LineChartItem(QLineSeries* series,QGraphicsItem *parent = 0);
17 explicit LineChartItem(QLineSeries* series,QGraphicsItem *parent = 0);
18 18 ~ LineChartItem(){};
19 19
20 20 //from QGraphicsItem
21 21 QRectF boundingRect() const;
22 22 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
23 23 QPainterPath shape() const;
24 24
25 25 void setPen(const QPen& pen);
26 26 void setPointsVisible(bool visible);
27 27
28 void createPoints(int count);
29 void deletePoints(int count);
30
31 28 public slots:
32 29 void handleUpdated();
33 30
34 31 protected:
35 32 virtual void setGeometry(QVector<QPointF>& points);
36 33
37 34 private:
35 void createPoints(int count);
36 void deletePoints(int count);
37
38 private:
38 39 QLineSeries* m_series;
39 40 QGraphicsItemGroup m_items;
40 41 QPainterPath m_path;
41 42 QRectF m_rect;
42 43 QPen m_pen;
43 44
44 45 friend class LineChartAnimatator;
45 46
46 47 };
47 48
48 49 QTCOMMERCIALCHART_END_NAMESPACE
49 50
50 51 #endif
@@ -1,94 +1,98
1 1 #include "qlineseries.h"
2 2
3 3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4 4
5 5 /*!
6 6 \class QLineSeries
7 7 \brief The QLineSeries class is used for making line charts.
8 8
9 9 \mainclass
10 10
11 11 A line chart is used to show information as a series of data points
12 12 connected by straight lines.
13 13
14 14 \image linechart.png
15 15
16 16 Creating basic line chart is simple:
17 17 \code
18 18 QLineSeries* series = new QLineSeries();
19 19 series->add(0, 6);
20 20 series->add(2, 4);
21 21 ...
22 22 chartView->addSeries(series);
23 23 \endcode
24 24 */
25 25
26 26 /*!
27 27 \fn virtual QSeriesType QLineSeries::type() const
28 28 \brief Returns type of series.
29 29 \sa QSeries, QSeriesType
30 30 */
31 31
32 32 /*!
33 \fn QPen QLineSeries::pen() const
34 \brief Returns the pen used to draw line for this series.
35 \sa setPen()
36 */
37
38 /*!
39 \fn bool QLineSeries::pointsVisible() const
33 \fn bool QLineSeries::pointsVisible() const
40 34 \brief Returns if the points are drawn for this series.
41 35 \sa setPointsVisible()
42 36 */
43 37
44
45 /*!
46 \fn void QLineSeries::pointReplaced(int index)
47 \brief \internal \a index
48 */
49
50 38 /*!
51 \fn void QLineSeries::pointAdded(int index)
52 \brief \internal \a index
39 \fn QPen QLineSeries::linePen() const
40 \brief Returns the pen used to draw line connecting points.
41 \sa setPen()
53 42 */
54 43
55 44 /*!
56 \fn void QLineSeries::pointRemoved(int index)
57 \brief \internal \a index
45 Constructs empty series object which is a child of \a parent.
46 When series object is added to QChartView or QChart instance ownerships is transfered.
58 47 */
48 QLineSeries::QLineSeries(QObject* parent):QXYSeries(parent),
49 m_pointsVisible(false)
50 {
59 51
52 }
60 53 /*!
61 \fn void QLineSeries::updated()
62 \brief \internal
54 Destroys the object. Series added to QChartView or QChart instances are owned by those,
55 and are deleted when mentioned object are destroyed.
63 56 */
57 QLineSeries::~QLineSeries()
58 {
59 }
64 60
65 61 /*!
66 Constructs empty series object which is a child of \a parent.
67 When series object is added to QChartView or QChart instance ownerships is transfered.
62 Sets \a pen used for drawing line connecting points.
68 63 */
69 QLineSeries::QLineSeries(QObject* parent):QXYSeries(parent)
64 void QLineSeries::setLinePen(const QPen& pen)
70 65 {
66 if(pen!=m_pen){
67 m_pen=pen;
68 emit updated();
69 }
71 70 }
71
72 72 /*!
73 Destroys the object. Series added to QChartView or QChart instances are owned by those,
74 and are deleted when mentioned object are destroyed.
73 Sets if data points are \a visible and should be drawn on line.
75 74 */
76 QLineSeries::~QLineSeries()
75 void QLineSeries::setPointsVisible(bool visible)
77 76 {
77 if(m_pointsVisible!=visible){
78 m_pointsVisible=visible;
79 emit updated();
80 }
78 81 }
79 82
83
80 84 QDebug operator<< (QDebug debug, const QLineSeries series)
81 85 {
82 86 Q_ASSERT(series.m_x.size() == series.m_y.size());
83 87
84 88 int size = series.m_x.size();
85 89
86 90 for (int i=0;i<size;i++) {
87 91 debug.nospace() << "(" << series.m_x.at(i) << ','<< series.m_y.at(i) << ") ";
88 92 }
89 93 return debug.space();
90 94 }
91 95
92 96 #include "moc_qlineseries.cpp"
93 97
94 98 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,27 +1,36
1 1 #ifndef QLINESERIES_H_
2 2 #define QLINESERIES_H_
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qxyseries.h"
6 6 #include <QDebug>
7 7 #include <QPen>
8 8 #include <QBrush>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class QTCOMMERCIALCHART_EXPORT QLineSeries : public QXYSeries
13 13 {
14 14 Q_OBJECT
15 15 public:
16 16 QLineSeries(QObject* parent=0);
17 17 virtual ~QLineSeries();
18 18
19 void setLinePen(const QPen& pen);
20 QPen linePen() const {return m_pen;}
21
22 void setPointsVisible(bool visible);
23 bool pointsVisible() const {return m_pointsVisible;}
24
19 25 public: // from QChartSeries
20 26 virtual QSeriesType type() const {return QSeries::SeriesTypeLine;}
21 27 friend QDebug operator<< (QDebug d, const QLineSeries series);
28 private:
29 QPen m_pen;
30 bool m_pointsVisible;
22 31
23 32 };
24 33
25 34 QTCOMMERCIALCHART_END_NAMESPACE
26 35
27 36 #endif
@@ -1,305 +1,206
1 1 #include "qscatterseries.h"
2 #include "scatterseries_p.h"
3 2 #include "qchart.h"
4 3
5 4 /*!
6 5 \class QScatterSeries
7 6 \brief QtCommercial Chart series API for showing scatter series.
8 7
9 8 \mainclass
10 9
11 10 Example on how to create a chart with scatter series:
12 11 \snippet ../example/scatter/main.cpp 1
13 12
14 13 The example code would result the following:
15 14
16 15 \image scatter_example1.jpg
17 16
18 17 To customize the graphical representation of the series, you can modify pen, brush, shape and
19 18 size of the marker items. For example:
20 19
21 20 \snippet ../example/scatter/main.cpp 3
22 21
23 22 Would present your scatter markers as big rectangles with opaque, uglyish green outlines and
24 23 opaque red filling instead of the beatiful markers defined by the chart's theme:
25 24 \image scatter_example_custom.jpg
26 25 */
27 26
28 27 /*!
29 28 \enum QScatterSeries::MarkerShape
30 29
31 30 This enum describes the shape used when rendering marker items.
32 31
33 32 \value MarkerShapeDefault
34 33 \value MarkerShapeX
35 34 \value MarkerShapeRectangle
36 35 \value MarkerShapeRoundedRectangle
37 36 \value MarkerShapeTiltedRectangle
38 37 \value MarkerShapeTriangle
39 38 \value MarkerShapeCircle
40 39 */
41 40
42 41 /*!
43 42 \fn QChartSeriesType QScatterSeries::type() const
44 43 \brief Returns QChartSeries::SeriesTypeScatter.
45 44 */
46 45
47 46 /*!
48 47 \fn void QScatterSeries::clicked(QPointF coordinate)
49 48 User clicked the scatter series. Note that the \a coordinate is the chart coordinate that the
50 49 click occurred on; not necessarily a data point coordinate. To find the corresponding (closest)
51 50 data point you can use closestPoint().
52 51 */
53 52
54 53 QTCOMMERCIALCHART_BEGIN_NAMESPACE
55 54
56 QScatterSeriesPrivate::QScatterSeriesPrivate(QObject *parent) :
57 QObject(parent),
58 m_data(QList<QPointF>()),
59 m_markerPen(QPen(QColor::Invalid)),
60 m_markerBrush(QBrush(QColor::Invalid)),
61 m_markerShape(QScatterSeries::MarkerShapeDefault),
62 m_markerSize(9.0)
63 {
64 }
65
66 void QScatterSeriesPrivate::emitChanged()
67 {
68 emit changed();
69 }
70
71 #include "moc_scatterseries_p.cpp"
72
73 55 /*!
74 56 Constructs a series object which is a child of \a parent.
75 57 */
76 58 QScatterSeries::QScatterSeries(QObject *parent) :
77 QSeries(parent),
78 d(new QScatterSeriesPrivate(this))
59 QXYSeries(parent),
60 m_shape(QScatterSeries::MarkerShapeDefault),
61 m_size(9.0)
79 62 {
80 63 }
81 64
82 65 /*!
83 66 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
84 67 */
85 68 QScatterSeries::~QScatterSeries()
86 69 {
87 delete d;
88 70 }
89 71
90 /*!
91 Add single data point with \a x and \a y coordinates to the series.
92 */
93 void QScatterSeries::add(qreal x, qreal y)
94 {
95 d->m_data.append(QPointF(x, y));
96 d->emitChanged();
97 }
98
99 /*!
100 Add single data point with \a value to the series.
101 */
102 void QScatterSeries::add(QPointF value)
103 {
104 d->m_data.append(value);
105 d->emitChanged();
106 }
107 72
108 /*!
109 Add list of \a points to the series.
110 */
111 void QScatterSeries::add(QList<QPointF> points)
112 {
113 d->m_data.append(points);
114 d->emitChanged();
115 }
116 73
117 74 /*!
118 75 Stream operator for adding a data point with \a value to the series.
119 76 \sa add()
120 77
121 78 For example:
122 79 \snippet ../example/scatter/main.cpp 2
123 80 */
124 QScatterSeries& QScatterSeries::operator << (const QPointF &value)
125 {
126 d->m_data.append(value);
127 d->emitChanged();
128 return *this;
129 }
81
130 82
131 83 /*!
132 84 Stream operator for adding a list of points to the series.
133 85 \sa add()
134 86 */
135 QScatterSeries& QScatterSeries::operator << (QList<QPointF> value)
136 {
137 d->m_data.append(value);
138 d->emitChanged();
139 return *this;
140 }
87
141 88
142 89 /*!
143 90 Replaces the data of the series with the given list of data \a points.
144 91 */
145 void QScatterSeries::setData(QList<QPointF> points)
146 {
147 d->m_data = points;
148 d->emitChanged();
149 }
92
150 93
151 94 /*!
152 95 Returns the current list of data points of the series.
153 96 */
154 QList<QPointF> QScatterSeries::data()
155 {
156 return d->m_data;
157 }
158 97
159 98 /*!
160 99 Replaces the point at \a index with \a newPoint. Returns true if \a index is a valid position
161 100 in the series data, false otherwise.
162 101 */
163 bool QScatterSeries::replace(int index, QPointF newPoint)
164 {
165 if (index >= 0 && index < d->m_data.count()) {
166 d->m_data.replace(index, newPoint);
167 d->emitChanged();
168 return true;
169 }
170 return false;
171 }
102
172 103
173 104 /*!
174 105 Remove the data point at \a index. Returns true if a point was removed, false if the point
175 106 at \a index does not exist on the series.
176 107 */
177 bool QScatterSeries::removeAt(int index)
178 {
179 if (index >=0 && index < d->m_data.count()) {
180 d->m_data.removeAt(index);
181 d->emitChanged();
182 return true;
183 }
184 return false;
185 }
108
186 109
187 110 /*!
188 111 Remove all occurrences of \a point from the series and returns the number of points removed.
189 112 */
190 int QScatterSeries::removeAll(QPointF point)
191 {
192 int count = d->m_data.removeAll(point);
193 d->emitChanged();
194 return count;
195 }
113
196 114
197 115 /*!
198 116 Remove all data points from the series.
199 117 */
200 void QScatterSeries::clear()
201 {
202 d->m_data.clear();
203 d->emitChanged();
204 }
205 118
206 119 /*!
207 120 Returns the index of the data point that is closest to \a coordinate. If several data points
208 121 are at the same distance from the \a coordinate, returns the last one. If no points exist,
209 122 returns -1.
210 */
123
211 124 int QScatterSeries::closestPoint(QPointF coordinate)
212 125 {
213 126 qreal distance(-1);
214 127 int pointIndex(-1);
215 128 for (int i(0); i < d->m_data.count(); i++) {
216 129 QPointF dataPoint = d->m_data.at(i);
217 130 QPointF difference = dataPoint - coordinate;
218 131 if (i == 0 || difference.manhattanLength() <= distance) {
219 132 distance = difference.manhattanLength();
220 133 pointIndex = i;
221 134 }
222 135 }
223 136 return pointIndex;
224 137 }
138 */
225 139
226 140 /*!
227 141 Returns the pen used for drawing markers.
228 142 */
229 QPen QScatterSeries::pen() const
230 {
231 return d->m_markerPen;
232 }
143
233 144
234 145 /*!
235 146 Overrides the default pen used for drawing a marker item with a user defined \a pen. The
236 147 default pen is defined by chart theme setting.
237 148
238 149 \sa setBrush()
239 150 \sa QChart::setChartTheme()
240 151 */
241 void QScatterSeries::setPen(const QPen &pen)
242 {
243 d->m_markerPen = pen;
244 d->emitChanged();
245 }
152
246 153
247 154 /*!
248 155 Returns the brush used for drawing markers.
249 156 */
250 QBrush QScatterSeries::brush() const
251 {
252 return d->m_markerBrush;
253 }
157
254 158
255 159 /*!
256 160 Overrides the default brush of the marker items with a user defined \a brush. The default brush
257 161 is defined by chart theme setting.
258 162
259 163 \sa setPen()
260 164 \sa QChart::setChartTheme()
261 165 */
262 void QScatterSeries::setBrush(const QBrush &brush)
263 {
264 d->m_markerBrush = brush;
265 d->emitChanged();
266 }
267 166
268 167 /*!
269 168 Returns the shape used for drawing markers.
270 169 */
271 170 QScatterSeries::MarkerShape QScatterSeries::shape() const
272 171 {
273 return (QScatterSeries::MarkerShape) d->m_markerShape;
172 return (QScatterSeries::MarkerShape) m_shape;
274 173 }
275 174
276 175 /*!
277 176 Overrides the default shape of the marker items with a user defined \a shape. The default shape
278 177 is defined by chart theme setting.
279 178 */
280 179 void QScatterSeries::setShape(MarkerShape shape)
281 180 {
282 d->m_markerShape = shape;
283 d->emitChanged();
181 m_shape = shape;
182 emit updated();
284 183 }
285 184
286 185 /*!
287 186 Returns the size of the marker items.
288 187 */
289 188 qreal QScatterSeries::size() const
290 189 {
291 return d->m_markerSize;
190 return m_size;
292 191 }
293 192
294 193 /*!
295 194 Set the \a size of the marker items. The default size is 9.0.
296 195 */
297 196 void QScatterSeries::setSize(qreal size)
298 197 {
299 d->m_markerSize = size;
300 d->emitChanged();
198 m_size = size;
199 emit updated();
301 200 }
302 201
202
203
303 204 #include "moc_qscatterseries.cpp"
304 205
305 206 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,71 +1,54
1 1 #ifndef QSCATTERSERIES_H
2 2 #define QSCATTERSERIES_H
3 3
4 #include "qseries.h"
4 #include "qchartglobal.h"
5 #include "qxyseries.h"
5 6 #include <QRectF>
6 7 #include <QColor>
7 8
8 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 10 class QScatterSeriesPrivate;
10 11
11 class QTCOMMERCIALCHART_EXPORT QScatterSeries : public QSeries
12 class QTCOMMERCIALCHART_EXPORT QScatterSeries : public QXYSeries
12 13 {
13 14 Q_OBJECT
14 15
15 16 public:
16 17 enum MarkerShape {
17 18 // TODO: to be defined by the graphics design
18 19 // TODO: marker shapes: "x", star, rectangle, tilted rect, triangle, circle, dot
19 20 MarkerShapeDefault = 0,
20 21 MarkerShapeX,
21 22 MarkerShapeRectangle,
22 23 MarkerShapeRoundedRectangle,
23 24 MarkerShapeTiltedRectangle,
24 25 MarkerShapeTriangle,
25 26 MarkerShapeCircle
26 27 };
27 28
28 29 public:
29 30 QScatterSeries(QObject *parent = 0);
30 31 ~QScatterSeries();
31 32
32 33 public: // from QChartSeries
33 34 QSeriesType type() const { return QSeries::SeriesTypeScatter; }
34 35
35 36 public:
36 void add(qreal x, qreal y);
37 void add(QPointF value);
38 void add(QList<QPointF> points);
39 void setData(QList<QPointF> points);
40 QScatterSeries& operator << (const QPointF &value);
41 QScatterSeries& operator << (QList<QPointF> points);
42 QList<QPointF> data();
43 bool replace(int index, QPointF newPoint);
44 bool removeAt(int index);
45 int removeAll(QPointF point);
46 void clear();
47 int closestPoint(QPointF coordinate);
48 //TODO: insert, replace...?
37 //int closestPoint(QPointF coordinate);
49 38
50 QPen pen() const;
51 void setPen(const QPen &pen);
52 QBrush brush() const;
53 void setBrush(const QBrush &brush);
54 39 MarkerShape shape() const;
55 40 void setShape(MarkerShape shape);
56 41 qreal size() const;
57 42 void setSize(qreal size);
58 43
59 Q_SIGNALS:
44 signals:
60 45 void clicked(QPointF coordinate);
61 46
62 47 private:
63 Q_DECLARE_PRIVATE(QScatterSeries)
64 Q_DISABLE_COPY(QScatterSeries)
65 friend class ScatterPresenter;
66 QScatterSeriesPrivate *d;
48 MarkerShape m_shape;
49 qreal m_size;
67 50 };
68 51
69 52 QTCOMMERCIALCHART_END_NAMESPACE
70 53
71 54 #endif // QSCATTERSERIES_H
@@ -1,13 +1,12
1 1 INCLUDEPATH += $$PWD
2 2 DEPENDPATH += $$PWD
3 3
4 4 SOURCES += \
5 5 $$PWD/qscatterseries.cpp \
6 $$PWD/scatterpresenter.cpp
6 $$PWD/scatterchartitem.cpp
7 7
8 8 PRIVATE_HEADERS += \
9 $$PWD/scatterpresenter_p.h \
10 $$PWD/scatterseries_p.h
9 $$PWD/scatterchartitem_p.h
11 10
12 11 PUBLIC_HEADERS += \
13 12 $$PWD/qscatterseries.h
@@ -1,142 +1,142
1 1 #include "qsplineseries.h"
2 2
3 3 /*!
4 4 \class QSplineSeries
5 5 \brief Series type used to store data needed to draw a spline.
6 6
7 7 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
8 8 Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
9 9 */
10 10
11 11 /*!
12 12 \fn QSeriesType QSplineSeries::type() const
13 13 Returns the type of the series
14 14 */
15 15
16 16 /*!
17 17 \fn QSeriesType QSplineSeries::controlPoint(int index) const
18 18 Returns the control point specified by \a index
19 19 */
20 20
21 21 QTCOMMERCIALCHART_BEGIN_NAMESPACE
22 22
23 23 /*!
24 24 Constructs empty series object which is a child of \a parent.
25 25 When series object is added to QChartView or QChart instance then the ownerships is transfered.
26 26 */
27 27
28 28 QSplineSeries::QSplineSeries(QObject *parent) :
29 QXYSeries(parent)
29 QLineSeries(parent)
30 30 {
31 31 connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints()));
32 32 connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints()));
33 33 connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints()));
34 34 }
35 35
36 36 /*!
37 37 \internal
38 38 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
39 39 */
40 40 void QSplineSeries::calculateControlPoints()
41 41 {
42 42
43 43 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
44 44 // CPOL License
45 45
46 46 int n = m_x.size() - 1;
47 47 if (n == 1)
48 48 { // Special case: Bezier curve should be a straight line.
49 49 // firstControlPoints = new Point[1];
50 50 // 3P1 = 2P0 + P3
51 51 m_controlPoints.append(QPointF((2 * m_x[0] + m_x[1]) / 3, (2 * m_y[0] + m_y[1]) / 3));
52 52
53 53 // P2 = 2P1 P0
54 54 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_x[0], 2 * m_controlPoints[0].y() - m_y[0]));
55 55 return;
56 56 }
57 57
58 58 // Calculate first Bezier control points
59 59 // Right hand side vector
60 60 // Set of equations for P0 to Pn points.
61 61 //
62 62 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
63 63 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
64 64 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
65 65 // | . . . . . . . . . . . . | | ... | | ... |
66 66 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
67 67 // | . . . . . . . . . . . . | | ... | | ... |
68 68 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
69 69 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
70 70 //
71 71 QList<qreal> rhs;
72 72 rhs.append(m_x[0] + 2 * m_x[1]);
73 73
74 74 // Set right hand side X values
75 75 for (int i = 1; i < n - 1; ++i)
76 76 rhs.append(4 * m_x[i] + 2 * m_x[i + 1]);
77 77
78 78 rhs.append((8 * m_x[n - 1] + m_x[n]) / 2.0);
79 79 // Get first control points X-values
80 80 QList<qreal> x = getFirstControlPoints(rhs);
81 81 rhs[0] = m_y[0] + 2 * m_y[1];
82 82
83 83 // Set right hand side Y values
84 84 for (int i = 1; i < n - 1; ++i)
85 85 rhs[i] = 4 * m_y[i] + 2 * m_y[i + 1];
86 86
87 87 rhs[n - 1] = (8 * m_y[n - 1] + m_y[n]) / 2.0;
88 88 // Get first control points Y-values
89 89 QList<qreal> y = getFirstControlPoints(rhs);
90 90
91 91 // Fill output arrays.
92 92 for (int i = 0; i < n; ++i)
93 93 {
94 94 // First control point
95 95 m_controlPoints.append(QPointF(x[i], y[i]));
96 96 // Second control point
97 97 if (i < n - 1)
98 98 m_controlPoints.append(QPointF(2 * m_x[i + 1] - x[i + 1], 2 * m_y[i + 1] - y[i + 1]));
99 99 else
100 100 m_controlPoints.append(QPointF((m_x[n] + x[n - 1]) / 2, (m_y[n] + y[n - 1]) / 2));
101 101 }
102 102 }
103 103
104 104 /*!
105 105 \internal
106 106 */
107 107 QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs)
108 108 {
109 109 QList<qreal> x; // Solution vector.
110 110 QList<qreal> tmp; // Temp workspace.
111 111
112 112 qreal b = 2.0;
113 113 x.append(rhs[0] / b);
114 114 tmp.append(0);
115 115 for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution.
116 116 {
117 117 tmp.append(1 / b);
118 118 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
119 119 x.append((rhs[i] - x[i - 1]) / b);
120 120 }
121 121 for (int i = 1; i < rhs.size(); i++)
122 122 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
123 123
124 124 return x;
125 125 }
126 126
127 127 /*!
128 128 \internal
129 129 Updates the control points, besed on currently avaiable knots.
130 130 */
131 131 void QSplineSeries::updateControlPoints()
132 132 {
133 133 if(m_x.size() > 1)
134 134 {
135 135 m_controlPoints.clear();
136 136 calculateControlPoints();
137 137 }
138 138 }
139 139
140 140 #include "moc_qsplineseries.cpp"
141 141
142 142 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,43 +1,43
1 1 #ifndef QSPLINESERIES_H
2 2 #define QSPLINESERIES_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include <QtGlobal>
6 #include "qxyseries.h"
6 #include "qlineseries.h"
7 7 #include <QList>
8 8 #include <QPointF>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 class QTCOMMERCIALCHART_EXPORT QSplineSeries : public QXYSeries
12 class QTCOMMERCIALCHART_EXPORT QSplineSeries : public QLineSeries
13 13 {
14 14 Q_OBJECT
15 15 public:
16 16
17 17 QSplineSeries(QObject *parent = 0);
18 18 QSeriesType type() const {return QSeries::SeriesTypeSpline;}
19 19
20 20 // int count() const { return m_x.size(); }
21 21 QPointF controlPoint(int index) const {return m_controlPoints[index];}
22 22
23 23 // TODO: allow the user to set custom control points
24 24 // void setCustomControlPoints(QList<QPointsF> controlPoints);
25 25 // bool calculateControlPointsAutomatically();
26 26 // void setCalculateControlPointsAutomatically();
27 27
28 28
29 29 private:
30 30 void calculateControlPoints();
31 31 QList<qreal> getFirstControlPoints(QList<qreal> rhs);
32 32
33 33 private slots:
34 34 void updateControlPoints();
35 35
36 36 private:
37 37 QList<QPointF> m_controlPoints;
38 38
39 39 };
40 40
41 41 QTCOMMERCIALCHART_END_NAMESPACE
42 42
43 43 #endif // QSPLINESERIES_H
@@ -1,213 +1,190
1 1 #include "qxyseries.h"
2 2
3 3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4 4
5 5 /*!
6 6 \class QXYSeries
7 \brief The QXYSeries class is used for making line charts.
8
9 \mainclass
10
11 A line chart is used to show information as a series of data points
12 connected by straight lines.
13
14 \image linechart.png
15
16 Creating basic line chart is simple:
17 \code
18 QXYSeries* series = new QXYSeries();
19 series->add(0, 6);
20 series->add(2, 4);
21 ...
22 chartView->addSeries(series);
23 \endcode
7 \brief The QXYSeries class is a base class for line, spline and scatter series.
24 8 */
25 9
26 10 /*!
27 11 \fn virtual QSeriesType QXYSeries::type() const
28 12 \brief Returns type of series.
29 13 \sa QSeries, QSeriesType
30 14 */
31 15
32 16 /*!
33 17 \fn QPen QXYSeries::pen() const
34 \brief Returns the pen used to draw line for this series.
18 \brief Returns the pen used to draw points for this series.
35 19 \sa setPen()
36 20 */
37 21
38 22 /*!
39 \fn bool QXYSeries::pointsVisible() const
40 \brief Returns if the points are drawn for this series.
41 \sa setPointsVisible()
42 */
43
44
45 /*!
46 23 \fn void QXYSeries::pointReplaced(int index)
47 24 \brief \internal \a index
48 25 */
49 26
50 27 /*!
51 28 \fn void QXYSeries::pointAdded(int index)
52 29 \brief \internal \a index
53 30 */
54 31
55 32 /*!
56 33 \fn void QXYSeries::pointRemoved(int index)
57 34 \brief \internal \a index
58 35 */
59 36
60 37 /*!
61 38 \fn void QXYSeries::updated()
62 39 \brief \internal
63 40 */
64 41
65 42 /*!
66 43 Constructs empty series object which is a child of \a parent.
67 44 When series object is added to QChartView or QChart instance ownerships is transfered.
68 45 */
69 QXYSeries::QXYSeries(QObject* parent):QSeries(parent),
70 m_pointsVisible(false)
46 QXYSeries::QXYSeries(QObject* parent):QSeries(parent)
71 47 {
72 48 }
73 49 /*!
74 50 Destroys the object. Series added to QChartView or QChart instances are owned by those,
75 51 and are deleted when mentioned object are destroyed.
76 52 */
77 53 QXYSeries::~QXYSeries()
78 54 {
79 55 }
80 56
81 57 /*!
82 58 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
83 59 */
84 60 void QXYSeries::add(qreal x,qreal y)
85 61 {
86 62 Q_ASSERT(m_x.size() == m_y.size());
87 63 m_x<<x;
88 64 m_y<<y;
89 65 emit pointAdded(m_x.size()-1);
90 66 }
91 67
92 68 /*!
93 69 This is an overloaded function.
94 70 Adds data \a point to the series. Points are connected with lines on the chart.
95 71 */
96 72 void QXYSeries::add(const QPointF& point)
97 73 {
98 74 add(point.x(),point.y());
99 75 }
100 76
101 77 /*!
102 78 Modifies \a y value for given \a x a value.
103 79 */
104 80 void QXYSeries::replace(qreal x,qreal y)
105 81 {
106 82 int index = m_x.indexOf(x);
107 83 m_x[index]=x;
108 84 m_y[index]=y;
109 85 emit pointReplaced(index);
110 86 }
111 87
112 88 /*!
113 89 This is an overloaded function.
114 90 Replaces current y value of for given \a point x value with \a point y value.
115 91 */
116 92 void QXYSeries::replace(const QPointF& point)
117 93 {
118 94 replace(point.x(),point.y());
119 95 }
120 96
121 97 /*!
122 98 Removes current \a x and y value.
123 99 */
124 100 void QXYSeries::remove(qreal x)
125 101 {
126 102 int index = m_x.indexOf(x);
127 103 emit pointRemoved(index);
128 104 m_x.remove(index);
129 105 m_y.remove(index);
130 106 }
131 107
132 108 /*!
133 109 Removes current \a point x value. Note \a point y value is ignored.
134 110 */
135 111 void QXYSeries::remove(const QPointF& point)
136 112 {
137 113 remove(point.x());
138 114 }
139 115
140 116 /*!
141 117 Clears all the data.
142 118 */
143 119 void QXYSeries::clear()
144 120 {
145 121 m_x.clear();
146 122 m_y.clear();
147 123 }
148 124
149 125 /*!
150 126 \internal \a pos
151 127 */
152 128 qreal QXYSeries::x(int pos) const
153 129 {
154 130 return m_x.at(pos);
155 131 }
156 132
157 133 /*!
158 134 \internal \a pos
159 135 */
160 136 qreal QXYSeries::y(int pos) const
161 137 {
162 138 return m_y.at(pos);
163 139 }
164 140
165 141 /*!
166 142 Returns number of data points within series.
167 143 */
168 144 int QXYSeries::count() const
169 145 {
170 146 Q_ASSERT(m_x.size() == m_y.size());
171 147
172 148 return m_x.size();
173 149
174 150 }
175 151
176 152 /*!
177 Sets \a pen used for drawing given series..
153 Sets \a pen used for points on the chart.
178 154 */
179 155 void QXYSeries::setPen(const QPen& pen)
180 156 {
181 157 if(pen!=m_pen){
182 m_pen=pen;
183 emit updated();
158 m_pen=pen;
159 emit updated();
184 160 }
185 161 }
186 162
187 163 /*!
188 Sets if data points are \a visible and should be drawn on line.
164 Sets \a brush used for points on the chart.
189 165 */
190 void QXYSeries::setPointsVisible(bool visible)
166
167 void QXYSeries::setBrush(const QBrush& brush)
191 168 {
192 if(m_pointsVisible!=visible){
193 m_pointsVisible=visible;
194 emit updated();
169 if(brush!=m_brush){
170 m_brush=brush;
171 emit updated();
195 172 }
196 173 }
197 174
198 175
199 176 /*!
200 177 Stream operator for adding a data \a point to the series.
201 178 \sa add()
202 179 */
203 180
204 181 QXYSeries& QXYSeries::operator<< (const QPointF &point)
205 182 {
206 183 add(point);
207 184 return *this;
208 185 }
209 186
210 187
211 188 #include "moc_qxyseries.cpp"
212 189
213 190 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,58 +1,64
1 1 #ifndef QXYSERIES_H_
2 2 #define QXYSERIES_H_
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qseries.h"
6 6 #include <QDebug>
7 7 #include <QPen>
8 8 #include <QBrush>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class QTCOMMERCIALCHART_EXPORT QXYSeries : public QSeries
13 13 {
14 14 Q_OBJECT
15 public:
15 protected:
16 16 QXYSeries(QObject* parent=0);
17 17 virtual ~QXYSeries();
18 18
19 19 public:
20 20 void add(qreal x, qreal y);
21 21 void add(const QPointF& point);
22 22 void replace(qreal x,qreal y);
23 23 void replace(const QPointF& point);
24 24 void remove(qreal x);
25 25 void remove(const QPointF& point);
26 26 void clear();
27 27
28 28 int count() const;
29 29 qreal x(int pos) const;
30 30 qreal y(int pos) const;
31 31
32 32 QXYSeries& operator << (const QPointF &point);
33 /*
34 void add(QList<QPointF> points);
35 void setData(QList<QPointF> points);
36 QScatterSeries& operator << (const QPointF &value);
37 QScatterSeries& operator << (QList<QPointF> points);
38 int removeAll(QPointF point);
39 */
33 40
34 41 void setPen(const QPen& pen);
35 42 QPen pen() const {return m_pen;}
36
37 void setPointsVisible(bool visible);
38 bool pointsVisible() const {return m_pointsVisible;}
43 void setBrush(const QBrush& pen);
44 QBrush brush() const {return m_brush;}
39 45
40 46 signals:
41 47 void updated();
42 48 void pointReplaced(int index);
43 49 void pointRemoved(int index);
44 50 void pointAdded(int index);
45 51
46 52
47 53 protected:
48 54 QVector<qreal> m_x;
49 55 QVector<qreal> m_y;
50 56
51 57 QPen m_pen;
52 bool m_pointsVisible;
58 QBrush m_brush;
53 59
54 60 };
55 61
56 62 QTCOMMERCIALCHART_END_NAMESPACE
57 63
58 64 #endif
@@ -1,55 +1,55
1 1 #ifndef XYCHARTITEM_H
2 2 #define XYCHARTITEM_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "chartitem_p.h"
6 6 #include <QPen>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 10 class ChartPresenter;
11 11 class QXYSeries;
12 12
13 13 class XYChartItem : public QObject , public ChartItem
14 14 {
15 15 Q_OBJECT
16 16 public:
17 XYChartItem(QXYSeries* series,QGraphicsItem *parent = 0);
17 explicit XYChartItem(QXYSeries* series,QGraphicsItem *parent = 0);
18 18 ~ XYChartItem(){};
19 19
20 20 QVector<QPointF> points() const {return m_points;}
21 21 QRectF clipRect() const { return m_clipRect;}
22 22
23 23 public slots:
24 24 void handlePointAdded(int index);
25 25 void handlePointRemoved(int index);
26 26 void handlePointReplaced(int index);
27 27 void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
28 28 void handleGeometryChanged(const QRectF& size);
29 29
30 30 protected:
31 31 virtual void updatePoints(QVector<QPointF>& points);
32 32 virtual void updatePoint(int index,QPointF& newPoint);
33 33 virtual void setGeometry(QVector<QPointF>& points);
34 34 QPointF calculateGeometryPoint(const QPointF& point) const;
35 35 QPointF calculateGeometryPoint(int index) const;
36 36 QVector<QPointF> calculateGeometryPoints() const;
37 37
38 38 private:
39 39 inline bool isEmpty();
40 40
41 41 private:
42 42 qreal m_minX;
43 43 qreal m_maxX;
44 44 qreal m_minY;
45 45 qreal m_maxY;
46 46 QXYSeries* m_series;
47 47 QSizeF m_size;
48 48 QRectF m_clipRect;
49 49 QVector<QPointF> m_points;
50 50
51 51 };
52 52
53 53 QTCOMMERCIALCHART_END_NAMESPACE
54 54
55 55 #endif
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now