MemoryViewer.cpp
Go to the documentation of this file.
1#include "MemoryViewer.h"
2
3#include <QApplication>
4#include <QClipboard>
5#include <QLabel>
6#include <QMenu>
7#include <QSettings>
8#include <QTimer>
9
10#include <Ice/Exception.h>
11
16
18
19#include <RobotAPI/interface/armem/actions.h>
20#include <RobotAPI/interface/armem/memory.h>
21#include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
26
27namespace armarx::armem::gui
28{
30 {
31 Logging::setTag("MemoryViewer");
32
33
34 _statusLabel = uiContext.statusLabel;
35 _statusLabel->clear();
36 _statusLabel->setContextMenuPolicy(Qt::CustomContextMenu);
37 connect(_statusLabel,
38 &QLabel::customContextMenuRequested,
39 [this](const QPoint& pos)
40 {
41 QMenu menu(_statusLabel);
42 menu.addAction("Copy to clipboard",
43 [this]()
44 { QApplication::clipboard()->setText(_statusLabel->text()); });
45 menu.addAction("Clear status", [this]() { _statusLabel->clear(); });
46 menu.exec(_statusLabel->mapToGlobal(pos));
47 });
48
49 _model = std::make_shared<armem::gui::model::MemoryViewerModel>();
50
51 _diskIOController = std::make_unique<armem::gui::controller::DiskIOController>(
52 uiContext,
53 _model);
54
55 _periodicUpdateController = std::make_unique<armem::gui::controller::PeriodicUpdateController>(
56 uiContext,
57 _model);
58
59 connect(_periodicUpdateController
60 ->memoryGroupBoxController()
61 ->memoryGroupBoxView()
62 ->tree(),
64 this,
66 connect(_periodicUpdateController
67 ->memoryGroupBoxController()
68 ->instanceGroupBoxController()
69 ->instanceGroupBoxView()
70 ->instanceView(),
72 this,
74
75 _livePlotController =
76 std::make_unique<armem::gui::controller::LivePlotController>(_model);
77 _periodicUpdateController
78 ->memoryGroupBoxController()
79 ->instanceGroupBoxController()
80 ->instanceGroupBoxView()
81 ->instanceView()
82 ->setLivePlotController(_livePlotController.get());
83 }
84
85 void
86 MemoryViewer::setLogTag(const std::string& _tag) // Leading _ silences a warning
87 {
88 Logging::setTag(_tag);
89 }
90
91 void
93 {
94 if (_mnsName.size() > 0)
95 {
96 component.usingProxy(_mnsName);
97 }
98 if (_debugObserverName.size() > 0)
99 {
100 component.usingProxy(_debugObserverName);
101 }
102
103 _model->setInitialized(true);
104 emit initialized();
105 }
106
107 void
108 MemoryViewer::onConnect(ManagedIceObject& component)
109 {
110 if (not _mnsName.empty())
111 {
112 armem::mns::MemoryNameSystemInterfacePrx mnsProxy;
113 component.getProxy(mnsProxy, _mnsName);
114 _model->setMns(std::make_unique<client::MemoryNameSystem>(mnsProxy));
115
116 const bool update = true;
117
118 _model->setMemoryReaders(_model->mns().getAllReaders(update));
119 _model->setMemoryWriters(_model->mns().getAllWriters(update));
120 }
121 // DebugObserver is optional (check for null on every call)
122 if (not _debugObserverName.empty())
123 {
125 component.getProxy(observer, _debugObserverName, false, "", false);
126 _model->setDebugObserver(observer);
127 }
128
129 emit _periodicUpdateController->startPeriodicTimerSignal();
130 _periodicUpdateController->startAutoUpdateTimerIfEnabled();
131
132 _livePlotController->onConnect();
133
134 _model->setConnected(true);
135 emit connected();
136 }
137
138 void
139 MemoryViewer::onDisconnect(ManagedIceObject&)
140 {
141 emit _periodicUpdateController->stopAutoUpdateTimerSignal();
142 emit _periodicUpdateController->stopPeriodicTimerSignal();
143
144 _livePlotController->onDisconnect();
145
146 _model->setConnected(false);
147
148 emit disconnected();
149 }
150
151 void
153 QWidget* parent,
154 const QPoint& pos,
155 QMenu* menu)
156 {
157 // Called if we have to stop because of an error.
158 auto showMenu = [menu, pos]()
159 {
160 if (menu)
161 menu->exec(pos);
162 };
163
164 if (memoryID == MemoryID())
165 {
166 // Empty MemoryID, don't try to generate actions.
167 showMenu();
168 return;
169 }
170
171 mns::dto::MemoryServerInterfaces prx;
172 try
173 {
174 prx = _model->mns().resolveServer(memoryID);
175 }
177 {
178 _statusLabel->setText(
179 QString::fromStdString(e.makeMsg(memoryID, "Could not resolve memory server.")));
180 showMenu();
181 return;
182 }
183
184 if (!prx.actions)
185 {
186 std::stringstream ss;
187 ss << "Memory server " << memoryID << " does not support actions or is offline.";
188 _statusLabel->setText(QString::fromStdString(ss.str()));
189 showMenu();
190 return;
191 }
192
193 actions::GetActionsOutputSeq result;
194 try
195 {
196 result = prx.actions->getActions({{armarx::toIce<data::MemoryID>(memoryID)}});
197 }
198 catch (const Ice::LocalException& e)
199 {
200 std::stringstream ss;
201 ss << "Could not get actions for " << memoryID << ".";
202 _statusLabel->setText(QString::fromStdString(ss.str()));
203 showMenu();
204 return;
205 }
206
207 if (result.size() == 0)
208 {
209 showMenu();
210 return;
211 }
212 auto builder = ActionsMenuBuilder(
213 memoryID,
214 parent,
215 [this, prx](const MemoryID& memoryID, const actions::ActionPath& path)
216 {
217 actions::data::ExecuteActionOutputSeq result;
218 try
219 {
220 result = prx.actions->executeActions(
221 {{armarx::toIce<armem::data::MemoryID>(memoryID), path}});
222 }
223 catch (const Ice::LocalException& e)
224 {
225 std::stringstream ss;
226 ss << "Failed to execute action: " << e.what();
227 _statusLabel->setText(QString::fromStdString(ss.str()));
228 }
229
230 for (const auto& [success, errorMessage] : result)
231 {
232 if (not success)
233 {
234 std::stringstream ss;
235 ss << "Failed to execute action: " << errorMessage;
236 _statusLabel->setText(QString::fromStdString(ss.str()));
237 ARMARX_WARNING << ss.str();
238 }
239 }
240 });
241
242 QMenu* actionsMenu = builder.buildActionsMenu(result[0]);
243 if (menu == nullptr)
244 {
245 actionsMenu->exec(pos);
246 }
247 else
248 {
249 menu->addMenu(actionsMenu);
250 menu->exec(pos);
251 }
252 }
253
254 const static std::string CONFIG_KEY_MEMORY = "MemoryViewer.MemoryNameSystem";
255 const static std::string CONFIG_KEY_DEBUG_OBSERVER = "MemoryViewer.DebugObserverName";
256
257 void
258 MemoryViewer::loadSettings(QSettings* settings)
259 {
260 _mnsName = settings->value(QString::fromStdString(CONFIG_KEY_MEMORY), "MemoryNameSystem")
261 .toString()
262 .toStdString();
263 _debugObserverName =
264 settings->value(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER), "DebugObserver")
265 .toString()
266 .toStdString();
267 }
268
269 void
270 MemoryViewer::saveSettings(QSettings* settings)
271 {
272 settings->setValue(QString::fromStdString(CONFIG_KEY_MEMORY),
273 QString::fromStdString(_mnsName));
274 settings->setValue(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER),
275 QString::fromStdString(_debugObserverName));
276 }
277
278 void
280 {
281 dialog->addProxyFinder<armarx::armem::mns::MemoryNameSystemInterfacePrx>(
282 {CONFIG_KEY_MEMORY, "MemoryNameSystem", "MemoryNameSystem"});
284 {CONFIG_KEY_DEBUG_OBSERVER, "Debug Observer", "DebugObserver"});
285 }
286
287 void
289 {
290 _mnsName = dialog->getProxyName(CONFIG_KEY_MEMORY);
291 if (_mnsName.empty())
292 {
293 _mnsName = "MemoryNameSystem";
294 }
295
296 _debugObserverName = dialog->getProxyName(CONFIG_KEY_DEBUG_OBSERVER);
297 }
298
299} // namespace armarx::armem::gui
void setTag(const LogTag &tag)
Definition Logging.cpp:54
The ManagedIceObject is the base class for all ArmarX objects.
A config-dialog containing one (or multiple) proxy finders.
void addProxyFinder(const std::vector< EntryData > &entryData)
std::string getProxyName(const std::string &entryName) const
Indicates that a query to the Memory Name System failed.
Definition mns.h:25
static std::string makeMsg(const MemoryID &memoryID, const std::string &errorMessage="")
Definition mns.cpp:36
QMenu * buildActionsMenu(actions::data::GetActionsOutput &actionsOutput)
void readConfigDialog(SimpleConfigDialog *dialog)
void setLogTag(const std::string &tag)
void showActionsMenu(const MemoryID &memoryID, QWidget *parent, const QPoint &pos, QMenu *menu)
void saveSettings(QSettings *settings)
void loadSettings(QSettings *settings)
void writeConfigDialog(SimpleConfigDialog *dialog)
MemoryViewer(MemoryViewerUIContext &uiContext)
void actionsMenuRequested(const MemoryID &memoryID, QWidget *parent, const QPoint &pos, QMenu *menu)
void actionsMenuRequested(const MemoryID &memoryID, QWidget *parent, const QPoint &pos, QMenu *menu)
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
void toIce(std::map< IceKeyT, IceValueT > &iceMap, const boost::container::flat_map< CppKeyT, CppValueT > &cppMap)