1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Charts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29#include <private/qabstractseries_p.h>
30#include <private/qabstractaxis_p.h>
31//themes
32#include <private/chartthemesystem_p.h>
33#include <private/chartthemelight_p.h>
34#include <private/chartthemebluecerulean_p.h>
35#include <private/chartthemedark_p.h>
36#include <private/chartthemebrownsand_p.h>
37#include <private/chartthemebluencs_p.h>
38#include <private/chartthemehighcontrast_p.h>
39#include <private/chartthemeblueicy_p.h>
40#include <private/chartthemeqt_p.h>
41
42QT_CHARTS_BEGIN_NAMESPACE
43
44ChartThemeManager::ChartThemeManager(QChart* chart) :
45 m_chart(chart)
46{
47}
48
49
50void ChartThemeManager::setTheme(QChart::ChartTheme theme)
51{
52 if (m_theme.isNull() || theme != m_theme->id()) {
53 switch (theme) {
54 case QChart::ChartThemeLight:
55 m_theme.reset(other: new ChartThemeLight());
56 break;
57 case QChart::ChartThemeBlueCerulean:
58 m_theme.reset(other: new ChartThemeBlueCerulean());
59 break;
60 case QChart::ChartThemeDark:
61 m_theme.reset(other: new ChartThemeDark());
62 break;
63 case QChart::ChartThemeBrownSand:
64 m_theme.reset(other: new ChartThemeBrownSand());
65 break;
66 case QChart::ChartThemeBlueNcs:
67 m_theme.reset(other: new ChartThemeBlueNcs());
68 break;
69 case QChart::ChartThemeHighContrast:
70 m_theme.reset(other: new ChartThemeHighContrast());
71 break;
72 case QChart::ChartThemeBlueIcy:
73 m_theme.reset(other: new ChartThemeBlueIcy());
74 break;
75 case QChart::ChartThemeQt:
76 m_theme.reset(other: new ChartThemeQt());
77 break;
78 default:
79 m_theme.reset(other: new ChartThemeSystem());
80 break;
81 }
82
83 if (!m_theme.isNull()) {
84 decorateChart(chart: m_chart,theme: m_theme.data());
85 decorateLegend(legend: m_chart->legend(),theme: m_theme.data());
86 foreach (QAbstractAxis* axis, m_axisList)
87 axis->d_ptr->initializeTheme(theme: m_theme.data(), forced: true);
88 foreach (QAbstractSeries* series, m_seriesMap.keys())
89 series->d_ptr->initializeTheme(index: m_seriesMap[series], theme: m_theme.data(), forced: true);
90 }
91 }
92}
93
94// decorateChart is only called when theme is forcibly initialized
95void ChartThemeManager::decorateChart(QChart *chart, ChartTheme *theme) const
96{
97 chart->setBackgroundBrush(theme->chartBackgroundGradient());
98
99 QPen pen(Qt::transparent);
100 QBrush brush;
101 chart->setPlotAreaBackgroundBrush(brush);
102 chart->setPlotAreaBackgroundPen(pen);
103 chart->setPlotAreaBackgroundVisible(false);
104
105 chart->setTitleFont(theme->masterFont());
106 chart->setTitleBrush(theme->labelBrush());
107 chart->setDropShadowEnabled(theme->isBackgroundDropShadowEnabled());
108}
109
110// decorateLegend is only called when theme is forcibly initialized
111void ChartThemeManager::decorateLegend(QLegend *legend, ChartTheme *theme) const
112{
113 legend->setPen(theme->axisLinePen());
114 legend->setBrush(theme->chartBackgroundGradient());
115 legend->setFont(theme->labelFont());
116 legend->setLabelBrush(theme->labelBrush());
117}
118
119int ChartThemeManager::createIndexKey(QList<int> keys) const
120{
121 std::sort(first: keys.begin(), last: keys.end());
122
123 int key = 0;
124 QList<int>::iterator i;
125 i = keys.begin();
126
127 while (i != keys.end()) {
128 if (*i != key)
129 break;
130 key++;
131 i++;
132 }
133
134 return key;
135}
136
137int ChartThemeManager::seriesCount(QAbstractSeries::SeriesType type) const
138{
139 int count = 0;
140 QList<QAbstractSeries *> series = m_seriesMap.keys();
141 foreach(QAbstractSeries *s, series) {
142 if (s->type() == type)
143 count++;
144 }
145 return count;
146}
147
148void ChartThemeManager::handleSeriesAdded(QAbstractSeries *series)
149{
150 int key = createIndexKey(keys: m_seriesMap.values());
151 m_seriesMap.insert(key: series,value: key);
152 series->d_ptr->initializeTheme(index: key,theme: m_theme.data(),forced: false);
153}
154
155void ChartThemeManager::handleSeriesRemoved(QAbstractSeries *series)
156{
157 m_seriesMap.remove(key: series);
158}
159
160void ChartThemeManager::handleAxisAdded(QAbstractAxis *axis)
161{
162 m_axisList.append(t: axis);
163 axis->d_ptr->initializeTheme(theme: m_theme.data(),forced: false);
164}
165
166void ChartThemeManager::handleAxisRemoved(QAbstractAxis *axis)
167{
168 m_axisList.removeAll(t: axis);
169}
170
171void ChartThemeManager::updateSeries(QAbstractSeries *series)
172{
173 if(m_seriesMap.contains(key: series)){
174 series->d_ptr->initializeTheme(index: m_seriesMap[series],theme: m_theme.data(),forced: false);
175 }
176}
177QList<QGradient> ChartThemeManager::generateSeriesGradients(const QList<QColor>& colors)
178{
179 QList<QGradient> result;
180 // Generate gradients in HSV color space
181 foreach (const QColor &color, colors) {
182 QLinearGradient g;
183 qreal h = color.hsvHueF();
184 qreal s = color.hsvSaturationF();
185
186 QColor start = color;
187 start.setHsvF(h, s: 0.0, v: 1.0);
188 g.setColorAt(pos: 0.0, color: start);
189
190 g.setColorAt(pos: 0.5, color);
191
192 QColor end = color;
193 end.setHsvF(h, s, v: 0.25);
194 g.setColorAt(pos: 1.0, color: end);
195
196 result << g;
197 }
198
199 return result;
200}
201
202
203QColor ChartThemeManager::colorAt(const QColor &start, const QColor &end, qreal pos)
204{
205 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
206 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
207 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
208 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
209 QColor c;
210 c.setRgbF(r, g, b);
211 return c;
212}
213
214QColor ChartThemeManager::colorAt(const QGradient &gradient, qreal pos)
215{
216 Q_ASSERT(pos >= 0 && pos <= 1.0);
217
218 QGradientStops stops = gradient.stops();
219 int count = stops.count();
220
221 // find previous stop relative to position
222 QGradientStop prev = stops.first();
223 for (int i = 0; i < count; i++) {
224 QGradientStop stop = stops.at(i);
225 if (pos > stop.first)
226 prev = stop;
227
228 // given position is actually a stop position?
229 if (pos == stop.first) {
230 //qDebug() << "stop color" << pos;
231 return stop.second;
232 }
233 }
234
235 // find next stop relative to position
236 QGradientStop next = stops.last();
237 for (int i = count - 1; i >= 0; i--) {
238 QGradientStop stop = stops.at(i);
239 if (pos < stop.first)
240 next = stop;
241 }
242
243 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
244
245 qreal range = next.first - prev.first;
246 qreal posDelta = pos - prev.first;
247 qreal relativePos = posDelta / range;
248
249 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
250
251 return colorAt(start: prev.second, end: next.second, pos: relativePos);
252}
253
254QT_CHARTS_END_NAMESPACE
255
256#include "moc_chartthememanager_p.cpp"
257

source code of qtcharts/src/charts/chartthememanager.cpp