BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
viewportaxisplotcontroller.test.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // qt-mvvm: Model-view-view-model framework for large GUI applications
4 //
5 //! @file mvvm/tests/testview/viewportaxisplotcontroller.test.cpp
6 //! @brief Implements class CLASS?
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2020
11 //! @authors Gennady Pospelov et al, Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "customplot_test_utils.h"
16 #include "google_test.h"
17 #include "mockwidgets.h"
22 #include "qcustomplot.h"
23 #include <QSignalSpy>
24 
25 using namespace ModelView;
26 using ::testing::_;
27 
28 //! Testing AxisPlotControllers.
29 
30 class ViewportAxisPlotControllerTest : public ::testing::Test {
31 public:
33 
34  std::unique_ptr<QSignalSpy> createSpy(QCPAxis* axis)
35  {
36  return std::make_unique<QSignalSpy>(
37  axis, static_cast<void (QCPAxis::*)(const QCPRange&)>(&QCPAxis::rangeChanged));
38  }
39 
40  std::unique_ptr<QSignalSpy> createSpy2(QCPAxis* axis)
41  {
42  return std::make_unique<QSignalSpy>(
43  axis, static_cast<void (QCPAxis::*)(const QCPRange&, const QCPRange&)>(
44  &QCPAxis::rangeChanged));
45  }
46 };
47 
49 
50 //! Initial state.
51 
53 {
54  auto custom_plot = std::make_unique<QCustomPlot>();
55 
56  auto axis = custom_plot->xAxis;
57 
58  // checking initial defaults
59  const double customplot_default_lower(0.0), customplot_default_upper(5.0);
60  EXPECT_EQ(axis->range().lower, customplot_default_lower);
61  EXPECT_EQ(axis->range().upper, customplot_default_upper);
62 
63  // controller shouldn''t change axis range
64  ViewportAxisPlotController controller(axis);
65  EXPECT_EQ(axis->range().lower, customplot_default_lower);
66  EXPECT_EQ(axis->range().upper, customplot_default_upper);
67 
68  // checking axis signaling
69  auto xChanged = createSpy(custom_plot->xAxis);
70  auto yChanged = createSpy(custom_plot->yAxis);
71 
72  // changing range of axis
73  custom_plot->xAxis->setRangeLower(1.0);
74 
75  // checking that QCPaxis properly emiting signals
76  EXPECT_EQ(xChanged->count(), 1);
77  EXPECT_EQ(yChanged->count(), 0);
78 }
79 
80 //! Controller subscribed to ViewportAxisItem.
81 //! Checking that QCPAxis get same parameters as in AxisItem.
82 
84 {
85  auto custom_plot = std::make_unique<QCustomPlot>();
86  const double expected_min = 1.0;
87  const double expected_max = 2.0;
88 
89  // creating the model with single ViewportAxisItem
90  SessionModel model;
91  auto axisItem = model.insertItem<ViewportAxisItem>();
92  axisItem->setProperty(ViewportAxisItem::P_MIN, expected_min);
93  axisItem->setProperty(ViewportAxisItem::P_MAX, expected_max);
94 
95  // setting up QCustomPlot and item controller.
96  ASSERT_TRUE(custom_plot->xAxis != nullptr);
97  ViewportAxisPlotController controller(custom_plot->xAxis);
98 
99  auto prev_y_range = custom_plot->yAxis->range();
100  auto xChanged = createSpy(custom_plot->xAxis);
101  auto yChanged = createSpy(custom_plot->yAxis);
102 
103  // Subscribtion to ViewportAxisItem should change QCPAxis range for X.
104  controller.setItem(axisItem);
105 
106  EXPECT_EQ(custom_plot->xAxis->range().lower, expected_min);
107  EXPECT_EQ(custom_plot->xAxis->range().upper, expected_max);
108  EXPECT_EQ(xChanged->count(), 1);
109  EXPECT_EQ(yChanged->count(), 0);
110 
111  // Range for QCPAxis y-axis should stay the same.
112  EXPECT_EQ(custom_plot->yAxis->range(), prev_y_range);
113 }
114 
115 //! Controller subscribed to ViewportAxisItem.
116 //! Change QCPAxis and check that ViewportAxisItem got new values.
117 
119 {
120  auto custom_plot = std::make_unique<QCustomPlot>();
121 
122  // creating the model with single ViewportAxisItem
123  SessionModel model;
124  auto axisItem = model.insertItem<ViewportAxisItem>();
125  axisItem->setProperty(ViewportAxisItem::P_MIN, 42.0);
126  axisItem->setProperty(ViewportAxisItem::P_MAX, 42.1);
127 
128  // setting up QCustomPlot and item controller.
129  const double expected_min = 1.0;
130  const double expected_max = 2.0;
131  auto xChanged = createSpy(custom_plot->xAxis);
132  auto yChanged = createSpy(custom_plot->yAxis);
133 
134  // Setting up controller.
135  ViewportAxisPlotController controller(custom_plot->xAxis);
136  controller.setItem(axisItem);
137 
138  EXPECT_EQ(xChanged->count(), 1);
139  EXPECT_EQ(yChanged->count(), 0);
140 
141  // Changing QCPAxis
142  custom_plot->xAxis->setRange(expected_min, expected_max);
143  EXPECT_EQ(xChanged->count(), 2);
144  EXPECT_EQ(yChanged->count(), 0);
145 
146  // Check changed properties in ViewportAxisItem
147  EXPECT_EQ(axisItem->property<double>(ViewportAxisItem::P_MIN), expected_min);
148  EXPECT_EQ(axisItem->property<double>(ViewportAxisItem::P_MAX), expected_max);
149 }
150 
151 //! Controller subscribed to ViewportAxisItem.
152 //! Change ViewportAxisItem and check that QCPAxis got new values.
153 
154 TEST_F(ViewportAxisPlotControllerTest, changeViewportAxisItem)
155 {
156  auto custom_plot = std::make_unique<QCustomPlot>();
157 
158  // creating the model with single ViewportAxisItem
159  SessionModel model;
160  auto axisItem = model.insertItem<ViewportAxisItem>();
161  axisItem->setProperty(ViewportAxisItem::P_MIN, 42.0);
162  axisItem->setProperty(ViewportAxisItem::P_MAX, 42.1);
163 
164  // setting up QCustomPlot and item controller.
165  ViewportAxisPlotController controller(custom_plot->xAxis);
166  controller.setItem(axisItem);
167  auto xChanged = createSpy(custom_plot->xAxis);
168  auto yChanged = createSpy(custom_plot->yAxis);
169 
170  // changing values
171  const double expected_min = 1.0;
172  const double expected_max = 2.0;
173  axisItem->setProperty(ViewportAxisItem::P_MIN, expected_min);
174  axisItem->setProperty(ViewportAxisItem::P_MAX, expected_max);
175 
176  // Checking QCPAxis
177  EXPECT_EQ(xChanged->count(), 2);
178  EXPECT_EQ(yChanged->count(), 0);
179  EXPECT_EQ(custom_plot->xAxis->range().lower, expected_min);
180  EXPECT_EQ(custom_plot->xAxis->range().upper, expected_max);
181 }
182 
183 //! Controller subscribed to ViewportAxisItem.
184 //! Change ViewportAxisItem and check that QCPAxis got new values.
185 //! Check correctness of signals issued by QCPAxisItem.
186 
187 TEST_F(ViewportAxisPlotControllerTest, changeViewportAxisItemSignaling)
188 {
189  auto custom_plot = std::make_unique<QCustomPlot>();
190 
191  // creating the model with single ViewportAxisItem
192  SessionModel model;
193  auto axisItem = model.insertItem<ViewportAxisItem>();
194  axisItem->setProperty(ViewportAxisItem::P_MIN, 1.0);
195  axisItem->setProperty(ViewportAxisItem::P_MAX, 2.0);
196 
197  // setting up QCustomPlot and item controller.
198  ViewportAxisPlotController controller(custom_plot->xAxis);
199  controller.setItem(axisItem);
200 
201  // initial condition
202  EXPECT_EQ(custom_plot->xAxis->range().lower, 1.0);
203  EXPECT_EQ(custom_plot->xAxis->range().upper, 2.0);
204 
205  auto rangeChanged = createSpy(custom_plot->xAxis);
206  auto rangeChanged2 = createSpy2(custom_plot->xAxis);
207 
208  // making a change
209  const double expected_max = 20.0;
210  axisItem->setProperty(ViewportAxisItem::P_MAX, expected_max);
211 
212  // Checking QCPAxis
213  EXPECT_EQ(rangeChanged->count(), 1);
214  EXPECT_EQ(rangeChanged2->count(), 1);
215  EXPECT_EQ(custom_plot->xAxis->range().lower, 1.0);
216  EXPECT_EQ(custom_plot->xAxis->range().upper, expected_max);
217 
218  QList<QVariant> arguments = rangeChanged->takeFirst();
219  EXPECT_EQ(arguments.size(), 1);
220  auto reportedRange = arguments.at(0).value<QCPRange>();
221  EXPECT_EQ(reportedRange.lower, 1.0);
222  EXPECT_EQ(reportedRange.upper, 20.0);
223 
224  arguments = rangeChanged2->takeFirst();
225  EXPECT_EQ(arguments.size(), 2);
226  auto newRange = arguments.at(0).value<QCPRange>();
227  auto oldRange = arguments.at(1).value<QCPRange>();
228  EXPECT_EQ(newRange.lower, 1.0);
229  EXPECT_EQ(newRange.upper, 20.0);
230  EXPECT_EQ(oldRange.lower, 1.0);
231  EXPECT_EQ(oldRange.upper, 2.0);
232 }
233 
234 //! Controller subscribed to ViewportAxisItem.
235 //! Change ViewportAxisItem and check that QCPAxis got new values.
236 //! Check correctness that there is not extra looping and item doesn't start changing many times
237 
238 TEST_F(ViewportAxisPlotControllerTest, changeViewportAxisItemMapping)
239 {
240  auto custom_plot = std::make_unique<QCustomPlot>();
241 
242  // creating the model with single ViewportAxisItem
243  SessionModel model;
244  auto axisItem = model.insertItem<ViewportAxisItem>();
245  axisItem->setProperty(ViewportAxisItem::P_MIN, 1.0);
246  axisItem->setProperty(ViewportAxisItem::P_MAX, 2.0);
247 
248  // setting up QCustomPlot and item controller.
249  ViewportAxisPlotController controller(custom_plot->xAxis);
250  controller.setItem(axisItem);
251 
252  MockWidgetForItem widget(axisItem);
253  EXPECT_CALL(widget, onDataChange(_, _)).Times(0);
254  EXPECT_CALL(widget, onPropertyChange(axisItem, ViewportAxisItem::P_MAX)).Times(1);
255  EXPECT_CALL(widget, onChildPropertyChange(_, _)).Times(0);
256  EXPECT_CALL(widget, onItemInserted(_, _)).Times(0);
257  EXPECT_CALL(widget, onAboutToRemoveItem(_, _)).Times(0);
258 
259  // making a change
260  const double expected_max = 20.0;
261  axisItem->setProperty(ViewportAxisItem::P_MAX, expected_max);
262 
263  EXPECT_EQ(custom_plot->xAxis->range().lower, 1.0);
264  EXPECT_EQ(custom_plot->xAxis->range().upper, expected_max);
265 }
266 
267 //! Set ViewportAxisItem logz, subscribe controller and check that QCPAxis has it.
268 
270 {
271  auto custom_plot = std::make_unique<QCustomPlot>();
272 
273  // creating the model with single ViewportAxisItem
274  SessionModel model;
275  auto axisItem = model.insertItem<ViewportAxisItem>();
276  axisItem->setProperty(ViewportAxisItem::P_IS_LOG, true);
277 
278  // setting up QCustomPlot and item controller.
279  auto qcp_axis = custom_plot->xAxis;
280  ViewportAxisPlotController controller(qcp_axis);
281  controller.setItem(axisItem);
282 
283  // QCPAxis should switch to logarithmic
284  EXPECT_EQ(qcp_axis->scaleType(), QCPAxis::stLogarithmic);
285 }
286 
287 //! Controller subscribed to ViewportAxisItem.
288 //! Change ViewportAxisItem logz and check that QCPAxis got new values.
289 
291 {
292  auto custom_plot = std::make_unique<QCustomPlot>();
293 
294  // creating the model with single ViewportAxisItem
295  SessionModel model;
296  auto axisItem = model.insertItem<ViewportAxisItem>();
297 
298  // setting up QCustomPlot and item controller.
299  auto qcp_axis = custom_plot->xAxis;
300  ViewportAxisPlotController controller(qcp_axis);
301  controller.setItem(axisItem);
302 
303  // initial linear scale of axis
304  EXPECT_EQ(qcp_axis->scaleType(), QCPAxis::stLinear);
305 
306  // changing scale
307  axisItem->setProperty(ViewportAxisItem::P_IS_LOG, true);
308 
309  // QCPAxis should switch to logarithmic
310  EXPECT_EQ(qcp_axis->scaleType(), QCPAxis::stLogarithmic);
311 }
312 
313 //! Controller subscribed to ViewportAxisItem.
314 //! Change ViewportAxisItem and check that QCPAxis got new values.
315 //! Same test as before, only QCPAxis y-axis checked.
316 
317 TEST_F(ViewportAxisPlotControllerTest, changeViewportAxisItemYCase)
318 {
319  auto custom_plot = std::make_unique<QCustomPlot>();
320 
321  // creating the model with single ViewportAxisItem
322  SessionModel model;
323  auto axisItem = model.insertItem<ViewportAxisItem>();
324  axisItem->setProperty(ViewportAxisItem::P_MIN, 42.0);
325  axisItem->setProperty(ViewportAxisItem::P_MAX, 42.1);
326 
327  // setting up QCustomPlot and item controller.
328  ViewportAxisPlotController controller(custom_plot->yAxis);
329  controller.setItem(axisItem);
330  auto xChanged = createSpy(custom_plot->xAxis);
331  auto yChanged = createSpy(custom_plot->yAxis);
332 
333  // changing values
334  const double expected_min = 1.0;
335  const double expected_max = 2.0;
336  axisItem->setProperty(ViewportAxisItem::P_MIN, expected_min);
337  axisItem->setProperty(ViewportAxisItem::P_MAX, expected_max);
338 
339  // Checking QCPAxis
340  EXPECT_EQ(xChanged->count(), 0);
341  EXPECT_EQ(yChanged->count(), 2);
342  EXPECT_EQ(custom_plot->yAxis->range().lower, expected_min);
343  EXPECT_EQ(custom_plot->yAxis->range().upper, expected_max);
344 }
345 
346 //! Model with two AxisItem's. Controller first is subscribed to one item, then to another.
347 
348 TEST_F(ViewportAxisPlotControllerTest, oneControllerTwoAxisItems)
349 {
350  auto custom_plot = std::make_unique<QCustomPlot>();
351 
352  // creating the model with single ViewportAxisItem
353  SessionModel model;
354  auto axis_item0 = model.insertItem<ViewportAxisItem>();
355  axis_item0->setProperty(ViewportAxisItem::P_MIN, 1.0);
356  axis_item0->setProperty(ViewportAxisItem::P_MAX, 2.0);
357 
358  auto axis_item1 = model.insertItem<ViewportAxisItem>();
359  axis_item1->setProperty(ViewportAxisItem::P_MIN, 10.0);
360  axis_item1->setProperty(ViewportAxisItem::P_MAX, 20.0);
361 
362  // setting up QCustomPlot and item controller.
363  auto controller = std::make_unique<ViewportAxisPlotController>(custom_plot->xAxis);
364  controller->setItem(axis_item0);
365  auto xChanged = createSpy(custom_plot->xAxis);
366  auto yChanged = createSpy(custom_plot->yAxis);
367 
368  // initial axis status
369  EXPECT_EQ(axis_item0->property<double>(ViewportAxisItem::P_MIN),
370  custom_plot->xAxis->range().lower);
371  EXPECT_EQ(axis_item0->property<double>(ViewportAxisItem::P_MAX),
372  custom_plot->xAxis->range().upper);
373 
374  // switching to second axis
375  controller->setItem(axis_item1);
376 
377  EXPECT_EQ(xChanged->count(), 1);
378  EXPECT_EQ(yChanged->count(), 0);
379 
380  EXPECT_EQ(axis_item1->property<double>(ViewportAxisItem::P_MIN),
381  custom_plot->xAxis->range().lower);
382  EXPECT_EQ(axis_item1->property<double>(ViewportAxisItem::P_MAX),
383  custom_plot->xAxis->range().upper);
384 
385  // changing QCPAxis
386  const double expected_min = 100.0;
387  const double expected_max = 200.0;
388  custom_plot->xAxis->setRange(expected_min, expected_max);
389 
390  // previous axis should still have original values
391  EXPECT_EQ(axis_item0->property<double>(ViewportAxisItem::P_MIN), 1.0);
392  EXPECT_EQ(axis_item0->property<double>(ViewportAxisItem::P_MAX), 2.0);
393 
394  // second axis should get values from QCPAxis
395  EXPECT_EQ(axis_item1->property<double>(ViewportAxisItem::P_MIN), expected_min);
396  EXPECT_EQ(axis_item1->property<double>(ViewportAxisItem::P_MAX), expected_max);
397 
398  // removing axes from the model
399  model.removeItem(model.rootItem(), {"", 0});
400  model.removeItem(model.rootItem(), {"", 0});
401  EXPECT_EQ(model.rootItem()->childrenCount(), 0);
402 
403  // no UB should follow (valgrind will tell us)
404  custom_plot->xAxis->setRange(1.0, 2.0);
405 
406  // destroying controller, no UB
407  controller.reset();
408  custom_plot->xAxis->setRange(2.0, 3.0);
409 }
410 
411 //! Controller subscribed to ViewportAxisItem.
412 //! Change ViewportAxisItem title and check that QCPAxis got new values.
413 
415 {
416  auto custom_plot = std::make_unique<QCustomPlot>();
417 
418  // creating the model with single ViewportAxisItem
419  SessionModel model;
420  auto axisItem = model.insertItem<ViewportAxisItem>();
421 
422  // setting up QCustomPlot and item controller.
423  auto qcp_axis = custom_plot->xAxis;
424  ViewportAxisPlotController controller(qcp_axis);
425  controller.setItem(axisItem);
426 
427  // changing title
428  auto textItem = axisItem->item<TextItem>(ViewportAxisItem::P_TITLE);
429  textItem->setProperty(TextItem::P_TEXT, "abc");
430 
431  // no need to change title size and font (checked in axistitlecontroller.test)
432 
433  // QCPAxis should switch to logarithmic
434  EXPECT_EQ(qcp_axis->label(), QString("abc"));
435 }
Defines class CLASS?
Mock widget to test ItemMapper functionality.
Definition: mockwidgets.h:36
static const std::string P_MAX
Definition: axisitems.h:32
static const std::string P_MIN
Definition: axisitems.h:31
void setItem(SessionItem *item)
int childrenCount() const
Returns total number of children in all tags.
void setProperty(const std::string &tag, const T &value)
Sets value to property item.
Definition: sessionitem.h:190
Main class to hold hierarchy of SessionItem objects.
Definition: sessionmodel.h:37
SessionItem * rootItem() const
Returns root item of the model.
T * insertItem(SessionItem *parent=nullptr, const TagRow &tagrow={})
Inserts item into given parent under given tagrow.
Definition: sessionmodel.h:104
void removeItem(SessionItem *parent, const TagRow &tagrow)
Removes given row from parent.
Represent text item on plot.
static const std::string P_TEXT
Item to represent viewport axis.
Definition: axisitems.h:43
static const std::string P_IS_LOG
Definition: axisitems.h:46
static const std::string P_TITLE
Definition: axisitems.h:45
Establishes communication between QCPAxis and ViewportAxisItem.
std::unique_ptr< QSignalSpy > createSpy2(QCPAxis *axis)
std::unique_ptr< QSignalSpy > createSpy(QCPAxis *axis)
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
materialitems.h Collection of materials to populate MaterialModel.
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
TEST_F(ViewportAxisPlotControllerTest, initialState)
Initial state.