IceGridViewer.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @package ArmarX::
17* @author Manfred Kroehnert ( Manfred.Kroehnert at kit dot edu)
18* @date 2013
19* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23#include "IceGridViewer.h"
24
26
27#include <algorithm>
28
29#include <Ice/ObjectAdapter.h>
30
34
35#include <ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ui_IceGridNodeView.h>
36#include <ArmarXGui/gui-plugins/SystemStateMonitorPlugin/ui_IceGridViewer.h>
37
38#include "NodeObserver.h"
40#include "model/NodeInfoModel.h"
42
43namespace armarx
44{
46 ui(new Ui::IceGridViewer), ADAPTER_NAME("IceGridNodeObserverGui")
47 {
48 ui->setupUi(getWidget());
49
50 qRegisterMetaType<QVector<int>>("QVector<int>");
51 qRegisterMetaType<IceGrid::ServerDynamicInfo>("IceGrid::ServerDynamicInfo");
52 connect(ui->gridNodeSelector,
53 SIGNAL(currentIndexChanged(int)),
54 this,
55 SLOT(selectGridNode(int)));
56
57 // Stack-allocated: the generated Ui holder is only needed to wire up the table
58 // views (which become children of contentWidget); the old heap allocation was
59 // never deleted (issue #64.16).
60 Ui::IceGridNodeView content;
61 content.setupUi(ui->contentWidget);
62 nodeInfoModel = new NodeInfoModel;
63 content.NodeInfo->setModel(nodeInfoModel);
64 serverInfoModel = new ServerInfoModel;
65 content.ServerInfo->setModel(serverInfoModel);
66 adapterInfoModel = new AdapterInfoModel;
67 content.AdapterInfo->setModel(adapterInfoModel);
68
69 connect(serverInfoModel,
70 SIGNAL(serverInfoChanged(IceGrid::ServerDynamicInfo)),
71 this,
72 SLOT(serverInfoChanged(IceGrid::ServerDynamicInfo)));
73
74 selectorModel = new QStringListModel;
75 ui->gridNodeSelector->setModel(selectorModel);
76 }
77
79 {
80 // The four models were unparented and leaked; delete them here (issue #64.16).
81 // Views still bound to them detach safely via Qt's model destroyed() handling.
82 delete ui;
83 delete nodeInfoModel;
84 delete serverInfoModel;
85 delete adapterInfoModel;
86 delete selectorModel;
87 }
88
89 void
90 IceGridViewer::loadSettings(QSettings* settings)
91 {
92 }
93
94 void
95 IceGridViewer::saveSettings(QSettings* settings)
96 {
97 }
98
99 void
101 {
102 // create new IceGridAdmin which also creates a new AdminSession
103 // Observers set on this new session won't interfer with the default observers
104 // used for tracking ManagedIceObject dependencies
105 iceGridAdmin = IceGridAdmin::Create(getIceManager()->getCommunicator(), ADAPTER_NAME);
106 // remove default observers which are not required and used here
107 iceGridAdmin->removeObservers();
108 }
109
110 void
112 {
113 IceGrid::AdminSessionPrx adminSession = iceGridAdmin->adminSession();
114
115 QtNodeObserverPtr observer = new QtNodeObserver(this);
116 Ice::ObjectPrx objectProxy =
117 iceGridAdmin->registerObjectWithNewAdapter(observer, ADAPTER_NAME, observerAdapter);
118 IceGrid::NodeObserverPrx nodeObserver = IceGrid::NodeObserverPrx::checkedCast(objectProxy);
119
120 // The first setObservers(NULL, ...) call was immediately overwritten by the next
121 // line and did nothing (issue #64.19).
122 adminSession->setObservers(nullptr, nodeObserver, nullptr, nullptr, nullptr);
123 }
124
125 void
127 {
128 // stop updating the AdminSession so it can be removed
129 iceGridAdmin->stop();
130 // remove observers so the IceGridAmin does not hold any more references to them
131 iceGridAdmin->adminSession()->setObservers(NULL, NULL, NULL, NULL, NULL);
132 // destroy the object adapter to remove the observer objects
133 observerAdapter->destroy();
134 }
135
136 void
137 IceGridViewer::gridNodeListUpdate(const IceGrid::NodeDynamicInfoSeq& nodeSeq)
138 {
139 // Called from the Ice dispatch thread. Marshal all model/widget access onto the
140 // GUI thread (this object's thread). Everything below then runs single-threaded,
141 // which is why gridNodeList needs no mutex (see issue #64.8/#64.9). The captured
142 // arguments are copies, so they stay valid after the Ice call returns.
144 this,
145 [this, nodeSeq]()
146 {
147 const QString lastSelectionText = ui->gridNodeSelector->currentText();
148
149 gridNodeList = nodeSeq;
150 QStringList nodeNames;
151 for (const auto& node : gridNodeList)
152 {
153 nodeNames.append(QString::fromStdString(node.info.name));
154 }
155 selectorModel->setStringList(nodeNames);
156
157 const int index = std::max(0, ui->gridNodeSelector->findText(lastSelectionText));
158 ui->gridNodeSelector->setCurrentIndex(index);
160 });
161 }
162
163 void
164 IceGridViewer::gridNodeListAdd(const IceGrid::NodeDynamicInfo& node)
165 {
167 this,
168 [this, node]()
169 {
170 QStringList currentEntries = selectorModel->stringList();
171 currentEntries.append(QString::fromStdString(node.info.name));
172 gridNodeList.push_back(node);
173 selectorModel->setStringList(currentEntries);
174 });
175 }
176
177 void
179 {
181 this,
182 [this, node]()
183 {
184 const QString lastSelectionText = ui->gridNodeSelector->currentText();
185
186 QStringList currentEntries = selectorModel->stringList();
187 currentEntries.removeOne(node);
188
189 // issue #64.10: the old hand-written erase loop advanced past the erased
190 // element (and past end() when it was the last one). Use erase-remove_if.
191 const std::string nodeName = node.toStdString();
192 gridNodeList.erase(std::remove_if(gridNodeList.begin(),
193 gridNodeList.end(),
194 [&nodeName](const IceGrid::NodeDynamicInfo& info)
195 { return info.info.name == nodeName; }),
196 gridNodeList.end());
197
198 selectorModel->setStringList(currentEntries);
199
200 const int index =
201 std::max<int>(0, ui->gridNodeSelector->findText(lastSelectionText));
202 ui->gridNodeSelector->setCurrentIndex(index);
204 });
205 }
206
207 void
208 IceGridViewer::updateServerInfo(const std::string& nodeName,
209 const IceGrid::ServerDynamicInfo& serverUpdateInfo)
210 {
212 this,
213 [this, nodeName, serverUpdateInfo]()
214 {
215 auto nodeEntry = std::find_if(gridNodeList.begin(),
216 gridNodeList.end(),
217 [&nodeName](const IceGrid::NodeDynamicInfo& nodeInfo)
218 { return nodeName == nodeInfo.info.name; });
219 if (nodeEntry == gridNodeList.end())
220 {
221 return;
222 }
223
224 auto serverEntry =
225 std::find_if(nodeEntry->servers.begin(),
226 nodeEntry->servers.end(),
227 [&serverUpdateInfo](const IceGrid::ServerDynamicInfo& serverInfo)
228 { return serverUpdateInfo.id == serverInfo.id; });
229
230 if (serverEntry == nodeEntry->servers.end())
231 {
232 nodeEntry->servers.push_back(serverUpdateInfo);
233 }
234 else if (serverUpdateInfo.pid == 0)
235 {
236 nodeEntry->servers.erase(serverEntry);
237 }
238 else
239 {
240 *serverEntry = serverUpdateInfo;
241 }
242
243 selectGridNode(ui->gridNodeSelector->currentIndex());
244 });
245 }
246
247 void
248 IceGridViewer::updateAdapterInfo(const std::string& nodeName,
249 const IceGrid::AdapterDynamicInfo& adapterUpdateInfo)
250 {
252 this,
253 [this, nodeName, adapterUpdateInfo]()
254 {
255 auto nodeEntry = std::find_if(gridNodeList.begin(),
256 gridNodeList.end(),
257 [&nodeName](const IceGrid::NodeDynamicInfo& nodeInfo)
258 { return nodeName == nodeInfo.info.name; });
259 if (nodeEntry == gridNodeList.end())
260 {
261 return;
262 }
263
264 auto adapterEntry = std::find_if(
265 nodeEntry->adapters.begin(),
266 nodeEntry->adapters.end(),
267 [&adapterUpdateInfo](const IceGrid::AdapterDynamicInfo& adapterInfo)
268 { return adapterUpdateInfo.id == adapterInfo.id; });
269
270 if (adapterEntry == nodeEntry->adapters.end())
271 {
272 // A null proxy signals adapter deactivation. If we never saw this
273 // adapter activate there is nothing to add - and storing the null
274 // proxy would later crash AdapterInfoModel::data() on repaint
275 // (issue #64.11).
276 if (adapterUpdateInfo.proxy)
277 {
278 nodeEntry->adapters.push_back(adapterUpdateInfo);
279 }
280 }
281 else if (!adapterUpdateInfo.proxy)
282 {
283 nodeEntry->adapters.erase(adapterEntry);
284 }
285 else
286 {
287 *adapterEntry = adapterUpdateInfo;
288 }
289
290 selectGridNode(ui->gridNodeSelector->currentIndex());
291 });
292 }
293
294 void
295 IceGridViewer::serverInfoChanged(IceGrid::ServerDynamicInfo serverInfo)
296 {
297 try
298 {
299 iceGridAdmin->getAdmin()->enableServer(serverInfo.id, serverInfo.enabled);
300 }
301 catch (...)
302 {
303 // Blocking Ice call on the GUI thread (triggered by the Enabled checkbox in
304 // ServerInfoModel). Never let an Ice exception escape into the Qt event loop
305 // (issue #64.12d).
306 ARMARX_WARNING << "Failed to enable/disable server " << serverInfo.id << ": "
308 }
309 }
310
311 void
313 {
314 // Runs on the GUI thread only: as a slot of ui->gridNodeSelector and from the
315 // marshaled observer handlers above. gridNodeList is therefore single-threaded
316 // and needs no lock (issue #64.9).
317 if (index < 0 || index >= (int)gridNodeList.size())
318 {
319 return;
320 }
321
322 nodeInfoModel->setData(gridNodeList[index].info);
323 serverInfoModel->setData(gridNodeList[index].servers);
324 adapterInfoModel->setData(gridNodeList[index].adapters);
325 }
326} // namespace armarx
uint8_t index
IceUtil::Handle< QtNodeObserver > QtNodeObserverPtr
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void onInitComponent() override
void gridNodeListAdd(const IceGrid::NodeDynamicInfo &node)
void loadSettings(QSettings *settings) override
Load stored manager models.
void saveSettings(QSettings *settings) override
Saves the manager models.
void gridNodeListRemove(const QString &node)
void updateServerInfo(const std::string &nodeName, const IceGrid::ServerDynamicInfo &serverUpdateInfo)
void onConnectComponent() override
void onExitComponent() override
Hook for subclass.
void serverInfoChanged(IceGrid::ServerDynamicInfo serverInfo)
void selectGridNode(int index)
void gridNodeListUpdate(const IceGrid::NodeDynamicInfoSeq &nodeSeq)
void updateAdapterInfo(const std::string &nodeName, const IceGrid::AdapterDynamicInfo &adapterUpdateInfo)
IceManagerPtr getIceManager() const
Returns the IceManager.
Ice::CommunicatorPtr getCommunicator() const
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:191
ArmarX Headers.
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::string GetHandledExceptionString()
void postToObject(QObject *context, Function &&function)
Run function on the GUI (main) thread's event loop.