#include "qchartglobal.h" #include "qlegend.h" #include "qseries.h" #include "legendmarker_p.h" #include "qxyseries.h" #include "qlineseries.h" #include "qareaseries.h" #include "qscatterseries.h" #include "qsplineseries.h" #include "qbarseries.h" #include "qstackedbarseries.h" #include "qpercentbarseries.h" #include "qbarset.h" #include "qpieseries.h" #include "qpieslice.h" #include #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE QLegend::QLegend(QGraphicsItem *parent) : QGraphicsObject(parent) ,mBoundingRect(0,0,1,1) ,mBackgroundBrush(Qt::darkGray) // TODO: from theme? ,mMinimumSize(50,20) // TODO: magic numbers ,mMaximumSize(150,100) ,mPreferredLayout(QLegend::PreferredLayoutVertical) { setVisible(false); } void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option) Q_UNUSED(widget) painter->setBrush(mBackgroundBrush); painter->drawRect(mBoundingRect); } QRectF QLegend::boundingRect() const { return mBoundingRect; } void QLegend::setBackgroundBrush(const QBrush& brush) { mBackgroundBrush = brush; } QBrush QLegend::backgroundBrush() const { return mBackgroundBrush; } void QLegend::setPreferredLayout(QLegend::PreferredLayout preferred) { mPreferredLayout = preferred; layoutChanged(); } QSizeF QLegend::minimumSize() const { return mMinimumSize; } void QLegend::setMinimumSize(const QSizeF size) { mMinimumSize = size; } void QLegend::handleSeriesAdded(QSeries* series, Domain* domain) { Q_UNUSED(domain) mSeriesList.append(series); createMarkers(series); layoutChanged(); } void QLegend::handleSeriesRemoved(QSeries* series) { if (series->type() == QSeries::SeriesTypeArea) { // This is special case. Area series has upper and lower series, which each have markers QAreaSeries* s = static_cast (series); deleteMarkers(s->upperSeries()); deleteMarkers(s->lowerSeries()); } else { deleteMarkers(series); } mSeriesList.removeOne(series); layoutChanged(); } void QLegend::handleGeometryChanged(const QRectF& size) { mBoundingRect = size; layoutChanged(); } void QLegend::createMarkers(QSeries *series) { switch (series->type()) { case QSeries::SeriesTypeLine: { QLineSeries* lineSeries = static_cast(series); appendMarkers(lineSeries); break; } case QSeries::SeriesTypeArea: { QAreaSeries* areaSeries = static_cast(series); appendMarkers(areaSeries->upperSeries()); if(areaSeries->lowerSeries()) appendMarkers(areaSeries->lowerSeries()); break; } case QSeries::SeriesTypeBar: { QBarSeries* barSeries = static_cast(series); appendMarkers(barSeries); break; } case QSeries::SeriesTypeStackedBar: { QStackedBarSeries* stackedBarSeries = static_cast(series); appendMarkers(stackedBarSeries); break; } case QSeries::SeriesTypePercentBar: { QPercentBarSeries* percentBarSeries = static_cast(series); appendMarkers(percentBarSeries); break; } case QSeries::SeriesTypeScatter: { QScatterSeries *scatterSeries = static_cast(series); appendMarkers(scatterSeries); break; } case QSeries::SeriesTypePie: { QPieSeries *pieSeries = static_cast(series); appendMarkers(pieSeries); break; } case QSeries::SeriesTypeSpline: { QSplineSeries* splineSeries = static_cast(series); appendMarkers(splineSeries); break; } default: { qDebug()<< "QLegend::createMarkers" << series->type() << "not implemented."; break; } } } void QLegend::appendMarkers(QXYSeries* series) { LegendMarker* marker = new LegendMarker(series,this); marker->setName(series->name()); marker->setBrush(series->brush()); connect(marker,SIGNAL(clicked(QSeries*,Qt::MouseButton)),this,SIGNAL(clicked(QSeries*,Qt::MouseButton))); mMarkers.append(marker); childItems().append(marker); } void QLegend::appendMarkers(QBarSeries *series) { foreach(QBarSet* s, series->barSets()) { LegendMarker* marker = new LegendMarker(series,s,this); marker->setName(s->name()); marker->setBrush(s->brush()); connect(marker,SIGNAL(clicked(QBarSet*,Qt::MouseButton)),this,SIGNAL(clicked(QBarSet*,Qt::MouseButton))); connect(s,SIGNAL(changed()),marker,SLOT(changed())); mMarkers.append(marker); childItems().append(marker); } } void QLegend::appendMarkers(QPieSeries *series) { foreach(QPieSlice* s, series->slices()) { LegendMarker* marker = new LegendMarker(series,s,this); marker->setName(s->label()); marker->setBrush(s->sliceBrush()); connect(marker,SIGNAL(clicked(QPieSlice*,Qt::MouseButton)),this,SIGNAL(clicked(QPieSlice*,Qt::MouseButton))); connect(s,SIGNAL(changed()),marker,SLOT(changed())); mMarkers.append(marker); childItems().append(marker); } } void QLegend::deleteMarkers(QSeries *series) { // Search all markers that belong to given series and delete them. foreach (LegendMarker *m, mMarkers) { if (m->series() == series) { mMarkers.removeOne(m); delete m; } } } void QLegend::layoutChanged() { // Calculate layout for markers and text if (mMarkers.count() <= 0) { // Nothing to do return; } // Limit legend size to maximum. QSizeF size = mBoundingRect.size(); // TODO: grid layout switch (mPreferredLayout) { case QLegend::PreferredLayoutHorizontal: { qreal steps = mMarkers.count(); qreal xStep = size.width() / (steps+1); qreal x = mBoundingRect.x() + xStep/2; qreal y = mBoundingRect.y(); // Half of legend marker min size foreach (LegendMarker* m, mMarkers) { m->setBoundingRect(QRectF(x,y,xStep,size.height()/2)); x += xStep; } break; } case QLegend::PreferredLayoutVertical: { // Limit markers to bounding rect size. if (size.width() > mBoundingRect.width()) { size.setWidth(mBoundingRect.width()); } qreal steps = mMarkers.count(); qreal yStep = size.height() / (steps+1); qreal x = mBoundingRect.x(); qreal y = mBoundingRect.y() + yStep/2; foreach (LegendMarker* m, mMarkers) { m->setBoundingRect(QRectF(x,y,size.width(),yStep)); y += yStep; } break; } default: { break; } } } #include "moc_qlegend.cpp" QTCOMMERCIALCHART_END_NAMESPACE