1 /***************************************************************************
2     File                 : QwtPieCurve.cpp
3     Project              : SciDAVis
4     --------------------------------------------------------------------
5     Copyright            : (C) 2006 by Ion Vasilief, Tilman Benkert
6     Email (use @ for *)  : ion_vasilief*yahoo.fr, thzs*gmx.net
7     Description          : Pie plot class
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *  This program is free software; you can redistribute it and/or modify   *
14  *  it under the terms of the GNU General Public License as published by   *
15  *  the Free Software Foundation; either version 2 of the License, or      *
16  *  (at your option) any later version.                                    *
17  *                                                                         *
18  *  This program is distributed in the hope that it will be useful,        *
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
21  *  GNU General Public License for more details.                           *
22  *                                                                         *
23  *   You should have received a copy of the GNU General Public License     *
24  *   along with this program; if not, write to the Free Software           *
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
26  *   Boston, MA  02110-1301  USA                                           *
27  *                                                                         *
28  ***************************************************************************/
29 #include "QwtPieCurve.h"
30 #include "ColorButton.h"
31 #include "Table.h"
32 #include "core/column/Column.h"
33 
34 #include <QPaintDevice>
35 #include <QPainter>
36 #include <QVarLengthArray>
37 #include <QLocale>
38 
39 #include <qwt_plot_layout.h>
40 
QwtPieCurve(Table * t,const QString & name,int startRow,int endRow)41 QwtPieCurve::QwtPieCurve(Table *t, const QString &name, int startRow, int endRow)
42     : DataCurve(t, QString(), name, startRow, endRow)
43 {
44     d_pie_ray = 100;
45     d_first_color = 0;
46     setPen(QPen(QColor(Qt::black), 1, Qt::SolidLine));
47     setBrush(QBrush(Qt::black, Qt::SolidPattern));
48 
49     setType(Graph::Pie);
50 }
51 
draw(QPainter * painter,const QwtScaleMap & xMap,const QwtScaleMap & yMap,int from,int to) const52 void QwtPieCurve::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap,
53                        int from, int to) const
54 {
55     if (!painter || dataSize() <= 0)
56         return;
57 
58     if (to < 0)
59         to = dataSize() - 1;
60 
61     drawPie(painter, xMap, yMap, from, to);
62 }
63 
drawPie(QPainter * painter,const QwtScaleMap &,const QwtScaleMap &,int from,int to) const64 void QwtPieCurve::drawPie(QPainter *painter, const QwtScaleMap &, const QwtScaleMap &, int from,
65                           int to) const
66 {
67     // This has to be synced with Graph::plotPie() for now... until we have a clean solution.
68     QRect canvas_rect = plot()->plotLayout()->canvasRect();
69     int radius = 0.4 * qMin(canvas_rect.width(), canvas_rect.height());
70 
71     QRect pieRect;
72     pieRect.setX(canvas_rect.center().x() - radius);
73     pieRect.setY(canvas_rect.center().y() - radius);
74     pieRect.setWidth(2 * radius);
75     pieRect.setHeight(2 * radius);
76 
77     double sum = 0.0;
78     for (int i = from; i <= to; i++) {
79         const double yi = y(i);
80         sum += yi;
81     }
82 
83     int angle = (int)(5760 * 0.75);
84     painter->save();
85     for (int i = from; i <= to; i++) {
86         const double yi = y(i);
87         const int value = (int)(yi / sum * 5760);
88 
89         painter->setPen(QwtPlotCurve::pen());
90         painter->setBrush(QBrush(color(i), QwtPlotCurve::brush().style()));
91         painter->drawPie(pieRect, -angle, -value);
92 
93         angle += value;
94     }
95     painter->restore();
96 }
97 
color(int i) const98 QColor QwtPieCurve::color(int i) const
99 {
100     int index = (d_first_color + i) % ColorButton::colors_count;
101     return ColorButton::color(index);
102 }
103 
setBrushStyle(const Qt::BrushStyle & style)104 void QwtPieCurve::setBrushStyle(const Qt::BrushStyle &style)
105 {
106     QBrush br = QwtPlotCurve::brush();
107     if (br.style() == style)
108         return;
109 
110     br.setStyle(style);
111     setBrush(br);
112 }
113 
loadData()114 bool QwtPieCurve::loadData()
115 {
116     QVarLengthArray<double> Y(abs(d_end_row - d_start_row) + 1);
117     int size = 0;
118     int ycol = d_table->colIndex(title().text());
119     Column *y_col_ptr = d_table->column(ycol);
120     auto yColType = d_table->columnType(ycol);
121 
122     for (int row = d_start_row; row <= d_end_row && row < y_col_ptr->rowCount(); row++) {
123         if (!y_col_ptr->isInvalid(row)) {
124             if (yColType == SciDAVis::ColumnMode::Text) {
125                 QString yval = y_col_ptr->textAt(row);
126                 bool valid_data = true;
127                 Y[size] = QLocale().toDouble(yval, &valid_data);
128                 if (!valid_data)
129                     continue;
130             } else
131                 Y[size] = y_col_ptr->valueAt(row);
132 
133             size++;
134         }
135     }
136     Y.resize(size);
137     setData(Y.data(), Y.data(), size);
138 
139     return true;
140 }
141 
updateBoundingRect()142 void QwtPieCurve::updateBoundingRect()
143 {
144     if (!plot())
145         return;
146 
147     QwtScaleMap xMap = plot()->canvasMap(xAxis());
148     int x_center = (xMap.p1() + xMap.p2()) / 2;
149     int x_left = x_center - d_pie_ray;
150     d_left_coord = xMap.invTransform(x_left);
151 }
152