TreeWidget.cpp
Go to the documentation of this file.
1 #include "TreeWidget.h"
2 
3 #include <QHeaderView>
4 #include <QMenu>
5 
6 #include <SimoxUtility/algorithm/string.h>
7 
8 #include <RobotAPI/interface/armem/actions.h>
11 
13 {
14 
16  {
17  initBuilders();
18  initWidget();
19  }
20 
21  void
22  TreeWidget::initWidget()
23  {
24  clear();
25  QStringList columns;
26  columns.insert(int(Columns::KEY), "Key");
27  columns.insert(int(Columns::SIZE), "#");
28  columns.insert(int(Columns::TYPE), "Type");
29  columns.insert(int(Columns::LEVEL), "Level");
30  columns.insert(int(Columns::ID), "Memory ID");
31  setColumnCount(columns.size());
32  setHeaderLabels(columns);
33 
34  header()->setMinimumSectionSize(25);
35  header()->resizeSection(int(Columns::KEY), 250);
36  header()->resizeSection(int(Columns::SIZE), 40);
37  header()->setTextElideMode(Qt::TextElideMode::ElideRight);
38 
39 
40  connect(this, &This::updated, this, &This::handleSelection);
41  connect(this, &QTreeWidget::currentItemChanged, this, &This::handleSelection);
42 
43  connect(this, &This::memorySelected, this, &This::itemSelected);
44  connect(this, &This::coreSegmentSelected, this, &This::itemSelected);
45  connect(this, &This::providerSegmentSelected, this, &This::itemSelected);
46  connect(this, &This::entitySelected, this, &This::itemSelected);
47  connect(this, &This::snapshotSelected, this, &This::itemSelected);
48  connect(this, &This::instanceSelected, this, &This::itemSelected);
49 
50  setContextMenuPolicy(Qt::CustomContextMenu);
51  connect(
52  this, &QTreeWidget::customContextMenuRequested, this, &This::prepareTreeContextMenu);
53  }
54 
55  void
56  TreeWidget::initBuilders()
57  {
58  memoryBuilder.setExpand(true);
59  memoryBuilder.setMakeItemFn([this](const std::string& name, const wm::Memory* memory)
60  { return makeItem(name, *memory); });
61  memoryBuilder.setUpdateItemFn(
62  [this](const std::string&, const wm::Memory* memory, QTreeWidgetItem* memoryItem)
63  {
64  updateContainerItem(*memory, memoryItem);
65  if (memoryItem)
66  {
67  updateChildren(*memory, memoryItem);
68  }
69  return true;
70  });
71 
72  auto nameFn = [](const auto& element) { return element.name(); };
73 
74  coreSegmentBuilder.setExpand(true);
75  coreSegmentBuilder.setNameFn(nameFn, int(Columns::KEY));
76  coreSegmentBuilder.setMakeItemFn([this](const wm::CoreSegment& coreSeg)
77  { return makeItem(coreSeg.name(), coreSeg); });
78  coreSegmentBuilder.setUpdateItemFn(
79  [this](const wm::CoreSegment& coreSeg, QTreeWidgetItem* coreSegItem)
80  {
81  updateContainerItem(coreSeg, coreSegItem);
82  updateChildren(coreSeg, coreSegItem);
83  return true;
84  });
85 
86  provSegmentBuilder.setExpand(true);
87  provSegmentBuilder.setNameFn(nameFn, int(Columns::KEY));
88  provSegmentBuilder.setMakeItemFn([this](const wm::ProviderSegment& provSeg)
89  { return makeItem(provSeg.name(), provSeg); });
90  provSegmentBuilder.setUpdateItemFn(
91  [this](const wm::ProviderSegment& provSeg, QTreeWidgetItem* provSegItem)
92  {
93  updateContainerItem(provSeg, provSegItem);
94  updateChildren(provSeg, provSegItem);
95  return true;
96  });
97 
98  // entityBuilder.setExpand(true);
99  entityBuilder.setNameFn(nameFn, int(Columns::KEY));
100  entityBuilder.setMakeItemFn([this](const wm::Entity& entity)
101  { return makeItem(entity.name(), entity); });
102  entityBuilder.setUpdateItemFn(
103  [this](const wm::Entity& entity, QTreeWidgetItem* entityItem)
104  {
105  updateContainerItem(entity, entityItem);
106  updateChildren(entity, entityItem);
107  return true;
108  });
109 
110  snapshotBuilder.setMakeItemFn(
111  [this](const wm::EntitySnapshot& snapshot)
112  {
113  QTreeWidgetItem* item = makeItem(toDateTimeMilliSeconds(snapshot.time()), snapshot);
114  item->setData(
115  int(Columns::KEY),
116  Qt::ItemDataRole::UserRole,
117  QVariant(static_cast<qlonglong>(snapshot.time().toMicroSecondsSinceEpoch())));
118  return item;
119  });
120  snapshotBuilder.setCompareFn(
121  [](const wm::EntitySnapshot& snapshot, QTreeWidgetItem* item)
122  {
124  static_cast<qlonglong>(snapshot.time().toMicroSecondsSinceEpoch()),
125  item->data(int(Columns::KEY), Qt::ItemDataRole::UserRole).toLongLong());
126  });
127  snapshotBuilder.setUpdateItemFn(
128  [this](const wm::EntitySnapshot& snapshot, QTreeWidgetItem* snapshotItem)
129  {
130  updateContainerItem(snapshot, snapshotItem);
131  updateChildren(snapshot, snapshotItem);
132  return true;
133  });
134 
135  instanceBuilder.setMakeItemFn(
136  [this](const wm::EntityInstance& instance)
137  {
138  QTreeWidgetItem* item = makeItem("", instance);
139  return item;
140  });
141  instanceBuilder.setCompareFn(
142  [](const wm::EntityInstance& lhs, QTreeWidgetItem* rhsItem)
143  { return armarx::detail::compare(lhs.index(), rhsItem->text(0).toInt()); });
144  instanceBuilder.setUpdateItemFn(
145  [this](const wm::EntityInstance& instance, QTreeWidgetItem* instanceItem)
146  {
147  updateItemItem(instance, instanceItem);
148  updateChildren(instance, instanceItem);
149  return true;
150  });
151  }
152 
153  void
155  {
156  // Removing elements during the update can create unwanted signals triggering selection handling.
157  handleSelections = false;
158  updateChildren(memory, this);
159  handleSelections = true;
160  emit updated();
161  }
162 
163  void
164  TreeWidget::update(const std::map<std::string, const armem::wm::Memory*>& memories)
165  {
166  handleSelections = false;
167  updateChildren(memories, this);
168  handleSelections = true;
169  emit updated();
170  }
171 
172  std::optional<MemoryID>
174  {
175  return _selectedID;
176  }
177 
178  void
179  TreeWidget::handleSelection()
180  {
181  if (!handleSelections)
182  {
183  return;
184  }
185  QTreeWidgetItem* item = this->currentItem();
186  if (!item)
187  {
188  return;
189  }
190 
191  MemoryID id(item->data(int(Columns::ID), Qt::UserRole).toString().toStdString());
192 
193  // Has the selection changed due to an update? If yes, signal this.
194  if (!_selectedID || id != *_selectedID)
195  {
196  _selectedID = id;
197 
198  const std::string levelName =
199  item->data(int(Columns::LEVEL), Qt::UserRole).toString().toStdString();
200  if (levelName == wm::Memory::getLevelName())
201  {
202  emit memorySelected(*_selectedID);
203  }
204  else if (levelName == wm::CoreSegment::getLevelName())
205  {
206  emit coreSegmentSelected(*_selectedID);
207  }
208  else if (levelName == wm::ProviderSegment::getLevelName())
209  {
210  emit providerSegmentSelected(*_selectedID);
211  }
212  else if (levelName == wm::Entity::getLevelName())
213  {
214  emit entitySelected(*_selectedID);
215  }
216  else if (levelName == wm::EntitySnapshot::getLevelName())
217  {
218  emit snapshotSelected(*_selectedID);
219  }
220  else if (levelName == wm::EntityInstance::getLevelName())
221  {
222  emit instanceSelected(*_selectedID);
223  }
224  }
225 
226  // Either selection or its contents have changed.
227  emit selectedItemChanged(*_selectedID);
228  }
229 
230  template <class ContainerT>
231  static auto
232  makeIteratorFn(const ContainerT& container)
233  {
234  return [&container](auto&& elementFn) { container.forEachChild(elementFn); };
235  }
236 
237  void
238  TreeWidget::updateChildren(const armem::wm::Memory& memory, QTreeWidget* tree)
239  {
240  updateChildren(std::map<std::string, const armem::wm::Memory*>{{memory.name(), &memory}},
241  tree);
242  }
243 
244  void
245  TreeWidget::updateChildren(const std::map<std::string, const armem::wm::Memory*>& memories,
246  QTreeWidget* tree)
247  {
248  memoryBuilder.updateTree(tree, memories);
249  }
250 
251  void
252  TreeWidget::updateChildren(const armem::wm::Memory& memory, QTreeWidgetItem* memoryItem)
253  {
254  coreSegmentBuilder.updateTreeWithIterator(memoryItem, makeIteratorFn(memory));
255  }
256 
257  void
258  TreeWidget::updateChildren(const armem::wm::CoreSegment& coreSeg, QTreeWidgetItem* coreSegItem)
259  {
260  provSegmentBuilder.updateTreeWithIterator(coreSegItem, makeIteratorFn(coreSeg));
261  }
262 
263  void
264  TreeWidget::updateChildren(const armem::wm::ProviderSegment& provSeg,
265  QTreeWidgetItem* provSegItem)
266  {
267  entityBuilder.updateTreeWithIterator(provSegItem, makeIteratorFn(provSeg));
268  }
269 
270  void
271  TreeWidget::updateChildren(const armem::wm::Entity& entity, QTreeWidgetItem* entityItem)
272  {
273  snapshotBuilder.updateTreeWithIterator(entityItem, makeIteratorFn(entity));
274  }
275 
276  void
277  TreeWidget::updateChildren(const armem::wm::EntitySnapshot& snapshot,
278  QTreeWidgetItem* snapshotItem)
279  {
280  instanceBuilder.updateTreeWithIterator(snapshotItem, makeIteratorFn(snapshot));
281  }
282 
283  void
284  TreeWidget::updateChildren(const armem::wm::EntityInstance& data, QTreeWidgetItem* dataItem)
285  {
286  (void)data, (void)dataItem;
287  }
288 
289  void
290  TreeWidget::prepareTreeContextMenu(const QPoint& pos)
291  {
292  const QTreeWidgetItem* item = this->itemAt(pos);
293  if (item == nullptr)
294  {
295  return;
296  }
297 
298  MemoryID memoryID(item->data(int(Columns::ID), Qt::UserRole).toString().toStdString());
299  emit actionsMenuRequested(memoryID, this, mapToGlobal(pos), nullptr);
300  }
301 
302  template <class MemoryItemT>
303  QTreeWidgetItem*
304  TreeWidget::makeItem(const std::string& key, const MemoryItemT& memoryItem)
305  {
306  (void)key;
307  return makeItem(memoryItem.getKeyString(), MemoryItemT::getLevelName(), memoryItem.id());
308  }
309 
310  QTreeWidgetItem*
311  TreeWidget::makeItem(const std::string& key, const std::string& levelName, const MemoryID& id)
312  {
313  QStringList columns;
314  columns.insert(int(Columns::KEY), QString::fromStdString(key));
315  columns.insert(int(Columns::SIZE), "");
316  columns.insert(int(Columns::TYPE), "");
317  columns.insert(int(Columns::LEVEL),
318  QString::fromStdString(simox::alg::capitalize_words(levelName)));
319  columns.insert(int(Columns::ID), QString::fromStdString(id.str()));
320 
321  QTreeWidgetItem* item = new QTreeWidgetItem(columns);
322  item->setData(int(Columns::LEVEL), Qt::UserRole, QString::fromStdString(levelName));
323  item->setData(int(Columns::ID), Qt::UserRole, QString::fromStdString(id.str()));
324  item->setTextAlignment(int(Columns::SIZE), Qt::AlignRight);
325  return item;
326  }
327 
328  void
329  TreeWidget::updateItemItem(const armem::base::detail::MemoryItem& level, QTreeWidgetItem* item)
330  {
331  (void)level, (void)item;
332  }
333 
334  template <class ContainerT>
335  void
336  TreeWidget::updateContainerItem(const ContainerT& container, QTreeWidgetItem* item)
337  {
338  updateItemItem(container, item);
339  item->setText(int(Columns::SIZE), QString::number(container.size()));
340 
341  // Does not work
342  if constexpr (std::is_base_of_v<base::detail::AronTyped, ContainerT>)
343  {
344  const base::detail::AronTyped& cast =
345  static_cast<const base::detail::AronTyped&>(container);
346  std::string typeName;
347  if (cast.aronType())
348  {
349  typeName = cast.aronType()->getFullName();
350  typeName = instance::sanitizeTypeName(typeName);
351  }
352  else
353  {
354  typeName = "(no Aron type)";
355  }
356  item->setText(int(Columns::TYPE), QString::fromStdString(typeName));
357  }
358  }
359 
360 } // namespace armarx::armem::gui::memory
sanitize_typename.h
armarx::armem::gui::memory
Definition: GroupBox.cpp:10
armarx::armem::server::wm::EntityInstance
armem::wm::EntityInstance EntityInstance
Definition: forward_declarations.h:65
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:43
armarx::armem::gui::instance::sanitizeTypeName
std::string sanitizeTypeName(const std::string &typeName)
Definition: sanitize_typename.cpp:31
armarx::conversions::cast
CvT cast(const auto &pt)
Definition: opencv.h:33
armarx::armem::gui::memory::TreeWidget::providerSegmentSelected
void providerSegmentSelected(const MemoryID &id)
armarx::armem::gui::memory::TreeWidget::entitySelected
void entitySelected(const MemoryID &id)
armarx::armem::base::EntityInstanceBase< EntityInstanceDataPtr, EntityInstanceMetadata >::getLevelName
static std::string getLevelName()
Definition: EntityInstanceBase.h:175
armarx::armem::base::MemoryBase< CoreSegment, Memory >::getLevelName
static std::string getLevelName()
Definition: MemoryBase.h:398
armarx::memory
Brief description of class memory.
Definition: memory.h:38
Object.h
armarx::armem::gui::memory::TreeWidget::instanceSelected
void instanceSelected(const MemoryID &id)
armarx::armem::base::ProviderSegmentBase< Entity, ProviderSegment >::getLevelName
static std::string getLevelName()
Definition: ProviderSegmentBase.h:353
armarx::armem::server::wm::Memory
Definition: memory_definitions.h:122
armarx::armem::gui::memory::TreeWidget::updated
void updated()
Tree contents have changed.
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::armem::toDateTimeMilliSeconds
std::string toDateTimeMilliSeconds(const Time &time, int decimals=6)
Returns timeas e.g.
Definition: Time.cpp:35
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::armem::wm::Memory
Client-side working memory.
Definition: memory_definitions.h:133
armarx::armem::gui::memory::TreeWidget::snapshotSelected
void snapshotSelected(const MemoryID &id)
armarx::armem::gui::memory::TreeWidget::actionsMenuRequested
void actionsMenuRequested(const MemoryID &memoryID, QWidget *parent, const QPoint &pos, QMenu *menu)
armarx::armem::gui::memory::TreeWidget::selectedID
std::optional< MemoryID > selectedID() const
Definition: TreeWidget.cpp:173
armarx::detail::compare
int compare(const T &lhs, const T &rhs)
Definition: TreeWidgetBuilder.h:321
armarx::armem::base::EntitySnapshotBase< EntityInstance, EntitySnapshot >::getLevelName
static std::string getLevelName()
Definition: EntitySnapshotBase.h:328
armarx::armem::gui::memory::TreeWidget::memorySelected
void memorySelected(const MemoryID &id)
TreeWidget.h
armarx::armem::server::wm::EntitySnapshot
armem::wm::EntitySnapshot EntitySnapshot
Definition: forward_declarations.h:66
armarx::armem::index::memoryID
const MemoryID memoryID
Definition: memory_ids.cpp:28
armarx::armem::gui::memory::TreeWidget::selectedItemChanged
void selectedItemChanged(const MemoryID &id)
The selected item or its contents have changed.
armarx::armem::gui::memory::TreeWidget::coreSegmentSelected
void coreSegmentSelected(const MemoryID &id)
armarx::armem::gui::memory::TreeWidget::TreeWidget
TreeWidget()
Definition: TreeWidget.cpp:15
armarx::armem::base::CoreSegmentBase< ProviderSegment, CoreSegment >::getLevelName
static std::string getLevelName()
Definition: CoreSegmentBase.h:404
armarx::armem::base::EntityBase< EntitySnapshot, Entity >::getLevelName
static std::string getLevelName()
Definition: EntityBase.h:690
armarx::armem::gui::memory::TreeWidget::update
void update(const armem::wm::Memory &memory)
Definition: TreeWidget.cpp:154
armarx::armem::gui::memory::TreeWidget::itemSelected
void itemSelected(const MemoryID &id)
armarx::human::MemoryID
const armem::MemoryID MemoryID
Definition: memory_ids.cpp:28