Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
++
++ #include "engine.h"
++ #include <QtCore/QItemSelectionModel>
++ #include <QtGui/QStandardItemModel>
++ #include <QtCharts/QVXYModelMapper>
++ #include <QtCharts/QHBarModelMapper>
++ #include <QtCharts/QVPieModelMapper>
++ #include <QtCharts/QLineSeries>
++ #include <QtCharts/QSplineSeries>
++ #include <QtCharts/QScatterSeries>
++ #include <QtCharts/QBarSeries>
++ #include <QtCharts/QPercentBarSeries>
++ #include <QtCharts/QStackedBarSeries>
++ #include <QtCharts/QAreaSeries>
++ #include <QtCharts/QPieSeries>
++ #include <QtCharts/QChart>
++ #include <QtCharts/QBarSet>
++
++
++ const qint32 MAGIC_NUMBER = 0x66666666;
++
++ Engine::Engine(QObject* parent) :
++ QObject(parent), m_count(10), m_chart(new QChart()), m_model(0), m_selection(0)
++ {
++ createModels();
++ }
++
++ Engine::~Engine()
++ {
++ delete m_chart;
++ delete m_selection;
++ delete m_model;
++ }
++
++ void Engine::createModels()
++ {
++ m_model = new QStandardItemModel(m_count, m_count);
++ m_model->setHorizontalHeaderLabels(
++ QStringList() << "A" << "B" << "C" << "D" << "E" << "F" << "G" << "H" << "I" << "J");
++ m_model->setVerticalHeaderLabels(
++ QStringList() << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8" << "9" << "10");
++ m_selection = new QItemSelectionModel(m_model);
++
++ }
++
++ QList<QAbstractSeries*> Engine::addSeries(QAbstractSeries::SeriesType type)
++ {
++ const QModelIndexList& list = m_selection->selectedIndexes();
++
++ QMultiMap<int, QModelIndex> columns;
++
++ for (const auto index : list) {
++ columns.insert(index.column(), index);
++ }
++
++ QList<int> keys = columns.uniqueKeys();
++
++ QModelIndexList rows = columns.values(keys.first());
++
++ int minRow = m_count + 1;
++ int maxRow = -1;
++
++ for (const auto index : rows) {
++ minRow = qMin(index.row(), minRow);
++ maxRow = qMax(index.row(), maxRow);
++ }
++
++ QList<QAbstractSeries*> result;
++ QColor color;
++
++ switch (type) {
++
++ case QAbstractSeries::SeriesTypeLine:
++ {
++ for (int i = 1; i < keys.count(); ++i) {
++ QLineSeries *line = new QLineSeries();
++ setupXYSeries(line, keys, i, minRow, maxRow);
++ result << line;
++ }
++ break;
++ }
++ case QAbstractSeries::SeriesTypeSpline:
++ {
++ for (int i = 1; i < keys.count(); ++i) {
++ QSplineSeries *line = new QSplineSeries();
++ setupXYSeries(line, keys, i, minRow, maxRow);
++ result << line;
++ }
++ break;
++ }
++ case QAbstractSeries::SeriesTypeScatter:
++ {
++ for (int i = 1; i < keys.count(); ++i) {
++ QScatterSeries *line = new QScatterSeries();
++ setupXYSeries(line, keys, i, minRow, maxRow);
++ result << line;
++ }
++ break;
++ }
++ case QAbstractSeries::SeriesTypeBar:
++ {
++ QBarSeries *bar = new QBarSeries();
++ setupBarSeries(bar,keys,minRow,maxRow);
++ result << bar;
++ break;
++ }
++ case QAbstractSeries::SeriesTypePercentBar:
++ {
++ QPercentBarSeries *bar = new QPercentBarSeries();
++ setupBarSeries(bar,keys,minRow,maxRow);
++ result << bar;
++ break;
++ }
++ case QAbstractSeries::SeriesTypeStackedBar:
++ {
++ QStackedBarSeries *bar = new QStackedBarSeries();
++ setupBarSeries(bar,keys,minRow,maxRow);
++ result << bar;
++ break;
++ }
++ case QAbstractSeries::SeriesTypePie:
++ {
++
++ QPieSeries *pie = new QPieSeries();
++ setupPieSeries(pie,keys,minRow,maxRow);
++ result << pie;
++ break;
++ }
++ case QAbstractSeries::SeriesTypeArea:
++ {
++ QAreaSeries *area = new QAreaSeries(new QLineSeries(), new QLineSeries());
++ setupAreaSeries(area,keys,minRow,maxRow);
++ result << area;
++ break;
++ }
++ }
++
++ m_chart->createDefaultAxes();
++ return result;
++ }
++
++ void Engine::removeSeries(QAbstractSeries* series)
++ {
++ m_chart->removeSeries(series);
++
++ for (const auto index : m_seriesModelIndex.value(series)) {
++ m_model->setData(index, QColor(Qt::white), Qt::BackgroundRole);
++ }
++ }
++
++ void Engine::clearModels()
++ {
++ delete m_selection;
++ m_selection = 0;
++ delete m_model;
++ m_model = 0;
++ createModels();
++ }
++
++ bool Engine::save(const QString &filename) const
++ {
++ if (filename.isEmpty())
++ return false;
++
++ QFile file(filename);
++
++ if (!file.open(QIODevice::WriteOnly)) {
++ return false;
++ }
++
++ QDataStream out(&file);
++ out << MAGIC_NUMBER;
++ out.setVersion(QDataStream::Qt_4_8);
++ out << m_model->rowCount();
++ out << m_model->columnCount();
++
++ for (int row = 0; row < m_model->rowCount(); ++row) {
++ for (int column = 0; column < m_model->columnCount(); ++column) {
++ QStandardItem *item = m_model->item(row, column);
++ if (item) {
++ out << row;
++ out << column;
++ out << item->data(Qt::EditRole).toString();
++ }
++ }
++ }
++ return true;
++ }
++
++ bool Engine::load(const QString &filename)
++ {
++ clearModels();
++
++ if (filename.isEmpty())
++ return false;
++
++ QFile file(filename);
++
++ if (!file.open(QIODevice::ReadOnly)) {
++ return false;
++ }
++
++ QDataStream in(&file);
++
++ qint32 magicNumber;
++ in >> magicNumber;
++
++ if (magicNumber != MAGIC_NUMBER)
++ return false;
++
++ in.setVersion(QDataStream::Qt_4_8);
++
++ int rowCount;
++ in >> rowCount;
++
++ int columnCount;
++ in >> columnCount;
++
++ while (!in.atEnd()) {
++ int row;
++ int column;
++ QString value;
++ in >> row >> column >> value;
++ QStandardItem *item = new QStandardItem();
++ bool ok;
++ double result = value.toDouble(&ok);
++ if(ok)
++ item->setData(result, Qt::EditRole);
++ else
++ item->setData(value, Qt::EditRole);
++ m_model->setItem(row, column, item);
++ }
++
++ return true;
++ }
++
++ void Engine::setupXYSeries(QXYSeries *xyseries, const QList<int>& columns, int column, int minRow, int maxRow)
++ {
++ QVXYModelMapper* mapper = new QVXYModelMapper(xyseries);
++ mapper->setSeries(xyseries);
++ mapper->setModel(m_model);
++ mapper->setXColumn(columns.first());
++ mapper->setYColumn(columns.at(column));
++ mapper->setFirstRow(minRow);
++ mapper->setRowCount(maxRow - minRow + 1);
++ m_chart->addSeries(xyseries);
++ xyseries->setName(QString("Series %1").arg(m_chart->series().count()));
++ QObject::connect(xyseries,SIGNAL(clicked(QPointF)),this,SIGNAL(selected()));
++ const QModelIndexList& list = m_selection->selectedIndexes();
++ QModelIndexList result;
++ for (const auto index : list) {
++ if (index.column() ==columns.at(column)){
++ m_model->setData(index, xyseries->pen().color(), Qt::BackgroundRole);
++ result << index;
++ }
++ }
++ m_seriesModelIndex.insert(xyseries,result);
++ }
++
++ void Engine::setupBarSeries(QAbstractBarSeries *bar, const QList<int>& columns, int minRow, int maxRow)
++ {
++ QHBarModelMapper* mapper = new QHBarModelMapper(bar);
++ mapper->setSeries(bar);
++ mapper->setModel(m_model);
++ mapper->setFirstColumn(minRow);
++ mapper->setColumnCount(maxRow - minRow + 1);
++ mapper->setFirstBarSetRow(columns.at(1));
++ mapper->setLastBarSetRow(columns.last());
++ m_chart->addSeries(bar);
++ bar->setName(QString("Series %1").arg(m_chart->series().count()));
++
++ const QModelIndexList& list = m_selection->selectedIndexes();
++ for (const auto index : list) {
++ if (index.column() >= columns.at(1) && index.column()<= columns.last()) {
++ //m_model->setData(index, bar->barSets().at(index.column())->brush().color(), Qt::BackgroundRole);
++ }
++ }
++ }
++
++ void Engine::setupPieSeries(QPieSeries *pie, const QList<int>& columns, int minRow, int maxRow)
++ {
++ QVPieModelMapper* mapper = new QVPieModelMapper(pie);
++ mapper->setSeries(pie);
++ mapper->setModel(m_model);
++ mapper->setValuesColumn(columns.at(1));
++ mapper->setLabelsColumn(columns.first());
++ mapper->setFirstRow(minRow);
++ mapper->setRowCount(maxRow - minRow + 1);
++ m_chart->addSeries(pie);
++ pie->setName(QString("Series %1").arg(m_chart->series().count()));
++
++ const QModelIndexList& list = m_selection->selectedIndexes();
++ for (const auto index : list) {
++ // m_model->setData(index, bar->barSets()pen().color(), Qt::BackgroundRole);
++ }
++ }
++
++ void Engine::setupAreaSeries(QAreaSeries *series, const QList<int>& columns, int minRow, int maxRow)
++ {
++ QVXYModelMapper* umapper = new QVXYModelMapper(series);
++ umapper->setSeries(series->upperSeries());
++ umapper->setModel(m_model);
++ umapper->setXColumn(columns.first());
++ umapper->setYColumn(columns.at(1));
++ umapper->setFirstRow(minRow);
++ umapper->setRowCount(maxRow - minRow + 1);
++
++ QVXYModelMapper* lmapper = new QVXYModelMapper(series);
++ lmapper->setSeries(series->lowerSeries());
++ lmapper->setModel(m_model);
++ lmapper->setXColumn(columns.first());
++ lmapper->setYColumn(columns.at(2));
++ lmapper->setFirstRow(minRow);
++ lmapper->setRowCount(maxRow - minRow + 1);
++
++ m_chart->addSeries(series);
++ series->setName(QString("Series %1").arg(m_chart->series().count()));
++
++ const QModelIndexList& list = m_selection->selectedIndexes();
++ for (const auto index : list) {
++ //if (index.column() ==columns.at(column))
++ // m_model->setData(index, xyseries->pen().color(), Qt::BackgroundRole);
++ }
++ }