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
76 void
77 MemoryViewer::setLogTag(const std::string& _tag) // Leading _ silences a warning
78 {
79 Logging::setTag(_tag);
80 }
81
82 void
84 {
85 if (_mnsName.size() > 0)
86 {
87 component.usingProxy(_mnsName);
88 }
89 if (_debugObserverName.size() > 0)
90 {
91 component.usingProxy(_debugObserverName);
92 }
93
94 _model->setInitialized(true);
95 emit initialized();
96 }
97
98 void
99 MemoryViewer::onConnect(ManagedIceObject& component)
100 {
101 if (not _mnsName.empty())
102 {
103 armem::mns::MemoryNameSystemInterfacePrx mnsProxy;
104 component.getProxy(mnsProxy, _mnsName);
105 _model->setMns(std::make_unique<client::MemoryNameSystem>(mnsProxy));
106
107 const bool update = true;
108
109 _model->setMemoryReaders(_model->mns().getAllReaders(update));
110 _model->setMemoryWriters(_model->mns().getAllWriters(update));
111 }
112 // DebugObserver is optional (check for null on every call)
113 if (not _debugObserverName.empty())
114 {
116 component.getProxy(observer, _debugObserverName, false, "", false);
117 _model->setDebugObserver(observer);
118 }
119
120 emit _periodicUpdateController->startPeriodicTimerSignal();
121 _periodicUpdateController->startAutoUpdateTimerIfEnabled();
122
123 _model->setConnected(true);
124 emit connected();
125 }
126
127 void
128 MemoryViewer::onDisconnect(ManagedIceObject&)
129 {
130 emit _periodicUpdateController->stopAutoUpdateTimerSignal();
131 emit _periodicUpdateController->stopPeriodicTimerSignal();
132
133 _model->setConnected(false);
134
135 emit disconnected();
136 }
137
138 void
140 QWidget* parent,
141 const QPoint& pos,
142 QMenu* menu)
143 {
144 // Called if we have to stop because of an error.
145 auto showMenu = [menu, pos]()
146 {
147 if (menu)
148 menu->exec(pos);
149 };
150
151 if (memoryID == MemoryID())
152 {
153 // Empty MemoryID, don't try to generate actions.
154 showMenu();
155 return;
156 }
157
158 mns::dto::MemoryServerInterfaces prx;
159 try
160 {
161 prx = _model->mns().resolveServer(memoryID);
162 }
164 {
165 _statusLabel->setText(
166 QString::fromStdString(e.makeMsg(memoryID, "Could not resolve memory server.")));
167 showMenu();
168 return;
169 }
170
171 if (!prx.actions)
172 {
173 std::stringstream ss;
174 ss << "Memory server " << memoryID << " does not support actions or is offline.";
175 _statusLabel->setText(QString::fromStdString(ss.str()));
176 showMenu();
177 return;
178 }
179
180 actions::GetActionsOutputSeq result;
181 try
182 {
183 result = prx.actions->getActions({{armarx::toIce<data::MemoryID>(memoryID)}});
184 }
185 catch (const Ice::LocalException& e)
186 {
187 std::stringstream ss;
188 ss << "Could not get actions for " << memoryID << ".";
189 _statusLabel->setText(QString::fromStdString(ss.str()));
190 showMenu();
191 return;
192 }
193
194 if (result.size() == 0)
195 {
196 showMenu();
197 return;
198 }
199 auto builder = ActionsMenuBuilder(
200 memoryID,
201 parent,
202 [this, prx](const MemoryID& memoryID, const actions::ActionPath& path)
203 {
204 actions::data::ExecuteActionOutputSeq result;
205 try
206 {
207 result = prx.actions->executeActions(
208 {{armarx::toIce<armem::data::MemoryID>(memoryID), path}});
209 }
210 catch (const Ice::LocalException& e)
211 {
212 std::stringstream ss;
213 ss << "Failed to execute action: " << e.what();
214 _statusLabel->setText(QString::fromStdString(ss.str()));
215 }
216
217 for (const auto& [success, errorMessage] : result)
218 {
219 if (not success)
220 {
221 std::stringstream ss;
222 ss << "Failed to execute action: " << errorMessage;
223 _statusLabel->setText(QString::fromStdString(ss.str()));
224 ARMARX_WARNING << ss.str();
225 }
226 }
227 });
228
229 QMenu* actionsMenu = builder.buildActionsMenu(result[0]);
230 if (menu == nullptr)
231 {
232 actionsMenu->exec(pos);
233 }
234 else
235 {
236 menu->addMenu(actionsMenu);
237 menu->exec(pos);
238 }
239 }
240
241 const static std::string CONFIG_KEY_MEMORY = "MemoryViewer.MemoryNameSystem";
242 const static std::string CONFIG_KEY_DEBUG_OBSERVER = "MemoryViewer.DebugObserverName";
243
244 void
245 MemoryViewer::loadSettings(QSettings* settings)
246 {
247 _mnsName = settings->value(QString::fromStdString(CONFIG_KEY_MEMORY), "MemoryNameSystem")
248 .toString()
249 .toStdString();
250 _debugObserverName =
251 settings->value(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER), "DebugObserver")
252 .toString()
253 .toStdString();
254 }
255
256 void
257 MemoryViewer::saveSettings(QSettings* settings)
258 {
259 settings->setValue(QString::fromStdString(CONFIG_KEY_MEMORY),
260 QString::fromStdString(_mnsName));
261 settings->setValue(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER),
262 QString::fromStdString(_debugObserverName));
263 }
264
265 void
267 {
268 dialog->addProxyFinder<armarx::armem::mns::MemoryNameSystemInterfacePrx>(
269 {CONFIG_KEY_MEMORY, "MemoryNameSystem", "MemoryNameSystem"});
271 {CONFIG_KEY_DEBUG_OBSERVER, "Debug Observer", "DebugObserver"});
272 }
273
274 void
276 {
277 _mnsName = dialog->getProxyName(CONFIG_KEY_MEMORY);
278 if (_mnsName.empty())
279 {
280 _mnsName = "MemoryNameSystem";
281 }
282
283 _debugObserverName = dialog->getProxyName(CONFIG_KEY_DEBUG_OBSERVER);
284 }
285
286} // 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)