~showard314/ubuntu/natty/qtiplot/Python2.7_fix

« back to all changes in this revision

Viewing changes to qtiplot/src/QwtPieCurve.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2008-04-04 15:11:55 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404151155-rjp12ziov4tryj0o
Tags: 0.9.4-1
* New upstream release.
* Refresh patches.
* Remove 04_homepage_url patch. Merged upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
    File                 : QwtPieCurve.cpp
3
3
    Project              : QtiPlot
4
4
    --------------------------------------------------------------------
5
 
    Copyright            : (C) 2006 by Ion Vasilief, Tilman Hoener zu Siederdissen
6
 
    Email (use @ for *)  : ion_vasilief*yahoo.fr, thzs*gmx.net
 
5
    Copyright            : (C) 2004 - 2008 by Ion Vasilie
 
6
    Email (use @ for *)  : ion_vasilief*yahoo.fr
7
7
    Description          : Pie plot class
8
8
 
9
9
 ***************************************************************************/
32
32
 
33
33
#include <QPaintDevice>
34
34
#include <QPainter>
 
35
#include <QPainterPath>
35
36
#include <QVarLengthArray>
36
37
 
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),
 
40
        d_pie_ray(50),
 
41
        d_first_color(0),
 
42
        d_start_azimuth(270),
 
43
        d_view_angle(33),
 
44
        d_thickness(33),
 
45
        d_horizontal_offset(0),
 
46
        d_edge_dist(25),
 
47
        d_counter_clockwise(false),
 
48
        d_auto_labeling(true),
 
49
        d_values(false),
 
50
        d_percentages(true),
 
51
        d_categories(false),
 
52
        d_fixed_labels_pos(true)
39
53
{
40
 
        d_pie_ray = 100;
41
 
        d_first_color = 0;
42
 
        setPen(QPen(QColor(Qt::black), 1, Qt::SolidLine));
43
 
        setBrush(QBrush(Qt::black, Qt::SolidPattern));
44
 
 
45
 
        setType(Graph::Pie);
 
54
        setPen(QPen(QColor(Qt::black), 1, Qt::SolidLine));
 
55
        setBrush(QBrush(Qt::SolidPattern));
 
56
    setStyle(QwtPlotCurve::UserCurve);
 
57
        setType(Graph::Pie);
 
58
        d_table_rows = QVarLengthArray<int>(0);
46
59
}
 
60
 
 
61
void QwtPieCurve::clone(QwtPieCurve* c)
 
62
{
 
63
    if (!c)
 
64
        return;
 
65
 
 
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();
 
79
 
 
80
        d_table_rows = c->d_table_rows;
 
81
}
47
82
 
48
 
void QwtPieCurve::draw(QPainter *painter,
49
 
                const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
50
 
{
51
 
        if ( !painter || dataSize() <= 0 )
 
83
void QwtPieCurve::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
 
84
{
 
85
    int size = dataSize();
 
86
        if ( !painter ||  size <= 0 )
52
87
                return;
53
88
 
54
89
        if (to < 0)
55
 
                to = dataSize() - 1;
56
 
 
57
 
        drawPie(painter, xMap, yMap, from, to);
 
90
                to = size - 1;
 
91
 
 
92
    if (size > 1)
 
93
        drawSlices(painter, xMap, yMap, from, to);
 
94
    else
 
95
        drawDisk(painter, xMap, yMap);
58
96
}
59
 
 
60
 
void QwtPieCurve::drawPie(QPainter *painter,
61
 
                const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
62
 
{
63
 
        int x_center = (xMap.p1() + xMap.p2())/2;
64
 
        int y_center = (yMap.p1() + yMap.p2())/2;
65
 
 
66
 
        int ray = (x_center - xMap.transform(d_left_coord));
67
 
    int d = 2*ray;
68
 
 
69
 
        QRect pieRect;
70
 
        pieRect.setX(x_center - ray);
71
 
        pieRect.setY(y_center - ray);
72
 
        pieRect.setWidth(d);
73
 
        pieRect.setHeight(d);
74
 
 
75
 
        double sum = 0.0;
76
 
        for (int i = from; i <= to; i++){
77
 
                const double yi = y(i);
78
 
                sum += yi;
 
97
 
 
98
void QwtPieCurve::drawDisk(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap) const
 
99
{
 
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);
 
107
 
 
108
        QRectF pieRect;
 
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);
 
113
 
 
114
        QRectF pieRect2 = pieRect;
 
115
    pieRect2.translate(0, thick);
 
116
 
 
117
    painter->save();
 
118
 
 
119
    painter->setPen(QwtPlotCurve::pen());
 
120
    painter->setBrush(QBrush(color(0), QwtPlotCurve::brush().style()));
 
121
 
 
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);
 
130
 
 
131
    painter->drawEllipse(pieRect);
 
132
 
 
133
    if (d_texts_list.size() > 0){
 
134
        PieLabel* l = d_texts_list[0];
 
135
        if (l){
 
136
            QString s;
 
137
            if (d_auto_labeling){
 
138
                                if (d_categories)
 
139
                                        s += QString::number(d_table_rows[0]) + "\n";
 
140
 
 
141
                if (d_values && d_percentages)
 
142
                    s += ((Plot *)plot())->locale().toString(y(0), 'g', 4) + " (100%)";
 
143
                else if (d_values)
 
144
                    s += ((Plot *)plot())->locale().toString(y(0), 'g', 4);
 
145
                else if (d_percentages)
 
146
                    s += "100%";
 
147
                l->setText(s);
 
148
                                if (l->isHidden())
 
149
                                        l->show();
 
150
            } else
 
151
                                l->setText(l->customText());
 
152
 
 
153
            if (d_fixed_labels_pos){
 
154
                double a_deg = d_start_azimuth + 180.0;
 
155
                if (a_deg > 360)
 
156
                    a_deg -= 360;
 
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)
 
163
                    y += thick;
 
164
 
 
165
                double dx = xMap.invTransform(x - l->width()/2);
 
166
                double dy = yMap.invTransform(y - l->height()/2);
 
167
                l->setOriginCoord(dx, dy);
 
168
            }
 
169
        }
 
170
    }
 
171
    painter->restore();
 
172
}
 
173
 
 
174
void QwtPieCurve::drawSlices(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
 
175
{
 
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);
 
183
 
 
184
        QRectF pieRect;
 
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);
 
189
 
 
190
        QRectF pieRect2 = pieRect;
 
191
    pieRect2.translate(0, thick);
 
192
 
 
193
        double sum = 0.0;
 
194
        for (int i = from; i <= to; i++)
 
195
                sum += y(i);
 
196
 
 
197
        const int sign = d_counter_clockwise ? 1 : -1;
 
198
 
 
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;
 
206
 
 
207
                double end = aux_angle + a;
 
208
                if (end >= 360)
 
209
            end -= 360;
 
210
        else if (end < 0)
 
211
            end += 360;
 
212
 
 
213
                end_angle[i] = end;
 
214
                aux_angle = end;
79
215
        }
80
216
 
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));
 
220
 
82
221
        painter->save();
 
222
 
 
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);
86
228
 
87
229
                painter->setPen(QwtPlotCurve::pen());
88
230
                painter->setBrush(QBrush(color(i), QwtPlotCurve::brush().style()));
89
 
                painter->drawPie(pieRect, -angle, -value);
90
 
 
 
231
 
 
232
                double deg = q*360;
 
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];
 
238
                }
 
239
 
 
240
        bool draw3D = false;
 
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;
 
245
            }
 
246
            draw3D = true;
 
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;
 
252
            draw3D = true;
 
253
                } else if (deg > 180 && start_3D_view_angle >= 180){
 
254
            deg = 180;
 
255
            end_3D_view_angle = 180;
 
256
            start_3D_view_angle = 0;
 
257
            draw3D = true;
 
258
                }
 
259
 
 
260
                if (draw3D){
 
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);
 
270
        } else {
 
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;
 
274
 
 
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);
 
279
 
 
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);
 
286
 
 
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);
 
295
            }
 
296
        }
 
297
 
 
298
                painter->drawPie(pieRect, sign*angle, sign*value);
91
299
                angle += value;
 
300
 
 
301
                if (i >= d_texts_list.size())
 
302
                        continue;
 
303
 
 
304
                PieLabel* l = d_texts_list[i];
 
305
                if (l){
 
306
                        QString s;
 
307
                        if (d_auto_labeling){
 
308
                                if (d_categories)
 
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) + "%)";
 
312
                                else if (d_values)
 
313
                                        s += locale.toString(yi, 'g', 4);
 
314
                                else if (d_percentages)
 
315
                                        s += locale.toString(q*100, 'g', 4) + "%";
 
316
                l->setText(s);
 
317
                                if (l->isHidden())
 
318
                                        l->show();
 
319
                        } else
 
320
                                l->setText(l->customText());
 
321
 
 
322
            if (d_fixed_labels_pos){
 
323
                double a_deg = start_angle[i] - sign*q*180.0;
 
324
                if (a_deg > 360)
 
325
                    a_deg -= 360.0;
 
326
                double a_rad = a_deg*M_PI/180.0;
 
327
 
 
328
                double rx = ray_x*(1 + 0.01*d_edge_dist);
 
329
                const double x = x_center + rx*cos(a_rad);
 
330
 
 
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)
 
334
                    y += thick;
 
335
 
 
336
                double dx = xMap.invTransform(x - l->width()/2);
 
337
                double dy = yMap.invTransform(y - l->height()/2);
 
338
                l->setOriginCoord(dx, dy);
 
339
            }
 
340
                }
92
341
        }
93
 
        painter->restore();
 
342
        painter->restore();
 
343
        delete [] start_angle;
 
344
        delete [] end_angle;
94
345
}
95
346
 
96
347
QColor QwtPieCurve::color(int i) const
97
348
{
98
 
        int index=(d_first_color+i) % ColorBox::numPredefinedColors();
99
 
        return ColorBox::color(index);
 
349
        return ColorBox::color((d_first_color + i) % ColorBox::numPredefinedColors());
100
350
}
101
351
 
102
352
void QwtPieCurve::setBrushStyle(const Qt::BrushStyle& style)
110
360
}
111
361
 
112
362
void QwtPieCurve::loadData()
113
 
{
114
 
        QVarLengthArray<double> X(abs(d_end_row - d_start_row) + 1);
 
363
{
 
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);
 
368
 
115
369
        int size = 0;
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);
122
 
            if (valid_data)
123
 
                size++;
 
375
            X[size] = locale.toDouble(xval, &valid_data);
 
376
            if (valid_data){
 
377
                                d_table_rows[size] = i + 1;
 
378
                size++;
 
379
                        }
124
380
                }
125
381
        }
126
 
        X.resize(size);
127
 
        setData(X.data(), X.data(), size);
 
382
        X.resize(size);
 
383
        d_table_rows.resize(size);
 
384
        setData(X.data(), X.data(), size);
 
385
        
 
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)
 
389
                return;
 
390
 
 
391
        //Else add new pie labels.
 
392
        for (int i = labels; i < size; i++ ){
 
393
                PieLabel* l = new PieLabel(d_plot, this);
 
394
                d_texts_list << l;
 
395
                l->hide();
 
396
        }
128
397
}
 
398
 
 
399
void QwtPieCurve::addLabel(PieLabel *l, bool clone)
 
400
{
 
401
        if (!l)
 
402
                return;
 
403
 
 
404
        if (clone){
 
405
                PieLabel *newLabel = new PieLabel((Plot *)plot(), this);
 
406
                newLabel->clone(l);
 
407
                newLabel->setCustomText(l->customText());
 
408
                d_texts_list << newLabel;
 
409
        } else {
 
410
                l->setPieCurve(this);
 
411
                d_texts_list << l;
 
412
        }
 
413
}
 
414
 
 
415
void QwtPieCurve::removeLabel(PieLabel *l)
 
416
{
 
417
        if (!l)
 
418
                return;
 
419
 
 
420
        int index = d_texts_list.indexOf(l);
 
421
        if (index < 0 || index >= d_texts_list.size())
 
422
                return;
 
423
 
 
424
        PieLabel *newLabel = new PieLabel((Plot *)plot(), this);
 
425
        newLabel->clone(l);
 
426
        newLabel->setCustomText(l->customText());
 
427
        newLabel->hide();
 
428
 
 
429
        d_texts_list.removeAt(index);
 
430
        d_texts_list.insert(index, newLabel);
 
431
}
129
432
 
130
 
void QwtPieCurve::updateBoundingRect()
 
433
void QwtPieCurve::initLabels()
131
434
{
132
 
    if (!plot())
133
 
        return;
134
 
 
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();
 
437
        double sum = 0.0;
 
438
        for (int i = 0; i < dataPoints; i++)
 
439
                sum += y(i);
 
440
 
 
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);
 
445
                d_texts_list << l;
 
446
                if (i < dataPoints)
 
447
            l->setText(locale.toString(y(i)/sum*100, 'g', 4) + "%");
 
448
                else
 
449
                        l->hide();
 
450
        }
 
451
}
 
452
 
 
453
PieLabel::PieLabel(Plot *plot, QwtPieCurve *pie):LegendWidget(plot),
 
454
        d_pie_curve(pie),
 
455
        d_custom_text(QString::null)
 
456
{
 
457
        setBackgroundColor(QColor(255, 255, 255, 0));
 
458
        setFrameStyle(0);
 
459
}
 
460
 
 
461
QString PieLabel::customText()
 
462
{
 
463
        if (d_custom_text.isEmpty())
 
464
                return text();
 
465
 
 
466
        return d_custom_text;
 
467
}
 
468
 
 
469
void PieLabel::closeEvent(QCloseEvent* e)
 
470
{
 
471
        if(d_pie_curve)
 
472
                d_pie_curve->removeLabel(this);
 
473
        e->accept();
139
474
}