##// END OF EJS Templates
Spline working somewhat
Marek Rosa -
r401:e71d8c300b9c
parent child
Show More
@@ -0,0 +1,11
1 #include <QtGui/QApplication>
2 #include "splinewidget.h"
3
4 int main(int argc, char *argv[])
5 {
6 QApplication a(argc, argv);
7 SplineWidget w;
8 w.show();
9
10 return a.exec();
11 }
@@ -0,0 +1,20
1 #-------------------------------------------------
2 #
3 # Project created by QtCreator 2012-02-29T12:37:46
4 #
5 #-------------------------------------------------
6
7 !include( ../example.pri ) {
8 error( "Couldn't find the example.pri file!" )
9 }
10
11 QT += core gui
12
13 TARGET = splinechart
14 TEMPLATE = app
15
16
17 SOURCES += main.cpp\
18 splinewidget.cpp
19
20 HEADERS += splinewidget.h
@@ -0,0 +1,53
1 #include "splinewidget.h"
2 #include "qchartview.h"
3 #include "qsplineseries.h"
4 #include "qlinechartseries.h"
5 #include <QGridLayout>
6
7 QTCOMMERCIALCHART_USE_NAMESPACE
8
9 SplineWidget::SplineWidget(QWidget *parent)
10 : QWidget(parent)
11 {
12 //create QSplineSeries
13 QSplineSeries* series = new QSplineSeries(this);
14 series->addData(QPointF(150, 100));
15 series->addData(QPointF(200, 180));
16 series->addData(QPointF(240, 130));
17 series->addData(QPointF(270, 120));
18 series->addData(QPointF(310, 120));
19 series->addData(QPointF(420, 160));
20 series->addData(QPointF(535, 250));
21
22 series->calculateControlPoints();
23
24 QLineChartSeries* lineSeries = new QLineChartSeries;
25 for (int i = 0; i < series->count() - 1; i++)
26 {
27 lineSeries->add(series->at(i).x(), series->at(i).y());
28 lineSeries->add(series->controlPoint(2*i).x(), series->controlPoint(2*i).y());
29 lineSeries->add(series->controlPoint(2*i + 1).x(), series->controlPoint(2*i + 1).y());
30 }
31
32 // QLineChartSeries* lineSeries2 = new QLineChartSeries;
33 // lineSeries2->add(10, 50);
34 // lineSeries2->add(30, 15);
35 // lineSeries2->add(60, 40);
36 // lineSeries2->add(90, 70);
37 // lineSeries2->add(100, 20);
38
39 //create chart view
40 QChartView* chart = new QChartView;
41 chart->setMinimumSize(800,600);
42 // chart->setGeometry(50, 50, 400, 300);
43 chart->addSeries(series);
44
45 QGridLayout* mainLayout = new QGridLayout;
46 mainLayout->addWidget(chart);
47 setLayout(mainLayout);
48 }
49
50 SplineWidget::~SplineWidget()
51 {
52
53 }
@@ -0,0 +1,15
1 #ifndef SPLINEWIDGET_H
2 #define SPLINEWIDGET_H
3
4 #include <QtGui/QWidget>
5
6 class SplineWidget : public QWidget
7 {
8 Q_OBJECT
9
10 public:
11 SplineWidget(QWidget *parent = 0);
12 ~SplineWidget();
13 };
14
15 #endif // SPLINEWIDGET_H
@@ -1,14 +1,15
1 1 TEMPLATE = subdirs
2 2 SUBDIRS += linechart \
3 3 zoomlinechart \
4 4 colorlinechart \
5 5 barchart \
6 6 stackedbarchart \
7 7 percentbarchart \
8 8 scatter \
9 9 piechart \
10 10 dynamiclinechart \
11 11 axischart \
12 12 multichart \
13 13 gdpbarchart \
14 presenterchart
14 presenterchart \
15 splinechart
@@ -1,357 +1,373
1 1 #include "chartdataset_p.h"
2 2 #include "qchartaxis.h"
3 3 //series
4 4 #include "qlinechartseries.h"
5 5 #include "qbarchartseries.h"
6 6 #include "qstackedbarchartseries.h"
7 7 #include "qpercentbarchartseries.h"
8 8 #include "qpieseries.h"
9 9 #include "qscatterseries.h"
10 #include "qsplineseries.h"
10 11
11 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 13
13 14 ChartDataSet::ChartDataSet(QObject *parent):QObject(parent),
14 m_axisX(new QChartAxis(this)),
15 m_axisY(new QChartAxis(this)),
16 m_domainIndex(0),
17 m_axisXInitialized(false)
15 m_axisX(new QChartAxis(this)),
16 m_axisY(new QChartAxis(this)),
17 m_domainIndex(0),
18 m_axisXInitialized(false)
18 19 {
19 20 }
20 21
21 22 ChartDataSet::~ChartDataSet()
22 23 {
23 24 // TODO Auto-generated destructor stub
24 25 }
25 26
26 27 const Domain ChartDataSet::domain(QChartAxis *axisY) const
27 28 {
28 int i = m_domainMap.count(axisY);
29 if(i == 0){
30 return Domain();
31 }
32 i = i - m_domainIndex -1;
29 int i = m_domainMap.count(axisY);
30 if(i == 0){
31 return Domain();
32 }
33 i = i - m_domainIndex -1;
33 34 return m_domainMap.values(axisY).at(i);
34 35 }
35 36
36 37 void ChartDataSet::addSeries(QChartSeries* series, QChartAxis *axisY)
37 38 {
38 39 // TODO: we should check the series not already added
39 40
40 41 series->setParent(this); // take ownership
41 42 clearDomains();
42 43
43 44 if(axisY==0) axisY = m_axisY;
44 45 axisY->setParent(this); // take ownership
45 46
46 47 QList<QChartSeries*> seriesList = m_seriesMap.values(axisY);
47 48
48 49 QList<Domain> domainList = m_domainMap.values(axisY);
49 50
50 51 Q_ASSERT(domainList.size()<=1);
51 52
52 53 Domain domain;
53 54
54 55 if(domainList.size()>0) domain = domainList.at(0);
55 56
56 57 switch(series->type())
57 58 {
58 case QChartSeries::SeriesTypeLine: {
59
60 QLineChartSeries* xyseries = static_cast<QLineChartSeries*>(series);
61
62 for (int i = 0; i < xyseries->count(); i++)
63 {
64 qreal x = xyseries->x(i);
65 qreal y = xyseries->y(i);
66 domain.m_minX = qMin(domain.m_minX,x);
67 domain.m_minY = qMin(domain.m_minY,y);
68 domain.m_maxX = qMax(domain.m_maxX,x);
69 domain.m_maxY = qMax(domain.m_maxY,y);
70 }
71 break;
72 }
73 case QChartSeries::SeriesTypeBar: {
74 qDebug() << "QChartSeries::SeriesTypeBar";
75 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
76 qreal x = barSeries->countCategories();
77 qreal y = barSeries->max();
59 case QChartSeries::SeriesTypeLine: {
60
61 QLineChartSeries* xyseries = static_cast<QLineChartSeries*>(series);
62
63 for (int i = 0; i < xyseries->count(); i++)
64 {
65 qreal x = xyseries->x(i);
66 qreal y = xyseries->y(i);
78 67 domain.m_minX = qMin(domain.m_minX,x);
79 68 domain.m_minY = qMin(domain.m_minY,y);
80 69 domain.m_maxX = qMax(domain.m_maxX,x);
81 70 domain.m_maxY = qMax(domain.m_maxY,y);
82 break;
83 71 }
84 case QChartSeries::SeriesTypeStackedBar: {
72 break;
73 }
74 case QChartSeries::SeriesTypeBar: {
75 qDebug() << "QChartSeries::SeriesTypeBar";
76 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
77 qreal x = barSeries->countCategories();
78 qreal y = barSeries->max();
79 domain.m_minX = qMin(domain.m_minX,x);
80 domain.m_minY = qMin(domain.m_minY,y);
81 domain.m_maxX = qMax(domain.m_maxX,x);
82 domain.m_maxY = qMax(domain.m_maxY,y);
83 break;
84 }
85 case QChartSeries::SeriesTypeStackedBar: {
85 86 qDebug() << "QChartSeries::SeriesTypeStackedBar";
86 87
87 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
88 qreal x = stackedBarSeries->countCategories();
89 qreal y = stackedBarSeries->maxCategorySum();
90 domain.m_minX = qMin(domain.m_minX,x);
91 domain.m_minY = qMin(domain.m_minY,y);
92 domain.m_maxX = qMax(domain.m_maxX,x);
93 domain.m_maxY = qMax(domain.m_maxY,y);
94 break;
95 }
96 case QChartSeries::SeriesTypePercentBar: {
88 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
89 qreal x = stackedBarSeries->countCategories();
90 qreal y = stackedBarSeries->maxCategorySum();
91 domain.m_minX = qMin(domain.m_minX,x);
92 domain.m_minY = qMin(domain.m_minY,y);
93 domain.m_maxX = qMax(domain.m_maxX,x);
94 domain.m_maxY = qMax(domain.m_maxY,y);
95 break;
96 }
97 case QChartSeries::SeriesTypePercentBar: {
97 98 qDebug() << "QChartSeries::SeriesTypePercentBar";
98 99
99 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
100 qreal x = percentBarSeries->countCategories();
101 domain.m_minX = qMin(domain.m_minX,x);
102 domain.m_minY = 0;
103 domain.m_maxX = qMax(domain.m_maxX,x);
104 domain.m_maxY = 100;
105 break;
106 }
100 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
101 qreal x = percentBarSeries->countCategories();
102 domain.m_minX = qMin(domain.m_minX,x);
103 domain.m_minY = 0;
104 domain.m_maxX = qMax(domain.m_maxX,x);
105 domain.m_maxY = 100;
106 break;
107 }
107 108
108 case QChartSeries::SeriesTypePie: {
109 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
110 // TODO: domain stuff
111 break;
112 }
109 case QChartSeries::SeriesTypePie: {
110 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
111 // TODO: domain stuff
112 break;
113 }
113 114
114 case QChartSeries::SeriesTypeScatter: {
115 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
116 Q_ASSERT(scatterSeries);
117 foreach (QPointF point, scatterSeries->data()) {
118 domain.m_minX = qMin(domain.m_minX, point.x());
119 domain.m_maxX = qMax(domain.m_maxX, point.x());
120 domain.m_minY = qMin(domain.m_minY, point.y());
121 domain.m_maxY = qMax(domain.m_maxY, point.y());
122 }
123 break;
115 case QChartSeries::SeriesTypeScatter: {
116 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
117 Q_ASSERT(scatterSeries);
118 foreach (QPointF point, scatterSeries->data()) {
119 domain.m_minX = qMin(domain.m_minX, point.x());
120 domain.m_maxX = qMax(domain.m_maxX, point.x());
121 domain.m_minY = qMin(domain.m_minY, point.y());
122 domain.m_maxY = qMax(domain.m_maxY, point.y());
124 123 }
124 break;
125 }
125 126
126 default: {
127 qDebug()<<__FUNCTION__<<"type" << series->type()<<"not supported";
128 return;
129 break;
127 case QChartSeries::SeriesTypeSpline: {
128 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
129
130 for (int i = 0; i < splineSeries->count(); i++)
131 {
132 qreal x = splineSeries->at(i).x();
133 qreal y = splineSeries->at(i).y();
134 domain.m_minX = qMin(domain.m_minX,x);
135 domain.m_minY = qMin(domain.m_minY,y);
136 domain.m_maxX = qMax(domain.m_maxX,x);
137 domain.m_maxY = qMax(domain.m_maxY,y);
130 138 }
139 break;
140 }
141
142 default: {
143 qDebug()<<__FUNCTION__<<"type" << series->type()<<"not supported";
144 return;
145 break;
146 }
131 147
132 148 }
133 149
134 150 if(!m_domainMap.contains(axisY))
135 151 {
136 152 emit axisAdded(axisY);
137 153 QObject::connect(axisY,SIGNAL(minChanged(qreal)),this,SLOT(handleMinChanged(qreal)));
138 154 QObject::connect(axisY,SIGNAL(maxChanged(qreal)),this,SLOT(handleMaxChanged(qreal)));
139 155 QObject::connect(axisY,SIGNAL(ticksChanged(QChartAxis*)),this,SLOT(handleTickChanged(QChartAxis*)));
140 156 }
141 157 m_domainMap.replace(axisY,domain);
142 158 m_seriesMap.insert(axisY,series);
143 159
144 160 if(!m_axisXInitialized)
145 161 {
146 162 emit axisAdded(axisX());
147 163 QObject::connect(axisX(),SIGNAL(minChanged(qreal)),this,SLOT(handleMinChanged(qreal)));
148 164 QObject::connect(axisX(),SIGNAL(maxChanged(qreal)),this,SLOT(handleMaxChanged(qreal)));
149 165 QObject::connect(axisX(),SIGNAL(ticksChanged(QChartAxis*)),this,SLOT(handleTickChanged(QChartAxis*)));
150 166 m_axisXInitialized=true;
151 167 }
152 168
153 169
154 170 emit seriesAdded(series);
155 171 QStringList ylabels = createLabels(axisY,domain.m_minY,domain.m_maxY);
156 172 QStringList xlabels = createLabels(axisX(),domain.m_minX,domain.m_maxX);
157 173 emit axisLabelsChanged(axisY,ylabels);
158 174 emit axisLabelsChanged(axisX(),xlabels);
159 175 emit seriesDomainChanged(series,domain);
160 176
161 177 }
162 178
163 179 void ChartDataSet::removeSeries(QChartSeries* series)
164 180 {
165 181 QList<QChartAxis*> keys = m_seriesMap.uniqueKeys();
166 182 foreach(QChartAxis* axis , keys) {
167 183 if(m_seriesMap.contains(axis,series)){
168 184 emit seriesRemoved(series);
169 185 m_seriesMap.remove(axis,series);
170 186 //remove axis if no longer there
171 187 if(!m_seriesMap.contains(axis)){
172 188 emit axisRemoved(axis);
173 189 m_domainMap.remove(axis);
174 190 if(axis != m_axisY)
175 delete axis;
191 delete axis;
176 192 }
177 193 series->setParent(0);
178 194 break;
179 195 }
180 196 }
181 197 }
182 198
183 199 void ChartDataSet::removeAllSeries()
184 200 {
185 201 QList<QChartAxis*> keys = m_seriesMap.uniqueKeys();
186 202 foreach(QChartAxis* axis , keys) {
187 203 QList<QChartSeries*> seriesList = m_seriesMap.values(axis);
188 204 for(int i =0 ; i < seriesList.size();i++ )
189 205 {
190 206 emit seriesRemoved(seriesList.at(i));
191 207 delete(seriesList.at(i));
192 208 }
193 209 m_seriesMap.remove(axis);
194 210 m_domainMap.remove(axis);
195 211 emit axisRemoved(axis);
196 212 if(axis != m_axisY) delete axis;
197 }
213 }
198 214 m_domainIndex=0;
199 215 }
200 216
201 217 bool ChartDataSet::nextDomain()
202 218 {
203 219 int limit = (m_domainMap.values().size()/m_domainMap.uniqueKeys().size())-1;
204 220
205 221 if (m_domainIndex < limit) {
206 222 m_domainIndex++;
207 223 setDomain(m_domainIndex);
208 224 return true;
209 225 }
210 226 else {
211 227 return false;
212 228 }
213 229 }
214 230
215 231 bool ChartDataSet::previousDomain()
216 232 {
217 233 if (m_domainIndex > 0) {
218 234 m_domainIndex--;
219 235 setDomain(m_domainIndex);
220 236 return true;
221 237 }
222 238 else {
223 239 return false;
224 240 }
225 241 }
226 242
227 243 void ChartDataSet::setDomain(int index)
228 244 {
229 245 QList<QChartAxis*> domainList = m_domainMap.uniqueKeys();
230 246
231 247 Domain domain;
232 248
233 249 foreach (QChartAxis* axis , domainList) {
234 250 int i = m_domainMap.count(axis) - index -1;
235 251 Q_ASSERT(i>=0);
236 252 domain = m_domainMap.values(axis).at(i);
237 253 QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY);
238 254 QList<QChartSeries*> seriesList = m_seriesMap.values(axis);
239 255 foreach(QChartSeries* series, seriesList) {
240 256 emit seriesDomainChanged(series,domain);
241 257 }
242 258 emit axisLabelsChanged(axis,labels);
243 259 }
244 260
245 261 QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX);
246 262 emit axisLabelsChanged(axisX(),labels);
247 263 }
248 264
249 265 void ChartDataSet::clearDomains(int toIndex)
250 266 {
251 267 Q_ASSERT(toIndex>=0);
252 268
253 269 m_domainIndex = toIndex;
254 270
255 271 QList<QChartAxis*> keys = m_domainMap.uniqueKeys();
256 272
257 273 foreach (QChartAxis* key , keys)
258 274 {
259 275 QList<Domain> domains = m_domainMap.values(key);
260 276 m_domainMap.remove(key);
261 277 int i = domains.size() - toIndex - 1;
262 278 while(i--){
263 279 domains.removeFirst();
264 280 }
265 281 for(int j=domains.size()-1; j>=0 ;j--)
266 282 m_domainMap.insert(key,domains.at(j));
267 283 }
268 284 }
269 285
270 286 void ChartDataSet::addDomain(const QRectF& rect, const QRectF& viewport)
271 287 {
272 288 Q_ASSERT(rect.isValid());
273 289 Q_ASSERT(viewport.isValid());
274 290
275 291 clearDomains(m_domainIndex);
276 292
277 293 QList<QChartAxis*> domainList = m_domainMap.uniqueKeys();
278 294
279 295 Domain domain;
280 296
281 297 foreach (QChartAxis* axis , domainList){
282 298 domain = m_domainMap.value(axis).subDomain(rect,viewport.width(),viewport.height());
283 299 QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY);
284 300 QList<QChartSeries*> seriesList = m_seriesMap.values(axis);
285 301 foreach(QChartSeries* series, seriesList){
286 302 emit seriesDomainChanged(series,domain);
287 303 }
288 304 emit axisLabelsChanged(axis,labels);
289 305 m_domainMap.insert(axis,domain);
290 306 }
291 307
292 308 QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX);
293 309 emit axisLabelsChanged(axisX(),labels);
294 310
295 311 m_domainIndex++;
296 312 }
297 313
298 314 QChartAxis* ChartDataSet::axisY(QChartSeries* series) const
299 315 {
300 316 if(series == 0) return m_axisY;
301 317
302 318 QList<QChartAxis*> keys = m_seriesMap.uniqueKeys();
303 319
304 320 foreach(QChartAxis* axis , keys) {
305 321 if(m_seriesMap.contains(axis,series)){
306 322 return axis;
307 323 }
308 324 }
309 325 return 0;
310 326 }
311 327
312 328 QStringList ChartDataSet::createLabels(QChartAxis* axis,qreal min, qreal max)
313 329 {
314 330 Q_ASSERT(max>=min);
315 331
316 332 QStringList labels;
317 333
318 334 int ticks = axis->ticksCount()-1;
319 335
320 336 for(int i=0; i<= ticks; i++){
321 337 qreal value = min + (i * (max - min)/ ticks);
322 338 QString label = axis->axisTickLabel(value);
323 339 if(label.isEmpty()){
324 340 labels << QString::number(value);
325 341 }else{
326 342 labels << label;
327 343 }
328 344 }
329 345 return labels;
330 346 }
331 347
332 348
333 349 void ChartDataSet::handleMinChanged(qreal min)
334 350 {
335 351
336 352 }
337 353
338 354 void ChartDataSet::handleMaxChanged(qreal max)
339 355 {
340 356
341 357 }
342 358
343 359 void ChartDataSet::handleTickChanged(QChartAxis* axis)
344 360 {
345 361 Domain domain = m_domainMap.value(axisY());
346 362 if(axis==axisX()){
347 363 QStringList labels = createLabels(axis,domain.m_minX,domain.m_maxX);
348 364 emit axisLabelsChanged(axis,labels);
349 365 }else{
350 366 QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY);
351 367 emit axisLabelsChanged(axis,labels);
352 368 }
353 369 }
354 370
355 371 #include "moc_chartdataset_p.cpp"
356 372
357 373 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,233 +1,236
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 #include "qsplineseries.h"
14 14 //items
15 15 #include "axisitem_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 #include "splinepresenter_p.h"
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
28 m_chart(chart),
29 m_dataset(dataset),
30 m_chartTheme(0),
31 m_marginSize(0),
32 m_rect(QRectF(QPoint(0,0),m_chart->size()))
28 m_chart(chart),
29 m_dataset(dataset),
30 m_chartTheme(0),
31 m_marginSize(0),
32 m_rect(QRectF(QPoint(0,0),m_chart->size()))
33 33 {
34 createConnections();
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 m_rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
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 AxisItem* item ;
81 81
82 82 if(axis==m_dataset->axisX()){
83 item = new AxisItem(AxisItem::X_AXIS,m_chart);
83 item = new AxisItem(AxisItem::X_AXIS,m_chart);
84 84 }else{
85 item = new AxisItem(AxisItem::Y_AXIS,m_chart);
85 item = new AxisItem(AxisItem::Y_AXIS,m_chart);
86 86 }
87 87 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
88 88 QObject::connect(axis,SIGNAL(update(QChartAxis*)),item,SLOT(handleAxisUpdate(QChartAxis*)));
89 89
90 90 item->handleAxisUpdate(axis);
91 91 item->handleGeometryChanged(m_rect);
92 92 m_chartTheme->decorate(axis,item);
93 93 m_axisItems.insert(axis,item);
94 94 }
95 95
96 96 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
97 97 {
98 98 AxisItem* item = m_axisItems.take(axis);
99 99 Q_ASSERT(item);
100 100 delete item;
101 101 }
102 102
103 103
104 104 void ChartPresenter::handleSeriesAdded(QChartSeries* series)
105 105 {
106 106 switch(series->type())
107 107 {
108 case QChartSeries::SeriesTypeLine: {
109 QLineChartSeries* lineSeries = static_cast<QLineChartSeries*>(series);
110 LineChartItem* item = new LineChartAnimationItem(this,lineSeries,m_chart);
111 m_chartTheme->decorate(item,lineSeries,m_chartItems.count());
112 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
113 QObject::connect(lineSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
114 m_chartItems.insert(series,item);
115 break;
116 }
117
118 case QChartSeries::SeriesTypeBar: {
119 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
120 BarPresenter* item = new BarPresenter(barSeries,m_chart);
121 m_chartTheme->decorate(item,barSeries,m_chartItems.count());
122 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
123 QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
124 m_chartItems.insert(series,item);
125 // m_axisXItem->setVisible(false);
126 break;
127 }
128
129 case QChartSeries::SeriesTypeStackedBar: {
130
131 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
132 StackedBarPresenter* item = new StackedBarPresenter(stackedBarSeries,m_chart);
133 m_chartTheme->decorate(item,stackedBarSeries,m_chartItems.count());
134 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
135 QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
136 m_chartItems.insert(series,item);
137 break;
138 }
139
140 case QChartSeries::SeriesTypePercentBar: {
141
142 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
143 PercentBarPresenter* item = new PercentBarPresenter(percentBarSeries,m_chart);
144 m_chartTheme->decorate(item,percentBarSeries ,m_chartItems.count());
145 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
146 QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
147 m_chartItems.insert(series,item);
148 break;
149 }
150 case QChartSeries::SeriesTypeScatter: {
151 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
152 ScatterPresenter *scatterPresenter = new ScatterPresenter(scatterSeries, m_chart);
153 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)),
154 scatterPresenter, SLOT(handleGeometryChanged(const QRectF&)));
155 m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
156 m_chartItems.insert(scatterSeries, scatterPresenter);
157 break;
158 }
159 case QChartSeries::SeriesTypePie: {
160 QPieSeries *s = qobject_cast<QPieSeries *>(series);
161 PiePresenter* pie = new PiePresenter(m_chart, s);
162 m_chartTheme->decorate(pie, s, m_chartItems.count());
163 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), pie, SLOT(handleGeometryChanged(const QRectF&)));
164 m_chartItems.insert(series, pie);
165 break;
166 }
108 case QChartSeries::SeriesTypeLine: {
109 QLineChartSeries* lineSeries = static_cast<QLineChartSeries*>(series);
110 LineChartItem* item = new LineChartAnimationItem(this,lineSeries,m_chart);
111 m_chartTheme->decorate(item,lineSeries,m_chartItems.count());
112 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
113 QObject::connect(lineSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
114 m_chartItems.insert(series,item);
115 break;
116 }
117
118 case QChartSeries::SeriesTypeBar: {
119 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
120 BarPresenter* item = new BarPresenter(barSeries,m_chart);
121 m_chartTheme->decorate(item,barSeries,m_chartItems.count());
122 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
123 QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
124 m_chartItems.insert(series,item);
125 // m_axisXItem->setVisible(false);
126 break;
127 }
128
129 case QChartSeries::SeriesTypeStackedBar: {
130
131 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
132 StackedBarPresenter* item = new StackedBarPresenter(stackedBarSeries,m_chart);
133 m_chartTheme->decorate(item,stackedBarSeries,m_chartItems.count());
134 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
135 QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
136 m_chartItems.insert(series,item);
137 break;
138 }
139
140 case QChartSeries::SeriesTypePercentBar: {
141
142 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
143 PercentBarPresenter* item = new PercentBarPresenter(percentBarSeries,m_chart);
144 m_chartTheme->decorate(item,percentBarSeries ,m_chartItems.count());
145 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
146 QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
147 m_chartItems.insert(series,item);
148 break;
149 }
150 case QChartSeries::SeriesTypeScatter: {
151 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
152 ScatterPresenter *scatterPresenter = new ScatterPresenter(scatterSeries, m_chart);
153 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)),
154 scatterPresenter, SLOT(handleGeometryChanged(const QRectF&)));
155 m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
156 m_chartItems.insert(scatterSeries, scatterPresenter);
157 break;
158 }
159 case QChartSeries::SeriesTypePie: {
160 QPieSeries *s = qobject_cast<QPieSeries *>(series);
161 PiePresenter* pie = new PiePresenter(m_chart, s);
162 m_chartTheme->decorate(pie, s, m_chartItems.count());
163 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), pie, SLOT(handleGeometryChanged(const QRectF&)));
164 m_chartItems.insert(series, pie);
165 break;
166 }
167 167 case QChartSeries::SeriesTypeSpline: {
168 168 QSplineSeries* splineSeries = qobject_cast<QSplineSeries*>(series);
169 SplinePresenter* splinePresenter = new SplinePresenter
169 SplinePresenter* splinePresenter = new SplinePresenter(splineSeries, m_chart);
170 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), splinePresenter, SLOT(handleGeometryChanged(const QRectF&)));
171 m_chartTheme->decorate(splinePresenter, splineSeries, m_chartItems.count());
172 m_chartItems.insert(splineSeries, splinePresenter);
173 break;
174 }
175 default: {
176 qDebug()<< "Series type" << series->type() << "not implemented.";
170 177 break;
171 178 }
172 default: {
173 qDebug()<< "Series type" << series->type() << "not implemented.";
174 break;
175 }
176 179 }
177 180
178 181 if(m_rect.isValid()) emit geometryChanged(m_rect);
179 182 }
180 183
181 184 void ChartPresenter::handleSeriesRemoved(QChartSeries* series)
182 185 {
183 ChartItem* item = m_chartItems.take(series);
184 delete item;
186 ChartItem* item = m_chartItems.take(series);
187 delete item;
185 188 }
186 189
187 190 void ChartPresenter::handleSeriesChanged(QChartSeries* series)
188 191 {
189 192 //TODO:
190 193 }
191 194
192 195 void ChartPresenter::handleSeriesDomainChanged(QChartSeries* series, const Domain& domain)
193 196 {
194 197 m_chartItems.value(series)->handleDomainChanged(domain);
195 198 }
196 199
197 200 void ChartPresenter::handleAxisLabelsChanged(QChartAxis* axis,const QStringList& labels)
198 201 {
199 202 m_axisItems.value(axis)->handleLabelsChanged(axis,labels);
200 203 }
201 204
202 205 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
203 206 {
204 207 delete m_chartTheme;
205 208
206 209 m_chartTheme = ChartTheme::createTheme(theme);
207 210
208 211 m_chartTheme->decorate(m_chart);
209 212 QMapIterator<QChartSeries*,ChartItem*> i(m_chartItems);
210 213
211 214 int index=0;
212 215 while (i.hasNext()) {
213 216 i.next();
214 217 index++;
215 218 m_chartTheme->decorate(i.value(),i.key(),index);
216 219 }
217 220
218 221 QMapIterator<QChartAxis*,AxisItem*> j(m_axisItems);
219 222 while (j.hasNext()) {
220 j.next();
221 m_chartTheme->decorate(j.key(),j.value());
223 j.next();
224 m_chartTheme->decorate(j.key(),j.value());
222 225 }
223 226 }
224 227
225 228 QChart::ChartTheme ChartPresenter::chartTheme()
226 229 {
227 230 return m_chartTheme->id();
228 231 }
229 232
230 233
231 234 #include "moc_chartpresenter_p.cpp"
232 235
233 236 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,229 +1,248
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 3 #include "qchartaxis.h"
4 4
5 5
6 6 //series
7 7 #include "qbarset.h"
8 8 #include "qbarchartseries.h"
9 9 #include "qstackedbarchartseries.h"
10 10 #include "qpercentbarchartseries.h"
11 11 #include "qlinechartseries.h"
12 12 #include "qscatterseries.h"
13 13 #include "qpieseries.h"
14 14 #include "qpieslice.h"
15 #include "qsplineseries.h"
15 16
16 17 //items
17 18 #include "axisitem_p.h"
18 19 #include "barpresenter.h"
19 20 #include "stackedbarpresenter.h"
20 21 #include "linechartitem_p.h"
21 22 #include "percentbarpresenter.h"
22 23 #include "scatterpresenter_p.h"
23 24 #include "piepresenter.h"
25 #include "splinepresenter_p.h"
24 26
25 27 //themes
26 28 #include "chartthemevanilla_p.h"
27 29 #include "chartthemeicy_p.h"
28 30 #include "chartthemegrayscale_p.h"
29 31 #include "chartthemescientific_p.h"
30 32
31 33
32 34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 35
34 36 /* TODO
35 37 case QChart::ChartThemeUnnamed1:
36 38 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff3fa9f5)), 2));
37 39 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff7AC943)), 2));
38 40 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF931E)), 2));
39 41 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF1D25)), 2));
40 42 m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF7BAC)), 2));
41 43
42 44 m_gradientStartColor = QColor(QRgb(0xfff3dc9e));
43 45 m_gradientEndColor = QColor(QRgb(0xffafafaf));
44 46 */
45 47
46 48 ChartTheme::ChartTheme(QChart::ChartTheme id)
47 49 {
48 50 m_id = id;
49 51 m_seriesColor.append(QRgb(0xff000000));
50 52 m_seriesColor.append(QRgb(0xff707070));
51 53 m_gradientStartColor = QColor(QRgb(0xffffffff));
52 54 m_gradientEndColor = QColor(QRgb(0xffafafaf));
53 55 }
54 56
55 57
56 58 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
57 59 {
58 60 switch(theme) {
59 61 case QChart::ChartThemeDefault:
60 62 return new ChartTheme();
61 63 case QChart::ChartThemeVanilla:
62 64 return new ChartThemeVanilla();
63 65 case QChart::ChartThemeIcy:
64 66 return new ChartThemeIcy();
65 67 case QChart::ChartThemeGrayscale:
66 68 return new ChartThemeGrayscale();
67 69 case QChart::ChartThemeScientific:
68 70 return new ChartThemeScientific();
69 71 }
70 72 }
71 73
72 74 void ChartTheme::decorate(QChart* chart)
73 75 {
74 76 QLinearGradient backgroundGradient;
75 77 backgroundGradient.setColorAt(0.0, m_gradientStartColor);
76 78 backgroundGradient.setColorAt(1.0, m_gradientEndColor);
77 79 backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
78 80 chart->setChartBackgroundBrush(backgroundGradient);
79 81 }
80 82 //TODO helper to by removed later
81 83 void ChartTheme::decorate(ChartItem* item, QChartSeries* series,int count)
82 84 {
83 85 switch(series->type())
84 86 {
85 87 case QChartSeries::SeriesTypeLine: {
86 88 QLineChartSeries* s = static_cast<QLineChartSeries*>(series);
87 89 LineChartItem* i = static_cast<LineChartItem*>(item);
88 90 decorate(i,s,count);
89 91 break;
90 92 }
91 93 case QChartSeries::SeriesTypeBar: {
92 94 QBarChartSeries* b = static_cast<QBarChartSeries*>(series);
93 95 BarPresenter* i = static_cast<BarPresenter*>(item);
94 96 decorate(i,b,count);
95 97 break;
96 98 }
97 99 case QChartSeries::SeriesTypeStackedBar: {
98 100 QStackedBarChartSeries* s = static_cast<QStackedBarChartSeries*>(series);
99 101 StackedBarPresenter* i = static_cast<StackedBarPresenter*>(item);
100 102 decorate(i,s,count);
101 103 break;
102 104 }
103 105 case QChartSeries::SeriesTypePercentBar: {
104 106 QPercentBarChartSeries* s = static_cast<QPercentBarChartSeries*>(series);
105 107 PercentBarPresenter* i = static_cast<PercentBarPresenter*>(item);
106 108 decorate(i,s,count);
107 109 break;
108 110 }
109 111 case QChartSeries::SeriesTypeScatter: {
110 112 QScatterSeries* s = qobject_cast<QScatterSeries*>(series);
111 113 Q_ASSERT(s);
112 114 ScatterPresenter* i = static_cast<ScatterPresenter*>(item);
113 115 Q_ASSERT(i);
114 116 decorate(i, s, count);
115 117 break;
116 118 }
117 119 case QChartSeries::SeriesTypePie: {
118 120 QPieSeries* s = static_cast<QPieSeries*>(series);
119 121 PiePresenter* i = static_cast<PiePresenter*>(item);
120 122 decorate(i,s,count);
121 123 break;
122 124 }
123 125 default:
124 126 qDebug()<<"Wrong item to be decorated by theme";
125 127 break;
126 128 }
127 129
128 130 }
129 131
130 132 void ChartTheme::decorate(LineChartItem* item, QLineChartSeries* series,int count)
131 133 {
132 134 QPen pen;
133 135 if(pen != series->pen()){
134 136 item->setPen(series->pen());
135 137 return;
136 138 }
137 139 pen.setColor(m_seriesColor.at(count%m_seriesColor.size()));
138 140 pen.setWidthF(2);
139 141 item->setPen(pen);
140 142 }
141 143
142 144 void ChartTheme::decorate(BarPresenter* item, QBarChartSeries* series,int count)
143 145 {
144 146 for (int i=0; i<series->countSets(); i++) {
145 147 series->nextSet(0==i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
146 148 }
147 149 }
148 150
149 151 void ChartTheme::decorate(StackedBarPresenter* item, QStackedBarChartSeries* series,int count)
150 152 {
151 153 for (int i=0; i<series->countSets(); i++) {
152 154 series->nextSet(0==i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
153 155 }
154 156 }
155 157
156 158 void ChartTheme::decorate(PercentBarPresenter* item, QPercentBarChartSeries* series,int count)
157 159 {
158 160 for (int i=0; i<series->countSets(); i++) {
159 161 series->nextSet(0==i)->setBrush(QBrush(m_seriesColor.at(i%m_seriesColor.count())));
160 162 }
161 163 }
162 164
163 165 void ChartTheme::decorate(ScatterPresenter* presenter, QScatterSeries* series, int count)
164 166 {
165 167 Q_ASSERT(presenter);
166 168 Q_ASSERT(series);
167 169
168 170 QColor color = m_seriesColor.at(count % m_seriesColor.size());
169 171 // TODO: define alpha in the theme? or in the series?
170 172 //color.setAlpha(120);
171 173
172 174 QBrush brush(color, Qt::SolidPattern);
173 175 presenter->m_markerBrush = brush;
174 176
175 177 QPen pen(brush, 3);
176 178 pen.setColor(color);
177 179 presenter->m_markerPen = pen;
178 180 }
179 181
180 182 void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int /*count*/)
181 183 {
182 184 // create a list of slice colors based on current theme
183 185 int i = 0;
184 186 QList<QColor> colors;
185 187 while (colors.count() < series->count()) {
186 188
187 189 // get base color
188 190 QColor c = m_seriesColor[i++];
189 191 i = i % m_seriesColor.count();
190 192
191 193 // -1 means achromatic color -> cannot manipulate lightness
192 194 // TODO: find a better way to randomize lightness
193 195 if (c.toHsv().hue() == -1)
194 196 qWarning() << "ChartTheme::decorate() warning: achromatic theme color";
195 197
196 198 // randomize lightness
197 199 qreal f = 50 + (qrand() % 100); // 50 is 50% darker, 100 is the same, 150 is 50% lighter
198 200 c = c.lighter(f);
199 201
200 202 // find duplicates
201 203 bool isUnique = true;
202 204 foreach (QColor color, colors) {
203 205 if (c == color)
204 206 isUnique = false;
205 207 }
206 208
207 209 // add to array if unique
208 210 //if (isUnique)
209 211 colors << c;
210 212 }
211 213
212 214 // finally update colors
213 215 foreach (QPieSlice* s, series->slices()) {
214 216 s->setPen(QPen(Qt::black)); // TODO: get from theme
215 217 s->setBrush(colors.takeFirst());
216 218 }
217 219 }
218 220
219 221
220 222 void ChartTheme::decorate(QChartAxis* axis,AxisItem* item)
221 223 {
222 224 //TODO: dummy defults for now
223 225 axis->setLabelsBrush(Qt::black);
224 226 axis->setLabelsPen(Qt::NoPen);
225 227 axis->setShadesPen(Qt::NoPen);
226 228 axis->setShadesOpacity(0.5);
227 229 }
228 230
231 void ChartTheme::decorate(SplinePresenter* presenter, QSplineSeries* series, int count)
232 {
233 Q_ASSERT(presenter);
234 Q_ASSERT(series);
235
236 // QColor color = m_seriesColor.at(count % m_seriesColor.size());
237 // TODO: define alpha in the theme? or in the series?
238 //color.setAlpha(120);
239
240 // QBrush brush(color, Qt::SolidPattern);
241 // presenter->m_markerBrush = brush;
242
243 // QPen pen(brush, 3);
244 // pen.setColor(color);
245 // presenter->m_markerPen = pen;
246 }
247
229 248 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,52 +1,55
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 QChartSeries;
12 12 class LineChartItem;
13 13 class QLineChartSeries;
14 14 class BarPresenter;
15 15 class QBarChartSeries;
16 16 class StackedBarPresenter;
17 17 class QStackedBarChartSeries;
18 18 class QPercentBarChartSeries;
19 19 class PercentBarPresenter;
20 20 class QScatterSeries;
21 21 class ScatterPresenter;
22 22 class PiePresenter;
23 23 class QPieSeries;
24 class SplinePresenter;
25 class QSplineSeries;
24 26
25 27 class ChartTheme
26 28 {
27 29 protected:
28 30 explicit ChartTheme(QChart::ChartTheme id = QChart::ChartThemeDefault);
29 31 public:
30 32 static ChartTheme* createTheme(QChart::ChartTheme theme);
31 33 QChart::ChartTheme id() const {return m_id;}
32 34 void decorate(QChart* chart);
33 35 void decorate(ChartItem* item, QChartSeries* series,int count);
34 36 void decorate(LineChartItem* item, QLineChartSeries*, int count);
35 37 void decorate(BarPresenter* item, QBarChartSeries* series,int count);
36 38 void decorate(StackedBarPresenter* item, QStackedBarChartSeries* series,int count);
37 39 void decorate(PercentBarPresenter* item, QPercentBarChartSeries* series,int count);
38 40 void decorate(ScatterPresenter* presenter, QScatterSeries* series, int count);
39 41 void decorate(PiePresenter* item, QPieSeries* series, int count);
40 42 void decorate(QChartAxis* axis,AxisItem* item);
43 void decorate(SplinePresenter* presenter, QSplineSeries* series, int count);
41 44
42 45 protected:
43 46 QChart::ChartTheme m_id;
44 47 QColor m_gradientStartColor;
45 48 QColor m_gradientEndColor;
46 49 QList<QColor> m_seriesColor;
47 50
48 51 };
49 52
50 53 QTCOMMERCIALCHART_END_NAMESPACE
51 54
52 55 #endif // CHARTTHEME_H
@@ -1,100 +1,110
1 1 #include "qsplineseries.h"
2 2
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
3 5 QSplineSeries::QSplineSeries(QObject *parent) :
4 QObject(parent)
6 QChartSeries(parent)
5 7 {
6 8 }
7 9
8 10 QSplineSeries& QSplineSeries::operator << (const QPointF &value)
9 11 {
10 d->m_data.append(value);
11 emit changed();
12 // d->m_data.append(value);
13 m_data.append(value);
14 // emit changed();
12 15 return *this;
13 16 }
14 17
15 void QSplineSeries::GetCurveControlPoints()
16 {
18 void QSplineSeries::addData(QPointF value)
19 {
20 m_data.append(value);
21 }
22
23 void QSplineSeries::calculateControlPoints()
24 {
25
26 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
27 // CPOL Licence
28
17 29 int n = m_data.size() - 1;
18 if (n < 1)
19 throw new ArgumentException
20 ("At least two knot points required", "knots");
21 if (n == 1)
22 { // Special case: Bezier curve should be a straight line.
23 firstControlPoints = new Point[1];
24 // 3P1 = 2P0 + P3
25 firstControlPoints[0].X = (2 * knots[0].X + knots[1].X) / 3;
26 firstControlPoints[0].Y = (2 * knots[0].Y + knots[1].Y) / 3;
27
28 secondControlPoints = new Point[1];
29 // P2 = 2P1 P0
30 secondControlPoints[0].X = 2 *
31 firstControlPoints[0].X - knots[0].X;
32 secondControlPoints[0].Y = 2 *
33 firstControlPoints[0].Y - knots[0].Y;
34 return;
35 }
36
37 // Calculate first Bezier control points
38 // Right hand side vector
39 double[] rhs = new double[n];
40
41 // Set right hand side X values
42 for (int i = 1; i < n - 1; ++i)
43 rhs[i] = 4 * knots[i].X + 2 * knots[i + 1].X;
44 rhs[0] = knots[0].X + 2 * knots[1].X;
45 rhs[n - 1] = (8 * knots[n - 1].X + knots[n].X) / 2.0;
46 // Get first control points X-values
47 double[] x = GetFirstControlPoints(rhs);
48
49 // Set right hand side Y values
50 for (int i = 1; i < n - 1; ++i)
51 rhs[i] = 4 * knots[i].Y + 2 * knots[i + 1].Y;
52 rhs[0] = knots[0].Y + 2 * knots[1].Y;
53 rhs[n - 1] = (8 * knots[n - 1].Y + knots[n].Y) / 2.0;
54 // Get first control points Y-values
55 double[] y = GetFirstControlPoints(rhs);
56
57 // Fill output arrays.
58 firstControlPoints = new Point[n];
59 secondControlPoints = new Point[n];
60 for (int i = 0; i < n; ++i)
61 {
62 // First control point
63 firstControlPoints[i] = new Point(x[i], y[i]);
64 // Second control point
65 if (i < n - 1)
66 secondControlPoints[i] = new Point(2 * knots
67 [i + 1].X - x[i + 1], 2 *
68 knots[i + 1].Y - y[i + 1]);
69 else
70 secondControlPoints[i] = new Point((knots
71 [n].X + x[n - 1]) / 2,
72 (knots[n].Y + y[n - 1]) / 2);
73 }
30 if (n == 1)
31 { // Special case: Bezier curve should be a straight line.
32 // firstControlPoints = new Point[1];
33 // 3P1 = 2P0 + P3
34 m_controlPoints.append(QPointF((2 * m_data[0].x() + m_data[1].x()) / 3, (2 * m_data[0].y() + m_data[1].y()) / 3));
35
36 // P2 = 2P1 P0
37 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_data[0].x(), 2 * m_controlPoints[0].y() - m_data[0].y()));
38 return;
74 39 }
75 40
76 /// <summary>
77 /// Solves a tridiagonal system for one of coordinates (x or y)
78 /// of first Bezier control points.
79 /// </summary>
80 /// <param name="rhs">Right hand side vector.</param>
81 /// <returns>Solution vector.</returns>
82 void GetFirstControlPoints(qreal[] rhs)
41 // Calculate first Bezier control points
42 // Right hand side vector
43 // Set of equations for P0 to Pn points.
44 //
45 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
46 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
47 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
48 // | . . . . . . . . . . . . | | ... | | ... |
49 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
50 // | . . . . . . . . . . . . | | ... | | ... |
51 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
52 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
53 //
54 QList<qreal> rhs;
55 rhs.append(m_data[0].x() + 2 * m_data[1].x());
56
57 // Set right hand side X values
58 for (int i = 1; i < m_data.size() - 1; ++i)
59 rhs.append(4 * m_data[i].x() + 2 * m_data[i + 1].x());
60
61 rhs.append((8 * m_data[n - 1].x() + m_data[n].x()) / 2.0);
62 // Get first control points X-values
63 QList<qreal> x = getFirstControlPoints(rhs);
64 rhs[0] = m_data[0].y() + 2 * m_data[1].y();
65
66 // Set right hand side Y values
67 for (int i = 1; i < m_data.size() - 1; ++i)
68 rhs[i] = 4 * m_data[i].y() + 2 * m_data[i + 1].y();
69
70 rhs[n - 1] = (8 * m_data[n - 1].y() + m_data[n].y()) / 2.0;
71 // Get first control points Y-values
72 QList<qreal> y = getFirstControlPoints(rhs);
73
74 // Fill output arrays.
75 // firstControlPoints = new Point[n];
76 // secondControlPoints = new Point[n];
77 for (int i = 0; i < m_data.size(); ++i)
83 78 {
84 int n = rhs.Length;
85 double[] x = new double[n]; // Solution vector.
86 double[] tmp = new double[n]; // Temp workspace.
87
88 double b = 2.0;
89 x[0] = rhs[0] / b;
90 for (int i = 1; i < n; i++) // Decomposition and forward substitution.
91 {
92 tmp[i] = 1 / b;
93 b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
94 x[i] = (rhs[i] - x[i - 1]) / b;
95 }
96 for (int i = 1; i < n; i++)
97 x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
98
99 return x;
79 // First control point
80 m_controlPoints.append(QPointF(x[i], y[i]));
81 // Second control point
82 if (i < n - 1)
83 m_controlPoints.append(QPointF(2 * m_data[i + 1].x() - x[i + 1], 2 * m_data[i + 1].y() - y[i + 1]));
84 else
85 m_controlPoints.append(QPointF((m_data[n].x() + x[n - 1]) / 2, (m_data[n].y() + y[n - 1]) / 2));
100 86 }
87 }
88
89 QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs)
90 {
91 QList<qreal> x; // Solution vector.
92 QList<qreal> tmp; // Temp workspace.
93
94 qreal b = 2.0;
95 x.append(rhs[0] / b);
96 tmp.append(0);
97 for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution.
98 {
99 tmp.append(1 / b);
100 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
101 x.append((rhs[i] - x[i - 1]) / b);
102 }
103 for (int i = 1; i < rhs.size(); i++)
104 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
105
106 return x;
107 }
108 #include "moc_qsplineseries.cpp"
109
110 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,31 +1,41
1 1 #ifndef QSPLINESERIES_H
2 2 #define QSPLINESERIES_H
3 3
4 #include "qchartglobal.h"
5 #include <QtGlobal>
4 6 #include "qchartseries.h"
7 #include <QList>
8 #include <QPointF>
5 9
6 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 11
8 12 class QSplineSeries : public QChartSeries
9 13 {
10 14 Q_OBJECT
11 15 public:
12 16
13 17 QSplineSeries(QObject *parent = 0);
14 18 QChartSeriesType type() const { return QChartSeries::SeriesTypeSpline; }
15 19 void addData(QPointF value);
16 20 QSplineSeries& operator << (const QPointF &value);
17 21 void calculateControlPoints();
22 QList<qreal> getFirstControlPoints(QList<qreal> rhs);
23
24 int count() const { return m_data.size(); }
25
26 QPointF at(int index) const { return m_data[index]; }
27 QPointF controlPoint(int index) const { return m_controlPoints[index]; }
18 28
19 29 signals:
20 30
21 31 public slots:
22 32
23 33 private:
24 34 QList<QPointF> m_data;
25 35 QList<QPointF> m_controlPoints;
26 36
27 37 };
28 38
29 39 QTCOMMERCIALCHART_END_NAMESPACE
30 40
31 41 #endif // QSPLINESERIES_H
@@ -1,15 +1,12
1 1 INCLUDEPATH += $$PWD
2 2 DEPENDPATH += $$PWD
3 3
4 4 SOURCES += \
5 5 $$PWD/qsplineseries.cpp \
6 splinechart/splinepresenter.cpp
6 $$PWD/splinepresenter.cpp
7 7
8 PRIVATE_HEADERS +=
8 PRIVATE_HEADERS += \
9 $$PWD/splinepresenter_p.h
9 10
10 11 PUBLIC_HEADERS += \
11 12 $$PWD/qsplineseries.h
12
13 HEADERS += \
14 splinechart/qsplineseries.h \
15 splinechart/splinepresenter_p.h
@@ -1,16 +1,54
1 1 #include "splinepresenter_p.h"
2 #include <QPainter>
2 3
3 SplinePresenter::SplinePresenter(QObject *parent) :
4 QObject(parent)
4 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5
6 SplinePresenter::SplinePresenter(QSplineSeries* series, QGraphicsObject *parent) :
7 ChartItem(parent),m_series(series),m_boundingRect()
5 8 {
9 if (parent)
10 m_boundingRect = parent->boundingRect();
11 else
12 m_boundingRect = QRectF(10,50, 250, 250);
6 13 }
7 14
8 15 void SplinePresenter::handleGeometryChanged(const QRectF&)
9 16 {
10 //
17 update();
11 18 }
12 19
13 20 void SplinePresenter::handleDomainChanged(const Domain& domain)
14 21 {
15 22 //
16 23 }
24
25 void SplinePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
26 {
27 Q_UNUSED(widget);
28 Q_UNUSED(option);
29 painter->save();
30
31 painter->setPen(Qt::SolidLine);
32
33 QPainterPath splinePath;
34 splinePath.moveTo(m_series->at(0));
35 for (int i = 0; i < m_series->count() - 1; i++)
36 {
37 painter->setPen(Qt::red);
38 splinePath.cubicTo(m_series->controlPoint(2 * i), m_series->controlPoint(2 * i + 1), m_series->at(i + 1));
39 painter->drawEllipse(m_series->at(i), 4, 4);
40
41 painter->setPen(Qt::blue);
42 painter->drawLine(m_series->at(i), m_series->controlPoint(2 * i));
43 painter->drawLine(m_series->at(i + 1), m_series->controlPoint(2 * i + 1));
44 painter->drawEllipse(m_series->controlPoint(2 * i), 4, 4);
45 painter->drawEllipse(m_series->controlPoint(2 * i + 1), 4, 4);
46 }
47 painter->setPen(Qt::red);
48 painter->drawPath(splinePath);
49 painter->restore();
50 }
51
52 #include "moc_splinepresenter_p.cpp"
53
54 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,26 +1,33
1 1 #ifndef SPLINEPRESENTER_P_H
2 2 #define SPLINEPRESENTER_P_H
3 3
4 4 #include "chartitem_p.h"
5 5 #include <QObject>
6 #include "qsplineseries.h"
6 7
7 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 9
9 10 class SplinePresenter : public QObject, public ChartItem
10 11 {
11 12 Q_OBJECT
12 13 public:
13 SplinePresenter(QObject *parent = 0);
14 SplinePresenter(QSplineSeries* series, QGraphicsObject *parent = 0);
14 15
15 void handleGeometryChanged(const QRectF&);
16 void handleDomainChanged(const Domain& domain);
16 QRectF boundingRect() const { return m_boundingRect; }
17 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
17 18
18 19 signals:
19 20
20 21 public slots:
22 void handleDomainChanged(const Domain& domain);
23 void handleGeometryChanged(const QRectF& rect);
24
25 private:
26 QSplineSeries* m_series;
27 QRectF m_boundingRect;
21 28
22 29 };
23 30
24 31 QTCOMMERCIALCHART_END_NAMESPACE
25 32
26 33 #endif // SPLINEPRESENTER_P_H
@@ -1,145 +1,145
1 1 #include "dataseriedialog.h"
2 2 #include <QDialogButtonBox>
3 3 #include <QGridLayout>
4 #include <QCheckbox>
4 #include <QCheckBox>
5 5 #include <QPushButton>
6 6 #include <QGroupBox>
7 7 #include <QRadioButton>
8 8 #include <QLabel>
9 9 #include <QDebug>
10 10
11 11 DataSerieDialog::DataSerieDialog(QString defaultType, QWidget *parent) :
12 12 QDialog(parent)
13 13 {
14 14 QDialogButtonBox *addSeriesBox = new QDialogButtonBox(Qt::Horizontal);
15 15 QPushButton *b = addSeriesBox->addButton(QDialogButtonBox::Ok);
16 16 connect(b, SIGNAL(clicked()), this, SLOT(accept()));
17 17 b = addSeriesBox->addButton(QDialogButtonBox::Cancel);
18 18 connect(b, SIGNAL(clicked()), this, SLOT(reject()));
19 19
20 20 QGridLayout *grid = new QGridLayout();
21 21
22 22 m_seriesTypeSelector = seriesTypeSelector();
23 23 m_columnCountSelector = columnCountSelector();
24 24 m_rowCountSelector = rowCountSelector();
25 25 m_dataCharacteristicsSelector = dataCharacteristicsSelector();
26 26
27 27 grid->addWidget(m_seriesTypeSelector, 0, 0);
28 28 grid->addWidget(m_columnCountSelector, 0, 1);
29 29 grid->addWidget(m_rowCountSelector, 1, 1);
30 30 grid->addWidget(m_dataCharacteristicsSelector, 1, 0);
31 31 m_labelsSelector = new QCheckBox("Labels defined");
32 32 m_labelsSelector->setChecked(true);
33 33 grid->addWidget(m_labelsSelector, 2, 0);
34 34 grid->addWidget(addSeriesBox, 3, 1);
35 35
36 36 setLayout(grid);
37 37 }
38 38
39 39 QGroupBox *DataSerieDialog::seriesTypeSelector()
40 40 {
41 41 QVBoxLayout *layout = new QVBoxLayout();
42 42
43 43 QRadioButton *line = new QRadioButton("Line");
44 44 line->setChecked(true);
45 45 layout->addWidget(line);
46 46 layout->addWidget(new QRadioButton("Area"));
47 47 layout->addWidget(new QRadioButton("Pie"));
48 48 layout->addWidget(new QRadioButton("Bar"));
49 49 layout->addWidget(new QRadioButton("Stacked bar"));
50 50 layout->addWidget(new QRadioButton("Percent bar"));
51 51 layout->addWidget(new QRadioButton("Scatter"));
52 52 layout->addWidget(new QRadioButton("Spline"));
53 53
54 54 QGroupBox *groupBox = new QGroupBox("Series type");
55 55 groupBox->setLayout(layout);
56 56
57 57 return groupBox;
58 58 }
59 59
60 60 QGroupBox *DataSerieDialog::columnCountSelector()
61 61 {
62 62 QVBoxLayout *layout = new QVBoxLayout();
63 63
64 64 QRadioButton *radio = new QRadioButton("1");
65 65 radio->setChecked(true);
66 66 layout->addWidget(radio);
67 67 layout->addWidget(new QRadioButton("2"));
68 68 layout->addWidget(new QRadioButton("3"));
69 69 layout->addWidget(new QRadioButton("5"));
70 70 layout->addWidget(new QRadioButton("10"));
71 71 layout->addWidget(new QRadioButton("100"));
72 72
73 73 QGroupBox *groupBox = new QGroupBox("Column count");
74 74 groupBox->setLayout(layout);
75 75
76 76 return groupBox;
77 77 }
78 78
79 79 QGroupBox *DataSerieDialog::rowCountSelector()
80 80 {
81 81 QVBoxLayout *layout = new QVBoxLayout();
82 82
83 83 layout->addWidget(new QRadioButton("1"));
84 84 QRadioButton *radio = new QRadioButton("10");
85 85 radio->setChecked(true);
86 86 layout->addWidget(radio);
87 87 layout->addWidget(new QRadioButton("50"));
88 88 layout->addWidget(new QRadioButton("100"));
89 89 layout->addWidget(new QRadioButton("10000"));
90 90 layout->addWidget(new QRadioButton("1000000"));
91 91
92 92 QGroupBox *groupBox = new QGroupBox("Row count");
93 93 groupBox->setLayout(layout);
94 94
95 95 return groupBox;
96 96 }
97 97
98 98 QGroupBox *DataSerieDialog::dataCharacteristicsSelector()
99 99 {
100 100 QVBoxLayout *layout = new QVBoxLayout();
101 101
102 102 QRadioButton *radio1 = new QRadioButton("Linear");
103 103 radio1->setChecked(true);
104 104 layout->addWidget(radio1);
105 105 layout->addWidget(new QRadioButton("Constant"));
106 106 layout->addWidget(new QRadioButton("Random"));
107 107 layout->addWidget(new QRadioButton("Sin"));
108 108 layout->addWidget(new QRadioButton("Sin + random"));
109 109
110 110 QGroupBox *groupBox = new QGroupBox("Data Characteristics");
111 111 groupBox->setLayout(layout);
112 112
113 113 return groupBox;
114 114 }
115 115
116 116 void DataSerieDialog::accept()
117 117 {
118 118 accepted(radioSelection(m_seriesTypeSelector),
119 119 radioSelection(m_columnCountSelector).toInt(),
120 120 radioSelection(m_rowCountSelector).toInt(),
121 121 radioSelection(m_dataCharacteristicsSelector),
122 122 m_labelsSelector->isChecked());
123 123 QDialog::accept();
124 124 }
125 125
126 126 QString DataSerieDialog::radioSelection(QGroupBox *groupBox)
127 127 {
128 128 QString selection;
129 129 QVBoxLayout *layout = qobject_cast<QVBoxLayout *>(groupBox->layout());
130 130 Q_ASSERT(layout);
131 131
132 132 for (int i(0); i < layout->count(); i++) {
133 133 QLayoutItem *item = layout->itemAt(i);
134 134 Q_ASSERT(item);
135 135 QRadioButton *radio = qobject_cast<QRadioButton *>(item->widget());
136 136 Q_ASSERT(radio);
137 137 if (radio->isChecked()) {
138 138 selection = radio->text();
139 139 break;
140 140 }
141 141 }
142 142
143 143 qDebug() << "radioSelection: " << selection;
144 144 return selection;
145 145 }
General Comments 0
You need to be logged in to leave comments. Login now