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