##// END OF EJS Templates
Some spline fixes
Marek Rosa -
r455:49ff5e3c0df2
parent child
Show More
@@ -1,77 +1,78
1 1 #include "splinepresenter_p.h"
2 2 #include <QPainter>
3 3
4 4 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5 5
6 6 SplinePresenter::SplinePresenter(QSplineSeries* series, QGraphicsObject *parent) :
7 7 LineChartItem(series, parent)//,m_boundingRect()
8 8 {
9 9 //
10 10 }
11 11
12 12
13 13
14 14 QPointF SplinePresenter::calculateGeometryControlPoint(int index) const
15 15 {
16 16 QSplineSeries* splineSeries = qobject_cast<QSplineSeries*>(m_series);
17 17 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
18 18 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
19 19 qreal x = (splineSeries->controlPoint(index).x() - m_minX)* deltaX;
20 20 qreal y = (splineSeries->controlPoint(index).y() - m_minY)*-deltaY + m_size.height();
21 21 return QPointF(x,y);
22 22 }
23 23
24 24 void SplinePresenter::applyGeometry(QVector<QPointF>& points)
25 25 {
26 26 if(points.size()==0) return;
27 27
28 qDebug() << "Kueku";
28 29 QPainterPath splinePath;
29 30 const QPointF& point = points.at(0);
30 31 splinePath.moveTo(point);
31 32
32 33 // QSplineSeries* splineSeries = qobject_cast<QSplineSeries*>(m_series);
33 34 for (int i = 0; i < points.size() - 1; i++)
34 35 {
35 36 const QPointF& point = points.at(i + 1);
36 37 splinePath.cubicTo(calculateGeometryControlPoint(2 * i), calculateGeometryControlPoint(2 * i + 1), point);
37 38 }
38 39
39 40
40 41
41 42 prepareGeometryChange();
42 43 m_path = splinePath;
43 44 m_rect = splinePath.boundingRect();
44 45 }
45 46
46 47 void SplinePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
47 48 {
48 49 Q_UNUSED(widget);
49 50 Q_UNUSED(option);
50 51 painter->save();
51 52 painter->setPen(m_pen);
52 53 painter->setClipRect(m_clipRect);
53 54 painter->drawPath(m_path);
54 55
55 56 QSplineSeries* splineSeries = qobject_cast<QSplineSeries*>(m_series);
56 57 for (int i = 0; i < m_points.size() - 1; i++)
57 58 {
58 59 painter->setPen(Qt::red);
59 60 painter->drawEllipse(m_points[i], 2, 2);
60 61
61 62 painter->setPen(Qt::blue);
62 63 // painter->drawLine(m_series->at(i), m_series->controlPoint(2 * i));
63 64 // painter->drawLine(m_series->at(i + 1), m_series->controlPoint(2 * i + 1));
64 65 // painter->drawEllipse(calculateGeometryControlPoint(2 * i), 4, 4);
65 66 // painter->drawEllipse(calculateGeometryControlPoint(2 * i + 1), 4, 4);
66 67 }
67 68 if (m_points.count() > 0)
68 69 {
69 70 painter->setPen(Qt::red);
70 71 painter->drawEllipse(m_points[m_points.count() - 1], 2, 2);
71 72 }
72 73 painter->restore();
73 74 }
74 75
75 76 #include "moc_splinepresenter_p.cpp"
76 77
77 78 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,33 +1,28
1 1 #ifndef SPLINEPRESENTER_P_H
2 2 #define SPLINEPRESENTER_P_H
3 3
4 4 #include "chartitem_p.h"
5 5 #include <QObject>
6 6 #include "qsplineseries.h"
7 7 #include "linechartitem_p.h"
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class SplinePresenter : public LineChartItem
12 12 {
13 13 Q_OBJECT
14 14 public:
15 15 SplinePresenter(QSplineSeries* series, QGraphicsObject *parent = 0);
16 16
17 17 void updateGeometry();
18 18
19 19 void applyGeometry(QVector<QPointF>& points);
20 20
21 21 QPointF calculateGeometryControlPoint(int index) const;
22 22
23 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
24
25 signals:
26
27 public slots:
28
23 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
29 24 };
30 25
31 26 QTCOMMERCIALCHART_END_NAMESPACE
32 27
33 28 #endif // SPLINEPRESENTER_P_H
@@ -1,342 +1,357
1 1 #include "mainwidget.h"
2 2 #include "dataseriedialog.h"
3 3 #include "qpieseries.h"
4 4 #include "qscatterseries.h"
5 5 #include <qlineseries.h>
6 #include "qsplineseries.h"
6 7 #include <qbarset.h>
7 8 #include <qbarseries.h>
8 9 #include <qstackedbarseries.h>
9 10 #include <qpercentbarseries.h>
10 11 #include <QPushButton>
11 12 #include <QComboBox>
12 13 #include <QSpinBox>
13 14 #include <QCheckBox>
14 15 #include <QGridLayout>
15 16 #include <QHBoxLayout>
16 17 #include <QLabel>
17 18 #include <QSpacerItem>
18 19 #include <QMessageBox>
19 20 #include <cmath>
20 21 #include <QDebug>
21 22 #include <QStandardItemModel>
22 23
23 24
24 25 QTCOMMERCIALCHART_USE_NAMESPACE
25 26
26 27 MainWidget::MainWidget(QWidget *parent) :
27 28 QWidget(parent),
28 29 m_addSerieDialog(0),
29 30 m_chartView(0)
30 31 {
31 32 m_chartView = new QChartView(this);
32 33 m_chartView->setRubberBandPolicy(QChartView::HorizonalRubberBand);
33 34
34 35 // Grid layout for the controls for configuring the chart widget
35 36 QGridLayout *grid = new QGridLayout();
36 37 QPushButton *addSeriesButton = new QPushButton("Add series");
37 38 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
38 39 grid->addWidget(addSeriesButton, 0, 1);
39 40 initBackroundCombo(grid);
40 41 initScaleControls(grid);
41 42 initThemeCombo(grid);
42 43 initCheckboxes(grid);
43 44
44 45 // add row with empty label to make all the other rows static
45 46 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
46 47 grid->setRowStretch(grid->rowCount() - 1, 1);
47 48
48 49 // Another grid layout as a main layout
49 50 QGridLayout *mainLayout = new QGridLayout();
50 51 mainLayout->addLayout(grid, 0, 0);
51 52
52 53 // Add layouts and the chart widget to the main layout
53 54 mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
54 55 setLayout(mainLayout);
55 56 }
56 57
57 58 // Combo box for selecting the chart's background
58 59 void MainWidget::initBackroundCombo(QGridLayout *grid)
59 60 {
60 61 QComboBox *backgroundCombo = new QComboBox(this);
61 62 backgroundCombo->addItem("Color");
62 63 backgroundCombo->addItem("Gradient");
63 64 backgroundCombo->addItem("Image");
64 65 connect(backgroundCombo, SIGNAL(currentIndexChanged(int)),
65 66 this, SLOT(backgroundChanged(int)));
66 67
67 68 grid->addWidget(new QLabel("Background:"), grid->rowCount(), 0);
68 69 grid->addWidget(backgroundCombo, grid->rowCount() - 1, 1);
69 70 }
70 71
71 72 // Scale related controls (auto-scale vs. manual min-max values)
72 73 void MainWidget::initScaleControls(QGridLayout *grid)
73 74 {
74 75 m_autoScaleCheck = new QCheckBox("Automatic scaling");
75 76 connect(m_autoScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(autoScaleChanged(int)));
76 77 // Allow setting also non-sense values (like -2147483648 and 2147483647)
77 78 m_xMinSpin = new QSpinBox();
78 79 m_xMinSpin->setMinimum(INT_MIN);
79 80 m_xMinSpin->setMaximum(INT_MAX);
80 81 m_xMinSpin->setValue(0);
81 82 connect(m_xMinSpin, SIGNAL(valueChanged(int)), this, SLOT(xMinChanged(int)));
82 83 m_xMaxSpin = new QSpinBox();
83 84 m_xMaxSpin->setMinimum(INT_MIN);
84 85 m_xMaxSpin->setMaximum(INT_MAX);
85 86 m_xMaxSpin->setValue(10);
86 87 connect(m_xMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(xMaxChanged(int)));
87 88 m_yMinSpin = new QSpinBox();
88 89 m_yMinSpin->setMinimum(INT_MIN);
89 90 m_yMinSpin->setMaximum(INT_MAX);
90 91 m_yMinSpin->setValue(0);
91 92 connect(m_yMinSpin, SIGNAL(valueChanged(int)), this, SLOT(yMinChanged(int)));
92 93 m_yMaxSpin = new QSpinBox();
93 94 m_yMaxSpin->setMinimum(INT_MIN);
94 95 m_yMaxSpin->setMaximum(INT_MAX);
95 96 m_yMaxSpin->setValue(10);
96 97 connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int)));
97 98
98 99 grid->addWidget(m_autoScaleCheck, grid->rowCount(), 0);
99 100 grid->addWidget(new QLabel("x min:"), grid->rowCount(), 0);
100 101 grid->addWidget(m_xMinSpin, grid->rowCount() - 1, 1);
101 102 grid->addWidget(new QLabel("x max:"), grid->rowCount(), 0);
102 103 grid->addWidget(m_xMaxSpin, grid->rowCount() - 1, 1);
103 104 grid->addWidget(new QLabel("y min:"), grid->rowCount(), 0);
104 105 grid->addWidget(m_yMinSpin, grid->rowCount() - 1, 1);
105 106 grid->addWidget(new QLabel("y max:"), grid->rowCount(), 0);
106 107 grid->addWidget(m_yMaxSpin, grid->rowCount() - 1, 1);
107 108
108 109 m_autoScaleCheck->setChecked(true);
109 110 }
110 111
111 112 // Combo box for selecting theme
112 113 void MainWidget::initThemeCombo(QGridLayout *grid)
113 114 {
114 115 QComboBox *chartTheme = new QComboBox();
115 116 chartTheme->addItem("Default");
116 117 chartTheme->addItem("Vanilla");
117 118 chartTheme->addItem("Icy");
118 119 chartTheme->addItem("Grayscale");
119 120 chartTheme->addItem("Scientific");
120 121 chartTheme->addItem("Unnamed1");
121 122 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
122 123 this, SLOT(changeChartTheme(int)));
123 124 grid->addWidget(new QLabel("Chart theme:"), 8, 0);
124 125 grid->addWidget(chartTheme, 8, 1);
125 126 }
126 127
127 128 // Different check boxes for customizing chart
128 129 void MainWidget::initCheckboxes(QGridLayout *grid)
129 130 {
130 131 // TODO: setZoomEnabled slot has been removed from QChartView -> Re-implement zoom on/off
131 132 QCheckBox *zoomCheckBox = new QCheckBox("Drag'n drop Zoom");
132 133 connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartView, SLOT(setZoomEnabled(bool)));
133 134 zoomCheckBox->setChecked(true);
134 135 grid->addWidget(zoomCheckBox, grid->rowCount(), 0);
135 136
136 137 QCheckBox *aliasCheckBox = new QCheckBox("Anti-alias");
137 138 connect(aliasCheckBox, SIGNAL(toggled(bool)), this, SLOT(antiAliasToggled(bool)));
138 139 aliasCheckBox->setChecked(false);
139 140 grid->addWidget(aliasCheckBox, grid->rowCount(), 0);
140 141 }
141 142
142 143 void MainWidget::antiAliasToggled(bool enabled)
143 144 {
144 145 m_chartView->setRenderHint(QPainter::Antialiasing, enabled);
145 146 }
146 147
147 148 void MainWidget::addSeries()
148 149 {
149 150 if (!m_addSerieDialog) {
150 151 m_addSerieDialog = new DataSerieDialog(this);
151 152 connect(m_addSerieDialog, SIGNAL(accepted(QString, int, int, QString, bool)),
152 153 this, SLOT(addSeries(QString, int, int, QString, bool)));
153 154 }
154 155 m_addSerieDialog->exec();
155 156 }
156 157
157 158 QList<RealList> MainWidget::generateTestData(int columnCount, int rowCount, QString dataCharacteristics)
158 159 {
159 160 // TODO: dataCharacteristics
160 161 QList<RealList> testData;
161 162 for (int j(0); j < columnCount; j++) {
162 163 QList <qreal> newColumn;
163 164 for (int i(0); i < rowCount; i++) {
164 165 if (dataCharacteristics == "Sin") {
165 166 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100));
166 167 } else if (dataCharacteristics == "Sin + random") {
167 168 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
168 169 } else if (dataCharacteristics == "Random") {
169 170 newColumn.append(rand() % 5);
170 171 } else if (dataCharacteristics == "Linear") {
171 172 //newColumn.append(i * (j + 1.0));
172 173 // TODO: temporary hack to make pie work; prevent zero values:
173 174 newColumn.append(i * (j + 1.0) + 0.1);
174 175 } else { // "constant"
175 176 newColumn.append((j + 1.0));
176 177 }
177 178 }
178 179 testData.append(newColumn);
179 180 }
180 181 return testData;
181 182 }
182 183
183 184 QStringList MainWidget::generateLabels(int count)
184 185 {
185 186 QStringList result;
186 187 for (int i(0); i < count; i++)
187 188 result.append("label" + QString::number(i));
188 189 return result;
189 190 }
190 191
191 192 void MainWidget::addSeries(QString seriesName, int columnCount, int rowCount, QString dataCharacteristics, bool labelsEnabled)
192 193 {
193 194 qDebug() << "addSeries: " << seriesName
194 195 << " columnCount: " << columnCount
195 196 << " rowCount: " << rowCount
196 197 << " dataCharacteristics: " << dataCharacteristics
197 198 << " labels enabled: " << labelsEnabled;
198 199 m_defaultSeriesName = seriesName;
199 200
200 201 QList<RealList> data = generateTestData(columnCount, rowCount, dataCharacteristics);
201 202
202 203 // Line series and scatter series use similar data
203 if (seriesName.contains("line", Qt::CaseInsensitive)) {
204 if (seriesName.contains("qline", Qt::CaseInsensitive)) {
204 205 for (int j(0); j < data.count(); j ++) {
205 206 QList<qreal> column = data.at(j);
206 207 QLineSeries *series = new QLineSeries();
207 208 for (int i(0); i < column.count(); i++) {
208 209 series->add(i, column.at(i));
209 210 }
210 211 m_chartView->addSeries(series);
211 212 setCurrentSeries(series);
212 213 }
213 214 } else if (seriesName.contains("scatter", Qt::CaseInsensitive)) {
214 215 for (int j(0); j < data.count(); j++) {
215 216 QList<qreal> column = data.at(j);
216 217 QScatterSeries *series = new QScatterSeries();
217 218 for (int i(0); i < column.count(); i++) {
218 (*series) << QPointF(i, column.at(i));
219 (*series) << QPointF(i, column.at(i));
219 220 }
220 221 m_chartView->addSeries(series);
221 222 setCurrentSeries(series);
222 223 }
223 224 } else if (seriesName.contains("pie", Qt::CaseInsensitive)) {
224 225 QStringList labels = generateLabels(rowCount);
225 226 for (int j(0); j < data.count(); j++) {
226 227 QPieSeries *series = new QPieSeries();
227 228 QList<qreal> column = data.at(j);
228 229 for (int i(0); i < column.count(); i++) {
229 230 series->add(column.at(i), labels.at(i));
230 231 }
231 232 m_chartView->addSeries(series);
232 233 setCurrentSeries(series);
233 234 }
234 235 } else if (seriesName == "Bar"
235 236 || seriesName == "Stacked bar"
236 237 || seriesName == "Percent bar") {
237 238 QStringList category;
238 239 QStringList labels = generateLabels(rowCount);
239 240 foreach(QString label, labels)
240 241 category << label;
241 242 QBarSeries* series = 0;
242 243 if (seriesName == "Bar")
243 244 series = new QBarSeries(category, this);
244 245 else if (seriesName == "Stacked bar")
245 246 series = new QStackedBarSeries(category, this);
246 247 else
247 248 series = new QPercentBarSeries(category, this);
248 249
249 250 for (int j(0); j < data.count(); j++) {
250 251 QList<qreal> column = data.at(j);
251 252 QBarSet *set = new QBarSet("set" + QString::number(j));
252 253 for (int i(0); i < column.count(); i++) {
253 254 *set << column.at(i);
254 255 }
255 256 series->addBarSet(set);
256 257 }
258
257 259 // TODO: new implementation of setFloatingValuesEnabled with signals
258 260 //series->setFloatingValuesEnabled(true);
259 261 series->setToolTipEnabled(true);
260 262 series->setSeparatorsEnabled(false);
261 263 m_chartView->addSeries(series);
262 264 setCurrentSeries(series);
263 265 }
266 else if (seriesName.contains("spline", Qt::CaseInsensitive)) {
267 for (int j(0); j < data.count(); j ++) {
268 QList<qreal> column = data.at(j);
269 QSplineSeries *series = new QSplineSeries();
270 for (int i(0); i < column.count(); i++) {
271 series->add(i, column.at(i));
272 }
273 m_chartView->addSeries(series);
274 setCurrentSeries(series);
275 }
264 276
265 // TODO: spline and area
277 // TODO: area
278 }
266 279 }
267 280
268 281 void MainWidget::setCurrentSeries(QSeries *series)
269 282 {
270 283 if (series) {
271 284 m_currentSeries = series;
272 285 switch (m_currentSeries->type()) {
273 286 case QSeries::SeriesTypeLine:
274 287 break;
275 288 case QSeries::SeriesTypeScatter:
276 289 break;
277 290 case QSeries::SeriesTypePie:
278 291 break;
279 292 case QSeries::SeriesTypeBar:
280 293 qDebug() << "setCurrentSeries (bar)";
281 294 break;
282 295 case QSeries::SeriesTypeStackedBar:
283 296 qDebug() << "setCurrentSeries (Stackedbar)";
284 297 break;
285 298 case QSeries::SeriesTypePercentBar:
286 299 qDebug() << "setCurrentSeries (Percentbar)";
287 300 break;
301 case QSeries::SeriesTypeSpline:
302 break;
288 303 default:
289 304 Q_ASSERT(false);
290 305 break;
291 306 }
292 307 }
293 308 }
294 309
295 310 void MainWidget::backgroundChanged(int itemIndex)
296 311 {
297 312 qDebug() << "backgroundChanged: " << itemIndex;
298 313 }
299 314
300 315 void MainWidget::autoScaleChanged(int value)
301 316 {
302 317 if (value) {
303 318 // TODO: enable auto scaling
304 319 } else {
305 320 // TODO: set scaling manually (and disable auto scaling)
306 321 }
307 322
308 323 m_xMinSpin->setEnabled(!value);
309 324 m_xMaxSpin->setEnabled(!value);
310 325 m_yMinSpin->setEnabled(!value);
311 326 m_yMaxSpin->setEnabled(!value);
312 327 }
313 328
314 329 void MainWidget::xMinChanged(int value)
315 330 {
316 331 qDebug() << "xMinChanged: " << value;
317 332 }
318 333
319 334 void MainWidget::xMaxChanged(int value)
320 335 {
321 336 qDebug() << "xMaxChanged: " << value;
322 337 }
323 338
324 339 void MainWidget::yMinChanged(int value)
325 340 {
326 341 qDebug() << "yMinChanged: " << value;
327 342 }
328 343
329 344 void MainWidget::yMaxChanged(int value)
330 345 {
331 346 qDebug() << "yMaxChanged: " << value;
332 347 }
333 348
334 349 void MainWidget::changeChartTheme(int themeIndex)
335 350 {
336 351 qDebug() << "changeChartTheme: " << themeIndex;
337 352 m_chartView->setChartTheme((QChart::ChartTheme) themeIndex);
338 353 //TODO: remove this hack. This is just to make it so that theme change is seen immediately.
339 354 QSize s = size();
340 355 s.setWidth(s.width()+1);
341 356 resize(s);
342 357 }
General Comments 0
You need to be logged in to leave comments. Login now