-
Rainer Kartmann authoredRainer Kartmann authored
MemoryViewer.cpp 9.02 KiB
#include "MemoryViewer.h"
#include <RobotAPI/libraries/armem/core/ice_conversions.h>
#include <RobotAPI/libraries/armem_gui/gui_utils.h>
#include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h>
#include <ArmarXCore/core/ManagedIceObject.h>
#include <ArmarXCore/core/time/TimeUtil.h>
#include <ArmarXCore/observers/variant/Variant.h>
#include <SimoxUtility/algorithm/get_map_keys_values.h>
#include <QBoxLayout>
#include <QDialog>
#include <QCheckBox>
#include <QGroupBox>
#include <QLabel>
#include <QLayout>
#include <QSettings>
namespace armarx::armem::gui
{
MemoryViewer::MemoryViewer(
QBoxLayout* updateWidgetLayout,
QGroupBox* _memoryGroupBox, QLayout* memoryGroupBoxParentLayout,
QGroupBox* _instanceGroupBox, QLayout* instanceGroupBoxParentLayout,
QLabel* statusLabel)
{
Logging::setTag("MemoryViewer");
this->statusLabel = statusLabel;
this->statusLabel->clear();
// Update timer
this->updateWidgetLayout = updateWidgetLayout;
updateWidget = new armem::gui::PeriodicUpdateWidget(2.0, 60);
updateWidgetLayout->insertWidget(0, updateWidget);
memoryGroup = new armem::gui::MemoryGroupBox();
armarx::gui::replaceWidget(_memoryGroupBox, memoryGroup, memoryGroupBoxParentLayout);
ARMARX_CHECK_NULL(_memoryGroupBox);
this->instanceGroup = new armem::gui::InstanceGroupBox();
armarx::gui::replaceWidget(_instanceGroupBox, instanceGroup, instanceGroupBoxParentLayout);
this->instanceGroup->setStatusLabel(statusLabel);
ARMARX_CHECK_NULL(_instanceGroupBox);
connect(this, &This::connected, this, &This::updateMemories);
connect(updateWidget, &armem::gui::PeriodicUpdateWidget::update, this, &This::updateMemories);
connect(this, &This::memoryDataChanged, this, &This::updateMemoryTree);
connect(memoryGroup->tree(), &armem::gui::MemoryTreeWidget::selectedItemChanged, this, &This::updateInstanceTree);
connect(memoryGroup->tree(), &armem::gui::MemoryTreeWidget::updated, this, &This::memoryTreeUpdated);
connect(instanceGroup, &armem::gui::InstanceGroupBox::viewUpdated, this, &This::instanceTreeUpdated);
}
void MemoryViewer::setLogTag(const std::string& tag)
{
Logging::setTag(tag);
}
void MemoryViewer::onInit(ManagedIceObject& component)
{
if (mnsName.size() > 0)
{
component.usingProxy(mnsName);
}
if (debugObserverName.size() > 0)
{
component.usingProxy(debugObserverName);
}
emit initialized();
}
void MemoryViewer::onConnect(ManagedIceObject& component)
{
if (!mnsName.empty())
{
component.getProxy(mns, mnsName);
auto res = mns->getAllRegisteredMemories();
for (auto& [name, proxy] : res.proxies)
{
armem::client::Reader memoryReader{proxy};
memoryReaders[name] = memoryReader;
}
}
// DebugObserver is optional (check for null on every call)
if (!debugObserverName.empty())
{
component.getProxy(debugObserver, debugObserverName, false, "", false);
}
updateWidget->startTimerIfEnabled();
emit connected();
}
void MemoryViewer::onDisconnect(ManagedIceObject&)
{
updateWidget->stopTimer();
emit disconnected();
}
void MemoryViewer::updateMemories()
{
memoryReaders.clear();
memoryData.clear();
for (auto& [name, proxy] : mns->getAllRegisteredMemories().proxies)
{
armem::client::Reader memoryReader{proxy};
memoryReaders[name] = memoryReader;
}
bool dataChanged = false;
for (auto& [name, reader] : memoryReaders)
{
TIMING_START(MemoryQuery);
{
armem::client::QueryInput input = memoryGroup->queryWidget()->queryInput();
armem::client::QueryResult result = reader.query(input);
if (result)
{
memoryData[name] = std::move(result.memory);
}
else
{
if (statusLabel)
{
statusLabel->setText(QString::fromStdString(result.errorMessage));
}
}
}
TIMING_END_STREAM(MemoryQuery, ARMARX_VERBOSE);
if (debugObserver)
{
debugObserver->setDebugDatafield(Logging::tag.tagName, "Memory Query [ms]", new Variant(MemoryQuery.toMilliSecondsDouble()));
}
if (memoryData[name])
{
dataChanged = true;
}
else
{
if (statusLabel)
{
statusLabel->setText("No query result.");
}
}
}
if (dataChanged)
{
emit memoryDataChanged();
}
}
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::Memory>& data = memoryData.at(selectedID.memoryName);
if (data)
{
if (!selectedID.hasEntityName())
{
return;
}
armem::MemoryID id = selectedID;
const armem::EntitySnapshot* snapshot = nullptr;
if (!id.hasTimestamp())
{
const armem::Entity& entity = data->getEntity(id);
if (entity.empty())
{
return;
}
snapshot = &entity.getLatestSnapshot();
id.timestamp = snapshot->time();
}
if (!id.hasInstanceIndex())
{
if (!snapshot)
{
try
{
snapshot = &data->getEntitySnapshot(id);
}
catch (const armem::error::ArMemError& e)
{
if (statusLabel)
{
statusLabel->setText(e.what());
}
}
}
if (snapshot && snapshot->size() > 0)
{
id.instanceIndex = 0;
}
}
if (id.hasInstanceIndex())
{
instanceGroup->view->update(id, *data);
}
}
}
void MemoryViewer::updateMemoryTree()
{
std::map<std::string, const armem::Memory*> convMap;
for (auto& [name, data] : memoryData)
{
if (data.has_value())
{
convMap[name] = &data.value();
}
}
if (convMap.empty())
{
return;
}
TIMING_START(GuiUpdate);
memoryGroup->tree()->update(convMap);
TIMING_END_STREAM(GuiUpdate, ARMARX_VERBOSE);
if (debugObserver)
{
debugObserver->setDebugDatafield(Logging::tag.tagName, "GUI Update [ms]", new Variant(GuiUpdate.toMilliSecondsDouble()));
}
}
const static std::string CONFIG_KEY_MEMORY = "MemoryViewer.MemoryNameSystem";
const static std::string CONFIG_KEY_DEBUG_OBSERVER = "MemoryViewer.DebugObserverName";
void MemoryViewer::loadSettings(QSettings* settings)
{
mnsName = settings->value(QString::fromStdString(CONFIG_KEY_MEMORY), "MemoryNameSystem").toString().toStdString();
debugObserverName = settings->value(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER), "DebugObserver").toString().toStdString();
}
void MemoryViewer::saveSettings(QSettings* settings)
{
settings->setValue(QString::fromStdString(CONFIG_KEY_MEMORY), QString::fromStdString(mnsName));
settings->setValue(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER), QString::fromStdString(debugObserverName));
}
void MemoryViewer::writeConfigDialog(SimpleConfigDialog* dialog)
{
dialog->addProxyFinder<armarx::armem::mns::MemoryNameSystemInterfacePrx>({CONFIG_KEY_MEMORY, "MemoryNameSystem", "*"});
dialog->addProxyFinder<armarx::DebugObserverInterfacePrx>({CONFIG_KEY_DEBUG_OBSERVER, "Debug Observer", "DebugObserver"});
}
void MemoryViewer::readConfigDialog(SimpleConfigDialog* dialog)
{
mnsName = dialog->getProxyName(CONFIG_KEY_MEMORY);
ARMARX_IMPORTANT << VAROUT(mnsName);
if (mnsName.empty())
{
mnsName = "MemoryNameSystem";
}
ARMARX_IMPORTANT << VAROUT(mnsName);
debugObserverName = dialog->getProxyName(CONFIG_KEY_DEBUG_OBSERVER);
}
}