diff --git a/examples/newlegend/mainwidget.cpp b/examples/newlegend/mainwidget.cpp index 4494d12..4d0d260 100644 --- a/examples/newlegend/mainwidget.cpp +++ b/examples/newlegend/mainwidget.cpp @@ -64,6 +64,15 @@ MainWidget::MainWidget(QWidget *parent) : connect(infoButton, SIGNAL(clicked()), this, SLOT(showDebugInfo())); m_buttonLayout->addWidget(infoButton, 7, 0); + QPushButton *connectButton = new QPushButton("Connect markers"); + connect(connectButton, SIGNAL(clicked()), this, SLOT(connectMarkers())); + m_buttonLayout->addWidget(connectButton, 8, 0); + + QPushButton *disConnectButton = new QPushButton("Disconnect markers"); + connect(disConnectButton, SIGNAL(clicked()), this, SLOT(disconnectMarkers())); + m_buttonLayout->addWidget(connectButton, 8, 0); + + m_legendPosX = new QDoubleSpinBox(); m_legendPosY = new QDoubleSpinBox(); m_legendWidth = new QDoubleSpinBox(); @@ -178,7 +187,6 @@ void MainWidget::toggleAttached() void MainWidget::addSlice() { QPieSlice* slice = new QPieSlice(QString("slice " + QString::number(m_series->count())), m_series->count()+1); -// slice->setValue(); m_series->append(slice); } @@ -190,6 +198,26 @@ void MainWidget::removeSlice() } } +void MainWidget::connectMarkers() +{ + // Example use case. + // Explode slice via marker. + // Should be doable via public api. + + foreach (QLegendMarker* marker, m_chart->legend()->markers()) { + // Disconnect possible existing connection to avoid multiple connections + QObject::disconnect(marker, SIGNAL(clicked()), this, SLOT(handleMarkerClicked())); + QObject::connect(marker, SIGNAL(clicked()), this, SLOT(handleMarkerClicked())); + } +} + +void MainWidget::disconnectMarkers() +{ + foreach (QLegendMarker* marker, m_chart->legend()->markers()) { + QObject::disconnect(marker, SIGNAL(clicked()), this, SLOT(handleMarkerClicked())); + } +} + void MainWidget::setLegendAlignment() { QPushButton *button = qobject_cast(sender()); @@ -236,6 +264,8 @@ void MainWidget::showDebugInfo() { qDebug() << "marker count:" << m_chart->legend()->markers().count(); foreach (QLegendMarker* marker, m_chart->legend()->markers()) { + qDebug() << "marker series type:" << marker->series()->type(); + qDebug() << "peer object:" << marker->peerObject(); qDebug() << "label:" << marker->label(); } } @@ -257,3 +287,15 @@ void MainWidget::updateLegendLayout() m_chart->legend()->update(); //![4] } + +void MainWidget::handleMarkerClicked() +{ + QLegendMarker* marker = qobject_cast (sender()); + + qDebug() << "marker clicked:" << marker; + + QPieSlice* slice = qobject_cast (marker->peerObject()); + Q_ASSERT(slice); + + slice->setExploded(!slice->isExploded()); +} diff --git a/examples/newlegend/mainwidget.h b/examples/newlegend/mainwidget.h index aa40b0b..a66c55c 100644 --- a/examples/newlegend/mainwidget.h +++ b/examples/newlegend/mainwidget.h @@ -50,6 +50,8 @@ public slots: void toggleAttached(); void addSlice(); void removeSlice(); + void connectMarkers(); + void disconnectMarkers(); void setLegendAlignment(); @@ -60,6 +62,8 @@ public slots: void updateLegendLayout(); + void handleMarkerClicked(); + private: diff --git a/src/legend/legend.pri b/src/legend/legend.pri index 28c7c7c..77813ba 100644 --- a/src/legend/legend.pri +++ b/src/legend/legend.pri @@ -6,14 +6,16 @@ SOURCES += \ $$PWD/legendmarker.cpp \ $$PWD/legendlayout.cpp \ $$PWD/qlegendmarker.cpp \ - $$PWD/qpielegendmarker.cpp + $$PWD/qpielegendmarker.cpp \ + $$PWD/legendmarkeritem.cpp PRIVATE_HEADERS += \ $$PWD/legendmarker_p.h \ $$PWD/legendscroller_p.h \ $$PWD/qlegend_p.h \ $$PWD/legendlayout_p.h \ - $$PWD/qlegendmarker_p.h + $$PWD/qlegendmarker_p.h \ + $$PWD/legendmarkeritem_p.h PUBLIC_HEADERS += \ diff --git a/src/legend/legendmarkeritem.cpp b/src/legend/legendmarkeritem.cpp new file mode 100644 index 0000000..14f2f6d --- /dev/null +++ b/src/legend/legendmarkeritem.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** + ** + ** 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$ + ** + ****************************************************************************/ + +#include "legendmarkeritem_p.h" +#include "qxyseries.h" +#include "qxyseries_p.h" +#include "qlegend.h" +#include "qabstractbarseries.h" +#include "qpieseries.h" +#include "qpieslice.h" +#include "qbarset.h" +#include "qbarset_p.h" +#include "qareaseries.h" +#include "qareaseries_p.h" +#include +#include +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +LegendMarkerItem::LegendMarkerItem(QAbstractSeries *series, QGraphicsObject *parent) : + QGraphicsObject(parent), + m_series(series), + m_markerRect(0,0,10.0,10.0), + m_boundingRect(0,0,0,0), + m_textItem(new QGraphicsSimpleTextItem(this)), + m_rectItem(new QGraphicsRectItem(this)), + m_margin(4), + m_space(4) +{ + //setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton); + m_rectItem->setRect(m_markerRect); +} + +void LegendMarkerItem::setPen(const QPen &pen) +{ + m_rectItem->setPen(pen); +} + +QPen LegendMarkerItem::pen() const +{ + return m_rectItem->pen(); +} + +void LegendMarkerItem::setBrush(const QBrush &brush) +{ + m_rectItem->setBrush(brush); +} + +QBrush LegendMarkerItem::brush() const +{ + return m_rectItem->brush(); +} + +void LegendMarkerItem::setFont(const QFont &font) +{ + m_textItem->setFont(font); + QFontMetrics fn(font); + m_markerRect = QRectF(0,0,fn.height()/2,fn.height()/2); + updateGeometry(); +} + +QFont LegendMarkerItem::font() const +{ + return m_textItem->font(); +} + +void LegendMarkerItem::setLabel(const QString label) +{ + m_text = label; + updateGeometry(); +} + +QString LegendMarkerItem::label() const +{ + return m_text; +} + +QRectF LegendMarkerItem::boundingRect() const +{ + return m_boundingRect; +} + +void LegendMarkerItem::setLabelBrush(const QBrush &brush) +{ + m_textItem->setBrush(brush); +} + +QBrush LegendMarkerItem::labelBrush() const +{ + return m_textItem->brush(); +} + + +void LegendMarkerItem::setGeometry(const QRectF& rect) +{ + QFontMetrics fn (font()); + + int width = rect.width(); + qreal x = m_margin + m_markerRect.width() + m_space + m_margin; + qreal y = qMax(m_markerRect.height()+2*m_margin,fn.height()+2*m_margin); + + if (fn.boundingRect(m_text).width() + x > width) + { + QString string = m_text + "..."; + while(fn.boundingRect(string).width() + x > width && string.length() > 3) + string.remove(string.length() - 4, 1); + m_textItem->setText(string); + } + else + m_textItem->setText(m_text); + + const QRectF& textRect = m_textItem->boundingRect(); + + + m_textItem->setPos(x-m_margin,y/2 - textRect.height()/2); + m_rectItem->setRect(m_markerRect); + m_rectItem->setPos(m_margin,y/2 - m_markerRect.height()/2); + + prepareGeometryChange(); + m_boundingRect = QRectF(0,0,x+textRect.width()+m_margin,y); +} + +void LegendMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option) + Q_UNUSED(widget) + Q_UNUSED(painter) +} + +QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const +{ + Q_UNUSED(constraint) + + QFontMetrics fn(m_textItem->font()); + QSizeF sh; + + switch (which) { + case Qt::MinimumSize: + sh = QSizeF(fn.boundingRect("...").width() + 2*m_margin + m_space +m_markerRect.width(),qMax(m_markerRect.height()+2*m_margin,fn.height()+2*m_margin)); + break; + case Qt::PreferredSize: + sh = QSizeF(fn.boundingRect(m_text).width() + 2*m_margin + m_space +m_markerRect.width(),qMax(m_markerRect.height()+2*m_margin,fn.height()+2*m_margin)); + break; + default: + break; + } + + return sh; +} + +void LegendMarkerItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + qDebug() << "LegendMarkerItem::mousePressEvent"; + QGraphicsObject::mousePressEvent(event); + //TODO: selected signal removed for now +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +AreaLegendMarkerItem::AreaLegendMarkerItem(QAreaSeries *series,QLegend *legend) : LegendMarkerItem(series,legend), +m_series(series) +{ + //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected())); +// QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated())); +// QObject::connect(series, SIGNAL(nameChanged()), this, SLOT(updated())); + updated(); +} + +void AreaLegendMarkerItem::updated() +{ + setBrush(m_series->brush()); + setLabel(m_series->name()); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +BarLegendMarkerItem::BarLegendMarkerItem(QAbstractBarSeries *barseries,QBarSet *barset, QLegend *legend) : LegendMarkerItem(barseries,legend), +m_barset(barset) +{ + //QObject::connect(this, SIGNAL(selected()),barset->d_ptr.data(), SIGNAL(selected())); +// QObject::connect(barset->d_ptr.data(), SIGNAL(updatedBars()), this, SLOT(updated())); + updated(); +} + +void BarLegendMarkerItem::updated() +{ + setBrush(m_barset->brush()); + setLabel(m_barset->label()); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +PieLegendMarkerItem::PieLegendMarkerItem(QPieSeries* series,QPieSlice *pieslice, QLegend *legend) : LegendMarkerItem(series,legend), +m_pieslice(pieslice) +{ +// QObject::connect(pieslice, SIGNAL(labelChanged()), this, SLOT(updated())); +// QObject::connect(pieslice, SIGNAL(brushChanged()), this, SLOT(updated())); + updated(); +} + +void PieLegendMarkerItem::updated() +{ + setBrush(m_pieslice->brush()); + setLabel(m_pieslice->label()); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +XYLegendMarkerItem::XYLegendMarkerItem(QXYSeries *series, QLegend *legend) : LegendMarkerItem(series,legend), +m_series(series) +{ + //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected())); +// QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated())); +// QObject::connect(series, SIGNAL(nameChanged()), this, SLOT(updated())); + updated(); +} + +void XYLegendMarkerItem::updated() +{ + setLabel(m_series->name()); + + if(m_series->type()== QAbstractSeries::SeriesTypeScatter) + { + setBrush(m_series->brush()); + + } + else { + setBrush(QBrush(m_series->pen().color())); + } +} + +#include "moc_legendmarkeritem_p.cpp" + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/legend/legendmarkeritem_p.h b/src/legend/legendmarkeritem_p.h new file mode 100644 index 0000000..37bfdb7 --- /dev/null +++ b/src/legend/legendmarkeritem_p.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the QtCommercial Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef LEGENDMARKERITEM_P_H +#define LEGENDMARKERITEM_P_H + +#include "qchartglobal.h" +#include +#include +#include +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QAbstractSeries; +class QAreaSeries; +class QXYSeries; +class QBarSet; +class QAbstractBarSeries; +class QPieSlice; +class QLegend; +class QPieSeries; + +class LegendMarkerItem : public QGraphicsObject, public QGraphicsLayoutItem +{ + Q_OBJECT + Q_INTERFACES(QGraphicsLayoutItem) +public: + explicit LegendMarkerItem(QAbstractSeries *m_series, QGraphicsObject *parent); + + void setPen(const QPen &pen); + QPen pen() const; + + void setBrush(const QBrush &brush); + QBrush brush() const; + + void setFont(const QFont &font); + QFont font() const; + + void setLabel(const QString label); + QString label() const; + + void setLabelBrush(const QBrush &brush); + QBrush labelBrush() const; + + QAbstractSeries *series() const { return m_series;} + + void setGeometry(const QRectF& rect); + + QRectF boundingRect() const; + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + + QSizeF sizeHint (Qt::SizeHint which, const QSizeF& constraint) const; + +protected: + // From QGraphicsObject + void mousePressEvent(QGraphicsSceneMouseEvent *event); + +//public Q_SLOTS: + //virtual void updated() = 0; + +protected: + QAbstractSeries *m_series; + QRectF m_markerRect; + QRectF m_boundingRect; +// QLegend* m_legend; + QGraphicsSimpleTextItem *m_textItem; + QGraphicsRectItem *m_rectItem; + qreal m_margin; + qreal m_space; + QString m_text; + +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class XYLegendMarkerItem : public LegendMarkerItem +{ +public: + XYLegendMarkerItem(QXYSeries *series, QLegend *legend); +protected: + void updated(); +private: + QXYSeries *m_series; +}; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class AreaLegendMarkerItem : public LegendMarkerItem +{ +public: + AreaLegendMarkerItem(QAreaSeries *series, QLegend *legend); +protected: + void updated(); +private: + QAreaSeries *m_series; +}; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class BarLegendMarkerItem : public LegendMarkerItem +{ +public: + BarLegendMarkerItem(QAbstractBarSeries *barseries, QBarSet *barset,QLegend *legend); +protected: + void updated(); +private: + QBarSet *m_barset; +}; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class PieLegendMarkerItem : public LegendMarkerItem +{ +public: + PieLegendMarkerItem(QPieSeries *pieSeries, QPieSlice *pieslice, QLegend *legend); +protected: + void updated(); +private: + QPieSlice *m_pieslice; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // LEGENDMARKERITEM_P_H diff --git a/src/legend/qlegend.cpp b/src/legend/qlegend.cpp index ad45a61..9588004 100644 --- a/src/legend/qlegend.cpp +++ b/src/legend/qlegend.cpp @@ -467,6 +467,8 @@ void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain) { Q_UNUSED(domain) + qDebug() << "QLegendPrivate::handleSeriesAdded"; + // New markers ---> QList newMarkers = series->d_ptr->createLegendMarkers(q_ptr); foreach (QLegendMarker* marker, newMarkers) { @@ -474,7 +476,8 @@ void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain) marker->setLabelBrush(m_labelBrush); marker->setVisible(series->isVisible()); // TODO: QLegendMarker has QGraphicsItem vs QLegendMarker is QGraphicsItem -// m_items->addToGroup(marker); +// TODO: possible hazard. What if marker is deleted and group still has pointer? +// m_items->addToGroup(marker->d_ptr.data()); m_legendMarkers << marker; } diff --git a/src/legend/qlegendmarker.cpp b/src/legend/qlegendmarker.cpp index a7057d3..7b73043 100644 --- a/src/legend/qlegendmarker.cpp +++ b/src/legend/qlegendmarker.cpp @@ -20,6 +20,7 @@ #include "qlegendmarker.h" #include "qlegendmarker_p.h" +#include "legendmarkeritem_p.h" #include #include @@ -106,7 +107,7 @@ QLegendMarkerPrivate::QLegendMarkerPrivate(QAbstractSeries *series, QLegendMarke q_ptr(q), m_series(series) { - + m_item = new LegendMarkerItem(m_series,this); } void QLegendMarkerPrivate::setGeometry(const QRectF& rect) @@ -174,6 +175,7 @@ QSizeF QLegendMarkerPrivate::sizeHint(Qt::SizeHint which, const QSizeF& constrai void QLegendMarkerPrivate::mousePressEvent(QGraphicsSceneMouseEvent *event) { + qDebug() << "QLegendMarkerPrivate::mousePressEvent" << event; QGraphicsObject::mousePressEvent(event); //TODO: selected signal removed for now } diff --git a/src/legend/qlegendmarker_p.h b/src/legend/qlegendmarker_p.h index 3046b8e..04c788f 100644 --- a/src/legend/qlegendmarker_p.h +++ b/src/legend/qlegendmarker_p.h @@ -50,6 +50,7 @@ class QLegend; class QPieSeries; class QLegendMarker; +class LegendMarkerItem; class QLegendMarkerPrivate : public QGraphicsObject, public QGraphicsLayoutItem { @@ -91,6 +92,8 @@ public Q_SLOTS: private: QLegendMarker *q_ptr; + LegendMarkerItem *m_item; + /* QLegend* m_legend; */ diff --git a/src/legend/qpielegendmarker.cpp b/src/legend/qpielegendmarker.cpp index 535bbb3..fe32a43 100644 --- a/src/legend/qpielegendmarker.cpp +++ b/src/legend/qpielegendmarker.cpp @@ -32,6 +32,11 @@ QPieLegendMarker::QPieLegendMarker(QPieSeries* series, QPieSlice* slice, QObject updated(); } +QPieSlice* QPieLegendMarker::peerObject() +{ + return m_slice; +} + void QPieLegendMarker::updated() { // TODO: to PIMPL. diff --git a/src/legend/qpielegendmarker.h b/src/legend/qpielegendmarker.h index c5f2cae..1d56e8e 100644 --- a/src/legend/qpielegendmarker.h +++ b/src/legend/qpielegendmarker.h @@ -34,9 +34,9 @@ class QTCOMMERCIALCHART_EXPORT QPieLegendMarker : public QLegendMarker public: explicit QPieLegendMarker(QPieSeries* series, QPieSlice* slice, QObject *parent = 0); - virtual QPieSlice* peerObject() { return m_slice; } + virtual QPieSlice* peerObject(); -// TODO: to pimp. +// TODO: to pimpl. void updated(); //Q_SIGNALS: @@ -48,6 +48,7 @@ private: // QScopedPointer d_ptr; Q_DISABLE_COPY(QPieLegendMarker) +// TODO: PIMPL QPieSlice* m_slice; }; diff --git a/src/piechart/qpieseries.cpp b/src/piechart/qpieseries.cpp index a8fc5a1..9a03a47 100644 --- a/src/piechart/qpieseries.cpp +++ b/src/piechart/qpieseries.cpp @@ -865,10 +865,11 @@ QList QPieSeriesPrivate::createLegendMarker(QLegend *legend) QList QPieSeriesPrivate::createLegendMarkers(QLegend* legend) { + Q_UNUSED(legend); Q_Q(QPieSeries); QList markers; foreach(QPieSlice* slice, q->slices()) { - QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend); + QPieLegendMarker* marker = new QPieLegendMarker(q,slice); markers << marker; } return markers;