From 221a9324f935795aced00755ca90ef68d6c19da1 2012-05-30 07:48:41 From: Marek Rosa Date: 2012-05-30 07:48:41 Subject: [PATCH] BarModel mapper refactored. --- diff --git a/src/barchart/barchart.pri b/src/barchart/barchart.pri index 96c41d7..b85acab 100644 --- a/src/barchart/barchart.pri +++ b/src/barchart/barchart.pri @@ -25,6 +25,7 @@ PRIVATE_HEADERS += \ $$PWD/qstackedbarseries_p.h\ $$PWD/qpercentbarseries_p.h \ $$PWD/qgroupedbarseries_p.h \ + $$PWD/qbarmodelmapper_p.h PUBLIC_HEADERS += \ $$PWD/qbarseries.h \ diff --git a/src/barchart/qbarmodelmapper.cpp b/src/barchart/qbarmodelmapper.cpp index d861b9a..c082b7c 100644 --- a/src/barchart/qbarmodelmapper.cpp +++ b/src/barchart/qbarmodelmapper.cpp @@ -1,95 +1,403 @@ #include "qbarmodelmapper.h" +#include "qbarmodelmapper_p.h" +#include "qbarseries.h" +#include "qbarset.h" +#include QTCOMMERCIALCHART_BEGIN_NAMESPACE QBarModelMapper::QBarModelMapper(QObject *parent) : QObject(parent), - m_first(0), - m_count(-1), - m_orientation(Qt::Vertical), - m_mapBarBottom(-1), - m_mapBarTop(-1), - m_mapCategories(-1) + d_ptr(new QBarModelMapperPrivate(this)) +{ +} + +QAbstractItemModel* QBarModelMapper::model() const +{ + Q_D(const QBarModelMapper); + return d->m_model; +} + +void QBarModelMapper::setModel(QAbstractItemModel *model) +{ + if (model == 0) + return; + + Q_D(QBarModelMapper); + if (d->m_model) { + disconnect(d->m_model, 0, d, 0); + } + + d->m_model = model; + d->initializeBarFromModel(); + // 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))); +} + +QBarSeries* QBarModelMapper::series() const +{ + Q_D(const QBarModelMapper); + return d->m_series; +} + +void QBarModelMapper::setSeries(QBarSeries *series) { + Q_D(QBarModelMapper); + if (d->m_series) { + disconnect(d->m_series, 0, d, 0); + } + + if (series == 0) + return; + + d->m_series = series; + d->initializeBarFromModel(); + // 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))); + // connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int))); } int QBarModelMapper::first() const { - return m_first; + Q_D(const QBarModelMapper); + return d->m_first; } void QBarModelMapper::setFirst(int first) { - m_first = qMax(first, 0); - emit updated(); + Q_D(QBarModelMapper); + d->m_first = qMax(first, 0); + d->initializeBarFromModel(); } int QBarModelMapper::count() const { - return m_count; + Q_D(const QBarModelMapper); + return d->m_count; } void QBarModelMapper::setCount(int count) { - m_count = qMax(count, -1); - emit updated(); + Q_D(QBarModelMapper); + d->m_count = qMax(count, -1); + d->initializeBarFromModel(); } Qt::Orientation QBarModelMapper::orientation() const { - return m_orientation; + Q_D(const QBarModelMapper); + return d->m_orientation; } void QBarModelMapper::setOrientation(Qt::Orientation orientation) { - m_orientation = orientation; - emit updated(); + Q_D(QBarModelMapper); + d->m_orientation = orientation; + d->initializeBarFromModel(); } -int QBarModelMapper::mapBarBottom() const +int QBarModelMapper::firstBarSection() const { - return m_mapBarBottom; + Q_D(const QBarModelMapper); + return d->m_firstBarSection; } -void QBarModelMapper::setMapBarBottom(int mapValues) +void QBarModelMapper::setFirstBarSection(int firstBarSection) { - m_mapBarBottom = mapValues; - emit updated(); + Q_D(QBarModelMapper); + d->m_firstBarSection = firstBarSection; + d->initializeBarFromModel(); } -int QBarModelMapper::mapBarTop() const +int QBarModelMapper::lastBarSection() const { - return m_mapBarTop; + Q_D(const QBarModelMapper); + return d->m_lastBarSection; } -void QBarModelMapper::setMapBarTop(int mapLabels) +void QBarModelMapper::setLastBarSection(int lastBarSection) { - m_mapBarTop = mapLabels; - emit updated(); + Q_D(QBarModelMapper); + d->m_lastBarSection = lastBarSection; + d->initializeBarFromModel(); } -int QBarModelMapper::mapCategories() const +int QBarModelMapper::categoriesSection() const { - return m_mapCategories; + Q_D(const QBarModelMapper); + return d->m_categoriesSection; } -void QBarModelMapper::setMapCategories(int mapCategories) +void QBarModelMapper::setCategoriesSection(int categoriesSection) { - m_mapCategories = mapCategories; - emit updated(); + Q_D(QBarModelMapper); + d->m_categoriesSection = categoriesSection; + d->initializeBarFromModel(); } void QBarModelMapper::reset() { - m_first = 0; - m_count = -1; - m_orientation = Qt::Vertical; - m_mapBarBottom = -1; - m_mapBarTop = -1; - m_mapCategories = -1; - emit updated(); + Q_D(QBarModelMapper); + d->m_first = 0; + d->m_count = -1; + d->m_orientation = Qt::Vertical; + d->m_firstBarSection = -1; + d->m_lastBarSection = -1; + d->m_categoriesSection = -1; + d->initializeBarFromModel(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +QBarModelMapperPrivate::QBarModelMapperPrivate(QBarModelMapper *q) : + m_series(0), + m_model(0), + m_first(0), + m_count(-1), + m_orientation(Qt::Vertical), + m_firstBarSection(-1), + m_lastBarSection(-1), + m_categoriesSection(-1), + m_seriesSignalsBlock(false), + m_modelSignalsBlock(false), + q_ptr(q) +{ +} + +void QBarModelMapperPrivate::blockModelSignals(bool block) +{ + m_modelSignalsBlock = block; +} + +void QBarModelMapperPrivate::blockSeriesSignals(bool block) +{ + m_seriesSignalsBlock = block; +} + +QModelIndex QBarModelMapperPrivate::barModelIndex(int barSection, int posInBar) +{ + if (m_count != -1 && posInBar >= m_count) + return QModelIndex(); // invalid + + if (barSection < m_firstBarSection || barSection > m_lastBarSection) + return QModelIndex(); // invalid + + if (m_orientation == Qt::Vertical) + return m_model->index(posInBar + m_first, barSection); + else + return m_model->index(barSection, posInBar + m_first); +} + +QModelIndex QBarModelMapperPrivate::categoriesModelIndex(int posInCategories) +{ + if (m_count != -1 && posInCategories >= m_count) + return QModelIndex(); // invalid + + if (m_orientation == Qt::Vertical) + return m_model->index(posInCategories + m_first, m_categoriesSection); + else + return m_model->index(m_categoriesSection, posInCategories + m_first); +} + +void QBarModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + 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); + // if (m_orientation == Qt::Vertical && (index.column() == m_xSection|| index.column() == m_ySection)) { + // if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) { + // oldPoint = m_series->points().at(index.row() - m_first); + // newPoint.setX(m_model->data(m_model->index(index.row(), m_xSection)).toReal()); + // newPoint.setY(m_model->data(m_model->index(index.row(), m_ySection)).toReal()); + // } + // } 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)) { + // oldPoint = m_series->points().at(index.column() - m_first); + // newPoint.setX(m_model->data(m_model->index(m_xSection, index.column())).toReal()); + // newPoint.setY(m_model->data(m_model->index(m_ySection, index.column())).toReal()); + // } + // } else { + // continue; + // } + // m_series->replace(oldPoint, newPoint); + // } + // blockSeriesSignals(false); + // } +} + +void QBarModelMapperPrivate::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_firstBarSection || start <= m_lastBarSection || start <= m_categoriesSection) // if the changes affect the map - reinitialize + initializeBarFromModel(); + blockSeriesSignals(false); +} + +void QBarModelMapperPrivate::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_firstBarSection || start <= m_lastBarSection || start <= m_categoriesSection) // if the changes affect the map - reinitialize + initializeBarFromModel(); + blockSeriesSignals(false); +} + +void QBarModelMapperPrivate::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_firstBarSection || start <= m_lastBarSection || start <= m_categoriesSection) // if the changes affect the map - reinitialize + initializeBarFromModel(); + blockSeriesSignals(false); +} + +void QBarModelMapperPrivate::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_firstBarSection || start <= m_lastBarSection || start <= m_categoriesSection) // if the changes affect the map - reinitialize + initializeBarFromModel(); + blockSeriesSignals(false); +} + +void QBarModelMapperPrivate::insertData(int start, int end) +{ + Q_UNUSED(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; + point.setX(m_model->data(xModelIndex(i - m_first), Qt::DisplayRole).toDouble()); + point.setY(m_model->data(yModelIndex(i - m_first), Qt::DisplayRole).toDouble()); + m_series->insert(i - m_first, point); + } + + // 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 QBarModelMapperPrivate::removeData(int start, int end) +{ + Q_UNUSED(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 { + int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed + int first = qMax(start, m_first); // get the index of the first item that will be removed. + int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed. + 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) + itemsAvailable = m_model->rowCount() - m_first - m_series->count(); + else + 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(); + if (toBeAdded > 0) + for (int i = m_series->count(); i < currentSize + toBeAdded; i++) { + QPointF point; + point.setX(m_model->data(xModelIndex(i), Qt::DisplayRole).toDouble()); + point.setY(m_model->data(yModelIndex(i), Qt::DisplayRole).toDouble()); + m_series->insert(i, point); + } + } + }*/ +} + +void QBarModelMapperPrivate::initializeBarFromModel() +{ + if (m_model == 0 || m_series == 0) + return; + + blockSeriesSignals(); + // clear current content + // m_series->clear(); + + // create the initial bar sets + for (int i = m_firstBarSection; i <= m_lastBarSection; i++) { + int posInBar = 0; + QModelIndex barIndex = barModelIndex(i, posInBar); + QBarSet *barSet = new QBarSet(m_model->headerData(i, Qt::Horizontal).toString()); + // QModelIndex yIndex = yModelIndex(pointPos); + while (barIndex.isValid()) { + barSet->append(m_model->data(barIndex, Qt::DisplayRole).toDouble()); + posInBar++; + barIndex = barModelIndex(i, posInBar); + } + m_series->append(barSet); + } + + if (m_categoriesSection != -1) { + int posInCategories = 0; + QStringList categories; + QModelIndex categoriesIndex = categoriesModelIndex(posInCategories); + while (categoriesIndex.isValid()) { + categories.append(m_model->data(categoriesIndex, Qt::DisplayRole).toString()); + posInCategories++; + categoriesIndex = categoriesModelIndex(posInCategories); + } + m_series->setCategories(categories); + } + blockSeriesSignals(false); } #include "moc_qbarmodelmapper.cpp" +#include "moc_qbarmodelmapper_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/barchart/qbarmodelmapper.h b/src/barchart/qbarmodelmapper.h index 632ab6f..42ca91b 100644 --- a/src/barchart/qbarmodelmapper.h +++ b/src/barchart/qbarmodelmapper.h @@ -4,45 +4,59 @@ #include "qchartglobal.h" #include +class QAbstractItemModel; + QTCOMMERCIALCHART_BEGIN_NAMESPACE +class QBarModelMapperPrivate; +class QBarSeries; + class QTCOMMERCIALCHART_EXPORT QBarModelMapper : public QObject { Q_OBJECT -public: + Q_PROPERTY(QBarSeries *series READ series WRITE setSeries) + Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel) + Q_PROPERTY(int first READ first WRITE setFirst) + Q_PROPERTY(int count READ count WRITE setCount) + Q_ENUMS(Qt::Orientation) + +protected: explicit QBarModelMapper(QObject *parent = 0); - + +public: + QAbstractItemModel* model() const; + void setModel(QAbstractItemModel *model); + + QBarSeries* series() const; + void setSeries(QBarSeries *series); + int first() const; void setFirst(int first); int count() const; void setCount(int count); - Qt::Orientation orientation() const; - void setOrientation(Qt::Orientation orientation); + int firstBarSection() const; + void setFirstBarSection(int firstBarSection); - int mapBarBottom() const; - void setMapBarBottom(int mapBarBottom); + int lastBarSection() const; + void setLastBarSection(int lastBarSection); - int mapBarTop() const; - void setMapBarTop(int mapBarTop); + int categoriesSection() const; + void setCategoriesSection(int categoriesSection); - int mapCategories() const; - void setMapCategories(int mapCategories); +protected: + Qt::Orientation orientation() const; + void setOrientation(Qt::Orientation orientation); void reset(); Q_SIGNALS: void updated(); -private: - int m_first; - int m_count; - Qt::Orientation m_orientation; - int m_mapBarBottom; - int m_mapBarTop; - int m_mapCategories; - +protected: + QBarModelMapperPrivate * const d_ptr; + Q_DECLARE_PRIVATE(QBarModelMapper) }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/barchart/qbarmodelmapper_p.h b/src/barchart/qbarmodelmapper_p.h new file mode 100644 index 0000000..e08476f --- /dev/null +++ b/src/barchart/qbarmodelmapper_p.h @@ -0,0 +1,60 @@ +#ifndef QBARMODELMAPPER_P_H +#define QBARMODELMAPPER_P_H + +#include "qchartglobal.h" +#include +#include "qbarmodelmapper.h" + +class QModelIndex; + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QBarModelMapperPrivate : public QObject +{ + Q_OBJECT +public: + explicit QBarModelMapperPrivate(QBarModelMapper *q); + +public Q_SLOTS: + // for the model + void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight); + void modelRowsAdded(QModelIndex parent, int start, int end); + void modelRowsRemoved(QModelIndex parent, int start, int end); + void modelColumnsAdded(QModelIndex parent, int start, int end); + void modelColumnsRemoved(QModelIndex parent, int start, int end); + +// // for the series +// void handlePointAdded(int pointPos); +// void handlePointRemoved(int pointPos); +// void handlePointReplaced(int pointPos); + + void initializeBarFromModel(); + +private: + QModelIndex barModelIndex(int barSection, int posInBar); + QModelIndex categoriesModelIndex(int posInCategories); + void insertData(int start, int end); + void removeData(int start, int end); + void blockModelSignals(bool block = true); + void blockSeriesSignals(bool block = true); + +private: + QBarSeries *m_series; + QAbstractItemModel *m_model; + int m_first; + int m_count; + Qt::Orientation m_orientation; + int m_firstBarSection; + int m_lastBarSection; + int m_categoriesSection; + bool m_seriesSignalsBlock; + bool m_modelSignalsBlock; + +private: + QBarModelMapper *q_ptr; + Q_DECLARE_PUBLIC(QBarModelMapper) +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // QBARMODELMAPPER_P_H