engine.cpp
341 lines
| 9.8 KiB
| text/x-c
|
CppLexer
Michal Klocek
|
r1126 | /**************************************************************************** | ||
Titta Heikkala
|
r2749 | ** | ||
Titta Heikkala
|
r2776 | ** Copyright (C) 2015 The Qt Company Ltd | ||
Titta Heikkala
|
r2749 | ** All rights reserved. | ||
Titta Heikkala
|
r2776 | ** For any questions to The Qt Company, please use contact form at http://qt.io | ||
Titta Heikkala
|
r2749 | ** | ||
** This file is part of the Qt Charts module. | ||||
** | ||||
** Licensees holding valid commercial license for Qt may use this file in | ||||
** accordance with the Qt License Agreement provided with the Software | ||||
** or, alternatively, in accordance with the terms contained in a written | ||||
Titta Heikkala
|
r2776 | ** agreement between you and The Qt Company. | ||
Titta Heikkala
|
r2749 | ** | ||
** If you have questions regarding the use of this file, please use | ||||
** contact form at http://qt.io | ||||
** | ||||
****************************************************************************/ | ||||
Michal Klocek
|
r1126 | |||
#include "engine.h" | ||||
Titta Heikkala
|
r2714 | #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> | ||||
Michal Klocek
|
r1126 | |||
Michal Klocek
|
r1199 | |||
Michal Klocek
|
r1126 | 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(); | ||||
QMap<int, QModelIndex> columns; | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, list) { | ||
Michal Klocek
|
r1126 | columns.insertMulti(index.column(), index); | ||
} | ||||
QList<int> keys = columns.uniqueKeys(); | ||||
QModelIndexList rows = columns.values(keys.first()); | ||||
int minRow = m_count + 1; | ||||
int maxRow = -1; | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, rows) { | ||
Michal Klocek
|
r1126 | 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: | ||||
{ | ||||
Michal Klocek
|
r1199 | QBarSeries *bar = new QBarSeries(); | ||
Michal Klocek
|
r1126 | setupBarSeries(bar,keys,minRow,maxRow); | ||
result << bar; | ||||
break; | ||||
} | ||||
case QAbstractSeries::SeriesTypePercentBar: | ||||
{ | ||||
Michal Klocek
|
r1199 | QPercentBarSeries *bar = new QPercentBarSeries(); | ||
Michal Klocek
|
r1126 | setupBarSeries(bar,keys,minRow,maxRow); | ||
result << bar; | ||||
break; | ||||
} | ||||
case QAbstractSeries::SeriesTypeStackedBar: | ||||
{ | ||||
Michal Klocek
|
r1199 | QStackedBarSeries *bar = new QStackedBarSeries(); | ||
Michal Klocek
|
r1126 | 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; | ||||
} | ||||
} | ||||
Michal Klocek
|
r1722 | |||
m_chart->createDefaultAxes(); | ||||
Michal Klocek
|
r1126 | return result; | ||
} | ||||
void Engine::removeSeries(QAbstractSeries* series) | ||||
{ | ||||
m_chart->removeSeries(series); | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, m_seriesModelIndex.value(series)) { | ||
Titta Heikkala
|
r2712 | m_model->setData(index, QColor(Qt::white), Qt::BackgroundRole); | ||
Michal Klocek
|
r1126 | } | ||
} | ||||
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) | ||||
{ | ||||
Michal Klocek
|
r1722 | 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); | ||||
Michal Klocek
|
r1126 | m_chart->addSeries(xyseries); | ||
xyseries->setName(QString("Series %1").arg(m_chart->series().count())); | ||||
Jani Honkonen
|
r2110 | QObject::connect(xyseries,SIGNAL(clicked(QPointF)),this,SIGNAL(selected())); | ||
Michal Klocek
|
r1126 | const QModelIndexList& list = m_selection->selectedIndexes(); | ||
QModelIndexList result; | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, list) { | ||
Michal Klocek
|
r1126 | if (index.column() ==columns.at(column)){ | ||
m_model->setData(index, xyseries->pen().color(), Qt::BackgroundRole); | ||||
result << index; | ||||
} | ||||
} | ||||
m_seriesModelIndex.insert(xyseries,result); | ||||
} | ||||
Michal Klocek
|
r1722 | void Engine::setupBarSeries(QAbstractBarSeries *bar, const QList<int>& columns, int minRow, int maxRow) | ||
Michal Klocek
|
r1126 | { | ||
Michal Klocek
|
r1722 | 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()); | ||||
Michal Klocek
|
r1126 | m_chart->addSeries(bar); | ||
bar->setName(QString("Series %1").arg(m_chart->series().count())); | ||||
const QModelIndexList& list = m_selection->selectedIndexes(); | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, list) { | ||
Michal Klocek
|
r1126 | 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) | ||||
{ | ||||
Michal Klocek
|
r1722 | 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); | ||||
Michal Klocek
|
r1126 | m_chart->addSeries(pie); | ||
pie->setName(QString("Series %1").arg(m_chart->series().count())); | ||||
const QModelIndexList& list = m_selection->selectedIndexes(); | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, list) { | ||
Michal Klocek
|
r1126 | // m_model->setData(index, bar->barSets()pen().color(), Qt::BackgroundRole); | ||
} | ||||
} | ||||
void Engine::setupAreaSeries(QAreaSeries *series, const QList<int>& columns, int minRow, int maxRow) | ||||
{ | ||||
Michal Klocek
|
r1722 | 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); | ||||
Michal Klocek
|
r1126 | m_chart->addSeries(series); | ||
series->setName(QString("Series %1").arg(m_chart->series().count())); | ||||
const QModelIndexList& list = m_selection->selectedIndexes(); | ||||
Jani Honkonen
|
r2100 | foreach (const QModelIndex& index, list) { | ||
Michal Klocek
|
r1126 | //if (index.column() ==columns.at(column)) | ||
// m_model->setData(index, xyseries->pen().color(), Qt::BackgroundRole); | ||||
} | ||||
} | ||||