##// END OF EJS Templates
Initial revision of boxplot series handling...
Mika Salmela -
r2461:95a0f898019d
parent child
Show More
@@ -0,0 +1,16
1 INCLUDEPATH += $$PWD
2 DEPENDPATH += $$PWD
3
4 SOURCES += \
5 $$PWD/boxplotchartitem.cpp \
6 $$PWD/qboxplotseries.cpp \
7 $$PWD/boxwhiskers.cpp
8
9 PRIVATE_HEADERS += \
10 $$PWD/boxplotchartitem_p.h \
11 $$PWD/qboxplotseries_p.h \
12 $$PWD/boxwhiskers_p.h \
13 $$PWD/boxwhiskersdata_p.h
14
15 PUBLIC_HEADERS += \
16 $$PWD/qboxplotseries.h
@@ -0,0 +1,196
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 #include "boxplotchartitem_p.h"
22 #include "qboxplotseries_p.h"
23 #include "bar_p.h"
24 #include "qbarset_p.h"
25 #include "qabstractbarseries_p.h"
26 #include "qbarset.h"
27 #include "boxwhiskers_p.h"
28 #include <QPainter>
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
32 BoxPlotChartItem::BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem* item) :
33 ChartItem(series->d_func(), item),
34 m_series(series),
35 m_animation(0),
36 m_animate(0)
37 {
38 connect(series->d_func(), SIGNAL(restructuredBars()), this, SLOT(handleDataStructureChanged()));
39 connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutChanged()));
40 connect(series->d_func(), SIGNAL(updatedBars()), this, SLOT(handleUpdatedBars()));
41 connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdatedBars()));
42 // QBoxPlotSeriesPrivate calls handleDataStructureChanged(), don't do it here
43 setZValue(ChartPresenter::BoxPlotSeriesZValue);
44
45 m_barSets = m_series->barSets();
46 }
47
48 BoxPlotChartItem::~BoxPlotChartItem()
49 {
50 qDebug() << "BoxPlotChartItem::~BoxPlotChartItem() " << m_seriesIndex;
51 }
52
53 void BoxPlotChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
54 {
55 Q_UNUSED(painter);
56 Q_UNUSED(option);
57 Q_UNUSED(widget);
58
59 //painter->setClipRect(QRectF(QPointF(0,0),domain()->size()));
60
61 //qDebug() << "ALERT EMPTY: BoxPlotChartItem::paint";
62 }
63
64 void BoxPlotChartItem::setAnimation(BoxPlotAnimation *animation)
65 {
66 //qDebug() << "BoxPlotChartItem::setAnimation :" << animation;
67
68 m_animation = animation;
69 if (m_animation) {
70 foreach (BoxWhiskers *item, m_boxTable.values()) {
71 m_animation->addBox(item);
72 }
73 handleDomainUpdated();
74 }
75 }
76
77 void BoxPlotChartItem::handleDataStructureChanged()
78 {
79 //qDebug() << "BoxPlotChartItem::handleDataStructureChanged()";
80 int setCount = m_series->count();
81
82 for (int s = 0; s < setCount; s++) {
83 QBarSet *set = m_series->d_func()->barsetAt(s);
84
85 BoxWhiskers *boxWhiskersItem = m_boxTable.value(set);
86 if (boxWhiskersItem == 0) {
87 // Item is not yet created, make a box and add it to hash table
88 boxWhiskersItem = new BoxWhiskers(domain(), this);
89 m_boxTable.insert(set, boxWhiskersItem);
90
91 boxWhiskersItem->setBrush(m_series->brush());
92 boxWhiskersItem->setPen(m_series->pen());
93 }
94 updateBoxGeometry(boxWhiskersItem, s);
95
96 boxWhiskersItem->updateGeometry();
97
98 if (m_animation)
99 m_animation->addBox(boxWhiskersItem);
100 }
101
102 //
103 handleDomainUpdated();
104 }
105
106 void BoxPlotChartItem::handleUpdatedBars()
107 {
108 //qDebug() << "BoxPlotChartItem::handleUpdatedBars()";
109
110 foreach (BoxWhiskers *item, m_boxTable.values()) {
111 item->setBrush(m_series->brush());
112 item->setPen(m_series->pen());
113 }
114 }
115
116 void BoxPlotChartItem::handleDomainUpdated()
117 {
118 //qDebug() << "BoxPlotChartItem::handleDomainUpdated() domain()->size() = " << domain()->size();
119
120 if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
121 return;
122
123 // Set my bounding rect to same as domain size
124 m_boundingRect.setRect(0.0, 0.0, domain()->size().width(), domain()->size().height());
125
126 foreach (BoxWhiskers *item, m_boxTable.values()) {
127 // Update the domain size for each BoxWhisker item
128 item->setDomainSize(domain()->size());
129
130 // If the animation is set, start the animation for each BoxWhisker item
131 if (m_animation) {
132 presenter()->startAnimation(m_animation->boxAnimation(item));
133 }
134 }
135 }
136
137 void BoxPlotChartItem::handleLayoutChanged()
138 {
139 //qDebug() << "BoxPlotChartItem::handleLayoutChanged() domain()->size() = " << domain()->size();
140 //foreach (BoxWhiskers *boxWhiskersItem, m_boxes)
141 // boxWhiskersItem->updateGeometry();
142 }
143
144 void BoxPlotChartItem::handleSeriesRemove(QAbstractSeries *series)
145 {
146 qDebug() << "BoxPlotChartItem::handleSeriesRemove " << m_seriesIndex;
147 QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
148 if (m_series == removedSeries) {
149 return;
150 }
151
152 m_seriesCount = m_seriesCount - 1;
153
154 handleDataStructureChanged();
155 }
156
157 QRectF BoxPlotChartItem::boundingRect() const
158 {
159 return m_boundingRect;
160 }
161
162 void BoxPlotChartItem::initializeLayout()
163 {
164 qDebug() << "ALERT EMPTY: BoxPlotChartItem::initializeLayout";
165 }
166
167 QVector<QRectF> BoxPlotChartItem::calculateLayout()
168 {
169 return QVector<QRectF>();
170 }
171
172 void BoxPlotChartItem::updateBoxGeometry(BoxWhiskers *box, int index)
173 {
174 QBarSet *set = m_series->d_func()->barsetAt(index);
175 //QBarSet *set = m_barSets.at(index);
176 BoxWhiskersData &data = box->m_data;
177 data.m_lowerExtreme = set->at(0);
178 data.m_lowerQuartile = set->at(1);
179 data.m_median = set->at(2);
180 data.m_upperQuartile = set->at(3);
181 data.m_upperExtreme = set->at(4);
182 data.m_index = index;
183 data.m_boxItems = m_series->count();
184
185 data.m_maxX = domain()->maxX();
186 data.m_minX = domain()->minX();
187 data.m_maxY = domain()->maxY();
188 data.m_minY = domain()->minY();
189
190 data.m_seriesIndex = m_seriesIndex;
191 data.m_seriesCount = m_seriesCount;
192 }
193
194 #include "moc_boxplotchartitem_p.cpp"
195
196 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,87
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 // W A R N I N G
22 // -------------
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
27 //
28 // We mean it.
29
30
31 #ifndef BOXPLOTCHARTITEM_H
32 #define BOXPLOTCHARTITEM_H
33
34 #include "boxwhiskers_p.h"
35 #include "qboxplotseries.h"
36 #include "chartitem_p.h"
37 #include "boxplotanimation_p.h"
38 #include <QGraphicsItem>
39
40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41
42 class BoxPlotSeriesPrivate;
43
44 class BoxPlotChartItem : public ChartItem
45 {
46 Q_OBJECT
47 public:
48 BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem* item =0);
49 ~BoxPlotChartItem();
50
51 void setAnimation(BoxPlotAnimation *animation);
52
53 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
54 QRectF boundingRect() const;
55
56 public Q_SLOTS:
57 void handleDataStructureChanged();
58 void handleDomainUpdated();
59 void handleLayoutChanged();
60 void handleUpdatedBars();
61 void handleSeriesRemove(QAbstractSeries *series);
62
63 private:
64 virtual QVector<QRectF> calculateLayout();
65 void initializeLayout();
66 void updateBoxGeometry(BoxWhiskers *box, int index);
67
68 protected:
69 friend class QBoxPlotSeriesPrivate;
70 QBoxPlotSeries *m_series; // Not owned.
71 QList<BoxWhiskers *> m_boxes;
72 QHash<QBarSet *, BoxWhiskers *> m_boxTable;
73 QList<QBarSet *> m_barSets;
74 int m_seriesIndex;
75 int m_seriesCount;
76
77 BoxPlotAnimation *m_animation;
78 bool m_animate;
79
80 QRectF m_boundingRect;
81
82 //QList<BoxPlotAnimation *> m_animations;
83 };
84
85 QTCOMMERCIALCHART_END_NAMESPACE
86
87 #endif // BOXPLOTCHARTITEM_H
@@ -0,0 +1,193
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 #include "boxwhiskers_p.h"
22 #include <QPainter>
23 #include <QDebug>
24 #include <QWidget>
25
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27
28 BoxWhiskers::BoxWhiskers(AbstractDomain *domain, QGraphicsObject *parent) :
29 QGraphicsObject(parent),
30 m_domain(domain)
31 {
32 }
33
34 BoxWhiskers::~BoxWhiskers()
35 {
36 //qDebug() << "BoxWhiskers::~BoxWhiskers()";
37 }
38
39 void BoxWhiskers::mousePressEvent(QGraphicsSceneMouseEvent *event)
40 {
41 Q_UNUSED(event)
42
43 qDebug() << "BoxWhiskers::mousePressEvent";
44 }
45
46 void BoxWhiskers::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
47 {
48 Q_UNUSED(event)
49
50 qDebug() << "BoxWhiskers::hoverEnterEvent";
51 }
52
53 void BoxWhiskers::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
54 {
55 Q_UNUSED(event)
56
57 qDebug() << "BoxWhiskers::hoverLeaveEvent";
58 }
59
60 void BoxWhiskers::setBrush(const QBrush &brush)
61 {
62 m_brush = brush;
63 }
64
65 void BoxWhiskers::setPen(const QPen &pen)
66 {
67 m_pen = pen;
68 }
69
70 void BoxWhiskers::setLayout(const BoxWhiskersData &data)
71 {
72 m_data = data;
73 // if (m_data.m_index == 1)
74 // qDebug() << "BoxWhiskers::setLayout";
75 updateGeometry();
76 //update(0.0, 0.0, m_data.m_domainSize.width(), m_data.m_domainSize.height());
77 update();
78 }
79
80
81 QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
82 {
83 //Q_UNUSED(which)
84 Q_UNUSED(constraint)
85
86 qDebug() << "BoxWhiskers::sizeHint, which = " << which;
87
88 return QSizeF();
89 }
90
91 void BoxWhiskers::setGeometry(const QRectF &rect) // TODO: Unused?
92 {
93 Q_UNUSED(rect)
94
95 qDebug() << "BoxWhiskers::setGeometry";
96 }
97
98 void BoxWhiskers::setDomainSize(const QSizeF &size)
99 {
100 m_domainSize = size;
101
102 updateBoundingRect();
103 }
104
105 QRectF BoxWhiskers::boundingRect() const
106 {
107 return m_boundingRect;
108 }
109
110 void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
111 {
112 Q_UNUSED(option)
113 Q_UNUSED(widget)
114 //Q_UNUSED(painter)
115
116 //painter->save();
117 //painter->setClipRect(parentItem()->boundingRect());
118 painter->setPen(m_pen);
119 painter->setBrush(m_brush);
120 qreal spanY = m_data.m_maxY - m_data.m_minY;
121 //painter->setClipRect(parentItem()->boundingRect());
122 painter->scale(m_domainSize.width() / m_data.m_boxItems, m_domainSize.height() / spanY);
123 painter->drawPath(m_boxPath);
124 //painter->restore();
125 }
126
127 void BoxWhiskers::updateGeometry()
128 {
129 prepareGeometryChange();
130
131 QPainterPath path;
132
133 // TODO: Dirty hack
134 if (m_data.m_seriesCount == 0) m_data.m_seriesCount = 1;
135
136 qreal columnWidth = 1.0 / m_data.m_seriesCount;
137 qreal left = 0.25 * columnWidth + columnWidth * m_data.m_seriesIndex;
138 qreal right = 0.75 * columnWidth + columnWidth * m_data.m_seriesIndex;
139 qreal middle = 0.5 * columnWidth + columnWidth * m_data.m_seriesIndex;
140
141 //whisker = 0.35 0.75
142
143 // Upper whisker
144 path.moveTo(left + m_data.m_index, m_data.m_maxY - m_data.m_upperExtreme);
145 path.lineTo(right + m_data.m_index, m_data.m_maxY - m_data.m_upperExtreme);
146 path.moveTo(middle + m_data.m_index, m_data.m_maxY - m_data.m_upperExtreme);
147 path.lineTo(middle + m_data.m_index, m_data.m_maxY - m_data.m_upperQuartile);
148 path.closeSubpath();
149
150 // Middle Box
151 path.addRect(left + m_data.m_index, m_data.m_maxY - m_data.m_upperQuartile,
152 0.5 * columnWidth, m_data.m_upperQuartile - m_data.m_lowerQuartile);
153
154 // Median/mean line
155 path.moveTo(left + m_data.m_index, m_data.m_maxY - m_data.m_median);
156 path.lineTo(right + m_data.m_index, m_data.m_maxY - m_data.m_median);
157
158 // Lower whisker
159 path.moveTo(left + m_data.m_index, m_data.m_maxY - m_data.m_lowerExtreme);
160 path.lineTo(right + m_data.m_index, m_data.m_maxY - m_data.m_lowerExtreme);
161 path.moveTo(middle + m_data.m_index, m_data.m_maxY - m_data.m_lowerExtreme);
162 path.lineTo(middle + m_data.m_index, m_data.m_maxY - m_data.m_lowerQuartile);
163 path.closeSubpath();
164
165 m_boxPath = path;
166
167 updateBoundingRect();
168
169 // qreal scaleY = m_domainSize.height() / (m_data.m_maxY - m_data.m_minY);
170 // qreal scaleX = m_domainSize.width() / m_data.m_boxItems;
171 // QRectF br = path.boundingRect();
172 // m_boundingRect = QRectF( br.x() * scaleX, br.y() * scaleY, br.width() * scaleX, br.height() * scaleY);
173
174 if (m_data.m_index == 5) {
175 //qDebug() << "myValue = " << myValue;
176 //qDebug() << "m_data.m_upperExtreme" << m_data.m_upperExtreme;
177 //qDebug() << "m_boundingRect = " << m_boundingRect;
178 // qDebug() << "x = " << m_boundingRect.x() << ", y = " << m_boundingRect.y() << ", width = "
179 // << m_boundingRect.width() << ", height = " << m_boundingRect.height();
180 }
181 }
182
183 void BoxWhiskers::updateBoundingRect()
184 {
185 qreal scaleY = m_domainSize.height() / (m_data.m_maxY - m_data.m_minY);
186 qreal scaleX = m_domainSize.width() / m_data.m_boxItems;
187 QRectF br = m_boxPath.boundingRect();
188 m_boundingRect = QRectF( br.x() * scaleX, br.y() * scaleY, br.width() * scaleX, br.height() * scaleY);
189 }
190
191 #include "moc_boxwhiskers_p.cpp"
192
193 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,96
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 // W A R N I N G
22 // -------------
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
27 //
28 // We mean it.
29
30 #ifndef BOXWHISKERS_H
31 #define BOXWHISKERS_H
32
33 #include "boxwhiskersdata_p.h"
34 #include "qchartglobal.h"
35 #include "qbarset.h"
36 #include "abstractdomain_p.h"
37 #include <QGraphicsRectItem>
38 #include <QGraphicsLineItem>
39 #include <QGraphicsLayoutItem>
40 #include <QPainterPath>
41
42 QTCOMMERCIALCHART_BEGIN_NAMESPACE
43
44 class QBarSet;
45
46 class BoxWhiskers : public QGraphicsObject/*, public QGraphicsLayoutItem*/
47 {
48 Q_OBJECT
49 //Q_INTERFACES(QGraphicsLayoutItem)
50 public:
51 BoxWhiskers(AbstractDomain *domain, QGraphicsObject *parent);
52 ~BoxWhiskers();
53
54 void setBrush(const QBrush &brush);
55 void setPen(const QPen &pen);
56 void setLayout(const BoxWhiskersData &data);
57 void setDomainSize(const QSizeF &size);
58
59 void mousePressEvent(QGraphicsSceneMouseEvent *event);
60 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
61 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
62
63 QRectF boundingRect() const;
64 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
65
66 // From QGraphicsLayoutItem // TODO tarkista n�m� jollei ole QGraphicsLayoutItem
67 void updateGeometry();
68 protected:
69 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
70 void setGeometry(const QRectF &rect);
71
72 private:
73 void updateBoundingRect();
74
75 Q_SIGNALS:
76 void clicked(int index, QBarSet *barset);
77 void hovered(bool status, QBarSet *barset);
78
79 private:
80 friend class BoxPlotChartItem;
81 friend class BoxPlotAnimation;
82
83 AbstractDomain *m_domain;
84 QPainterPath m_boxPath;
85 QRectF m_boundingRect;
86 bool m_hovering;
87 bool m_validData;
88 QBrush m_brush;
89 QPen m_pen;
90 BoxWhiskersData m_data;
91 QSizeF m_domainSize;
92 };
93
94 QTCOMMERCIALCHART_END_NAMESPACE
95
96 #endif // BOXWHISKERS_H
@@ -0,0 +1,80
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 // W A R N I N G
22 // -------------
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
27 //
28 // We mean it.
29
30 #ifndef BOXWHISKERSDATA_P_H
31 #define BOXWHISKERSDATA_P_H
32
33 #include "qchartglobal.h"
34 #include <QSizeF>
35
36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37
38 class BoxWhiskersData
39 {
40 public:
41 BoxWhiskersData() :
42 m_lowerExtreme(0.0),
43 m_lowerQuartile(0.0),
44 m_median(0.0),
45 m_upperQuartile(0.0),
46 m_upperExtreme(0.0),
47 m_index(0),
48 m_boxItems(0),
49 m_maxX(0.0),
50 m_minX(0.0),
51 m_maxY(0.0),
52 m_minY(0.0),
53 m_seriesIndex(0),
54 m_seriesCount(0)
55 {
56 }
57
58 // Box related statistics
59 qreal m_lowerExtreme;
60 qreal m_lowerQuartile;
61 qreal m_median;
62 qreal m_upperQuartile;
63 qreal m_upperExtreme;
64 int m_index;
65 int m_boxItems;
66
67 // Domain boundaries, axis
68 qreal m_maxX;
69 qreal m_minX;
70 qreal m_maxY;
71 qreal m_minY;
72
73 // Serieses related data
74 int m_seriesIndex;
75 int m_seriesCount;
76 };
77
78 QTCOMMERCIALCHART_END_NAMESPACE
79
80 #endif // BOXWHISKERSDATA_P_H
@@ -0,0 +1,280
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 #include "qboxplotseries.h"
22 #include "qboxplotseries_p.h"
23 #include "qboxplotlegendmarker.h"
24 #include "boxplotchartitem_p.h"
25 #include "chartdataset_p.h"
26 #include "charttheme_p.h"
27 #include "qvalueaxis.h"
28 #include "charttheme_p.h"
29 #include "boxplotanimation_p.h"
30 #include "qchart_p.h"
31
32 #include <QDebug>
33
34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35
36 /*!
37 \class QBoxPlotSeries
38 \brief Series for creating stacked bar chart
39 \mainclass
40
41 QBoxPlotSeries represents a series of data shown as bars. The purpose of this class is to draw bars
42 as stacks, where bars in same category are stacked on top of each other.
43 QBoxPlotSeries groups the data from sets to categories, which are defined by QStringList.
44
45 See the \l {BoxPlotChart Example} {stacked bar chart example} to learn how to create a stacked bar chart.
46 \image examples_boxplotchart.png
47
48 \sa QBarSet, QPercentBarSeries, QAbstractBarSeries
49 */
50
51 /*!
52 \qmlclass BoxPlotSeries QBoxPlotSeries
53 \inherits AbstractBarSeries
54
55 The following QML shows how to create a simple stacked bar chart:
56 \snippet ../demos/qmlchart/qml/qmlchart/View7.qml 1
57 \beginfloatleft
58 \image demos_qmlchart7.png
59 \endfloat
60 \clearfloat
61 */
62
63 /*!
64 Constructs empty QBoxPlotSeries.
65 QBoxPlotSeries is QObject which is a child of a \a parent.
66 */
67 QBoxPlotSeries::QBoxPlotSeries(QObject *parent)
68 : QAbstractBarSeries(*new QBoxPlotSeriesPrivate(this), parent)
69 {
70 }
71
72 /*!
73 Destructor. Removes series from chart.
74 */
75 QBoxPlotSeries::~QBoxPlotSeries()
76 {
77 qDebug() << "QBoxPlotSeries::~QBoxPlotSeries";
78
79 Q_D(QBoxPlotSeries);
80 if (d->m_chart)
81 d->m_chart->removeSeries(this);
82 }
83
84 /*!
85 Returns QChartSeries::SeriesTypeBoxPlot.
86 */
87 QAbstractSeries::SeriesType QBoxPlotSeries::type() const
88 {
89 return QAbstractSeries::SeriesTypeBoxPlot;
90 }
91
92 void QBoxPlotSeries::setBrush(const QBrush &brush)
93 {
94 Q_D(QBoxPlotSeries);
95
96 if (d->m_brush != brush) {
97 d->m_brush = brush;
98 emit d->updated();
99 }
100 }
101
102 QBrush QBoxPlotSeries::brush() const
103 {
104 Q_D(const QBoxPlotSeries);
105
106 return d->m_brush;
107 }
108
109 void QBoxPlotSeries::setPen(const QPen &pen)
110 {
111 Q_D(QBoxPlotSeries);
112
113 if (d->m_pen != pen) {
114 d->m_pen = pen;
115 emit d->updated();
116 }
117 }
118
119 QPen QBoxPlotSeries::pen() const
120 {
121 Q_D(const QBoxPlotSeries);
122
123 return d->m_pen;
124 }
125
126 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
127
128 QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q)
129 : QAbstractBarSeriesPrivate(q),
130 m_pen(QPen(Qt::NoPen)),
131 m_brush(QBrush(Qt::NoBrush))
132 {
133 }
134
135 QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()
136 {
137 qDebug() << "QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()";
138 disconnect(this, 0, 0, 0);
139 }
140
141 void QBoxPlotSeriesPrivate::initializeDomain()
142 {
143 qreal minX(domain()->minX());
144 qreal minY(domain()->minY());
145 qreal maxX(domain()->maxX());
146 qreal maxY(domain()->maxY());
147
148 qreal x = categoryCount();
149 minX = qMin(minX, - (qreal)0.5);
150 minY = qMin(minY, bottom());
151 maxX = qMax(maxX, x - (qreal)0.5);
152 //maxY = qMax(maxY, top());
153 maxY = qMax(maxY, max());
154
155 domain()->setRange(minX, maxX, minY, maxY);
156 }
157
158 void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
159 {
160 Q_Q(QBoxPlotSeries);
161
162 BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q,parent);
163 m_item.reset(boxPlot);
164 QAbstractSeriesPrivate::initializeGraphics(parent);
165
166 if (m_chart) {
167 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesChange(QAbstractSeries*)) );
168 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SLOT(handleSeriesRemove(QAbstractSeries*)) );
169
170 QList<QAbstractSeries *> serieses = m_chart->series();
171 boxPlot->m_seriesCount = serieses.count();
172
173 // Tries to find this series from the Chart's list of serieses and deduce the index
174 int index = 0;
175 foreach (QAbstractSeries *s, serieses) {
176 if (q == static_cast<QBoxPlotSeries *>(s)) {
177 boxPlot->m_seriesIndex = index;
178 m_index = index;
179 }
180 index++;
181 }
182 }
183
184 // Make BoxPlotChartItem to instantiate box & whisker items
185 boxPlot->handleDataStructureChanged();
186 }
187
188 void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
189 {
190 Q_Q(QBoxPlotSeries);
191
192 const QList<QGradient> gradients = theme->seriesGradients();
193
194 if (forced || m_brush == QBrush(Qt::NoBrush)) {
195 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.1);
196 q->setBrush(brushColor);
197 }
198
199 if (forced || m_pen == QPen(Qt::NoPen)) {
200 QPen pen;
201 pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 1.0));
202 pen.setWidthF(1.0);
203 pen.setCosmetic(true);
204 q->setPen(pen);
205 }
206 }
207
208 void QBoxPlotSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
209 {
210 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
211 Q_ASSERT(item);
212 if (options.testFlag(QChart::SeriesAnimations)) {
213 item->setAnimation(new BoxPlotAnimation(item));
214 }else{
215 item->setAnimation((BoxPlotAnimation *)0);
216 }
217 QAbstractSeriesPrivate::initializeAnimations(options);
218 }
219
220 QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend)
221 {
222 Q_Q(QBoxPlotSeries);
223 QList<QLegendMarker*> list;
224 return list << new QBoxPlotLegendMarker(q, legend);
225 }
226
227 void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
228 {
229 qDebug() << "QBoxPlotSeriesPrivate::handleSeriesRemove";
230 Q_Q(QBoxPlotSeries);
231
232 QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
233 QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
234
235 // Test if series removed is me, then don't do anything
236 if (q != removedSeries) {
237 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
238 if (item) {
239 item->m_seriesCount = item->m_seriesCount - 1;
240 if (removedSeries->d_func()->m_index < m_index) {
241 m_index--;
242 item->m_seriesIndex = m_index;
243 }
244
245 item->handleDataStructureChanged();
246 }
247 }
248 }
249
250 void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
251 {
252 Q_UNUSED(series);
253
254 Q_Q(QBoxPlotSeries);
255
256 BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.data());
257
258 if (m_chart) {
259 QList<QAbstractSeries *> serieses = m_chart->series();
260 boxPlot->m_seriesCount = serieses.count();
261
262 // Tries to find this series from the Chart's list of serieses and deduce the index
263 int index = 0;
264 foreach (QAbstractSeries *s, serieses) {
265 if (q == static_cast<QBoxPlotSeries *>(s)) {
266 boxPlot->m_seriesIndex = index;
267 m_index = index;
268 }
269 index++;
270 }
271 }
272
273 boxPlot->handleDataStructureChanged();
274 }
275
276 #include "moc_qboxplotseries.cpp"
277 #include "moc_qboxplotseries_p.cpp"
278
279 QTCOMMERCIALCHART_END_NAMESPACE
280
@@ -0,0 +1,57
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 #ifndef QBOXPLOTSERIES_H
22 #define QBOXPLOTSERIES_H
23
24 #include <qchartglobal.h>
25 #include <qabstractbarseries.h>
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
29 class QBoxPlotSeriesPrivate;
30 //class QBarSet;
31
32 class QTCOMMERCIALCHART_EXPORT QBoxPlotSeries : public QAbstractBarSeries
33 {
34 Q_OBJECT
35 public:
36 explicit QBoxPlotSeries(QObject *parent = 0);
37 ~QBoxPlotSeries();
38
39 QAbstractSeries::SeriesType type() const;
40
41 void mika();
42
43 void setBrush(const QBrush &brush);
44 QBrush brush() const;
45 void setPen(const QPen &pen);
46 QPen pen() const;
47
48 private:
49 Q_DECLARE_PRIVATE(QBoxPlotSeries)
50 Q_DISABLE_COPY(QBoxPlotSeries)
51 friend class BoxPlotChartItem;
52 friend class QBoxPlotLegendMarkerPrivate;
53 };
54
55 QTCOMMERCIALCHART_END_NAMESPACE
56
57 #endif // QBOXPLOTSERIES_H
@@ -0,0 +1,73
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 // W A R N I N G
22 // -------------
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
27 //
28 // We mean it.
29
30 #ifndef QBOXPLOTSERIES_P_H
31 #define QBOXPLOTSERIES_P_H
32
33 #include "qboxplotseries.h"
34 #include "qabstractbarseries_p.h"
35 #include "abstractdomain_p.h"
36 #include "qbarset.h"
37
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39
40 class QBoxPlotSeriesPrivate : public QAbstractBarSeriesPrivate
41 {
42 Q_OBJECT
43
44 public:
45 QBoxPlotSeriesPrivate(QBoxPlotSeries *q);
46 ~QBoxPlotSeriesPrivate();
47
48 void initializeGraphics(QGraphicsItem* parent);
49 void initializeDomain();
50 void initializeAnimations(QChart::AnimationOptions options);
51 void initializeTheme(int index, ChartTheme* theme, bool forced = false);
52
53 QList<QLegendMarker*> createLegendMarkers(QLegend *legend);
54
55 Q_SIGNALS:
56 void updated();
57
58 private slots:
59 void handleSeriesChange(QAbstractSeries *series);
60 void handleSeriesRemove(QAbstractSeries *series);
61
62 protected:
63 QPen m_pen;
64 QBrush m_brush;
65 int m_index;
66
67 private:
68 Q_DECLARE_PUBLIC(QBoxPlotSeries)
69 };
70
71 QTCOMMERCIALCHART_END_NAMESPACE
72
73 #endif
@@ -75,6 +75,7 include(scatterchart/scatter.pri)
75 75 include(splinechart/splinechart.pri)
76 76 include(themes/themes.pri)
77 77 include(xychart/xychart.pri)
78 include(boxplotchart/boxplotchart.pri)
78 79
79 80 HEADERS += $$PUBLIC_HEADERS
80 81 HEADERS += $$PRIVATE_HEADERS
General Comments 0
You need to be logged in to leave comments. Login now