chartdataset.cpp
404 lines
| 11.0 KiB
| text/x-c
|
CppLexer
/ src / chartdataset.cpp
Michal Klocek
|
r131 | #include "chartdataset_p.h" | ||
Michal Klocek
|
r223 | #include "qchartaxis.h" | ||
Michal Klocek
|
r139 | //series | ||
Michal Klocek
|
r349 | #include "qlineseries.h" | ||
sauimone
|
r338 | #include "qbarseries.h" | ||
#include "qstackedbarseries.h" | ||||
#include "qpercentbarseries.h" | ||||
Jani Honkonen
|
r146 | #include "qpieseries.h" | ||
Tero Ahola
|
r158 | #include "qscatterseries.h" | ||
Michal Klocek
|
r131 | |||
QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||||
Michal Klocek
|
r223 | ChartDataSet::ChartDataSet(QObject *parent):QObject(parent), | ||
m_axisX(new QChartAxis(this)), | ||||
m_axisY(new QChartAxis(this)), | ||||
m_domainIndex(0), | ||||
m_axisXInitialized(false) | ||||
Michal Klocek
|
r131 | { | ||
} | ||||
ChartDataSet::~ChartDataSet() | ||||
{ | ||||
// TODO Auto-generated destructor stub | ||||
} | ||||
Michal Klocek
|
r223 | const Domain ChartDataSet::domain(QChartAxis *axisY) const | ||
Michal Klocek
|
r131 | { | ||
Michal Klocek
|
r223 | int i = m_domainMap.count(axisY); | ||
if(i == 0){ | ||||
return Domain(); | ||||
} | ||||
i = i - m_domainIndex -1; | ||||
return m_domainMap.values(axisY).at(i); | ||||
Michal Klocek
|
r131 | } | ||
Michal Klocek
|
r360 | void ChartDataSet::addSeries(QSeries* series, QChartAxis *axisY) | ||
Michal Klocek
|
r131 | { | ||
Michal Klocek
|
r139 | // TODO: we should check the series not already added | ||
Jani Honkonen
|
r229 | series->setParent(this); // take ownership | ||
Michal Klocek
|
r223 | clearDomains(); | ||
if(axisY==0) axisY = m_axisY; | ||||
Michal Klocek
|
r248 | axisY->setParent(this); // take ownership | ||
Michal Klocek
|
r223 | |||
Michal Klocek
|
r360 | QList<QSeries*> seriesList = m_seriesMap.values(axisY); | ||
Michal Klocek
|
r223 | |||
QList<Domain> domainList = m_domainMap.values(axisY); | ||||
Q_ASSERT(domainList.size()<=1); | ||||
Domain domain; | ||||
if(domainList.size()>0) domain = domainList.at(0); | ||||
Michal Klocek
|
r139 | |||
switch(series->type()) | ||||
{ | ||||
Michal Klocek
|
r360 | case QSeries::SeriesTypeLine: { | ||
Michal Klocek
|
r139 | |||
Michal Klocek
|
r349 | QLineSeries* xyseries = static_cast<QLineSeries*>(series); | ||
Michal Klocek
|
r139 | |||
for (int i = 0; i < xyseries->count(); i++) | ||||
{ | ||||
qreal x = xyseries->x(i); | ||||
qreal y = xyseries->y(i); | ||||
domain.m_minX = qMin(domain.m_minX,x); | ||||
domain.m_minY = qMin(domain.m_minY,y); | ||||
domain.m_maxX = qMax(domain.m_maxX,x); | ||||
domain.m_maxY = qMax(domain.m_maxY,y); | ||||
} | ||||
break; | ||||
} | ||||
Michal Klocek
|
r360 | case QSeries::SeriesTypeBar: { | ||
sauimone
|
r173 | qDebug() << "QChartSeries::SeriesTypeBar"; | ||
sauimone
|
r338 | QBarSeries* barSeries = static_cast<QBarSeries*>(series); | ||
sauimone
|
r366 | qreal x = barSeries->categoryCount(); | ||
Michal Klocek
|
r139 | qreal y = barSeries->max(); | ||
domain.m_minX = qMin(domain.m_minX,x); | ||||
domain.m_minY = qMin(domain.m_minY,y); | ||||
domain.m_maxX = qMax(domain.m_maxX,x); | ||||
domain.m_maxY = qMax(domain.m_maxY,y); | ||||
sauimone
|
r167 | break; | ||
Michal Klocek
|
r139 | } | ||
Michal Klocek
|
r360 | case QSeries::SeriesTypeStackedBar: { | ||
sauimone
|
r173 | qDebug() << "QChartSeries::SeriesTypeStackedBar"; | ||
Michal Klocek
|
r139 | |||
sauimone
|
r338 | QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series); | ||
sauimone
|
r366 | qreal x = stackedBarSeries->categoryCount(); | ||
sauimone
|
r172 | qreal y = stackedBarSeries->maxCategorySum(); | ||
Michal Klocek
|
r139 | domain.m_minX = qMin(domain.m_minX,x); | ||
domain.m_minY = qMin(domain.m_minY,y); | ||||
domain.m_maxX = qMax(domain.m_maxX,x); | ||||
domain.m_maxY = qMax(domain.m_maxY,y); | ||||
break; | ||||
sauimone
|
r167 | } | ||
Michal Klocek
|
r360 | case QSeries::SeriesTypePercentBar: { | ||
sauimone
|
r173 | qDebug() << "QChartSeries::SeriesTypePercentBar"; | ||
Michal Klocek
|
r139 | |||
sauimone
|
r338 | QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series); | ||
sauimone
|
r366 | qreal x = percentBarSeries->categoryCount(); | ||
Michal Klocek
|
r139 | domain.m_minX = qMin(domain.m_minX,x); | ||
domain.m_minY = 0; | ||||
domain.m_maxX = qMax(domain.m_maxX,x); | ||||
domain.m_maxY = 100; | ||||
break; | ||||
sauimone
|
r167 | } | ||
Michal Klocek
|
r139 | |||
Michal Klocek
|
r360 | case QSeries::SeriesTypePie: { | ||
Jani Honkonen
|
r142 | QPieSeries *pieSeries = static_cast<QPieSeries *>(series); | ||
// TODO: domain stuff | ||||
break; | ||||
} | ||||
Michal Klocek
|
r360 | case QSeries::SeriesTypeScatter: { | ||
Tero Ahola
|
r158 | QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series); | ||
Q_ASSERT(scatterSeries); | ||||
foreach (QPointF point, scatterSeries->data()) { | ||||
domain.m_minX = qMin(domain.m_minX, point.x()); | ||||
domain.m_maxX = qMax(domain.m_maxX, point.x()); | ||||
domain.m_minY = qMin(domain.m_minY, point.y()); | ||||
domain.m_maxY = qMax(domain.m_maxY, point.y()); | ||||
} | ||||
break; | ||||
} | ||||
Michal Klocek
|
r139 | default: { | ||
qDebug()<<__FUNCTION__<<"type" << series->type()<<"not supported"; | ||||
return; | ||||
break; | ||||
} | ||||
} | ||||
Michal Klocek
|
r223 | if(!m_domainMap.contains(axisY)) | ||
{ | ||||
emit axisAdded(axisY); | ||||
Michal Klocek
|
r400 | QObject::connect(axisY,SIGNAL(rangeChanged(QChartAxis*)),this,SLOT(handleRangeChanged(QChartAxis*))); | ||
Michal Klocek
|
r223 | QObject::connect(axisY,SIGNAL(ticksChanged(QChartAxis*)),this,SLOT(handleTickChanged(QChartAxis*))); | ||
} | ||||
if(!m_axisXInitialized) | ||||
{ | ||||
emit axisAdded(axisX()); | ||||
Michal Klocek
|
r400 | QObject::connect(axisX(),SIGNAL(rangeChanged(QChartAxis*)),this,SLOT(handleRangeChanged(QChartAxis*))); | ||
Michal Klocek
|
r223 | QObject::connect(axisX(),SIGNAL(ticksChanged(QChartAxis*)),this,SLOT(handleTickChanged(QChartAxis*))); | ||
m_axisXInitialized=true; | ||||
} | ||||
Michal Klocek
|
r400 | m_domainMap.replace(axisY,domain); | ||
m_seriesMap.insert(axisY,series); | ||||
Michal Klocek
|
r389 | emit seriesAdded(series); | ||
Michal Klocek
|
r411 | setDomain(m_domainIndex,axisY); | ||
Michal Klocek
|
r223 | |||
} | ||||
Michal Klocek
|
r360 | void ChartDataSet::removeSeries(QSeries* series) | ||
Michal Klocek
|
r223 | { | ||
QList<QChartAxis*> keys = m_seriesMap.uniqueKeys(); | ||||
foreach(QChartAxis* axis , keys) { | ||||
if(m_seriesMap.contains(axis,series)){ | ||||
emit seriesRemoved(series); | ||||
m_seriesMap.remove(axis,series); | ||||
//remove axis if no longer there | ||||
Michal Klocek
|
r258 | if(!m_seriesMap.contains(axis)){ | ||
Michal Klocek
|
r223 | emit axisRemoved(axis); | ||
m_domainMap.remove(axis); | ||||
Michal Klocek
|
r258 | if(axis != m_axisY) | ||
Michal Klocek
|
r223 | delete axis; | ||
} | ||||
Michal Klocek
|
r258 | series->setParent(0); | ||
Michal Klocek
|
r223 | break; | ||
} | ||||
} | ||||
Michal Klocek
|
r139 | } | ||
Michal Klocek
|
r258 | void ChartDataSet::removeAllSeries() | ||
{ | ||||
QList<QChartAxis*> keys = m_seriesMap.uniqueKeys(); | ||||
foreach(QChartAxis* axis , keys) { | ||||
Michal Klocek
|
r360 | QList<QSeries*> seriesList = m_seriesMap.values(axis); | ||
Michal Klocek
|
r258 | for(int i =0 ; i < seriesList.size();i++ ) | ||
{ | ||||
emit seriesRemoved(seriesList.at(i)); | ||||
delete(seriesList.at(i)); | ||||
} | ||||
m_seriesMap.remove(axis); | ||||
m_domainMap.remove(axis); | ||||
emit axisRemoved(axis); | ||||
if(axis != m_axisY) delete axis; | ||||
} | ||||
m_domainIndex=0; | ||||
} | ||||
Michal Klocek
|
r139 | bool ChartDataSet::nextDomain() | ||
{ | ||||
Michal Klocek
|
r223 | int limit = (m_domainMap.values().size()/m_domainMap.uniqueKeys().size())-1; | ||
if (m_domainIndex < limit) { | ||||
Michal Klocek
|
r139 | m_domainIndex++; | ||
Michal Klocek
|
r223 | setDomain(m_domainIndex); | ||
Michal Klocek
|
r139 | return true; | ||
} | ||||
else { | ||||
return false; | ||||
} | ||||
} | ||||
bool ChartDataSet::previousDomain() | ||||
{ | ||||
if (m_domainIndex > 0) { | ||||
m_domainIndex--; | ||||
Michal Klocek
|
r223 | setDomain(m_domainIndex); | ||
Michal Klocek
|
r139 | return true; | ||
} | ||||
else { | ||||
return false; | ||||
} | ||||
} | ||||
Michal Klocek
|
r223 | void ChartDataSet::setDomain(int index) | ||
Michal Klocek
|
r139 | { | ||
Michal Klocek
|
r223 | QList<QChartAxis*> domainList = m_domainMap.uniqueKeys(); | ||
Michal Klocek
|
r265 | |||
Michal Klocek
|
r373 | if(domainList.count()==0) return; | ||
Michal Klocek
|
r265 | Domain domain; | ||
Michal Klocek
|
r223 | foreach (QChartAxis* axis , domainList) { | ||
int i = m_domainMap.count(axis) - index -1; | ||||
Q_ASSERT(i>=0); | ||||
Michal Klocek
|
r265 | domain = m_domainMap.values(axis).at(i); | ||
Michal Klocek
|
r223 | QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY); | ||
Michal Klocek
|
r360 | QList<QSeries*> seriesList = m_seriesMap.values(axis); | ||
foreach(QSeries* series, seriesList) { | ||||
Michal Klocek
|
r223 | emit seriesDomainChanged(series,domain); | ||
} | ||||
Michal Klocek
|
r403 | axis->updateRange(domain.m_minY,domain.m_maxY); | ||
Michal Klocek
|
r399 | emit axisRangeChanged(axis,labels); | ||
Michal Klocek
|
r400 | |||
Michal Klocek
|
r223 | } | ||
QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX); | ||||
Michal Klocek
|
r403 | axisX()->updateRange(domain.m_minX,domain.m_maxY); | ||
Michal Klocek
|
r399 | emit axisRangeChanged(axisX(),labels); | ||
Michal Klocek
|
r223 | } | ||
Michal Klocek
|
r411 | void ChartDataSet::setDomain(int index,QChartAxis* axis) | ||
{ | ||||
int i = m_domainMap.count(axis) - index -1; | ||||
Q_ASSERT(i>=0); | ||||
Domain domain = m_domainMap.values(axis).at(i); | ||||
{ | ||||
QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY); | ||||
QList<QSeries*> seriesList = m_seriesMap.values(axis); | ||||
foreach(QSeries* series, seriesList) { | ||||
emit seriesDomainChanged(series,domain); | ||||
} | ||||
axis->updateRange(domain.m_minY,domain.m_maxY); | ||||
emit axisRangeChanged(axis,labels); | ||||
} | ||||
QStringList labels = createLabels(axisX(),domain.m_minX,domain.m_maxX); | ||||
axisX()->updateRange(domain.m_minX,domain.m_maxY); | ||||
emit axisRangeChanged(axisX(),labels); | ||||
} | ||||
Michal Klocek
|
r223 | void ChartDataSet::clearDomains(int toIndex) | ||
{ | ||||
Q_ASSERT(toIndex>=0); | ||||
m_domainIndex = toIndex; | ||||
QList<QChartAxis*> keys = m_domainMap.uniqueKeys(); | ||||
foreach (QChartAxis* key , keys) | ||||
{ | ||||
QList<Domain> domains = m_domainMap.values(key); | ||||
m_domainMap.remove(key); | ||||
int i = domains.size() - toIndex - 1; | ||||
while(i--){ | ||||
domains.removeFirst(); | ||||
} | ||||
for(int j=domains.size()-1; j>=0 ;j--) | ||||
m_domainMap.insert(key,domains.at(j)); | ||||
Michal Klocek
|
r139 | } | ||
} | ||||
Michal Klocek
|
r223 | void ChartDataSet::addDomain(const QRectF& rect, const QRectF& viewport) | ||
Michal Klocek
|
r139 | { | ||
Michal Klocek
|
r223 | Q_ASSERT(rect.isValid()); | ||
Q_ASSERT(viewport.isValid()); | ||||
clearDomains(m_domainIndex); | ||||
QList<QChartAxis*> domainList = m_domainMap.uniqueKeys(); | ||||
Michal Klocek
|
r266 | Domain domain; | ||
Michal Klocek
|
r223 | foreach (QChartAxis* axis , domainList){ | ||
Michal Klocek
|
r266 | domain = m_domainMap.value(axis).subDomain(rect,viewport.width(),viewport.height()); | ||
Michal Klocek
|
r223 | m_domainMap.insert(axis,domain); | ||
} | ||||
Michal Klocek
|
r400 | setDomain(++m_domainIndex); | ||
Michal Klocek
|
r223 | } | ||
Michal Klocek
|
r360 | QChartAxis* ChartDataSet::axisY(QSeries* series) const | ||
Michal Klocek
|
r223 | { | ||
if(series == 0) return m_axisY; | ||||
QList<QChartAxis*> keys = m_seriesMap.uniqueKeys(); | ||||
foreach(QChartAxis* axis , keys) { | ||||
if(m_seriesMap.contains(axis,series)){ | ||||
return axis; | ||||
} | ||||
} | ||||
return 0; | ||||
} | ||||
QStringList ChartDataSet::createLabels(QChartAxis* axis,qreal min, qreal max) | ||||
{ | ||||
Q_ASSERT(max>=min); | ||||
Michal Klocek
|
r139 | |||
Michal Klocek
|
r223 | QStringList labels; | ||
Michal Klocek
|
r241 | int ticks = axis->ticksCount()-1; | ||
Michal Klocek
|
r223 | |||
for(int i=0; i<= ticks; i++){ | ||||
qreal value = min + (i * (max - min)/ ticks); | ||||
QString label = axis->axisTickLabel(value); | ||||
if(label.isEmpty()){ | ||||
labels << QString::number(value); | ||||
}else{ | ||||
labels << label; | ||||
} | ||||
} | ||||
return labels; | ||||
} | ||||
Michal Klocek
|
r400 | void ChartDataSet::handleRangeChanged(QChartAxis* axis) | ||
Michal Klocek
|
r223 | { | ||
Michal Klocek
|
r400 | qreal min = axis->min(); | ||
qreal max = axis->max(); | ||||
Michal Klocek
|
r223 | |||
Michal Klocek
|
r400 | if(axis==axisX()) { | ||
Michal Klocek
|
r223 | |||
Michal Klocek
|
r400 | m_domainIndex=0; | ||
clearDomains(m_domainIndex); | ||||
QList<QChartAxis*> domainList = m_domainMap.uniqueKeys(); | ||||
foreach (QChartAxis* axis , domainList) { | ||||
Q_ASSERT(m_domainMap.values(axis).size()==1); | ||||
Domain domain = m_domainMap.value(axis); | ||||
domain.m_minX=min; | ||||
domain.m_maxX=max; | ||||
m_domainMap.replace(axis,domain); | ||||
} | ||||
Michal Klocek
|
r411 | setDomain(m_domainIndex); | ||
Michal Klocek
|
r400 | } | ||
else { | ||||
QList<Domain> domains = m_domainMap.values(axis); | ||||
m_domainMap.remove(axis); | ||||
for(int i=0;i<domains.size();i++) | ||||
{ | ||||
domains[i].m_minY=min; | ||||
domains[i].m_maxY=max; | ||||
} | ||||
for(int j=domains.size()-1; j>=0;j--) | ||||
m_domainMap.insert(axis,domains.at(j)); | ||||
Michal Klocek
|
r411 | |||
setDomain(m_domainIndex,axis); | ||||
Michal Klocek
|
r400 | } | ||
Michal Klocek
|
r223 | |||
Michal Klocek
|
r411 | |||
Michal Klocek
|
r223 | } | ||
void ChartDataSet::handleTickChanged(QChartAxis* axis) | ||||
{ | ||||
if(axis==axisX()){ | ||||
Michal Klocek
|
r400 | Domain domain = m_domainMap.value(axisY()); | ||
Michal Klocek
|
r223 | QStringList labels = createLabels(axis,domain.m_minX,domain.m_maxX); | ||
Michal Klocek
|
r399 | emit axisRangeChanged(axis,labels); | ||
Michal Klocek
|
r223 | }else{ | ||
Michal Klocek
|
r400 | Domain domain = m_domainMap.value(axis); | ||
Michal Klocek
|
r223 | QStringList labels = createLabels(axis,domain.m_minY,domain.m_maxY); | ||
Michal Klocek
|
r399 | emit axisRangeChanged(axis,labels); | ||
Michal Klocek
|
r223 | } | ||
Michal Klocek
|
r131 | } | ||
#include "moc_chartdataset_p.cpp" | ||||
QTCOMMERCIALCHART_END_NAMESPACE | ||||