qbarseries.cpp
404 lines
| 11.5 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r794 | /**************************************************************************** | ||
** | ||||
** Copyright (C) 2012 Digia Plc | ||||
** All rights reserved. | ||||
** For any questions to Digia, please use contact form at http://qt.digia.com | ||||
** | ||||
** This file is part of the Qt Commercial Charts Add-on. | ||||
** | ||||
** $QT_BEGIN_LICENSE$ | ||||
** Licensees holding valid Qt Commercial licenses may use this file in | ||||
** accordance with the Qt Commercial License Agreement provided with the | ||||
** Software or, alternatively, in accordance with the terms contained in | ||||
** a written agreement between you and Digia. | ||||
** | ||||
** If you have questions regarding the use of this file, please use | ||||
** contact form at http://qt.digia.com | ||||
** $QT_END_LICENSE$ | ||||
** | ||||
****************************************************************************/ | ||||
sauimone
|
r71 | #include <QDebug> | ||
sauimone
|
r338 | #include "qbarseries.h" | ||
sauimone
|
r172 | #include "qbarset.h" | ||
#include "barchartmodel_p.h" | ||||
sauimone
|
r126 | |||
sauimone
|
r56 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r338 | \class QBarSeries | ||
sauimone
|
r313 | \brief part of QtCommercial chart API. | ||
sauimone
|
r338 | QBarSeries represents a series of data shown as bars. One QBarSeries can contain multible | ||
QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined | ||||
sauimone
|
r377 | by QStringList. | ||
sauimone
|
r313 | |||
sauimone
|
r319 | \mainclass | ||
sauimone
|
r377 | \sa QBarSet, QStackedBarSeries, QPercentBarSeries | ||
sauimone
|
r313 | */ | ||
/*! | ||||
Michal Klocek
|
r360 | \fn virtual QSeriesType QBarSeries::type() const | ||
sauimone
|
r313 | \brief Returns type of series. | ||
Michal Klocek
|
r360 | \sa QSeries, QSeriesType | ||
sauimone
|
r313 | */ | ||
sauimone
|
r425 | |||
sauimone
|
r313 | /*! | ||
sauimone
|
r338 | \fn void QBarSeries::showToolTip(QPoint pos, QString tip) | ||
sauimone
|
r319 | \brief \internal \a pos \a tip | ||
sauimone
|
r313 | */ | ||
/*! | ||||
sauimone
|
r387 | Constructs empty QBarSeries. Parameter \a categories defines the categories for chart. | ||
sauimone
|
r338 | QBarSeries is QObject which is a child of a \a parent. | ||
sauimone
|
r313 | */ | ||
sauimone
|
r762 | QBarSeries::QBarSeries(QBarCategories categories, QObject *parent) : QSeries(parent), | ||
sauimone
|
r763 | m_internalModel(new BarChartModel(categories, this)) | ||
sauimone
|
r71 | { | ||
sauimone
|
r764 | m_model = 0; | ||
Marek Rosa
|
r528 | m_mapCategories = -1; | ||
Jani Honkonen
|
r609 | m_mapBarBottom = -1; | ||
m_mapBarTop = -1; | ||||
Marek Rosa
|
r734 | m_mapFirst = 0; | ||
m_mapCount = 0; | ||||
Marek Rosa
|
r630 | m_mapOrientation = Qt::Vertical; | ||
sauimone
|
r71 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r425 | Adds a set of bars to series. Takes ownership of \a set. | ||
sauimone
|
r812 | Connects the clicked(QString, Qt::MouseButtons) signal | ||
sauimone
|
r425 | of \a set to this series | ||
sauimone
|
r313 | */ | ||
sauimone
|
r776 | void QBarSeries::appendBarSet(QBarSet *set) | ||
sauimone
|
r171 | { | ||
sauimone
|
r776 | m_internalModel->appendBarSet(set); | ||
sauimone
|
r812 | connect(set, SIGNAL(clicked(QString,Qt::MouseButtons)), this, SLOT(barsetClicked(QString,Qt::MouseButtons))); | ||
Marek Rosa
|
r655 | connect(set, SIGNAL(valueChanged()), this, SLOT(barsetChanged())); | ||
sauimone
|
r681 | emit updatedBars(); | ||
sauimone
|
r171 | } | ||
sauimone
|
r313 | /*! | ||
Removes a set of bars from series. Releases ownership of \a set. Doesnt delete \a set. | ||||
sauimone
|
r812 | Disconnects the clicked(QString, Qt::MouseButtons) signal | ||
sauimone
|
r425 | of \a set from this series | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | void QBarSeries::removeBarSet(QBarSet *set) | ||
sauimone
|
r171 | { | ||
sauimone
|
r812 | disconnect(set, SIGNAL(clicked(QString,Qt::MouseButtons)), this, SLOT(barsetClicked(QString,Qt::MouseButtons))); | ||
sauimone
|
r763 | m_internalModel->removeBarSet(set); | ||
sauimone
|
r681 | emit updatedBars(); | ||
sauimone
|
r172 | } | ||
Marek Rosa
|
r662 | void QBarSeries::insertBarSet(int i, QBarSet *set) | ||
{ | ||||
sauimone
|
r763 | m_internalModel->insertBarSet(i, set); | ||
Marek Rosa
|
r662 | // emit barsetChanged(); | ||
} | ||||
void QBarSeries::insertCategory(int i, QString category) | ||||
{ | ||||
sauimone
|
r763 | m_internalModel->insertCategory(i, category); | ||
Marek Rosa
|
r662 | } | ||
Marek Rosa
|
r663 | void QBarSeries::removeCategory(int i) | ||
{ | ||||
sauimone
|
r763 | m_internalModel->removeCategory(i); | ||
Marek Rosa
|
r663 | } | ||
sauimone
|
r313 | /*! | ||
Returns number of sets in series. | ||||
*/ | ||||
sauimone
|
r776 | int QBarSeries::barsetCount() const | ||
sauimone
|
r214 | { | ||
Marek Rosa
|
r662 | // if(m_model) | ||
// return m_mapBarTop - m_mapBarBottom; | ||||
// else | ||||
sauimone
|
r763 | return m_internalModel->barsetCount(); | ||
sauimone
|
r214 | } | ||
sauimone
|
r323 | /*! | ||
Returns number of categories in series | ||||
*/ | ||||
sauimone
|
r776 | int QBarSeries::categoryCount() const | ||
sauimone
|
r323 | { | ||
sauimone
|
r763 | return m_internalModel->categoryCount(); | ||
sauimone
|
r323 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r357 | Returns a list of sets in series. Keeps ownership of sets. | ||
*/ | ||||
sauimone
|
r776 | QList<QBarSet*> QBarSeries::barSets() const | ||
sauimone
|
r214 | { | ||
sauimone
|
r763 | return m_internalModel->barSets(); | ||
sauimone
|
r214 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r357 | \internal \a index | ||
sauimone
|
r313 | */ | ||
sauimone
|
r357 | QBarSet* QBarSeries::barsetAt(int index) | ||
sauimone
|
r288 | { | ||
sauimone
|
r776 | return m_internalModel->barsetAt(index); | ||
sauimone
|
r288 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal \a category | ||
sauimone
|
r313 | */ | ||
sauimone
|
r412 | QString QBarSeries::categoryName(int category) | ||
sauimone
|
r288 | { | ||
sauimone
|
r763 | return m_internalModel->categoryName(category); | ||
sauimone
|
r288 | } | ||
sauimone
|
r313 | /*! | ||
Enables or disables tooltip depending on parameter \a enabled. | ||||
Tooltip shows the name of set, when mouse is hovering on top of bar. | ||||
Calling without parameter \a enabled, enables the tooltip | ||||
*/ | ||||
sauimone
|
r357 | void QBarSeries::setToolTipEnabled(bool enabled) | ||
sauimone
|
r280 | { | ||
sauimone
|
r487 | // TODO: what if we add sets after call to this function? Those sets won't have tooltip enabled. | ||
sauimone
|
r296 | if (enabled) { | ||
sauimone
|
r763 | for (int i=0; i<m_internalModel->barsetCount(); i++) { | ||
sauimone
|
r776 | QBarSet *set = m_internalModel->barsetAt(i); | ||
Tero Ahola
|
r737 | connect(set, SIGNAL(showToolTip(QPoint,QString)), this, SIGNAL(showToolTip(QPoint,QString))); | ||
sauimone
|
r296 | } | ||
} else { | ||||
sauimone
|
r763 | for (int i=0; i<m_internalModel->barsetCount(); i++) { | ||
sauimone
|
r776 | QBarSet *set = m_internalModel->barsetAt(i); | ||
Tero Ahola
|
r737 | disconnect(set, SIGNAL(showToolTip(QPoint,QString)), this, SIGNAL(showToolTip(QPoint,QString))); | ||
sauimone
|
r296 | } | ||
} | ||||
sauimone
|
r288 | } | ||
sauimone
|
r425 | |||
/*! | ||||
\internal \a category | ||||
*/ | ||||
sauimone
|
r812 | void QBarSeries::barsetClicked(QString category, Qt::MouseButtons button) | ||
sauimone
|
r425 | { | ||
sauimone
|
r812 | emit clicked(qobject_cast<QBarSet*>(sender()), category, button); | ||
sauimone
|
r425 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | qreal QBarSeries::min() | ||
sauimone
|
r172 | { | ||
sauimone
|
r763 | return m_internalModel->min(); | ||
sauimone
|
r172 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | qreal QBarSeries::max() | ||
sauimone
|
r172 | { | ||
sauimone
|
r763 | return m_internalModel->max(); | ||
sauimone
|
r171 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal \a set \a category | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | qreal QBarSeries::valueAt(int set, int category) | ||
sauimone
|
r172 | { | ||
sauimone
|
r763 | return m_internalModel->valueAt(set, category); | ||
sauimone
|
r172 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal \a set \a category | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | qreal QBarSeries::percentageAt(int set, int category) | ||
sauimone
|
r288 | { | ||
sauimone
|
r763 | return m_internalModel->percentageAt(set, category); | ||
sauimone
|
r288 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal \a category | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | qreal QBarSeries::categorySum(int category) | ||
sauimone
|
r288 | { | ||
sauimone
|
r763 | return m_internalModel->categorySum(category); | ||
sauimone
|
r288 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | qreal QBarSeries::maxCategorySum() | ||
sauimone
|
r172 | { | ||
sauimone
|
r763 | return m_internalModel->maxCategorySum(); | ||
sauimone
|
r172 | } | ||
sauimone
|
r313 | /*! | ||
sauimone
|
r319 | \internal | ||
sauimone
|
r313 | */ | ||
sauimone
|
r338 | BarChartModel& QBarSeries::model() | ||
sauimone
|
r172 | { | ||
sauimone
|
r763 | return *m_internalModel; | ||
sauimone
|
r172 | } | ||
Tero Ahola
|
r737 | bool QBarSeries::setModel(QAbstractItemModel *model) | ||
Marek Rosa
|
r527 | { | ||
Marek Rosa
|
r630 | // disconnect signals from old model | ||
if(m_model) | ||||
{ | ||||
disconnect(m_model, 0, this, 0); | ||||
m_mapCategories = -1; | ||||
m_mapBarBottom = -1; | ||||
m_mapBarTop = -1; | ||||
Marek Rosa
|
r734 | m_mapFirst = 0; | ||
m_mapCount = 0; | ||||
Marek Rosa
|
r630 | m_mapOrientation = Qt::Vertical; | ||
} | ||||
// set new model | ||||
if(model) | ||||
{ | ||||
m_model = model; | ||||
return true; | ||||
} | ||||
else | ||||
{ | ||||
sauimone
|
r764 | m_model = 0; | ||
Marek Rosa
|
r630 | return false; | ||
} | ||||
Marek Rosa
|
r527 | } | ||
Tero Ahola
|
r611 | // TODO | ||
Marek Rosa
|
r630 | void QBarSeries::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation) | ||
Marek Rosa
|
r527 | { | ||
sauimone
|
r764 | if (!m_model) | ||
Marek Rosa
|
r630 | return; | ||
Tero Ahola
|
r737 | |||
Marek Rosa
|
r630 | m_mapCategories = categories; | ||
m_mapBarBottom = bottomBoundry; | ||||
m_mapBarTop = topBoundry; | ||||
Marek Rosa
|
r735 | // m_mapFirst = 1; | ||
Marek Rosa
|
r630 | m_mapOrientation = orientation; | ||
// connect the signals | ||||
Tero Ahola
|
r737 | if (m_mapOrientation == Qt::Vertical) { | ||
Marek Rosa
|
r735 | m_mapCount = m_model->rowCount() - m_mapFirst; | ||
Tero Ahola
|
r737 | connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), | ||
this, SLOT(modelUpdated(QModelIndex, QModelIndex))); | ||||
connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), | ||||
this, SLOT(modelDataAdded(QModelIndex,int,int))); | ||||
connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), | ||||
this, SLOT(modelDataRemoved(QModelIndex,int,int))); | ||||
} else { | ||||
Marek Rosa
|
r735 | m_mapCount = m_model->columnCount() - m_mapFirst; | ||
Tero Ahola
|
r737 | connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), | ||
this, SLOT(modelUpdated(QModelIndex, QModelIndex))); | ||||
connect(m_model,SIGNAL(columnsInserted(QModelIndex, int, int)), | ||||
this, SLOT(modelDataAdded(QModelIndex,int,int))); | ||||
connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)), | ||||
this, SLOT(modelDataRemoved(QModelIndex,int,int))); | ||||
Marek Rosa
|
r630 | } | ||
// create the initial bars | ||||
sauimone
|
r763 | delete m_internalModel; | ||
Tero Ahola
|
r737 | if (m_mapOrientation == Qt::Vertical) { | ||
Marek Rosa
|
r630 | QStringList categories; | ||
Marek Rosa
|
r734 | for (int k = m_mapFirst; k < m_mapFirst + m_mapCount; k++) | ||
Marek Rosa
|
r650 | categories << m_model->data(m_model->index(k, m_mapCategories), Qt::DisplayRole).toString(); | ||
sauimone
|
r763 | m_internalModel = new BarChartModel(categories, this); | ||
Marek Rosa
|
r630 | |||
Tero Ahola
|
r737 | for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) { | ||
Marek Rosa
|
r650 | QBarSet* barSet = new QBarSet(QString("Column: %1").arg(i + 1)); | ||
Marek Rosa
|
r734 | for(int m = m_mapFirst; m < m_mapFirst + m_mapCount; m++) | ||
Marek Rosa
|
r650 | *barSet << m_model->data(m_model->index(m, i), Qt::DisplayRole).toDouble(); | ||
sauimone
|
r776 | appendBarSet(barSet); | ||
Marek Rosa
|
r630 | } | ||
Tero Ahola
|
r737 | } else { | ||
Marek Rosa
|
r630 | QStringList categories; | ||
Marek Rosa
|
r734 | for (int k = m_mapFirst; k < m_mapFirst + m_mapCount; k++) | ||
Marek Rosa
|
r650 | categories << m_model->data(m_model->index(m_mapCategories, k), Qt::DisplayRole).toString(); | ||
sauimone
|
r763 | m_internalModel = new BarChartModel(categories, this); | ||
Marek Rosa
|
r630 | |||
Tero Ahola
|
r737 | for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) { | ||
Marek Rosa
|
r650 | QBarSet* barSet = new QBarSet(QString("Row: %1").arg(i + 1)); | ||
Marek Rosa
|
r734 | for(int m = m_mapFirst; m < m_mapFirst + m_mapCount; m++) | ||
Marek Rosa
|
r650 | *barSet << m_model->data(m_model->index(i, m), Qt::DisplayRole).toDouble(); | ||
sauimone
|
r776 | appendBarSet(barSet); | ||
Marek Rosa
|
r630 | } | ||
} | ||||
Marek Rosa
|
r527 | } | ||
Marek Rosa
|
r734 | void QBarSeries::setModelMappingShift(int first, int count) | ||
{ | ||||
m_mapFirst = first; | ||||
m_mapCount = count; | ||||
} | ||||
Marek Rosa
|
r630 | void QBarSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight) | ||
{ | ||||
Q_UNUSED(bottomRight) | ||||
if (m_mapOrientation == Qt::Vertical) | ||||
{ | ||||
Marek Rosa
|
r734 | // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries | ||
if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop && topLeft.row() >= m_mapFirst && topLeft.row() < m_mapFirst + m_mapCount) | ||||
barsetAt(topLeft.column() - m_mapBarBottom)->setValue(topLeft.row() - m_mapFirst, m_model->data(topLeft, Qt::DisplayRole).toDouble()); | ||||
Marek Rosa
|
r630 | } | ||
else | ||||
{ | ||||
Marek Rosa
|
r734 | // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries | ||
if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop && topLeft.column() >= m_mapFirst && topLeft.column() < m_mapFirst + m_mapCount) | ||||
barsetAt(topLeft.row() - m_mapBarBottom)->setValue(topLeft.column() - m_mapFirst, m_model->data(topLeft, Qt::DisplayRole).toDouble()); | ||||
Marek Rosa
|
r630 | } | ||
} | ||||
Marek Rosa
|
r662 | void QBarSeries::modelDataAdded(QModelIndex /*parent*/, int start, int /*end*/) | ||
Marek Rosa
|
r630 | { | ||
Tero Ahola
|
r737 | if (m_mapOrientation == Qt::Vertical) { | ||
Marek Rosa
|
r734 | insertCategory(start - m_mapFirst, QString("Row: %1").arg(start + 1)); | ||
Tero Ahola
|
r737 | for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++) { | ||
Marek Rosa
|
r734 | barsetAt(i)->insertValue(start - m_mapFirst, m_model->data(m_model->index(start, i), Qt::DisplayRole).toDouble()); | ||
Marek Rosa
|
r662 | } | ||
Tero Ahola
|
r737 | } else { | ||
Marek Rosa
|
r734 | insertCategory(start - m_mapFirst, QString("Column: %1").arg(start + 1)); | ||
Tero Ahola
|
r737 | for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++) { | ||
Marek Rosa
|
r734 | barsetAt(i)->insertValue(start - m_mapFirst, m_model->data(m_model->index(i, start), Qt::DisplayRole).toDouble()); | ||
Marek Rosa
|
r662 | } | ||
} | ||||
emit restructuredBar(1); | ||||
Marek Rosa
|
r630 | } | ||
Tero Ahola
|
r737 | void QBarSeries::modelDataRemoved(QModelIndex parent, int start, int end) | ||
Marek Rosa
|
r630 | { | ||
Tero Ahola
|
r737 | Q_UNUSED(parent) | ||
Q_UNUSED(end) | ||||
Marek Rosa
|
r734 | removeCategory(start - m_mapFirst); | ||
Marek Rosa
|
r663 | for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++) | ||
{ | ||||
Marek Rosa
|
r734 | barsetAt(i)->removeValue(start - m_mapFirst); | ||
Marek Rosa
|
r663 | } | ||
emit restructuredBar(1); | ||||
Marek Rosa
|
r630 | } | ||
void QBarSeries::barsetChanged() | ||||
Marek Rosa
|
r527 | { | ||
Marek Rosa
|
r655 | emit updatedBars(); | ||
Marek Rosa
|
r527 | } | ||
Michal Klocek
|
r703 | QBarCategories QBarSeries::categories() const | ||
{ | ||||
QBarCategories categories; | ||||
sauimone
|
r763 | int count = m_internalModel->categoryCount(); | ||
Tero Ahola
|
r737 | for (int i=1; i <= count; i++) { | ||
sauimone
|
r763 | categories.insert(i, m_internalModel->categoryName(i - 1)); | ||
Michal Klocek
|
r703 | } | ||
return categories; | ||||
} | ||||
sauimone
|
r820 | void QBarSeries::setLabelsVisible(bool visible) | ||
sauimone
|
r813 | { | ||
foreach (QBarSet* s, barSets()) { | ||||
sauimone
|
r820 | s->setLabelsVisible(visible); | ||
sauimone
|
r813 | } | ||
} | ||||
sauimone
|
r338 | #include "moc_qbarseries.cpp" | ||
sauimone
|
r71 | |||
sauimone
|
r56 | QTCOMMERCIALCHART_END_NAMESPACE | ||