33
33
#include <QPaintDevice>
34
34
#include <QPainter>
35
#include <QPainterPath>
35
36
#include <QVarLengthArray>
37
38
QwtPieCurve::QwtPieCurve(Table *t, const QString& name, int startRow, int endRow):
38
DataCurve(t, QString(), name, startRow, endRow)
39
DataCurve(t, QString(), name, startRow, endRow),
45
d_horizontal_offset(0),
47
d_counter_clockwise(false),
48
d_auto_labeling(true),
52
d_fixed_labels_pos(true)
42
setPen(QPen(QColor(Qt::black), 1, Qt::SolidLine));
43
setBrush(QBrush(Qt::black, Qt::SolidPattern));
54
setPen(QPen(QColor(Qt::black), 1, Qt::SolidLine));
55
setBrush(QBrush(Qt::SolidPattern));
56
setStyle(QwtPlotCurve::UserCurve);
58
d_table_rows = QVarLengthArray<int>(0);
61
void QwtPieCurve::clone(QwtPieCurve* c)
66
d_pie_ray = c->radius();
67
d_first_color = c->firstColor();
68
d_start_azimuth = c->startAzimuth();
69
d_view_angle = c->viewAngle();
70
d_thickness = c->thickness();
71
d_horizontal_offset = c->horizontalOffset();
72
d_edge_dist = c->labelsEdgeDistance();
73
d_counter_clockwise = c->counterClockwise();
74
d_auto_labeling = c->labelsAutoFormat();
75
d_values = c->labelsValuesFormat();
76
d_percentages = c->labelsPercentagesFormat();
77
d_categories = c->labelCategories();
78
d_fixed_labels_pos = c->fixedLabelsPosition();
80
d_table_rows = c->d_table_rows;
48
void QwtPieCurve::draw(QPainter *painter,
49
const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
51
if ( !painter || dataSize() <= 0 )
83
void QwtPieCurve::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
85
int size = dataSize();
86
if ( !painter || size <= 0 )
57
drawPie(painter, xMap, yMap, from, to);
93
drawSlices(painter, xMap, yMap, from, to);
95
drawDisk(painter, xMap, yMap);
60
void QwtPieCurve::drawPie(QPainter *painter,
61
const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
63
int x_center = (xMap.p1() + xMap.p2())/2;
64
int y_center = (yMap.p1() + yMap.p2())/2;
66
int ray = (x_center - xMap.transform(d_left_coord));
70
pieRect.setX(x_center - ray);
71
pieRect.setY(y_center - ray);
76
for (int i = from; i <= to; i++){
77
const double yi = y(i);
98
void QwtPieCurve::drawDisk(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap) const
100
const double x_width = fabs(xMap.p1() - xMap.p2());
101
const double x_center = (xMap.p1() + xMap.p2())*0.5 + d_horizontal_offset*0.01*x_width;
102
const double y_center = (yMap.p1() + yMap.p2())*0.5;
103
const double ray_x = d_pie_ray*0.005*qMin(x_width, fabs(yMap.p1() - yMap.p2()));
104
const double view_angle_rad = d_view_angle*M_PI/180.0;
105
const double ray_y = ray_x*sin(view_angle_rad);
106
const double thick = 0.01*d_thickness*ray_x*cos(view_angle_rad);
109
pieRect.setX(x_center - ray_x);
110
pieRect.setY(y_center - ray_y);
111
pieRect.setWidth(2*ray_x);
112
pieRect.setHeight(2*ray_y);
114
QRectF pieRect2 = pieRect;
115
pieRect2.translate(0, thick);
119
painter->setPen(QwtPlotCurve::pen());
120
painter->setBrush(QBrush(color(0), QwtPlotCurve::brush().style()));
122
QPointF start(x_center + ray_x, y_center);
123
QPainterPath path(start);
124
path.lineTo(start.x(), start.y() + thick);
125
path.arcTo(pieRect2, 0, -180.0);
126
QPointF aux = path.currentPosition();
127
path.lineTo(aux.x(), aux.y() - thick);
128
path.arcTo(pieRect, -180.0, 180.0);
129
painter->drawPath(path);
131
painter->drawEllipse(pieRect);
133
if (d_texts_list.size() > 0){
134
PieLabel* l = d_texts_list[0];
137
if (d_auto_labeling){
139
s += QString::number(d_table_rows[0]) + "\n";
141
if (d_values && d_percentages)
142
s += ((Plot *)plot())->locale().toString(y(0), 'g', 4) + " (100%)";
144
s += ((Plot *)plot())->locale().toString(y(0), 'g', 4);
145
else if (d_percentages)
151
l->setText(l->customText());
153
if (d_fixed_labels_pos){
154
double a_deg = d_start_azimuth + 180.0;
157
double a_rad = a_deg*M_PI/180.0;
158
double rx = ray_x*(1 + 0.01*d_edge_dist);
159
const double x = x_center + rx*cos(a_rad);
160
double ry = ray_y*(1 + 0.01*d_edge_dist);
161
double y = y_center + ry*sin(a_rad);
162
if (a_deg > 0 && a_deg < 180)
165
double dx = xMap.invTransform(x - l->width()/2);
166
double dy = yMap.invTransform(y - l->height()/2);
167
l->setOriginCoord(dx, dy);
174
void QwtPieCurve::drawSlices(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
176
const double x_width = fabs(xMap.p1() - xMap.p2());
177
const double x_center = (xMap.p1() + xMap.p2())*0.5 + d_horizontal_offset*0.01*x_width;
178
const double y_center = (yMap.p1() + yMap.p2())*0.5;
179
const double ray_x = d_pie_ray*0.005*qMin(x_width, fabs(yMap.p1() - yMap.p2()));
180
const double view_angle_rad = d_view_angle*M_PI/180.0;
181
const double ray_y = ray_x*sin(view_angle_rad);
182
const double thick = 0.01*d_thickness*ray_x*cos(view_angle_rad);
185
pieRect.setX(x_center - ray_x);
186
pieRect.setY(y_center - ray_y);
187
pieRect.setWidth(2*ray_x);
188
pieRect.setHeight(2*ray_y);
190
QRectF pieRect2 = pieRect;
191
pieRect2.translate(0, thick);
194
for (int i = from; i <= to; i++)
197
const int sign = d_counter_clockwise ? 1 : -1;
199
const int size = dataSize();
200
double *start_angle = new double[size];
201
double *end_angle = new double[size];
202
double aux_angle = d_start_azimuth;
203
for (int i = from; i <= to; i++){
204
double a = -sign*y(i)/sum*360.0;
205
start_angle[i] = aux_angle;
207
double end = aux_angle + a;
81
int angle = (int)(5760 * 0.75);
217
int angle = (int)(5760 * d_start_azimuth/360.0);
218
if (d_counter_clockwise)
219
angle = (int)(5760 * (1 - d_start_azimuth/360.0));
223
QLocale locale = ((Plot *)plot())->locale();
83
224
for (int i = from; i <= to; i++){
84
225
const double yi = y(i);
85
const int value = (int)(yi/sum*5760);
226
const double q = yi/sum;
227
const int value = (int)(q*5760);
87
229
painter->setPen(QwtPlotCurve::pen());
88
230
painter->setBrush(QBrush(color(i), QwtPlotCurve::brush().style()));
89
painter->drawPie(pieRect, -angle, -value);
233
double start_3D_view_angle = start_angle[i];
234
double end_3D_view_angle = end_angle[i];
235
if (d_counter_clockwise){
236
start_3D_view_angle = end_angle[i];
237
end_3D_view_angle = start_angle[i];
241
if (deg <= 180 && start_3D_view_angle >= 0 && start_3D_view_angle < 180){
242
if ((end_3D_view_angle > 180 && end_3D_view_angle > start_3D_view_angle)){
243
deg = 180 - start_3D_view_angle;
244
end_3D_view_angle = 180.0;
247
} else if (start_3D_view_angle >= 180 && end_3D_view_angle < start_3D_view_angle){
248
if (end_3D_view_angle > 180)
249
end_3D_view_angle = 180;
250
deg = end_3D_view_angle;
251
start_3D_view_angle = 0;
253
} else if (deg > 180 && start_3D_view_angle >= 180){
255
end_3D_view_angle = 180;
256
start_3D_view_angle = 0;
261
double rad = start_3D_view_angle/180.0*M_PI;
262
QPointF start(x_center + ray_x*cos(rad), y_center + ray_y*sin(rad));
263
QPainterPath path(start);
264
path.lineTo(start.x(), start.y() + thick);
265
path.arcTo(pieRect2, -start_3D_view_angle, -deg);
266
QPointF aux = path.currentPosition();
267
path.lineTo(aux.x(), aux.y() - thick);
268
path.arcTo(pieRect, -end_3D_view_angle, deg);
269
painter->drawPath(path);
271
if (start_3D_view_angle >= 0 && start_3D_view_angle < 180){
272
if (end_3D_view_angle > 180)
273
end_3D_view_angle = 0;
275
double rad = start_3D_view_angle/180.0*M_PI;
276
QPointF start(x_center + ray_x*cos(rad), y_center + ray_y*sin(rad));
277
QPainterPath path(start);
278
path.lineTo(start.x(), start.y() + thick);
280
deg = 180 - start_3D_view_angle;
281
path.arcTo(pieRect2, -start_3D_view_angle, -deg);
282
QPointF aux = path.currentPosition();
283
path.lineTo(aux.x(), aux.y() - thick);
284
path.arcTo(pieRect, -180, deg);
285
painter->drawPath(path);
287
path.moveTo(QPointF(x_center + ray_x, y_center));
288
aux = path.currentPosition();
289
path.lineTo(aux.x(), aux.y() + thick);
290
path.arcTo(pieRect2, 0, -end_3D_view_angle);
291
aux = path.currentPosition();
292
path.lineTo(aux.x(), aux.y() - thick);
293
path.arcTo(pieRect, -end_3D_view_angle, end_3D_view_angle);
294
painter->drawPath(path);
298
painter->drawPie(pieRect, sign*angle, sign*value);
301
if (i >= d_texts_list.size())
304
PieLabel* l = d_texts_list[i];
307
if (d_auto_labeling){
309
s += QString::number(d_table_rows[i]) + "\n";
310
if (d_values && d_percentages)
311
s += locale.toString(yi, 'g', 4) + " (" + locale.toString(q*100, 'g', 4) + "%)";
313
s += locale.toString(yi, 'g', 4);
314
else if (d_percentages)
315
s += locale.toString(q*100, 'g', 4) + "%";
320
l->setText(l->customText());
322
if (d_fixed_labels_pos){
323
double a_deg = start_angle[i] - sign*q*180.0;
326
double a_rad = a_deg*M_PI/180.0;
328
double rx = ray_x*(1 + 0.01*d_edge_dist);
329
const double x = x_center + rx*cos(a_rad);
331
double ry = ray_y*(1 + 0.01*d_edge_dist);
332
double y = y_center + ry*sin(a_rad);
333
if (a_deg > 0 && a_deg < 180)
336
double dx = xMap.invTransform(x - l->width()/2);
337
double dy = yMap.invTransform(y - l->height()/2);
338
l->setOriginCoord(dx, dy);
343
delete [] start_angle;
96
347
QColor QwtPieCurve::color(int i) const
98
int index=(d_first_color+i) % ColorBox::numPredefinedColors();
99
return ColorBox::color(index);
349
return ColorBox::color((d_first_color + i) % ColorBox::numPredefinedColors());
102
352
void QwtPieCurve::setBrushStyle(const Qt::BrushStyle& style)
112
362
void QwtPieCurve::loadData()
114
QVarLengthArray<double> X(abs(d_end_row - d_start_row) + 1);
364
Plot *d_plot = (Plot *)plot();
365
QLocale locale = d_plot->locale();
366
QVarLengthArray<double> X(abs(d_end_row - d_start_row) + 1);
367
d_table_rows.resize(abs(d_end_row - d_start_row) + 1);
116
370
int ycol = d_table->colIndex(title().text());
117
371
for (int i = d_start_row; i <= d_end_row; i++ ){
118
372
QString xval = d_table->text(i, ycol);
119
373
bool valid_data = true;
120
374
if (!xval.isEmpty()){
121
X[size] = ((Plot *)plot())->locale().toDouble(xval, &valid_data);
375
X[size] = locale.toDouble(xval, &valid_data);
377
d_table_rows[size] = i + 1;
127
setData(X.data(), X.data(), size);
383
d_table_rows.resize(size);
384
setData(X.data(), X.data(), size);
386
int labels = d_texts_list.size();
387
//If there are no labels (initLabels() wasn't called yet) or if we have enough labels: do nothing!
388
if(d_texts_list.isEmpty() || labels == size)
391
//Else add new pie labels.
392
for (int i = labels; i < size; i++ ){
393
PieLabel* l = new PieLabel(d_plot, this);
399
void QwtPieCurve::addLabel(PieLabel *l, bool clone)
405
PieLabel *newLabel = new PieLabel((Plot *)plot(), this);
407
newLabel->setCustomText(l->customText());
408
d_texts_list << newLabel;
410
l->setPieCurve(this);
415
void QwtPieCurve::removeLabel(PieLabel *l)
420
int index = d_texts_list.indexOf(l);
421
if (index < 0 || index >= d_texts_list.size())
424
PieLabel *newLabel = new PieLabel((Plot *)plot(), this);
426
newLabel->setCustomText(l->customText());
429
d_texts_list.removeAt(index);
430
d_texts_list.insert(index, newLabel);
130
void QwtPieCurve::updateBoundingRect()
433
void QwtPieCurve::initLabels()
135
QwtScaleMap xMap = plot()->canvasMap(xAxis());
136
int x_center = (xMap.p1() + xMap.p2())/2;
137
int x_left = x_center - d_pie_ray;
138
d_left_coord = xMap.invTransform(x_left);
435
int size = abs(d_end_row - d_start_row) + 1;
436
int dataPoints = dataSize();
438
for (int i = 0; i < dataPoints; i++)
441
Plot *d_plot = (Plot *)plot();
442
QLocale locale = d_plot->locale();
443
for (int i = 0; i <size; i++ ){
444
PieLabel* l = new PieLabel(d_plot, this);
447
l->setText(locale.toString(y(i)/sum*100, 'g', 4) + "%");
453
PieLabel::PieLabel(Plot *plot, QwtPieCurve *pie):LegendWidget(plot),
455
d_custom_text(QString::null)
457
setBackgroundColor(QColor(255, 255, 255, 0));
461
QString PieLabel::customText()
463
if (d_custom_text.isEmpty())
466
return d_custom_text;
469
void PieLabel::closeEvent(QCloseEvent* e)
472
d_pie_curve->removeLabel(this);