1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Charts module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 or (at your option) any later version |
20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by |
21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include <QtTest/QtTest> |
31 | #include <QtCharts/qabstractaxis.h> |
32 | #include <QtCharts/qvalueaxis.h> |
33 | #include <QtCharts/qlogvalueaxis.h> |
34 | #include <QtCharts/qbarcategoryaxis.h> |
35 | #include <QtCharts/qcategoryaxis.h> |
36 | #ifndef QT_QREAL_IS_FLOAT |
37 | #include <QtCharts/qdatetimeaxis.h> |
38 | #endif |
39 | #include <QtCharts/qlineseries.h> |
40 | #include <QtCharts/qareaseries.h> |
41 | #include <QtCharts/qscatterseries.h> |
42 | #include <QtCharts/qsplineseries.h> |
43 | #include <QtCharts/qpieseries.h> |
44 | #include <QtCharts/qbarseries.h> |
45 | #include <QtCharts/qpercentbarseries.h> |
46 | #include <QtCharts/qstackedbarseries.h> |
47 | #include <private/chartdataset_p.h> |
48 | #include <private/abstractdomain_p.h> |
49 | #include <tst_definitions.h> |
50 | |
51 | QT_CHARTS_USE_NAMESPACE |
52 | |
53 | Q_DECLARE_METATYPE(AbstractDomain *) |
54 | Q_DECLARE_METATYPE(QAbstractAxis *) |
55 | Q_DECLARE_METATYPE(QAbstractSeries *) |
56 | Q_DECLARE_METATYPE(QList<QAbstractSeries *>) |
57 | Q_DECLARE_METATYPE(QList<QAbstractAxis *>) |
58 | Q_DECLARE_METATYPE(Qt::Alignment) |
59 | Q_DECLARE_METATYPE(QList<Qt::Alignment>) |
60 | Q_DECLARE_METATYPE(QLineSeries *) |
61 | |
62 | class tst_ChartDataSet: public QObject { |
63 | |
64 | Q_OBJECT |
65 | public: |
66 | tst_ChartDataSet():m_dataset(0){}; |
67 | |
68 | public Q_SLOTS: |
69 | void initTestCase(); |
70 | void cleanupTestCase(); |
71 | void init(); |
72 | void cleanup(); |
73 | |
74 | private Q_SLOTS: |
75 | void chartdataset_data(); |
76 | void chartdataset(); |
77 | void addSeries_data(); |
78 | void addSeries(); |
79 | void removeSeries_data(); |
80 | void removeSeries(); |
81 | void addAxis_data(); |
82 | void addAxis(); |
83 | void removeAxis_data(); |
84 | void removeAxis(); |
85 | void attachAxis_data(); |
86 | void attachAxis(); |
87 | void detachAxis_data(); |
88 | void detachAxis(); |
89 | void domainChangePreservesRanges(); |
90 | |
91 | private: |
92 | void compareDomain(QAbstractSeries *series, qreal minX, qreal maxX, |
93 | qreal minY, qreal maxY) const; |
94 | ChartDataSet* m_dataset; |
95 | }; |
96 | |
97 | void tst_ChartDataSet::initTestCase() |
98 | { |
99 | qRegisterMetaType<AbstractDomain*>(); |
100 | qRegisterMetaType<QAbstractAxis*>(); |
101 | qRegisterMetaType<QAbstractSeries*>(); |
102 | } |
103 | |
104 | void tst_ChartDataSet::cleanupTestCase() |
105 | { |
106 | QTest::qWait(ms: 1); // Allow final deleteLaters to run |
107 | } |
108 | |
109 | void tst_ChartDataSet::init() |
110 | { |
111 | Q_ASSERT(!m_dataset); |
112 | m_dataset = new ChartDataSet(0); |
113 | } |
114 | |
115 | |
116 | void tst_ChartDataSet::cleanup() |
117 | { |
118 | delete m_dataset; |
119 | m_dataset = 0; |
120 | } |
121 | |
122 | void tst_ChartDataSet::chartdataset_data() |
123 | { |
124 | } |
125 | |
126 | void tst_ChartDataSet::chartdataset() |
127 | { |
128 | QVERIFY(m_dataset->axes().isEmpty()); |
129 | QVERIFY(m_dataset->series().isEmpty()); |
130 | m_dataset->createDefaultAxes(); |
131 | } |
132 | |
133 | |
134 | void tst_ChartDataSet::addSeries_data() |
135 | { |
136 | QTest::addColumn<QAbstractSeries*>(name: "series" ); |
137 | |
138 | QAbstractSeries* line = new QLineSeries(this); |
139 | QTest::newRow(dataTag: "line" ) << line; |
140 | |
141 | QAbstractSeries* area = new QAreaSeries(static_cast<QLineSeries*>(new QLineSeries(this))); |
142 | QTest::newRow(dataTag: "area" ) << area; |
143 | |
144 | QAbstractSeries* scatter = new QScatterSeries(this); |
145 | QTest::newRow(dataTag: "scatter" ) << scatter; |
146 | |
147 | QAbstractSeries* spline = new QSplineSeries(this); |
148 | QTest::newRow(dataTag: "spline" ) << spline; |
149 | |
150 | QAbstractSeries* pie = new QPieSeries(this); |
151 | QTest::newRow(dataTag: "pie" ) << pie; |
152 | |
153 | QAbstractSeries* bar = new QBarSeries(this); |
154 | QTest::newRow(dataTag: "bar" ) << bar; |
155 | |
156 | QAbstractSeries* percent = new QPercentBarSeries(this); |
157 | QTest::newRow(dataTag: "percent" ) << percent; |
158 | |
159 | QAbstractSeries* stacked = new QStackedBarSeries(this); |
160 | QTest::newRow(dataTag: "stacked" ) << stacked; |
161 | } |
162 | |
163 | void tst_ChartDataSet::addSeries() |
164 | { |
165 | QFETCH(QAbstractSeries*, series); |
166 | QVERIFY(m_dataset->series().isEmpty()); |
167 | |
168 | QSignalSpy spy0(m_dataset, SIGNAL(axisAdded(QAbstractAxis*))); |
169 | QSignalSpy spy1(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*))); |
170 | QSignalSpy spy2(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*))); |
171 | QSignalSpy spy3(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*))); |
172 | |
173 | m_dataset->addSeries(series); |
174 | |
175 | QCOMPARE(m_dataset->series().count(),1); |
176 | TRY_COMPARE(spy0.count(), 0); |
177 | TRY_COMPARE(spy1.count(), 0); |
178 | TRY_COMPARE(spy2.count(), 1); |
179 | TRY_COMPARE(spy3.count(), 0); |
180 | } |
181 | |
182 | void tst_ChartDataSet::removeSeries_data() |
183 | { |
184 | addSeries_data(); |
185 | } |
186 | |
187 | void tst_ChartDataSet::removeSeries() |
188 | { |
189 | QFETCH(QAbstractSeries*, series); |
190 | QVERIFY(m_dataset->series().isEmpty()); |
191 | m_dataset->addSeries(series); |
192 | |
193 | QSignalSpy spy0(m_dataset, SIGNAL(axisAdded(QAbstractAxis*))); |
194 | QSignalSpy spy1(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*))); |
195 | QSignalSpy spy2(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*))); |
196 | QSignalSpy spy3(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*))); |
197 | |
198 | m_dataset->removeSeries(series); |
199 | |
200 | QCOMPARE(m_dataset->series().count(),0); |
201 | TRY_COMPARE(spy0.count(), 0); |
202 | TRY_COMPARE(spy1.count(), 0); |
203 | TRY_COMPARE(spy2.count(), 0); |
204 | TRY_COMPARE(spy3.count(), 1); |
205 | |
206 | delete series; |
207 | } |
208 | |
209 | void tst_ChartDataSet::addAxis_data() |
210 | { |
211 | QTest::addColumn<QAbstractAxis*>(name: "axis" ); |
212 | QAbstractAxis* value = new QValueAxis(this); |
213 | QAbstractAxis* logvalue = new QLogValueAxis(this); |
214 | QAbstractAxis* category = new QCategoryAxis(this); |
215 | QAbstractAxis* barcategory = new QBarCategoryAxis(this); |
216 | #ifndef QT_QREAL_IS_FLOAT |
217 | QAbstractAxis* datetime = new QDateTimeAxis(this); |
218 | #endif |
219 | |
220 | QTest::newRow(dataTag: "value" ) << value; |
221 | QTest::newRow(dataTag: "logvalue" ) << logvalue; |
222 | QTest::newRow(dataTag: "category" ) << category; |
223 | QTest::newRow(dataTag: "barcategory" ) << barcategory; |
224 | #ifndef QT_QREAL_IS_FLOAT |
225 | QTest::newRow(dataTag: "datetime" ) << datetime; |
226 | #endif |
227 | } |
228 | |
229 | void tst_ChartDataSet::addAxis() |
230 | { |
231 | QFETCH(QAbstractAxis*, axis); |
232 | QVERIFY(m_dataset->axes().isEmpty()); |
233 | |
234 | QSignalSpy spy0(m_dataset, SIGNAL(axisAdded(QAbstractAxis*))); |
235 | QSignalSpy spy1(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*))); |
236 | QSignalSpy spy2(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*))); |
237 | QSignalSpy spy3(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*))); |
238 | |
239 | m_dataset->addAxis(axis,aligment: Qt::AlignBottom); |
240 | |
241 | QCOMPARE(m_dataset->axes().count(),1); |
242 | TRY_COMPARE(spy0.count(), 1); |
243 | TRY_COMPARE(spy1.count(), 0); |
244 | TRY_COMPARE(spy2.count(), 0); |
245 | TRY_COMPARE(spy3.count(), 0); |
246 | } |
247 | |
248 | void tst_ChartDataSet::removeAxis_data() |
249 | { |
250 | addAxis_data(); |
251 | } |
252 | |
253 | void tst_ChartDataSet::removeAxis() |
254 | { |
255 | QFETCH(QAbstractAxis*, axis); |
256 | QVERIFY(m_dataset->series().isEmpty()); |
257 | m_dataset->addAxis(axis,aligment: Qt::AlignBottom); |
258 | |
259 | QSignalSpy spy0(m_dataset, SIGNAL(axisAdded(QAbstractAxis*))); |
260 | QSignalSpy spy1(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*))); |
261 | QSignalSpy spy2(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*))); |
262 | QSignalSpy spy3(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*))); |
263 | |
264 | m_dataset->removeAxis(axis); |
265 | |
266 | QCOMPARE(m_dataset->axes().count(),0); |
267 | QCOMPARE(m_dataset->series().count(),0); |
268 | TRY_COMPARE(spy0.count(), 0); |
269 | TRY_COMPARE(spy1.count(), 1); |
270 | TRY_COMPARE(spy2.count(), 0); |
271 | TRY_COMPARE(spy3.count(), 0); |
272 | |
273 | delete axis; |
274 | } |
275 | |
276 | void tst_ChartDataSet::attachAxis_data() |
277 | { |
278 | |
279 | QTest::addColumn<QList<QAbstractSeries*> >(name: "series" ); |
280 | QTest::addColumn<QList<QAbstractAxis*> >(name: "axis" ); |
281 | QTest::addColumn<QList<Qt::Alignment> >(name: "alignment" ); |
282 | QTest::addColumn<QAbstractSeries*>(name: "attachSeries" ); |
283 | QTest::addColumn<QAbstractAxis*>(name: "attachAxis" ); |
284 | QTest::addColumn<bool>(name: "success" ); |
285 | |
286 | { |
287 | QList<QAbstractSeries*> series; |
288 | QList<QAbstractAxis*> axes; |
289 | QList<Qt::Alignment> alignment; |
290 | QAbstractSeries* line = new QLineSeries(this); |
291 | QAbstractAxis* value1 = new QValueAxis(this); |
292 | QAbstractAxis* value2 = new QValueAxis(this); |
293 | series << line << 0; |
294 | axes << value1 << value2; |
295 | alignment << Qt::AlignBottom << Qt::AlignLeft; |
296 | QTest::newRow(dataTag: "first" ) << series << axes << alignment << line << value2 << true ; |
297 | } |
298 | |
299 | { |
300 | QList<QAbstractSeries*> series; |
301 | QList<QAbstractAxis*> axes; |
302 | QList<Qt::Alignment> alignment; |
303 | QAbstractSeries* line = new QLineSeries(this); |
304 | QAbstractAxis* value1 = new QValueAxis(this); |
305 | QAbstractAxis* value2 = new QValueAxis(this); |
306 | series << 0 << line; |
307 | axes << value1 << value2; |
308 | alignment << Qt::AlignBottom << Qt::AlignLeft; |
309 | QTest::newRow(dataTag: "second" ) << series << axes << alignment << line << value1 << true; |
310 | } |
311 | |
312 | } |
313 | |
314 | void tst_ChartDataSet::attachAxis() |
315 | { |
316 | QFETCH(QList<QAbstractSeries*>, series); |
317 | QFETCH(QList<QAbstractAxis*>, axis); |
318 | QFETCH(QList<Qt::Alignment>, alignment); |
319 | QFETCH(QAbstractSeries*, attachSeries); |
320 | QFETCH(QAbstractAxis*, attachAxis); |
321 | QFETCH(bool, success); |
322 | |
323 | Q_ASSERT(series.count() == axis.count()); |
324 | Q_ASSERT(series.count() == alignment.count()); |
325 | |
326 | QVERIFY(m_dataset->series().isEmpty()); |
327 | QVERIFY(m_dataset->axes().isEmpty()); |
328 | |
329 | for(int i = 0 ; i < series.count() ; i++){ |
330 | if(series[i]) m_dataset->addSeries(series: series[i]); |
331 | if(axis[i]) m_dataset->addAxis(axis: axis[i],aligment: alignment[i]); |
332 | if(series[i] && axis[i]) m_dataset->attachAxis(series: series[i],axis: axis[i]); |
333 | } |
334 | |
335 | QSignalSpy spy0(m_dataset, SIGNAL(axisAdded(QAbstractAxis*))); |
336 | QSignalSpy spy1(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*))); |
337 | QSignalSpy spy2(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*))); |
338 | QSignalSpy spy3(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*))); |
339 | |
340 | QCOMPARE(m_dataset->attachAxis(attachSeries,attachAxis),success); |
341 | |
342 | } |
343 | |
344 | void tst_ChartDataSet::detachAxis_data() |
345 | { |
346 | QTest::addColumn<QList<QAbstractSeries*> >(name: "series" ); |
347 | QTest::addColumn<QList<QAbstractAxis*> >(name: "axis" ); |
348 | QTest::addColumn<QAbstractSeries*>(name: "detachSeries" ); |
349 | QTest::addColumn<QAbstractAxis*>(name: "detachAxis" ); |
350 | QTest::addColumn<bool>(name: "success" ); |
351 | |
352 | { |
353 | QList<QAbstractSeries*> series; |
354 | QList<QAbstractAxis*> axes; |
355 | QAbstractSeries* line = new QLineSeries(this); |
356 | QAbstractAxis* value = new QValueAxis(this); |
357 | series << line; |
358 | axes << value; |
359 | QTest::newRow(dataTag: "first" ) << series << axes << line << value << true; |
360 | } |
361 | } |
362 | |
363 | void tst_ChartDataSet::detachAxis() |
364 | { |
365 | QFETCH(QList<QAbstractSeries*>, series); |
366 | QFETCH(QList<QAbstractAxis*>, axis); |
367 | QFETCH(QAbstractSeries*, detachSeries); |
368 | QFETCH(QAbstractAxis*, detachAxis); |
369 | QFETCH(bool, success); |
370 | |
371 | Q_ASSERT(series.count() == axis.count()); |
372 | |
373 | QVERIFY(m_dataset->series().isEmpty()); |
374 | QVERIFY(m_dataset->axes().isEmpty()); |
375 | |
376 | for(int i = 0; i < series.count(); i++) { |
377 | if(series[i]) m_dataset->addSeries(series: series[i]); |
378 | if(axis[i]) m_dataset->addAxis(axis: axis[i],aligment: Qt::AlignBottom); |
379 | if(series[i] && axis[i]) m_dataset->attachAxis(series: series[i],axis: axis[i]); |
380 | } |
381 | |
382 | QSignalSpy spy0(m_dataset, SIGNAL(axisAdded(QAbstractAxis*))); |
383 | QSignalSpy spy1(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*))); |
384 | QSignalSpy spy2(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*))); |
385 | QSignalSpy spy3(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*))); |
386 | |
387 | QCOMPARE(m_dataset->detachAxis(detachSeries,detachAxis),success); |
388 | } |
389 | |
390 | void tst_ChartDataSet::domainChangePreservesRanges() |
391 | { |
392 | // This test checks that domain ranges stay correct after an axis attachment causes domain |
393 | // to be recreated. |
394 | QVERIFY(m_dataset->series().isEmpty()); |
395 | QVERIFY(m_dataset->axes().isEmpty()); |
396 | |
397 | QLineSeries* line = new QLineSeries(this); |
398 | QValueAxis* value1 = new QValueAxis(this); |
399 | QValueAxis* value2 = new QValueAxis(this); |
400 | QLogValueAxis* logValue1 = new QLogValueAxis(this); |
401 | QLogValueAxis* logValue2 = new QLogValueAxis(this); |
402 | (*line) << QPointF(1.0, 2.0) << QPointF(10.0, 20.0); |
403 | |
404 | value1->setRange(min: 2.0, max: 6.0); |
405 | value2->setRange(min: 3.0, max: 7.0); |
406 | logValue1->setRange(min: 4.0, max: 8.0); |
407 | logValue2->setRange(min: 5.0, max: 9.0); |
408 | |
409 | m_dataset->addSeries(series: line); |
410 | compareDomain(series: line, minX: 1.0, maxX: 10.0, minY: 2.0, maxY: 20.0); |
411 | m_dataset->addAxis(axis: value1, aligment: Qt::AlignBottom); |
412 | m_dataset->addAxis(axis: value2, aligment: Qt::AlignLeft); |
413 | m_dataset->addAxis(axis: logValue1, aligment: Qt::AlignBottom); |
414 | m_dataset->addAxis(axis: logValue2, aligment: Qt::AlignLeft); |
415 | compareDomain(series: line, minX: 1.0, maxX: 10.0, minY: 2.0, maxY: 20.0); |
416 | |
417 | // Start with two value axes |
418 | m_dataset->attachAxis(series: line, axis: value1); |
419 | compareDomain(series: line, minX: 2.0, maxX: 6.0, minY: 2.0, maxY: 20.0); |
420 | m_dataset->attachAxis(series: line, axis: value2); |
421 | compareDomain(series: line, minX: 2.0, maxX: 6.0, minY: 3.0, maxY: 7.0); |
422 | |
423 | // Detach y value and attach y logvalue |
424 | m_dataset->detachAxis(series: line, axis: value2); |
425 | compareDomain(series: line, minX: 2.0, maxX: 6.0, minY: 3.0, maxY: 7.0); // Detach doesn't change domain ranges |
426 | m_dataset->attachAxis(series: line, axis: logValue2); |
427 | compareDomain(series: line, minX: 2.0, maxX: 6.0, minY: 5.0, maxY: 9.0); |
428 | |
429 | // Detach x value and attach x logvalue |
430 | m_dataset->detachAxis(series: line, axis: value1); |
431 | compareDomain(series: line, minX: 2.0, maxX: 6.0, minY: 5.0, maxY: 9.0); // Detach doesn't change domain ranges |
432 | m_dataset->attachAxis(series: line, axis: logValue1); |
433 | compareDomain(series: line, minX: 4.0, maxX: 8.0, minY: 5.0, maxY: 9.0); |
434 | |
435 | // Detach y logvalue and attach y value |
436 | m_dataset->detachAxis(series: line, axis: logValue2); |
437 | compareDomain(series: line, minX: 4.0, maxX: 8.0, minY: 5.0, maxY: 9.0); // Detach doesn't change domain ranges |
438 | m_dataset->attachAxis(series: line, axis: value2); |
439 | compareDomain(series: line, minX: 4.0, maxX: 8.0, minY: 3.0, maxY: 7.0); |
440 | } |
441 | |
442 | void tst_ChartDataSet::compareDomain(QAbstractSeries *series, qreal minX, qreal maxX, |
443 | qreal minY, qreal maxY) const |
444 | { |
445 | AbstractDomain *domain = m_dataset->domainForSeries(series); |
446 | QCOMPARE(domain->minX(), minX); |
447 | QCOMPARE(domain->maxX(), maxX); |
448 | QCOMPARE(domain->minY(), minY); |
449 | QCOMPARE(domain->maxY(), maxY); |
450 | } |
451 | |
452 | QTEST_MAIN(tst_ChartDataSet) |
453 | #include "tst_chartdataset.moc" |
454 | |