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