@@ -0,0 +1,76 | |||||
|
1 | #include "pieslicelabel.h" | |||
|
2 | #include <QPainter> | |||
|
3 | #include <qmath.h> | |||
|
4 | ||||
|
5 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
6 | ||||
|
7 | #define PI 3.14159265 | |||
|
8 | ||||
|
9 | PieSliceLabel::PieSliceLabel(QGraphicsItem* parent) | |||
|
10 | :QGraphicsItem(parent) | |||
|
11 | { | |||
|
12 | m_pen = QPen(Qt::black); | |||
|
13 | } | |||
|
14 | ||||
|
15 | PieSliceLabel::~PieSliceLabel() | |||
|
16 | { | |||
|
17 | ||||
|
18 | } | |||
|
19 | ||||
|
20 | QRectF PieSliceLabel::boundingRect() const | |||
|
21 | { | |||
|
22 | return m_rect; | |||
|
23 | } | |||
|
24 | ||||
|
25 | QPainterPath PieSliceLabel::shape() const | |||
|
26 | { | |||
|
27 | return m_path; | |||
|
28 | } | |||
|
29 | ||||
|
30 | void PieSliceLabel::paint(QPainter *painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) | |||
|
31 | { | |||
|
32 | painter->setRenderHint(QPainter::Antialiasing); | |||
|
33 | painter->setPen(m_pen); | |||
|
34 | painter->drawPath(m_path); | |||
|
35 | } | |||
|
36 | ||||
|
37 | void PieSliceLabel::updateGeometry(const QPointF& startPoint, qreal armAngle, qreal armLength) | |||
|
38 | { | |||
|
39 | prepareGeometryChange(); | |||
|
40 | ||||
|
41 | QPainterPath path; | |||
|
42 | path.moveTo(startPoint); | |||
|
43 | ||||
|
44 | // draw arm | |||
|
45 | qreal dx = qSin(armAngle*(PI/180)) * armLength; | |||
|
46 | qreal dy = -qCos(armAngle*(PI/180)) * armLength; | |||
|
47 | QPointF p1 = startPoint + QPointF(dx, dy); | |||
|
48 | path.lineTo(p1); | |||
|
49 | ||||
|
50 | QPointF p2 = p1; | |||
|
51 | QPointF pt = p1; | |||
|
52 | if (armAngle < 180) { | |||
|
53 | p2 += QPointF(50, 0); | |||
|
54 | } else { | |||
|
55 | p2 += QPointF(-50,0); | |||
|
56 | pt = p2; | |||
|
57 | } | |||
|
58 | path.lineTo(p2); | |||
|
59 | ||||
|
60 | QFont font; | |||
|
61 | pt += QPointF(0,-2); | |||
|
62 | path.addText(pt, font, m_label); | |||
|
63 | ||||
|
64 | m_path = path; | |||
|
65 | m_rect = path.boundingRect(); | |||
|
66 | } | |||
|
67 | ||||
|
68 | void PieSliceLabel::setLabel(QString label) | |||
|
69 | { | |||
|
70 | m_label = label; | |||
|
71 | // TODO: animation? | |||
|
72 | } | |||
|
73 | ||||
|
74 | ||||
|
75 | ||||
|
76 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -0,0 +1,36 | |||||
|
1 | #ifndef PIELABEL_H | |||
|
2 | #define PIELABEL_H | |||
|
3 | ||||
|
4 | #include "qchartglobal.h" | |||
|
5 | #include <QGraphicsItem> | |||
|
6 | #include <QPen> | |||
|
7 | ||||
|
8 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
9 | ||||
|
10 | class PieSliceLabel : public QGraphicsItem | |||
|
11 | { | |||
|
12 | public: | |||
|
13 | PieSliceLabel(QGraphicsItem* parent = 0); | |||
|
14 | ~PieSliceLabel(); | |||
|
15 | ||||
|
16 | public: // from QGraphicsItem | |||
|
17 | QRectF boundingRect() const; | |||
|
18 | QPainterPath shape() const; | |||
|
19 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); | |||
|
20 | ||||
|
21 | public: | |||
|
22 | void updateGeometry(const QPointF& startPoint, qreal armAngle, qreal armLength); | |||
|
23 | void setLabel(QString label); | |||
|
24 | QString label() const {return m_label;} | |||
|
25 | void setPen(QPen pen); | |||
|
26 | ||||
|
27 | private: | |||
|
28 | QString m_label; | |||
|
29 | QPainterPath m_path; | |||
|
30 | QRectF m_rect; | |||
|
31 | QPen m_pen; | |||
|
32 | }; | |||
|
33 | ||||
|
34 | QTCOMMERCIALCHART_END_NAMESPACE | |||
|
35 | ||||
|
36 | #endif // PIELABEL_H |
@@ -1,33 +1,33 | |||||
1 | #include <QtGui/QApplication> |
|
1 | #include <QtGui/QApplication> | |
2 | #include <QMainWindow> |
|
2 | #include <QMainWindow> | |
3 | #include <cmath> |
|
3 | #include <cmath> | |
4 | #include <qchartglobal.h> |
|
4 | #include <qchartglobal.h> | |
5 | #include <qchartview.h> |
|
5 | #include <qchartview.h> | |
6 | #include <qpieseries.h> |
|
6 | #include <qpieseries.h> | |
7 |
|
7 | |||
8 | QTCOMMERCIALCHART_USE_NAMESPACE |
|
8 | QTCOMMERCIALCHART_USE_NAMESPACE | |
9 |
|
9 | |||
10 | int main(int argc, char *argv[]) |
|
10 | int main(int argc, char *argv[]) | |
11 | { |
|
11 | { | |
12 | QApplication a(argc, argv); |
|
12 | QApplication a(argc, argv); | |
13 |
|
13 | |||
14 | // Create widget and scatter series |
|
14 | // Create widget and scatter series | |
15 | QChartView *chartWidget = new QChartView(); |
|
15 | QChartView *chartWidget = new QChartView(); | |
16 | QPieSeries *series = qobject_cast<QPieSeries *>(chartWidget->createSeries(QChartSeries::SeriesTypePie)); |
|
16 | QPieSeries *series = qobject_cast<QPieSeries *>(chartWidget->createSeries(QChartSeries::SeriesTypePie)); | |
17 | Q_ASSERT(series); |
|
17 | Q_ASSERT(series); | |
18 |
|
18 | |||
19 | // Add test data to the series |
|
19 | // Add test data to the series | |
20 |
series->add(QPieSlice(1, "test1", Qt::red, tr |
|
20 | series->add(QPieSlice(1, "test1", true, true, QPen(Qt::red, 2), QBrush(Qt::red))); | |
21 |
series->add(QPieSlice(2, "test2" |
|
21 | series->add(QPieSlice(2, "test2")); | |
22 |
series->add(QPieSlice(3, "test3" |
|
22 | series->add(QPieSlice(3, "test3")); | |
23 |
series->add(QPieSlice(4, "test4" |
|
23 | series->add(QPieSlice(4, "test4")); | |
24 |
series->add(QPieSlice(5, "test5" |
|
24 | series->add(QPieSlice(5, "test5")); | |
25 |
|
25 | |||
26 | // Use the chart widget as the central widget |
|
26 | // Use the chart widget as the central widget | |
27 | QMainWindow w; |
|
27 | QMainWindow w; | |
28 | w.resize(640, 480); |
|
28 | w.resize(640, 480); | |
29 | w.setCentralWidget(chartWidget); |
|
29 | w.setCentralWidget(chartWidget); | |
30 | w.show(); |
|
30 | w.show(); | |
31 |
|
31 | |||
32 | return a.exec(); |
|
32 | return a.exec(); | |
33 | } |
|
33 | } |
@@ -1,212 +1,210 | |||||
1 | #include "charttheme_p.h" |
|
1 | #include "charttheme_p.h" | |
2 | #include "qchart.h" |
|
2 | #include "qchart.h" | |
3 |
|
3 | |||
4 |
|
4 | |||
5 | //series |
|
5 | //series | |
6 | #include "barchartseries.h" |
|
6 | #include "barchartseries.h" | |
7 | #include "stackedbarchartseries.h" |
|
7 | #include "stackedbarchartseries.h" | |
8 | #include "percentbarchartseries.h" |
|
8 | #include "percentbarchartseries.h" | |
9 | #include "qlinechartseries.h" |
|
9 | #include "qlinechartseries.h" | |
10 | #include "qpieseries.h" |
|
10 | #include "qpieseries.h" | |
11 |
|
11 | |||
12 | //items |
|
12 | //items | |
13 | #include "axisitem_p.h" |
|
13 | #include "axisitem_p.h" | |
14 | #include "bargroup.h" |
|
14 | #include "bargroup.h" | |
15 | #include "stackedbargroup.h" |
|
15 | #include "stackedbargroup.h" | |
16 | #include "linechartitem_p.h" |
|
16 | #include "linechartitem_p.h" | |
17 | #include "percentbargroup.h" |
|
17 | #include "percentbargroup.h" | |
18 | #include "piepresenter.h" |
|
18 | #include "piepresenter.h" | |
19 |
|
19 | |||
20 | //themes |
|
20 | //themes | |
21 | #include "chartthemevanilla_p.h" |
|
21 | #include "chartthemevanilla_p.h" | |
22 | #include "chartthemeicy_p.h" |
|
22 | #include "chartthemeicy_p.h" | |
23 | #include "chartthemegrayscale_p.h" |
|
23 | #include "chartthemegrayscale_p.h" | |
24 | #include "chartthemescientific_p.h" |
|
24 | #include "chartthemescientific_p.h" | |
25 |
|
25 | |||
26 |
|
26 | |||
27 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
27 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
28 |
|
28 | |||
29 | /* TODO |
|
29 | /* TODO | |
30 | case QChart::ChartThemeUnnamed1: |
|
30 | case QChart::ChartThemeUnnamed1: | |
31 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff3fa9f5)), 2)); |
|
31 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff3fa9f5)), 2)); | |
32 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff7AC943)), 2)); |
|
32 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xff7AC943)), 2)); | |
33 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF931E)), 2)); |
|
33 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF931E)), 2)); | |
34 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF1D25)), 2)); |
|
34 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF1D25)), 2)); | |
35 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF7BAC)), 2)); |
|
35 | m_seriesThemes.append(SeriesTheme(QColor(QRgb(0xffFF7BAC)), 2)); | |
36 |
|
36 | |||
37 | m_gradientStartColor = QColor(QRgb(0xfff3dc9e)); |
|
37 | m_gradientStartColor = QColor(QRgb(0xfff3dc9e)); | |
38 | m_gradientEndColor = QColor(QRgb(0xffafafaf)); |
|
38 | m_gradientEndColor = QColor(QRgb(0xffafafaf)); | |
39 | */ |
|
39 | */ | |
40 |
|
40 | |||
41 | ChartTheme::ChartTheme(QChart::ChartTheme id) |
|
41 | ChartTheme::ChartTheme(QChart::ChartTheme id) | |
42 | { |
|
42 | { | |
43 | m_id = id; |
|
43 | m_id = id; | |
44 | m_seriesColor.append(QRgb(0xff000000)); |
|
44 | m_seriesColor.append(QRgb(0xff000000)); | |
45 | m_seriesColor.append(QRgb(0xff707070)); |
|
45 | m_seriesColor.append(QRgb(0xff707070)); | |
46 | m_gradientStartColor = QColor(QRgb(0xffffffff)); |
|
46 | m_gradientStartColor = QColor(QRgb(0xffffffff)); | |
47 | m_gradientEndColor = QColor(QRgb(0xffafafaf)); |
|
47 | m_gradientEndColor = QColor(QRgb(0xffafafaf)); | |
48 | } |
|
48 | } | |
49 |
|
49 | |||
50 |
|
50 | |||
51 | ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme) |
|
51 | ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme) | |
52 | { |
|
52 | { | |
53 | switch(theme) { |
|
53 | switch(theme) { | |
54 | case QChart::ChartThemeDefault: |
|
54 | case QChart::ChartThemeDefault: | |
55 | return new ChartTheme(); |
|
55 | return new ChartTheme(); | |
56 | case QChart::ChartThemeVanilla: |
|
56 | case QChart::ChartThemeVanilla: | |
57 | return new ChartThemeVanilla(); |
|
57 | return new ChartThemeVanilla(); | |
58 | case QChart::ChartThemeIcy: |
|
58 | case QChart::ChartThemeIcy: | |
59 | return new ChartThemeIcy(); |
|
59 | return new ChartThemeIcy(); | |
60 | case QChart::ChartThemeGrayscale: |
|
60 | case QChart::ChartThemeGrayscale: | |
61 | return new ChartThemeGrayscale(); |
|
61 | return new ChartThemeGrayscale(); | |
62 | case QChart::ChartThemeScientific: |
|
62 | case QChart::ChartThemeScientific: | |
63 | return new ChartThemeScientific(); |
|
63 | return new ChartThemeScientific(); | |
64 | } |
|
64 | } | |
65 | } |
|
65 | } | |
66 |
|
66 | |||
67 | void ChartTheme::decorate(QChart* chart) |
|
67 | void ChartTheme::decorate(QChart* chart) | |
68 | { |
|
68 | { | |
69 | QLinearGradient backgroundGradient; |
|
69 | QLinearGradient backgroundGradient; | |
70 | backgroundGradient.setColorAt(0.0, m_gradientStartColor); |
|
70 | backgroundGradient.setColorAt(0.0, m_gradientStartColor); | |
71 | backgroundGradient.setColorAt(1.0, m_gradientEndColor); |
|
71 | backgroundGradient.setColorAt(1.0, m_gradientEndColor); | |
72 | backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode); |
|
72 | backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode); | |
73 | chart->setChartBackgroundBrush(backgroundGradient); |
|
73 | chart->setChartBackgroundBrush(backgroundGradient); | |
74 | } |
|
74 | } | |
75 | //TODO helper to by removed later |
|
75 | //TODO helper to by removed later | |
76 | void ChartTheme::decorate(ChartItem* item, QChartSeries* series,int count) |
|
76 | void ChartTheme::decorate(ChartItem* item, QChartSeries* series,int count) | |
77 | { |
|
77 | { | |
78 | switch(series->type()) |
|
78 | switch(series->type()) | |
79 | { |
|
79 | { | |
80 | case QChartSeries::SeriesTypeLine: { |
|
80 | case QChartSeries::SeriesTypeLine: { | |
81 | QLineChartSeries* s = static_cast<QLineChartSeries*>(series); |
|
81 | QLineChartSeries* s = static_cast<QLineChartSeries*>(series); | |
82 | LineChartItem* i = static_cast<LineChartItem*>(item); |
|
82 | LineChartItem* i = static_cast<LineChartItem*>(item); | |
83 | decorate(i,s,count); |
|
83 | decorate(i,s,count); | |
84 | break; |
|
84 | break; | |
85 | } |
|
85 | } | |
86 | case QChartSeries::SeriesTypeBar: { |
|
86 | case QChartSeries::SeriesTypeBar: { | |
87 | BarChartSeries* b = static_cast<BarChartSeries*>(series); |
|
87 | BarChartSeries* b = static_cast<BarChartSeries*>(series); | |
88 | BarGroup* i = static_cast<BarGroup*>(item); |
|
88 | BarGroup* i = static_cast<BarGroup*>(item); | |
89 | decorate(i,b,count); |
|
89 | decorate(i,b,count); | |
90 | break; |
|
90 | break; | |
91 | } |
|
91 | } | |
92 | case QChartSeries::SeriesTypeStackedBar: { |
|
92 | case QChartSeries::SeriesTypeStackedBar: { | |
93 | StackedBarChartSeries* s = static_cast<StackedBarChartSeries*>(series); |
|
93 | StackedBarChartSeries* s = static_cast<StackedBarChartSeries*>(series); | |
94 | StackedBarGroup* i = static_cast<StackedBarGroup*>(item); |
|
94 | StackedBarGroup* i = static_cast<StackedBarGroup*>(item); | |
95 | decorate(i,s,count); |
|
95 | decorate(i,s,count); | |
96 | break; |
|
96 | break; | |
97 | } |
|
97 | } | |
98 | case QChartSeries::SeriesTypePercentBar: { |
|
98 | case QChartSeries::SeriesTypePercentBar: { | |
99 | PercentBarChartSeries* s = static_cast<PercentBarChartSeries*>(series); |
|
99 | PercentBarChartSeries* s = static_cast<PercentBarChartSeries*>(series); | |
100 | PercentBarGroup* i = static_cast<PercentBarGroup*>(item); |
|
100 | PercentBarGroup* i = static_cast<PercentBarGroup*>(item); | |
101 | decorate(i,s,count); |
|
101 | decorate(i,s,count); | |
102 | break; |
|
102 | break; | |
103 | } |
|
103 | } | |
104 | case QChartSeries::SeriesTypePie: { |
|
104 | case QChartSeries::SeriesTypePie: { | |
105 | QPieSeries* s = static_cast<QPieSeries*>(series); |
|
105 | QPieSeries* s = static_cast<QPieSeries*>(series); | |
106 | PiePresenter* i = static_cast<PiePresenter*>(item); |
|
106 | PiePresenter* i = static_cast<PiePresenter*>(item); | |
107 | decorate(i,s,count); |
|
107 | decorate(i,s,count); | |
108 | break; |
|
108 | break; | |
109 | } |
|
109 | } | |
110 | default: |
|
110 | default: | |
111 | qDebug()<<"Wrong item to be decorated by theme"; |
|
111 | qDebug()<<"Wrong item to be decorated by theme"; | |
112 | break; |
|
112 | break; | |
113 | } |
|
113 | } | |
114 |
|
114 | |||
115 | } |
|
115 | } | |
116 |
|
116 | |||
117 | void ChartTheme::decorate(LineChartItem* item, QLineChartSeries* series,int count) |
|
117 | void ChartTheme::decorate(LineChartItem* item, QLineChartSeries* series,int count) | |
118 | { |
|
118 | { | |
119 | QPen pen; |
|
119 | QPen pen; | |
120 | if(pen != series->pen()){ |
|
120 | if(pen != series->pen()){ | |
121 | item->setPen(series->pen()); |
|
121 | item->setPen(series->pen()); | |
122 | return; |
|
122 | return; | |
123 | } |
|
123 | } | |
124 | pen.setColor(m_seriesColor.at(count%m_seriesColor.size())); |
|
124 | pen.setColor(m_seriesColor.at(count%m_seriesColor.size())); | |
125 | pen.setWidthF(2); |
|
125 | pen.setWidthF(2); | |
126 | item->setPen(pen); |
|
126 | item->setPen(pen); | |
127 | } |
|
127 | } | |
128 |
|
128 | |||
129 | void ChartTheme::decorate(BarGroup* item, BarChartSeries* series,int count) |
|
129 | void ChartTheme::decorate(BarGroup* item, BarChartSeries* series,int count) | |
130 | { |
|
130 | { | |
131 | item->resetColors(); |
|
131 | item->resetColors(); | |
132 | for (int i=0; i<m_seriesColor.count(); i++) { |
|
132 | for (int i=0; i<m_seriesColor.count(); i++) { | |
133 | item->addColor(m_seriesColor.at(i)); |
|
133 | item->addColor(m_seriesColor.at(i)); | |
134 | } |
|
134 | } | |
135 | item->addColor(QColor(255,0,0,128)); |
|
135 | item->addColor(QColor(255,0,0,128)); | |
136 | item->addColor(QColor(255,255,0,128)); |
|
136 | item->addColor(QColor(255,255,0,128)); | |
137 | item->addColor(QColor(0,255,0,128)); |
|
137 | item->addColor(QColor(0,255,0,128)); | |
138 | item->addColor(QColor(0,0,255,128)); |
|
138 | item->addColor(QColor(0,0,255,128)); | |
139 | item->addColor(QColor(255,128,0,128)); |
|
139 | item->addColor(QColor(255,128,0,128)); | |
140 | } |
|
140 | } | |
141 |
|
141 | |||
142 | void ChartTheme::decorate(StackedBarGroup* item, StackedBarChartSeries* series,int count) |
|
142 | void ChartTheme::decorate(StackedBarGroup* item, StackedBarChartSeries* series,int count) | |
143 | { |
|
143 | { | |
144 | item->resetColors(); |
|
144 | item->resetColors(); | |
145 | for (int i=0; i< m_seriesColor.count(); i++) { |
|
145 | for (int i=0; i< m_seriesColor.count(); i++) { | |
146 | item->addColor(m_seriesColor.at(i)); |
|
146 | item->addColor(m_seriesColor.at(i)); | |
147 | } |
|
147 | } | |
148 | item->addColor(QColor(255,0,0,128)); |
|
148 | item->addColor(QColor(255,0,0,128)); | |
149 | item->addColor(QColor(255,255,0,128)); |
|
149 | item->addColor(QColor(255,255,0,128)); | |
150 | item->addColor(QColor(0,255,0,128)); |
|
150 | item->addColor(QColor(0,255,0,128)); | |
151 | item->addColor(QColor(0,0,255,128)); |
|
151 | item->addColor(QColor(0,0,255,128)); | |
152 | item->addColor(QColor(255,128,0,128)); |
|
152 | item->addColor(QColor(255,128,0,128)); | |
153 | } |
|
153 | } | |
154 |
|
154 | |||
155 | void ChartTheme::decorate(PercentBarGroup* item, PercentBarChartSeries* series,int count) |
|
155 | void ChartTheme::decorate(PercentBarGroup* item, PercentBarChartSeries* series,int count) | |
156 | { |
|
156 | { | |
157 | item->resetColors(); |
|
157 | item->resetColors(); | |
158 | for (int i=0; i< m_seriesColor.count(); i++) { |
|
158 | for (int i=0; i< m_seriesColor.count(); i++) { | |
159 | item->addColor(m_seriesColor.at(i)); |
|
159 | item->addColor(m_seriesColor.at(i)); | |
160 | } |
|
160 | } | |
161 | item->addColor(QColor(255,0,0,128)); |
|
161 | item->addColor(QColor(255,0,0,128)); | |
162 | item->addColor(QColor(255,255,0,128)); |
|
162 | item->addColor(QColor(255,255,0,128)); | |
163 | item->addColor(QColor(0,255,0,128)); |
|
163 | item->addColor(QColor(0,255,0,128)); | |
164 | item->addColor(QColor(0,0,255,128)); |
|
164 | item->addColor(QColor(0,0,255,128)); | |
165 | item->addColor(QColor(255,128,0,128)); |
|
165 | item->addColor(QColor(255,128,0,128)); | |
166 | } |
|
166 | } | |
167 |
|
167 | |||
168 | void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int /*count*/) |
|
168 | void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int /*count*/) | |
169 | { |
|
169 | { | |
170 | // create a list of slice colors based on current theme |
|
170 | // create a list of slice colors based on current theme | |
171 | int i = 0; |
|
171 | int i = 0; | |
172 | QList<QColor> colors; |
|
172 | QList<QColor> colors; | |
173 | while (colors.count() < series->count()) { |
|
173 | while (colors.count() < series->count()) { | |
174 |
|
174 | |||
175 | // get base color |
|
175 | // get base color | |
176 | QColor c = m_seriesColor[i++]; |
|
176 | QColor c = m_seriesColor[i++]; | |
177 | i = i % m_seriesColor.count(); |
|
177 | i = i % m_seriesColor.count(); | |
178 |
|
178 | |||
179 | // -1 means achromatic color -> cannot manipulate lightness |
|
179 | // -1 means achromatic color -> cannot manipulate lightness | |
180 | // TODO: find a better way to randomize lightness |
|
180 | // TODO: find a better way to randomize lightness | |
181 | if (c.toHsv().hue() == -1) |
|
181 | if (c.toHsv().hue() == -1) | |
182 | qWarning() << "ChartTheme::decorate() warning: achromatic theme color"; |
|
182 | qWarning() << "ChartTheme::decorate() warning: achromatic theme color"; | |
183 |
|
183 | |||
184 | // randomize lightness |
|
184 | // randomize lightness | |
185 | qreal f = 50 + (qrand() % 100); // 50 is 50% darker, 100 is the same, 150 is 50% lighter |
|
185 | qreal f = 50 + (qrand() % 100); // 50 is 50% darker, 100 is the same, 150 is 50% lighter | |
186 | c = c.lighter(f); |
|
186 | c = c.lighter(f); | |
187 |
|
187 | |||
188 | // find duplicates |
|
188 | // find duplicates | |
189 | bool isUnique = true; |
|
189 | bool isUnique = true; | |
190 | foreach (QColor color, colors) { |
|
190 | foreach (QColor color, colors) { | |
191 | if (c == color) |
|
191 | if (c == color) | |
192 | isUnique = false; |
|
192 | isUnique = false; | |
193 | } |
|
193 | } | |
194 |
|
194 | |||
195 | // add to array if unique |
|
195 | // add to array if unique | |
196 | //if (isUnique) |
|
196 | //if (isUnique) | |
197 | colors << c; |
|
197 | colors << c; | |
198 | } |
|
198 | } | |
199 |
|
199 | |||
200 | // finally update colors |
|
200 | // finally update colors | |
201 | QList<QPieSlice> slices; |
|
201 | foreach (QPieSliceId id, series->ids()) { | |
202 | for (int i=0; i<series->count(); i++) { |
|
202 | QPieSlice s = series->slice(id); | |
203 | QPieSlice slice = series->slice(i); |
|
203 | s.setPen(QPen(Qt::black)); // TODO: get from theme | |
204 |
s |
|
204 | s.setBrush(colors.takeFirst()); | |
205 | slices << slice; |
|
205 | series->update(s); | |
206 | } |
|
206 | } | |
207 |
|
||||
208 | series->set(slices); |
|
|||
209 | } |
|
207 | } | |
210 |
|
208 | |||
211 |
|
209 | |||
212 | QTCOMMERCIALCHART_END_NAMESPACE |
|
210 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,14 +1,16 | |||||
1 | INCLUDEPATH += $$PWD |
|
1 | INCLUDEPATH += $$PWD | |
2 | DEPENDPATH += $$PWD |
|
2 | DEPENDPATH += $$PWD | |
3 |
|
3 | |||
4 | SOURCES += \ |
|
4 | SOURCES += \ | |
5 | $$PWD/qpieseries.cpp \ |
|
5 | $$PWD/qpieseries.cpp \ | |
6 | $$PWD/pieslice.cpp \ |
|
6 | $$PWD/pieslice.cpp \ | |
7 | $$PWD/piepresenter.cpp |
|
7 | $$PWD/piepresenter.cpp \ | |
|
8 | $$PWD/pieslicelabel.cpp | |||
8 |
|
9 | |||
9 | PRIVATE_HEADERS += \ |
|
10 | PRIVATE_HEADERS += \ | |
10 | $$PWD/piepresenter.h \ |
|
11 | $$PWD/piepresenter.h \ | |
11 | $$PWD/pieslice.h |
|
12 | $$PWD/pieslice.h \ | |
|
13 | $$PWD/pieslicelabel.h | |||
12 |
|
14 | |||
13 | PUBLIC_HEADERS += \ |
|
15 | PUBLIC_HEADERS += \ | |
14 | $$PWD/qpieseries.h |
|
16 | $$PWD/qpieseries.h |
@@ -1,127 +1,170 | |||||
1 |
|
1 | |||
2 | #include "piepresenter.h" |
|
2 | #include "piepresenter.h" | |
3 | #include "pieslice.h" |
|
3 | #include "pieslice.h" | |
4 | #include <QDebug> |
|
4 | #include <QDebug> | |
5 | #include <QTime> |
|
5 | #include <QTime> | |
6 |
|
6 | |||
7 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
7 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
8 |
|
8 | |||
9 |
PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series) |
|
9 | PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series) | |
10 | ChartItem(parent), |
|
10 | :ChartItem(parent), | |
11 |
m_ |
|
11 | m_series(series) | |
12 | { |
|
12 | { | |
13 | Q_ASSERT(parent); |
|
|||
14 | Q_ASSERT(series); |
|
13 | Q_ASSERT(series); | |
15 |
|
14 | connect(series, SIGNAL(changed(const QPieSeries::ChangeSet&)), this, SLOT(handleSeriesChanged(const QPieSeries::ChangeSet&))); | ||
16 | m_rect = parentItem()->boundingRect(); |
|
|||
17 | setAcceptHoverEvents(true); |
|
|||
18 | qsrand(QTime::currentTime().msec()); // for random color generation |
|
|||
19 |
|
||||
20 | connect(series, SIGNAL(changed(const PieChangeSet&)), this, SLOT(handleSeriesChanged(const PieChangeSet&))); |
|
|||
21 | connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry())); |
|
15 | connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry())); | |
22 | connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry())); |
|
16 | connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry())); | |
23 | } |
|
17 | } | |
24 |
|
18 | |||
25 | PiePresenter::~PiePresenter() |
|
19 | PiePresenter::~PiePresenter() | |
26 | { |
|
20 | { | |
27 | while (m_slices.count()) |
|
21 | // slices deleted automatically through QGraphicsItem | |
28 | delete m_slices.takeLast(); |
|
|||
29 | } |
|
22 | } | |
30 |
|
23 | |||
31 | void PiePresenter::handleSeriesChanged(const PieChangeSet& /*changeSet*/) |
|
24 | void PiePresenter::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) | |
32 | { |
|
25 | { | |
33 | const qreal fullPie = 360; |
|
26 | // TODO: paint shadows for all components | |
34 | qreal total = 0; |
|
27 | // - get paths from items & merge & offset and draw with shadow color? | |
35 |
|
||||
36 | // calculate total and set random color if there is no color |
|
|||
37 | for (int i=0; i<m_pieSeries->count(); i++) { |
|
|||
38 | QPieSlice& slice = m_pieSeries->m_slices[i]; |
|
|||
39 | total += slice.m_value; |
|
|||
40 | if (slice.m_color == QColor::Invalid) { |
|
|||
41 | slice.m_color.setRed(qrand() % 255); |
|
|||
42 | slice.m_color.setGreen(qrand() % 255); |
|
|||
43 | slice.m_color.setBlue(qrand() % 255); |
|
|||
44 | } |
|
28 | } | |
|
29 | ||||
|
30 | void PiePresenter::handleSeriesChanged(const QPieSeries::ChangeSet& changeSet) | |||
|
31 | { | |||
|
32 | qDebug() << "PiePresenter::handleSeriesChanged()"; | |||
|
33 | qDebug() << " added : " << changeSet.m_added; | |||
|
34 | qDebug() << " changed: " << changeSet.m_changed; | |||
|
35 | qDebug() << " removed: " << changeSet.m_removed; | |||
|
36 | ||||
|
37 | // ignore changeset when there are no visual slices | |||
|
38 | // changeset might not be valid about the added slices | |||
|
39 | if (m_slices.count() == 0) { | |||
|
40 | foreach (QPieSliceId id, m_series->m_slices.keys()) | |||
|
41 | addSlice(id); | |||
|
42 | return; | |||
45 | } |
|
43 | } | |
46 |
|
44 | |||
47 | // TODO: no need to create new slices in case size changed; we should re-use the existing ones |
|
45 | foreach (QPieSliceId id, changeSet.m_removed) | |
48 | while (m_slices.count()) |
|
46 | deleteSlice(id); | |
49 | delete m_slices.takeLast(); |
|
|||
50 |
|
47 | |||
51 | // create slices |
|
48 | foreach (QPieSliceId id, changeSet.m_changed) | |
52 | qreal angle = 0; |
|
49 | updateSlice(id); | |
53 | for (int i=0; i<m_pieSeries->count(); i++) { |
|
50 | ||
54 | QPieSlice sliceData = m_pieSeries->slice(i); |
|
51 | foreach (QPieSliceId id, changeSet.m_added) | |
55 | qreal span = sliceData.m_value / total * fullPie; |
|
52 | addSlice(id); | |
56 | PieSlice *slice = new PieSlice(this, i, angle, span); |
|
|||
57 | m_slices.append(slice); |
|
|||
58 | angle += span; |
|
|||
59 | } |
|
|||
60 | } |
|
53 | } | |
61 |
|
54 | |||
62 | void PiePresenter::updateGeometry() |
|
55 | void PiePresenter::updateGeometry() | |
63 | { |
|
56 | { | |
64 | prepareGeometryChange(); |
|
57 | prepareGeometryChange(); | |
65 |
|
58 | |||
66 | m_pieRect = m_rect; |
|
59 | m_pieRect = m_rect; | |
67 |
|
60 | |||
68 | if (m_pieRect.width() < m_pieRect.height()) { |
|
61 | if (m_pieRect.width() < m_pieRect.height()) { | |
69 |
m_pieRect.setWidth(m_pieRect.width() * m_ |
|
62 | m_pieRect.setWidth(m_pieRect.width() * m_series->sizeFactor()); | |
70 | m_pieRect.setHeight(m_pieRect.width()); |
|
63 | m_pieRect.setHeight(m_pieRect.width()); | |
71 | m_pieRect.moveCenter(m_rect.center()); |
|
64 | m_pieRect.moveCenter(m_rect.center()); | |
72 | } else { |
|
65 | } else { | |
73 |
m_pieRect.setHeight(m_pieRect.height() * m_ |
|
66 | m_pieRect.setHeight(m_pieRect.height() * m_series->sizeFactor()); | |
74 | m_pieRect.setWidth(m_pieRect.height()); |
|
67 | m_pieRect.setWidth(m_pieRect.height()); | |
75 | m_pieRect.moveCenter(m_rect.center()); |
|
68 | m_pieRect.moveCenter(m_rect.center()); | |
76 | } |
|
69 | } | |
77 |
|
70 | |||
78 |
switch (m_ |
|
71 | switch (m_series->position()) { | |
79 | case QPieSeries::PiePositionTopLeft: { |
|
72 | case QPieSeries::PiePositionTopLeft: { | |
80 | m_pieRect.setHeight(m_pieRect.height() / 2); |
|
73 | m_pieRect.setHeight(m_pieRect.height() / 2); | |
81 | m_pieRect.setWidth(m_pieRect.height()); |
|
74 | m_pieRect.setWidth(m_pieRect.height()); | |
82 | m_pieRect.moveCenter(QPointF(m_rect.center().x() / 2, m_rect.center().y() / 2)); |
|
75 | m_pieRect.moveCenter(QPointF(m_rect.center().x() / 2, m_rect.center().y() / 2)); | |
83 | break; |
|
76 | break; | |
84 | } |
|
77 | } | |
85 | case QPieSeries::PiePositionTopRight: { |
|
78 | case QPieSeries::PiePositionTopRight: { | |
86 | m_pieRect.setHeight(m_pieRect.height() / 2); |
|
79 | m_pieRect.setHeight(m_pieRect.height() / 2); | |
87 | m_pieRect.setWidth(m_pieRect.height()); |
|
80 | m_pieRect.setWidth(m_pieRect.height()); | |
88 | m_pieRect.moveCenter(QPointF((m_rect.center().x() / 2) * 3, m_rect.center().y() / 2)); |
|
81 | m_pieRect.moveCenter(QPointF((m_rect.center().x() / 2) * 3, m_rect.center().y() / 2)); | |
89 | break; |
|
82 | break; | |
90 | } |
|
83 | } | |
91 | case QPieSeries::PiePositionBottomLeft: { |
|
84 | case QPieSeries::PiePositionBottomLeft: { | |
92 | m_pieRect.setHeight(m_pieRect.height() / 2); |
|
85 | m_pieRect.setHeight(m_pieRect.height() / 2); | |
93 | m_pieRect.setWidth(m_pieRect.height()); |
|
86 | m_pieRect.setWidth(m_pieRect.height()); | |
94 | m_pieRect.moveCenter(QPointF(m_rect.center().x() / 2, (m_rect.center().y() / 2) * 3)); |
|
87 | m_pieRect.moveCenter(QPointF(m_rect.center().x() / 2, (m_rect.center().y() / 2) * 3)); | |
95 | break; |
|
88 | break; | |
96 | } |
|
89 | } | |
97 | case QPieSeries::PiePositionBottomRight: { |
|
90 | case QPieSeries::PiePositionBottomRight: { | |
98 | m_pieRect.setHeight(m_pieRect.height() / 2); |
|
91 | m_pieRect.setHeight(m_pieRect.height() / 2); | |
99 | m_pieRect.setWidth(m_pieRect.height()); |
|
92 | m_pieRect.setWidth(m_pieRect.height()); | |
100 | m_pieRect.moveCenter(QPointF((m_rect.center().x() / 2) * 3, (m_rect.center().y() / 2) * 3)); |
|
93 | m_pieRect.moveCenter(QPointF((m_rect.center().x() / 2) * 3, (m_rect.center().y() / 2) * 3)); | |
101 | break; |
|
94 | break; | |
102 | } |
|
95 | } | |
103 | default: |
|
96 | default: | |
104 | break; |
|
97 | break; | |
105 | } |
|
98 | } | |
106 |
|
99 | |||
107 | qDebug() << "presentation rect:" << m_rect; |
|
100 | // update slice geometry | |
108 | qDebug() << "pie rect:" << m_pieRect; |
|
101 | const qreal fullPie = 360; | |
109 | foreach (PieSlice *slice, m_slices) |
|
102 | qreal angle = 0; | |
110 | slice->updateGeometry(); |
|
103 | foreach (QPieSliceId id, m_slices.keys()) { | |
|
104 | qreal span = fullPie * m_series->slice(id).percentage(); | |||
|
105 | m_slices[id]->updateGeometry(m_pieRect, angle, span); | |||
|
106 | angle += span; | |||
|
107 | } | |||
|
108 | ||||
|
109 | //qDebug() << "PiePresenter::updateGeometry" << m_rect << m_pieRect; | |||
111 | } |
|
110 | } | |
112 |
|
111 | |||
113 | void PiePresenter::handleDomainChanged(const Domain& domain) |
|
112 | void PiePresenter::handleDomainChanged(const Domain& domain) | |
114 | { |
|
113 | { | |
115 | // TODO |
|
114 | // TODO | |
116 | } |
|
115 | } | |
117 |
|
116 | |||
118 | void PiePresenter::handleGeometryChanged(const QRectF& rect) |
|
117 | void PiePresenter::handleGeometryChanged(const QRectF& rect) | |
119 | { |
|
118 | { | |
120 | m_rect = rect; |
|
119 | m_rect = rect; | |
121 | updateGeometry(); |
|
120 | updateGeometry(); | |
|
121 | } | |||
|
122 | ||||
|
123 | void PiePresenter::addSlice(QPieSliceId id) | |||
|
124 | { | |||
|
125 | qDebug() << "PiePresenter::addSlice()" << id; | |||
|
126 | ||||
|
127 | if (m_slices.contains(id)) { | |||
|
128 | qWarning() << "PiePresenter::addSlice(): slice already exists!" << id; | |||
|
129 | updateSlice(id); | |||
|
130 | return; | |||
|
131 | } | |||
|
132 | ||||
|
133 | // create slice | |||
|
134 | PieSlice *slice = new PieSlice(id, m_series, this); | |||
|
135 | m_slices.insert(id, slice); | |||
|
136 | ||||
|
137 | updateGeometry(); | |||
|
138 | } | |||
122 |
|
139 | |||
|
140 | void PiePresenter::updateSlice(QPieSliceId id) | |||
|
141 | { | |||
|
142 | qDebug() << "PiePresenter::updateSlice()" << id; | |||
|
143 | ||||
|
144 | // TODO: animation | |||
|
145 | if (m_slices.contains(id)) | |||
|
146 | m_slices.value(id)->updateData(); | |||
|
147 | else { | |||
|
148 | qWarning() << "PiePresenter::updateSlice(): slice does not exist!" << id; | |||
|
149 | addSlice(id); | |||
|
150 | } | |||
|
151 | ||||
|
152 | updateGeometry(); | |||
|
153 | } | |||
|
154 | ||||
|
155 | void PiePresenter::deleteSlice(QPieSliceId id) | |||
|
156 | { | |||
|
157 | qDebug() << "PiePresenter::deleteSlice()" << id; | |||
|
158 | ||||
|
159 | // TODO: animation | |||
|
160 | if (m_slices.contains(id)) | |||
|
161 | delete m_slices.take(id); | |||
|
162 | else | |||
|
163 | qWarning() << "PiePresenter::deleteSlice(): slice does not exist!" << id; | |||
|
164 | ||||
|
165 | updateGeometry(); | |||
123 | } |
|
166 | } | |
124 |
|
167 | |||
125 | #include "moc_piepresenter.cpp" |
|
168 | #include "moc_piepresenter.cpp" | |
126 |
|
169 | |||
127 | QTCOMMERCIALCHART_END_NAMESPACE |
|
170 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,43 +1,49 | |||||
1 | #ifndef PIEPRESENTER_H |
|
1 | #ifndef PIEPRESENTER_H | |
2 | #define PIEPRESENTER_H |
|
2 | #define PIEPRESENTER_H | |
3 |
|
3 | |||
4 | #include "chartitem_p.h" |
|
4 | #include "chartitem_p.h" | |
5 | #include "qpieseries.h" |
|
5 | #include "qpieseries.h" | |
|
6 | #include <QSignalMapper> | |||
6 |
|
7 | |||
7 | class QGraphicsItem; |
|
8 | class QGraphicsItem; | |
8 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
9 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
9 | class PieSlice; |
|
10 | class PieSlice; | |
10 |
|
11 | |||
11 | class PiePresenter : public QObject, public ChartItem |
|
12 | class PiePresenter : public QObject, public ChartItem | |
12 | { |
|
13 | { | |
13 | Q_OBJECT |
|
14 | Q_OBJECT | |
14 |
|
15 | |||
15 | public: |
|
16 | public: | |
16 | // TODO: use a generic data class instead of x and y |
|
17 | // TODO: use a generic data class instead of x and y | |
17 | PiePresenter(QGraphicsItem *parent, QPieSeries *series); |
|
18 | PiePresenter(QGraphicsItem *parent, QPieSeries *series); | |
18 | ~PiePresenter(); |
|
19 | ~PiePresenter(); | |
19 |
|
20 | |||
20 | public: // from QGraphicsItem |
|
21 | public: // from QGraphicsItem | |
21 | QRectF boundingRect() const { return m_rect; } |
|
22 | QRectF boundingRect() const { return m_rect; } | |
22 |
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) |
|
23 | void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); | |
23 |
|
24 | |||
24 | public: |
|
25 | public: | |
25 | QRectF pieRect() const { return m_pieRect; } |
|
26 | QRectF pieRect() const { return m_pieRect; } | |
26 |
|
27 | |||
27 | public Q_SLOTS: |
|
28 | public Q_SLOTS: | |
28 | void handleSeriesChanged(const PieChangeSet& changeSet); |
|
29 | void handleSeriesChanged(const QPieSeries::ChangeSet& changeSet); | |
29 | void handleDomainChanged(const Domain& domain); |
|
30 | void handleDomainChanged(const Domain& domain); | |
30 | void handleGeometryChanged(const QRectF& rect); |
|
31 | void handleGeometryChanged(const QRectF& rect); | |
31 | void updateGeometry(); |
|
32 | void updateGeometry(); | |
32 |
|
33 | |||
33 | private: |
|
34 | private: | |
|
35 | void addSlice(QPieSliceId id); | |||
|
36 | void updateSlice(QPieSliceId id); | |||
|
37 | void deleteSlice(QPieSliceId id); | |||
|
38 | ||||
|
39 | private: | |||
34 | friend class PieSlice; |
|
40 | friend class PieSlice; | |
35 |
Q |
|
41 | QHash<QPieSliceId, PieSlice*> m_slices; | |
36 |
QPieSeries *m_ |
|
42 | QPieSeries *m_series; | |
37 | QRectF m_rect; |
|
43 | QRectF m_rect; | |
38 | QRectF m_pieRect; |
|
44 | QRectF m_pieRect; | |
39 | }; |
|
45 | }; | |
40 |
|
46 | |||
41 | QTCOMMERCIALCHART_END_NAMESPACE |
|
47 | QTCOMMERCIALCHART_END_NAMESPACE | |
42 |
|
48 | |||
43 | #endif // PIEPRESENTER_H |
|
49 | #endif // PIEPRESENTER_H |
@@ -1,122 +1,135 | |||||
1 | #include "pieslice.h" |
|
1 | #include "pieslice.h" | |
|
2 | #include "pieslicelabel.h" | |||
2 | #include "piepresenter.h" |
|
3 | #include "piepresenter.h" | |
3 | #include "qpieseries.h" |
|
4 | #include "qpieseries.h" | |
4 | #include <QPainter> |
|
5 | #include <QPainter> | |
5 | #include <QDebug> |
|
6 | #include <QDebug> | |
6 | #include <qmath.h> |
|
7 | #include <qmath.h> | |
7 | #include <QGraphicsSceneEvent> |
|
8 | #include <QGraphicsSceneEvent> | |
|
9 | #include <QTime> | |||
8 |
|
10 | |||
9 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
11 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
10 |
|
12 | |||
11 | #define PI 3.14159265 |
|
13 | #define PI 3.14159265 | |
12 | #define EXPLODE_OFFSET 20 |
|
14 | #define EXPLODE_OFFSET 20 | |
13 |
|
15 | |||
14 | QPointF offset(qreal angle, qreal length) |
|
16 | QPointF offset(qreal angle, qreal length) | |
15 | { |
|
17 | { | |
16 | qreal dx = qSin(angle*(PI/180)) * length; |
|
18 | qreal dx = qSin(angle*(PI/180)) * length; | |
17 | qreal dy = qCos(angle*(PI/180)) * length; |
|
19 | qreal dy = qCos(angle*(PI/180)) * length; | |
18 | return QPointF(dx, -dy); |
|
20 | return QPointF(dx, -dy); | |
19 | } |
|
21 | } | |
20 |
|
22 | |||
21 | PieSlice::PieSlice(PiePresenter *presenter, int seriesIndex, qreal startAngle, qreal span) |
|
23 | PieSlice::PieSlice(QPieSliceId id, QPieSeries *series, QGraphicsItem* parent) | |
22 |
:QGraphics |
|
24 | :QGraphicsObject(parent), | |
23 | m_label(new QGraphicsTextItem(this)), |
|
25 | m_id(id), | |
24 |
m_series |
|
26 | m_series(series), | |
25 | m_startAngle(startAngle), |
|
27 | m_slicelabel(new PieSliceLabel(this)), | |
26 | m_span(span) |
|
28 | m_isHovering(false) | |
27 | { |
|
29 | { | |
28 |
Q_ASSERT( |
|
30 | Q_ASSERT(series); | |
29 | setAcceptHoverEvents(true); |
|
31 | setAcceptHoverEvents(true); | |
30 | setAcceptedMouseButtons(Qt::LeftButton); |
|
32 | setAcceptedMouseButtons(Qt::LeftButton); | |
31 |
update |
|
33 | updateData(); | |
32 |
|
||||
33 | // TODO: use themes |
|
|||
34 | m_pen = QPen(Qt::black); |
|
|||
35 | m_brush = QBrush(sliceData().m_color); |
|
|||
36 | } |
|
34 | } | |
37 |
|
35 | |||
38 | PieSlice::~PieSlice() |
|
36 | PieSlice::~PieSlice() | |
39 | { |
|
37 | { | |
|
38 | qDebug() << "~PieSlice()" << m_id; | |||
40 | } |
|
39 | } | |
41 |
|
40 | |||
42 | QRectF PieSlice::boundingRect() const |
|
41 | QRectF PieSlice::boundingRect() const | |
43 | { |
|
42 | { | |
44 | return m_rect; |
|
43 | return m_rect; | |
45 | } |
|
44 | } | |
46 |
|
45 | |||
47 | QPainterPath PieSlice::shape() const |
|
46 | QPainterPath PieSlice::shape() const | |
48 | { |
|
47 | { | |
49 | return m_path; |
|
48 | return m_path; | |
50 | } |
|
49 | } | |
51 |
|
50 | |||
52 | void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) |
|
51 | void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) | |
53 | { |
|
52 | { | |
54 | painter->setRenderHint(QPainter::Antialiasing); |
|
53 | // set hover brush | |
|
54 | // TODO: what if we are using gradients... | |||
|
55 | QBrush brush = m_data.brush(); | |||
|
56 | if (m_isHovering) | |||
|
57 | brush.setColor(brush.color().lighter()); | |||
55 |
|
58 | |||
56 | // TODO: themes |
|
59 | painter->setRenderHint(QPainter::Antialiasing); | |
57 | painter->setPen(m_pen); |
|
60 | painter->setPen(m_data.pen()); | |
58 |
painter->setBrush( |
|
61 | painter->setBrush(brush); | |
59 | painter->drawPath(m_path); |
|
62 | painter->drawPath(m_path); | |
60 |
|
||||
61 | // Draw the label |
|
|||
62 | // TODO: do this better |
|
|||
63 | //QTextItem text; |
|
|||
64 | painter->drawText(m_center, sliceData().m_label); |
|
|||
65 | } |
|
63 | } | |
66 |
|
64 | |||
67 | void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* event) |
|
65 | void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/) | |
68 | { |
|
66 | { | |
69 | m_brush = QBrush(sliceData().m_color.lighter()); |
|
67 | m_isHovering = true; | |
70 | update(); |
|
68 | update(); | |
|
69 | // TODO: emit hoverEnter() | |||
71 | } |
|
70 | } | |
72 |
|
71 | |||
73 | void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/) |
|
72 | void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/) | |
74 | { |
|
73 | { | |
75 | m_brush = QBrush(sliceData().m_color); |
|
74 | m_isHovering = false; | |
76 | update(); |
|
75 | update(); | |
|
76 | // TODO: emit hoverLeave() | |||
77 | } |
|
77 | } | |
78 |
|
78 | |||
79 | void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/) |
|
79 | void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/) | |
80 | { |
|
80 | { | |
81 | QPieSlice data = sliceData(); |
|
81 | // TODO: emit clicked | |
82 | data.m_isExploded = !data.m_isExploded; |
|
82 | // TODO: should we let the user decide if this can be exploded? | |
83 | (static_cast<PiePresenter*>(parentItem()))->m_pieSeries->update(m_seriesIndex, data); |
|
83 | m_data.setExploded(!m_data.isExploded()); | |
|
84 | m_series->update(m_data); | |||
84 | } |
|
85 | } | |
85 |
|
86 | |||
86 | void PieSlice::updateGeometry() |
|
87 | void PieSlice::updateGeometry(QRectF rect, qreal startAngle, qreal span) | |
87 | { |
|
88 | { | |
88 | prepareGeometryChange(); |
|
89 | prepareGeometryChange(); | |
89 |
|
90 | |||
90 | PiePresenter *presenter = static_cast<PiePresenter*>(parentItem()); |
|
91 | // calculate center angle | |
91 | QRectF rect = presenter->pieRect(); |
|
92 | qreal centerAngle = startAngle + (span/2); | |
92 | rect.adjust(EXPLODE_OFFSET, EXPLODE_OFFSET, -EXPLODE_OFFSET ,-EXPLODE_OFFSET); |
|
|||
93 |
|
93 | |||
94 | qreal centerAngle = m_startAngle + (m_span/2); |
|
94 | // adjust rect for exploding | |
95 |
|
95 | rect.adjust(EXPLODE_OFFSET, EXPLODE_OFFSET, -EXPLODE_OFFSET ,-EXPLODE_OFFSET); | ||
96 | if (presenter->m_pieSeries->slice(m_seriesIndex).m_isExploded) { |
|
96 | if (m_data.isExploded()) { | |
97 | QPointF d = offset((centerAngle), EXPLODE_OFFSET); |
|
97 | QPointF d = offset((centerAngle), EXPLODE_OFFSET); | |
98 | rect.translate(d.x(), d.y()); |
|
98 | rect.translate(d.x(), d.y()); | |
99 | } |
|
99 | } | |
100 |
|
100 | |||
101 | qreal angle = (-m_startAngle) + (90); |
|
101 | // update slice path | |
102 | qreal span = -m_span; |
|
102 | // TODO: draw the shape so that it might have a hole in the center | |
103 |
|
||||
104 | QPainterPath path; |
|
103 | QPainterPath path; | |
105 | path.moveTo(rect.center()); |
|
104 | path.moveTo(rect.center()); | |
106 | path.arcTo(rect, angle, span); |
|
105 | path.arcTo(rect, -startAngle + 90, -span); | |
107 |
|
||||
108 | // TODO: draw the shape so that it might have a hole in the center |
|
|||
109 |
|
||||
110 | m_path = path; |
|
106 | m_path = path; | |
111 | m_rect = path.boundingRect(); |
|
107 | m_rect = path.boundingRect(); | |
112 |
|
108 | |||
|
109 | // update label position | |||
113 | qreal radius = rect.height() / 2; |
|
110 | qreal radius = rect.height() / 2; | |
114 |
|
|
111 | QPointF edgeCenter = rect.center() + offset(centerAngle, radius + 5); | |
|
112 | m_slicelabel->updateGeometry(edgeCenter, centerAngle, 50); | |||
|
113 | ||||
|
114 | //qDebug() << "PieSlice::updateGeometry" << m_rect; | |||
115 | } |
|
115 | } | |
116 |
|
116 | |||
117 |
|
|
117 | void PieSlice::updateData() | |
118 | { |
|
118 | { | |
119 | return (static_cast<PiePresenter*>(parentItem()))->m_pieSeries->slice(m_seriesIndex); |
|
119 | if (!m_series->m_slices.contains(m_id)) | |
|
120 | qWarning() << "PieSlice::updateData(): cannot find slice data!" << m_id; | |||
|
121 | ||||
|
122 | QPieSlice data = m_series->slice(m_id); | |||
|
123 | // TODO: find out what has changed and trigger some animation | |||
|
124 | m_data = data; | |||
|
125 | ||||
|
126 | update(); | |||
|
127 | ||||
|
128 | m_slicelabel->setLabel(m_data.label()); | |||
|
129 | m_slicelabel->setVisible(m_data.isLabelVisible()); | |||
|
130 | m_slicelabel->update(); | |||
120 | } |
|
131 | } | |
121 |
|
132 | |||
|
133 | #include "moc_pieslice.cpp" | |||
|
134 | ||||
122 | QTCOMMERCIALCHART_END_NAMESPACE |
|
135 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,49 +1,51 | |||||
1 | #ifndef PIESLICE_H |
|
1 | #ifndef PIESLICE_H | |
2 | #define PIESLICE_H |
|
2 | #define PIESLICE_H | |
3 |
|
3 | |||
4 | #include "qchartglobal.h" |
|
4 | #include "qchartglobal.h" | |
5 | #include "charttheme_p.h" |
|
5 | #include "charttheme_p.h" | |
6 | #include "qpieseries.h" |
|
6 | #include "qpieseries.h" | |
7 | #include <QGraphicsItem> |
|
7 | #include <QGraphicsItem> | |
8 | #include <QRectF> |
|
8 | #include <QRectF> | |
9 | #include <QColor> |
|
9 | #include <QColor> | |
10 | #include <QPen> |
|
10 | #include <QPen> | |
11 |
|
11 | |||
12 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
12 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
13 | class PiePresenter; |
|
13 | class PiePresenter; | |
|
14 | class PieSliceLabel; | |||
14 |
|
15 | |||
15 |
class PieSlice : public QGraphics |
|
16 | class PieSlice : public QGraphicsObject | |
16 | { |
|
17 | { | |
|
18 | Q_OBJECT | |||
|
19 | ||||
17 | public: |
|
20 | public: | |
18 | PieSlice(PiePresenter *piePresenter, int seriesIndex, qreal startAngle, qreal span); |
|
21 | PieSlice(QPieSliceId id, QPieSeries *series, QGraphicsItem* parent = 0); | |
19 | ~PieSlice(); |
|
22 | ~PieSlice(); | |
20 |
|
23 | |||
21 | public: // from QGraphicsItem |
|
24 | public: // from QGraphicsItem | |
22 | QRectF boundingRect() const; |
|
25 | QRectF boundingRect() const; | |
23 | QPainterPath shape() const; |
|
26 | QPainterPath shape() const; | |
24 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); |
|
27 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); | |
25 | void hoverEnterEvent(QGraphicsSceneHoverEvent *event); |
|
28 | void hoverEnterEvent(QGraphicsSceneHoverEvent *event); | |
26 | void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); |
|
29 | void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); | |
27 | void mousePressEvent(QGraphicsSceneMouseEvent *event); |
|
30 | void mousePressEvent(QGraphicsSceneMouseEvent *event); | |
28 |
|
31 | |||
29 | public: |
|
32 | Q_SIGNALS: | |
30 | void updateGeometry(); |
|
33 | void clicked(); | |
31 |
|
34 | |||
32 | private: |
|
35 | public: | |
33 | QPieSlice sliceData(); |
|
36 | void updateGeometry(QRectF rect, qreal startAngle, qreal span); | |
|
37 | void updateData(); | |||
34 |
|
38 | |||
35 | private: |
|
39 | private: | |
36 | QGraphicsTextItem* m_label; |
|
40 | QPieSliceId m_id; | |
37 |
|
|
41 | QPieSeries* m_series; | |
38 | qreal m_startAngle; |
|
42 | QPieSlice m_data; | |
39 | qreal m_span; |
|
43 | PieSliceLabel* m_slicelabel; | |
40 | QPainterPath m_path; |
|
44 | QPainterPath m_path; | |
41 | QRectF m_rect; |
|
45 | QRectF m_rect; | |
42 | QPointF m_center; |
|
46 | bool m_isHovering; | |
43 | QPen m_pen; |
|
|||
44 | QBrush m_brush; |
|
|||
45 | }; |
|
47 | }; | |
46 |
|
48 | |||
47 | QTCOMMERCIALCHART_END_NAMESPACE |
|
49 | QTCOMMERCIALCHART_END_NAMESPACE | |
48 |
|
50 | |||
49 | #endif // PIESLICE_H |
|
51 | #endif // PIESLICE_H |
@@ -1,109 +1,152 | |||||
1 | #include "qpieseries.h" |
|
1 | #include "qpieseries.h" | |
2 | #include "piepresenter.h" |
|
2 | #include "piepresenter.h" | |
3 | #include "pieslice.h" |
|
3 | #include "pieslice.h" | |
4 | #include <QDebug> |
|
4 | #include <QDebug> | |
5 |
|
5 | |||
6 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
6 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
7 |
|
7 | |||
8 | QPieSeries::QPieSeries(QObject *parent) : |
|
8 | QPieSeries::QPieSeries(QObject *parent) : | |
9 | QChartSeries(parent), |
|
9 | QChartSeries(parent), | |
10 | m_sizeFactor(1.0), |
|
10 | m_sizeFactor(1.0), | |
11 | m_position(PiePositionMaximized) |
|
11 | m_position(PiePositionMaximized), | |
|
12 | m_sliceIdSeed(0) | |||
12 | { |
|
13 | { | |
13 | } |
|
14 | } | |
14 |
|
15 | |||
15 | QPieSeries::~QPieSeries() |
|
16 | QPieSeries::~QPieSeries() | |
16 | { |
|
17 | { | |
17 |
|
18 | |||
18 | } |
|
19 | } | |
19 |
|
20 | |||
20 | bool QPieSeries::setData(QList<qreal> data) |
|
21 | bool QPieSeries::setData(QList<qreal> data) | |
21 | { |
|
22 | { | |
|
23 | // TODO: remove this function | |||
22 | QList<QPieSlice> slices; |
|
24 | QList<QPieSlice> slices; | |
23 | foreach (int value, data) |
|
25 | foreach (int value, data) | |
24 | slices << QPieSlice(value, QString::number(value)); |
|
26 | slices << QPieSlice(value, QString::number(value)); | |
25 | return set(slices); |
|
27 | return set(slices); | |
26 | } |
|
28 | } | |
27 |
|
29 | |||
28 | bool QPieSeries::set(QList<QPieSlice> slices) |
|
30 | bool QPieSeries::set(const QList<QPieSlice>& slices) | |
29 | { |
|
31 | { | |
30 | if (!slices.count()) |
|
32 | if (!slices.count()) | |
31 | return false; |
|
33 | return false; | |
32 |
|
34 | |||
33 |
|
|
35 | ChangeSet changeSet; | |
34 |
|
36 | |||
35 | for (int i=slices.count(); i<m_slices.count(); i++) |
|
37 | foreach (QPieSlice s, m_slices.values()) | |
36 | changeSet.m_removed << i; |
|
38 | changeSet.m_removed << s.id(); | |
37 |
|
39 | |||
38 | for (int i=0; i<slices.count(); i++) { |
|
40 | m_slices.clear(); | |
39 | if (i < m_slices.count()) |
|
41 | ||
40 | changeSet.m_changed << i; |
|
42 | foreach (QPieSlice s, slices) { | |
41 | else |
|
43 | s.m_id = generateSliceId(); | |
42 | changeSet.m_added << i; |
|
44 | m_slices.insert(s.id(), s); | |
|
45 | changeSet.m_added << s.id(); | |||
43 | } |
|
46 | } | |
44 |
|
47 | |||
45 | m_slices = slices; |
|
48 | updateDerivativeData(); | |
46 | emit changed(changeSet); |
|
49 | emit changed(changeSet); | |
|
50 | ||||
47 | return true; |
|
51 | return true; | |
48 | } |
|
52 | } | |
49 |
|
53 | |||
50 | bool QPieSeries::add(QList<QPieSlice> slices) |
|
54 | bool QPieSeries::add(const QList<QPieSlice>& slices) | |
51 | { |
|
55 | { | |
52 | if (!slices.count()) |
|
56 | if (!slices.count()) | |
53 | return false; |
|
57 | return false; | |
54 |
|
58 | |||
55 |
|
|
59 | ChangeSet changeSet; | |
56 | for (int i=0; i<slices.count(); i++) |
|
60 | foreach (QPieSlice s, slices) { | |
57 | changeSet.m_added << m_slices.count() + i; |
|
61 | s.m_id = generateSliceId(); | |
|
62 | m_slices.insert(s.id(), s); | |||
|
63 | changeSet.m_added << s.id(); | |||
|
64 | } | |||
58 |
|
65 | |||
59 | m_slices += slices; |
|
66 | updateDerivativeData(); | |
60 | emit changed(changeSet); |
|
67 | emit changed(changeSet); | |
|
68 | ||||
61 | return true; |
|
69 | return true; | |
62 | } |
|
70 | } | |
63 |
|
71 | |||
64 | bool QPieSeries::add(QPieSlice slice) |
|
72 | bool QPieSeries::add(const QPieSlice& slice) | |
65 | { |
|
73 | { | |
66 | return add(QList<QPieSlice>() << slice); |
|
74 | return add(QList<QPieSlice>() << slice); | |
67 | } |
|
75 | } | |
68 |
|
76 | |||
69 | QPieSlice QPieSeries::slice(int index) const |
|
77 | bool QPieSeries::update(const QPieSlice& slice) | |
70 | { |
|
78 | { | |
71 | if ((index >= 0) && (index < m_slices.count())) |
|
79 | if (!m_slices.contains(slice.id())) | |
72 | return m_slices.at(index); |
|
80 | return false; // series does not contain this slice | |
73 | return QPieSlice(); |
|
81 | ||
|
82 | m_slices[slice.id()] = slice; | |||
|
83 | ||||
|
84 | ChangeSet changeSet; | |||
|
85 | changeSet.m_changed << slice.id(); | |||
|
86 | updateDerivativeData(); | |||
|
87 | emit changed(changeSet); | |||
|
88 | ||||
|
89 | return true; | |||
74 | } |
|
90 | } | |
75 |
|
91 | |||
76 |
bool QPieSeries:: |
|
92 | bool QPieSeries::remove(QPieSliceId id) | |
77 | { |
|
93 | { | |
78 | if ((index >= 0) && (index < m_slices.count())) { |
|
94 | if (!m_slices.contains(id)) | |
79 | m_slices[index] = slice; |
|
95 | return false; // series does not contain this slice | |
80 | PieChangeSet changeSet; |
|
96 | ||
81 | changeSet.m_changed << index; |
|
97 | m_slices.remove(id); | |
|
98 | ||||
|
99 | ChangeSet changeSet; | |||
|
100 | changeSet.m_removed << id; | |||
|
101 | updateDerivativeData(); | |||
82 |
|
|
102 | emit changed(changeSet); | |
|
103 | ||||
83 |
|
|
104 | return true; | |
84 | } |
|
105 | } | |
85 | return false; |
|
106 | ||
|
107 | QPieSlice QPieSeries::slice(QPieSliceId id) const | |||
|
108 | { | |||
|
109 | return m_slices.value(id); | |||
86 | } |
|
110 | } | |
87 |
|
111 | |||
88 | void QPieSeries::setSizeFactor(qreal factor) |
|
112 | void QPieSeries::setSizeFactor(qreal factor) | |
89 | { |
|
113 | { | |
90 | if (factor < 0.0) |
|
114 | if (factor < 0.0) | |
91 | return; |
|
115 | return; | |
92 |
|
116 | |||
93 | if (m_sizeFactor != factor) { |
|
117 | if (m_sizeFactor != factor) { | |
94 | m_sizeFactor = factor; |
|
118 | m_sizeFactor = factor; | |
95 | emit sizeFactorChanged(); |
|
119 | emit sizeFactorChanged(); | |
96 | } |
|
120 | } | |
97 | } |
|
121 | } | |
98 |
|
122 | |||
99 | void QPieSeries::setPosition(PiePosition position) |
|
123 | void QPieSeries::setPosition(PiePosition position) | |
100 | { |
|
124 | { | |
101 | if (m_position != position) { |
|
125 | if (m_position != position) { | |
102 | m_position = position; |
|
126 | m_position = position; | |
103 | emit positionChanged(); |
|
127 | emit positionChanged(); | |
104 | } |
|
128 | } | |
105 | } |
|
129 | } | |
106 |
|
130 | |||
|
131 | QPieSliceId QPieSeries::generateSliceId() | |||
|
132 | { | |||
|
133 | // Id is quint64 so it should be enough for us. | |||
|
134 | // Note that id is not unique between pie series. | |||
|
135 | return m_sliceIdSeed++; | |||
|
136 | } | |||
|
137 | ||||
|
138 | void QPieSeries::updateDerivativeData() | |||
|
139 | { | |||
|
140 | m_total = 0; | |||
|
141 | foreach (const QPieSlice& s, m_slices.values()) | |||
|
142 | m_total += s.value(); | |||
|
143 | ||||
|
144 | Q_ASSERT(m_total > 0); // TODO: remove this before release | |||
|
145 | ||||
|
146 | foreach (QPieSliceId id, m_slices.keys()) | |||
|
147 | m_slices[id].m_percentage = m_slices.value(id).value() / m_total; | |||
|
148 | } | |||
|
149 | ||||
107 | #include "moc_qpieseries.cpp" |
|
150 | #include "moc_qpieseries.cpp" | |
108 |
|
151 | |||
109 | QTCOMMERCIALCHART_END_NAMESPACE |
|
152 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,97 +1,157 | |||||
1 | #ifndef PIESERIES_H |
|
1 | #ifndef PIESERIES_H | |
2 | #define PIESERIES_H |
|
2 | #define PIESERIES_H | |
3 |
|
3 | |||
4 | #include "qchartseries.h" |
|
4 | #include "qchartseries.h" | |
5 | #include <QObject> |
|
5 | #include <QObject> | |
6 | #include <QRectF> |
|
6 | #include <QRectF> | |
7 | #include <QColor> |
|
7 | #include <QColor> | |
|
8 | #include <QPen> | |||
|
9 | #include <QBrush> | |||
8 |
|
10 | |||
9 | class QGraphicsObject; |
|
11 | class QGraphicsObject; | |
10 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
12 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
11 | class PiePresenter; |
|
13 | class PiePresenter; | |
12 | class PieSlice; |
|
14 | class PieSlice; | |
13 |
|
15 | |||
|
16 | typedef quint64 QPieSliceId; | |||
|
17 | ||||
14 | class QPieSlice |
|
18 | class QPieSlice | |
15 | { |
|
19 | { | |
16 | public: |
|
20 | public: | |
17 | QPieSlice() |
|
21 | QPieSlice() | |
18 | :m_value(0), m_label("<empty>"), m_color(QColor::Invalid), m_isExploded(false) {} |
|
22 | :m_id(-1), m_value(0), m_isLabelVisible(true), m_isExploded(false), m_percentage(0) {} | |
19 |
|
23 | |||
20 |
QPieSlice(qreal value, QString label = |
|
24 | QPieSlice(qreal value, QString label = QString(), bool labelVisible = true, bool exploded = false, QPen pen = QPen(), QBrush brush = QBrush()) | |
21 |
:m_value(value), m_label(label), m_ |
|
25 | :m_id(-1), m_value(value), m_label(label), m_isLabelVisible(labelVisible), m_isExploded(exploded), m_pen(pen), m_brush(brush), m_percentage(0) {} | |
22 | public: |
|
26 | ||
|
27 | QPieSliceId id() const { return m_id; } | |||
|
28 | ||||
|
29 | void setValue(qreal value) { m_value = value; } | |||
|
30 | qreal value() const { return m_value; } | |||
|
31 | ||||
|
32 | void setLabel(QString label) { m_label = label; } | |||
|
33 | QString label() const { return m_label; } | |||
|
34 | ||||
|
35 | void setLabelVisible(bool visible) { m_isLabelVisible = visible; } | |||
|
36 | bool isLabelVisible() const { return m_isLabelVisible; } | |||
|
37 | ||||
|
38 | void setExploded(bool exploded) { m_isExploded = exploded; } | |||
|
39 | bool isExploded() const { return m_isExploded; } | |||
|
40 | ||||
|
41 | void setPen(QPen pen) { m_pen = pen; } | |||
|
42 | QPen pen() const { return m_pen; } | |||
|
43 | ||||
|
44 | void setBrush(QBrush brush) { m_brush = brush; } | |||
|
45 | QBrush brush() const { return m_brush; } | |||
|
46 | ||||
|
47 | qreal percentage() const { return m_percentage; } | |||
|
48 | ||||
|
49 | private: | |||
|
50 | ||||
|
51 | // TODO: use private class | |||
|
52 | friend class QPieSeries; | |||
|
53 | ||||
|
54 | QPieSliceId m_id; | |||
23 | qreal m_value; |
|
55 | qreal m_value; | |
24 | QString m_label; |
|
56 | QString m_label; | |
25 | QColor m_color; // TODO: should we even define color here? |
|
57 | bool m_isLabelVisible; | |
26 | bool m_isExploded; |
|
58 | bool m_isExploded; | |
27 | }; |
|
|||
28 |
|
59 | |||
29 | class PieChangeSet |
|
60 | QPen m_pen; | |
30 | { |
|
61 | QBrush m_brush; | |
31 | public: |
|
62 | ||
32 | QList<int> m_added; |
|
63 | qreal m_percentage; // generated content | |
33 | QList<int> m_removed; |
|
|||
34 | QList<int> m_changed; |
|
|||
35 | }; |
|
64 | }; | |
36 |
|
65 | |||
37 | class QTCOMMERCIALCHART_EXPORT QPieSeries : public QChartSeries |
|
66 | class QTCOMMERCIALCHART_EXPORT QPieSeries : public QChartSeries | |
38 | { |
|
67 | { | |
39 | Q_OBJECT |
|
68 | Q_OBJECT | |
40 |
|
69 | |||
41 | public: |
|
70 | public: | |
42 | enum PiePosition { |
|
71 | enum PiePosition { | |
43 | PiePositionMaximized = 0, |
|
72 | PiePositionMaximized = 0, | |
44 | PiePositionTopLeft, |
|
73 | PiePositionTopLeft, | |
45 | PiePositionTopRight, |
|
74 | PiePositionTopRight, | |
46 | PiePositionBottomLeft, |
|
75 | PiePositionBottomLeft, | |
47 | PiePositionBottomRight |
|
76 | PiePositionBottomRight | |
48 | }; |
|
77 | }; | |
49 |
|
78 | |||
|
79 | class ChangeSet | |||
|
80 | { | |||
|
81 | public: | |||
|
82 | QList<QPieSliceId> m_added; | |||
|
83 | QList<QPieSliceId> m_removed; | |||
|
84 | QList<QPieSliceId> m_changed; | |||
|
85 | }; | |||
|
86 | ||||
50 | public: |
|
87 | public: | |
51 | QPieSeries(QObject *parent = 0); |
|
88 | QPieSeries(QObject *parent = 0); | |
52 | ~QPieSeries(); |
|
89 | ~QPieSeries(); | |
53 |
|
90 | |||
54 | public: // from QChartSeries |
|
91 | public: // from QChartSeries | |
55 | QChartSeriesType type() const { return QChartSeries::SeriesTypePie; } |
|
92 | QChartSeriesType type() const { return QChartSeries::SeriesTypePie; } | |
56 | virtual bool setData(QList<qreal> data); |
|
93 | virtual bool setData(QList<qreal> data); // TODO: remove this | |
57 |
|
94 | |||
58 | public: |
|
95 | public: | |
59 | bool set(QList<QPieSlice> slices); |
|
96 | // TODO: should we return id/bool or what? | |
60 | bool add(QList<QPieSlice> slices); |
|
97 | // TODO: should we prefer passing a modifiable reference? | |
61 |
bool |
|
98 | bool set(const QList<QPieSlice>& slices); | |
|
99 | bool add(const QList<QPieSlice>& slices); | |||
|
100 | bool add(const QPieSlice& slice); | |||
|
101 | bool update(const QPieSlice& slice); | |||
|
102 | bool remove(QPieSliceId id); | |||
62 |
|
103 | |||
63 | int count() const { return m_slices.count(); } |
|
104 | int count() const { return m_slices.count(); } | |
64 |
|
105 | |||
65 | QList<QPieSlice> slices() const { return m_slices; } |
|
106 | QList<QPieSlice> slices() const { return m_slices.values(); } | |
66 | QPieSlice slice(int index) const; |
|
107 | QList<QPieSliceId> ids() const { return m_slices.keys(); } | |
67 | bool update(int index, QPieSlice slice); |
|
108 | QPieSlice slice(QPieSliceId id) const; | |
|
109 | ||||
|
110 | // TODO: sorting? | |||
68 |
|
111 | |||
69 | // TODO: convenience functions |
|
112 | // TODO: convenience functions | |
70 | //void updateValue(int sliceIndex, qreal value); |
|
113 | //void updateValue(int sliceIndex, qreal value); | |
71 | //void updateLabel(int sliceIndex, QString label); |
|
114 | //void updateLabel(int sliceIndex, QString label); | |
72 | //void updateColor(int sliceIndex, QColor color); |
|
115 | //void updateColor(int sliceIndex, QColor color); | |
73 | //void updateExploded(int slizeIndex, bool exploded); |
|
116 | //void updateExploded(int slizeIndex, bool exploded); | |
74 |
|
117 | |||
|
118 | // TODO: customization | |||
|
119 | // set/get pen/brush | |||
|
120 | // - for label | |||
|
121 | // - for whole pie/slice | |||
|
122 | ||||
75 | void setSizeFactor(qreal sizeFactor); |
|
123 | void setSizeFactor(qreal sizeFactor); | |
76 | qreal sizeFactor() const { return m_sizeFactor; } |
|
124 | qreal sizeFactor() const { return m_sizeFactor; } | |
77 |
|
125 | |||
78 | void setPosition(PiePosition position); |
|
126 | void setPosition(PiePosition position); | |
79 | PiePosition position() const { return m_position; } |
|
127 | PiePosition position() const { return m_position; } | |
80 |
|
128 | |||
81 | Q_SIGNALS: |
|
129 | Q_SIGNALS: | |
82 | void changed(const PieChangeSet& changeSet); |
|
130 | void changed(const QPieSeries::ChangeSet& changeSet); | |
83 | void sizeFactorChanged(); |
|
131 | void sizeFactorChanged(); | |
84 | void positionChanged(); |
|
132 | void positionChanged(); | |
|
133 | //void sliceClicked(QPieSliceId id); | |||
|
134 | //void sliceHoverEnter(QPieSliceId id); | |||
|
135 | //void sliceHoverLeave(QPieSliceId id); | |||
|
136 | ||||
|
137 | private: | |||
|
138 | QPieSliceId generateSliceId(); | |||
|
139 | void updateDerivativeData(); | |||
85 |
|
140 | |||
86 | private: |
|
141 | private: | |
87 | Q_DISABLE_COPY(QPieSeries) |
|
142 | Q_DISABLE_COPY(QPieSeries) | |
88 | friend class PiePresenter; |
|
143 | ||
89 | // TODO: use PIML |
|
144 | // TODO: use PIML | |
90 | QList<QPieSlice> m_slices; |
|
145 | friend class PiePresenter; | |
|
146 | friend class PieSlice; | |||
|
147 | ||||
|
148 | QHash<QPieSliceId, QPieSlice> m_slices; | |||
91 | qreal m_sizeFactor; |
|
149 | qreal m_sizeFactor; | |
92 | PiePosition m_position; |
|
150 | PiePosition m_position; | |
|
151 | qreal m_total; | |||
|
152 | QPieSliceId m_sliceIdSeed; | |||
93 | }; |
|
153 | }; | |
94 |
|
154 | |||
95 | QTCOMMERCIALCHART_END_NAMESPACE |
|
155 | QTCOMMERCIALCHART_END_NAMESPACE | |
96 |
|
156 | |||
97 | #endif // PIESERIES_H |
|
157 | #endif // PIESERIES_H |
General Comments 0
You need to be logged in to leave comments.
Login now