6 #include <SimoxUtility/algorithm/string.h>
9 #include <QDoubleSpinBox>
11 #include <QPushButton>
28 if (!widgetConnections.empty())
31 for (
const auto& conn : widgetConnections)
35 widgetConnections.clear();
38 this->widget = widget;
41 widgetConnections.append(connect(widget, &QTreeWidget::itemExpanded, [
this](QTreeWidgetItem * item)
43 if (item->parent() || this->layers ==
nullptr)
48 std::string
id = item->text(0).toStdString();
49 auto* layer = this->layers->findLayer(this->layerID);
53 if (element !=
nullptr)
55 this->updateLayerElementProperties(item, element->
data);
60 widget->setColumnCount(2);
61 widget->setHeaderLabels({
"Property",
"Value"});
62 widget->setHeaderHidden(
false);
70 if (layerID == this->layerID)
79 this->maxElementCountDefault =
max;
84 if (this->enabled !=
value)
86 this->enabled =
value;
101 this->layers = layers;
103 showMoreItem =
nullptr;
104 maxElementCount = maxElementCountDefault;
114 if (enabled && layers)
116 auto* layer = layers->
findLayer(layerID);
117 if (layer !=
nullptr)
119 updateLayerElements(layer->elements);
125 void LayerInfoTree::clearLayerElements()
130 showMoreItem =
nullptr;
135 void LayerInfoTree::updateLayerElements(
const std::vector<viz::CoinLayerElement>& elements)
141 int index = widget->indexOfTopLevelItem(showMoreItem);
143 delete widget->takeTopLevelItem(
index);
144 showMoreItem =
nullptr;
148 int currentIndex = 0;
151 std::string
const& name = element.data->id;
153 if (maxElementCount >= 0 && currentIndex >= maxElementCount)
160 if (currentIndex >= widget->topLevelItemCount())
163 QTreeWidgetItem* item = insertLayerElementItem(currentIndex, name, element.data);
164 updateLayerElementProperties(item, element.data);
170 QTreeWidgetItem* currentItem = widget->topLevelItem(currentIndex);
174 while (currentItem !=
nullptr && name.c_str() > currentItem->text(0))
177 delete widget->takeTopLevelItem(currentIndex);
178 currentItem = widget->topLevelItem(currentIndex);
181 if (currentItem !=
nullptr && name.c_str() < currentItem->text(0))
184 currentItem = insertLayerElementItem(currentIndex, name, element.data);
185 updateLayerElementProperties(currentItem, element.data);
190 if (currentItem !=
nullptr && name.c_str() == currentItem->text(0))
193 updateLayerElementItem(currentItem, element.data);
194 if (currentItem->isExpanded())
196 updateLayerElementProperties(currentItem, element.data);
205 QTreeWidgetItem* LayerInfoTree::insertLayerElementItem(
206 int index,
const std::string& name,
const viz::data::ElementPtr& element)
208 QTreeWidgetItem* item =
new QTreeWidgetItem(QStringList { name.c_str(), getTypeName(element).c_str() });
211 widget->insertTopLevelItem(
index, item);
215 void LayerInfoTree::updateLayerElementItem(QTreeWidgetItem* item,
const viz::data::ElementPtr& element)
218 item->setText(1, getTypeName(element).c_str());
222 void LayerInfoTree::updateLayerElementProperties(QTreeWidgetItem* item,
const viz::data::ElementPtr& element)
224 bool recursive =
true;
225 updateJsonChildren(item, serializeElement(element), recursive);
229 std::string LayerInfoTree::getTypeName(
const viz::data::ElementPtr& element)
const
231 const std::string typeName = simox::meta::get_type_name(*element);
234 :
"<unknown type '" + typeName +
"'>";
238 nlohmann::json LayerInfoTree::serializeElement(
const viz::data::ElementPtr& element)
const
242 return nlohmann::json(element);
244 catch (
const viz::error::NoSerializerForType&)
246 return nlohmann::json::object();
251 void LayerInfoTree::updateJsonChildren(QTreeWidgetItem* parent,
const nlohmann::json& json,
bool recursive)
255 nlohmann::json jmeta = nlohmann::json::object();
262 if (iItem >= parent->childCount())
264 QTreeWidgetItem* item = addJsonChild(parent, key);
265 updateJsonItem(item, key, j, jmeta, recursive);
269 QTreeWidgetItem* currentItem = parent->child(iItem);
270 updateJsonItem(currentItem, key, j, jmeta, recursive);
274 while (parent->childCount() >
int(json.size()))
276 parent->removeChild(parent->child(parent->childCount() - 1));
279 else if (json.is_object())
281 namespace meta = viz::json::meta;
283 : nlohmann::json::object();
286 for (
auto it : json.items())
289 if (isMetaKey(it.key()))
295 if (jmeta.count(it.key()) > 0 && jmeta.at(it.key()) ==
meta::HIDE)
300 if (iItem >= parent->childCount())
302 QTreeWidgetItem* item = addJsonChild(parent, it.key());
303 updateJsonItem(item, it.key(), it.value(), jmeta, recursive);
308 QTreeWidgetItem* currentItem = parent->child(iItem);
310 while (it.key().c_str() > currentItem->text(0))
313 parent->removeChild(currentItem);
314 currentItem = parent->child(iItem);
317 if (it.key().c_str() < currentItem->text(0))
320 currentItem = addJsonChild(parent, it.key());
321 updateJsonItem(currentItem, it.key(), it.value(), jmeta, recursive);
326 if (it.key().c_str() == currentItem->text(0))
329 updateJsonItem(currentItem, it.key(), it.value(), jmeta, recursive);
338 QTreeWidgetItem* LayerInfoTree::addJsonChild(QTreeWidgetItem* parent,
const std::string& key)
340 QTreeWidgetItem* child =
new QTreeWidgetItem(QStringList { key.c_str(),
"" });
343 parent->addChild(child);
349 void LayerInfoTree::updateJsonItem(
350 QTreeWidgetItem* item,
const std::string& key,
const nlohmann::json&
value,
351 const nlohmann::json& parentMeta,
354 const int columnKey = 0;
357 item->setText(columnKey, key.c_str());
359 updateJsonItemValue(item, key,
value, parentMeta);
364 updateJsonChildren(item,
value, recursive);
369 void LayerInfoTree::updateJsonItemValue(
370 QTreeWidgetItem* item,
const std::string& key,
const nlohmann::json&
value,
371 const nlohmann::json& parentMeta)
373 const int columnValue = 1;
375 if (parentMeta.count(key) > 0)
377 const nlohmann::json& metaValue = parentMeta.at(key);
378 if (metaValue.is_string())
380 const std::string metaString = metaValue.get<std::string>();
383 item->setText(columnValue, getValuePreview(
value).toString());
385 item->setData(0, Qt::CheckStateRole, QVariant());
392 if (QWidget* w = widget->itemWidget(item, columnValue))
394 updateValueWidget(
value, w);
396 else if (QWidget* w = getValueWidget(item,
value); w)
398 widget->setItemWidget(item, columnValue, w);
403 item->setText(columnValue, getValuePreview(
value).
toString());
408 QVariant LayerInfoTree::getValuePreview(
const nlohmann::json& json)
const
410 std::stringstream ss;
414 case nlohmann::json::value_t::null:
415 return QVariant(
"null");
417 case nlohmann::json::value_t::object:
419 std::vector<std::string> keys;
420 for (
auto it : json.items())
422 if (!isMetaKey(it.key()))
424 keys.push_back(it.key());
427 ss <<
"object [" << simox::alg::join(keys,
", ") <<
"]";
428 return QVariant(ss.str().c_str());
431 case nlohmann::json::value_t::array:
432 ss <<
"array of size " << json.size();
433 return QVariant(ss.str().c_str());
435 case nlohmann::json::value_t::string:
436 return QVariant(json.get<std::string>().c_str());
437 case nlohmann::json::value_t::boolean:
438 return QVariant(json.get<
bool>());
439 case nlohmann::json::value_t::number_integer:
440 return QVariant(json.get<
int>());
441 case nlohmann::json::value_t::number_unsigned:
442 return QVariant(json.get<
unsigned int>());
443 case nlohmann::json::value_t::number_float:
444 return QVariant(json.get<
float>());
447 return QVariant(
"n/a");
452 QWidget* LayerInfoTree::getValueWidget(QTreeWidgetItem* item,
const nlohmann::json& json)
const
454 auto setChecked = [item]()
456 item->setCheckState(0, Qt::CheckState::Checked);
461 case nlohmann::json::value_t::string:
464 QLineEdit* w =
new QLineEdit(json.get<std::string>().c_str());
465 connect(w, &QLineEdit::editingFinished,
this, setChecked);
468 case nlohmann::json::value_t::boolean:
470 QCheckBox* w =
new QCheckBox(
"Enabled");
471 w->setChecked(json.get<
bool>());
472 connect(w, &QCheckBox::stateChanged,
this, setChecked);
475 case nlohmann::json::value_t::number_integer:
476 case nlohmann::json::value_t::number_unsigned:
478 QSpinBox* w =
new QSpinBox();
479 w->setMinimum(std::numeric_limits<int>::lowest());
481 w->setValue(json.get<
int>());
482 connect(w, qOverload<int>(&QSpinBox::valueChanged),
this, setChecked);
485 case nlohmann::json::value_t::number_float:
487 QDoubleSpinBox* w =
new QDoubleSpinBox();
488 w->setMinimum(std::numeric_limits<double>::lowest());
490 w->setValue(json.get<
double>());
491 connect(w, qOverload<double>(&QDoubleSpinBox::valueChanged),
this, setChecked);
494 case nlohmann::json::value_t::null:
495 case nlohmann::json::value_t::object:
496 case nlohmann::json::value_t::array:
505 void LayerInfoTree::updateValueWidget(
const nlohmann::json& json, QWidget* widget)
const
509 case nlohmann::json::value_t::string:
511 QLineEdit* w =
dynamic_cast<QLineEdit*
>(widget);
513 w->setText(json.get<std::string>().c_str());
516 case nlohmann::json::value_t::boolean:
518 QCheckBox* w =
dynamic_cast<QCheckBox*
>(widget);
520 w->setChecked(json.get<
bool>());
523 case nlohmann::json::value_t::number_integer:
524 case nlohmann::json::value_t::number_unsigned:
526 QSpinBox* w =
dynamic_cast<QSpinBox*
>(widget);
528 w->setValue(json.get<
int>());
531 case nlohmann::json::value_t::number_float:
533 QDoubleSpinBox* w =
dynamic_cast<QDoubleSpinBox*
>(widget);
535 w->setValue(json.get<
double>());
538 case nlohmann::json::value_t::null:
539 case nlohmann::json::value_t::object:
540 case nlohmann::json::value_t::array:
547 bool LayerInfoTree::isMetaKey(
const std::string& key)
549 return key.substr(0, 2) ==
"__" && key.substr(key.size() - 2) ==
"__";
552 void LayerInfoTree::addShowMoreItem()
554 ARMARX_CHECK_NULL(showMoreItem) <<
"There should not be a showMoreItem when this function is called.";
556 auto* layer = this->layers->
findLayer(this->layerID);
557 if (layer ==
nullptr)
560 <<
"/" << this->layerID.second <<
"' found";
564 std::stringstream ss;
565 ss <<
"Showing " << widget->topLevelItemCount() <<
" of " << layer->elements.size() <<
" elements.";
568 QTreeWidgetItem* item =
new QTreeWidgetItem(QStringList {
"", ss.str().c_str() });
569 widget->addTopLevelItem(item);
571 QPushButton* button =
new QPushButton(
"Show more");
572 widget->setItemWidget(item, 0, button);
574 connect(button, &QPushButton::pressed, [
this, layer]()
576 maxElementCount += maxElementCountDefault;
577 this->updateLayerElements(layer->elements);
580 this->showMoreItem = item;