From 7b90ec69ce9a3353820d295c222ef3f79537484d 2012-02-29 07:45:14 From: Michal Klocek Date: 2012-02-29 07:45:14 Subject: [PATCH] Rewrite animation hadnling in line series * Clean up the old code * implement single animator * buffer value replace request * optimize calls to geometry changed * remove old not used slots * add ownership line animator --- diff --git a/src/axisanimationitem_p.h b/src/axisanimationitem_p.h index f7c7870..f4b70b1 100644 --- a/src/axisanimationitem_p.h +++ b/src/axisanimationitem_p.h @@ -29,7 +29,7 @@ class AxisAnimator: public QVariantAnimation { public: AxisAnimator(AxisItem *axis,QObject *parent = 0); - virtual ~AxisAnimator(); + ~AxisAnimator(); protected: virtual QVariant interpolated (const QVariant & from, const QVariant & to, qreal progress ) const; virtual void updateCurrentValue (const QVariant & value ); diff --git a/src/axisitem.cpp b/src/axisitem.cpp index cea51b9..e086ff8 100644 --- a/src/axisitem.cpp +++ b/src/axisitem.cpp @@ -58,9 +58,6 @@ void AxisItem::clear(int count) if(lines.size()%2) delete(shades.takeLast()); delete(axis.takeLast()); } - - m_thicksList.clear(); - } void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) diff --git a/src/barchart/barpresenterbase_p.h b/src/barchart/barpresenterbase_p.h index c342ba1..45c0499 100644 --- a/src/barchart/barpresenterbase_p.h +++ b/src/barchart/barpresenterbase_p.h @@ -35,7 +35,7 @@ public: virtual void dataChanged(); // data of series has changed -> need to recalculate bar sizes virtual void layoutChanged() = 0; // layout has changed -> need to recalculate bar sizes -protected slots: +public slots: void handleModelChanged(int index); void handleDomainChanged(const Domain& domain); void handleGeometryChanged(const QRectF& size); diff --git a/src/chartdataset.cpp b/src/chartdataset.cpp index 85cab17..54fc613 100644 --- a/src/chartdataset.cpp +++ b/src/chartdataset.cpp @@ -150,12 +150,11 @@ void ChartDataSet::addSeries(QSeries* series, QChartAxis *axisY) m_axisXInitialized=true; } - - emit seriesAdded(series); QStringList ylabels = createLabels(axisY,domain.m_minY,domain.m_maxY); QStringList xlabels = createLabels(axisX(),domain.m_minX,domain.m_maxX); emit axisLabelsChanged(axisY,ylabels); emit axisLabelsChanged(axisX(),xlabels); + emit seriesAdded(series); emit seriesDomainChanged(series,domain); } diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp index 61c8704..c1b6923 100644 --- a/src/chartpresenter.cpp +++ b/src/chartpresenter.cpp @@ -118,8 +118,11 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) } m_chartTheme->decorate(item,lineSeries,m_chartItems.count()); QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&))); - QObject::connect(lineSeries,SIGNAL(pointChanged(int)),item,SLOT(handleModelChanged(int))); + QObject::connect(lineSeries,SIGNAL(pointReplaced(int)),item,SLOT(handlePointReplaced(int))); + QObject::connect(lineSeries,SIGNAL(pointAdded(int)),item,SLOT(handlePointAdded(int))); + QObject::connect(lineSeries,SIGNAL(pointRemoved(int)),item,SLOT(handlePointRemoved(int))); m_chartItems.insert(series,item); + if(m_rect.isValid()) item->handleGeometryChanged(m_rect); break; } @@ -131,6 +134,7 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int))); m_chartItems.insert(series,item); // m_axisXItem->setVisible(false); + if(m_rect.isValid()) item->handleGeometryChanged(m_rect); break; } @@ -142,6 +146,7 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&))); QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int))); m_chartItems.insert(series,item); + if(m_rect.isValid()) item->handleGeometryChanged(m_rect); break; } @@ -153,6 +158,7 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&))); QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int))); m_chartItems.insert(series,item); + if(m_rect.isValid()) item->handleGeometryChanged(m_rect); break; } case QSeries::SeriesTypeScatter: { @@ -163,6 +169,7 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) scatterPresenter, SLOT(handleGeometryChanged(const QRectF&))); m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count()); m_chartItems.insert(scatterSeries, scatterPresenter); + if(m_rect.isValid()) scatterPresenter->handleGeometryChanged(m_rect); break; } case QSeries::SeriesTypePie: { @@ -186,6 +193,7 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) } m_chartItems.insert(series, pie); + pie->handleGeometryChanged(m_rect); break; } default: { @@ -193,8 +201,6 @@ void ChartPresenter::handleSeriesAdded(QSeries* series) break; } } - - if(m_rect.isValid()) emit geometryChanged(m_rect); } void ChartPresenter::handleSeriesRemoved(QSeries* series) @@ -203,11 +209,6 @@ void ChartPresenter::handleSeriesRemoved(QSeries* series) delete item; } -void ChartPresenter::handleSeriesChanged(QSeries* series) -{ - //TODO: -} - void ChartPresenter::handleSeriesDomainChanged(QSeries* series, const Domain& domain) { m_chartItems.value(series)->handleDomainChanged(domain); diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h index 62d4769..e78acaf 100644 --- a/src/chartpresenter_p.h +++ b/src/chartpresenter_p.h @@ -53,7 +53,6 @@ public slots: void handleAxisRemoved(QChartAxis* axis); void handleSeriesDomainChanged(QSeries* series, const Domain& domain); void handleAxisLabelsChanged(QChartAxis* axis, const QStringList& labels); - void handleSeriesChanged(QSeries* series); void handleGeometryChanged(); signals: void geometryChanged(const QRectF& rect); diff --git a/src/linechart/linechartanimationitem.cpp b/src/linechart/linechartanimationitem.cpp index 0a07e80..61f5501 100644 --- a/src/linechart/linechartanimationitem.cpp +++ b/src/linechart/linechartanimationitem.cpp @@ -19,8 +19,19 @@ LineChartAnimationItem::~LineChartAnimationItem() void LineChartAnimationItem::addPoints(const QVector& points) { - m_data=points; - clearView(); + QVector vector0 = vector1; + calculateLayout(vector1); + if(vector1.count()==0) return; + vector0.resize(vector1.size()); + + + LineChartAnimatator *animation = new LineChartAnimatator(this,this); + animation->setDuration(duration); + animation->setEasingCurve(QEasingCurve::InOutBack); + animation->setKeyValueAt(0.0, qVariantFromValue(vector0)); + animation->setKeyValueAt(1.0, qVariantFromValue(vector1)); + animation->start(QAbstractAnimation::DeleteWhenStopped); + QPropertyAnimation *animation = new QPropertyAnimation(this, "a_addPoints", parent()); animation->setDuration(duration); //animation->setEasingCurve(QEasingCurve::InOutBack); @@ -29,7 +40,7 @@ void LineChartAnimationItem::addPoints(const QVector& points) animation->start(QAbstractAnimation::DeleteWhenStopped); } -void LineChartAnimationItem::setPoint(int index,const QPointF& point) +void LineChartAnimationItem::replacePoint(int index,const QPointF& point) { AnimationHelper* helper = new AnimationHelper(this,index); QPropertyAnimation *animation = new QPropertyAnimation(helper, "point", parent()); @@ -52,11 +63,42 @@ void LineChartAnimationItem::aw_addPoints(int points) void LineChartAnimationItem::aw_setPoint(int index,const QPointF& point) { - LineChartItem::setPoint(index,point); + LineChartItem::replacePoint(index,point); updateGeometry(); update(); } +LineChartAnimatator::LineChartAnimatator(LineChartItem *item, int index , QObject *parent = 0 ):QVariantAnimation(parent), + m_item(item), + m_index(index) +{ +}; + +LineChartAnimatator::~LineChartAnimatator() +{ +} + +QVariant LineChartAnimatator::interpolated(const QVariant &start, const QVariant & end, qreal progress ) const +{ + QVector startVector = qVariantValue >(start); + QVector endVecotr = qVariantValue >(end); + QVector result; + Q_ASSERT(startVector.count() == endVecotr.count()); + + for(int i =0 ;i< startVector.count();i++){ + qreal value = startVector[i] + ((endVecotr[i]- startVector[i]) * progress);//qBound(0.0, progress, 1.0)); + result << value; + } + return qVariantFromValue(result); +} + + +void LineChartAnimatator::updateCurrentValue (const QVariant & value ) +{ + QVector vector = qVariantValue >(value); + m_axis->applyLayout(vector); +} + #include "moc_linechartanimationitem_p.cpp" diff --git a/src/linechart/linechartanimationitem_p.h b/src/linechart/linechartanimationitem_p.h index 163df48..eef325e 100644 --- a/src/linechart/linechartanimationitem_p.h +++ b/src/linechart/linechartanimationitem_p.h @@ -10,22 +10,13 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE class LineChartItem; class LineChartAnimationItem : public LineChartItem { - Q_OBJECT - Q_PROPERTY(int a_addPoints READ ar_addPoints WRITE aw_addPoints); - // Q_PROPERTY(QPointF a_setPoint READ ar_setPoint WRITE aw_setPoint); + public: LineChartAnimationItem(ChartPresenter* presenter, QLineSeries *series, QGraphicsItem *parent = 0); virtual ~LineChartAnimationItem(); void addPoints(const QVector& points); - void setPoint(int index,const QPointF& point); - //void removePoint(const QPointF& point){}; - //void setPoint(const QPointF& oldPoint, const QPointF& newPoint){}; - - int ar_addPoints() const { return m_addPoints;} - void aw_addPoints(int points); - const QPointF& ar_setPoint() const { return m_setPoint;} - void aw_setPoint(int index,const QPointF& point); + void replacePoint(int index,const QPointF& point); private: QVector m_data; @@ -35,16 +26,12 @@ private: int m_setPoint_index; }; -class AnimationHelper: public QObject +class LineChartAnimatator: public QVariantAnimation { - Q_OBJECT - Q_PROPERTY(QPointF point READ point WRITE setPoint); + public: - AnimationHelper(LineChartAnimationItem* item,int index):m_item(item),m_index(index){}; - void setPoint(const QPointF& point){ - m_item->aw_setPoint(m_index,point); - } - QPointF point(){return m_point;} + LineChartAnimatator(LineChartItem *item, int index , QObject *parent = 0 ):m_item(item),m_index(index){}; + QPointF m_point; LineChartAnimationItem* m_item; int m_index; diff --git a/src/linechart/linechartitem.cpp b/src/linechart/linechartitem.cpp index 2212b29..24e3a12 100644 --- a/src/linechart/linechartitem.cpp +++ b/src/linechart/linechartitem.cpp @@ -10,10 +10,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE LineChartItem::LineChartItem(ChartPresenter* presenter, QLineSeries* series,QGraphicsItem *parent):ChartItem(parent), m_presenter(presenter), -m_series(series), -m_dirtyData(false), -m_dirtyGeometry(false), -m_dirtyDomain(false) +m_series(series) { setZValue(ChartPresenter::LineChartZValue); } @@ -28,78 +25,23 @@ QPainterPath LineChartItem::shape() const return m_path; } - -void LineChartItem::addPoints(const QVector& points) +void LineChartItem::createPoints(int count) { - m_data = points; - for(int i=0; isetPos(point.x()-1,point.y()-1);; - if(!m_clipRect.contains(point) || !m_series->pointsVisible()) item->setVisible(false); - m_points << item; + for (int i = 0; i < count; ++i) { + QGraphicsRectItem* item = new QGraphicsRectItem(0,0,3,3,this); + m_items.addToGroup(item); } } -void LineChartItem::addPoint(const QPointF& point) +void LineChartItem::clearPoints(int count) { - m_data << point; - QGraphicsRectItem* item = new QGraphicsRectItem(0,0,3,3,this); - m_clipRect.contains(point); - item->setPos(point.x()-1,point.y()-1); - if(!m_clipRect.contains(point) || !m_series->pointsVisible()) item->setVisible(false); - m_points << item; -} - -void LineChartItem::removePoint(const QPointF& point) -{ - Q_ASSERT(m_data.count() == m_points.count()); - int index = m_data.lastIndexOf(point,0); - m_data.remove(index); - delete(m_points.takeAt(index)); -} + QList items = m_items.childItems(); -void LineChartItem::setPoint(const QPointF& oldPoint,const QPointF& newPoint) -{ - Q_ASSERT(m_data.count() == m_points.count()); - int index = m_data.lastIndexOf(oldPoint,0); - - if(index > -1){ - m_data.replace(index,newPoint); - QGraphicsItem* item = m_points.at(index); - item->setPos(newPoint.x()-1,newPoint.y()-1); + for (int i = 0; i < count; ++i) { + delete(items.takeLast()); } } -void LineChartItem::setPoint(int index,const QPointF& point) -{ - Q_ASSERT(m_data.count() == m_points.count()); - Q_ASSERT(index>=0); - - m_data.replace(index,point); - QGraphicsItem* item = m_points.at(index); - item->setPos(point.x()-1,point.y()-1); -} - -void LineChartItem::clear() -{ - qDeleteAll(m_points); - m_points.clear(); - m_hash.clear(); - m_path = QPainterPath(); - m_rect = QRect(); - m_data.clear(); -} - -void LineChartItem::clearView() -{ - qDeleteAll(m_points); - m_points.clear(); - m_path = QPainterPath(); - m_rect = QRect(); - m_data.clear(); -} - void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); @@ -111,58 +53,66 @@ void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt painter->restore(); } -void LineChartItem::calculatePoint(QPointF& point, int index, const QLineSeries* series,const QSizeF& size, const Domain& domain) const +QPointF LineChartItem::calculatePoint(int index) const { - const qreal deltaX = size.width()/domain.spanX(); - const qreal deltaY = size.height()/domain.spanY(); - qreal x = (series->x(index) - domain.m_minX)* deltaX; - qreal y = (series->y(index) - domain.m_minY)*-deltaY + size.height(); - point.setX(x); - point.setY(y); + const qreal deltaX = m_size.width()/m_domain.spanX(); + const qreal deltaY = m_size.height()/m_domain.spanY(); + qreal x = (m_series->x(index) - m_domain.m_minX)* deltaX; + qreal y = (m_series->y(index) - m_domain.m_minY)*-deltaY + m_size.height(); + return QPointF(x,y); } -void LineChartItem::calculatePoints(QVector& points, QHash& hash,const QLineSeries* series,const QSizeF& size, const Domain& domain) const +void LineChartItem::calculatePoints(QVector& points, QVector& map) const { - const qreal deltaX = size.width()/domain.spanX(); - const qreal deltaY = size.height()/domain.spanY(); + const qreal deltaX = m_size.width()/m_domain.spanX(); + const qreal deltaY = m_size.height()/m_domain.spanY(); - for (int i = 0; i < series->count(); ++i) { - qreal x = (series->x(i) - domain.m_minX)* deltaX; - qreal y = (series->y(i) - domain.m_minY)*-deltaY + size.height(); - hash[i] = points.size(); + for (int i = 0; i < m_series->count(); ++i) { + qreal x = (m_series->x(i) - m_domain.m_minX)* deltaX; + qreal y = (m_series->y(i) - m_domain.m_minY)*-deltaY + m_size.height(); + map << i; points << QPointF(x,y); } } -void LineChartItem::updateDomain() +void LineChartItem::updateItem(QVector& points,QVector& map) { - clear(); - prepareGeometryChange(); - calculatePoints(m_data,m_hash,m_series,m_size, m_domain); - addPoints(m_data); -} + int diff = m_points.size() - points.size(); -void LineChartItem::updateData() -{ - //for now the same - updateDomain(); + if(diff>0) { + clearPoints(diff); + } + else if(diff<0) { + createPoints(-diff); + } + + applyGeometry(points); + m_points=points; + m_map=map; } -void LineChartItem::updateGeometry() +void LineChartItem::applyGeometry(QVector& points) { + if(points.size()==0) return; - if(m_data.size()==0) return; + QList items = m_items.childItems(); - prepareGeometryChange(); QPainterPath path; - const QPointF& point = m_data.at(0); + const QPointF& point = points.at(0); path.moveTo(point); - - foreach( const QPointF& point , m_data) { + QGraphicsItem* item = items.at(0); + item->setPos(point.x()-1,point.y()-1); + + for(int i=1 ; i< points.size();i++) { + QGraphicsItem* item = items.at(i); + const QPointF& point = points.at(i); + item->setPos(point.x()-1,point.y()-1); + if(!m_clipRect.contains(point)) item->setVisible(false); path.lineTo(point); } + prepareGeometryChange(); m_path = path; m_rect = path.boundingRect(); } @@ -174,14 +124,78 @@ void LineChartItem::setPen(const QPen& pen) //handlers -void LineChartItem::handleModelChanged(int index) +void LineChartItem::handlePointAdded(int index) { Q_ASSERT(indexcount()); - if(m_hash.contains(index)){ - int i = m_hash.value(index); - QPointF point; - calculatePoint(point,index,m_series,m_size,m_domain); - setPoint(i,point); + Q_ASSERT(index>=0); + + if(m_map.contains(index)){ + + int i = m_map.indexOf(index); + + QPointF point = calculatePoint(index); + + if(point.isNull()) return; + + QVector points = m_points; + points.insert(i,point); + + for(int j=i;jcount()); + Q_ASSERT(index>=0); + + if(m_map.contains(index)){ + + int i = m_map.value(index); + + QVector points = m_points; + points.remove(i); + + for(int j=i;jcount()); + Q_ASSERT(index>=0); + + if(m_map.contains(index)){ + + int i = m_map.indexOf(index); + + QPointF point = calculatePoint(index); + + QVector points = m_points; + points.replace(i,point); + + updateItem(points,m_map); + + }else{ + //ignore + return; } update(); } @@ -189,7 +203,12 @@ void LineChartItem::handleModelChanged(int index) void LineChartItem::handleDomainChanged(const Domain& domain) { m_domain = domain; - updateDomain(); + if(m_domain.isEmpty()) return; + + QVector points; + QVector map; + calculatePoints(points,map); + updateItem(points,map); update(); } @@ -198,9 +217,24 @@ void LineChartItem::handleGeometryChanged(const QRectF& rect) Q_ASSERT(rect.isValid()); m_size=rect.size(); m_clipRect=rect.translated(-rect.topLeft()); - updateDomain(); - updateGeometry(); setPos(rect.topLeft()); + + if(m_domain.isEmpty()) return; + if(m_points.isEmpty()) return; + + QVector points; + QVector map; + calculatePoints(points,map); + updateItem(points,map); + update(); +} + +void LineChartItem::handleSeriesUpdated() +{ + if(m_points.count()==0) return; + + m_items.setVisible(m_series->pointsVisible()); + setPen(m_series->pen()); update(); } diff --git a/src/linechart/linechartitem_p.h b/src/linechart/linechartitem_p.h index 68ff1c9..ee08228 100644 --- a/src/linechart/linechartitem_p.h +++ b/src/linechart/linechartitem_p.h @@ -9,7 +9,6 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE class ChartPresenter; class QLineSeries; -class LineChartAnimationItem; class LineChartItem : public QObject , public ChartItem { @@ -24,32 +23,28 @@ public: QPainterPath shape() const; void setPen(const QPen& pen); - const Domain& domain() const { return m_domain;} + void setPointsVisible(bool visible); + +public slots: + void handlePointAdded(int index); + void handlePointRemoved(int index); + void handlePointReplaced(int index); + void handleDomainChanged(const Domain& domain); + void handleGeometryChanged(const QRectF& size); +protected: virtual void addPoint(const QPointF& ); virtual void addPoints(const QVector& points); virtual void removePoint(const QPointF& point); - virtual void setPoint(const QPointF& oldPoint, const QPointF& newPoint); - virtual void setPoint(int index,const QPointF& point); - void setPointsVisible(bool visible); - void clear(); - void clearView(); - int count() const { return m_data.size();} - - const QVector& points(){ return m_data;} + virtual void replacePoint(const QPointF& oldPoint, const QPointF& newPoint); + virtual void replacePoint(int index,const QPointF& point); + virtual void updateItem(QVector& points,QVector& map); + virtual void applyGeometry(QVector& points); -protected: - virtual void updateGeometry(); - virtual void updateData(); - virtual void updateDomain(); - //refactor - void calculatePoint(QPointF& point, int index, const QLineSeries* series,const QSizeF& size, const Domain& domain) const; - void calculatePoints(QVector& points,QHash& hash,const QLineSeries* series, const QSizeF& size, const Domain& domain) const; + void clear(); -protected slots: - void handleModelChanged(int index); - void handleDomainChanged(const Domain& domain); - void handleGeometryChanged(const QRectF& size); + QPointF calculatePoint(int index) const; + void calculatePoints(QVector& points,QVector& map) const; private: ChartPresenter* m_presenter; @@ -58,14 +53,11 @@ private: QRectF m_rect; QRectF m_clipRect; Domain m_domain; - QList m_points; - QVector m_data; - QHash m_hash; + QList m_items; + QVector m_points; + QVector m_map; QLineSeries* m_series; QPen m_pen; - bool m_dirtyData; - bool m_dirtyGeometry; - bool m_dirtyDomain; }; diff --git a/src/linechart/qlineseries.cpp b/src/linechart/qlineseries.cpp index fa960ef..eba6f0f 100644 --- a/src/linechart/qlineseries.cpp +++ b/src/linechart/qlineseries.cpp @@ -43,7 +43,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE /*! - \fn void QLineSeries::pointChanged(int index) + \fn void QLineSeries::pointReplaced(int index) \brief \internal \a index */ @@ -101,7 +101,7 @@ void QLineSeries::replace(qreal x,qreal y) int index = m_x.indexOf(x); m_x[index]=x; m_y[index]=y; - emit pointChanged(index); + emit pointReplaced(index); } /*! diff --git a/src/linechart/qlineseries.h b/src/linechart/qlineseries.h index 8861a7c..2c9601d 100644 --- a/src/linechart/qlineseries.h +++ b/src/linechart/qlineseries.h @@ -40,7 +40,7 @@ public: // from QChartSeries friend QDebug operator<< (QDebug d, const QLineSeries series); signals: - void pointChanged(int index); + void pointReplaced(int index); void pointRemoved(int index); void pointAdded(int index);