##// END OF EJS Templates
Changed BoxPlot to use domain for calculating geometry points....
Mika Salmela -
r2554:93cea193b2c2
parent child
Show More
@@ -1,210 +1,203
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "boxplotchartitem_p.h"
21 #include "boxplotchartitem_p.h"
22 #include "qboxplotseries_p.h"
22 #include "qboxplotseries_p.h"
23 #include "bar_p.h"
23 #include "bar_p.h"
24 #include "qboxset_p.h"
24 #include "qboxset_p.h"
25 #include "qabstractbarseries_p.h"
25 #include "qabstractbarseries_p.h"
26 #include "qboxset.h"
26 #include "qboxset.h"
27 #include "boxwhiskers_p.h"
27 #include "boxwhiskers_p.h"
28 #include <QPainter>
28 #include <QPainter>
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 BoxPlotChartItem::BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item) :
32 BoxPlotChartItem::BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item) :
33 ChartItem(series->d_func(), item),
33 ChartItem(series->d_func(), item),
34 m_series(series),
34 m_series(series),
35 m_animation(0),
35 m_animation(0),
36 m_animate(0),
36 m_animate(0)
37 m_domainMaxY(0.0),
38 m_domainMinY(0.0)
39 {
37 {
40 connect(series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), this, SLOT(handleBoxsetRemove(QList<QBoxSet *>)));
38 connect(series, SIGNAL(boxsetsRemoved(QList<QBoxSet *>)), this, SLOT(handleBoxsetRemove(QList<QBoxSet *>)));
41 connect(series->d_func(), SIGNAL(restructuredBoxes()), this, SLOT(handleDataStructureChanged()));
39 connect(series->d_func(), SIGNAL(restructuredBoxes()), this, SLOT(handleDataStructureChanged()));
42 connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutChanged()));
40 connect(series->d_func(), SIGNAL(updatedLayout()), this, SLOT(handleLayoutChanged()));
43 connect(series->d_func(), SIGNAL(updatedBoxes()), this, SLOT(handleUpdatedBars()));
41 connect(series->d_func(), SIGNAL(updatedBoxes()), this, SLOT(handleUpdatedBars()));
44 connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdatedBars()));
42 connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdatedBars()));
45 // QBoxPlotSeriesPrivate calls handleDataStructureChanged(), don't do it here
43 // QBoxPlotSeriesPrivate calls handleDataStructureChanged(), don't do it here
46 setZValue(ChartPresenter::BoxPlotSeriesZValue);
44 setZValue(ChartPresenter::BoxPlotSeriesZValue);
47 }
45 }
48
46
49 BoxPlotChartItem::~BoxPlotChartItem()
47 BoxPlotChartItem::~BoxPlotChartItem()
50 {
48 {
51 }
49 }
52
50
53 void BoxPlotChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
51 void BoxPlotChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
54 {
52 {
55 Q_UNUSED(painter);
53 Q_UNUSED(painter);
56 Q_UNUSED(option);
54 Q_UNUSED(option);
57 Q_UNUSED(widget);
55 Q_UNUSED(widget);
58 }
56 }
59
57
60 void BoxPlotChartItem::setAnimation(BoxPlotAnimation *animation)
58 void BoxPlotChartItem::setAnimation(BoxPlotAnimation *animation)
61 {
59 {
62 m_animation = animation;
60 m_animation = animation;
63 if (m_animation) {
61 if (m_animation) {
64 foreach (BoxWhiskers *item, m_boxTable.values())
62 foreach (BoxWhiskers *item, m_boxTable.values())
65 m_animation->addBox(item);
63 m_animation->addBox(item);
66 handleDomainUpdated();
64 handleDomainUpdated();
67 }
65 }
68 }
66 }
69
67
70 void BoxPlotChartItem::handleDataStructureChanged()
68 void BoxPlotChartItem::handleDataStructureChanged()
71 {
69 {
72 int setCount = m_series->count();
70 int setCount = m_series->count();
73
71
74 for (int s = 0; s < setCount; s++) {
72 for (int s = 0; s < setCount; s++) {
75 QBoxSet *set = m_series->d_func()->boxSetAt(s);
73 QBoxSet *set = m_series->d_func()->boxSetAt(s);
76
74
77 BoxWhiskers *box = m_boxTable.value(set);
75 BoxWhiskers *box = m_boxTable.value(set);
78 if (!box) {
76 if (!box) {
79 // Item is not yet created, make a box and add it to hash table
77 // Item is not yet created, make a box and add it to hash table
80 box = new BoxWhiskers(set, domain(), this);
78 box = new BoxWhiskers(set, domain(), this);
81 m_boxTable.insert(set, box);
79 m_boxTable.insert(set, box);
82 connect(box, SIGNAL(clicked(QBoxSet *)), m_series, SIGNAL(clicked(QBoxSet *)));
80 connect(box, SIGNAL(clicked(QBoxSet *)), m_series, SIGNAL(clicked(QBoxSet *)));
83 connect(box, SIGNAL(hovered(bool, QBoxSet *)), m_series, SIGNAL(hovered(bool, QBoxSet *)));
81 connect(box, SIGNAL(hovered(bool, QBoxSet *)), m_series, SIGNAL(hovered(bool, QBoxSet *)));
84 connect(box, SIGNAL(clicked(QBoxSet *)), set, SIGNAL(clicked()));
82 connect(box, SIGNAL(clicked(QBoxSet *)), set, SIGNAL(clicked()));
85 connect(box, SIGNAL(hovered(bool, QBoxSet *)), set, SIGNAL(hovered(bool)));
83 connect(box, SIGNAL(hovered(bool, QBoxSet *)), set, SIGNAL(hovered(bool)));
86
84
87 // Set the decorative issues for the newly created box
85 // Set the decorative issues for the newly created box
88 box->setBrush(m_series->brush());
86 box->setBrush(m_series->brush());
89 box->setPen(m_series->pen());
87 box->setPen(m_series->pen());
90 }
88 }
91 updateBoxGeometry(box, s);
89 updateBoxGeometry(box, s);
92
90
93 box->updateGeometry();
91 box->updateGeometry(domain());
94
92
95 if (m_animation)
93 if (m_animation)
96 m_animation->addBox(box);
94 m_animation->addBox(box);
97 }
95 }
98
96
99 handleDomainUpdated();
97 handleDomainUpdated();
100 }
98 }
101
99
102 void BoxPlotChartItem::handleUpdatedBars()
100 void BoxPlotChartItem::handleUpdatedBars()
103 {
101 {
104 foreach (BoxWhiskers *item, m_boxTable.values()) {
102 foreach (BoxWhiskers *item, m_boxTable.values()) {
105 item->setBrush(m_series->brush());
103 item->setBrush(m_series->brush());
106 item->setPen(m_series->pen());
104 item->setPen(m_series->pen());
107 }
105 }
108 // Override with QBoxSet specific settings
106 // Override with QBoxSet specific settings
109 foreach (QBoxSet *set, m_boxTable.keys()) {
107 foreach (QBoxSet *set, m_boxTable.keys()) {
110 if (set->brush().style() != Qt::NoBrush)
108 if (set->brush().style() != Qt::NoBrush)
111 m_boxTable.value(set)->setBrush(set->brush());
109 m_boxTable.value(set)->setBrush(set->brush());
112 if (set->pen().style() != Qt::NoPen)
110 if (set->pen().style() != Qt::NoPen)
113 m_boxTable.value(set)->setPen(set->pen());
111 m_boxTable.value(set)->setPen(set->pen());
114 }
112 }
115 }
113 }
116
114
117 void BoxPlotChartItem::handleBoxsetRemove(QList<QBoxSet*> barSets)
115 void BoxPlotChartItem::handleBoxsetRemove(QList<QBoxSet*> barSets)
118 {
116 {
119 foreach (QBoxSet *set, barSets) {
117 foreach (QBoxSet *set, barSets) {
120 BoxWhiskers *boxItem = m_boxTable.value(set);
118 BoxWhiskers *boxItem = m_boxTable.value(set);
121 m_boxTable.remove(set);
119 m_boxTable.remove(set);
122 delete boxItem;
120 delete boxItem;
123 }
121 }
124 }
122 }
125
123
126 void BoxPlotChartItem::handleDomainUpdated()
124 void BoxPlotChartItem::handleDomainUpdated()
127 {
125 {
128 if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
126 if ((domain()->size().width() <= 0) || (domain()->size().height() <= 0))
129 return;
127 return;
130
128
131 // Set my bounding rect to same as domain size
129 // Set my bounding rect to same as domain size. Add one pixel at the top (-1.0) and the bottom as 0.0 would
132 m_boundingRect.setRect(0.0, 0.0, domain()->size().width(), domain()->size().height());
130 // snip a bit off from the whisker at the grid line
131 m_boundingRect.setRect(0.0, -1.0, domain()->size().width(), domain()->size().height() + 1.0);
133
132
134 foreach (BoxWhiskers *item, m_boxTable.values()) {
133 foreach (BoxWhiskers *item, m_boxTable.values()) {
135 // Update the domain size for each BoxWhisker item
134 item->updateGeometry(domain());
136 item->setDomainSize(domain()->size());
137 if (domain()->minY() != m_domainMinY || domain()->maxY() != m_domainMaxY) {
138 item->updateGeometry();
139 m_domainMinY = domain()->minY();
140 m_domainMaxY = domain()->maxY();
141 }
142
135
143 // If the animation is set, start the animation for each BoxWhisker item
136 // If the animation is set, start the animation for each BoxWhisker item
144 if (m_animation)
137 if (m_animation)
145 presenter()->startAnimation(m_animation->boxAnimation(item));
138 presenter()->startAnimation(m_animation->boxAnimation(item));
146 }
139 }
147 }
140 }
148
141
149 void BoxPlotChartItem::handleLayoutChanged()
142 void BoxPlotChartItem::handleLayoutChanged()
150 {
143 {
151 foreach (BoxWhiskers *item, m_boxTable.values()) {
144 foreach (BoxWhiskers *item, m_boxTable.values()) {
152 if (m_animation)
145 if (m_animation)
153 m_animation->setAnimationStart(item);
146 m_animation->setAnimationStart(item);
154
147
155 bool dirty = updateBoxGeometry(item, item->m_data.m_index);
148 bool dirty = updateBoxGeometry(item, item->m_data.m_index);
156 if (dirty && m_animation)
149 if (dirty && m_animation)
157 presenter()->startAnimation(m_animation->boxChangeAnimation(item));
150 presenter()->startAnimation(m_animation->boxChangeAnimation(item));
158 else
151 else
159 item->updateGeometry();
152 item->updateGeometry(domain());
160 }
153 }
161 }
154 }
162
155
163 QRectF BoxPlotChartItem::boundingRect() const
156 QRectF BoxPlotChartItem::boundingRect() const
164 {
157 {
165 return m_boundingRect;
158 return m_boundingRect;
166 }
159 }
167
160
168 void BoxPlotChartItem::initializeLayout()
161 void BoxPlotChartItem::initializeLayout()
169 {
162 {
170 }
163 }
171
164
172 QVector<QRectF> BoxPlotChartItem::calculateLayout()
165 QVector<QRectF> BoxPlotChartItem::calculateLayout()
173 {
166 {
174 return QVector<QRectF>();
167 return QVector<QRectF>();
175 }
168 }
176
169
177 bool BoxPlotChartItem::updateBoxGeometry(BoxWhiskers *box, int index)
170 bool BoxPlotChartItem::updateBoxGeometry(BoxWhiskers *box, int index)
178 {
171 {
179 bool changed = false;
172 bool changed = false;
180
173
181 QBoxSet *set = m_series->d_func()->boxSetAt(index);
174 QBoxSet *set = m_series->d_func()->boxSetAt(index);
182 BoxWhiskersData &data = box->m_data;
175 BoxWhiskersData &data = box->m_data;
183
176
184 if ((data.m_lowerExtreme != set->at(0)) || (data.m_lowerQuartile != set->at(1)) ||
177 if ((data.m_lowerExtreme != set->at(0)) || (data.m_lowerQuartile != set->at(1)) ||
185 (data.m_median != set->at(2)) || (data.m_upperQuartile != set->at(3)) || (data.m_upperExtreme != set->at(4))) {
178 (data.m_median != set->at(2)) || (data.m_upperQuartile != set->at(3)) || (data.m_upperExtreme != set->at(4))) {
186 changed = true;
179 changed = true;
187 }
180 }
188
181
189 data.m_lowerExtreme = set->at(0);
182 data.m_lowerExtreme = set->at(0);
190 data.m_lowerQuartile = set->at(1);
183 data.m_lowerQuartile = set->at(1);
191 data.m_median = set->at(2);
184 data.m_median = set->at(2);
192 data.m_upperQuartile = set->at(3);
185 data.m_upperQuartile = set->at(3);
193 data.m_upperExtreme = set->at(4);
186 data.m_upperExtreme = set->at(4);
194 data.m_index = index;
187 data.m_index = index;
195 data.m_boxItems = m_series->count();
188 data.m_boxItems = m_series->count();
196
189
197 data.m_maxX = domain()->maxX();
190 data.m_maxX = domain()->maxX();
198 data.m_minX = domain()->minX();
191 data.m_minX = domain()->minX();
199 data.m_maxY = domain()->maxY();
192 data.m_maxY = domain()->maxY();
200 data.m_minY = domain()->minY();
193 data.m_minY = domain()->minY();
201
194
202 data.m_seriesIndex = m_seriesIndex;
195 data.m_seriesIndex = m_seriesIndex;
203 data.m_seriesCount = m_seriesCount;
196 data.m_seriesCount = m_seriesCount;
204
197
205 return changed;
198 return changed;
206 }
199 }
207
200
208 #include "moc_boxplotchartitem_p.cpp"
201 #include "moc_boxplotchartitem_p.cpp"
209
202
210 QTCOMMERCIALCHART_END_NAMESPACE
203 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,87 +1,85
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
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
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30
30
31 #ifndef BOXPLOTCHARTITEM_H
31 #ifndef BOXPLOTCHARTITEM_H
32 #define BOXPLOTCHARTITEM_H
32 #define BOXPLOTCHARTITEM_H
33
33
34 #include "boxwhiskers_p.h"
34 #include "boxwhiskers_p.h"
35 #include "qboxplotseries.h"
35 #include "qboxplotseries.h"
36 #include "chartitem_p.h"
36 #include "chartitem_p.h"
37 #include "boxplotanimation_p.h"
37 #include "boxplotanimation_p.h"
38 #include "qboxset.h"
38 #include "qboxset.h"
39 #include <QGraphicsItem>
39 #include <QGraphicsItem>
40
40
41 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41 QTCOMMERCIALCHART_BEGIN_NAMESPACE
42
42
43 class BoxPlotSeriesPrivate;
43 class BoxPlotSeriesPrivate;
44
44
45 class BoxPlotChartItem : public ChartItem
45 class BoxPlotChartItem : public ChartItem
46 {
46 {
47 Q_OBJECT
47 Q_OBJECT
48 public:
48 public:
49 BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item = 0);
49 BoxPlotChartItem(QBoxPlotSeries *series, QGraphicsItem *item = 0);
50 ~BoxPlotChartItem();
50 ~BoxPlotChartItem();
51
51
52 void setAnimation(BoxPlotAnimation *animation);
52 void setAnimation(BoxPlotAnimation *animation);
53
53
54 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
54 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
55 QRectF boundingRect() const;
55 QRectF boundingRect() const;
56
56
57 public Q_SLOTS:
57 public Q_SLOTS:
58 void handleDataStructureChanged();
58 void handleDataStructureChanged();
59 void handleDomainUpdated();
59 void handleDomainUpdated();
60 void handleLayoutChanged();
60 void handleLayoutChanged();
61 void handleUpdatedBars();
61 void handleUpdatedBars();
62 void handleBoxsetRemove(QList<QBoxSet *> barSets);
62 void handleBoxsetRemove(QList<QBoxSet *> barSets);
63
63
64 private:
64 private:
65 virtual QVector<QRectF> calculateLayout();
65 virtual QVector<QRectF> calculateLayout();
66 void initializeLayout();
66 void initializeLayout();
67 bool updateBoxGeometry(BoxWhiskers *box, int index);
67 bool updateBoxGeometry(BoxWhiskers *box, int index);
68
68
69 protected:
69 protected:
70 friend class QBoxPlotSeriesPrivate;
70 friend class QBoxPlotSeriesPrivate;
71 QBoxPlotSeries *m_series; // Not owned.
71 QBoxPlotSeries *m_series; // Not owned.
72 QList<BoxWhiskers *> m_boxes;
72 QList<BoxWhiskers *> m_boxes;
73 QHash<QBoxSet *, BoxWhiskers *> m_boxTable;
73 QHash<QBoxSet *, BoxWhiskers *> m_boxTable;
74 int m_seriesIndex;
74 int m_seriesIndex;
75 int m_seriesCount;
75 int m_seriesCount;
76
76
77 BoxPlotAnimation *m_animation;
77 BoxPlotAnimation *m_animation;
78 bool m_animate;
78 bool m_animate;
79 qreal m_domainMaxY;
80 qreal m_domainMinY;
81
79
82 QRectF m_boundingRect;
80 QRectF m_boundingRect;
83 };
81 };
84
82
85 QTCOMMERCIALCHART_END_NAMESPACE
83 QTCOMMERCIALCHART_END_NAMESPACE
86
84
87 #endif // BOXPLOTCHARTITEM_H
85 #endif // BOXPLOTCHARTITEM_H
@@ -1,167 +1,171
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "boxwhiskers_p.h"
21 #include "boxwhiskers_p.h"
22 #include <QPainter>
22 #include <QPainter>
23 #include <QWidget>
23 #include <QWidget>
24
24
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26
26
27 BoxWhiskers::BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent) :
27 BoxWhiskers::BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent) :
28 QGraphicsObject(parent),
28 QGraphicsObject(parent),
29 m_boxSet(set),
29 m_boxSet(set),
30 m_domain(domain)
30 m_domain(domain)
31 {
31 {
32 setAcceptHoverEvents(true);
32 setAcceptHoverEvents(true);
33 setAcceptedMouseButtons(Qt::MouseButtonMask);
33 setAcceptedMouseButtons(Qt::MouseButtonMask);
34 }
34 }
35
35
36 BoxWhiskers::~BoxWhiskers()
36 BoxWhiskers::~BoxWhiskers()
37 {
37 {
38 }
38 }
39
39
40 void BoxWhiskers::mousePressEvent(QGraphicsSceneMouseEvent *event)
40 void BoxWhiskers::mousePressEvent(QGraphicsSceneMouseEvent *event)
41 {
41 {
42 Q_UNUSED(event)
42 Q_UNUSED(event)
43 emit clicked(m_boxSet);
43 emit clicked(m_boxSet);
44 }
44 }
45
45
46 void BoxWhiskers::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
46 void BoxWhiskers::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
47 {
47 {
48 Q_UNUSED(event)
48 Q_UNUSED(event)
49 emit hovered(true, m_boxSet);
49 emit hovered(true, m_boxSet);
50 }
50 }
51
51
52 void BoxWhiskers::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
52 void BoxWhiskers::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
53 {
53 {
54 Q_UNUSED(event)
54 Q_UNUSED(event)
55 emit hovered(false, m_boxSet);
55 emit hovered(false, m_boxSet);
56 }
56 }
57
57
58 void BoxWhiskers::setBrush(const QBrush &brush)
58 void BoxWhiskers::setBrush(const QBrush &brush)
59 {
59 {
60 m_brush = brush;
60 m_brush = brush;
61 update();
61 update();
62 }
62 }
63
63
64 void BoxWhiskers::setPen(const QPen &pen)
64 void BoxWhiskers::setPen(const QPen &pen)
65 {
65 {
66 m_pen = pen;
66 m_pen = pen;
67 update();
67 update();
68 }
68 }
69
69
70 void BoxWhiskers::setLayout(const BoxWhiskersData &data)
70 void BoxWhiskers::setLayout(const BoxWhiskersData &data)
71 {
71 {
72 m_data = data;
72 m_data = data;
73
73
74 updateGeometry();
74 updateGeometry(m_domain);
75 update();
75 update();
76 }
76 }
77
77
78
79 QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
78 QSizeF BoxWhiskers::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
80 {
79 {
81 Q_UNUSED(which)
80 Q_UNUSED(which)
82 Q_UNUSED(constraint)
81 Q_UNUSED(constraint)
83
82
84 return QSizeF();
83 return QSizeF();
85 }
84 }
86
85
87 void BoxWhiskers::setGeometry(const QRectF &rect)
86 void BoxWhiskers::setGeometry(const QRectF &rect)
88 {
87 {
89 Q_UNUSED(rect)
88 Q_UNUSED(rect)
90 }
89 }
91
90
92 void BoxWhiskers::setDomainSize(const QSizeF &size)
93 {
94 m_domainSize = size;
95
96 updateBoundingRect();
97 }
98
99 QRectF BoxWhiskers::boundingRect() const
91 QRectF BoxWhiskers::boundingRect() const
100 {
92 {
101 return m_boundingRect;
93 return m_boundingRect;
102 }
94 }
103
95
104 void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
96 void BoxWhiskers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
105 {
97 {
106 Q_UNUSED(option)
98 Q_UNUSED(option)
107 Q_UNUSED(widget)
99 Q_UNUSED(widget)
108
100
109 painter->setPen(m_pen);
101 painter->setPen(m_pen);
110 painter->setBrush(m_brush);
102 painter->setBrush(m_brush);
111 painter->setClipRect(parentItem()->boundingRect());
103 painter->setClipRect(parentItem()->boundingRect());
112 painter->scale(m_domainSize.width() / m_data.m_boxItems, m_domainSize.height() / m_domain->spanY());
113 painter->drawPath(m_boxPath);
104 painter->drawPath(m_boxPath);
114 }
105 }
115
106
116 void BoxWhiskers::updateGeometry()
107 void BoxWhiskers::updateGeometry(AbstractDomain *domain)
117 {
108 {
109 m_domain = domain;
110
118 prepareGeometryChange();
111 prepareGeometryChange();
119
112
120 QPainterPath path;
113 QPainterPath path;
114 m_boxPath = path;
115 m_boundingRect = m_boxPath.boundingRect();
121
116
122 qreal columnWidth = 1.0 / m_data.m_seriesCount;
117 qreal columnWidth = 1.0 / m_data.m_seriesCount;
123 qreal left = 0.25 * columnWidth + columnWidth * m_data.m_seriesIndex;
118 qreal left = 0.25 * columnWidth + columnWidth * m_data.m_seriesIndex + m_data.m_index - 0.5;
124 qreal right = 0.75 * columnWidth + columnWidth * m_data.m_seriesIndex;
119 qreal barWidth = columnWidth / 2.0;
125 qreal middle = 0.5 * columnWidth + columnWidth * m_data.m_seriesIndex;
120
126 qreal domainMaxY = m_domain->maxY();
121 QPointF geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_upperExtreme), m_validData);
122 if (!m_validData)
123 return;
124 qreal geometryLeft = geometryPoint.x();
125 qreal geometryUpperExtreme = geometryPoint.y();
126 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left + barWidth, m_data.m_upperQuartile), m_validData);
127 if (!m_validData)
128 return;
129 qreal geometryRight = geometryPoint.x();
130 qreal geometryUpperQuartile = geometryPoint.y();
131 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerQuartile), m_validData);
132 if (!m_validData)
133 return;
134 qreal geometryLowerQuartile = geometryPoint.y();
135 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_lowerExtreme), m_validData);
136 if (!m_validData)
137 return;
138 qreal geometryLowerExtreme = geometryPoint.y();
139 geometryPoint = m_domain->calculateGeometryPoint(QPointF(left, m_data.m_median), m_validData);
140 if (!m_validData)
141 return;
142 qreal geometryMedian = geometryPoint.y();
127
143
128 // Upper whisker
144 // Upper whisker
129 path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
145 path.moveTo(geometryLeft, geometryUpperExtreme);
130 path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
146 path.lineTo(geometryRight, geometryUpperExtreme);
131 path.moveTo(middle + m_data.m_index, domainMaxY - m_data.m_upperExtreme);
147 path.moveTo((geometryLeft + geometryRight) / 2.0, geometryUpperExtreme);
132 path.lineTo(middle + m_data.m_index, domainMaxY - m_data.m_upperQuartile);
148 path.lineTo((geometryLeft + geometryRight) / 2.0, geometryUpperQuartile);
133
149
134 // Middle Box
150 // Middle Box
135 path.addRect(left + m_data.m_index, domainMaxY - m_data.m_upperQuartile,
151 path.addRect(geometryLeft, geometryUpperQuartile, geometryRight - geometryLeft, geometryLowerQuartile - geometryUpperQuartile);
136 0.5 * columnWidth, m_data.m_upperQuartile - m_data.m_lowerQuartile);
137
152
138 // Median/mean line
153 // Median line
139 path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_median);
154 path.moveTo(geometryLeft, geometryMedian);
140 path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_median);
155 path.lineTo(geometryRight, geometryMedian);
141
156
142 // Lower whisker
157 // Lower whisker
143 path.moveTo(left + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
158 path.moveTo(geometryLeft, geometryLowerExtreme);
144 path.lineTo(right + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
159 path.lineTo(geometryRight, geometryLowerExtreme);
145 path.moveTo(middle + m_data.m_index, domainMaxY - m_data.m_lowerExtreme);
160 path.moveTo((geometryLeft + geometryRight) / 2.0, geometryLowerQuartile);
146 path.lineTo(middle + m_data.m_index, domainMaxY - m_data.m_lowerQuartile);
161 path.lineTo((geometryLeft + geometryRight) / 2.0, geometryLowerExtreme);
147
162
148 path.closeSubpath();
163 path.closeSubpath();
149
164
150 m_boxPath = path;
165 m_boxPath = path;
151
166 m_boundingRect = m_boxPath.boundingRect();
152 updateBoundingRect();
153 }
154
155 void BoxWhiskers::updateBoundingRect()
156 {
157 qreal scaleY = m_domainSize.height() / (m_domain->maxY() - m_domain->minY());
158 qreal scaleX = m_domainSize.width() / m_data.m_boxItems;
159 QRectF br = m_boxPath.boundingRect();
160
161 m_boundingRect = QRectF(br.x() * scaleX, br.y() * scaleY,
162 br.width() * scaleX, br.height() * scaleY);
163 }
167 }
164
168
165 #include "moc_boxwhiskers_p.cpp"
169 #include "moc_boxwhiskers_p.cpp"
166
170
167 QTCOMMERCIALCHART_END_NAMESPACE
171 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,96 +1,92
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
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
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef BOXWHISKERS_H
30 #ifndef BOXWHISKERS_H
31 #define BOXWHISKERS_H
31 #define BOXWHISKERS_H
32
32
33 #include "boxwhiskersdata_p.h"
33 #include "boxwhiskersdata_p.h"
34 #include "qchartglobal.h"
34 #include "qchartglobal.h"
35 #include "abstractdomain_p.h"
35 #include "abstractdomain_p.h"
36 #include <QBoxSet>
36 #include <QBoxSet>
37 #include <QGraphicsRectItem>
37 #include <QGraphicsRectItem>
38 #include <QGraphicsLineItem>
38 #include <QGraphicsLineItem>
39 #include <QGraphicsLayoutItem>
39 #include <QGraphicsLayoutItem>
40 #include <QPainterPath>
40 #include <QPainterPath>
41
41
42 QTCOMMERCIALCHART_BEGIN_NAMESPACE
42 QTCOMMERCIALCHART_BEGIN_NAMESPACE
43
43
44 class QBarSet;
44 class QBarSet;
45
45
46 class BoxWhiskers : public QGraphicsObject
46 class BoxWhiskers : public QGraphicsObject
47 {
47 {
48 Q_OBJECT
48 Q_OBJECT
49
49
50 public:
50 public:
51 BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent);
51 BoxWhiskers(QBoxSet *set, AbstractDomain *domain, QGraphicsObject *parent);
52 ~BoxWhiskers();
52 ~BoxWhiskers();
53
53
54 void setBrush(const QBrush &brush);
54 void setBrush(const QBrush &brush);
55 void setPen(const QPen &pen);
55 void setPen(const QPen &pen);
56 void setLayout(const BoxWhiskersData &data);
56 void setLayout(const BoxWhiskersData &data);
57 void setDomainSize(const QSizeF &size);
58
57
59 void mousePressEvent(QGraphicsSceneMouseEvent *event);
58 void mousePressEvent(QGraphicsSceneMouseEvent *event);
60 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
59 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
61 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
60 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
62
61
63 QRectF boundingRect() const;
62 QRectF boundingRect() const;
64 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
63 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
65
64
66 void updateGeometry();
65 void updateGeometry(AbstractDomain *domain);
67 protected:
66 protected:
68 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
67 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
69 void setGeometry(const QRectF &rect);
68 void setGeometry(const QRectF &rect);
70
69
71 private:
72 void updateBoundingRect();
73
74 Q_SIGNALS:
70 Q_SIGNALS:
75 void clicked(QBoxSet *boxset);
71 void clicked(QBoxSet *boxset);
76 void hovered(bool status, QBoxSet *boxset);
72 void hovered(bool status, QBoxSet *boxset);
77
73
78 private:
74 private:
79 friend class BoxPlotChartItem;
75 friend class BoxPlotChartItem;
80 friend class BoxPlotAnimation;
76 friend class BoxPlotAnimation;
81
77
82 QBoxSet *m_boxSet;
78 QBoxSet *m_boxSet;
83 AbstractDomain *m_domain;
79 AbstractDomain *m_domain;
84 QPainterPath m_boxPath;
80 QPainterPath m_boxPath;
85 QRectF m_boundingRect;
81 QRectF m_boundingRect;
86 bool m_hovering;
82 bool m_hovering;
87 bool m_validData;
83 bool m_validData;
88 QBrush m_brush;
84 QBrush m_brush;
89 QPen m_pen;
85 QPen m_pen;
90 BoxWhiskersData m_data;
86 BoxWhiskersData m_data;
91 QSizeF m_domainSize;
87 QSizeF m_domainSize;
92 };
88 };
93
89
94 QTCOMMERCIALCHART_END_NAMESPACE
90 QTCOMMERCIALCHART_END_NAMESPACE
95
91
96 #endif // BOXWHISKERS_H
92 #endif // BOXWHISKERS_H
@@ -1,680 +1,680
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qboxplotseries.h"
21 #include "qboxplotseries.h"
22 #include "qboxplotseries_p.h"
22 #include "qboxplotseries_p.h"
23 #include "qboxplotlegendmarker.h"
23 #include "qboxplotlegendmarker.h"
24 #include "qbarcategoryaxis.h"
24 #include "qbarcategoryaxis.h"
25 #include "boxplotchartitem_p.h"
25 #include "boxplotchartitem_p.h"
26 #include "chartdataset_p.h"
26 #include "chartdataset_p.h"
27 #include "charttheme_p.h"
27 #include "charttheme_p.h"
28 #include "qvalueaxis.h"
28 #include "qvalueaxis.h"
29 #include "charttheme_p.h"
29 #include "charttheme_p.h"
30 #include "boxplotanimation_p.h"
30 #include "boxplotanimation_p.h"
31 #include "qchart_p.h"
31 #include "qchart_p.h"
32 #include "qboxset.h"
32 #include "qboxset.h"
33 #include "qboxset_p.h"
33 #include "qboxset_p.h"
34
34
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36
36
37 /*!
37 /*!
38 \class QBoxPlotSeries
38 \class QBoxPlotSeries
39 \brief Series for creating box-and-whiskers chart
39 \brief Series for creating box-and-whiskers chart
40 \mainclass
40 \mainclass
41
41
42 QBoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
42 QBoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
43 a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
43 a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
44 QBoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
44 QBoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
45
45
46 See the \l {Box and Whiskers Example} {box-and-whiskers chart example} to learn how to create a box-and-whiskers chart.
46 See the \l {Box and Whiskers Example} {box-and-whiskers chart example} to learn how to create a box-and-whiskers chart.
47 \image examples_boxplotchart.png
47 \image examples_boxplotchart.png
48
48
49 \sa QBoxSet
49 \sa QBoxSet
50 */
50 */
51
51
52 /*!
52 /*!
53 \qmlclass BoxPlotSeries QBoxPlotSeries
53 \qmlclass BoxPlotSeries QBoxPlotSeries
54 \inherits QAbstractSeries
54 \inherits QAbstractSeries
55
55
56 BoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
56 BoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
57 a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
57 a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
58 BoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
58 BoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
59
59
60 The following QML shows how to create a simple box-and-whiskers chart:
60 The following QML shows how to create a simple box-and-whiskers chart:
61 \code
61 \code
62 import QtQuick 1.0
62 import QtQuick 1.0
63 import QtCommercial.Chart 1.1
63 import QtCommercial.Chart 1.1
64
64
65 ChartView {
65 ChartView {
66 title: "Box Plot series"
66 title: "Box Plot series"
67 width: 400
67 width: 400
68 height: 300
68 height: 300
69 theme: ChartView.ChartThemeBrownSand
69 theme: ChartView.ChartThemeBrownSand
70 legend.alignment: Qt.AlignBottom
70 legend.alignment: Qt.AlignBottom
71
71
72 BoxPlotSeries {
72 BoxPlotSeries {
73 id: plotSeries
73 id: plotSeries
74 name: "Income"
74 name: "Income"
75 BoxSet { label: "Jan"; values: [3, 4, 5.1, 6.2, 8.5] }
75 BoxSet { label: "Jan"; values: [3, 4, 5.1, 6.2, 8.5] }
76 BoxSet { label: "Feb"; values: [5, 6, 7.5, 8.6, 11.8] }
76 BoxSet { label: "Feb"; values: [5, 6, 7.5, 8.6, 11.8] }
77 BoxSet { label: "Mar"; values: [3.2, 5, 5.7, 8, 9.2] }
77 BoxSet { label: "Mar"; values: [3.2, 5, 5.7, 8, 9.2] }
78 BoxSet { label: "Apr"; values: [3.8, 5, 6.4, 7, 8] }
78 BoxSet { label: "Apr"; values: [3.8, 5, 6.4, 7, 8] }
79 BoxSet { label: "May"; values: [4, 5, 5.2, 6, 7] }
79 BoxSet { label: "May"; values: [4, 5, 5.2, 6, 7] }
80 }
80 }
81 }
81 }
82 \endcode
82 \endcode
83
83
84 \beginfloatleft
84 \beginfloatleft
85 \image examples_qmlboxplot.png
85 \image examples_qmlboxplot.png
86 \endfloat
86 \endfloat
87 \clearfloat
87 \clearfloat
88 */
88 */
89
89
90 /*!
90 /*!
91 \fn QBoxPlotSeries::boxsetsAdded(QList<QBoxSet *> sets)
91 \fn QBoxPlotSeries::boxsetsAdded(QList<QBoxSet *> sets)
92 \brief Signal is emitted when a new \a sets of box-and-whiskers data is added to the series.
92 \brief Signal is emitted when a new \a sets of box-and-whiskers data is added to the series.
93 */
93 */
94
94
95 /*!
95 /*!
96 \fn QBoxPlotSeries::boxsetsRemoved(QList<QBoxSet *> sets)
96 \fn QBoxPlotSeries::boxsetsRemoved(QList<QBoxSet *> sets)
97 \brief Signal is emitted when \a sets of box-and-whiskers data is removed from the series.
97 \brief Signal is emitted when \a sets of box-and-whiskers data is removed from the series.
98 */
98 */
99
99
100 /*!
100 /*!
101 \fn QBoxPlotSeries::clicked(QBoxSet *boxset)
101 \fn QBoxPlotSeries::clicked(QBoxSet *boxset)
102 \brief Signal is emitted when the user clicks the \a boxset on the chart.
102 \brief Signal is emitted when the user clicks the \a boxset on the chart.
103 */
103 */
104
104
105 /*!
105 /*!
106 \fn QBoxPlotSeries::hovered(bool status, QBoxSet *boxset)
106 \fn QBoxPlotSeries::hovered(bool status, QBoxSet *boxset)
107 \brief Signal is emitted when there is change in hover \a status over \a boxset.
107 \brief Signal is emitted when there is change in hover \a status over \a boxset.
108 */
108 */
109
109
110 /*!
110 /*!
111 \fn QBoxPlotSeries::countChanged()
111 \fn QBoxPlotSeries::countChanged()
112 \brief Signal is emitted when there is change in count of box-and-whiskers items in the series.
112 \brief Signal is emitted when there is change in count of box-and-whiskers items in the series.
113 */
113 */
114 /*!
114 /*!
115 \fn virtual SeriesType QBoxPlotSeries::type() const
115 \fn virtual SeriesType QBoxPlotSeries::type() const
116 \brief Returns type of series.
116 \brief Returns type of series.
117 \sa QAbstractSeries, SeriesType
117 \sa QAbstractSeries, SeriesType
118 */
118 */
119 /*!
119 /*!
120 \qmlmethod BoxPlotSeries::append(const QString label, QVariantList values)
120 \qmlmethod BoxPlotSeries::append(const QString label, QVariantList values)
121 Appends a new box-and-whiskers set with \a label and \a values to the series.
121 Appends a new box-and-whiskers set with \a label and \a values to the series.
122 */
122 */
123 /*!
123 /*!
124 \qmlmethod BoxPlotSeries::append(BoxSet *box)
124 \qmlmethod BoxPlotSeries::append(BoxSet *box)
125 Appends the \a box to the series.
125 Appends the \a box to the series.
126 */
126 */
127 /*!
127 /*!
128 \qmlmethod BoxPlotSeries::insert(int index, const QString label, QVariantList values)
128 \qmlmethod BoxPlotSeries::insert(int index, const QString label, QVariantList values)
129 Inserts a new box-and-whiskers set with \a label and \a values at the \a index position.
129 Inserts a new box-and-whiskers set with \a label and \a values at the \a index position.
130 */
130 */
131 /*!
131 /*!
132 \qmlmethod BoxPlotSeries::remove(QBoxSet *boxset)
132 \qmlmethod BoxPlotSeries::remove(QBoxSet *boxset)
133 Removes the \a boxset from the series.
133 Removes the \a boxset from the series.
134 */
134 */
135 /*!
135 /*!
136 \qmlmethod BoxPlotSeries::clear()
136 \qmlmethod BoxPlotSeries::clear()
137 Removes all boxsets from the series. Deletes removed sets.
137 Removes all boxsets from the series. Deletes removed sets.
138 */
138 */
139
139
140 /*!
140 /*!
141 \qmlsignal BoxPlotSeries::onClicked(BoxSet boxset);
141 \qmlsignal BoxPlotSeries::onClicked(BoxSet boxset);
142 Signal is emitted when the user clicks the \a boxset on the chart.
142 Signal is emitted when the user clicks the \a boxset on the chart.
143 */
143 */
144 /*!
144 /*!
145 \qmlsignal BoxPlotSeries::onHovered(bool status, BoxSet boxset);
145 \qmlsignal BoxPlotSeries::onHovered(bool status, BoxSet boxset);
146 Signal is emitted when there is change in hover \a status over \a boxset.
146 Signal is emitted when there is change in hover \a status over \a boxset.
147 */
147 */
148 /*!
148 /*!
149 \qmlsignal BoxPlotSeries::onCountChanged();
149 \qmlsignal BoxPlotSeries::onCountChanged();
150 Signal is emitted when there is change in count of box-and-whiskers items in the series.
150 Signal is emitted when there is change in count of box-and-whiskers items in the series.
151 */
151 */
152 /*!
152 /*!
153 \qmlsignal BoxPlotSeries::onBoxsetsAdded()
153 \qmlsignal BoxPlotSeries::onBoxsetsAdded()
154 Signal is emitted when new box-and-whiskers sets are added to the series.
154 Signal is emitted when new box-and-whiskers sets are added to the series.
155 */
155 */
156 /*!
156 /*!
157 \qmlsignal BoxPlotSeries::boxsetsRemoved()
157 \qmlsignal BoxPlotSeries::boxsetsRemoved()
158 Signal is emitted when new box-and-whiskers sets are removed from the series.
158 Signal is emitted when new box-and-whiskers sets are removed from the series.
159 */
159 */
160
160
161 /*!
161 /*!
162 Constructs empty QBoxPlotSeries.
162 Constructs empty QBoxPlotSeries.
163 QBoxPlotSeries is QObject which is a child of a \a parent.
163 QBoxPlotSeries is QObject which is a child of a \a parent.
164 */
164 */
165 QBoxPlotSeries::QBoxPlotSeries(QObject *parent)
165 QBoxPlotSeries::QBoxPlotSeries(QObject *parent)
166 : QAbstractSeries(*new QBoxPlotSeriesPrivate(this), parent)
166 : QAbstractSeries(*new QBoxPlotSeriesPrivate(this), parent)
167 {
167 {
168 }
168 }
169
169
170 /*!
170 /*!
171 Destructor. Removes series from chart.
171 Destructor. Removes series from chart.
172 */
172 */
173 QBoxPlotSeries::~QBoxPlotSeries()
173 QBoxPlotSeries::~QBoxPlotSeries()
174 {
174 {
175 Q_D(QBoxPlotSeries);
175 Q_D(QBoxPlotSeries);
176 if (d->m_chart)
176 if (d->m_chart)
177 d->m_chart->removeSeries(this);
177 d->m_chart->removeSeries(this);
178 }
178 }
179
179
180 /*!
180 /*!
181 Adds a single box and whiskers set to series. Takes ownership of the \a set. If the set is null or is already in series, it won't be appended.
181 Adds a single box and whiskers set to series. Takes ownership of the \a set. If the set is null or is already in series, it won't be appended.
182 Returns true, if appending succeeded.
182 Returns true, if appending succeeded.
183 */
183 */
184 bool QBoxPlotSeries::append(QBoxSet *set)
184 bool QBoxPlotSeries::append(QBoxSet *set)
185 {
185 {
186 Q_D(QBoxPlotSeries);
186 Q_D(QBoxPlotSeries);
187
187
188 bool success = d->append(set);
188 bool success = d->append(set);
189 if (success) {
189 if (success) {
190 QList<QBoxSet *> sets;
190 QList<QBoxSet *> sets;
191 sets.append(set);
191 sets.append(set);
192 set->setParent(this);
192 set->setParent(this);
193 emit boxsetsAdded(sets);
193 emit boxsetsAdded(sets);
194 emit countChanged();
194 emit countChanged();
195 }
195 }
196 return success;
196 return success;
197 }
197 }
198
198
199 /*!
199 /*!
200 Removes boxset from the series. Deletes the \a set and returns true if successful.
200 Removes boxset from the series. Deletes the \a set and returns true if successful.
201 */
201 */
202 bool QBoxPlotSeries::remove(QBoxSet *set)
202 bool QBoxPlotSeries::remove(QBoxSet *set)
203 {
203 {
204 Q_D(QBoxPlotSeries);
204 Q_D(QBoxPlotSeries);
205 bool success = d->remove(set);
205 bool success = d->remove(set);
206 if (success) {
206 if (success) {
207 QList<QBoxSet *> sets;
207 QList<QBoxSet *> sets;
208 sets.append(set);
208 sets.append(set);
209 set->setParent(0);
209 set->setParent(0);
210 emit boxsetsRemoved(sets);
210 emit boxsetsRemoved(sets);
211 emit countChanged();
211 emit countChanged();
212 delete set;
212 delete set;
213 set = 0;
213 set = 0;
214 }
214 }
215 return success;
215 return success;
216 }
216 }
217
217
218 /*!
218 /*!
219 Takes a single \a set from the series. Does not delete the boxset object.
219 Takes a single \a set from the series. Does not delete the boxset object.
220
220
221 NOTE: The series remains as the boxset's parent object. You must set the
221 NOTE: The series remains as the boxset's parent object. You must set the
222 parent object to take full ownership.
222 parent object to take full ownership.
223
223
224 Returns true if take was successful.
224 Returns true if take was successful.
225 */
225 */
226 bool QBoxPlotSeries::take(QBoxSet *set)
226 bool QBoxPlotSeries::take(QBoxSet *set)
227 {
227 {
228 Q_D(QBoxPlotSeries);
228 Q_D(QBoxPlotSeries);
229
229
230 bool success = d->remove(set);
230 bool success = d->remove(set);
231 if (success) {
231 if (success) {
232 QList<QBoxSet *> sets;
232 QList<QBoxSet *> sets;
233 sets.append(set);
233 sets.append(set);
234 emit boxsetsRemoved(sets);
234 emit boxsetsRemoved(sets);
235 emit countChanged();
235 emit countChanged();
236 }
236 }
237 return success;
237 return success;
238 }
238 }
239
239
240 /*!
240 /*!
241 Adds a list of boxsets to series. Takes ownership of the \a sets.
241 Adds a list of boxsets to series. Takes ownership of the \a sets.
242 Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
242 Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
243 nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
243 nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
244 and function returns false.
244 and function returns false.
245 */
245 */
246 bool QBoxPlotSeries::append(QList<QBoxSet *> sets)
246 bool QBoxPlotSeries::append(QList<QBoxSet *> sets)
247 {
247 {
248 Q_D(QBoxPlotSeries);
248 Q_D(QBoxPlotSeries);
249 bool success = d->append(sets);
249 bool success = d->append(sets);
250 if (success) {
250 if (success) {
251 emit boxsetsAdded(sets);
251 emit boxsetsAdded(sets);
252 emit countChanged();
252 emit countChanged();
253 }
253 }
254 return success;
254 return success;
255 }
255 }
256
256
257 /*!
257 /*!
258 Insert a box-and-whiskers set to the series at \a index postion. Takes ownership of the \a set. If the set is null or
258 Insert a box-and-whiskers set to the series at \a index postion. Takes ownership of the \a set. If the set is null or
259 is already in series, it won't be appended. Returns true, if inserting succeeded.
259 is already in series, it won't be appended. Returns true, if inserting succeeded.
260
260
261 */
261 */
262 bool QBoxPlotSeries::insert(int index, QBoxSet *set)
262 bool QBoxPlotSeries::insert(int index, QBoxSet *set)
263 {
263 {
264 Q_D(QBoxPlotSeries);
264 Q_D(QBoxPlotSeries);
265 bool success = d->insert(index, set);
265 bool success = d->insert(index, set);
266 if (success) {
266 if (success) {
267 QList<QBoxSet *> sets;
267 QList<QBoxSet *> sets;
268 sets.append(set);
268 sets.append(set);
269 emit boxsetsAdded(sets);
269 emit boxsetsAdded(sets);
270 emit countChanged();
270 emit countChanged();
271 }
271 }
272 return success;
272 return success;
273 }
273 }
274
274
275 /*!
275 /*!
276 Removes all boxsets from the series. Deletes removed sets.
276 Removes all boxsets from the series. Deletes removed sets.
277 */
277 */
278 void QBoxPlotSeries::clear()
278 void QBoxPlotSeries::clear()
279 {
279 {
280 Q_D(QBoxPlotSeries);
280 Q_D(QBoxPlotSeries);
281 QList<QBoxSet *> sets = boxSets();
281 QList<QBoxSet *> sets = boxSets();
282 bool success = d->remove(sets);
282 bool success = d->remove(sets);
283 if (success) {
283 if (success) {
284 emit boxsetsRemoved(sets);
284 emit boxsetsRemoved(sets);
285 emit countChanged();
285 emit countChanged();
286 foreach (QBoxSet *set, sets)
286 foreach (QBoxSet *set, sets)
287 delete set;
287 delete set;
288 }
288 }
289 }
289 }
290
290
291 /*!
291 /*!
292 Returns number of sets in series.
292 Returns number of sets in series.
293 */
293 */
294 int QBoxPlotSeries::count() const
294 int QBoxPlotSeries::count() const
295 {
295 {
296 Q_D(const QBoxPlotSeries);
296 Q_D(const QBoxPlotSeries);
297 return d->m_boxSets.count();
297 return d->m_boxSets.count();
298 }
298 }
299
299
300 /*!
300 /*!
301 Returns a list of sets in series. Keeps ownership of sets.
301 Returns a list of sets in series. Keeps ownership of sets.
302 */
302 */
303 QList<QBoxSet *> QBoxPlotSeries::boxSets() const
303 QList<QBoxSet *> QBoxPlotSeries::boxSets() const
304 {
304 {
305 Q_D(const QBoxPlotSeries);
305 Q_D(const QBoxPlotSeries);
306 return d->m_boxSets;
306 return d->m_boxSets;
307 }
307 }
308
308
309 /*
309 /*
310 Returns QAbstractSeries::SeriesTypeBoxPlot.
310 Returns QAbstractSeries::SeriesTypeBoxPlot.
311 */
311 */
312 QAbstractSeries::SeriesType QBoxPlotSeries::type() const
312 QAbstractSeries::SeriesType QBoxPlotSeries::type() const
313 {
313 {
314 return QAbstractSeries::SeriesTypeBoxPlot;
314 return QAbstractSeries::SeriesTypeBoxPlot;
315 }
315 }
316
316
317 /*!
317 /*!
318 Sets brush for the series. Box-and-whiskers items are drawn using \a brush
318 Sets brush for the series. Box-and-whiskers items are drawn using \a brush
319 */
319 */
320 void QBoxPlotSeries::setBrush(const QBrush &brush)
320 void QBoxPlotSeries::setBrush(const QBrush &brush)
321 {
321 {
322 Q_D(QBoxPlotSeries);
322 Q_D(QBoxPlotSeries);
323
323
324 if (d->m_brush != brush) {
324 if (d->m_brush != brush) {
325 d->m_brush = brush;
325 d->m_brush = brush;
326 emit d->updated();
326 emit d->updated();
327 }
327 }
328 }
328 }
329
329
330 /*!
330 /*!
331 Returns brush of the series.
331 Returns brush of the series.
332 */
332 */
333 QBrush QBoxPlotSeries::brush() const
333 QBrush QBoxPlotSeries::brush() const
334 {
334 {
335 Q_D(const QBoxPlotSeries);
335 Q_D(const QBoxPlotSeries);
336
336
337 return d->m_brush;
337 return d->m_brush;
338 }
338 }
339
339
340 /*!
340 /*!
341 Sets pen for the series. Box-and-whiskers items are drawn using \a pen
341 Sets pen for the series. Box-and-whiskers items are drawn using \a pen
342 */
342 */
343 void QBoxPlotSeries::setPen(const QPen &pen)
343 void QBoxPlotSeries::setPen(const QPen &pen)
344 {
344 {
345 Q_D(QBoxPlotSeries);
345 Q_D(QBoxPlotSeries);
346
346
347 if (d->m_pen != pen) {
347 if (d->m_pen != pen) {
348 d->m_pen = pen;
348 d->m_pen = pen;
349 emit d->updated();
349 emit d->updated();
350 }
350 }
351 }
351 }
352
352
353 /*!
353 /*!
354 Returns the pen of this series.
354 Returns the pen of this series.
355 */
355 */
356 QPen QBoxPlotSeries::pen() const
356 QPen QBoxPlotSeries::pen() const
357 {
357 {
358 Q_D(const QBoxPlotSeries);
358 Q_D(const QBoxPlotSeries);
359
359
360 return d->m_pen;
360 return d->m_pen;
361 }
361 }
362
362
363 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
363 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
364
364
365 QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q)
365 QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q)
366 : QAbstractSeriesPrivate(q),
366 : QAbstractSeriesPrivate(q),
367 m_pen(QChartPrivate::defaultPen()),
367 m_pen(QChartPrivate::defaultPen()),
368 m_brush(QChartPrivate::defaultBrush())
368 m_brush(QChartPrivate::defaultBrush())
369 {
369 {
370 }
370 }
371
371
372 QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()
372 QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()
373 {
373 {
374 disconnect(this, 0, 0, 0);
374 disconnect(this, 0, 0, 0);
375 }
375 }
376
376
377 void QBoxPlotSeriesPrivate::initializeDomain()
377 void QBoxPlotSeriesPrivate::initializeDomain()
378 {
378 {
379 qreal minX(domain()->minX());
379 qreal minX(domain()->minX());
380 qreal minY(domain()->minY());
380 qreal minY(domain()->minY());
381 qreal maxX(domain()->maxX());
381 qreal maxX(domain()->maxX());
382 qreal maxY(domain()->maxY());
382 qreal maxY(domain()->maxY());
383
383
384 qreal x = m_boxSets.count();
384 qreal x = m_boxSets.count();
385 minX = qMin(minX, - (qreal)0.5);
385 minX = qMin(minX, qreal(-0.5));
386 minY = qMin(minY, min());
386 minY = qMin(minY, min());
387 maxX = qMax(maxX, x - (qreal)0.5);
387 maxX = qMax(maxX, x - qreal(0.5));
388 maxY = qMax(maxY, max());
388 maxY = qMax(maxY, max());
389
389
390 domain()->setRange(minX, maxX, minY, maxY);
390 domain()->setRange(minX, maxX, minY, maxY);
391 }
391 }
392
392
393 void QBoxPlotSeriesPrivate::initializeAxes()
393 void QBoxPlotSeriesPrivate::initializeAxes()
394 {
394 {
395 foreach (QAbstractAxis* axis, m_axes) {
395 foreach (QAbstractAxis* axis, m_axes) {
396 if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
396 if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
397 if (axis->orientation() == Qt::Horizontal)
397 if (axis->orientation() == Qt::Horizontal)
398 populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
398 populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
399 }
399 }
400 }
400 }
401 }
401 }
402
402
403 QAbstractAxis::AxisType QBoxPlotSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
403 QAbstractAxis::AxisType QBoxPlotSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
404 {
404 {
405 if (orientation == Qt::Horizontal)
405 if (orientation == Qt::Horizontal)
406 return QAbstractAxis::AxisTypeBarCategory;
406 return QAbstractAxis::AxisTypeBarCategory;
407
407
408 return QAbstractAxis::AxisTypeValue;
408 return QAbstractAxis::AxisTypeValue;
409 }
409 }
410
410
411 QAbstractAxis* QBoxPlotSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
411 QAbstractAxis* QBoxPlotSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
412 {
412 {
413 Q_UNUSED(orientation);
413 Q_UNUSED(orientation);
414
414
415 return 0;
415 return 0;
416 }
416 }
417
417
418 void QBoxPlotSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
418 void QBoxPlotSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
419 {
419 {
420 QStringList categories;
420 QStringList categories;
421 if (axis->categories().isEmpty()) {
421 if (axis->categories().isEmpty()) {
422 for (int i(1); i < m_boxSets.count() + 1; i++) {
422 for (int i(1); i < m_boxSets.count() + 1; i++) {
423 QBoxSet *set = m_boxSets.at(i - 1);
423 QBoxSet *set = m_boxSets.at(i - 1);
424 if (set->label().isEmpty())
424 if (set->label().isEmpty())
425 categories << QString::number(i);
425 categories << QString::number(i);
426 else
426 else
427 categories << set->label();
427 categories << set->label();
428 }
428 }
429 axis->append(categories);
429 axis->append(categories);
430 }
430 }
431 }
431 }
432
432
433 void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
433 void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
434 {
434 {
435 Q_Q(QBoxPlotSeries);
435 Q_Q(QBoxPlotSeries);
436
436
437 BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q, parent);
437 BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q, parent);
438 m_item.reset(boxPlot);
438 m_item.reset(boxPlot);
439 QAbstractSeriesPrivate::initializeGraphics(parent);
439 QAbstractSeriesPrivate::initializeGraphics(parent);
440
440
441 if (m_chart) {
441 if (m_chart) {
442 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesChange(QAbstractSeries*)) );
442 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesChange(QAbstractSeries*)) );
443 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SLOT(handleSeriesRemove(QAbstractSeries*)) );
443 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SLOT(handleSeriesRemove(QAbstractSeries*)) );
444
444
445 QList<QAbstractSeries *> serieses = m_chart->series();
445 QList<QAbstractSeries *> serieses = m_chart->series();
446
446
447 // Tries to find this series from the Chart's list of series and deduce the index
447 // Tries to find this series from the Chart's list of series and deduce the index
448 int index = 0;
448 int index = 0;
449 foreach (QAbstractSeries *s, serieses) {
449 foreach (QAbstractSeries *s, serieses) {
450 if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
450 if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
451 if (q == static_cast<QBoxPlotSeries *>(s)) {
451 if (q == static_cast<QBoxPlotSeries *>(s)) {
452 boxPlot->m_seriesIndex = index;
452 boxPlot->m_seriesIndex = index;
453 m_index = index;
453 m_index = index;
454 }
454 }
455 index++;
455 index++;
456 }
456 }
457 }
457 }
458 boxPlot->m_seriesCount = index;
458 boxPlot->m_seriesCount = index;
459 }
459 }
460
460
461 // Make BoxPlotChartItem to instantiate box & whisker items
461 // Make BoxPlotChartItem to instantiate box & whisker items
462 boxPlot->handleDataStructureChanged();
462 boxPlot->handleDataStructureChanged();
463 }
463 }
464
464
465 void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
465 void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
466 {
466 {
467 Q_Q(QBoxPlotSeries);
467 Q_Q(QBoxPlotSeries);
468
468
469 const QList<QGradient> gradients = theme->seriesGradients();
469 const QList<QGradient> gradients = theme->seriesGradients();
470
470
471 if (forced || QChartPrivate::defaultBrush() == m_brush) {
471 if (forced || QChartPrivate::defaultBrush() == m_brush) {
472 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.5);
472 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.5);
473 q->setBrush(brushColor);
473 q->setBrush(brushColor);
474 }
474 }
475
475
476 if (forced || QChartPrivate::defaultPen() == m_pen) {
476 if (forced || QChartPrivate::defaultPen() == m_pen) {
477 QPen pen = theme->outlinePen();
477 QPen pen = theme->outlinePen();
478 pen.setCosmetic(true);
478 pen.setCosmetic(true);
479 q->setPen(pen);
479 q->setPen(pen);
480 }
480 }
481 }
481 }
482
482
483 void QBoxPlotSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
483 void QBoxPlotSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
484 {
484 {
485 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
485 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
486 Q_ASSERT(item);
486 Q_ASSERT(item);
487 if (options.testFlag(QChart::SeriesAnimations))
487 if (options.testFlag(QChart::SeriesAnimations))
488 item->setAnimation(new BoxPlotAnimation(item));
488 item->setAnimation(new BoxPlotAnimation(item));
489 else
489 else
490 item->setAnimation((BoxPlotAnimation *)0);
490 item->setAnimation((BoxPlotAnimation *)0);
491 QAbstractSeriesPrivate::initializeAnimations(options);
491 QAbstractSeriesPrivate::initializeAnimations(options);
492 }
492 }
493
493
494 QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend)
494 QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend)
495 {
495 {
496 Q_Q(QBoxPlotSeries);
496 Q_Q(QBoxPlotSeries);
497 QList<QLegendMarker *> list;
497 QList<QLegendMarker *> list;
498 return list << new QBoxPlotLegendMarker(q, legend);
498 return list << new QBoxPlotLegendMarker(q, legend);
499 }
499 }
500
500
501 void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
501 void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
502 {
502 {
503 Q_Q(QBoxPlotSeries);
503 Q_Q(QBoxPlotSeries);
504
504
505 QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
505 QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
506 QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
506 QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
507
507
508 // Test if series removed is me, then don't do anything
508 // Test if series removed is me, then don't do anything
509 if (q != removedSeries) {
509 if (q != removedSeries) {
510 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
510 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
511 if (item) {
511 if (item) {
512 item->m_seriesCount = item->m_seriesCount - 1;
512 item->m_seriesCount = item->m_seriesCount - 1;
513 if (removedSeries->d_func()->m_index < m_index) {
513 if (removedSeries->d_func()->m_index < m_index) {
514 m_index--;
514 m_index--;
515 item->m_seriesIndex = m_index;
515 item->m_seriesIndex = m_index;
516 }
516 }
517
517
518 item->handleDataStructureChanged();
518 item->handleDataStructureChanged();
519 }
519 }
520 }
520 }
521 }
521 }
522
522
523 void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
523 void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
524 {
524 {
525 Q_UNUSED(series);
525 Q_UNUSED(series);
526
526
527 Q_Q(QBoxPlotSeries);
527 Q_Q(QBoxPlotSeries);
528
528
529 BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.data());
529 BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.data());
530
530
531 if (m_chart) {
531 if (m_chart) {
532 QList<QAbstractSeries *> serieses = m_chart->series();
532 QList<QAbstractSeries *> serieses = m_chart->series();
533
533
534 // Tries to find this series from the Chart's list of series and deduce the index
534 // Tries to find this series from the Chart's list of series and deduce the index
535 int index = 0;
535 int index = 0;
536 foreach (QAbstractSeries *s, serieses) {
536 foreach (QAbstractSeries *s, serieses) {
537 if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
537 if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
538 if (q == static_cast<QBoxPlotSeries *>(s)) {
538 if (q == static_cast<QBoxPlotSeries *>(s)) {
539 boxPlot->m_seriesIndex = index;
539 boxPlot->m_seriesIndex = index;
540 m_index = index;
540 m_index = index;
541 }
541 }
542 index++;
542 index++;
543 }
543 }
544 }
544 }
545 boxPlot->m_seriesCount = index;
545 boxPlot->m_seriesCount = index;
546 }
546 }
547
547
548 boxPlot->handleDataStructureChanged();
548 boxPlot->handleDataStructureChanged();
549 }
549 }
550
550
551 bool QBoxPlotSeriesPrivate::append(QBoxSet *set)
551 bool QBoxPlotSeriesPrivate::append(QBoxSet *set)
552 {
552 {
553 if ((m_boxSets.contains(set)) || (set == 0))
553 if ((m_boxSets.contains(set)) || (set == 0))
554 return false; // Fail if set is already in list or set is null.
554 return false; // Fail if set is already in list or set is null.
555
555
556 m_boxSets.append(set);
556 m_boxSets.append(set);
557 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
557 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
558 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
558 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
559 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
559 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
560
560
561 emit restructuredBoxes(); // this notifies boxplotchartitem
561 emit restructuredBoxes(); // this notifies boxplotchartitem
562 return true;
562 return true;
563 }
563 }
564
564
565 bool QBoxPlotSeriesPrivate::remove(QBoxSet *set)
565 bool QBoxPlotSeriesPrivate::remove(QBoxSet *set)
566 {
566 {
567 if (!m_boxSets.contains(set))
567 if (!m_boxSets.contains(set))
568 return false; // Fail if set is not in list
568 return false; // Fail if set is not in list
569
569
570 m_boxSets.removeOne(set);
570 m_boxSets.removeOne(set);
571 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
571 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
572 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
572 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
573 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
573 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
574
574
575 emit restructuredBoxes(); // this notifies boxplotchartitem
575 emit restructuredBoxes(); // this notifies boxplotchartitem
576 return true;
576 return true;
577 }
577 }
578
578
579 bool QBoxPlotSeriesPrivate::append(QList<QBoxSet *> sets)
579 bool QBoxPlotSeriesPrivate::append(QList<QBoxSet *> sets)
580 {
580 {
581 foreach (QBoxSet *set, sets) {
581 foreach (QBoxSet *set, sets) {
582 if ((set == 0) || (m_boxSets.contains(set)))
582 if ((set == 0) || (m_boxSets.contains(set)))
583 return false; // Fail if any of the sets is null or is already appended.
583 return false; // Fail if any of the sets is null or is already appended.
584 if (sets.count(set) != 1)
584 if (sets.count(set) != 1)
585 return false; // Also fail if same set is more than once in given list.
585 return false; // Also fail if same set is more than once in given list.
586 }
586 }
587
587
588 foreach (QBoxSet *set, sets) {
588 foreach (QBoxSet *set, sets) {
589 m_boxSets.append(set);
589 m_boxSets.append(set);
590 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
590 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
591 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
591 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
592 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
592 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
593 }
593 }
594
594
595 emit restructuredBoxes(); // this notifies boxplotchartitem
595 emit restructuredBoxes(); // this notifies boxplotchartitem
596 return true;
596 return true;
597 }
597 }
598
598
599 bool QBoxPlotSeriesPrivate::remove(QList<QBoxSet *> sets)
599 bool QBoxPlotSeriesPrivate::remove(QList<QBoxSet *> sets)
600 {
600 {
601 if (sets.count() == 0)
601 if (sets.count() == 0)
602 return false;
602 return false;
603
603
604 foreach (QBoxSet *set, sets) {
604 foreach (QBoxSet *set, sets) {
605 if ((set == 0) || (!m_boxSets.contains(set)))
605 if ((set == 0) || (!m_boxSets.contains(set)))
606 return false; // Fail if any of the sets is null or is not in series
606 return false; // Fail if any of the sets is null or is not in series
607 if (sets.count(set) != 1)
607 if (sets.count(set) != 1)
608 return false; // Also fail if same set is more than once in given list.
608 return false; // Also fail if same set is more than once in given list.
609 }
609 }
610
610
611 foreach (QBoxSet *set, sets) {
611 foreach (QBoxSet *set, sets) {
612 m_boxSets.removeOne(set);
612 m_boxSets.removeOne(set);
613 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
613 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
614 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
614 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
615 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
615 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
616 }
616 }
617
617
618 emit restructuredBoxes(); // this notifies boxplotchartitem
618 emit restructuredBoxes(); // this notifies boxplotchartitem
619
619
620 return true;
620 return true;
621 }
621 }
622
622
623 bool QBoxPlotSeriesPrivate::insert(int index, QBoxSet *set)
623 bool QBoxPlotSeriesPrivate::insert(int index, QBoxSet *set)
624 {
624 {
625 if ((m_boxSets.contains(set)) || (set == 0))
625 if ((m_boxSets.contains(set)) || (set == 0))
626 return false; // Fail if set is already in list or set is null.
626 return false; // Fail if set is already in list or set is null.
627
627
628 m_boxSets.insert(index, set);
628 m_boxSets.insert(index, set);
629 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
629 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
630 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
630 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
631 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
631 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
632
632
633 emit restructuredBoxes(); // this notifies boxplotchartitem
633 emit restructuredBoxes(); // this notifies boxplotchartitem
634 return true;
634 return true;
635 }
635 }
636
636
637 QBoxSet *QBoxPlotSeriesPrivate::boxSetAt(int index)
637 QBoxSet *QBoxPlotSeriesPrivate::boxSetAt(int index)
638 {
638 {
639 return m_boxSets.at(index);
639 return m_boxSets.at(index);
640 }
640 }
641
641
642 qreal QBoxPlotSeriesPrivate::min()
642 qreal QBoxPlotSeriesPrivate::min()
643 {
643 {
644 if (m_boxSets.count() <= 0)
644 if (m_boxSets.count() <= 0)
645 return 0;
645 return 0;
646
646
647 qreal min = m_boxSets.at(0)->at(0);
647 qreal min = m_boxSets.at(0)->at(0);
648
648
649 foreach (QBoxSet *set, m_boxSets) {
649 foreach (QBoxSet *set, m_boxSets) {
650 for (int i = 0; i < 5; i++) {
650 for (int i = 0; i < 5; i++) {
651 if (set->at(i) < min)
651 if (set->at(i) < min)
652 min = set->at(i);
652 min = set->at(i);
653 }
653 }
654 }
654 }
655
655
656 return min;
656 return min;
657 }
657 }
658
658
659 qreal QBoxPlotSeriesPrivate::max()
659 qreal QBoxPlotSeriesPrivate::max()
660 {
660 {
661 if (m_boxSets.count() <= 0)
661 if (m_boxSets.count() <= 0)
662 return 0;
662 return 0;
663
663
664 qreal max = m_boxSets.at(0)->at(0);
664 qreal max = m_boxSets.at(0)->at(0);
665
665
666 foreach (QBoxSet *set, m_boxSets) {
666 foreach (QBoxSet *set, m_boxSets) {
667 for (int i = 0; i < 5; i++) {
667 for (int i = 0; i < 5; i++) {
668 if (set->at(i) > max)
668 if (set->at(i) > max)
669 max = set->at(i);
669 max = set->at(i);
670 }
670 }
671 }
671 }
672
672
673 return max;
673 return max;
674 }
674 }
675
675
676 #include "moc_qboxplotseries.cpp"
676 #include "moc_qboxplotseries.cpp"
677 #include "moc_qboxplotseries_p.cpp"
677 #include "moc_qboxplotseries_p.cpp"
678
678
679 QTCOMMERCIALCHART_END_NAMESPACE
679 QTCOMMERCIALCHART_END_NAMESPACE
680
680
@@ -1,416 +1,419
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "mainwidget.h"
21 #include "mainwidget.h"
22 #include "customtablemodel.h"
22 #include "customtablemodel.h"
23 #include <QVBoxPlotModelMapper>
23 #include <QVBoxPlotModelMapper>
24 #include <QTableView>
24 #include <QTableView>
25 #include <QHeaderView>
25 #include <QHeaderView>
26 #include <QChartView>
26 #include <QChartView>
27 #include <QBoxPlotSeries>
27 #include <QBoxPlotSeries>
28 #include <QBoxSet>
28 #include <QBoxSet>
29 #include <QLegend>
29 #include <QLegend>
30 #include <QBarCategoryAxis>
30 #include <QBarCategoryAxis>
31 #include <QBrush>
31 #include <QBrush>
32 #include <QColor>
32 #include <QColor>
33 #include <QPushButton>
33 #include <QPushButton>
34 #include <QComboBox>
34 #include <QComboBox>
35 #include <QSpinBox>
35 #include <QSpinBox>
36 #include <QCheckBox>
36 #include <QCheckBox>
37 #include <QGridLayout>
37 #include <QGridLayout>
38 #include <QHBoxLayout>
38 #include <QHBoxLayout>
39 #include <QLabel>
39 #include <QLabel>
40 #include <QSpacerItem>
40 #include <QSpacerItem>
41 #include <QMessageBox>
41 #include <QMessageBox>
42 #include <cmath>
42 #include <cmath>
43 #include <QDebug>
43 #include <QDebug>
44 #include <QStandardItemModel>
44 #include <QStandardItemModel>
45 #include <QBarCategoryAxis>
45 #include <QBarCategoryAxis>
46
46 #include <QLogValueAxis>
47
47
48 QTCOMMERCIALCHART_USE_NAMESPACE
48 QTCOMMERCIALCHART_USE_NAMESPACE
49
49
50 QString addCategories[] = {"Jul", "Aug", "Sep", "Nov", "Dec"};
50 QString addCategories[] = {"Jul", "Aug", "Sep", "Nov", "Dec"};
51 static const int maxAddCategories = 5;
51
52
52 MainWidget::MainWidget(QWidget *parent) :
53 MainWidget::MainWidget(QWidget *parent) :
53 QWidget(parent),
54 QWidget(parent),
54 m_chart(0),
55 m_chart(0),
56 m_axis(0),
55 rowPos(0),
57 rowPos(0),
56 nSeries(0),
58 nSeries(0),
57 nNewBoxes(0)
59 nNewBoxes(0)
58 {
60 {
59 m_chart = new QChart();
61 m_chart = new QChart();
60
62
61 // Grid layout for the controls for configuring the chart widget
63 // Grid layout for the controls for configuring the chart widget
62 QGridLayout *grid = new QGridLayout();
64 QGridLayout *grid = new QGridLayout();
63
65
64 // Create add a series button
66 // Create add a series button
65 QPushButton *addSeriesButton = new QPushButton("Add a series");
67 QPushButton *addSeriesButton = new QPushButton("Add a series");
66 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
68 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
67 grid->addWidget(addSeriesButton, rowPos++, 1);
69 grid->addWidget(addSeriesButton, rowPos++, 1);
68
70
69 // Create remove a series button
71 // Create remove a series button
70 QPushButton *removeSeriesButton = new QPushButton("Remove a series");
72 QPushButton *removeSeriesButton = new QPushButton("Remove a series");
71 connect(removeSeriesButton, SIGNAL(clicked()), this, SLOT(removeSeries()));
73 connect(removeSeriesButton, SIGNAL(clicked()), this, SLOT(removeSeries()));
72 grid->addWidget(removeSeriesButton, rowPos++, 1);
74 grid->addWidget(removeSeriesButton, rowPos++, 1);
73
75
74 // Create add a single box button
76 // Create add a single box button
75 QPushButton *addBoxButton = new QPushButton("Add a box");
77 QPushButton *addBoxButton = new QPushButton("Add a box");
76 connect(addBoxButton, SIGNAL(clicked()), this, SLOT(addBox()));
78 connect(addBoxButton, SIGNAL(clicked()), this, SLOT(addBox()));
77 grid->addWidget(addBoxButton, rowPos++, 1);
79 grid->addWidget(addBoxButton, rowPos++, 1);
78
80
79 // Create insert a box button
81 // Create insert a box button
80 QPushButton *insertBoxButton = new QPushButton("Insert a box");
82 QPushButton *insertBoxButton = new QPushButton("Insert a box");
81 connect(insertBoxButton, SIGNAL(clicked()), this, SLOT(insertBox()));
83 connect(insertBoxButton, SIGNAL(clicked()), this, SLOT(insertBox()));
82 grid->addWidget(insertBoxButton, rowPos++, 1);
84 grid->addWidget(insertBoxButton, rowPos++, 1);
83
85
84 // Create add a single box button
86 // Create add a single box button
85 QPushButton *removeBoxButton = new QPushButton("Remove a box");
87 QPushButton *removeBoxButton = new QPushButton("Remove a box");
86 connect(removeBoxButton, SIGNAL(clicked()), this, SLOT(removeBox()));
88 connect(removeBoxButton, SIGNAL(clicked()), this, SLOT(removeBox()));
87 grid->addWidget(removeBoxButton, rowPos++, 1);
89 grid->addWidget(removeBoxButton, rowPos++, 1);
88
90
89 // Create clear button
91 // Create clear button
90 QPushButton *clearButton = new QPushButton("Clear");
92 QPushButton *clearButton = new QPushButton("Clear");
91 connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
93 connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
92 grid->addWidget(clearButton, rowPos++, 1);
94 grid->addWidget(clearButton, rowPos++, 1);
93
95
94 // Create clear button
96 // Create clear button
95 QPushButton *clearBoxButton = new QPushButton("ClearBox");
97 QPushButton *clearBoxButton = new QPushButton("ClearBox");
96 connect(clearBoxButton, SIGNAL(clicked()), this, SLOT(clearBox()));
98 connect(clearBoxButton, SIGNAL(clicked()), this, SLOT(clearBox()));
97 grid->addWidget(clearBoxButton, rowPos++, 1);
99 grid->addWidget(clearBoxButton, rowPos++, 1);
98
100
99
101
100 // Create set brush button
102 // Create set brush button
101 QPushButton *setBrushButton = new QPushButton("Set brush");
103 QPushButton *setBrushButton = new QPushButton("Set brush");
102 connect(setBrushButton, SIGNAL(clicked()), this, SLOT(setBrush()));
104 connect(setBrushButton, SIGNAL(clicked()), this, SLOT(setBrush()));
103 grid->addWidget(setBrushButton, rowPos++, 1);
105 grid->addWidget(setBrushButton, rowPos++, 1);
104
106
105 initThemeCombo(grid);
107 initThemeCombo(grid);
106 initCheckboxes(grid);
108 initCheckboxes(grid);
107
109
108 m_model = new CustomTableModel;
110 m_model = new CustomTableModel;
109 QTableView *tableView = new QTableView;
111 QTableView *tableView = new QTableView;
110 tableView->setModel(m_model);
112 tableView->setModel(m_model);
111 tableView->setMaximumWidth(200);
113 tableView->setMaximumWidth(200);
112 grid->addWidget(tableView, rowPos++, 0, 3, 2, Qt::AlignLeft);
114 grid->addWidget(tableView, rowPos++, 0, 3, 2, Qt::AlignLeft);
113 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
115 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
114 tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
116 tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
115 tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
117 tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
116 #else
118 #else
117 tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
119 tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
118 tableView->verticalHeader()->setResizeMode(QHeaderView::Stretch);
120 tableView->verticalHeader()->setResizeMode(QHeaderView::Stretch);
119 #endif
121 #endif
120
122
121 // add row with empty label to make all the other rows static
123 // add row with empty label to make all the other rows static
122 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
124 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
123 grid->setRowStretch(grid->rowCount() - 1, 1);
125 grid->setRowStretch(grid->rowCount() - 1, 1);
124
126
125 // Create chart view with the chart
127 // Create chart view with the chart
126 m_chartView = new QChartView(m_chart, this);
128 m_chartView = new QChartView(m_chart, this);
127 //m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
128
129
129 // Another grid layout as a main layout
130 // Another grid layout as a main layout
130 QGridLayout *mainLayout = new QGridLayout();
131 QGridLayout *mainLayout = new QGridLayout();
131 mainLayout->addLayout(grid, 0, 0);
132 mainLayout->addLayout(grid, 0, 0);
132 mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
133 mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
133 setLayout(mainLayout);
134 setLayout(mainLayout);
134
135
135 legendToggled(false);
136 legendToggled(false);
136 animationToggled(false);
137 animationToggled(false);
137 }
138 }
138
139
139 // Combo box for selecting theme
140 // Combo box for selecting theme
140 void MainWidget::initThemeCombo(QGridLayout *grid)
141 void MainWidget::initThemeCombo(QGridLayout *grid)
141 {
142 {
142 QComboBox *chartTheme = new QComboBox();
143 QComboBox *chartTheme = new QComboBox();
143 chartTheme->addItem("Default");
144 chartTheme->addItem("Default");
144 chartTheme->addItem("Light");
145 chartTheme->addItem("Light");
145 chartTheme->addItem("Blue Cerulean");
146 chartTheme->addItem("Blue Cerulean");
146 chartTheme->addItem("Dark");
147 chartTheme->addItem("Dark");
147 chartTheme->addItem("Brown Sand");
148 chartTheme->addItem("Brown Sand");
148 chartTheme->addItem("Blue NCS");
149 chartTheme->addItem("Blue NCS");
149 chartTheme->addItem("High Contrast");
150 chartTheme->addItem("High Contrast");
150 chartTheme->addItem("Blue Icy");
151 chartTheme->addItem("Blue Icy");
151 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
152 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
152 this, SLOT(changeChartTheme(int)));
153 this, SLOT(changeChartTheme(int)));
153 grid->addWidget(new QLabel("Chart theme:"), rowPos, 0);
154 grid->addWidget(new QLabel("Chart theme:"), rowPos, 0);
154 grid->addWidget(chartTheme, rowPos++, 1);
155 grid->addWidget(chartTheme, rowPos++, 1);
155 }
156 }
156
157
157 // Different check boxes for customizing chart
158 // Different check boxes for customizing chart
158 void MainWidget::initCheckboxes(QGridLayout *grid)
159 void MainWidget::initCheckboxes(QGridLayout *grid)
159 {
160 {
160 QCheckBox *animationCheckBox = new QCheckBox("Animation");
161 QCheckBox *animationCheckBox = new QCheckBox("Animation");
161 connect(animationCheckBox, SIGNAL(toggled(bool)), this, SLOT(animationToggled(bool)));
162 connect(animationCheckBox, SIGNAL(toggled(bool)), this, SLOT(animationToggled(bool)));
162 animationCheckBox->setChecked(false);
163 animationCheckBox->setChecked(false);
163 grid->addWidget(animationCheckBox, rowPos++, 0);
164 grid->addWidget(animationCheckBox, rowPos++, 0);
164
165
165 QCheckBox *legendCheckBox = new QCheckBox("Legend");
166 QCheckBox *legendCheckBox = new QCheckBox("Legend");
166 connect(legendCheckBox, SIGNAL(toggled(bool)), this, SLOT(legendToggled(bool)));
167 connect(legendCheckBox, SIGNAL(toggled(bool)), this, SLOT(legendToggled(bool)));
167 legendCheckBox->setChecked(false);
168 legendCheckBox->setChecked(false);
168 grid->addWidget(legendCheckBox, rowPos++, 0);
169 grid->addWidget(legendCheckBox, rowPos++, 0);
169
170
170 QCheckBox *titleCheckBox = new QCheckBox("Title");
171 QCheckBox *titleCheckBox = new QCheckBox("Title");
171 connect(titleCheckBox, SIGNAL(toggled(bool)), this, SLOT(titleToggled(bool)));
172 connect(titleCheckBox, SIGNAL(toggled(bool)), this, SLOT(titleToggled(bool)));
172 titleCheckBox->setChecked(false);
173 titleCheckBox->setChecked(false);
173 grid->addWidget(titleCheckBox, rowPos++, 0);
174 grid->addWidget(titleCheckBox, rowPos++, 0);
174
175
175 QCheckBox *modelMapperCheckBox = new QCheckBox("Use model mapper");
176 QCheckBox *modelMapperCheckBox = new QCheckBox("Use model mapper");
176 connect(modelMapperCheckBox, SIGNAL(toggled(bool)), this, SLOT(modelMapperToggled(bool)));
177 connect(modelMapperCheckBox, SIGNAL(toggled(bool)), this, SLOT(modelMapperToggled(bool)));
177 modelMapperCheckBox->setChecked(false);
178 modelMapperCheckBox->setChecked(false);
178 grid->addWidget(modelMapperCheckBox, rowPos++, 0);
179 grid->addWidget(modelMapperCheckBox, rowPos++, 0);
179
180
180 }
181 }
181
182
182 void MainWidget::addSeries()
183 void MainWidget::addSeries()
183 {
184 {
184 qDebug() << "BoxPlotTester::MainWidget::addSeries()";
185 qDebug() << "BoxPlotTester::MainWidget::addSeries()";
185
186
186 if (nSeries > 9)
187 if (nSeries > 9)
187 return;
188 return;
188
189
189 // Initial data
190 // Initial data
190 //![1]
191 QBoxSet *set0 = new QBoxSet();
191 QBoxSet *set0 = new QBoxSet();
192 QBoxSet *set1 = new QBoxSet();
192 QBoxSet *set1 = new QBoxSet();
193 QBoxSet *set2 = new QBoxSet();
193 QBoxSet *set2 = new QBoxSet();
194 QBoxSet *set3 = new QBoxSet();
194 QBoxSet *set3 = new QBoxSet();
195 QBoxSet *set4 = new QBoxSet();
195 QBoxSet *set4 = new QBoxSet();
196 QBoxSet *set5 = new QBoxSet();
196 QBoxSet *set5 = new QBoxSet();
197
197
198 // low bot med top upp
198 // low bot med top upp
199 *set0 << 1 << 2 << 4.4 << 13 << 15;
199 *set0 << -1 << 2 << 4 << 13 << 15;
200 *set1 << 5 << 6 << 7.5 << 8 << 12;
200 *set1 << 5 << 6 << 7.5 << 8 << 12;
201 *set2 << 3 << 5 << 5.7 << 8 << 9;
201 *set2 << 3 << 5 << 5.7 << 8 << 9;
202 *set3 << 5 << 6 << 6.8 << 7 << 8;
202 *set3 << 5 << 6 << 6.8 << 7 << 8;
203 *set4 << 4 << 5 << 5.2 << 6 << 7;
203 *set4 << 4 << 5 << 5.2 << 6 << 7;
204 *set5 << 4 << 7 << 8.2 << 9 << 10;
204 *set5 << 4 << 7 << 8.2 << 9 << 10;
205
205
206 m_series[nSeries] = new QBoxPlotSeries();
206 m_series[nSeries] = new QBoxPlotSeries();
207 m_series[nSeries]->append(set0);
207 m_series[nSeries]->append(set0);
208 m_series[nSeries]->append(set1);
208 m_series[nSeries]->append(set1);
209 m_series[nSeries]->append(set2);
209 m_series[nSeries]->append(set2);
210 m_series[nSeries]->append(set3);
210 m_series[nSeries]->append(set3);
211 m_series[nSeries]->append(set4);
211 m_series[nSeries]->append(set4);
212 m_series[nSeries]->append(set5);
212 m_series[nSeries]->append(set5);
213 m_series[nSeries]->setName("Box & Whiskers");
213 m_series[nSeries]->setName("Box & Whiskers");
214
214
215 connect(m_series[nSeries], SIGNAL(clicked(QBoxSet*)), this, SLOT(boxClicked(QBoxSet*)));
215 connect(m_series[nSeries], SIGNAL(clicked(QBoxSet*)), this, SLOT(boxClicked(QBoxSet*)));
216 connect(m_series[nSeries], SIGNAL(hovered(bool, QBoxSet*)), this, SLOT(boxHovered(bool, QBoxSet*)));
216 connect(m_series[nSeries], SIGNAL(hovered(bool, QBoxSet*)), this, SLOT(boxHovered(bool, QBoxSet*)));
217 connect(set1, SIGNAL(clicked()), this, SLOT(singleBoxClicked()));
217 connect(set1, SIGNAL(clicked()), this, SLOT(singleBoxClicked()));
218 connect(set2, SIGNAL(hovered(bool)), this, SLOT(singleBoxHovered(bool)));
218 connect(set2, SIGNAL(hovered(bool)), this, SLOT(singleBoxHovered(bool)));
219
219
220 m_chart->addSeries(m_series[nSeries]);
220 m_chart->addSeries(m_series[nSeries]);
221
221
222 if (nSeries == 0) {
222 if (!m_axis) {
223 QStringList categories;
223 QStringList categories;
224 categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
224 categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
225 m_axis = new QBarCategoryAxis();
225 m_axis = new QBarCategoryAxis();
226 m_axis->append(categories);
226 m_axis->append(categories);
227 m_chart->createDefaultAxes();
227 m_chart->createDefaultAxes();
228 m_chart->setAxisX(m_axis, m_series[nSeries]);
229 }
228 }
229 m_chart->setAxisX(m_axis, m_series[nSeries]);
230
230
231 nSeries++;
231 nSeries++;
232 }
232 }
233
233
234 void MainWidget::removeSeries()
234 void MainWidget::removeSeries()
235 {
235 {
236 qDebug() << "BoxPlotTester::MainWidget::removeSeries()";
236 qDebug() << "BoxPlotTester::MainWidget::removeSeries()";
237
237
238 if (nSeries > 0) {
238 if (nSeries > 0) {
239 nSeries--;
239 nSeries--;
240 m_chart->removeSeries(m_series[nSeries]);
240 m_chart->removeSeries(m_series[nSeries]);
241 delete m_series[nSeries];
241 delete m_series[nSeries];
242 } else {
242 } else {
243 qDebug() << "Create a series first";
243 qDebug() << "Create a series first";
244 }
244 }
245 }
245 }
246
246
247 void MainWidget::addBox()
247 void MainWidget::addBox()
248 {
248 {
249 qDebug() << "BoxPlotTester::MainWidget::addBox()";
249 qDebug() << "BoxPlotTester::MainWidget::addBox()";
250
250
251 if (nSeries > 0) {
251 if (nSeries > 0 && nNewBoxes < maxAddCategories) {
252 QBoxSet *newSet = new QBoxSet();
252 QBoxSet *newSet = new QBoxSet();
253 newSet->setValue(QBoxSet::LowerExtreme, 5.0);
253 newSet->setValue(QBoxSet::LowerExtreme, 5.0);
254 newSet->setValue(QBoxSet::LowerQuartile, 6.0);
254 newSet->setValue(QBoxSet::LowerQuartile, 6.0);
255 newSet->setValue(QBoxSet::Median, 6.8);
255 newSet->setValue(QBoxSet::Median, 6.8);
256 newSet->setValue(QBoxSet::UpperQuartile, 7.0);
256 newSet->setValue(QBoxSet::UpperQuartile, 7.0);
257 newSet->setValue(QBoxSet::UpperExtreme, 8.0);
257 newSet->setValue(QBoxSet::UpperExtreme, 8.0);
258
258
259 for (int i = 0; i < nSeries; i++)
259 m_series[0]->append(newSet);
260 m_series[i]->append(newSet);
261
260
262 m_axis->append(addCategories[nNewBoxes]);
261 m_axis->append(addCategories[nNewBoxes]);
263
262
264 nNewBoxes++;
263 nNewBoxes++;
265 }
264 }
266 }
265 }
267
266
268 void MainWidget::insertBox()
267 void MainWidget::insertBox()
269 {
268 {
270 qDebug() << "BoxPlotTester::MainWidget::insertBox()";
269 qDebug() << "BoxPlotTester::MainWidget::insertBox()";
271
270
272 if (nSeries > 0) {
271 if (nSeries > 0) {
273 QBoxSet *newSet = new QBoxSet();
272 QBoxSet *newSet = new QBoxSet();
274 *newSet << 2 << 6 << 6.8 << 7 << 10;
273 *newSet << 2 << 6 << 6.8 << 7 << 10;
275
274
276 for (int i = 0; i < nSeries; i++)
275 for (int i = 0; i < nSeries; i++)
277 m_series[i]->insert(1, newSet);
276 m_series[i]->insert(1, newSet);
278
277
279 m_axis->append(addCategories[nNewBoxes]);
278 m_axis->append(addCategories[nNewBoxes]);
280
279
281 nNewBoxes++;
280 nNewBoxes++;
282 }
281 }
283 }
282 }
284
283
285 void MainWidget::removeBox()
284 void MainWidget::removeBox()
286 {
285 {
287 qDebug() << "BoxPlotTester::MainWidget::removeBox";
286 qDebug() << "BoxPlotTester::MainWidget::removeBox";
288
287
289 if (nSeries > 0) {
288 if (nSeries > 0) {
290 for (int i = 0; i < nSeries; i++) {
289 for (int i = 0; i < nSeries; i++) {
291 QList<QBoxSet *> sets = m_series[i]->boxSets();
290 qDebug() << "m_series[i]->count() = " << m_series[i]->count();
292 m_series[i]->remove(sets.at(m_series[i]->count() - 3));
291 if (m_series[i]->count() > 3) {
292 QList<QBoxSet *> sets = m_series[i]->boxSets();
293 m_series[i]->remove(sets.at(m_series[i]->count() - 3));
294 }
293 }
295 }
294
296
295 m_axis->remove(m_axis->at(1));
297 if (m_axis->count() > 3)
298 m_axis->remove(m_axis->at(1));
296 } else {
299 } else {
297 qDebug() << "Create a series first";
300 qDebug() << "Create a series first";
298 }
301 }
299 }
302 }
300
303
301 void MainWidget::clear()
304 void MainWidget::clear()
302 {
305 {
303 qDebug() << "BoxPlotTester::MainWidget::clear";
306 qDebug() << "BoxPlotTester::MainWidget::clear";
304
307
305 if (nSeries > 0)
308 if (nSeries > 0)
306 m_series[0]->clear();
309 m_series[0]->clear();
307 else
310 else
308 qDebug() << "Create a series first";
311 qDebug() << "Create a series first";
309 }
312 }
310
313
311 void MainWidget::clearBox()
314 void MainWidget::clearBox()
312 {
315 {
313 qDebug() << "BoxPlotTester::MainWidget::clearBox";
316 qDebug() << "BoxPlotTester::MainWidget::clearBox";
314
317
315 if (nSeries > 0) {
318 if (nSeries > 0) {
316 QList<QBoxSet *> sets = m_series[0]->boxSets();
319 QList<QBoxSet *> sets = m_series[0]->boxSets();
317 sets.at(1)->clear();
320 sets.at(1)->clear();
318 } else {
321 } else {
319 qDebug() << "Create a series first";
322 qDebug() << "Create a series first";
320 }
323 }
321 }
324 }
322
325
323 void MainWidget::setBrush()
326 void MainWidget::setBrush()
324 {
327 {
325 qDebug() << "BoxPlotTester::MainWidget::setBrush";
328 qDebug() << "BoxPlotTester::MainWidget::setBrush";
326
329
327 if (nSeries > 0) {
330 if (nSeries > 0) {
328 QList<QBoxSet *> sets = m_series[0]->boxSets();
331 QList<QBoxSet *> sets = m_series[0]->boxSets();
329 sets.at(1)->setBrush(QBrush(QColor(Qt::yellow)));
332 sets.at(1)->setBrush(QBrush(QColor(Qt::yellow)));
330 } else {
333 } else {
331 qDebug() << "Create a series first";
334 qDebug() << "Create a series first";
332 }
335 }
333 }
336 }
334
337
335 void MainWidget::animationToggled(bool enabled)
338 void MainWidget::animationToggled(bool enabled)
336 {
339 {
337 qDebug() << "BoxPlotTester::Animation toggled to " << enabled;
340 qDebug() << "BoxPlotTester::Animation toggled to " << enabled;
338 if (enabled)
341 if (enabled)
339 m_chart->setAnimationOptions(QChart::SeriesAnimations);
342 m_chart->setAnimationOptions(QChart::SeriesAnimations);
340 else
343 else
341 m_chart->setAnimationOptions(QChart::NoAnimation);
344 m_chart->setAnimationOptions(QChart::NoAnimation);
342 }
345 }
343
346
344 void MainWidget::legendToggled(bool enabled)
347 void MainWidget::legendToggled(bool enabled)
345 {
348 {
346 qDebug() << "BoxPlotTester::Legend toggled to " << enabled;
349 qDebug() << "BoxPlotTester::Legend toggled to " << enabled;
347 m_chart->legend()->setVisible(enabled);
350 m_chart->legend()->setVisible(enabled);
348 if (enabled)
351 if (enabled)
349 m_chart->legend()->setAlignment(Qt::AlignBottom);
352 m_chart->legend()->setAlignment(Qt::AlignBottom);
350 }
353 }
351
354
352 void MainWidget::titleToggled(bool enabled)
355 void MainWidget::titleToggled(bool enabled)
353 {
356 {
354 qDebug() << "BoxPlotTester::Title toggled to " << enabled;
357 qDebug() << "BoxPlotTester::Title toggled to " << enabled;
355 if (enabled)
358 if (enabled)
356 m_chart->setTitle("Simple boxplotchart example");
359 m_chart->setTitle("Simple boxplotchart example");
357 else
360 else
358 m_chart->setTitle("");
361 m_chart->setTitle("");
359 }
362 }
360
363
361 void MainWidget::modelMapperToggled(bool enabled)
364 void MainWidget::modelMapperToggled(bool enabled)
362 {
365 {
363 if (enabled) {
366 if (enabled) {
364 m_series[nSeries] = new QBoxPlotSeries();
367 m_series[nSeries] = new QBoxPlotSeries();
365
368
366 int first = 0;
369 int first = 0;
367 int count = 5;
370 int count = 5;
368 QVBoxPlotModelMapper *mapper = new QVBoxPlotModelMapper(this);
371 QVBoxPlotModelMapper *mapper = new QVBoxPlotModelMapper(this);
369 mapper->setFirstBoxSetColumn(0);
372 mapper->setFirstBoxSetColumn(0);
370 mapper->setLastBoxSetColumn(5);
373 mapper->setLastBoxSetColumn(5);
371 mapper->setFirstRow(first);
374 mapper->setFirstRow(first);
372 mapper->setRowCount(count);
375 mapper->setRowCount(count);
373 mapper->setSeries(m_series[nSeries]);
376 mapper->setSeries(m_series[nSeries]);
374 mapper->setModel(m_model);
377 mapper->setModel(m_model);
375 m_chart->addSeries(m_series[nSeries]);
378 m_chart->addSeries(m_series[nSeries]);
376
379
377 nSeries++;
380 nSeries++;
378 } else {
381 } else {
379 removeSeries();
382 removeSeries();
380 }
383 }
381 }
384 }
382
385
383 void MainWidget::changeChartTheme(int themeIndex)
386 void MainWidget::changeChartTheme(int themeIndex)
384 {
387 {
385 qDebug() << "BoxPlotTester::changeChartTheme: " << themeIndex;
388 qDebug() << "BoxPlotTester::changeChartTheme: " << themeIndex;
386 if (themeIndex == 0)
389 if (themeIndex == 0)
387 m_chart->setTheme(QChart::ChartThemeLight);
390 m_chart->setTheme(QChart::ChartThemeLight);
388 else
391 else
389 m_chart->setTheme((QChart::ChartTheme) (themeIndex - 1));
392 m_chart->setTheme((QChart::ChartTheme) (themeIndex - 1));
390 }
393 }
391
394
392 void MainWidget::boxClicked(QBoxSet *set)
395 void MainWidget::boxClicked(QBoxSet *set)
393 {
396 {
394 qDebug() << "boxClicked, median = " << set->at(QBoxSet::Median);
397 qDebug() << "boxClicked, median = " << set->at(QBoxSet::Median);
395 }
398 }
396
399
397 void MainWidget::boxHovered(bool state, QBoxSet *set)
400 void MainWidget::boxHovered(bool state, QBoxSet *set)
398 {
401 {
399 if (state)
402 if (state)
400 qDebug() << "box median " << set->at(QBoxSet::Median) << " hover started";
403 qDebug() << "box median " << set->at(QBoxSet::Median) << " hover started";
401 else
404 else
402 qDebug() << "box median " << set->at(QBoxSet::Median) << " hover ended";
405 qDebug() << "box median " << set->at(QBoxSet::Median) << " hover ended";
403 }
406 }
404
407
405 void MainWidget::singleBoxClicked()
408 void MainWidget::singleBoxClicked()
406 {
409 {
407 qDebug() << "singleBoxClicked";
410 qDebug() << "singleBoxClicked";
408 }
411 }
409
412
410 void MainWidget::singleBoxHovered(bool state)
413 void MainWidget::singleBoxHovered(bool state)
411 {
414 {
412 if (state)
415 if (state)
413 qDebug() << "single box hover started";
416 qDebug() << "single box hover started";
414 else
417 else
415 qDebug() << "single box hover ended";
418 qDebug() << "single box hover ended";
416 }
419 }
General Comments 0
You need to be logged in to leave comments. Login now