/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Charts module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "chartview.h" #include #include #include #include #include #include #include #include #include QT_CHARTS_USE_NAMESPACE #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), m_xMin(0.0), m_xMax(20.0), m_yMin(0.0), m_yMax(10.0), m_backgroundBrush(new QBrush(Qt::white)), m_plotAreaBackgroundBrush(new QBrush(Qt::NoBrush)), m_backgroundPen(new QPen(Qt::NoPen)), m_plotAreaBackgroundPen(new QPen(Qt::NoPen)), m_animationOptions(QChart::NoAnimation), m_chart(0), m_xAxis(0), m_yAxis(0), m_xAxisMode(AxisModeValue), m_yAxisMode(AxisModeValue), m_pointCount(100) { ui->setupUi(this); ui->yMinSpin->setValue(m_yMin); ui->yMaxSpin->setValue(m_yMax); ui->xMinSpin->setValue(m_xMin); ui->xMaxSpin->setValue(m_xMax); initXYValueChart(); setXAxis(AxisModeValue); setYAxis(AxisModeValue); connect(ui->yMinSpin, SIGNAL(valueChanged(double)), this, SLOT(yMinChanged(double))); connect(ui->yMaxSpin, SIGNAL(valueChanged(double)), this, SLOT(yMaxChanged(double))); connect(ui->xMinSpin, SIGNAL(valueChanged(double)), this, SLOT(xMinChanged(double))); connect(ui->xMaxSpin, SIGNAL(valueChanged(double)), this, SLOT(xMaxChanged(double))); connect(ui->animationsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(animationIndexChanged(int))); connect(ui->xAxisComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(xAxisIndexChanged(int))); connect(ui->yAxisComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(yAxisIndexChanged(int))); connect(ui->backgroundComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundIndexChanged(int))); connect(ui->plotAreaComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(plotAreaIndexChanged(int))); connect(ui->themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(themeIndexChanged(int))); connect(ui->addSeriesButton, SIGNAL(clicked(bool)), this, SLOT(addSeriesClicked())); connect(ui->addGLSeriesButton, SIGNAL(clicked(bool)), this, SLOT(addGLSeriesClicked())); connect(ui->removeSeriesButton, SIGNAL(clicked(bool)), this, SLOT(removeSeriesClicked())); connect(ui->countComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(countIndexChanged(int))); connect(ui->colorsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(colorIndexChanged(int))); connect(ui->widthComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widthIndexChanged(int))); ui->chartView->setChart(m_chart); ui->chartView->setRenderHint(QPainter::Antialiasing); QObject::connect(m_chart->scene(), &QGraphicsScene::changed, &m_dataSource, &DataSource::handleSceneChanged); m_dataSource.startUpdates(m_seriesList, ui->fpsLabel); } MainWindow::~MainWindow() { delete ui; } void MainWindow::initXYValueChart() { m_chart = new QChart(); m_chart->setTitle("Use arrow keys to scroll and +/- to zoom"); m_chart->setAnimationOptions(m_animationOptions); m_chart->setBackgroundBrush(*m_backgroundBrush); m_chart->setBackgroundPen(*m_backgroundPen); m_chart->setPlotAreaBackgroundBrush(*m_plotAreaBackgroundBrush); m_chart->setPlotAreaBackgroundPen(*m_plotAreaBackgroundPen); } void MainWindow::setXAxis(MainWindow::AxisMode mode) { if (m_xAxis) { m_chart->removeAxis(m_xAxis); delete m_xAxis; m_xAxis = 0; } m_xAxisMode = mode; switch (m_xAxisMode) { case AxisModeNone: return; case AxisModeValue: m_xAxis = new QValueAxis(); break; case AxisModeLogValue: m_xAxis = new QLogValueAxis(); break; case AxisModeDateTime: m_xAxis = new QDateTimeAxis(); break; case AxisModeCategory: m_xAxis = new QCategoryAxis(); applyCategories(); break; default: qWarning() << "Unsupported AxisMode"; return; } m_chart->addAxis(m_xAxis, Qt::AlignBottom); foreach (QAbstractSeries *series, m_seriesList) series->attachAxis(m_xAxis); applyRanges(); } void MainWindow::setYAxis(MainWindow::AxisMode mode) { if (m_yAxis) { m_chart->removeAxis(m_yAxis); delete m_yAxis; m_yAxis = 0; } m_yAxisMode = mode; switch (m_yAxisMode) { case AxisModeNone: return; case AxisModeValue: m_yAxis = new QValueAxis(); break; case AxisModeLogValue: m_yAxis = new QLogValueAxis(); break; case AxisModeDateTime: m_yAxis = new QDateTimeAxis(); break; case AxisModeCategory: m_yAxis = new QCategoryAxis(); applyCategories(); break; default: qWarning() << "Unsupported AxisMode"; return; } m_chart->addAxis(m_yAxis, Qt::AlignLeft); foreach (QAbstractSeries *series, m_seriesList) series->attachAxis(m_yAxis); applyRanges(); } void MainWindow::applyRanges() { if (m_xAxis) { if (m_xAxisMode == AxisModeLogValue) { if (m_xMin <= 0) m_xMin = 1.0; if (m_xMax <= m_xMin) m_xMax = m_xMin + 1.0; } if (m_xAxisMode == AxisModeDateTime) { QDateTime dateTimeMin; QDateTime dateTimeMax; dateTimeMin.setMSecsSinceEpoch(qint64(m_xMin)); dateTimeMax.setMSecsSinceEpoch(qint64(m_xMax)); m_xAxis->setRange(dateTimeMin, dateTimeMax); } else { m_xAxis->setRange(m_xMin, m_xMax); } ui->xMinSpin->setValue(m_xMin); ui->xMaxSpin->setValue(m_xMax); } if (m_yAxis) { if (m_yAxisMode == AxisModeLogValue) { if (m_yMin <= 0) m_yMin = 1.0; if (m_yMax <= m_yMin) m_yMax = m_yMin + 1.0; } if (m_yAxisMode == AxisModeDateTime) { QDateTime dateTimeMin; QDateTime dateTimeMax; dateTimeMin.setMSecsSinceEpoch(qint64(m_yMin)); dateTimeMax.setMSecsSinceEpoch(qint64(m_yMax)); m_yAxis->setRange(dateTimeMin, dateTimeMax); } else { m_yAxis->setRange(m_yMin, m_yMax); } ui->yMinSpin->setValue(m_yMin); ui->yMaxSpin->setValue(m_yMax); } } void MainWindow::xMinChanged(double value) { m_xMin = value; applyRanges(); } void MainWindow::xMaxChanged(double value) { m_xMax = value; applyRanges(); } void MainWindow::yMinChanged(double value) { m_yMin = value; applyRanges(); } void MainWindow::yMaxChanged(double value) { m_yMax = value; applyRanges(); } void MainWindow::animationIndexChanged(int index) { switch (index) { case 0: m_animationOptions = QChart::NoAnimation; break; case 1: m_animationOptions = QChart::SeriesAnimations; break; case 2: m_animationOptions = QChart::GridAxisAnimations; break; case 3: m_animationOptions = QChart::AllAnimations; break; default: break; } m_chart->setAnimationOptions(m_animationOptions); } void MainWindow::xRangeChanged(qreal min, qreal max) { if (!qFuzzyCompare(qreal(ui->xMinSpin->value()), min)) ui->xMinSpin->setValue(min); if (!qFuzzyCompare(qreal(ui->xMaxSpin->value()), max)) ui->xMaxSpin->setValue(max); } void MainWindow::yRangeChanged(qreal min, qreal max) { if (!qFuzzyCompare(qreal(ui->yMinSpin->value()), min)) ui->yMinSpin->setValue(min); if (!qFuzzyCompare(qreal(ui->yMaxSpin->value()), max)) ui->yMaxSpin->setValue(max); } void MainWindow::xAxisIndexChanged(int index) { switch (index) { case 0: setXAxis(AxisModeNone); break; case 1: setXAxis(AxisModeValue); break; case 2: setXAxis(AxisModeLogValue); break; case 3: setXAxis(AxisModeDateTime); break; case 4: setXAxis(AxisModeCategory); break; default: qWarning("Invalid Index!"); } } void MainWindow::yAxisIndexChanged(int index) { switch (index) { case 0: setYAxis(AxisModeNone); break; case 1: setYAxis(AxisModeValue); break; case 2: setYAxis(AxisModeLogValue); break; case 3: setYAxis(AxisModeDateTime); break; case 4: setYAxis(AxisModeCategory); break; default: qWarning("Invalid Index!"); } } void MainWindow::themeIndexChanged(int index) { m_chart->setTheme(QChart::ChartTheme(index)); } void MainWindow::addSeriesClicked() { addSeries(false); } void MainWindow::removeSeriesClicked() { if (m_seriesList.size()) { QXYSeries *series = m_seriesList.takeAt(m_seriesList.size() - 1); m_chart->removeSeries(series); delete series; } } void MainWindow::addGLSeriesClicked() { addSeries(true); } void MainWindow::countIndexChanged(int index) { m_pointCount = ui->countComboBox->itemText(index).toInt(); for (int i = 0; i < m_seriesList.size(); i++) { m_dataSource.generateData(i, 2, m_pointCount); } } void MainWindow::colorIndexChanged(int index) { QColor color = QColor(ui->colorsComboBox->itemText(index).toLower()); foreach (QXYSeries *series, m_seriesList) { if (series->type() == QAbstractSeries::SeriesTypeScatter) { QScatterSeries *scatterSeries = static_cast(series); scatterSeries->setBorderColor(color); scatterSeries->setColor(color); } else { series->setColor(color); } } } void MainWindow::widthIndexChanged(int index) { int width = ui->widthComboBox->itemText(index).toInt(); foreach (QXYSeries *series, m_seriesList) { if (series->type() == QAbstractSeries::SeriesTypeScatter) { QScatterSeries *scatterSeries = static_cast(series); scatterSeries->setMarkerSize(width); } else { QColor color = QColor(ui->colorsComboBox->itemText( ui->colorsComboBox->currentIndex()).toLower()); series->setPen(QPen(QBrush(color), width)); } } } void MainWindow::backgroundIndexChanged(int index) { delete m_backgroundBrush; delete m_backgroundPen; switch (index) { case 0: m_backgroundBrush = new QBrush(Qt::white); m_backgroundPen = new QPen(Qt::NoPen); break; case 1: m_backgroundBrush = new QBrush(Qt::blue); m_backgroundPen = new QPen(Qt::NoPen); break; case 2: m_backgroundBrush = new QBrush(Qt::yellow); m_backgroundPen = new QPen(Qt::black, 2); break; default: break; } m_chart->setBackgroundBrush(*m_backgroundBrush); m_chart->setBackgroundPen(*m_backgroundPen); } void MainWindow::plotAreaIndexChanged(int index) { delete m_plotAreaBackgroundBrush; delete m_plotAreaBackgroundPen; switch (index) { case 0: m_plotAreaBackgroundBrush = new QBrush(Qt::green); m_plotAreaBackgroundPen = new QPen(Qt::green); m_chart->setPlotAreaBackgroundVisible(false); break; case 1: m_plotAreaBackgroundBrush = new QBrush(Qt::magenta); m_plotAreaBackgroundPen = new QPen(Qt::NoPen); m_chart->setPlotAreaBackgroundVisible(true); break; case 2: m_plotAreaBackgroundBrush = new QBrush(Qt::lightGray); m_plotAreaBackgroundPen = new QPen(Qt::red, 6); m_chart->setPlotAreaBackgroundVisible(true); break; default: break; } m_chart->setPlotAreaBackgroundBrush(*m_plotAreaBackgroundBrush); m_chart->setPlotAreaBackgroundPen(*m_plotAreaBackgroundPen); } void MainWindow::applyCategories() { // Basic layout is three categories, extended has five if (m_xAxisMode == AxisModeCategory) { QCategoryAxis *angCatAxis = static_cast(m_xAxis); if (angCatAxis->count() == 0) { angCatAxis->setStartValue(2); angCatAxis->append("Category A", 6); angCatAxis->append("Category B", 12); angCatAxis->append("Category C", 18); } } if (m_yAxisMode == AxisModeCategory) { QCategoryAxis *radCatAxis = static_cast(m_yAxis); if (radCatAxis->count() == 0) { radCatAxis->setStartValue(1); radCatAxis->append("Category 1", 3); radCatAxis->append("Category 2", 4); radCatAxis->append("Category 3", 8); } } } void MainWindow::addSeries(bool gl) { QColor color = QColor(ui->colorsComboBox->itemText(ui->colorsComboBox->currentIndex()).toLower()); int width = ui->widthComboBox->itemText(ui->widthComboBox->currentIndex()).toInt(); if (m_seriesList.size() < maxSeriesCount) { QXYSeries *series; if (qrand() % 2) { series = new QLineSeries; series->setPen(QPen(QBrush(color), width)); } else { QScatterSeries *scatterSeries = new QScatterSeries; scatterSeries->setMarkerSize(width); scatterSeries->setBorderColor(color); scatterSeries->setBrush(QBrush(color)); series = scatterSeries; } series->setUseOpenGL(gl); m_dataSource.generateData(m_seriesList.size(), 2, m_pointCount); m_seriesList.append(series); m_chart->addSeries(series); if (m_xAxis) series->attachAxis(m_xAxis); if (m_yAxis) series->attachAxis(m_yAxis); applyRanges(); } }