##// END OF EJS Templates
Z order for pie
Tero Ahola -
r490:5facde66eb08
parent child
Show More
@@ -1,21 +1,22
1 TEMPLATE = subdirs
1 TEMPLATE = subdirs
2 SUBDIRS += linechart \
2 SUBDIRS += linechart \
3 zoomlinechart \
3 zoomlinechart \
4 colorlinechart \
4 colorlinechart \
5 barchart \
5 barchart \
6 stackedbarchart \
6 stackedbarchart \
7 percentbarchart \
7 percentbarchart \
8 scatterchart \
8 scatterchart \
9 piechart \
9 piechart \
10 piechartcustomization \
10 piechartcustomization \
11 piechartdrilldown \
11 piechartdrilldown \
12 dynamiclinechart \
12 dynamiclinechart \
13 axischart \
13 axischart \
14 multichart \
14 multichart \
15 gdpbarchart \
15 gdpbarchart \
16 presenterchart \
16 presenterchart \
17 chartview \
17 chartview \
18 scatterinteractions \
18 scatterinteractions \
19 splinechart \
19 splinechart \
20 areachart \
20 areachart \
21 stackedbarchartdrilldown
21 stackedbarchartdrilldown \
22 customcolors
@@ -1,81 +1,82
1 #ifndef CHARTPRESENTER_H_
1 #ifndef CHARTPRESENTER_H_
2 #define CHARTPRESENTER_H_
2 #define CHARTPRESENTER_H_
3
3
4 #include "qchartglobal.h"
4 #include "qchartglobal.h"
5 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
5 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
6 #include "qchartaxis.h"
6 #include "qchartaxis.h"
7 #include <QRectF>
7 #include <QRectF>
8
8
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10
10
11 class ChartItem;
11 class ChartItem;
12 class QSeries;
12 class QSeries;
13 class ChartDataSet;
13 class ChartDataSet;
14 //class QChart;
14 //class QChart;
15 class Domain;
15 class Domain;
16 class AxisItem;
16 class AxisItem;
17 class ChartTheme;
17 class ChartTheme;
18
18
19 class ChartPresenter: public QObject
19 class ChartPresenter: public QObject
20 {
20 {
21 Q_OBJECT
21 Q_OBJECT
22 public:
22 public:
23 enum ZValues {
23 enum ZValues {
24 BackgroundZValue = -1,
24 BackgroundZValue = -1,
25 ShadesZValue,
25 ShadesZValue,
26 GridZValue,
26 GridZValue,
27 AxisZValue,
27 AxisZValue,
28 LineChartZValue,
28 LineChartZValue,
29 ScatterSeriesZValue
29 ScatterSeriesZValue,
30 PieSeriesZValue
30 };
31 };
31
32
32 ChartPresenter(QChart* chart,ChartDataSet *dataset);
33 ChartPresenter(QChart* chart,ChartDataSet *dataset);
33 virtual ~ChartPresenter();
34 virtual ~ChartPresenter();
34
35
35 void setMargin(int margin);
36 void setMargin(int margin);
36 int margin() const;
37 int margin() const;
37
38
38 QRectF geometry() const;
39 QRectF geometry() const;
39
40
40 void setChartTheme(QChart::ChartTheme theme);
41 void setChartTheme(QChart::ChartTheme theme);
41 QChart::ChartTheme chartTheme();
42 QChart::ChartTheme chartTheme();
42
43
43 void setAnimationOptions(QChart::AnimationOptions options);
44 void setAnimationOptions(QChart::AnimationOptions options);
44 QChart::AnimationOptions animationOptions() const;
45 QChart::AnimationOptions animationOptions() const;
45
46
46 void zoomIn();
47 void zoomIn();
47 void zoomIn(const QRectF& rect);
48 void zoomIn(const QRectF& rect);
48 void zoomOut();
49 void zoomOut();
49 void zoomReset();
50 void zoomReset();
50
51
51
52
52 private:
53 private:
53 void createConnections();
54 void createConnections();
54
55
55 public slots:
56 public slots:
56 void handleSeriesAdded(QSeries* series,Domain* domain);
57 void handleSeriesAdded(QSeries* series,Domain* domain);
57 void handleSeriesRemoved(QSeries* series);
58 void handleSeriesRemoved(QSeries* series);
58 void handleAxisAdded(QChartAxis* axis,Domain* domain);
59 void handleAxisAdded(QChartAxis* axis,Domain* domain);
59 void handleAxisRemoved(QChartAxis* axis);
60 void handleAxisRemoved(QChartAxis* axis);
60 void handleGeometryChanged();
61 void handleGeometryChanged();
61
62
62 signals:
63 signals:
63 void geometryChanged(const QRectF& rect);
64 void geometryChanged(const QRectF& rect);
64
65
65 private:
66 private:
66 QChart* m_chart;
67 QChart* m_chart;
67 ChartDataSet* m_dataset;
68 ChartDataSet* m_dataset;
68 ChartTheme *m_chartTheme;
69 ChartTheme *m_chartTheme;
69 int m_zoomIndex;
70 int m_zoomIndex;
70 int m_marginSize;
71 int m_marginSize;
71 QMap<QSeries*,ChartItem*> m_chartItems;
72 QMap<QSeries*,ChartItem*> m_chartItems;
72 QMap<QChartAxis*,AxisItem*> m_axisItems;
73 QMap<QChartAxis*,AxisItem*> m_axisItems;
73 QVector<QRectF> m_zoomStack;
74 QVector<QRectF> m_zoomStack;
74 QRectF m_rect;
75 QRectF m_rect;
75 QChart::AnimationOptions m_options;
76 QChart::AnimationOptions m_options;
76
77
77 };
78 };
78
79
79 QTCOMMERCIALCHART_END_NAMESPACE
80 QTCOMMERCIALCHART_END_NAMESPACE
80
81
81 #endif /* CHARTPRESENTER_H_ */
82 #endif /* CHARTPRESENTER_H_ */
@@ -1,154 +1,158
1 #include "piepresenter_p.h"
1 #include "piepresenter_p.h"
2 #include "pieslice_p.h"
2 #include "pieslice_p.h"
3 #include "qpieslice.h"
3 #include "qpieslice.h"
4 #include "qpieseries.h"
4 #include "qpieseries.h"
5 #include "chartpresenter_p.h"
5 #include <QDebug>
6 #include <QDebug>
6 #include <QPainter>
7 #include <QPainter>
7
8
8
9
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10
11
11 PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series)
12 PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series)
12 :ChartItem(parent),
13 :ChartItem(parent),
13 m_series(series)
14 m_series(series)
14 {
15 {
15 Q_ASSERT(series);
16 Q_ASSERT(series);
16 connect(series, SIGNAL(changed(const QPieSeries::ChangeSet&)), this, SLOT(handleSeriesChanged(const QPieSeries::ChangeSet&)));
17 connect(series, SIGNAL(changed(const QPieSeries::ChangeSet&)), this, SLOT(handleSeriesChanged(const QPieSeries::ChangeSet&)));
17 connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry()));
18 connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry()));
18 connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry()));
19 connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry()));
19
20
20 if (m_series->count()) {
21 if (m_series->count()) {
21 QPieSeries::ChangeSet changeSet;
22 QPieSeries::ChangeSet changeSet;
22 changeSet.appendAdded(m_series->m_slices);
23 changeSet.appendAdded(m_series->m_slices);
23 handleSeriesChanged(changeSet);
24 handleSeriesChanged(changeSet);
24 }
25 }
26
27 // Note: the following does not affect as long as the item does not have anything to paint
28 setZValue(ChartPresenter::PieSeriesZValue);
25 }
29 }
26
30
27 PiePresenter::~PiePresenter()
31 PiePresenter::~PiePresenter()
28 {
32 {
29 // slices deleted automatically through QGraphicsItem
33 // slices deleted automatically through QGraphicsItem
30 }
34 }
31
35
32 void PiePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
36 void PiePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
33 {
37 {
34 // TODO: paint shadows for all components
38 // TODO: paint shadows for all components
35 // - get paths from items & merge & offset and draw with shadow color?
39 // - get paths from items & merge & offset and draw with shadow color?
36 //painter->setBrush(QBrush(Qt::red));
40 //painter->setBrush(QBrush(Qt::red));
37 //painter->drawRect(m_debugRect);
41 //painter->drawRect(m_debugRect);
38 }
42 }
39
43
40 void PiePresenter::handleSeriesChanged(const QPieSeries::ChangeSet& changeSet)
44 void PiePresenter::handleSeriesChanged(const QPieSeries::ChangeSet& changeSet)
41 {
45 {
42 //qDebug() << "PiePresenter::handleSeriesChanged()";
46 //qDebug() << "PiePresenter::handleSeriesChanged()";
43 //qDebug() << " added : " << changeSet.added();
47 //qDebug() << " added : " << changeSet.added();
44 //qDebug() << " changed: " << changeSet.changed();
48 //qDebug() << " changed: " << changeSet.changed();
45 //qDebug() << " removed: " << changeSet.removed();
49 //qDebug() << " removed: " << changeSet.removed();
46
50
47 foreach (QPieSlice* s, changeSet.added())
51 foreach (QPieSlice* s, changeSet.added())
48 addSlice(s);
52 addSlice(s);
49
53
50 foreach (QPieSlice* s, changeSet.changed())
54 foreach (QPieSlice* s, changeSet.changed())
51 updateSlice(s);
55 updateSlice(s);
52
56
53 foreach (QPieSlice* s, changeSet.removed())
57 foreach (QPieSlice* s, changeSet.removed())
54 deleteSlice(s);
58 deleteSlice(s);
55
59
56 // every change possibly changes the actual pie size
60 // every change possibly changes the actual pie size
57 updateGeometry();
61 updateGeometry();
58 }
62 }
59
63
60 void PiePresenter::handleDomainChanged(const Domain& domain)
64 void PiePresenter::handleDomainChanged(const Domain& domain)
61 {
65 {
62 // TODO
66 // TODO
63 }
67 }
64
68
65 void PiePresenter::handleGeometryChanged(const QRectF& rect)
69 void PiePresenter::handleGeometryChanged(const QRectF& rect)
66 {
70 {
67 m_rect = rect;
71 m_rect = rect;
68 prepareGeometryChange();
72 prepareGeometryChange();
69 updateGeometry();
73 updateGeometry();
70 }
74 }
71
75
72 void PiePresenter::updateGeometry()
76 void PiePresenter::updateGeometry()
73 {
77 {
74 if (!m_rect.isValid() || m_rect.isEmpty())
78 if (!m_rect.isValid() || m_rect.isEmpty())
75 return;
79 return;
76
80
77 // find pie center coordinates
81 // find pie center coordinates
78 QPointF center;
82 QPointF center;
79 center.setX(m_rect.left() + (m_rect.width() * m_series->m_hPositionFactor));
83 center.setX(m_rect.left() + (m_rect.width() * m_series->m_hPositionFactor));
80 center.setY(m_rect.top() + (m_rect.height() * m_series->m_vPositionFactor));
84 center.setY(m_rect.top() + (m_rect.height() * m_series->m_vPositionFactor));
81
85
82 // find maximum radius for pie
86 // find maximum radius for pie
83 qreal radius = m_rect.height() / 2;
87 qreal radius = m_rect.height() / 2;
84 if (m_rect.width() < m_rect.height())
88 if (m_rect.width() < m_rect.height())
85 radius = m_rect.width() / 2;
89 radius = m_rect.width() / 2;
86
90
87 // apply size factor
91 // apply size factor
88 radius *= m_series->m_pieSizeFactor;
92 radius *= m_series->m_pieSizeFactor;
89
93
90 // update slices
94 // update slices
91 if (m_pieCenter != center || m_pieRadius != radius) {
95 if (m_pieCenter != center || m_pieRadius != radius) {
92 m_pieCenter = center;
96 m_pieCenter = center;
93 m_pieRadius = radius;
97 m_pieRadius = radius;
94 //qDebug() << "PiePresenter::updateGeometry()" << m_rect << m_pieCenter << m_pieRadius;
98 //qDebug() << "PiePresenter::updateGeometry()" << m_rect << m_pieCenter << m_pieRadius;
95 foreach (PieSlice* s, m_slices.values()) {
99 foreach (PieSlice* s, m_slices.values()) {
96 s->setPieCenterAndRadius(center, radius);
100 s->setPieCenterAndRadius(center, radius);
97 s->updateGeometry();
101 s->updateGeometry();
98 s->update();
102 s->update();
99 }
103 }
100 }
104 }
101
105
102 update();
106 update();
103 }
107 }
104
108
105 void PiePresenter::addSlice(QPieSlice* sliceData)
109 void PiePresenter::addSlice(QPieSlice* sliceData)
106 {
110 {
107 //qDebug() << "PiePresenter::addSlice()" << sliceData;
111 //qDebug() << "PiePresenter::addSlice()" << sliceData;
108
112
109 if (m_slices.keys().contains(sliceData)) {
113 if (m_slices.keys().contains(sliceData)) {
110 Q_ASSERT(0); // TODO: how to handle this nicely?
114 Q_ASSERT(0); // TODO: how to handle this nicely?
111 return;
115 return;
112 }
116 }
113
117
114 // create slice
118 // create slice
115 PieSlice *slice = new PieSlice(this);
119 PieSlice *slice = new PieSlice(this);
116 slice->setPieCenterAndRadius(m_pieCenter, m_pieRadius);
120 slice->setPieCenterAndRadius(m_pieCenter, m_pieRadius);
117 slice->updateData(sliceData);
121 slice->updateData(sliceData);
118 slice->updateGeometry();
122 slice->updateGeometry();
119 slice->update();
123 slice->update();
120 m_slices.insert(sliceData, slice);
124 m_slices.insert(sliceData, slice);
121
125
122 // connect signals
126 // connect signals
123 connect(slice, SIGNAL(clicked()), sliceData, SIGNAL(clicked()));
127 connect(slice, SIGNAL(clicked()), sliceData, SIGNAL(clicked()));
124 connect(slice, SIGNAL(hoverEnter()), sliceData, SIGNAL(hoverEnter()));
128 connect(slice, SIGNAL(hoverEnter()), sliceData, SIGNAL(hoverEnter()));
125 connect(slice, SIGNAL(hoverLeave()), sliceData, SIGNAL(hoverLeave()));
129 connect(slice, SIGNAL(hoverLeave()), sliceData, SIGNAL(hoverLeave()));
126 }
130 }
127
131
128 void PiePresenter::updateSlice(QPieSlice* sliceData)
132 void PiePresenter::updateSlice(QPieSlice* sliceData)
129 {
133 {
130 //qDebug() << "PiePresenter::updateSlice()" << sliceData;
134 //qDebug() << "PiePresenter::updateSlice()" << sliceData;
131
135
132 if (!m_slices.contains(sliceData)) {
136 if (!m_slices.contains(sliceData)) {
133 Q_ASSERT(0); // TODO: how to handle this nicely?
137 Q_ASSERT(0); // TODO: how to handle this nicely?
134 return;
138 return;
135 }
139 }
136
140
137 m_slices[sliceData]->updateData(sliceData);
141 m_slices[sliceData]->updateData(sliceData);
138 }
142 }
139
143
140 void PiePresenter::deleteSlice(QPieSlice* sliceData)
144 void PiePresenter::deleteSlice(QPieSlice* sliceData)
141 {
145 {
142 //qDebug() << "PiePresenter::deleteSlice()" << sliceData;
146 //qDebug() << "PiePresenter::deleteSlice()" << sliceData;
143
147
144 if (!m_slices.contains(sliceData)) {
148 if (!m_slices.contains(sliceData)) {
145 Q_ASSERT(0); // TODO: how to handle this nicely?
149 Q_ASSERT(0); // TODO: how to handle this nicely?
146 return;
150 return;
147 }
151 }
148
152
149 delete m_slices.take(sliceData);
153 delete m_slices.take(sliceData);
150 }
154 }
151
155
152 #include "moc_piepresenter_p.cpp"
156 #include "moc_piepresenter_p.cpp"
153
157
154 QTCOMMERCIALCHART_END_NAMESPACE
158 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,208 +1,210
1 #include "pieslice_p.h"
1 #include "pieslice_p.h"
2 #include "piepresenter_p.h"
2 #include "piepresenter_p.h"
3 #include "qpieseries.h"
3 #include "qpieseries.h"
4 #include "qpieslice.h"
4 #include "qpieslice.h"
5 #include "chartpresenter_p.h"
5 #include <QPainter>
6 #include <QPainter>
6 #include <QDebug>
7 #include <QDebug>
7 #include <qmath.h>
8 #include <qmath.h>
8 #include <QGraphicsSceneEvent>
9 #include <QGraphicsSceneEvent>
9 #include <QTime>
10 #include <QTime>
10
11
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12
13
13 #define PI 3.14159265 // TODO: is this defined in some header?
14 #define PI 3.14159265 // TODO: is this defined in some header?
14
15
15 QPointF offset(qreal angle, qreal length)
16 QPointF offset(qreal angle, qreal length)
16 {
17 {
17 qreal dx = qSin(angle*(PI/180)) * length;
18 qreal dx = qSin(angle*(PI/180)) * length;
18 qreal dy = qCos(angle*(PI/180)) * length;
19 qreal dy = qCos(angle*(PI/180)) * length;
19 return QPointF(dx, -dy);
20 return QPointF(dx, -dy);
20 }
21 }
21
22
22 PieSlice::PieSlice(QGraphicsItem* parent)
23 PieSlice::PieSlice(QGraphicsItem* parent)
23 :QGraphicsObject(parent),
24 :QGraphicsObject(parent),
24 m_pieRadius(0),
25 m_pieRadius(0),
25 m_startAngle(0),
26 m_startAngle(0),
26 m_angleSpan(0),
27 m_angleSpan(0),
27 m_isExploded(false),
28 m_isExploded(false),
28 m_explodeDistanceFactor(0),
29 m_explodeDistanceFactor(0),
29 m_labelVisible(false),
30 m_labelVisible(false),
30 m_labelArmLengthFactor(0)
31 m_labelArmLengthFactor(0)
31 {
32 {
32 setAcceptHoverEvents(true);
33 setAcceptHoverEvents(true);
33 setAcceptedMouseButtons(Qt::LeftButton);
34 setAcceptedMouseButtons(Qt::LeftButton);
35 setZValue(ChartPresenter::PieSeriesZValue);
34 }
36 }
35
37
36 PieSlice::~PieSlice()
38 PieSlice::~PieSlice()
37 {
39 {
38
40
39 }
41 }
40
42
41 QRectF PieSlice::boundingRect() const
43 QRectF PieSlice::boundingRect() const
42 {
44 {
43 return m_slicePath.boundingRect();
45 return m_slicePath.boundingRect();
44 }
46 }
45
47
46 QPainterPath PieSlice::shape() const
48 QPainterPath PieSlice::shape() const
47 {
49 {
48 // Don't include the label and label arm.
50 // Don't include the label and label arm.
49 // This is used to detect a mouse clicks. We do not want clicks from label.
51 // This is used to detect a mouse clicks. We do not want clicks from label.
50 return m_slicePath;
52 return m_slicePath;
51 }
53 }
52
54
53 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
55 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
54 {
56 {
55 painter->setClipRect(parentItem()->boundingRect());
57 painter->setClipRect(parentItem()->boundingRect());
56
58
57 painter->save();
59 painter->save();
58 painter->setPen(m_slicePen);
60 painter->setPen(m_slicePen);
59 painter->setBrush(m_sliceBrush);
61 painter->setBrush(m_sliceBrush);
60 painter->drawPath(m_slicePath);
62 painter->drawPath(m_slicePath);
61 painter->restore();
63 painter->restore();
62
64
63 if (m_labelVisible) {
65 if (m_labelVisible) {
64 painter->save();
66 painter->save();
65 painter->setPen(m_labelArmPen);
67 painter->setPen(m_labelArmPen);
66 painter->drawPath(m_labelArmPath);
68 painter->drawPath(m_labelArmPath);
67 painter->restore();
69 painter->restore();
68
70
69 painter->setFont(m_labelFont);
71 painter->setFont(m_labelFont);
70 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
72 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
71 }
73 }
72 }
74 }
73
75
74 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
76 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
75 {
77 {
76 emit hoverEnter();
78 emit hoverEnter();
77 }
79 }
78
80
79 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
81 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
80 {
82 {
81 emit hoverLeave();
83 emit hoverLeave();
82 }
84 }
83
85
84 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
86 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
85 {
87 {
86 emit clicked();
88 emit clicked();
87 }
89 }
88
90
89 void PieSlice::setPieCenterAndRadius(QPointF center, qreal radius)
91 void PieSlice::setPieCenterAndRadius(QPointF center, qreal radius)
90 {
92 {
91 m_pieCenter = center;
93 m_pieCenter = center;
92 m_pieRadius = radius;
94 m_pieRadius = radius;
93 }
95 }
94
96
95 void PieSlice::updateGeometry()
97 void PieSlice::updateGeometry()
96 {
98 {
97 if (m_pieRadius <= 0)
99 if (m_pieRadius <= 0)
98 return;
100 return;
99
101
100 prepareGeometryChange();
102 prepareGeometryChange();
101
103
102 // update slice path
104 // update slice path
103 qreal centerAngle;
105 qreal centerAngle;
104 QPointF armStart;
106 QPointF armStart;
105 m_slicePath = slicePath(m_pieCenter, m_pieRadius, m_startAngle, m_angleSpan, m_isExploded, m_pieRadius * m_explodeDistanceFactor, &centerAngle, &armStart);
107 m_slicePath = slicePath(m_pieCenter, m_pieRadius, m_startAngle, m_angleSpan, m_isExploded, m_pieRadius * m_explodeDistanceFactor, &centerAngle, &armStart);
106
108
107 // update text rect
109 // update text rect
108 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
110 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
109
111
110 // update label arm path
112 // update label arm path
111 QPointF labelTextStart;
113 QPointF labelTextStart;
112 m_labelArmPath = labelArmPath(armStart, centerAngle, m_pieRadius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
114 m_labelArmPath = labelArmPath(armStart, centerAngle, m_pieRadius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
113
115
114 // update text position
116 // update text position
115 m_labelTextRect.moveBottomLeft(labelTextStart);
117 m_labelTextRect.moveBottomLeft(labelTextStart);
116
118
117 //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan;
119 //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan;
118 }
120 }
119
121
120 void PieSlice::updateData(const QPieSlice* sliceData)
122 void PieSlice::updateData(const QPieSlice* sliceData)
121 {
123 {
122 // TODO: compare what has changes to avoid unneccesary geometry updates
124 // TODO: compare what has changes to avoid unneccesary geometry updates
123
125
124 m_startAngle = sliceData->startAngle();
126 m_startAngle = sliceData->startAngle();
125 m_angleSpan = sliceData->m_angleSpan;
127 m_angleSpan = sliceData->m_angleSpan;
126 m_isExploded = sliceData->isExploded();
128 m_isExploded = sliceData->isExploded();
127 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
129 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
128 m_slicePen = sliceData->slicePen();
130 m_slicePen = sliceData->slicePen();
129 m_sliceBrush = sliceData->sliceBrush();
131 m_sliceBrush = sliceData->sliceBrush();
130
132
131 m_labelVisible = sliceData->isLabelVisible();
133 m_labelVisible = sliceData->isLabelVisible();
132 m_labelText = sliceData->label();
134 m_labelText = sliceData->label();
133 m_labelFont = sliceData->labelFont();
135 m_labelFont = sliceData->labelFont();
134 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
136 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
135 m_labelArmPen = sliceData->labelArmPen();
137 m_labelArmPen = sliceData->labelArmPen();
136
138
137 updateGeometry();
139 updateGeometry();
138 update();
140 update();
139 }
141 }
140
142
141 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, bool exploded, qreal explodeDistance, qreal* centerAngle, QPointF* armStart)
143 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, bool exploded, qreal explodeDistance, qreal* centerAngle, QPointF* armStart)
142 {
144 {
143 // calculate center angle
145 // calculate center angle
144 *centerAngle = startAngle + (angleSpan/2);
146 *centerAngle = startAngle + (angleSpan/2);
145
147
146 // calculate slice rectangle
148 // calculate slice rectangle
147 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
149 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
148
150
149 // adjust rect for exploding
151 // adjust rect for exploding
150 if (exploded) {
152 if (exploded) {
151 qreal dx = qSin(*centerAngle*(PI/180)) * explodeDistance;
153 qreal dx = qSin(*centerAngle*(PI/180)) * explodeDistance;
152 qreal dy = -qCos(*centerAngle*(PI/180)) * explodeDistance;
154 qreal dy = -qCos(*centerAngle*(PI/180)) * explodeDistance;
153 rect.translate(dx, dy);
155 rect.translate(dx, dy);
154 }
156 }
155
157
156 // slice path
158 // slice path
157 // TODO: draw the shape so that it might have a hole in the center
159 // TODO: draw the shape so that it might have a hole in the center
158 QPainterPath path;
160 QPainterPath path;
159 path.moveTo(rect.center());
161 path.moveTo(rect.center());
160 path.arcTo(rect, -startAngle + 90, -angleSpan);
162 path.arcTo(rect, -startAngle + 90, -angleSpan);
161 path.closeSubpath();
163 path.closeSubpath();
162
164
163 // calculate label arm start point
165 // calculate label arm start point
164 *armStart = center;
166 *armStart = center;
165 if (exploded)
167 if (exploded)
166 *armStart += offset(*centerAngle, explodeDistance + radius + PIESLICE_LABEL_GAP);
168 *armStart += offset(*centerAngle, explodeDistance + radius + PIESLICE_LABEL_GAP);
167 else
169 else
168 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
170 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
169
171
170 return path;
172 return path;
171 }
173 }
172
174
173 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
175 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
174 {
176 {
175 qreal dx = qSin(angle*(PI/180)) * length;
177 qreal dx = qSin(angle*(PI/180)) * length;
176 qreal dy = -qCos(angle*(PI/180)) * length;
178 qreal dy = -qCos(angle*(PI/180)) * length;
177 QPointF parm1 = start + QPointF(dx, dy);
179 QPointF parm1 = start + QPointF(dx, dy);
178
180
179 QPointF parm2 = parm1;
181 QPointF parm2 = parm1;
180 if (angle < 180) { // arm swings the other way on the left side
182 if (angle < 180) { // arm swings the other way on the left side
181 parm2 += QPointF(textWidth, 0);
183 parm2 += QPointF(textWidth, 0);
182 *textStart = parm1;
184 *textStart = parm1;
183 }
185 }
184 else {
186 else {
185 parm2 += QPointF(-textWidth,0);
187 parm2 += QPointF(-textWidth,0);
186 *textStart = parm2;
188 *textStart = parm2;
187 }
189 }
188
190
189 // elevate the text position a bit so that it does not hit the line
191 // elevate the text position a bit so that it does not hit the line
190 *textStart += QPointF(0, -5);
192 *textStart += QPointF(0, -5);
191
193
192 QPainterPath path;
194 QPainterPath path;
193 path.moveTo(start);
195 path.moveTo(start);
194 path.lineTo(parm1);
196 path.lineTo(parm1);
195 path.lineTo(parm2);
197 path.lineTo(parm2);
196
198
197 return path;
199 return path;
198 }
200 }
199
201
200 QRectF PieSlice::labelTextRect(QFont font, QString text)
202 QRectF PieSlice::labelTextRect(QFont font, QString text)
201 {
203 {
202 QFontMetricsF fm(font);
204 QFontMetricsF fm(font);
203 return fm.boundingRect(text);
205 return fm.boundingRect(text);
204 }
206 }
205
207
206 #include "moc_pieslice_p.cpp"
208 #include "moc_pieslice_p.cpp"
207
209
208 QTCOMMERCIALCHART_END_NAMESPACE
210 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now