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
30#include "themewidget.h"
31#include "ui_themewidget.h"
32
33#include <QtCharts/QChartView>
34#include <QtCharts/QPieSeries>
35#include <QtCharts/QPieSlice>
36#include <QtCharts/QAbstractBarSeries>
37#include <QtCharts/QPercentBarSeries>
38#include <QtCharts/QStackedBarSeries>
39#include <QtCharts/QBarSeries>
40#include <QtCharts/QBarSet>
41#include <QtCharts/QLineSeries>
42#include <QtCharts/QSplineSeries>
43#include <QtCharts/QScatterSeries>
44#include <QtCharts/QAreaSeries>
45#include <QtCharts/QLegend>
46#include <QtWidgets/QGridLayout>
47#include <QtWidgets/QFormLayout>
48#include <QtWidgets/QComboBox>
49#include <QtWidgets/QSpinBox>
50#include <QtWidgets/QCheckBox>
51#include <QtWidgets/QGroupBox>
52#include <QtWidgets/QLabel>
53#include <QtCore/QRandomGenerator>
54#include <QtCharts/QBarCategoryAxis>
55#include <QtWidgets/QApplication>
56#include <QtCharts/QValueAxis>
57
58ThemeWidget::ThemeWidget(QWidget *parent) :
59 QWidget(parent),
60 m_listCount(3),
61 m_valueMax(10),
62 m_valueCount(7),
63 m_dataTable(generateRandomData(listCount: m_listCount, valueMax: m_valueMax, valueCount: m_valueCount)),
64 m_ui(new Ui_ThemeWidgetForm)
65{
66 m_ui->setupUi(this);
67 populateThemeBox();
68 populateAnimationBox();
69 populateLegendBox();
70
71 //create charts
72
73 QChartView *chartView;
74
75 chartView = new QChartView(createAreaChart());
76 m_ui->gridLayout->addWidget(chartView, row: 1, column: 0);
77 m_charts << chartView;
78
79 chartView = new QChartView(createPieChart());
80 // Funny things happen if the pie slice labels do not fit the screen, so we ignore size policy
81 chartView->setSizePolicy(hor: QSizePolicy::Ignored, ver: QSizePolicy::Ignored);
82 m_ui->gridLayout->addWidget(chartView, row: 1, column: 1);
83 m_charts << chartView;
84
85 //![5]
86 chartView = new QChartView(createLineChart());
87 m_ui->gridLayout->addWidget(chartView, row: 1, column: 2);
88 //![5]
89 m_charts << chartView;
90
91 chartView = new QChartView(createBarChart(valueCount: m_valueCount));
92 m_ui->gridLayout->addWidget(chartView, row: 2, column: 0);
93 m_charts << chartView;
94
95 chartView = new QChartView(createSplineChart());
96 m_ui->gridLayout->addWidget(chartView, row: 2, column: 1);
97 m_charts << chartView;
98
99 chartView = new QChartView(createScatterChart());
100 m_ui->gridLayout->addWidget(chartView, row: 2, column: 2);
101 m_charts << chartView;
102
103 // Set defaults
104 m_ui->antialiasCheckBox->setChecked(true);
105
106 // Set the colors from the light theme as default ones
107 QPalette pal = qApp->palette();
108 pal.setColor(acr: QPalette::Window, acolor: QRgb(0xf0f0f0));
109 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x404044));
110 qApp->setPalette(pal);
111
112 updateUI();
113}
114
115ThemeWidget::~ThemeWidget()
116{
117 delete m_ui;
118}
119
120DataTable ThemeWidget::generateRandomData(int listCount, int valueMax, int valueCount) const
121{
122 DataTable dataTable;
123
124 // generate random data
125 for (int i(0); i < listCount; i++) {
126 DataList dataList;
127 qreal yValue(0);
128 for (int j(0); j < valueCount; j++) {
129 yValue = yValue + QRandomGenerator::global()->bounded(highest: valueMax / (qreal) valueCount);
130 QPointF value((j + QRandomGenerator::global()->generateDouble()) * ((qreal) m_valueMax / (qreal) valueCount),
131 yValue);
132 QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
133 dataList << Data(value, label);
134 }
135 dataTable << dataList;
136 }
137
138 return dataTable;
139}
140
141void ThemeWidget::populateThemeBox()
142{
143 // add items to theme combobox
144 m_ui->themeComboBox->addItem(atext: "Light", auserData: QChart::ChartThemeLight);
145 m_ui->themeComboBox->addItem(atext: "Blue Cerulean", auserData: QChart::ChartThemeBlueCerulean);
146 m_ui->themeComboBox->addItem(atext: "Dark", auserData: QChart::ChartThemeDark);
147 m_ui->themeComboBox->addItem(atext: "Brown Sand", auserData: QChart::ChartThemeBrownSand);
148 m_ui->themeComboBox->addItem(atext: "Blue NCS", auserData: QChart::ChartThemeBlueNcs);
149 m_ui->themeComboBox->addItem(atext: "High Contrast", auserData: QChart::ChartThemeHighContrast);
150 m_ui->themeComboBox->addItem(atext: "Blue Icy", auserData: QChart::ChartThemeBlueIcy);
151 m_ui->themeComboBox->addItem(atext: "Qt", auserData: QChart::ChartThemeQt);
152}
153
154void ThemeWidget::populateAnimationBox()
155{
156 // add items to animation combobox
157 m_ui->animatedComboBox->addItem(atext: "No Animations", auserData: QChart::NoAnimation);
158 m_ui->animatedComboBox->addItem(atext: "GridAxis Animations", auserData: QChart::GridAxisAnimations);
159 m_ui->animatedComboBox->addItem(atext: "Series Animations", auserData: QChart::SeriesAnimations);
160 m_ui->animatedComboBox->addItem(atext: "All Animations", auserData: QChart::AllAnimations);
161}
162
163void ThemeWidget::populateLegendBox()
164{
165 // add items to legend combobox
166 m_ui->legendComboBox->addItem(atext: "No Legend ", auserData: 0);
167 m_ui->legendComboBox->addItem(atext: "Legend Top", auserData: Qt::AlignTop);
168 m_ui->legendComboBox->addItem(atext: "Legend Bottom", auserData: Qt::AlignBottom);
169 m_ui->legendComboBox->addItem(atext: "Legend Left", auserData: Qt::AlignLeft);
170 m_ui->legendComboBox->addItem(atext: "Legend Right", auserData: Qt::AlignRight);
171}
172
173QChart *ThemeWidget::createAreaChart() const
174{
175 QChart *chart = new QChart();
176 chart->setTitle("Area chart");
177
178 // The lower series initialized to zero values
179 QLineSeries *lowerSeries = 0;
180 QString name("Series ");
181 int nameIndex = 0;
182 for (int i(0); i < m_dataTable.count(); i++) {
183 QLineSeries *upperSeries = new QLineSeries(chart);
184 for (int j(0); j < m_dataTable[i].count(); j++) {
185 Data data = m_dataTable[i].at(i: j);
186 if (lowerSeries) {
187 const QVector<QPointF>& points = lowerSeries->pointsVector();
188 upperSeries->append(point: QPointF(j, points[i].y() + data.first.y()));
189 } else {
190 upperSeries->append(point: QPointF(j, data.first.y()));
191 }
192 }
193 QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
194 area->setName(name + QString::number(nameIndex));
195 nameIndex++;
196 chart->addSeries(series: area);
197 lowerSeries = upperSeries;
198 }
199
200 chart->createDefaultAxes();
201 chart->axes(orientation: Qt::Horizontal).first()->setRange(min: 0, max: m_valueCount - 1);
202 chart->axes(orientation: Qt::Vertical).first()->setRange(min: 0, max: m_valueMax);
203 // Add space to label to add space between labels and axis
204 QValueAxis *axisY = qobject_cast<QValueAxis*>(object: chart->axes(orientation: Qt::Vertical).first());
205 Q_ASSERT(axisY);
206 axisY->setLabelFormat("%.1f ");
207
208 return chart;
209}
210
211QChart *ThemeWidget::createBarChart(int valueCount) const
212{
213 Q_UNUSED(valueCount);
214 QChart *chart = new QChart();
215 chart->setTitle("Bar chart");
216
217 QStackedBarSeries *series = new QStackedBarSeries(chart);
218 for (int i(0); i < m_dataTable.count(); i++) {
219 QBarSet *set = new QBarSet("Bar set " + QString::number(i));
220 for (const Data &data : m_dataTable[i])
221 *set << data.first.y();
222 series->append(set);
223 }
224 chart->addSeries(series);
225
226 chart->createDefaultAxes();
227 chart->axes(orientation: Qt::Vertical).first()->setRange(min: 0, max: m_valueMax * 2);
228 // Add space to label to add space between labels and axis
229 QValueAxis *axisY = qobject_cast<QValueAxis*>(object: chart->axes(orientation: Qt::Vertical).first());
230 Q_ASSERT(axisY);
231 axisY->setLabelFormat("%.1f ");
232
233 return chart;
234}
235
236QChart *ThemeWidget::createLineChart() const
237{
238 //![1]
239 QChart *chart = new QChart();
240 chart->setTitle("Line chart");
241 //![1]
242
243 //![2]
244 QString name("Series ");
245 int nameIndex = 0;
246 for (const DataList &list : m_dataTable) {
247 QLineSeries *series = new QLineSeries(chart);
248 for (const Data &data : list)
249 series->append(point: data.first);
250 series->setName(name + QString::number(nameIndex));
251 nameIndex++;
252 chart->addSeries(series);
253 }
254 //![2]
255
256 //![3]
257 chart->createDefaultAxes();
258 chart->axes(orientation: Qt::Horizontal).first()->setRange(min: 0, max: m_valueMax);
259 chart->axes(orientation: Qt::Vertical).first()->setRange(min: 0, max: m_valueCount);
260 //![3]
261 //![4]
262 // Add space to label to add space between labels and axis
263 QValueAxis *axisY = qobject_cast<QValueAxis*>(object: chart->axes(orientation: Qt::Vertical).first());
264 Q_ASSERT(axisY);
265 axisY->setLabelFormat("%.1f ");
266 //![4]
267
268 return chart;
269}
270
271QChart *ThemeWidget::createPieChart() const
272{
273 QChart *chart = new QChart();
274 chart->setTitle("Pie chart");
275
276 QPieSeries *series = new QPieSeries(chart);
277 for (const Data &data : m_dataTable[0]) {
278 QPieSlice *slice = series->append(label: data.second, value: data.first.y());
279 if (data == m_dataTable[0].first()) {
280 // Show the first slice exploded with label
281 slice->setLabelVisible();
282 slice->setExploded();
283 slice->setExplodeDistanceFactor(0.5);
284 }
285 }
286 series->setPieSize(0.4);
287 chart->addSeries(series);
288
289 return chart;
290}
291
292QChart *ThemeWidget::createSplineChart() const
293{
294 QChart *chart = new QChart();
295 chart->setTitle("Spline chart");
296 QString name("Series ");
297 int nameIndex = 0;
298 for (const DataList &list : m_dataTable) {
299 QSplineSeries *series = new QSplineSeries(chart);
300 for (const Data &data : list)
301 series->append(point: data.first);
302 series->setName(name + QString::number(nameIndex));
303 nameIndex++;
304 chart->addSeries(series);
305 }
306
307 chart->createDefaultAxes();
308 chart->axes(orientation: Qt::Horizontal).first()->setRange(min: 0, max: m_valueMax);
309 chart->axes(orientation: Qt::Vertical).first()->setRange(min: 0, max: m_valueCount);
310
311 // Add space to label to add space between labels and axis
312 QValueAxis *axisY = qobject_cast<QValueAxis*>(object: chart->axes(orientation: Qt::Vertical).first());
313 Q_ASSERT(axisY);
314 axisY->setLabelFormat("%.1f ");
315 return chart;
316}
317
318QChart *ThemeWidget::createScatterChart() const
319{
320 // scatter chart
321 QChart *chart = new QChart();
322 chart->setTitle("Scatter chart");
323 QString name("Series ");
324 int nameIndex = 0;
325 for (const DataList &list : m_dataTable) {
326 QScatterSeries *series = new QScatterSeries(chart);
327 for (const Data &data : list)
328 series->append(point: data.first);
329 series->setName(name + QString::number(nameIndex));
330 nameIndex++;
331 chart->addSeries(series);
332 }
333
334 chart->createDefaultAxes();
335 chart->axes(orientation: Qt::Horizontal).first()->setRange(min: 0, max: m_valueMax);
336 chart->axes(orientation: Qt::Vertical).first()->setRange(min: 0, max: m_valueCount);
337 // Add space to label to add space between labels and axis
338 QValueAxis *axisY = qobject_cast<QValueAxis*>(object: chart->axes(orientation: Qt::Vertical).first());
339 Q_ASSERT(axisY);
340 axisY->setLabelFormat("%.1f ");
341 return chart;
342}
343
344void ThemeWidget::updateUI()
345{
346 //![6]
347 QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(
348 m_ui->themeComboBox->itemData(index: m_ui->themeComboBox->currentIndex()).toInt());
349 //![6]
350 const auto charts = m_charts;
351 if (!m_charts.isEmpty() && m_charts.at(i: 0)->chart()->theme() != theme) {
352 for (QChartView *chartView : charts) {
353 //![7]
354 chartView->chart()->setTheme(theme);
355 //![7]
356 }
357
358 // Set palette colors based on selected theme
359 //![8]
360 QPalette pal = window()->palette();
361 if (theme == QChart::ChartThemeLight) {
362 pal.setColor(acr: QPalette::Window, acolor: QRgb(0xf0f0f0));
363 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x404044));
364 //![8]
365 } else if (theme == QChart::ChartThemeDark) {
366 pal.setColor(acr: QPalette::Window, acolor: QRgb(0x121218));
367 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0xd6d6d6));
368 } else if (theme == QChart::ChartThemeBlueCerulean) {
369 pal.setColor(acr: QPalette::Window, acolor: QRgb(0x40434a));
370 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0xd6d6d6));
371 } else if (theme == QChart::ChartThemeBrownSand) {
372 pal.setColor(acr: QPalette::Window, acolor: QRgb(0x9e8965));
373 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x404044));
374 } else if (theme == QChart::ChartThemeBlueNcs) {
375 pal.setColor(acr: QPalette::Window, acolor: QRgb(0x018bba));
376 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x404044));
377 } else if (theme == QChart::ChartThemeHighContrast) {
378 pal.setColor(acr: QPalette::Window, acolor: QRgb(0xffab03));
379 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x181818));
380 } else if (theme == QChart::ChartThemeBlueIcy) {
381 pal.setColor(acr: QPalette::Window, acolor: QRgb(0xcee7f0));
382 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x404044));
383 } else {
384 pal.setColor(acr: QPalette::Window, acolor: QRgb(0xf0f0f0));
385 pal.setColor(acr: QPalette::WindowText, acolor: QRgb(0x404044));
386 }
387 window()->setPalette(pal);
388 }
389
390 // Update antialiasing
391 //![11]
392 bool checked = m_ui->antialiasCheckBox->isChecked();
393 for (QChartView *chart : charts)
394 chart->setRenderHint(hint: QPainter::Antialiasing, enabled: checked);
395 //![11]
396
397 // Update animation options
398 //![9]
399 QChart::AnimationOptions options(
400 m_ui->animatedComboBox->itemData(index: m_ui->animatedComboBox->currentIndex()).toInt());
401 if (!m_charts.isEmpty() && m_charts.at(i: 0)->chart()->animationOptions() != options) {
402 for (QChartView *chartView : charts)
403 chartView->chart()->setAnimationOptions(options);
404 }
405 //![9]
406
407 // Update legend alignment
408 //![10]
409 Qt::Alignment alignment(
410 m_ui->legendComboBox->itemData(index: m_ui->legendComboBox->currentIndex()).toInt());
411
412 if (!alignment) {
413 for (QChartView *chartView : charts)
414 chartView->chart()->legend()->hide();
415 } else {
416 for (QChartView *chartView : charts) {
417 chartView->chart()->legend()->setAlignment(alignment);
418 chartView->chart()->legend()->show();
419 }
420 }
421 //![10]
422}
423
424

source code of qtcharts/examples/charts/chartthemes/themewidget.cpp