##// END OF EJS Templates
Theme change now affects also XY series
Tero Ahola -
r615:91322882c9fd
parent child
Show More
@@ -1,323 +1,302
1 #include "charttheme_p.h"
1 #include "charttheme_p.h"
2 #include "qchart.h"
2 #include "qchart.h"
3 #include "qchartview.h"
3 #include "qchartview.h"
4 #include "qlegend.h"
4 #include "qlegend.h"
5 #include "qchartaxis.h"
5 #include "qchartaxis.h"
6 #include <QTime>
6 #include <QTime>
7
7
8 //series
8 //series
9 #include "qbarset.h"
9 #include "qbarset.h"
10 #include "qbarseries.h"
10 #include "qbarseries.h"
11 #include "qstackedbarseries.h"
11 #include "qstackedbarseries.h"
12 #include "qpercentbarseries.h"
12 #include "qpercentbarseries.h"
13 #include "qlineseries.h"
13 #include "qlineseries.h"
14 #include "qareaseries.h"
14 #include "qareaseries.h"
15 #include "qscatterseries.h"
15 #include "qscatterseries.h"
16 #include "qpieseries.h"
16 #include "qpieseries.h"
17 #include "qpieslice.h"
17 #include "qpieslice.h"
18 #include "qsplineseries.h"
18 #include "qsplineseries.h"
19
19
20 //items
20 //items
21 #include "axisitem_p.h"
21 #include "axisitem_p.h"
22 #include "barpresenter_p.h"
22 #include "barpresenter_p.h"
23 #include "stackedbarpresenter_p.h"
23 #include "stackedbarpresenter_p.h"
24 #include "percentbarpresenter_p.h"
24 #include "percentbarpresenter_p.h"
25 #include "linechartitem_p.h"
25 #include "linechartitem_p.h"
26 #include "areachartitem_p.h"
26 #include "areachartitem_p.h"
27 #include "scatterchartitem_p.h"
27 #include "scatterchartitem_p.h"
28 #include "piechartitem_p.h"
28 #include "piechartitem_p.h"
29 #include "splinechartitem_p.h"
29 #include "splinechartitem_p.h"
30
30
31 //themes
31 //themes
32 #include "chartthemedefault_p.h"
32 #include "chartthemedefault_p.h"
33 #include "chartthemevanilla_p.h"
33 #include "chartthemevanilla_p.h"
34 #include "chartthemeicy_p.h"
34 #include "chartthemeicy_p.h"
35 #include "chartthemegrayscale_p.h"
35 #include "chartthemegrayscale_p.h"
36 #include "chartthemescientific_p.h"
36 #include "chartthemescientific_p.h"
37 #include "chartthemebluecerulean_p.h"
37 #include "chartthemebluecerulean_p.h"
38 #include "chartthemelight_p.h"
38 #include "chartthemelight_p.h"
39
39
40
40
41 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41 QTCOMMERCIALCHART_BEGIN_NAMESPACE
42
42
43 ChartTheme::ChartTheme(QChart::ChartTheme id) :
43 ChartTheme::ChartTheme(QChart::ChartTheme id) :
44 m_masterFont(QFont()),
44 m_masterFont(QFont()),
45 m_titleBrush(QColor(QRgb(0x000000))),
45 m_titleBrush(QColor(QRgb(0x000000))),
46 m_axisLinePen(QPen(QRgb(0x000000))),
46 m_axisLinePen(QPen(QRgb(0x000000))),
47 m_axisLabelBrush(QColor(QRgb(0x000000))),
47 m_axisLabelBrush(QColor(QRgb(0x000000))),
48 m_backgroundShadesPen(Qt::NoPen),
48 m_backgroundShadesPen(Qt::NoPen),
49 m_backgroundShadesBrush(Qt::NoBrush),
49 m_backgroundShadesBrush(Qt::NoBrush),
50 m_backgroundShades(BackgroundShadesNone),
50 m_backgroundShades(BackgroundShadesNone),
51 m_gridLinePen(QPen(QRgb(0x000000)))
51 m_gridLinePen(QPen(QRgb(0x000000)))
52 {
52 {
53 m_id = id;
53 m_id = id;
54 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
54 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
55 }
55 }
56
56
57
57
58 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
58 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
59 {
59 {
60 switch(theme) {
60 switch(theme) {
61 case QChart::ChartThemeVanilla:
61 case QChart::ChartThemeVanilla:
62 return new ChartThemeVanilla();
62 return new ChartThemeVanilla();
63 case QChart::ChartThemeIcy:
63 case QChart::ChartThemeIcy:
64 return new ChartThemeIcy();
64 return new ChartThemeIcy();
65 case QChart::ChartThemeGrayscale:
65 case QChart::ChartThemeGrayscale:
66 return new ChartThemeGrayscale();
66 return new ChartThemeGrayscale();
67 case QChart::ChartThemeScientific:
67 case QChart::ChartThemeScientific:
68 return new ChartThemeScientific();
68 return new ChartThemeScientific();
69 case QChart::ChartThemeBlueCerulean:
69 case QChart::ChartThemeBlueCerulean:
70 return new ChartThemeBlueCerulean();
70 return new ChartThemeBlueCerulean();
71 case QChart::ChartThemeLight:
71 case QChart::ChartThemeLight:
72 return new ChartThemeLight();
72 return new ChartThemeLight();
73 default:
73 default:
74 return new ChartThemeDefault();
74 return new ChartThemeDefault();
75 }
75 }
76 }
76 }
77
77
78 void ChartTheme::decorate(QChart* chart)
78 void ChartTheme::decorate(QChart* chart)
79 {
79 {
80 if (m_backgroundShades == BackgroundShadesNone) {
80 if (m_backgroundShades == BackgroundShadesNone) {
81 chart->setChartBackgroundBrush(m_chartBackgroundGradient);
81 chart->setChartBackgroundBrush(m_chartBackgroundGradient);
82 } else {
82 } else {
83 chart->setChartBackgroundBrush(Qt::NoBrush);
83 chart->setChartBackgroundBrush(Qt::NoBrush);
84 }
84 }
85 chart->setChartTitleFont(m_masterFont);
85 chart->setChartTitleFont(m_masterFont);
86 chart->setChartTitleBrush(m_titleBrush);
86 chart->setChartTitleBrush(m_titleBrush);
87 }
87 }
88
88
89 void ChartTheme::decorate(QLegend* legend)
89 void ChartTheme::decorate(QLegend* legend)
90 {
90 {
91 legend->setBackgroundBrush(m_chartBackgroundGradient);
91 legend->setBackgroundBrush(m_chartBackgroundGradient);
92 }
92 }
93
93
94 void ChartTheme::decorate(QAreaSeries* series, int index)
94 void ChartTheme::decorate(QAreaSeries* series, int index)
95 {
95 {
96 QPen pen;
96 QPen pen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
97 QBrush brush;
97 pen.setWidthF(2);
98 series->setPen(pen);
98
99
99 if (pen == series->pen()){
100 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
100 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
101 series->setBrush(brush);
101 pen.setWidthF(2);
102 series->setPen(pen);
103 }
104
105 if (brush == series->brush()) {
106 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
107 series->setBrush(brush);
108 }
109 }
102 }
110
103
111
104
112 void ChartTheme::decorate(QLineSeries* series,int index)
105 void ChartTheme::decorate(QLineSeries* series,int index)
113 {
106 {
114 QPen pen;
107 QPen pen(m_seriesColors.at(index%m_seriesColors.size()));
115 if(pen == series->pen()){
108 pen.setWidthF(2);
116 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
109 series->setPen(pen);
117 pen.setWidthF(2);
118 series->setPen(pen);
119 }
120 }
110 }
121
111
122 void ChartTheme::decorate(QBarSeries* series,int index)
112 void ChartTheme::decorate(QBarSeries* series,int index)
123 {
113 {
124 QList<QBarSet*> sets = series->barSets();
114 QList<QBarSet*> sets = series->barSets();
125 for (int i=0; i<sets.count(); i++) {
115 for (int i=0; i<sets.count(); i++) {
126 qreal pos = 0.5;
116 qreal pos = 0.5;
127 if (sets.count() > 1)
117 if (sets.count() > 1)
128 pos = (qreal) i / (qreal) (sets.count() - 1);
118 pos = (qreal) i / (qreal) (sets.count() - 1);
129 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
119 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
130 sets.at(i)->setBrush(QBrush(c));
120 sets.at(i)->setBrush(QBrush(c));
131
121
132 // Pick label color as far as possible from bar color (within gradient).
122 // Pick label color as far as possible from bar color (within gradient).
133 // 0.3 is magic number that was picked as value that gave enough contrast with icy theme gradient :)
123 // 0.3 is magic number that was picked as value that gave enough contrast with icy theme gradient :)
134 // TODO: better picking of label color?
124 // TODO: better picking of label color?
135 if (pos < 0.3) {
125 if (pos < 0.3) {
136 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
126 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
137 } else {
127 } else {
138 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
128 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
139 }
129 }
140 sets.at(i)->setFloatingValuePen(QPen(c));
130 sets.at(i)->setFloatingValuePen(QPen(c));
141 }
131 }
142 }
132 }
143
133
144 void ChartTheme::decorate(QStackedBarSeries* series,int index)
134 void ChartTheme::decorate(QStackedBarSeries* series,int index)
145 {
135 {
146 QList<QBarSet*> sets = series->barSets();
136 QList<QBarSet*> sets = series->barSets();
147 for (int i=0; i<sets.count(); i++) {
137 for (int i=0; i<sets.count(); i++) {
148 qreal pos = 0.5;
138 qreal pos = 0.5;
149 if (sets.count() > 1)
139 if (sets.count() > 1)
150 pos = (qreal) i / (qreal) (sets.count() - 1);
140 pos = (qreal) i / (qreal) (sets.count() - 1);
151 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
141 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
152 sets.at(i)->setBrush(QBrush(c));
142 sets.at(i)->setBrush(QBrush(c));
153
143
154 if (pos < 0.3) {
144 if (pos < 0.3) {
155 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
145 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
156 } else {
146 } else {
157 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
147 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
158 }
148 }
159 sets.at(i)->setFloatingValuePen(QPen(c));
149 sets.at(i)->setFloatingValuePen(QPen(c));
160 }
150 }
161 }
151 }
162
152
163 void ChartTheme::decorate(QPercentBarSeries* series,int index)
153 void ChartTheme::decorate(QPercentBarSeries* series,int index)
164 {
154 {
165 QList<QBarSet*> sets = series->barSets();
155 QList<QBarSet*> sets = series->barSets();
166 for (int i=0; i<sets.count(); i++) {
156 for (int i=0; i<sets.count(); i++) {
167 qreal pos = 0.5;
157 qreal pos = 0.5;
168 if (sets.count() > 1)
158 if (sets.count() > 1)
169 pos = (qreal) i / (qreal) (sets.count() - 1);
159 pos = (qreal) i / (qreal) (sets.count() - 1);
170 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
160 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
171 sets.at(i)->setBrush(QBrush(c));
161 sets.at(i)->setBrush(QBrush(c));
172
162
173 if (pos < 0.3) {
163 if (pos < 0.3) {
174 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
164 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1);
175 } else {
165 } else {
176 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
166 c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0);
177 }
167 }
178 sets.at(i)->setFloatingValuePen(QPen(c));
168 sets.at(i)->setFloatingValuePen(QPen(c));
179 }
169 }
180 }
170 }
181
171
182 void ChartTheme::decorate(QScatterSeries* series, int index)
172 void ChartTheme::decorate(QScatterSeries* series, int index)
183 {
173 {
174 QPen pen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
175 pen.setWidthF(2);
176 series->setPen(pen);
184
177
185 QPen pen;
178 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
186 QBrush brush;
179 series->setBrush(brush);
187
188 if (pen == series->pen()) {
189 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1.0));
190 pen.setWidthF(2);
191 series->setPen(pen);
192 }
193
194 if (brush == series->brush()) {
195 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
196 series->setBrush(brush);
197 }
198 }
180 }
199
181
200 void ChartTheme::decorate(QPieSeries* series, int index)
182 void ChartTheme::decorate(QPieSeries* series, int index)
201 {
183 {
202 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
184 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
203 for (int i(0); i < series->slices().count(); i++) {
185 for (int i(0); i < series->slices().count(); i++) {
204 qreal pos = (qreal) i / (qreal) series->count();
186 qreal pos = (qreal) i / (qreal) series->count();
205 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.1);
187 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.1);
206 series->slices().at(i)->setSlicePen(penColor);
188 series->slices().at(i)->setSlicePen(penColor);
207 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
189 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
208 series->slices().at(i)->setSliceBrush(brushColor);
190 series->slices().at(i)->setSliceBrush(brushColor);
209 }
191 }
210 }
192 }
211
193
212 void ChartTheme::decorate(QSplineSeries* series, int index)
194 void ChartTheme::decorate(QSplineSeries* series, int index)
213 {
195 {
214 QPen pen;
196 QPen pen(m_seriesColors.at(index%m_seriesColors.size()));
215 if(pen == series->pen()){
197 pen.setWidthF(2);
216 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
198 series->setPen(pen);
217 pen.setWidthF(2);
218 series->setPen(pen);
219 }
220 }
199 }
221
200
222 void ChartTheme::decorate(QChartAxis* axis,bool axisX)
201 void ChartTheme::decorate(QChartAxis* axis,bool axisX)
223 {
202 {
224 if (axis->isAxisVisible()) {
203 if (axis->isAxisVisible()) {
225 axis->setLabelsBrush(m_axisLabelBrush);
204 axis->setLabelsBrush(m_axisLabelBrush);
226 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
205 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
227 if (m_backgroundShades == BackgroundShadesBoth
206 if (m_backgroundShades == BackgroundShadesBoth
228 || (m_backgroundShades == BackgroundShadesVertical && axisX)
207 || (m_backgroundShades == BackgroundShadesVertical && axisX)
229 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX)) {
208 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX)) {
230 axis->setShadesPen(m_backgroundShadesPen);
209 axis->setShadesPen(m_backgroundShadesPen);
231 axis->setShadesBrush(m_backgroundShadesBrush);
210 axis->setShadesBrush(m_backgroundShadesBrush);
232 } else {
211 } else {
233 // The shades not supposed to be shown for this axis, clear possible brush and pen
212 // The shades not supposed to be shown for this axis, clear possible brush and pen
234 axis->setShadesPen(Qt::NoPen);
213 axis->setShadesPen(Qt::NoPen);
235 axis->setShadesBrush(Qt::NoBrush);
214 axis->setShadesBrush(Qt::NoBrush);
236 }
215 }
237 axis->setAxisPen(m_axisLinePen);
216 axis->setAxisPen(m_axisLinePen);
238 axis->setGridLinePen(m_gridLinePen);
217 axis->setGridLinePen(m_gridLinePen);
239 axis->setLabelsFont(m_masterFont);
218 axis->setLabelsFont(m_masterFont);
240 }
219 }
241 }
220 }
242
221
243 void ChartTheme::generateSeriesGradients()
222 void ChartTheme::generateSeriesGradients()
244 {
223 {
245 // Generate gradients in HSV color space
224 // Generate gradients in HSV color space
246 foreach (QColor color, m_seriesColors) {
225 foreach (QColor color, m_seriesColors) {
247 QLinearGradient g;
226 QLinearGradient g;
248 qreal h = color.hsvHueF();
227 qreal h = color.hsvHueF();
249 qreal s = color.hsvSaturationF();
228 qreal s = color.hsvSaturationF();
250
229
251 // TODO: tune the algorithm to give nice results with most base colors defined in
230 // TODO: tune the algorithm to give nice results with most base colors defined in
252 // most themes. The rest of the gradients we can define manually in theme specific
231 // most themes. The rest of the gradients we can define manually in theme specific
253 // implementation.
232 // implementation.
254 QColor start = color;
233 QColor start = color;
255 start.setHsvF(h, 0.05, 0.95);
234 start.setHsvF(h, 0.05, 0.95);
256 g.setColorAt(0.0, start);
235 g.setColorAt(0.0, start);
257
236
258 g.setColorAt(0.5, color);
237 g.setColorAt(0.5, color);
259
238
260 QColor end = color;
239 QColor end = color;
261 end.setHsvF(h, s, 0.25);
240 end.setHsvF(h, s, 0.25);
262 g.setColorAt(1.0, end);
241 g.setColorAt(1.0, end);
263
242
264 m_seriesGradients << g;
243 m_seriesGradients << g;
265 }
244 }
266 }
245 }
267
246
268
247
269 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
248 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
270 {
249 {
271 Q_ASSERT(pos >=0.0 && pos <= 1.0);
250 Q_ASSERT(pos >=0.0 && pos <= 1.0);
272 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
251 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
273 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
252 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
274 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
253 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
275 QColor c;
254 QColor c;
276 c.setRgbF(r, g, b);
255 c.setRgbF(r, g, b);
277 return c;
256 return c;
278 }
257 }
279
258
280 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
259 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
281 {
260 {
282 Q_ASSERT(pos >=0 && pos <= 1.0);
261 Q_ASSERT(pos >=0 && pos <= 1.0);
283
262
284 // another possibility:
263 // another possibility:
285 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
264 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
286
265
287 QGradientStops stops = gradient.stops();
266 QGradientStops stops = gradient.stops();
288 int count = stops.count();
267 int count = stops.count();
289
268
290 // find previous stop relative to position
269 // find previous stop relative to position
291 QGradientStop prev = stops.first();
270 QGradientStop prev = stops.first();
292 for (int i=0; i<count; i++) {
271 for (int i=0; i<count; i++) {
293 QGradientStop stop = stops.at(i);
272 QGradientStop stop = stops.at(i);
294 if (pos > stop.first)
273 if (pos > stop.first)
295 prev = stop;
274 prev = stop;
296
275
297 // given position is actually a stop position?
276 // given position is actually a stop position?
298 if (pos == stop.first) {
277 if (pos == stop.first) {
299 //qDebug() << "stop color" << pos;
278 //qDebug() << "stop color" << pos;
300 return stop.second;
279 return stop.second;
301 }
280 }
302 }
281 }
303
282
304 // find next stop relative to position
283 // find next stop relative to position
305 QGradientStop next = stops.last();
284 QGradientStop next = stops.last();
306 for (int i=count-1; i>=0; i--) {
285 for (int i=count-1; i>=0; i--) {
307 QGradientStop stop = stops.at(i);
286 QGradientStop stop = stops.at(i);
308 if (pos < stop.first)
287 if (pos < stop.first)
309 next = stop;
288 next = stop;
310 }
289 }
311
290
312 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
291 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
313
292
314 qreal range = next.first - prev.first;
293 qreal range = next.first - prev.first;
315 qreal posDelta = pos - prev.first;
294 qreal posDelta = pos - prev.first;
316 qreal relativePos = posDelta / range;
295 qreal relativePos = posDelta / range;
317
296
318 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
297 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
319
298
320 return colorAt(prev.second, next.second, relativePos);
299 return colorAt(prev.second, next.second, relativePos);
321 }
300 }
322
301
323 QTCOMMERCIALCHART_END_NAMESPACE
302 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now