diff --git a/src/legend/qarealegendmarker.cpp b/src/legend/qarealegendmarker.cpp index 40b103a..c19d7d3 100644 --- a/src/legend/qarealegendmarker.cpp +++ b/src/legend/qarealegendmarker.cpp @@ -67,6 +67,16 @@ QAreaLegendMarkerPrivate::~QAreaLegendMarkerPrivate() QObject::disconnect(m_series, SIGNAL(nameChanged()), this, SLOT(updated())); } +QAreaSeries* QAreaLegendMarkerPrivate::series() +{ + return m_series; +} + +QObject* QAreaLegendMarkerPrivate::relatedObject() +{ + return m_series; +} + void QAreaLegendMarkerPrivate::updated() { m_item->setBrush(m_series->brush()); diff --git a/src/legend/qarealegendmarker_p.h b/src/legend/qarealegendmarker_p.h index 9de60d9..e2f88c5 100644 --- a/src/legend/qarealegendmarker_p.h +++ b/src/legend/qarealegendmarker_p.h @@ -48,6 +48,10 @@ public: explicit QAreaLegendMarkerPrivate(QAreaLegendMarker *q, QAreaSeries *series, QLegend *legend); virtual ~QAreaLegendMarkerPrivate(); + // internal + virtual QAreaSeries* series(); + virtual QObject* relatedObject(); + public Q_SLOTS: virtual void updated(); diff --git a/src/legend/qbarlegendmarker.cpp b/src/legend/qbarlegendmarker.cpp index 25159b9..66fc2fd 100644 --- a/src/legend/qbarlegendmarker.cpp +++ b/src/legend/qbarlegendmarker.cpp @@ -76,6 +76,16 @@ QBarLegendMarkerPrivate::~QBarLegendMarkerPrivate() QObject::disconnect(m_barset, SIGNAL(penChanged()), this, SLOT(updated())); } +QAbstractBarSeries* QBarLegendMarkerPrivate::series() +{ + return m_series; +} + +QObject* QBarLegendMarkerPrivate::relatedObject() +{ + return m_barset; +} + void QBarLegendMarkerPrivate::updated() { m_item->setPen(m_barset->pen()); diff --git a/src/legend/qbarlegendmarker_p.h b/src/legend/qbarlegendmarker_p.h index 5981397..27a27c6 100644 --- a/src/legend/qbarlegendmarker_p.h +++ b/src/legend/qbarlegendmarker_p.h @@ -49,6 +49,9 @@ public: explicit QBarLegendMarkerPrivate(QBarLegendMarker *q, QAbstractBarSeries *series, QBarSet *barset, QLegend *legend); virtual ~QBarLegendMarkerPrivate(); + virtual QAbstractBarSeries* series(); + virtual QObject* relatedObject(); + public Q_SLOTS: virtual void updated(); diff --git a/src/legend/qlegend.cpp b/src/legend/qlegend.cpp index ac01b25..1d75b19 100644 --- a/src/legend/qlegend.cpp +++ b/src/legend/qlegend.cpp @@ -43,7 +43,7 @@ #include #include -#include +#include "qlegendmarker.h" #include "qlegendmarker_p.h" #include "legendmarkeritem_p.h" @@ -483,13 +483,8 @@ void QLegendPrivate::appendSeries(QAbstractSeries* series) } QList newMarkers = series->d_ptr->createLegendMarkers(q_ptr); - foreach (QLegendMarker* marker, newMarkers) { - marker->setFont(m_font); - marker->setLabelBrush(m_labelBrush); - marker->setVisible(series->isVisible()); - m_items->addToGroup(marker->d_ptr.data()->item()); - m_legendMarkers << marker; - } + decorateMarkers(newMarkers); + addMarkers(newMarkers); // TODO: This is the part I don't like. There should be better solution. // On the other hand. It is only one switch case for appending and another for removing series @@ -534,14 +529,14 @@ void QLegendPrivate::removeSeries(QAbstractSeries* series) m_series.removeOne(series); } - foreach (QLegendMarker *marker, m_legendMarkers) { - if (marker->series() == series) { - marker->d_ptr.data()->item()->setVisible(false); - m_items->removeFromGroup(marker->d_ptr.data()->item()); - delete marker; - m_legendMarkers.removeAll(marker); + // Find out, which markers to remove + QList removed; + foreach (QLegendMarker *m, m_legendMarkers) { + if (m->series() == series) { + removed << m; } } + removeMarkers(removed); switch (series->type()) { @@ -571,9 +566,7 @@ void QLegendPrivate::removeSeries(QAbstractSeries* series) } } - QObject::disconnect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged())); -// QObject::disconnect(series->d_ptr.data(), SIGNAL(legendPropertiesUpdated(QAbstractSeries*)), this, SLOT(handleLegendPropertiesUpdated(QAbstractSeries*))); m_layout->invalidate(); // q_ptr->layout()->activate(); @@ -608,18 +601,70 @@ void QLegendPrivate::handleSeriesVisibleChanged() void QLegendPrivate::handleCountChanged() { - // TODO: With new markers, the series should notify markers directly. - // TODO: Better way to handle updates. Remove/Add series again seems like overkill. + // Here we handle the changes in marker count. + // Can happen for example when pieslice(s) have been added to or removed from pieseries. QAbstractSeries *series = qobject_cast (sender()); qDebug() << "QLegendPrivate::handleSeriesUpdated" << series; - // Handle new or removed markers - // Handle changes of marker pen/brush/label. every property that legend is interested - handleSeriesRemoved(series); - handleSeriesAdded(series); + QList createdMarkers = series->d_ptr->createLegendMarkers(q_ptr); + + // Find out removed markers and created markers + QList removedMarkers; + foreach (QLegendMarker *oldMarker, m_legendMarkers) { + // we have marker, which is related to sender. + if (oldMarker->series() == series) { + bool found = false; + foreach(QLegendMarker *newMarker, createdMarkers) { + // New marker considered existing if: + // - d_ptr->relatedObject() is same for both markers. + if (newMarker->d_ptr->relatedObject() == oldMarker->d_ptr->relatedObject()) { + // Delete the new marker, since we already have existing marker, that might be connected on user side. + found = true; + createdMarkers.removeOne(newMarker); + delete newMarker; + } + } + if (!found) { + // No related object found for marker, add to removedMarkers list + removedMarkers << oldMarker; + } + } + } + + removeMarkers(removedMarkers); + addMarkers(createdMarkers); + + q_ptr->layout()->invalidate(); +} + +void QLegendPrivate::addMarkers(QList markers) +{ + foreach (QLegendMarker* marker, markers) { + m_items->addToGroup(marker->d_ptr.data()->item()); + m_legendMarkers << marker; + } +} + +void QLegendPrivate::removeMarkers(QList markers) +{ + foreach (QLegendMarker *marker, markers) { + marker->d_ptr->item()->setVisible(false); + m_items->removeFromGroup(marker->d_ptr->item()); + delete marker; + m_legendMarkers.removeOne(marker); + } +} + +void QLegendPrivate::decorateMarkers(QList markers) +{ + foreach (QLegendMarker* marker, markers) { + marker->setFont(m_font); + marker->setLabelBrush(m_labelBrush); + } } + #include "moc_qlegend.cpp" #include "moc_qlegend_p.cpp" diff --git a/src/legend/qlegend_p.h b/src/legend/qlegend_p.h index 1b1abb5..32fdf77 100644 --- a/src/legend/qlegend_p.h +++ b/src/legend/qlegend_p.h @@ -66,6 +66,12 @@ public Q_SLOTS: void handleCountChanged(); private: + // Internal helpers + void addMarkers(QList markers); + void removeMarkers(QList markers); + void decorateMarkers(QList markers); + +private: QLegend *q_ptr; ChartPresenter *m_presenter; LegendLayout *m_layout; diff --git a/src/legend/qlegendmarker.cpp b/src/legend/qlegendmarker.cpp index 6932852..ec954be 100644 --- a/src/legend/qlegendmarker.cpp +++ b/src/legend/qlegendmarker.cpp @@ -25,6 +25,7 @@ #include #include #include +#include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -32,6 +33,7 @@ QLegendMarker::QLegendMarker(QLegendMarkerPrivate &d, QObject *parent) : QObject(parent), d_ptr(&d) { + d_ptr->m_item->setVisible(d_ptr->series()->isVisible()); } QLegendMarker::~QLegendMarker() @@ -104,6 +106,7 @@ QLegendMarkerPrivate::QLegendMarkerPrivate(QLegendMarker *q, QLegend *legend) : m_legend(legend) { m_item = new LegendMarkerItem(this); +// m_item->setVisible(q->series()->isVisible()); } QLegendMarkerPrivate::~QLegendMarkerPrivate() diff --git a/src/legend/qlegendmarker.h b/src/legend/qlegendmarker.h index 5f23612..f743b66 100644 --- a/src/legend/qlegendmarker.h +++ b/src/legend/qlegendmarker.h @@ -74,14 +74,13 @@ public: virtual QAbstractSeries* series() = 0; -protected: - explicit QLegendMarker(QLegendMarkerPrivate &d, QObject *parent = 0); - Q_SIGNALS: void clicked(); void hovered(bool status); protected: + explicit QLegendMarker(QLegendMarkerPrivate &d, QObject *parent = 0); + QScopedPointer d_ptr; Q_DISABLE_COPY(QLegendMarker) friend class QLegendPrivate; diff --git a/src/legend/qlegendmarker_p.h b/src/legend/qlegendmarker_p.h index 85bdf6a..7889d1e 100644 --- a/src/legend/qlegendmarker_p.h +++ b/src/legend/qlegendmarker_p.h @@ -66,6 +66,10 @@ public: // Item gets the event, logic for event is here void handleMousePressEvent(QGraphicsSceneEvent *event); + // internal + virtual QAbstractSeries* series() = 0; + virtual QObject* relatedObject() = 0; + public Q_SLOTS: virtual void updated() {}; diff --git a/src/legend/qpielegendmarker.cpp b/src/legend/qpielegendmarker.cpp index dcf218d..44946fb 100644 --- a/src/legend/qpielegendmarker.cpp +++ b/src/legend/qpielegendmarker.cpp @@ -76,6 +76,16 @@ QPieLegendMarkerPrivate::~QPieLegendMarkerPrivate() QObject::disconnect(m_slice, SIGNAL(penChanged()), this, SLOT(updated())); } +QPieSeries* QPieLegendMarkerPrivate::series() +{ + return m_series; +} + +QObject* QPieLegendMarkerPrivate::relatedObject() +{ + return m_slice; +} + void QPieLegendMarkerPrivate::updated() { m_item->setPen(m_slice->pen()); diff --git a/src/legend/qpielegendmarker_p.h b/src/legend/qpielegendmarker_p.h index f662be8..62f83df 100644 --- a/src/legend/qpielegendmarker_p.h +++ b/src/legend/qpielegendmarker_p.h @@ -49,6 +49,10 @@ public: explicit QPieLegendMarkerPrivate(QPieLegendMarker *q, QPieSeries *series, QPieSlice *slice, QLegend *legend); virtual ~QPieLegendMarkerPrivate(); + // internal + virtual QPieSeries* series(); + virtual QObject* relatedObject(); + public Q_SLOTS: virtual void updated(); diff --git a/src/legend/qxylegendmarker.cpp b/src/legend/qxylegendmarker.cpp index 8db1338..ad7c34d 100644 --- a/src/legend/qxylegendmarker.cpp +++ b/src/legend/qxylegendmarker.cpp @@ -67,6 +67,16 @@ QXYLegendMarkerPrivate::~QXYLegendMarkerPrivate() QObject::disconnect(m_series, SIGNAL(nameChanged()), this, SLOT(updated())); } +QAbstractSeries* QXYLegendMarkerPrivate::series() +{ + return m_series; +} + +QObject* QXYLegendMarkerPrivate::relatedObject() +{ + return m_series; +} + void QXYLegendMarkerPrivate::updated() { m_item->setLabel(m_series->name()); diff --git a/src/legend/qxylegendmarker_p.h b/src/legend/qxylegendmarker_p.h index c4130c3..98c7c5b 100644 --- a/src/legend/qxylegendmarker_p.h +++ b/src/legend/qxylegendmarker_p.h @@ -48,6 +48,10 @@ public: explicit QXYLegendMarkerPrivate(QXYLegendMarker *q, QXYSeries *series, QLegend *legend); virtual ~QXYLegendMarkerPrivate(); + // internal + virtual QAbstractSeries* series(); + virtual QObject* relatedObject(); + public Q_SLOTS: virtual void updated();