##// END OF EJS Templates
Fix format for linux
perrinel -
r912:fedc6e2cf64d
parent child
Show More
@@ -1,151 +1,151
1 1 #include <Data/ArrayData.h>
2 2 #include <Data/OptionalAxis.h>
3 3
4 4 #include <QObject>
5 5 #include <QtTest>
6 6
7 7 Q_DECLARE_METATYPE(OptionalAxis)
8 8 Q_DECLARE_METATYPE(Unit)
9 9
10 10 class TestOptionalAxis : public QObject {
11 11 Q_OBJECT
12 12
13 13 private slots:
14 14 /// Tests the creation of a undefined axis
15 15 void testNotDefinedAxisCtor();
16 16
17 17 /// Tests the creation of a undefined axis
18 18 void testDefinedAxisCtor_data();
19 19 void testDefinedAxisCtor();
20 20
21 21 /// Tests @sa OptionalAxis::at() method
22 22 void testAt_data();
23 23 void testAt();
24 24
25 25 /// Tests @sa OptionalAxis::size() method
26 26 void testSize_data();
27 27 void testSize();
28 28
29 29 /// Tests @sa OptionalAxis::unit() method
30 30 void testUnit_data();
31 31 void testUnit();
32 32 };
33 33
34 34 void TestOptionalAxis::testNotDefinedAxisCtor()
35 35 {
36 36 OptionalAxis notDefinedAxis{};
37 37 QVERIFY(!notDefinedAxis.isDefined());
38 38 }
39 39
40 40 void TestOptionalAxis::testDefinedAxisCtor_data()
41 41 {
42 42 QTest::addColumn<bool>("noData"); // If set to true, nullptr is passed as data of the axis
43 43 QTest::addColumn<std::vector<double> >(
44 44 "data"); // Values assigned to the axis when 'noData' flag is set to false
45 45 QTest::addColumn<Unit>("unit"); // Unit assigned to the axis
46 46
47 47 QTest::newRow("validData") << false << std::vector<double>{1, 2, 3} << Unit{"Hz"};
48 48 QTest::newRow("invalidData") << true << std::vector<double>{} << Unit{"Hz"};
49 49 }
50 50
51 51 void TestOptionalAxis::testDefinedAxisCtor()
52 52 {
53 53 QFETCH(bool, noData);
54 54 QFETCH(Unit, unit);
55 55
56 56 // When there is no data, we expect that the constructor returns exception
57 57 if (noData) {
58 58 QVERIFY_EXCEPTION_THROWN(OptionalAxis(nullptr, unit), std::invalid_argument);
59 59 }
60 60 else {
61 61 QFETCH(std::vector<double>, data);
62 62
63 63 OptionalAxis axis{std::make_shared<ArrayData<1> >(data), unit};
64 64 QVERIFY(axis.isDefined());
65 65 }
66 66 }
67 67
68 68 void TestOptionalAxis::testAt_data()
69 69 {
70 70 QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not)
71 71 QTest::addColumn<int>("index"); // Index to test in the axis
72 72 QTest::addColumn<double>("expectedValue"); // Expected axis value for the index
73 73
74 74 OptionalAxis definedAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}),
75 75 Unit{"Hz"}};
76 76
77 77 QTest::newRow("data1") << definedAxis << 0 << 1.;
78 78 QTest::newRow("data2") << definedAxis << 1 << 2.;
79 79 QTest::newRow("data3") << definedAxis << 2 << 3.;
80 80 QTest::newRow("data4 (index out of bounds)")
81 81 << definedAxis << 3
82 82 << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for out of bounds index
83 83 QTest::newRow("data5 (index out of bounds)")
84 84 << definedAxis << -1
85 85 << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for out of bounds index
86 86 QTest::newRow("data6 (axis not defined)")
87 87 << OptionalAxis{} << 0
88 88 << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for undefined axis
89 89 }
90 90
91 91 void TestOptionalAxis::testAt()
92 92 {
93 93 QFETCH(OptionalAxis, axis);
94 94 QFETCH(int, index);
95 95 QFETCH(double, expectedValue);
96 96
97 97 auto value = axis.at(index);
98 98 QVERIFY((std::isnan(value) && std::isnan(expectedValue)) || value == expectedValue);
99 99 }
100 100
101 101 void TestOptionalAxis::testSize_data()
102 102 {
103 103 QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not)
104 104 QTest::addColumn<int>("expectedSize"); // Expected number of data in the axis
105 105
106 106 // Lambda that creates default defined axis (with the values passed in parameter)
107 107 auto axis = [](std::vector<double> values) {
108 108 return OptionalAxis{std::make_shared<ArrayData<1> >(std::move(values)), Unit{"Hz"}};
109 109 };
110 110
111 111 QTest::newRow("data1") << axis({}) << 0;
112 112 QTest::newRow("data2") << axis({1, 2, 3}) << 3;
113 113 QTest::newRow("data3") << axis({1, 2, 3, 4}) << 4;
114 QTest::newRow("data4 (axis not defined)")
115 << OptionalAxis{} << 0; // Expects 0 for undefined axis
114 QTest::newRow("data4 (axis not defined)") << OptionalAxis{}
115 << 0; // Expects 0 for undefined axis
116 116 }
117 117
118 118 void TestOptionalAxis::testSize()
119 119 {
120 120 QFETCH(OptionalAxis, axis);
121 121 QFETCH(int, expectedSize);
122 122
123 123 QCOMPARE(axis.size(), expectedSize);
124 124 }
125 125
126 126 void TestOptionalAxis::testUnit_data()
127 127 {
128 128 QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not)
129 129 QTest::addColumn<Unit>("expectedUnit"); // Expected unit for the axis
130 130
131 131 // Lambda that creates default defined axis (with the unit passed in parameter)
132 132 auto axis = [](Unit unit) {
133 133 return OptionalAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}), unit};
134 134 };
135 135
136 136 QTest::newRow("data1") << axis(Unit{"Hz"}) << Unit{"Hz"};
137 137 QTest::newRow("data2") << axis(Unit{"t", true}) << Unit{"t", true};
138 QTest::newRow("data3 (axis not defined)")
139 << OptionalAxis{} << Unit{}; // Expects default unit for undefined axis
138 QTest::newRow("data3 (axis not defined)") << OptionalAxis{}
139 << Unit{}; // Expects default unit for undefined axis
140 140 }
141 141
142 142 void TestOptionalAxis::testUnit()
143 143 {
144 144 QFETCH(OptionalAxis, axis);
145 145 QFETCH(Unit, expectedUnit);
146 146
147 147 QCOMPARE(axis.unit(), expectedUnit);
148 148 }
149 149
150 150 QTEST_MAIN(TestOptionalAxis)
151 151 #include "TestOptionalAxis.moc"
@@ -1,426 +1,426
1 1 #include "Data/ScalarSeries.h"
2 2
3 3 #include "DataSeriesBuilders.h"
4 4 #include "DataSeriesUtils.h"
5 5
6 6 #include <QObject>
7 7 #include <QtTest>
8 8
9 9 /**
10 10 * @brief The TestScalarSeries class defines unit tests on scalar series.
11 11 *
12 12 * Most of these unit tests use generic tests defined for DataSeries (@sa DataSeriesUtils)
13 13 */
14 14 class TestScalarSeries : public QObject {
15 15 Q_OBJECT
16 16 private slots:
17 17 /// Tests construction of a scalar series
18 18 void testCtor_data();
19 19 void testCtor();
20 20
21 21 /// Tests merge of two scalar series
22 22 void testMerge_data();
23 23 void testMerge();
24 24
25 25 /// Tests merge of a vector series in a scalar series
26 26 void testMergeWithVector_data();
27 27 void testMergeWithVector();
28 28
29 29 /// Tests get min x-axis data of a scalar series
30 30 void testMinXAxisData_data();
31 31 void testMinXAxisData();
32 32
33 33 /// Tests get max x-axis data of a scalar series
34 34 void testMaxXAxisData_data();
35 35 void testMaxXAxisData();
36 36
37 37 /// Tests purge of a scalar series
38 38 void testPurge_data();
39 39 void testPurge();
40 40
41 41 /// Tests get x-axis range of a scalar series
42 42 void testXAxisRange_data();
43 43 void testXAxisRange();
44 44
45 45 /// Tests get values bounds of a scalar series
46 46 void testValuesBounds_data();
47 47 void testValuesBounds();
48 48 };
49 49
50 50 void TestScalarSeries::testCtor_data()
51 51 {
52 52 // x-axis data
53 53 QTest::addColumn<DataContainer>("xAxisData");
54 54 // values data
55 55 QTest::addColumn<DataContainer>("valuesData");
56 56
57 57 // construction expected to be valid
58 58 QTest::addColumn<bool>("expectOK");
59 59 // expected x-axis data (when construction is valid)
60 60 QTest::addColumn<DataContainer>("expectedXAxisData");
61 61 // expected values data (when construction is valid)
62 62 QTest::addColumn<DataContainer>("expectedValuesData");
63 63
64 64 QTest::newRow("invalidData (different sizes of vectors)")
65 65 << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 200., 300.} << false
66 66 << DataContainer{} << DataContainer{};
67 67
68 68 QTest::newRow("sortedData") << DataContainer{1., 2., 3., 4., 5.}
69 69 << DataContainer{100., 200., 300., 400., 500.} << true
70 70 << DataContainer{1., 2., 3., 4., 5.}
71 71 << DataContainer{100., 200., 300., 400., 500.};
72 72
73 73 QTest::newRow("unsortedData") << DataContainer{5., 4., 3., 2., 1.}
74 74 << DataContainer{100., 200., 300., 400., 500.} << true
75 75 << DataContainer{1., 2., 3., 4., 5.}
76 76 << DataContainer{500., 400., 300., 200., 100.};
77 77
78 78 QTest::newRow("unsortedData2")
79 79 << DataContainer{1., 4., 3., 5., 2.} << DataContainer{100., 200., 300., 400., 500.} << true
80 80 << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 500., 300., 200., 400.};
81 81 }
82 82
83 83 void TestScalarSeries::testCtor()
84 84 {
85 85 // Creates series
86 86 QFETCH(DataContainer, xAxisData);
87 87 QFETCH(DataContainer, valuesData);
88 88 QFETCH(bool, expectOK);
89 89
90 90 if (expectOK) {
91 91 auto series = std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
92 92 Unit{}, Unit{});
93 93
94 94 // Validates results : we check that the data series is sorted on its x-axis data
95 95 QFETCH(DataContainer, expectedXAxisData);
96 96 QFETCH(DataContainer, expectedValuesData);
97 97
98 98 validateRange(series->cbegin(), series->cend(), expectedXAxisData, expectedValuesData);
99 99 }
100 100 else {
101 101 QVERIFY_EXCEPTION_THROWN(std::make_shared<ScalarSeries>(
102 102 std::move(xAxisData), std::move(valuesData), Unit{}, Unit{}),
103 103 std::invalid_argument);
104 104 }
105 105 }
106 106
107 107 void TestScalarSeries::testMerge_data()
108 108 {
109 109 testMerge_struct<ScalarSeries, DataContainer>();
110 110
111 111 QTest::newRow("sortedMerge") << ScalarBuilder{}
112 112 .setX({1., 2., 3., 4., 5.})
113 113 .setValues({100., 200., 300., 400., 500.})
114 114 .build()
115 115 << ScalarBuilder{}
116 116 .setX({6., 7., 8., 9., 10.})
117 117 .setValues({600., 700., 800., 900., 1000.})
118 118 .build()
119 119 << DataContainer{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}
120 120 << DataContainer{100., 200., 300., 400., 500.,
121 121 600., 700., 800., 900., 1000.};
122 122
123 123 QTest::newRow("unsortedMerge")
124 124 << ScalarBuilder{}
125 125 .setX({6., 7., 8., 9., 10.})
126 126 .setValues({600., 700., 800., 900., 1000.})
127 127 .build()
128 128 << ScalarBuilder{}
129 129 .setX({1., 2., 3., 4., 5.})
130 130 .setValues({100., 200., 300., 400., 500.})
131 131 .build()
132 132 << DataContainer{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}
133 133 << DataContainer{100., 200., 300., 400., 500., 600., 700., 800., 900., 1000.};
134 134
135 135 QTest::newRow("unsortedMerge2 (merge not made because source is in the bounds of dest)")
136 136 << ScalarBuilder{}
137 137 .setX({1., 2., 8., 9., 10})
138 138 .setValues({100., 200., 800., 900., 1000.})
139 139 .build()
140 140 << ScalarBuilder{}
141 141 .setX({3., 4., 5., 6., 7.})
142 142 .setValues({300., 400., 500., 600., 700.})
143 143 .build()
144 144 << DataContainer{1., 2., 8., 9., 10.} << DataContainer{100., 200., 800., 900., 1000.};
145 145
146 146 QTest::newRow("unsortedMerge3")
147 147 << ScalarBuilder{}
148 148 .setX({3., 4., 5., 7., 8})
149 149 .setValues({300., 400., 500., 700., 800.})
150 150 .build()
151 151 << ScalarBuilder{}
152 152 .setX({1., 2., 3., 7., 10.})
153 153 .setValues({100., 200., 333., 777., 1000.})
154 154 .build()
155 155 << DataContainer{1., 2., 3., 4., 5., 7., 8., 10.}
156 156 << DataContainer{100., 200., 300., 400., 500., 700., 800., 1000.};
157 157
158 158 QTest::newRow("emptySource") << ScalarBuilder{}
159 159 .setX({3., 4., 5., 7., 8})
160 160 .setValues({300., 400., 500., 700., 800.})
161 161 .build()
162 162 << ScalarBuilder{}.setX({}).setValues({}).build()
163 163 << DataContainer{3., 4., 5., 7., 8.}
164 164 << DataContainer{300., 400., 500., 700., 800.};
165 165 }
166 166
167 167 void TestScalarSeries::testMerge()
168 168 {
169 169 testMerge_t<ScalarSeries, DataContainer>();
170 170 }
171 171
172 172 void TestScalarSeries::testMergeWithVector_data()
173 173 {
174 174 testMergeDifferentTypes_struct<VectorSeries, ScalarSeries>();
175 175
176 QTest::newRow("mergeVectorInScalar")
177 << ScalarBuilder{}
178 .setX({1., 2., 3., 4., 5.})
179 .setValues({100., 200., 300., 400., 500.})
180 .build()
181 << VectorBuilder{}
182 .setX({6., 7., 8., 9., 10.})
183 .setXValues({600., 700., 800., 900., 1000.})
184 .setYValues({610., 710., 810., 910., 1010.})
185 .setZValues({620., 720., 820., 920., 1020.})
186 .build()
187 << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 200., 300., 400., 500.};
176 QTest::newRow("mergeVectorInScalar") << ScalarBuilder{}
177 .setX({1., 2., 3., 4., 5.})
178 .setValues({100., 200., 300., 400., 500.})
179 .build()
180 << VectorBuilder{}
181 .setX({6., 7., 8., 9., 10.})
182 .setXValues({600., 700., 800., 900., 1000.})
183 .setYValues({610., 710., 810., 910., 1010.})
184 .setZValues({620., 720., 820., 920., 1020.})
185 .build()
186 << DataContainer{1., 2., 3., 4., 5.}
187 << DataContainer{100., 200., 300., 400., 500.};
188 188 }
189 189
190 190 void TestScalarSeries::testMergeWithVector()
191 191 {
192 192 testMergeDifferentTypes_t<VectorSeries, ScalarSeries>();
193 193 }
194 194
195 195 void TestScalarSeries::testMinXAxisData_data()
196 196 {
197 197 testMinXAxisData_struct<ScalarSeries>();
198 198
199 199 QTest::newRow("minData1") << ScalarBuilder{}
200 200 .setX({1., 2., 3., 4., 5.})
201 201 .setValues({100., 200., 300., 400., 500.})
202 202 .build()
203 203 << 0. << true << 1.;
204 204 QTest::newRow("minData2") << ScalarBuilder{}
205 205 .setX({1., 2., 3., 4., 5.})
206 206 .setValues({100., 200., 300., 400., 500.})
207 207 .build()
208 208 << 1. << true << 1.;
209 209 QTest::newRow("minData3") << ScalarBuilder{}
210 210 .setX({1., 2., 3., 4., 5.})
211 211 .setValues({100., 200., 300., 400., 500.})
212 212 .build()
213 213 << 1.1 << true << 2.;
214 214 QTest::newRow("minData4") << ScalarBuilder{}
215 215 .setX({1., 2., 3., 4., 5.})
216 216 .setValues({100., 200., 300., 400., 500.})
217 217 .build()
218 218 << 5. << true << 5.;
219 219 QTest::newRow("minData5") << ScalarBuilder{}
220 220 .setX({1., 2., 3., 4., 5.})
221 221 .setValues({100., 200., 300., 400., 500.})
222 222 .build()
223 223 << 5.1 << false << std::numeric_limits<double>::quiet_NaN();
224 224 QTest::newRow("minData6") << ScalarBuilder{}.setX({}).setValues({}).build() << 1.1 << false
225 225 << std::numeric_limits<double>::quiet_NaN();
226 226 }
227 227
228 228 void TestScalarSeries::testMinXAxisData()
229 229 {
230 230 testMinXAxisData_t<ScalarSeries>();
231 231 }
232 232
233 233 void TestScalarSeries::testMaxXAxisData_data()
234 234 {
235 235 testMaxXAxisData_struct<ScalarSeries>();
236 236
237 237 QTest::newRow("maxData1") << ScalarBuilder{}
238 238 .setX({1., 2., 3., 4., 5.})
239 239 .setValues({100., 200., 300., 400., 500.})
240 240 .build()
241 241 << 6. << true << 5.;
242 242 QTest::newRow("maxData2") << ScalarBuilder{}
243 243 .setX({1., 2., 3., 4., 5.})
244 244 .setValues({100., 200., 300., 400., 500.})
245 245 .build()
246 246 << 5. << true << 5.;
247 247 QTest::newRow("maxData3") << ScalarBuilder{}
248 248 .setX({1., 2., 3., 4., 5.})
249 249 .setValues({100., 200., 300., 400., 500.})
250 250 .build()
251 251 << 4.9 << true << 4.;
252 252 QTest::newRow("maxData4") << ScalarBuilder{}
253 253 .setX({1., 2., 3., 4., 5.})
254 254 .setValues({100., 200., 300., 400., 500.})
255 255 .build()
256 256 << 1.1 << true << 1.;
257 257 QTest::newRow("maxData5") << ScalarBuilder{}
258 258 .setX({1., 2., 3., 4., 5.})
259 259 .setValues({100., 200., 300., 400., 500.})
260 260 .build()
261 261 << 1. << true << 1.;
262 262 QTest::newRow("maxData6") << ScalarBuilder{}.setX({}).setValues({}).build() << 1.1 << false
263 263 << std::numeric_limits<double>::quiet_NaN();
264 264 }
265 265
266 266 void TestScalarSeries::testMaxXAxisData()
267 267 {
268 268 testMaxXAxisData_t<ScalarSeries>();
269 269 }
270 270
271 271 void TestScalarSeries::testPurge_data()
272 272 {
273 273 testPurge_struct<ScalarSeries>();
274 274
275 275 QTest::newRow("purgeScalar") << ScalarBuilder{}
276 276 .setX({1., 2., 3., 4., 5.})
277 277 .setValues({100., 200., 300., 400., 500.})
278 278 .build()
279 279 << 2. << 4. << DataContainer{2., 3., 4.}
280 280 << std::vector<DataContainer>{{200., 300., 400.}};
281 QTest::newRow("purgeScalar1 (min/max swap)")
282 << ScalarBuilder{}
283 .setX({1., 2., 3., 4., 5.})
284 .setValues({100., 200., 300., 400., 500.})
285 .build()
286 << 4. << 2. << DataContainer{2., 3., 4.} << std::vector<DataContainer>{{200., 300., 400.}};
281 QTest::newRow("purgeScalar1 (min/max swap)") << ScalarBuilder{}
282 .setX({1., 2., 3., 4., 5.})
283 .setValues({100., 200., 300., 400., 500.})
284 .build()
285 << 4. << 2. << DataContainer{2., 3., 4.}
286 << std::vector<DataContainer>{{200., 300., 400.}};
287 287 QTest::newRow("purgeScalar2") << ScalarBuilder{}
288 288 .setX({1., 2., 3., 4., 5.})
289 289 .setValues({100., 200., 300., 400., 500.})
290 290 .build()
291 291 << 0. << 2.5 << DataContainer{1., 2.}
292 292 << std::vector<DataContainer>{{100., 200.}};
293 293 QTest::newRow("purgeScalar3") << ScalarBuilder{}
294 294 .setX({1., 2., 3., 4., 5.})
295 295 .setValues({100., 200., 300., 400., 500.})
296 296 .build()
297 297 << 3.5 << 7. << DataContainer{4., 5.}
298 298 << std::vector<DataContainer>{{400., 500.}};
299 299 QTest::newRow("purgeScalar4") << ScalarBuilder{}
300 300 .setX({1., 2., 3., 4., 5.})
301 301 .setValues({100., 200., 300., 400., 500.})
302 302 .build()
303 303 << 0. << 7. << DataContainer{1., 2., 3., 4., 5.}
304 304 << std::vector<DataContainer>{{100., 200., 300., 400., 500.}};
305 305 QTest::newRow("purgeScalar5") << ScalarBuilder{}
306 306 .setX({1., 2., 3., 4., 5.})
307 307 .setValues({100., 200., 300., 400., 500.})
308 308 .build()
309 309 << 5.5 << 7. << DataContainer{} << std::vector<DataContainer>{{}};
310 310 }
311 311
312 312 void TestScalarSeries::testPurge()
313 313 {
314 314 testPurge_t<ScalarSeries>();
315 315 }
316 316
317 317 void TestScalarSeries::testXAxisRange_data()
318 318 {
319 319 testXAxisRange_struct<ScalarSeries>();
320 320
321 321 QTest::newRow("xAxisRange") << ScalarBuilder{}
322 322 .setX({1., 2., 3., 4., 5.})
323 323 .setValues({100., 200., 300., 400., 500.})
324 324 .build()
325 325 << -1. << 3.2 << DataContainer{1., 2., 3.}
326 326 << DataContainer{100., 200., 300.};
327 QTest::newRow("xAxisRange1 (min/max swap)")
328 << ScalarBuilder{}
329 .setX({1., 2., 3., 4., 5.})
330 .setValues({100., 200., 300., 400., 500.})
331 .build()
332 << 3.2 << -1. << DataContainer{1., 2., 3.} << DataContainer{100., 200., 300.};
327 QTest::newRow("xAxisRange1 (min/max swap)") << ScalarBuilder{}
328 .setX({1., 2., 3., 4., 5.})
329 .setValues({100., 200., 300., 400., 500.})
330 .build()
331 << 3.2 << -1. << DataContainer{1., 2., 3.}
332 << DataContainer{100., 200., 300.};
333 333 QTest::newRow("xAxisRange2") << ScalarBuilder{}
334 334 .setX({1., 2., 3., 4., 5.})
335 335 .setValues({100., 200., 300., 400., 500.})
336 336 .build()
337 337 << 1. << 4. << DataContainer{1., 2., 3., 4.}
338 338 << DataContainer{100., 200., 300., 400.};
339 339 QTest::newRow("xAxisRange3") << ScalarBuilder{}
340 340 .setX({1., 2., 3., 4., 5.})
341 341 .setValues({100., 200., 300., 400., 500.})
342 342 .build()
343 343 << 1. << 3.9 << DataContainer{1., 2., 3.}
344 344 << DataContainer{100., 200., 300.};
345 345 QTest::newRow("xAxisRange4") << ScalarBuilder{}
346 346 .setX({1., 2., 3., 4., 5.})
347 347 .setValues({100., 200., 300., 400., 500.})
348 348 .build()
349 349 << 0. << 0.9 << DataContainer{} << DataContainer{};
350 350 QTest::newRow("xAxisRange5") << ScalarBuilder{}
351 351 .setX({1., 2., 3., 4., 5.})
352 352 .setValues({100., 200., 300., 400., 500.})
353 353 .build()
354 354 << 0. << 1. << DataContainer{1.} << DataContainer{100.};
355 355 QTest::newRow("xAxisRange6") << ScalarBuilder{}
356 356 .setX({1., 2., 3., 4., 5.})
357 357 .setValues({100., 200., 300., 400., 500.})
358 358 .build()
359 359 << 2.1 << 6. << DataContainer{3., 4., 5.}
360 360 << DataContainer{300., 400., 500.};
361 361 QTest::newRow("xAxisRange7") << ScalarBuilder{}
362 362 .setX({1., 2., 3., 4., 5.})
363 363 .setValues({100., 200., 300., 400., 500.})
364 364 .build()
365 365 << 6. << 9. << DataContainer{} << DataContainer{};
366 366 QTest::newRow("xAxisRange8") << ScalarBuilder{}
367 367 .setX({1., 2., 3., 4., 5.})
368 368 .setValues({100., 200., 300., 400., 500.})
369 369 .build()
370 370 << 5. << 9. << DataContainer{5.} << DataContainer{500.};
371 371 }
372 372
373 373 void TestScalarSeries::testXAxisRange()
374 374 {
375 375 testXAxisRange_t<ScalarSeries>();
376 376 }
377 377
378 378 void TestScalarSeries::testValuesBounds_data()
379 379 {
380 380 testValuesBounds_struct<ScalarSeries>();
381 381
382 382 auto nan = std::numeric_limits<double>::quiet_NaN();
383 383
384 384 QTest::newRow("scalarBounds1") << ScalarBuilder{}
385 385 .setX({1., 2., 3., 4., 5.})
386 386 .setValues({100., 200., 300., 400., 500.})
387 387 .build()
388 388 << 0. << 6. << true << 100. << 500.;
389 389 QTest::newRow("scalarBounds2") << ScalarBuilder{}
390 390 .setX({1., 2., 3., 4., 5.})
391 391 .setValues({100., 200., 300., 400., 500.})
392 392 .build()
393 393 << 2. << 4. << true << 200. << 400.;
394 394 QTest::newRow("scalarBounds3") << ScalarBuilder{}
395 395 .setX({1., 2., 3., 4., 5.})
396 396 .setValues({100., 200., 300., 400., 500.})
397 397 .build()
398 398 << 0. << 0.5 << false << nan << nan;
399 399 QTest::newRow("scalarBounds4") << ScalarBuilder{}
400 400 .setX({1., 2., 3., 4., 5.})
401 401 .setValues({100., 200., 300., 400., 500.})
402 402 .build()
403 403 << 5.1 << 6. << false << nan << nan;
404 QTest::newRow("scalarBounds5")
405 << ScalarBuilder{}.setX({1.}).setValues({100.}).build() << 0. << 2. << true << 100. << 100.;
406 QTest::newRow("scalarBounds6")
407 << ScalarBuilder{}.setX({}).setValues({}).build() << 0. << 2. << false << nan << nan;
404 QTest::newRow("scalarBounds5") << ScalarBuilder{}.setX({1.}).setValues({100.}).build() << 0.
405 << 2. << true << 100. << 100.;
406 QTest::newRow("scalarBounds6") << ScalarBuilder{}.setX({}).setValues({}).build() << 0. << 2.
407 << false << nan << nan;
408 408
409 409 // Tests with NaN values: NaN values are not included in min/max search
410 410 QTest::newRow("scalarBounds7") << ScalarBuilder{}
411 411 .setX({1., 2., 3., 4., 5.})
412 412 .setValues({nan, 200., 300., 400., nan})
413 413 .build()
414 414 << 0. << 6. << true << 200. << 400.;
415 415 QTest::newRow("scalarBounds8")
416 416 << ScalarBuilder{}.setX({1., 2., 3., 4., 5.}).setValues({nan, nan, nan, nan, nan}).build()
417 417 << 0. << 6. << true << nan << nan;
418 418 }
419 419
420 420 void TestScalarSeries::testValuesBounds()
421 421 {
422 422 testValuesBounds_t<ScalarSeries>();
423 423 }
424 424
425 425 QTEST_MAIN(TestScalarSeries)
426 426 #include "TestScalarSeries.moc"
@@ -1,45 +1,47
1 1 #include "DataSource/DataSourceTreeWidget.h"
2 2 #include "Common/MimeTypesDef.h"
3 3 #include "DataSource/DataSourceController.h"
4 4 #include "DataSource/DataSourceItem.h"
5 5 #include "DataSource/DataSourceTreeWidgetItem.h"
6 6
7 7 #include "DragAndDrop/DragDropHelper.h"
8 8 #include "SqpApplication.h"
9 9
10 10 #include <QMimeData>
11 11
12 DataSourceTreeWidget::DataSourceTreeWidget(QWidget *parent) : QTreeWidget(parent) {}
12 DataSourceTreeWidget::DataSourceTreeWidget(QWidget *parent) : QTreeWidget(parent)
13 {
14 }
13 15
14 16 QMimeData *DataSourceTreeWidget::mimeData(const QList<QTreeWidgetItem *> items) const
15 17 {
16 18 auto mimeData = new QMimeData;
17 19
18 20 // Basic check to ensure the item are correctly typed
19 21 Q_ASSERT(items.isEmpty() || dynamic_cast<DataSourceTreeWidgetItem *>(items.first()) != nullptr);
20 22
21 23 QVariantList productData;
22 24
23 25 for (auto item : items) {
24 26 auto dataSourceTreeItem = static_cast<DataSourceTreeWidgetItem *>(item);
25 27 auto dataSource = dataSourceTreeItem->data();
26 28
27 29 if (dataSource->type() == DataSourceItemType::COMPONENT
28 30 || dataSource->type() == DataSourceItemType::PRODUCT) {
29 31 auto metaData = dataSource->data();
30 32 productData << metaData;
31 33 }
32 34 }
33 35
34 36 auto encodedData = sqpApp->dataSourceController().mimeDataForProductsData(productData);
35 37 mimeData->setData(MIME_TYPE_PRODUCT_LIST, encodedData);
36 38
37 39 return mimeData;
38 40 }
39 41
40 42 void DataSourceTreeWidget::startDrag(Qt::DropActions supportedActions)
41 43 {
42 44 // Resets the drag&drop operations before it's starting
43 45 sqpApp->dragDropHelper().resetDragAndDrop();
44 46 QTreeWidget::startDrag(supportedActions);
45 47 }
@@ -1,292 +1,294
1 1 #include "DragAndDrop/DragDropHelper.h"
2 2 #include "DragAndDrop/DragDropScroller.h"
3 3 #include "DragAndDrop/DragDropTabSwitcher.h"
4 4 #include "SqpApplication.h"
5 5 #include "Visualization/VisualizationDragDropContainer.h"
6 6 #include "Visualization/VisualizationDragWidget.h"
7 7 #include "Visualization/VisualizationWidget.h"
8 8 #include "Visualization/operations/FindVariableOperation.h"
9 9
10 10 #include "Variable/Variable.h"
11 11 #include "Variable/VariableController.h"
12 12
13 13 #include "Common/MimeTypesDef.h"
14 14 #include "Common/VisualizationDef.h"
15 15
16 16 #include <QDir>
17 17 #include <QLabel>
18 18 #include <QUrl>
19 19 #include <QVBoxLayout>
20 20
21 21
22 22 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDropHelper")
23 23
24 24
25 25 struct DragDropHelper::DragDropHelperPrivate {
26 26
27 27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 29 QLabel *m_PlaceHolderLabel;
30 30 QWidget *m_PlaceBackground;
31 31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 34 // QTemporaryFile to have a name which is not generated.
35 35
36 36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37 37
38 38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40 40
41 41 QList<QWidget *> m_WidgetToClose;
42 42
43 43 explicit DragDropHelperPrivate()
44 44 : m_PlaceHolder{std::make_unique<QWidget>()},
45 45 m_DragDropScroller{std::make_unique<DragDropScroller>()},
46 46 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
47 47 {
48 48
49 49 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
50 50 layout->setSpacing(0);
51 51 layout->setContentsMargins(0, 0, 0, 0);
52 52
53 53 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
54 54 m_PlaceHolderLabel->setMinimumHeight(25);
55 55 layout->addWidget(m_PlaceHolderLabel);
56 56
57 57 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
58 58 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
59 59 layout->addWidget(m_PlaceBackground);
60 60
61 61 sqpApp->installEventFilter(m_DragDropScroller.get());
62 62 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
63 63
64 64 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
65 65 }
66 66
67 67 void preparePlaceHolder(DragDropHelper::PlaceHolderType type, const QString &topLabelText) const
68 68 {
69 69 if (m_CurrentDragWidget) {
70 70 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
71 71 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
72 72 }
73 73 else {
74 74 // Configuration of the placeHolder when there is no dragWidget
75 75 // (for instance with a drag from a variable)
76 76
77 77 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
78 78 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
79 79 }
80 80
81 81 switch (type) {
82 82 case DragDropHelper::PlaceHolderType::Graph:
83 83 m_PlaceBackground->setStyleSheet(
84 84 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
85 85 break;
86 86 case DragDropHelper::PlaceHolderType::Zone:
87 87 case DragDropHelper::PlaceHolderType::Default:
88 88 m_PlaceBackground->setStyleSheet(
89 89 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
90 90 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
91 91 break;
92 92 }
93 93
94 94 m_PlaceHolderLabel->setText(topLabelText);
95 95 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
96 96 }
97 97 };
98 98
99 99
100 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
100 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
101 {
102 }
101 103
102 104 DragDropHelper::~DragDropHelper()
103 105 {
104 106 QFile::remove(impl->m_ImageTempUrl);
105 107 }
106 108
107 109 void DragDropHelper::resetDragAndDrop()
108 110 {
109 111 setCurrentDragWidget(nullptr);
110 112 impl->m_HighlightedDragWidget = nullptr;
111 113 }
112 114
113 115 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
114 116 {
115 117 if (impl->m_CurrentDragWidget) {
116 118
117 119 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
118 120 }
119 121
120 122 if (dragWidget) {
121 123 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
122 124 impl->m_DragWidgetDestroyedConnection
123 125 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
124 126 [this]() { impl->m_CurrentDragWidget = nullptr; });
125 127 }
126 128
127 129 impl->m_CurrentDragWidget = dragWidget;
128 130 }
129 131
130 132 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
131 133 {
132 134 return impl->m_CurrentDragWidget;
133 135 }
134 136
135 137 QWidget &DragDropHelper::placeHolder() const
136 138 {
137 139 return *impl->m_PlaceHolder;
138 140 }
139 141
140 142 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
141 143 const QString &topLabelText)
142 144 {
143 145 removePlaceHolder();
144 146 impl->preparePlaceHolder(type, topLabelText);
145 147 layout->insertWidget(index, impl->m_PlaceHolder.get());
146 148 impl->m_PlaceHolder->show();
147 149 }
148 150
149 151 void DragDropHelper::removePlaceHolder()
150 152 {
151 153 auto parentWidget = impl->m_PlaceHolder->parentWidget();
152 154 if (parentWidget) {
153 155 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
154 156 impl->m_PlaceHolder->setParent(nullptr);
155 157 impl->m_PlaceHolder->hide();
156 158 }
157 159 }
158 160
159 161 bool DragDropHelper::isPlaceHolderSet() const
160 162 {
161 163 return impl->m_PlaceHolder->parentWidget();
162 164 }
163 165
164 166 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
165 167 {
166 168 impl->m_DragDropScroller->addScrollArea(scrollArea);
167 169 }
168 170
169 171 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
170 172 {
171 173 impl->m_DragDropScroller->removeScrollArea(scrollArea);
172 174 }
173 175
174 176 void DragDropHelper::addDragDropTabBar(QTabBar *tabBar)
175 177 {
176 178 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
177 179 }
178 180
179 181 void DragDropHelper::removeDragDropTabBar(QTabBar *tabBar)
180 182 {
181 183 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
182 184 }
183 185
184 186 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
185 187 {
186 188 image.save(impl->m_ImageTempUrl);
187 189 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
188 190 }
189 191
190 192 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
191 193 {
192 194 if (impl->m_HighlightedDragWidget) {
193 195 impl->m_HighlightedDragWidget->highlightForMerge(false);
194 196 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
195 197 }
196 198
197 199 if (dragWidget) {
198 200 dragWidget->highlightForMerge(true);
199 201
200 202 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
201 203 impl->m_DragWidgetDestroyedConnection
202 204 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
203 205 [this]() { impl->m_HighlightedDragWidget = nullptr; });
204 206 }
205 207
206 208 impl->m_HighlightedDragWidget = dragWidget;
207 209 }
208 210
209 211 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
210 212 {
211 213 return impl->m_HighlightedDragWidget;
212 214 }
213 215
214 216 void DragDropHelper::delayedCloseWidget(QWidget *widget)
215 217 {
216 218 widget->hide();
217 219 impl->m_WidgetToClose << widget;
218 220 }
219 221
220 222 void DragDropHelper::doCloseWidgets()
221 223 {
222 224 for (auto widget : impl->m_WidgetToClose) {
223 225 widget->close();
224 226 }
225 227
226 228 impl->m_WidgetToClose.clear();
227 229 }
228 230
229 231 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
230 232 VisualizationDragDropContainer *dropContainer)
231 233 {
232 234 if (!mimeData || !dropContainer) {
233 235 qCWarning(LOG_DragDropHelper()) << QObject::tr(
234 236 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
235 237 Q_ASSERT(false);
236 238 return false;
237 239 }
238 240
239 241 auto result = false;
240 242
241 243 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
242 244 auto variables = sqpApp->variableController().variablesForMimeData(
243 245 mimeData->data(MIME_TYPE_VARIABLE_LIST));
244 246
245 247 if (variables.count() == 1) {
246 248
247 249 auto variable = variables.first();
248 250 if (variable->dataSeries() != nullptr) {
249 251
250 252 // Check that the variable is not already in a graph
251 253
252 254 auto parent = dropContainer->parentWidget();
253 255 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
254 256 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
255 257 }
256 258
257 259 if (parent) {
258 260 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
259 261
260 262 FindVariableOperation findVariableOperation{variable};
261 263 visualizationWidget->accept(&findVariableOperation);
262 264 auto variableContainers = findVariableOperation.result();
263 265 if (variableContainers.empty()) {
264 266 result = true;
265 267 }
266 268 else {
267 269 // result = false: the variable already exist in the visualisation
268 270 }
269 271 }
270 272 else {
271 273 qCWarning(LOG_DragDropHelper()) << QObject::tr(
272 274 "DragDropHelper::checkMimeDataForVisualization, the parent "
273 275 "VisualizationWidget cannot be found. Cannot check if the variable is "
274 276 "already used or not.");
275 277 }
276 278 }
277 279 else {
278 280 // result = false: the variable is not fully loaded
279 281 }
280 282 }
281 283 else {
282 284 // result = false: cannot drop multiple variables in the visualisation
283 285 }
284 286 }
285 287 else {
286 288 // Other MIME data
287 289 // no special rules, accepted by default
288 290 result = true;
289 291 }
290 292
291 293 return result;
292 294 }
@@ -1,13 +1,15
1 1 #include "Variable/VariableInspectorTableView.h"
2 2
3 3 #include "DragAndDrop/DragDropHelper.h"
4 4 #include "SqpApplication.h"
5 5
6 VariableInspectorTableView::VariableInspectorTableView(QWidget *parent) : QTableView(parent) {}
6 VariableInspectorTableView::VariableInspectorTableView(QWidget *parent) : QTableView(parent)
7 {
8 }
7 9
8 10 void VariableInspectorTableView::startDrag(Qt::DropActions supportedActions)
9 11 {
10 12 // Resets the drag&drop operations before it's starting
11 13 sqpApp->dragDropHelper().resetDragAndDrop();
12 14 QTableView::startDrag(supportedActions);
13 15 }
General Comments 0
You need to be logged in to leave comments. Login now