BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
sessionitem.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/testmodel/sessionitem.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 "google_test.h"
16 #include "mvvm/model/itempool.h"
17 #include "mvvm/model/itemutils.h"
18 #include "mvvm/model/sessionitem.h"
21 #include "mvvm/model/taginfo.h"
23 #include "test_utils.h"
24 #include <memory>
25 #include <stdexcept>
26 
27 using namespace ModelView;
28 
29 class SessionItemTest : public ::testing::Test {
30 public:
32 };
33 
35 
36 TEST_F(SessionItemTest, initialState)
37 {
38  SessionItem item;
39  const int role = ItemDataRole::DATA;
40 
41  EXPECT_EQ(item.model(), nullptr);
42  EXPECT_EQ(item.parent(), nullptr);
43  EXPECT_EQ(item.childrenCount(), 0);
44  EXPECT_FALSE(item.data<QVariant>(role).isValid());
45  EXPECT_TRUE(item.children().empty());
46  EXPECT_EQ(item.modelType(), Constants::BaseType);
47  EXPECT_EQ(item.displayName(), Constants::BaseType);
48 
49  // Initially item has already an identifier defined.
50  std::vector<int> expected_roles = {ItemDataRole::IDENTIFIER, ItemDataRole::DISPLAY};
51  EXPECT_EQ(item.itemData()->roles(), expected_roles);
52 
53  // Identifier is not zero
54  EXPECT_FALSE(item.identifier().empty());
55 }
56 
58 {
59  SessionItem item2("Layer");
60  EXPECT_EQ(item2.modelType(), "Layer");
61 }
62 
63 //! Validating ::setData and appearance of roles.
64 
66 {
67  SessionItem item;
68  const int role = ItemDataRole::DATA;
69 
70  EXPECT_FALSE(item.data<QVariant>(role).isValid());
71 
72  QVariant expected(42.0);
73  EXPECT_TRUE(item.setData(expected, role));
74 
75  std::vector<int> expected_roles = {ItemDataRole::IDENTIFIER, ItemDataRole::DISPLAY,
77  EXPECT_EQ(item.itemData()->roles(), expected_roles);
78  EXPECT_EQ(item.data<QVariant>(role), expected);
79 
80  // setting another value
81  EXPECT_TRUE(item.setData(43.0, role));
82  EXPECT_EQ(item.itemData()->roles(), expected_roles);
83  EXPECT_EQ(item.data<QVariant>(role), QVariant::fromValue(43.0));
84 
85  // setting same value
86  EXPECT_FALSE(item.setData(43.0, role));
87  EXPECT_EQ(item.itemData()->roles(), expected_roles);
88  EXPECT_EQ(item.data<QVariant>(role), QVariant::fromValue(43.0));
89 }
90 
91 //! Validating ::setData in the context of implicit conversion.
92 
93 TEST_F(SessionItemTest, setDataAndImplicitConversion)
94 {
95  {
96  SessionItem item;
97  const int role = ItemDataRole::DATA;
98  EXPECT_TRUE(item.setData(43.0, ItemDataRole::DATA));
99  EXPECT_EQ(item.data<QVariant>(role).typeName(), Constants::double_type_name);
100  }
101 
102  {
103  SessionItem item;
104  const int role = ItemDataRole::DATA;
105  EXPECT_TRUE(item.setData(43, ItemDataRole::DATA));
106  EXPECT_EQ(item.data<QVariant>(role).typeName(), Constants::int_type_name);
107  }
108 }
109 
111 {
112  SessionItem item;
113 
114  EXPECT_FALSE(item.hasData());
115  EXPECT_TRUE(item.hasData(ItemDataRole::IDENTIFIER));
116  EXPECT_FALSE(item.hasData(ItemDataRole::DATA));
117  EXPECT_TRUE(item.hasData(ItemDataRole::DISPLAY));
118  EXPECT_FALSE(item.hasData(ItemDataRole::APPEARANCE));
119  EXPECT_FALSE(item.hasData(ItemDataRole::LIMITS));
120  EXPECT_FALSE(item.hasData(ItemDataRole::TOOLTIP));
121  EXPECT_FALSE(item.hasData(ItemDataRole::EDITORTYPE));
122 
123  item.setData(42.0);
124  EXPECT_TRUE(item.hasData());
125 }
126 
127 TEST_F(SessionItemTest, setDoubleData)
128 {
129  SessionItem item;
130  const double expected = 42.0;
131  EXPECT_TRUE(item.setData(expected));
132  EXPECT_EQ(item.data<double>(), expected);
133 }
134 
136 {
137  SessionItem item;
138  const int expected = 42;
139  EXPECT_TRUE(item.setData(expected));
140  EXPECT_EQ(item.data<int>(), expected);
141 }
142 
143 TEST_F(SessionItemTest, setBoolData)
144 {
145  SessionItem item;
146  const bool expected_true = true;
147  EXPECT_TRUE(item.setData(expected_true));
148  EXPECT_EQ(item.data<bool>(), expected_true);
149  const bool expected_false = false;
150  EXPECT_TRUE(item.setData(expected_false));
151  EXPECT_EQ(item.data<bool>(), expected_false);
152 }
153 
154 TEST_F(SessionItemTest, setStringData)
155 {
156  SessionItem item;
157  const std::string expected{"abc"};
158  EXPECT_TRUE(item.setData(expected));
159  EXPECT_EQ(item.data<std::string>(), expected);
160 }
161 
162 //! Display role.
163 
164 TEST_F(SessionItemTest, displayName)
165 {
166  SessionItem item("Property");
167  QVariant data(42.0);
168  EXPECT_TRUE(item.setData(data));
169 
170  // default display name coincide with model type
171  EXPECT_EQ(item.displayName(), "Property");
172 
173  // checking setter
174  item.setDisplayName("width");
175  EXPECT_EQ(item.displayName(), "width");
176  EXPECT_EQ(item.data<double>(), 42.0);
177 }
178 
179 //! Attempt to set the different Variant to already existing role.
180 
181 TEST_F(SessionItemTest, variantMismatch)
182 {
183  SessionItem item;
184  const int role = ItemDataRole::DATA;
185  QVariant expected(42.0);
186 
187  // setting data for the first time
188  EXPECT_TRUE(item.setData(expected, role));
189 
190  std::vector<int> expected_roles = {ItemDataRole::IDENTIFIER, ItemDataRole::DISPLAY,
192  EXPECT_EQ(item.itemData()->roles(), expected_roles);
193  EXPECT_EQ(item.data<QVariant>(role), expected);
194 
195  // attempt to rewrite variant with another type
196  EXPECT_THROW(item.setData(std::string("abc"), role), std::runtime_error);
197 
198  // removing value by passing invalid variant
199  EXPECT_NO_THROW(item.setData(QVariant(), role));
200  EXPECT_EQ(item.itemData()->roles().size(), 2);
201 }
202 
203 //! Item registration in a pool.
204 
205 TEST_F(SessionItemTest, registerItem)
206 {
207  auto item = std::make_unique<SessionItem>();
208  auto item_id = item->identifier();
209  EXPECT_EQ(item->itemData()->roles().size(), 2u);
210 
211  std::shared_ptr<ItemPool> pool;
212 
213  // creating pool
214  pool.reset(new ItemPool);
215  pool->register_item(item.get(), item_id);
216  // registration shouldn't change item identifier
217  EXPECT_EQ(item->identifier(), item_id);
218 
219  // registration key should coincide with item identifier
220  auto key = pool->key_for_item(item.get());
221  std::vector<int> expected_roles = {ItemDataRole::IDENTIFIER, ItemDataRole::DISPLAY};
222  EXPECT_EQ(item->itemData()->roles(), expected_roles);
223  EXPECT_EQ(item_id, key);
224 }
225 
226 //! Item registration in a pool.
227 
229 {
230  SessionItem item;
231  EXPECT_EQ(item.itemTags()->defaultTag(), std::string());
232  EXPECT_FALSE(Utils::HasTag(item, "defaultTag"));
233 }
234 
235 //! Registering tags
236 
237 TEST_F(SessionItemTest, registerTag)
238 {
239  SessionItem item;
240  item.registerTag(TagInfo::universalTag("tagname"));
241  EXPECT_TRUE(Utils::HasTag(item, "tagname"));
242 
243  // registering of tag with same name forbidden
244  EXPECT_THROW(item.registerTag(TagInfo::universalTag("tagname")), std::runtime_error);
245 
246  // registering empty tag is forbidden
247  EXPECT_THROW(item.registerTag(TagInfo::universalTag("")), std::runtime_error);
248 }
249 
250 //! Registering tag and setting it as default
251 
252 TEST_F(SessionItemTest, registerDefaultTag)
253 {
254  SessionItem item;
255  item.registerTag(TagInfo::universalTag("tagname"), /*set_as_default*/ true);
256  EXPECT_EQ(item.itemTags()->defaultTag(), "tagname");
257 }
258 
259 //! Simple child insert.
260 
262 {
263  auto parent = std::make_unique<SessionItem>();
264  parent->registerTag(TagInfo::universalTag("defaultTag"), /*set_as_default*/ true);
265 
266  std::unique_ptr<SessionItem> child(new SessionItem);
267 
268  // empty parent
269  EXPECT_EQ(parent->childrenCount(), 0);
270  EXPECT_EQ(Utils::IndexOfChild(parent.get(), nullptr), -1);
271  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child.get()), -1);
272  EXPECT_EQ(parent->getItem("", 0), nullptr);
273  EXPECT_EQ(parent->getItem("", -1), nullptr);
274  EXPECT_EQ(parent->getItem("", 10), nullptr);
275 
276  // inserting child
277  auto p_child = child.release();
278  parent->insertItem(p_child, {"", 0});
279  EXPECT_EQ(parent->childrenCount(), 1);
280  EXPECT_EQ(Utils::IndexOfChild(parent.get(), p_child), 0);
281  EXPECT_EQ(parent->children()[0], p_child);
282  EXPECT_EQ(parent->getItem("", 0), p_child);
283  EXPECT_EQ(p_child->parent(), parent.get());
284 }
285 
286 //! Simple children insert.
287 
288 TEST_F(SessionItemTest, insertChildren)
289 {
290  auto parent = std::make_unique<SessionItem>();
291  parent->registerTag(TagInfo::universalTag("defaultTag"), /*set_as_default*/ true);
292 
293  auto child1 = new SessionItem;
294  auto child2 = new SessionItem;
295  auto child3 = new SessionItem;
296  auto child4 = new SessionItem;
297 
298  // inserting two items
299  parent->insertItem(child1, TagRow::append());
300  parent->insertItem(child2, TagRow::append());
301  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child1), 0);
302  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child2), 1);
303  EXPECT_EQ(parent->getItem("", 0), child1);
304  EXPECT_EQ(parent->getItem("", 1), child2);
305  std::vector<SessionItem*> expected = {child1, child2};
306  EXPECT_EQ(parent->children(), expected);
307 
308  // inserting third item between two others
309  parent->insertItem(child3, {"", 1});
310  expected = {child1, child3, child2};
311  EXPECT_EQ(parent->children(), expected);
312  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child1), 0);
313  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child2), 2);
314  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child3), 1);
315  EXPECT_EQ(parent->getItem("", 0), child1);
316  EXPECT_EQ(parent->getItem("", 1), child3);
317  EXPECT_EQ(parent->getItem("", 2), child2);
318  EXPECT_EQ(parent->getItem("", 3), nullptr);
319 
320  // inserting forth item using index equal to number of items
321  parent->insertItem(child4, {"", parent->childrenCount()});
322 
323  // checking parents
324  EXPECT_EQ(child1->parent(), parent.get());
325  EXPECT_EQ(child2->parent(), parent.get());
326  EXPECT_EQ(child3->parent(), parent.get());
327  EXPECT_EQ(child4->parent(), parent.get());
328 
329  // attempt to insert same item twice
330  EXPECT_THROW(parent->insertItem(child2, TagRow::append()), std::runtime_error);
331 
332  // attempt to insert item using out of scope index
333  auto child5 = std::make_unique<SessionItem>();
334  EXPECT_FALSE(parent->insertItem(child5.get(), {"", parent->childrenCount() + 1}));
335 }
336 
337 //! Removing (taking) item from parent.
338 
340 {
341  auto parent = std::make_unique<SessionItem>();
342  parent->registerTag(TagInfo::universalTag("defaultTag"), /*set_as_default*/ true);
343 
344  auto child1 = new SessionItem;
345  auto child2 = new SessionItem;
346  auto child3 = new SessionItem;
347 
348  // inserting items
349  parent->insertItem(child1, TagRow::append());
350  parent->insertItem(child2, TagRow::append());
351  parent->insertItem(child3, TagRow::append());
352 
353  EXPECT_EQ(parent->childrenCount(), 3);
354 
355  // taking non-existing rows
356  EXPECT_EQ(parent->takeItem({"", -1}), nullptr);
357  EXPECT_EQ(parent->takeItem({"", parent->childrenCount()}), nullptr);
358 
359  // taking first row
360  auto taken = parent->takeItem({"", 0});
361  EXPECT_EQ(taken->parent(), nullptr);
362  std::vector<SessionItem*> expected = {child2, child3};
363  EXPECT_EQ(parent->children(), expected);
364 
365  delete taken;
366 }
367 
368 //! Insert and take tagged items.
369 
370 TEST_F(SessionItemTest, singleTagAndItems)
371 {
372  const std::string tag1 = "tag1";
373 
374  // creating parent with one tag
375  auto parent = std::make_unique<SessionItem>();
376  parent->registerTag(TagInfo::universalTag(tag1));
377  EXPECT_TRUE(Utils::HasTag(*parent, tag1));
378 
379  // inserting two children
380  auto child1 = new SessionItem;
381  auto child2 = new SessionItem;
382  parent->insertItem(child1, {tag1, -1});
383  parent->insertItem(child2, {tag1, -1});
384 
385  // testing result of insertion via non-tag interface
386  std::vector<SessionItem*> expected = {child1, child2};
387  EXPECT_EQ(parent->children(), expected);
388  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child1), 0);
389  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child2), 1);
390 
391  // testing single item access via tag interface
392  EXPECT_EQ(parent->getItem(tag1), child1);
393  EXPECT_EQ(parent->getItem(tag1, 0), child1);
394  EXPECT_EQ(parent->getItem(tag1, 1), child2);
395  EXPECT_EQ(parent->getItem(tag1, 2), nullptr); // wrong row
396 
397  // access to multiple items via tags interface
398  EXPECT_EQ(parent->getItems(tag1), expected);
399 
400  // removing first item
401  delete parent->takeItem({tag1, 0});
402  EXPECT_EQ(parent->getItems(tag1), std::vector<SessionItem*>() = {child2});
403  // removing second item
404  delete parent->takeItem({tag1, 0});
405  EXPECT_EQ(parent->getItems(tag1), std::vector<SessionItem*>() = {});
406 
407  // removing from already empty container
408  EXPECT_EQ(parent->takeItem({tag1, 0}), nullptr);
409 }
410 
411 //! Insert and take tagged items when two tags are present.
412 
413 TEST_F(SessionItemTest, twoTagsAndItems)
414 {
415  const std::string tag1 = "tag1";
416  const std::string tag2 = "tag2";
417 
418  // creating parent with one tag
419  auto parent = std::make_unique<SessionItem>();
420  parent->registerTag(TagInfo::universalTag(tag1));
421  parent->registerTag(TagInfo::universalTag(tag2));
422  EXPECT_TRUE(Utils::HasTag(*parent, tag1));
423  EXPECT_TRUE(Utils::HasTag(*parent, tag2));
424 
425  // inserting two children
426  auto child_t1_a = new SessionItem;
427  auto child_t1_b = new SessionItem;
428  auto child_t2_a = new SessionItem;
429  auto child_t2_b = new SessionItem;
430  auto child_t2_c = new SessionItem;
431  parent->insertItem(child_t2_a, {tag2, -1});
432  parent->insertItem(child_t2_c, {tag2, -1});
433 
434  parent->insertItem(child_t1_a, {tag1, -1});
435  parent->insertItem(child_t1_b, {tag1, -1});
436 
437  parent->insertItem(child_t2_b, {tag2, 1}); // between child_t2_a and child_t2_c
438 
439  // testing item access via non-tag interface
440  std::vector<SessionItem*> expected = {child_t1_a, child_t1_b, child_t2_a, child_t2_b,
441  child_t2_c};
442  EXPECT_EQ(parent->children(), expected);
443  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child_t1_a), 0);
444  EXPECT_EQ(Utils::IndexOfChild(parent.get(), child_t2_c), 4);
445 
446  // testing single item access via tag interface
447  EXPECT_EQ(parent->getItem(tag1), child_t1_a);
448  EXPECT_EQ(parent->getItem(tag1, 0), child_t1_a);
449  EXPECT_EQ(parent->getItem(tag1, 1), child_t1_b);
450  EXPECT_EQ(parent->getItem(tag2, 0), child_t2_a);
451  EXPECT_EQ(parent->getItem(tag2, 1), child_t2_b);
452  EXPECT_EQ(parent->getItem(tag2, 2), child_t2_c);
453  EXPECT_EQ(parent->getItem(tag2, 3), nullptr); // no items with such row
454 
455  // access to multiple items via tags interface
456  expected = {child_t1_a, child_t1_b};
457  EXPECT_EQ(parent->getItems(tag1), expected);
458  expected = {child_t2_a, child_t2_b, child_t2_c};
459  EXPECT_EQ(parent->getItems(tag2), expected);
460 
461  // removing item from the middle of tag2
462  delete parent->takeItem({tag2, 1});
463  expected = {child_t1_a, child_t1_b};
464  EXPECT_EQ(parent->getItems(tag1), expected);
465  expected = {child_t2_a, child_t2_c};
466  EXPECT_EQ(parent->getItems(tag2), expected);
467 }
468 
469 //! Inserting and removing items when tag has limits.
470 
471 TEST_F(SessionItemTest, tagWithLimits)
472 {
473  const std::string tag1 = "tag1";
474  const int maxItems = 3;
475  auto parent = std::make_unique<SessionItem>();
476  parent->registerTag(TagInfo(tag1, 0, maxItems, std::vector<std::string>() = {}));
477 
478  // placing maximu allowed number of items
479  std::vector<SessionItem*> expected;
480  for (int i = 0; i < maxItems; ++i) {
481  auto child = new SessionItem;
482  expected.push_back(child);
483  EXPECT_TRUE(parent->insertItem(child, {tag1, -1}));
484  }
485  EXPECT_EQ(parent->getItems(tag1), expected);
486 
487  // no room for extra item
488  auto extra = new SessionItem;
489  EXPECT_FALSE(parent->insertItem(extra, {tag1, -1}));
490 
491  // removing first element
492  delete parent->takeItem({tag1, 0});
493  expected.erase(expected.begin());
494  EXPECT_EQ(parent->getItems(tag1), expected);
495 
496  // adding extra item
497  parent->insertItem(extra, {tag1, -1});
498  expected.push_back(extra);
499  EXPECT_EQ(parent->getItems(tag1), expected);
500 }
501 
502 //! Inserting and removing items when tag has limits.
503 
504 TEST_F(SessionItemTest, tagModelTypes)
505 {
506  const std::string tag1 = "tag1";
507  const std::string tag2 = "tag2";
508  const std::string modelType1 = "ModelType1";
509  const std::string modelType2 = "ModelType2";
510  const std::string modelType3 = "ModelType3";
511  const std::string modelType4 = "ModelType4";
512 
513  auto parent = std::make_unique<SessionItem>();
514  parent->registerTag(
515  TagInfo(tag1, 0, -1, std::vector<std::string>() = {modelType1, modelType2}));
516  parent->registerTag(TagInfo(tag2, 0, -1, std::vector<std::string>() = {modelType3}));
517 
518  auto item1 = new SessionItem(modelType1);
519  auto item2 = new SessionItem(modelType2);
520  auto item3 = new SessionItem(modelType3);
521 
522  // attempt to add item not intended for tag
523  EXPECT_FALSE(parent->insertItem(item1, {tag2, -1}));
524  EXPECT_FALSE(parent->insertItem(item3, {tag1, -1}));
525 
526  // normal insert to appropriate tag
527  parent->insertItem(item3, {tag2, -1});
528  parent->insertItem(item1, {tag1, -1});
529  parent->insertItem(item2, {tag1, -1});
530 
531  std::vector<SessionItem*> expected = {item1, item2};
532  EXPECT_EQ(parent->getItems(tag1), expected);
533  expected = {item3};
534  EXPECT_EQ(parent->getItems(tag2), expected);
535 }
536 
537 //! Testing method ::tag.
538 
540 {
541  const std::string tag1 = "tag1";
542  const std::string tag2 = "tag2";
543 
544  // creating parent with one tag
545  auto parent = std::make_unique<SessionItem>();
546  parent->registerTag(TagInfo::universalTag(tag1));
547  parent->registerTag(TagInfo::universalTag(tag2));
548 
549  // inserting two children
550  auto child_t1_a = new SessionItem;
551  auto child_t1_b = new SessionItem;
552  auto child_t2_a = new SessionItem;
553  auto child_t2_b = new SessionItem;
554  auto child_t2_c = new SessionItem;
555  parent->insertItem(child_t2_a, {tag2, -1});
556  parent->insertItem(child_t2_c, {tag2, -1});
557  parent->insertItem(child_t1_a, {tag1, -1});
558  parent->insertItem(child_t1_b, {tag1, -1});
559  parent->insertItem(child_t2_b, {tag2, 1}); // between child_t2_a and child_t2_c
560 
561  EXPECT_EQ(child_t1_a->tagRow().tag, "tag1");
562  EXPECT_EQ(child_t1_b->tagRow().tag, "tag1");
563  EXPECT_EQ(child_t2_a->tagRow().tag, "tag2");
564  EXPECT_EQ(child_t2_b->tagRow().tag, "tag2");
565  EXPECT_EQ(child_t2_c->tagRow().tag, "tag2");
566 
567  SessionItem parentless_item;
568  EXPECT_EQ(parentless_item.tagRow().tag, "");
569 }
570 
571 //! Checks row of item in its tag
572 
574 {
575  const std::string tag1 = "tag1";
576  const std::string tag2 = "tag2";
577 
578  // creating parent with one tag
579  auto parent = std::make_unique<SessionItem>();
580  parent->registerTag(TagInfo::universalTag(tag1));
581  parent->registerTag(TagInfo::universalTag(tag2));
582 
583  // inserting two children
584  auto child_t1_a = new SessionItem;
585  auto child_t1_b = new SessionItem;
586  auto child_t2_a = new SessionItem;
587  auto child_t2_b = new SessionItem;
588  auto child_t2_c = new SessionItem;
589  parent->insertItem(child_t2_a, {tag2, -1}); // 0
590  parent->insertItem(child_t2_c, {tag2, -1}); // 2
591  parent->insertItem(child_t1_a, {tag1, -1}); // 0
592  parent->insertItem(child_t1_b, {tag1, -1}); // 1
593  parent->insertItem(child_t2_b, {tag2, 1}); // 1 between child_t2_a and child_t2_c
594 
595  EXPECT_EQ(child_t1_a->tagRow().row, 0);
596  EXPECT_EQ(child_t1_b->tagRow().row, 1);
597  EXPECT_EQ(child_t2_a->tagRow().row, 0);
598  EXPECT_EQ(child_t2_b->tagRow().row, 1);
599  EXPECT_EQ(child_t2_c->tagRow().row, 2);
600 
601  EXPECT_EQ(child_t1_a->tagRow().tag, "tag1");
602  EXPECT_EQ(child_t1_b->tagRow().tag, "tag1");
603  EXPECT_EQ(child_t2_a->tagRow().tag, "tag2");
604  EXPECT_EQ(child_t2_b->tagRow().tag, "tag2");
605  EXPECT_EQ(child_t2_c->tagRow().tag, "tag2");
606 }
607 
608 //! Checks row of item in its tag
609 
610 TEST_F(SessionItemTest, tagRowOfItem)
611 {
612  const std::string tag1 = "tag1";
613  const std::string tag2 = "tag2";
614 
615  // creating parent with one tag
616  auto parent = std::make_unique<SessionItem>();
617  parent->registerTag(TagInfo::universalTag(tag1));
618  parent->registerTag(TagInfo::universalTag(tag2));
619 
620  // inserting two children
621  auto child_t1_a = new SessionItem;
622  auto child_t1_b = new SessionItem;
623  auto child_t2_a = new SessionItem;
624  auto child_t2_b = new SessionItem;
625  auto child_t2_c = new SessionItem;
626  parent->insertItem(child_t2_a, {tag2, -1}); // 0
627  parent->insertItem(child_t2_c, {tag2, -1}); // 2
628  parent->insertItem(child_t1_a, {tag1, -1}); // 0
629  parent->insertItem(child_t1_b, {tag1, -1}); // 1
630  parent->insertItem(child_t2_b, {tag2, 1}); // 1 between child_t2_a and child_t2_c
631 
632  EXPECT_EQ(parent->tagRowOfItem(child_t1_a).row, 0);
633  EXPECT_EQ(parent->tagRowOfItem(child_t1_b).row, 1);
634  EXPECT_EQ(parent->tagRowOfItem(child_t2_a).row, 0);
635  EXPECT_EQ(parent->tagRowOfItem(child_t2_b).row, 1);
636  EXPECT_EQ(parent->tagRowOfItem(child_t2_c).row, 2);
637 
638  EXPECT_EQ(parent->tagRowOfItem(child_t1_a).tag, "tag1");
639  EXPECT_EQ(parent->tagRowOfItem(child_t1_b).tag, "tag1");
640  EXPECT_EQ(parent->tagRowOfItem(child_t2_a).tag, "tag2");
641  EXPECT_EQ(parent->tagRowOfItem(child_t2_b).tag, "tag2");
642  EXPECT_EQ(parent->tagRowOfItem(child_t2_c).tag, "tag2");
643 }
644 
645 //! Checks item appearance (enabled/disabled and editable/readonly).
646 
648 {
649  SessionItem item("Model");
650 
651  // there shouldn't be any data
652  auto variant = item.data<QVariant>(ItemDataRole::APPEARANCE);
653  EXPECT_FALSE(variant.isValid());
654 
655  // default status
656  EXPECT_TRUE(item.isEnabled());
657  EXPECT_TRUE(item.isEditable());
658 
659  // disabling item
660  item.setEnabled(false);
661  EXPECT_FALSE(item.isEnabled());
662  EXPECT_TRUE(item.isEditable());
663 
664  // data should be there now
665  variant = item.data<QVariant>(ItemDataRole::APPEARANCE);
666  EXPECT_TRUE(variant.isValid());
667 
668  // making it readonly
669  item.setEditable(false);
670  EXPECT_FALSE(item.isEnabled());
671  EXPECT_FALSE(item.isEditable());
672 }
673 
674 //! Checks item tooltip.
675 
677 {
678  SessionItem item("Model");
679 
680  EXPECT_EQ(item.toolTip(), "");
681  EXPECT_FALSE(item.hasData(ItemDataRole::TOOLTIP));
682 
683  EXPECT_EQ(item.setToolTip("abc"), &item);
684  EXPECT_TRUE(item.hasData(ItemDataRole::TOOLTIP));
685  EXPECT_EQ(item.toolTip(), "abc");
686 }
687 
688 //! Checks item's editor type.
689 
691 {
692  SessionItem item("Model");
693 
694  EXPECT_EQ(item.editorType(), "");
695  EXPECT_FALSE(item.hasData(ItemDataRole::EDITORTYPE));
696 
697  EXPECT_EQ(item.setEditorType("abc"), &item);
698  EXPECT_TRUE(item.hasData(ItemDataRole::EDITORTYPE));
699  EXPECT_EQ(item.editorType(), "abc");
700 }
701 
703 {
704  const std::string tag1 = "tag1";
705  const std::string tag2 = "tag2";
706 
707  // creating parent with one tag
708  auto parent = std::make_unique<SessionItem>();
709  parent->registerTag(TagInfo::universalTag(tag1));
710  parent->registerTag(TagInfo::universalTag(tag2));
711 
712  // inserting two children
713  auto child_t1_a = new SessionItem;
714  auto child_t2_a = new SessionItem;
715  auto child_t2_b = new SessionItem;
716  parent->insertItem(child_t1_a, {tag1, -1});
717  parent->insertItem(child_t2_a, {tag2, -1});
718  parent->insertItem(child_t2_b, {tag2, -1});
719 
720  EXPECT_EQ(parent->itemCount(tag1), 1);
721  EXPECT_EQ(parent->itemCount(tag2), 2);
722 }
Provides registration of SessionItem pointers and their unique identifiers in global memory pool.
Definition: itempool.h:29
std::vector< int > roles() const
std::string defaultTag() const
Returns the name of the default tag.
The main object representing an editable/displayable/serializable entity.
Definition: sessionitem.h:38
SessionItemTags * itemTags()
Returns pointer to internal collection of tag-registered items (non-const version).
std::string identifier() const
Returns unique identifier.
Definition: sessionitem.cpp:87
SessionItem * setEditable(bool value)
Sets editable flag to given value (fluent interface).
SessionItem * setEnabled(bool value)
Sets enabled flag to given value (fluent interface).
SessionItem * setToolTip(const std::string &tooltip)
Sets item tooltip (fluent interface).
bool hasData(int role=ItemDataRole::DATA) const
Returns true if item has data on board with given role.
std::string editorType() const
Returns editor type.
bool isEnabled() const
Returns true if this item has enabled flag set.
void registerTag(const TagInfo &tagInfo, bool set_as_default=false)
Registers tag to hold items under given name.
bool setData(const T &value, int role=ItemDataRole::DATA, bool direct=false)
Sets data for a given role.
Definition: sessionitem.h:141
std::string toolTip() const
Returns item tooltip, if exists.
bool isEditable() const
Returns true if this item has editable flag set.
SessionItem * setEditorType(const std::string &editor_type)
Sets editor type (fluent interface).
SessionItem * parent() const
Returns parent item. Will return nullptr if item doesn't have a parent.
SessionModel * model() const
Returns the model to which given item belongs to.
int childrenCount() const
Returns total number of children in all tags.
T data(int role=ItemDataRole::DATA) const
Returns data of given type T for given role.
Definition: sessionitem.h:148
std::vector< SessionItem * > children() const
Returns vector of children formed from all chidlren from all tags.
SessionItemData * itemData()
Returns pointer to item's data container (non-const version).
virtual std::string displayName() const
Returns display name.
Definition: sessionitem.cpp:94
bool insertItem(SessionItem *item, const TagRow &tagrow)
Insert item into given tag under the given row.
TagRow tagRow() const
Returns TagRow of this item under which it is accessible through its parent.
virtual SessionItem * setDisplayName(const std::string &name)
Sets display name (fluent interface).
model_type modelType() const
Returns item's model type.
Definition: sessionitem.cpp:80
Holds info about single tag for SessionItem.
Definition: taginfo.h:28
static TagInfo universalTag(std::string name, std::vector< std::string > modelTypes={})
Constructs universal tag intended for unlimited amount of various items.
Definition: taginfo.cpp:34
static TagRow append(const std::string &tag_name={})
Returns TagRow corresponding to the append to tag_name.
Definition: tagrow.cpp:36
std::string tag
Definition: tagrow.h:27
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
const model_type BaseType
Definition: mvvm_types.h:45
const std::string double_type_name
const std::string int_type_name
const int TOOLTIP
tooltip for item's data
Definition: mvvm_types.h:34
const int EDITORTYPE
type of custom editor for the data role
Definition: mvvm_types.h:35
const int DATA
main data role
Definition: mvvm_types.h:30
const int APPEARANCE
appearance flag
Definition: mvvm_types.h:32
const int LIMITS
possibly limits on item's data
Definition: mvvm_types.h:33
const int DISPLAY
display name
Definition: mvvm_types.h:31
const int IDENTIFIER
unique identifier
Definition: mvvm_types.h:29
MVVM_MODEL_EXPORT int IndexOfChild(const SessionItem *parent, const SessionItem *child)
Returns index in children array corresponding to given child.
Definition: itemutils.cpp:81
MVVM_MODEL_EXPORT bool HasTag(const SessionItem &item, const std::string &tag)
Returns true if given item has registered tag.
Definition: itemutils.cpp:86
materialitems.h Collection of materials to populate MaterialModel.
Defines class CLASS?
TEST_F(SessionItemTest, initialState)
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?