##// END OF EJS Templates
optimized calculations for stacked bar animation
optimized calculations for stacked bar animation

File last commit:

r1397:95d60d3807f4
r1430:aef513fa0d93
Show More
qxymodelmapper.cpp
522 lines | 16.6 KiB | text/x-c | CppLexer
/ src / xychart / qxymodelmapper.cpp
Marek Rosa
Added license text to mapper classes
r1355 /****************************************************************************
**
** 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$
**
****************************************************************************/
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 #include "qxymodelmapper.h"
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 #include "qxymodelmapper_p.h"
#include "qxyseries.h"
#include <QAbstractItemModel>
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164
QTCOMMERCIALCHART_BEGIN_NAMESPACE
Marek Rosa
Model mappers docs updated
r1378 /*!
\class QXYModelMapper
\brief part of QtCommercial chart API.
\mainclass
Marek Rosa
Updated mapper classes descriptions
r1397 Model mappers allow you to use QAbstractItemModel derived models as a data source for a chart series.
Marek Rosa
Model mappers docs updated
r1378 The instance of this class cannot be created directly. QHXYModelMapper of QVXYModelMapper should be used instead. This class is used to create a connection between QXYSeries and QAbstractItemModel derived model object.
It is possible to use both QAbstractItemModel and QXYSeries model API. QXYModelMapper makes sure that QXYSeries and the model are kept in sync.
NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
*/
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
\property QXYModelMapper::series
\brief Defines the QPieSeries object that is used by the mapper.
Marek Rosa
Model mappers docs updated
r1378 All the data in the series is discarded when it is set to the mapper.
Marek Rosa
Added documentation for XYModelMapper classes
r1344 When new series is specified the old series is disconnected (it preserves its data)
*/
/*!
\property QXYModelMapper::model
\brief Defines the model that is used by the mapper.
*/
/*!
\property QXYModelMapper::first
\brief Defines which item of the model's row/column should be mapped as the first x/y pair
Minimal and default value is: 0
*/
/*!
\property QXYModelMapper::count
\brief Defines the number of rows/columns of the model that are mapped as the data for QXYSeries
Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
*/
Marek Rosa
ModelMappers dosc update
r1347 /*!
Constructs a mapper object which is a child of \a parent.
*/
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 QXYModelMapper::QXYModelMapper(QObject *parent):
QObject(parent),
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 d_ptr(new QXYModelMapperPrivate(this))
{
}
QAbstractItemModel* QXYModelMapper::model() const
{
Q_D(const QXYModelMapper);
return d->m_model;
}
void QXYModelMapper::setModel(QAbstractItemModel *model)
{
if (model == 0)
return;
Q_D(QXYModelMapper);
if (d->m_model) {
disconnect(d->m_model, 0, d, 0);
}
d->m_model = model;
d->initializeXYFromModel();
// connect signals from the model
connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
}
QXYSeries* QXYModelMapper::series() const
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(const QXYModelMapper);
return d->m_series;
}
void QXYModelMapper::setSeries(QXYSeries *series)
{
Q_D(QXYModelMapper);
if (d->m_series) {
disconnect(d->m_series, 0, d, 0);
}
if (series == 0)
return;
d->m_series = series;
d->initializeXYFromModel();
// connect the signals from the series
connect(d->m_series, SIGNAL(pointAdded(int)), d, SLOT(handlePointAdded(int)));
connect(d->m_series, SIGNAL(pointRemoved(int)), d, SLOT(handlePointRemoved(int)));
Marek Rosa
XYModelMapper slots for series signals implemented
r1262 connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int)));
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
int QXYModelMapper::first() const
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(const QXYModelMapper);
return d->m_first;
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
void QXYModelMapper::setFirst(int first)
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(QXYModelMapper);
d->m_first = qMax(first, 0);
d->initializeXYFromModel();
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
int QXYModelMapper::count() const
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(const QXYModelMapper);
return d->m_count;
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
void QXYModelMapper::setCount(int count)
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(QXYModelMapper);
d->m_count = qMax(count, -1);
d->initializeXYFromModel();
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Returns the orientation that is used when QXYModelMapper accesses the model.
This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
or from columns (Qt::Vertical)
*/
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 Qt::Orientation QXYModelMapper::orientation() const
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(const QXYModelMapper);
return d->m_orientation;
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Returns the \a orientation that is used when QXYModelMapper accesses the model.
This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
or from columns (Qt::Vertical)
*/
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 void QXYModelMapper::setOrientation(Qt::Orientation orientation)
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(QXYModelMapper);
d->m_orientation = orientation;
d->initializeXYFromModel();
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Returns which section of the model is kept in sync with the x values of the QXYSeries
*/
Marek Rosa
Added Vertical and Horizontal QXYModelMapper
r1252 int QXYModelMapper::xSection() const
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(const QXYModelMapper);
return d->m_xSection;
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Sets the model section that is kept in sync with the x values of the QXYSeries.
Parameter \a xSection specifies the section of the model.
*/
Marek Rosa
Added Vertical and Horizontal QXYModelMapper
r1252 void QXYModelMapper::setXSection(int xSection)
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(QXYModelMapper);
Marek Rosa
Added tests for XYModelMapper
r1352 d->m_xSection = qMax(-1, xSection);
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 d->initializeXYFromModel();
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Returns which section of the model is kept in sync with the y values of the QXYSeries
*/
Marek Rosa
Added Vertical and Horizontal QXYModelMapper
r1252 int QXYModelMapper::ySection() const
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(const QXYModelMapper);
return d->m_ySection;
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Sets the model section that is kept in sync with the y values of the QXYSeries.
Parameter \a ySection specifies the section of the model.
*/
Marek Rosa
Added Vertical and Horizontal QXYModelMapper
r1252 void QXYModelMapper::setYSection(int ySection)
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(QXYModelMapper);
Marek Rosa
Added tests for XYModelMapper
r1352 d->m_ySection = qMax(-1, ySection);
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 d->initializeXYFromModel();
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
Marek Rosa
Added documentation for XYModelMapper classes
r1344 /*!
Resets the QXYModelMapper to the default state.
first: 0; count: -1; xSection: -1; ySection: -1;
*/
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 void QXYModelMapper::reset()
{
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 Q_D(QXYModelMapper);
d->m_first = 0;
d->m_count = -1;
d->m_orientation = Qt::Vertical;
d->m_xSection = -1;
d->m_ySection = -1;
d->initializeXYFromModel();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
QXYModelMapperPrivate::QXYModelMapperPrivate(QXYModelMapper *q) :
m_series(0),
m_model(0),
m_first(0),
m_count(-1),
m_orientation(Qt::Vertical),
m_xSection(-1),
m_ySection(-1),
m_seriesSignalsBlock(false),
m_modelSignalsBlock(false),
q_ptr(q)
{
}
void QXYModelMapperPrivate::blockModelSignals(bool block)
{
m_modelSignalsBlock = block;
}
void QXYModelMapperPrivate::blockSeriesSignals(bool block)
{
m_seriesSignalsBlock = block;
}
QModelIndex QXYModelMapperPrivate::xModelIndex(int xPos)
{
if (m_count != -1 && xPos >= m_count)
return QModelIndex(); // invalid
if (m_orientation == Qt::Vertical)
return m_model->index(xPos + m_first, m_xSection);
else
return m_model->index(m_xSection, xPos + m_first);
}
QModelIndex QXYModelMapperPrivate::yModelIndex(int yPos)
{
if (m_count != -1 && yPos >= m_count)
return QModelIndex(); // invalid
if (m_orientation == Qt::Vertical)
return m_model->index(yPos + m_first, m_ySection);
else
return m_model->index(m_ySection, yPos + m_first);
}
void QXYModelMapperPrivate::handlePointAdded(int pointPos)
{
Marek Rosa
XYModelMapper slots for series signals implemented
r1262 if (m_seriesSignalsBlock)
return;
if (m_count != -1)
m_count += 1;
blockModelSignals();
if (m_orientation == Qt::Vertical)
m_model->insertRows(pointPos + m_first, 1);
else
m_model->insertColumns(pointPos + m_first, 1);
m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
blockModelSignals(false);
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
void QXYModelMapperPrivate::handlePointRemoved(int pointPos)
{
Marek Rosa
XYModelMapper slots for series signals implemented
r1262 if (m_seriesSignalsBlock)
return;
if (m_count != -1)
m_count -= 1;
blockModelSignals();
if (m_orientation == Qt::Vertical)
m_model->removeRow(pointPos + m_first);
else
m_model->removeColumn(pointPos + m_first);
blockModelSignals(false);
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
void QXYModelMapperPrivate::handlePointReplaced(int pointPos)
{
Marek Rosa
XYModelMapper slots for series signals implemented
r1262 if (m_seriesSignalsBlock)
return;
blockModelSignals();
m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
blockModelSignals(false);
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
void QXYModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
{
Tero Ahola
XY model mappers to QML api
r1278 if (m_model == 0 || m_series == 0)
return;
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 if (m_modelSignalsBlock)
return;
blockSeriesSignals();
QModelIndex index;
QPointF oldPoint;
QPointF newPoint;
for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
index = topLeft.sibling(row, column);
Marek Rosa
Fixed problem with qhxymodelmapper
r1317 if (m_orientation == Qt::Vertical && (index.column() == m_xSection || index.column() == m_ySection)) {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
Marek Rosa
Fixed problem with qhxymodelmapper
r1317 QModelIndex xIndex = xModelIndex(index.row() - m_first);
QModelIndex yIndex = yModelIndex(index.row() - m_first);
if (xIndex.isValid() && yIndex.isValid()) {
oldPoint = m_series->points().at(index.row() - m_first);
newPoint.setX(m_model->data(xIndex).toReal());
newPoint.setY(m_model->data(yIndex).toReal());
}
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
} else if (m_orientation == Qt::Horizontal && (index.row() == m_xSection || index.row() == m_ySection)) {
if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
Marek Rosa
Fixed problem with qhxymodelmapper
r1317 QModelIndex xIndex = xModelIndex(index.column() - m_first);
QModelIndex yIndex = yModelIndex(index.column() - m_first);
if (xIndex.isValid() && yIndex.isValid()) {
oldPoint = m_series->points().at(index.column() - m_first);
newPoint.setX(m_model->data(xIndex).toReal());
newPoint.setY(m_model->data(yIndex).toReal());
}
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
} else {
continue;
}
m_series->replace(oldPoint, newPoint);
}
}
Marek Rosa
BarModelMapper: implemented model updated slots. Some more work needed with categories
r1295 blockSeriesSignals(false);
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
void QXYModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
{
Q_UNUSED(parent);
if (m_modelSignalsBlock)
return;
blockSeriesSignals();
if (m_orientation == Qt::Vertical)
insertData(start, end);
else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
initializeXYFromModel();
blockSeriesSignals(false);
}
void QXYModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
{
Q_UNUSED(parent);
if (m_modelSignalsBlock)
return;
blockSeriesSignals();
if (m_orientation == Qt::Vertical)
removeData(start, end);
else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
initializeXYFromModel();
blockSeriesSignals(false);
}
void QXYModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
{
Q_UNUSED(parent);
if (m_modelSignalsBlock)
return;
blockSeriesSignals();
if (m_orientation == Qt::Horizontal)
insertData(start, end);
else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
initializeXYFromModel();
blockSeriesSignals(false);
}
void QXYModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
{
Q_UNUSED(parent);
if (m_modelSignalsBlock)
return;
blockSeriesSignals();
if (m_orientation == Qt::Horizontal)
removeData(start, end);
else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
initializeXYFromModel();
blockSeriesSignals(false);
}
void QXYModelMapperPrivate::insertData(int start, int end)
{
if (m_model == 0 || m_series == 0)
return;
if (m_count != -1 && start >= m_first + m_count) {
return;
} else {
int addedCount = end - start + 1;
if (m_count != -1 && addedCount > m_count)
addedCount = m_count;
int first = qMax(start, m_first);
int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
for (int i = first; i <= last; i++) {
QPointF point;
Marek Rosa
Fixed problem with qhxymodelmapper
r1317 QModelIndex xIndex = xModelIndex(i - m_first);
QModelIndex yIndex = yModelIndex(i - m_first);
if (xIndex.isValid() && yIndex.isValid()) {
point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
m_series->insert(i - m_first, point);
}
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
// remove excess of slices (abouve m_count)
if (m_count != -1 && m_series->points().size() > m_count)
for (int i = m_series->points().size() - 1; i >= m_count; i--) {
m_series->remove(m_series->points().at(i));
}
}
}
void QXYModelMapperPrivate::removeData(int start, int end)
{
if (m_model == 0 || m_series == 0)
return;
int removedCount = end - start + 1;
if (m_count != -1 && start >= m_first + m_count) {
return;
} else {
Marek Rosa
Added Vertical and Horizontal BarModelMappers
r1294 int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 int first = qMax(start, m_first); // get the index of the first item that will be removed.
Marek Rosa
Added Vertical and Horizontal BarModelMappers
r1294 int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed.
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 for (int i = last; i >= first; i--) {
m_series->remove(m_series->points().at(i - m_first));
}
if (m_count != -1) {
int itemsAvailable; // check how many are available to be added
if (m_orientation == Qt::Vertical)
Marek Rosa
Added Vertical and Horizontal BarModelMappers
r1294 itemsAvailable = m_model->rowCount() - m_first - m_series->count();
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 else
Marek Rosa
Added Vertical and Horizontal BarModelMappers
r1294 itemsAvailable = m_model->columnCount() - m_first - m_series->count();
int toBeAdded = qMin(itemsAvailable, m_count - m_series->count()); // add not more items than there is space left to be filled.
int currentSize = m_series->count();
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 if (toBeAdded > 0)
Marek Rosa
Added Vertical and Horizontal BarModelMappers
r1294 for (int i = m_series->count(); i < currentSize + toBeAdded; i++) {
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 QPointF point;
Marek Rosa
Fixed problem with qhxymodelmapper
r1317 QModelIndex xIndex = xModelIndex(i);
QModelIndex yIndex = yModelIndex(i);
if (xIndex.isValid() && yIndex.isValid()) {
point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
m_series->insert(i, point);
}
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 }
}
}
}
void QXYModelMapperPrivate::initializeXYFromModel()
{
if (m_model == 0 || m_series == 0)
return;
blockSeriesSignals();
// clear current content
m_series->clear();
// create the initial slices set
int pointPos = 0;
QModelIndex xIndex = xModelIndex(pointPos);
QModelIndex yIndex = yModelIndex(pointPos);
while (xIndex.isValid() && yIndex.isValid()) {
QPointF point;
point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
m_series->append(point);
pointPos++;
xIndex = xModelIndex(pointPos);
yIndex = yModelIndex(pointPos);
}
blockSeriesSignals(false);
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164 }
#include "moc_qxymodelmapper.cpp"
Marek Rosa
XYModelMapper slots for model signals implemented
r1256 #include "moc_qxymodelmapper_p.cpp"
Marek Rosa
Mapper class added for xyseries and pieseries. Model support commented out for barseries for now.
r1164
QTCOMMERCIALCHART_END_NAMESPACE