diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp index 754e95e7652a3d3c248605b2d3a6a0c7f4f44b7b..35be06032527f3d35d3b50468168842b82c8ab72 100644 --- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp +++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp @@ -77,6 +77,7 @@ namespace armarx::armem::gui connect(memoryGroup->tree(), &armem::gui::MemoryTreeWidget::updated, this, &This::memoryTreeUpdated); connect(instanceGroup, &armem::gui::InstanceGroupBox::viewUpdated, this, &This::instanceTreeUpdated); + connect(instanceGroup->view, &armem::gui::InstanceView::memoryIdResolutionRequested, this, &This::resolveMemoryID); } void MemoryViewer::setLogTag(const std::string& tag) @@ -126,6 +127,27 @@ namespace armarx::armem::gui emit disconnected(); } + const armem::wm::Memory* MemoryViewer::getSingleMemoryData(const std::string& memoryName) + { + auto it = memoryData.find(memoryName); + if (it == memoryData.end()) + { + std::stringstream ss; + ss << "Memory name '" << memoryName << "' is unknown. Known are: " + << simox::alg::get_keys(memoryData); + statusLabel->setText(QString::fromStdString(ss.str())); + return nullptr; + } + else if (not it->second.has_value()) + { + return nullptr; + } + else + { + return &it->second.value(); + } + } + void MemoryViewer::store() { TIMING_START(MemoryStore); @@ -227,17 +249,7 @@ namespace armarx::armem::gui void MemoryViewer::updateInstanceTree(const armem::MemoryID& selectedID) { - if (memoryData.find(selectedID.memoryName) == memoryData.end()) - { - std::stringstream ss; - ss << "Memory name '" << selectedID.memoryName << "' is unknown. Known are: " - << simox::alg::get_keys(memoryData); - statusLabel->setText(QString::fromStdString(ss.str())); - return; - } - - const std::optional<armem::wm::Memory>& data = memoryData.at(selectedID.memoryName); - + const armem::wm::Memory* data = getSingleMemoryData(selectedID.memoryName); if (data) { if (!selectedID.hasEntityName()) @@ -284,6 +296,36 @@ namespace armarx::armem::gui } } + void MemoryViewer::resolveMemoryID(const MemoryID& id) + { + ARMARX_IMPORTANT << "Resolving memory ID: " << id; + + try + { + const wm::Memory* data = getSingleMemoryData(id.memoryName); + if (data) + { + if (id.hasInstanceIndex()) + { + const wm::EntityInstance& instance = data->getEntityInstance(id); + } + else if (id.hasTimestamp()) + { + const wm::EntitySnapshot& snapshot = data->getEntitySnapshot(id); + } + else if (id.hasEntityName()) + { + const wm::Entity& entity = data->getEntity(id); + } + } + } + catch (const armem::error::ArMemError& e) + { + ARMARX_WARNING << e.what(); + statusLabel->setText(e.what()); + } + } + void MemoryViewer::updateMemoryTree() { std::map<std::string, const armem::wm::Memory*> convMap; diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.h b/source/RobotAPI/libraries/armem_gui/MemoryViewer.h index 16a2ddc16453d485a82016629240d0432b984cc1..b184b85960376a2c9ed14c10452ecb70ad548a76 100644 --- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.h +++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.h @@ -65,14 +65,15 @@ namespace armarx::armem::gui public slots: + void updateMemories(); + void updateInstanceTree(const armem::MemoryID& selectedID); + + void resolveMemoryID(const MemoryID& id); + // LTMControlWidget void store(); void exportHere(); - // Other - void updateMemories(); - void updateInstanceTree(const armem::MemoryID& selectedID); - signals: @@ -99,6 +100,8 @@ namespace armarx::armem::gui void onConnect(ManagedIceObject& component); void onDisconnect(ManagedIceObject& component); + const armem::wm::Memory* getSingleMemoryData(const std::string& memoryName); + public: diff --git a/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp b/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp index b33c381970dfe3f3eb0ce0b0b7be9e9599f75f7f..187120df303ada4d116ccc1a2dfbd457619469a6 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp +++ b/source/RobotAPI/libraries/armem_gui/instance/GroupBox.cpp @@ -21,8 +21,8 @@ namespace armarx::armem::gui::instance QHBoxLayout* checkBoxLayout = new QHBoxLayout(); checkBoxLayout->addWidget(useTypeInfoCheckBox); - layout->addLayout(checkBoxLayout); layout->addWidget(view); + layout->addLayout(checkBoxLayout); this->setTitle("Instance View (select an entity instance on the left)"); const int margin = 3; diff --git a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp index 429d2f3603967f64728e59113841b85c862b8d46..90ff5082dbf2944593428d92181272889c471f0a 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp +++ b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.cpp @@ -19,8 +19,12 @@ #include <RobotAPI/libraries/aron/core/navigator/data/complex/NDArray.h> #include <RobotAPI/libraries/aron/core/navigator/type/container/Object.h> +#include <RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h> +#include <RobotAPI/libraries/armem/core/aron_conversions.h> + #include <RobotAPI/libraries/armem_gui/gui_utils.h> #include <RobotAPI/libraries/armem_gui/instance/ImageView.h> +#include <RobotAPI/libraries/armem_gui/instance/sanitize_typename.h> #include <RobotAPI/libraries/armem_gui/instance/serialize_path.h> #include <RobotAPI/libraries/armem_gui/instance/tree_builders/DataTreeBuilder.h> #include <RobotAPI/libraries/armem_gui/instance/tree_builders/TypedDataTreeBuilder.h> @@ -205,15 +209,22 @@ namespace armarx::armem::gui::instance return; } + auto getPath = [item]() + { + QStringList qpath = item->data(int(Columns::KEY), Qt::UserRole).toStringList(); + aron::Path path = deserializePath(qpath); + return path; + }; + QMenu menu(this); + // Type descriptor based actions aron::type::Descriptor type = static_cast<aron::type::Descriptor>(item->data(int(Columns::TYPE), Qt::UserRole).toInt()); switch (type) { case aron::type::Descriptor::eIVTCByteImage: { - QStringList qpath = item->data(int(Columns::KEY), Qt::UserRole).toStringList(); - aron::Path path = deserializePath(qpath); + aron::Path path = getPath(); QAction* viewAction = new QAction("Show image"); menu.addAction(viewAction); @@ -224,10 +235,28 @@ namespace armarx::armem::gui::instance } break; default: - return; + break; } - menu.exec(tree->mapToGlobal(pos)); + // Type name based actions + const std::string typeName = item->text(int(Columns::TYPE)).toStdString(); + if (typeName == instance::sanitizedMemoryIDTypeName) + { + aron::Path path = getPath(); + + QAction* viewAction = new QAction("Resolve Memory ID"); + menu.addAction(viewAction); + connect(viewAction, &QAction::triggered, [this, path]() + { + this->requestMemoryIdResolution(path); + }); + } + + + if (menu.actions().size() > 0) + { + menu.exec(tree->mapToGlobal(pos)); + } } void InstanceView::showImageView(const aron::Path& elementPath) @@ -251,6 +280,49 @@ namespace armarx::armem::gui::instance imageView = std::nullopt; } + void InstanceView::requestMemoryIdResolution(const aron::Path& elementPath) + { + const aron::datanavigator::DictNavigatorPtr& data = currentInstance->data(); + + aron::datanavigator::NavigatorPtr element; + try + { + element = data->navigateAbsolute(elementPath); + } + // This can happen when the underlying entity structure changes (a new entity has been selected). + catch (const aron::error::AronException&) + { + // showErrorMessage(e.what()); + return; + } + catch (const armarx::LocalException&) + { + // showErrorMessage(e.what()); + return; + } + + auto dictElement = std::dynamic_pointer_cast<aron::datanavigator::DictNavigator>(element); + if (!dictElement) + { + return; + } + + MemoryID id; + try + { + arondto::MemoryID dto; + dto.fromAron(dictElement); + armem::fromAron(dto, id); + } + catch (const armarx::aron::error::AronException&) + { + return; + } + + ARMARX_IMPORTANT << "emit memoryIdResolutionRequested(id = " << id << ")"; + emit memoryIdResolutionRequested(id); + } + void InstanceView::updateImageView(const aron::datanavigator::DictNavigatorPtr& data) { using aron::datanavigator::NDArrayNavigator; diff --git a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.h b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.h index 0b0a0ee2655f506fa09f15b99dd0edc149e88470..dea3580b42d787d9da20ea8f0e98b8b20a39e8e1 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/InstanceView.h +++ b/source/RobotAPI/libraries/armem_gui/instance/InstanceView.h @@ -43,14 +43,18 @@ namespace armarx::armem::gui::instance void updated(); void instanceSelected(const MemoryID& id); + void memoryIdResolutionRequested(const MemoryID& id); private slots: void prepareTreeContextMenu(const QPoint& pos); + void showImageView(const aron::Path& elementPath); void removeImageView(); + void requestMemoryIdResolution(const aron::Path& elementPath); + private: diff --git a/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp b/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp index 9db04814561de68c4e7390093a7a7b3659f0219c..d99d2378dcf67dd8e6d8e44a3dca92b8013be85c 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp +++ b/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.cpp @@ -8,12 +8,14 @@ static const std::string MemoryIDTypeName = armarx::armem::arondto::MemoryID::toInitialAronType()->getName(); +const std::string armarx::armem::gui::instance::sanitizedMemoryIDTypeName = "MemoryID"; + std::string armarx::armem::gui::instance::sanitizeTypeName(const std::string& typeName) { if (typeName == MemoryIDTypeName) { - return "MemoryID"; + return sanitizedMemoryIDTypeName; } namespace s = simox::alg; diff --git a/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.h b/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.h index 80c77acf229ecb6d70b55b6ac1c5b951a0cb89bd..09bd9629bbee6f1381e4ab2a8d61777117db9b0c 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.h +++ b/source/RobotAPI/libraries/armem_gui/instance/sanitize_typename.h @@ -6,6 +6,8 @@ namespace armarx::armem::gui::instance { + extern const std::string sanitizedMemoryIDTypeName; + std::string sanitizeTypeName(const std::string& typeName); }