1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
5
6#include <private/qabstractseries_p.h>
7#include <private/qabstractaxis_p.h>
8//themes
9#include <private/chartthemesystem_p.h>
10#include <private/chartthemelight_p.h>
11#include <private/chartthemebluecerulean_p.h>
12#include <private/chartthemedark_p.h>
13#include <private/chartthemebrownsand_p.h>
14#include <private/chartthemebluencs_p.h>
15#include <private/chartthemehighcontrast_p.h>
16#include <private/chartthemeblueicy_p.h>
17#include <private/chartthemeqt_p.h>
18
19QT_BEGIN_NAMESPACE
20
21ChartThemeManager::ChartThemeManager(QChart* chart) :
22 m_chart(chart)
23{
24}
25
26
27void ChartThemeManager::setTheme(QChart::ChartTheme theme)
28{
29 if (m_theme.isNull() || theme != m_theme->id()) {
30 switch (theme) {
31 case QChart::ChartThemeLight:
32 m_theme.reset(other: new ChartThemeLight());
33 break;
34 case QChart::ChartThemeBlueCerulean:
35 m_theme.reset(other: new ChartThemeBlueCerulean());
36 break;
37 case QChart::ChartThemeDark:
38 m_theme.reset(other: new ChartThemeDark());
39 break;
40 case QChart::ChartThemeBrownSand:
41 m_theme.reset(other: new ChartThemeBrownSand());
42 break;
43 case QChart::ChartThemeBlueNcs:
44 m_theme.reset(other: new ChartThemeBlueNcs());
45 break;
46 case QChart::ChartThemeHighContrast:
47 m_theme.reset(other: new ChartThemeHighContrast());
48 break;
49 case QChart::ChartThemeBlueIcy:
50 m_theme.reset(other: new ChartThemeBlueIcy());
51 break;
52 case QChart::ChartThemeQt:
53 m_theme.reset(other: new ChartThemeQt());
54 break;
55 default:
56 m_theme.reset(other: new ChartThemeSystem());
57 break;
58 }
59
60 if (!m_theme.isNull()) {
61 decorateChart(chart: m_chart,theme: m_theme.data());
62 decorateLegend(legend: m_chart->legend(),theme: m_theme.data());
63 foreach (QAbstractAxis* axis, m_axisList)
64 axis->d_ptr->initializeTheme(theme: m_theme.data(), forced: true);
65 foreach (QAbstractSeries* series, m_seriesMap.keys())
66 series->d_ptr->initializeTheme(index: m_seriesMap[series], theme: m_theme.data(), forced: true);
67 }
68 }
69}
70
71// decorateChart is only called when theme is forcibly initialized
72void ChartThemeManager::decorateChart(QChart *chart, ChartTheme *theme) const
73{
74 chart->setBackgroundBrush(theme->chartBackgroundGradient());
75
76 QPen pen(Qt::transparent);
77 QBrush brush;
78 chart->setPlotAreaBackgroundBrush(brush);
79 chart->setPlotAreaBackgroundPen(pen);
80 chart->setPlotAreaBackgroundVisible(false);
81
82 chart->setTitleFont(theme->masterFont());
83 chart->setTitleBrush(theme->labelBrush());
84 chart->setDropShadowEnabled(theme->isBackgroundDropShadowEnabled());
85}
86
87// decorateLegend is only called when theme is forcibly initialized
88void ChartThemeManager::decorateLegend(QLegend *legend, ChartTheme *theme) const
89{
90 legend->setPen(theme->axisLinePen());
91 legend->setBrush(theme->chartBackgroundGradient());
92 legend->setFont(theme->labelFont());
93 legend->setLabelBrush(theme->labelBrush());
94}
95
96int ChartThemeManager::createIndexKey(const QList<int> &keys) const
97{
98 auto keysCopy = keys;
99 std::sort(first: keysCopy.begin(), last: keysCopy.end());
100
101 int i = 0;
102 for (const auto key : keysCopy) {
103 if (i != key)
104 break;
105 ++i;
106 }
107 return i;
108}
109
110int ChartThemeManager::seriesCount(QAbstractSeries::SeriesType type) const
111{
112 int count = 0;
113 QList<QAbstractSeries *> series = m_seriesMap.keys();
114 foreach(QAbstractSeries *s, series) {
115 if (s->type() == type)
116 count++;
117 }
118 return count;
119}
120
121void ChartThemeManager::handleSeriesAdded(QAbstractSeries *series)
122{
123 int key = createIndexKey(keys: m_seriesMap.values());
124 m_seriesMap.insert(key: series,value: key);
125 series->d_ptr->initializeTheme(index: key,theme: m_theme.data(),forced: false);
126}
127
128void ChartThemeManager::handleSeriesRemoved(QAbstractSeries *series)
129{
130 m_seriesMap.remove(key: series);
131}
132
133void ChartThemeManager::handleAxisAdded(QAbstractAxis *axis)
134{
135 m_axisList.append(t: axis);
136 axis->d_ptr->initializeTheme(theme: m_theme.data(),forced: false);
137}
138
139void ChartThemeManager::handleAxisRemoved(QAbstractAxis *axis)
140{
141 m_axisList.removeAll(t: axis);
142}
143
144void ChartThemeManager::updateSeries(QAbstractSeries *series)
145{
146 if(m_seriesMap.contains(key: series)){
147 series->d_ptr->initializeTheme(index: m_seriesMap[series],theme: m_theme.data(),forced: false);
148 }
149}
150QList<QGradient> ChartThemeManager::generateSeriesGradients(const QList<QColor>& colors)
151{
152 QList<QGradient> result;
153 // Generate gradients in HSV color space
154 foreach (const QColor &color, colors) {
155 QLinearGradient g;
156 qreal h = color.hsvHueF();
157 qreal s = color.hsvSaturationF();
158
159 QColor start = color;
160 start.setHsvF(h, s: 0.0, v: 1.0);
161 g.setColorAt(pos: 0.0, color: start);
162
163 g.setColorAt(pos: 0.5, color);
164
165 QColor end = color;
166 end.setHsvF(h, s, v: 0.25);
167 g.setColorAt(pos: 1.0, color: end);
168
169 result << g;
170 }
171
172 return result;
173}
174
175
176QColor ChartThemeManager::colorAt(const QColor &start, const QColor &end, qreal pos)
177{
178 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
179 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
180 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
181 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
182 QColor c;
183 c.setRgbF(r, g, b);
184 return c;
185}
186
187QColor ChartThemeManager::colorAt(const QGradient &gradient, qreal pos)
188{
189 Q_ASSERT(pos >= 0 && pos <= 1.0);
190
191 QGradientStops stops = gradient.stops();
192 int count = stops.size();
193
194 // find previous stop relative to position
195 QGradientStop prev = stops.first();
196 for (int i = 0; i < count; i++) {
197 QGradientStop stop = stops.at(i);
198 if (pos > stop.first)
199 prev = stop;
200
201 // given position is actually a stop position?
202 if (pos == stop.first) {
203 //qDebug() << "stop color" << pos;
204 return stop.second;
205 }
206 }
207
208 // find next stop relative to position
209 QGradientStop next = stops.last();
210 for (int i = count - 1; i >= 0; i--) {
211 QGradientStop stop = stops.at(i);
212 if (pos < stop.first)
213 next = stop;
214 }
215
216 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
217
218 qreal range = next.first - prev.first;
219 qreal posDelta = pos - prev.first;
220 qreal relativePos = posDelta / range;
221
222 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
223
224 return colorAt(start: prev.second, end: next.second, pos: relativePos);
225}
226
227QT_END_NAMESPACE
228
229#include "moc_chartthememanager_p.cpp"
230

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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