DebugDrawerViewerWidgetController.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 RobotAPI::gui-plugins::DebugDrawerViewerWidgetController
17 * \author Mirko Waechter ( mirko dot waechter at kit dot edu )
18 * \date 2016
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
23
24#include <string>
25
26#include <QTimer>
27
28#include <SimoxUtility/algorithm/string/string_tools.h>
29
31
32namespace armarx
33{
35 {
36 rootVisu = nullptr;
37 widget.setupUi(getWidget());
38
39 QTimer* timer = new QTimer(this);
40 connect(timer, SIGNAL(timeout()), this, SLOT(updateComboClearLayer()));
41 timer->start(100);
42 }
43
44 void
46 {
47 (void)settings; // unused
48 }
49
50 void
52 {
53 (void)settings; // unused
54 }
55
56 void
58 {
59 rootVisu = new SoSeparator;
60 rootVisu->ref();
61
62
64 connect(widget.btnClearAll,
65 SIGNAL(clicked()),
66 this,
67 SLOT(on_btnClearAll_clicked()),
68 Qt::UniqueConnection);
69 connect(widget.btnClearLayer,
70 SIGNAL(clicked()),
71 this,
72 SLOT(on_btnClearLayer_clicked()),
73 Qt::UniqueConnection);
74 }
75
76 void
78 {
79 // create the debugdrawer component
80 std::string debugDrawerComponentName = "GUIDebugDrawer_" + getName();
81 ARMARX_INFO << "Creating component " << debugDrawerComponentName;
82 debugDrawer =
84
85 if (mutex3D)
86 {
87 //ARMARX_IMPORTANT << "mutex3d:" << mutex3D.get();
88 debugDrawer->setMutex(mutex3D);
89 }
90 else
91 {
92 ARMARX_ERROR << " No 3d mutex available...";
93 }
94
96 m->addObject(debugDrawer, false);
97
98 {
99 std::unique_lock lock(*mutex3D);
100 rootVisu->addChild(debugDrawer->getVisualization());
101 }
103 }
104
105 void
107 {
108 if (rootVisu)
109 {
110 rootVisu->removeAllChildren();
111 rootVisu->unref();
112 rootVisu = nullptr;
113 }
114 }
115
116 SoNode*
118 {
119 return rootVisu;
120 }
121
122 void
123 armarx::DebugDrawerViewerWidgetController::on_btnClearAll_clicked()
124 {
125 if (debugDrawer)
126 {
127 ARMARX_INFO << "Clearing all visualization layers";
128 debugDrawer->clearAll();
129 }
130 }
131
132 void
133 DebugDrawerViewerWidgetController::on_btnClearLayer_clicked()
134 {
135 if (debugDrawer)
136 {
137 int index = widget.comboClearLayer->currentIndex();
138 std::string layerName =
139 widget.comboClearLayer->itemData(index).toString().toStdString();
140
141 if (!layerName.empty())
142 {
143 ARMARX_INFO << "Clearing layer: '" << layerName << "'";
144 debugDrawer->clearLayer(layerName);
145 }
146 }
147 }
148
149 void
150 DebugDrawerViewerWidgetController::updateComboClearLayer()
151 {
152 QComboBox* combo = widget.comboClearLayer;
153
154 auto setItalic = [combo](bool italic)
155 {
156 QFont font = combo->font();
157 font.setItalic(italic);
158 combo->setFont(font);
159 };
160
161 auto disableButton = [combo, this, &setItalic](const std::string& hint)
162 {
163 QString itemText(hint.c_str());
164 QString itemData("");
165 setItalic(true);
166
167 if (combo->count() != 1)
168 {
169 combo->clear();
170 combo->insertItem(0, itemText, itemData);
171 }
172 else
173 {
174 combo->setItemText(0, itemText);
175 combo->setItemData(0, itemData);
176 }
177
178 this->widget.btnClearLayer->setEnabled(false);
179 };
180
181 if (!debugDrawer)
182 {
183 disableButton("not connected");
184 return;
185 }
186
187 // fetch layer information
188 LayerInformationSequence layers = debugDrawer->layerInformation();
189
190 if (layers.empty())
191 {
192 disableButton("no layers");
193 return;
194 }
195 else
196 {
197 setItalic(false);
198 this->widget.btnClearLayer->setEnabled(true);
199 }
200
201 // sort the layers by name
202 std::sort(layers.begin(),
203 layers.end(),
204 [](const LayerInformation& lhs, const LayerInformation& rhs)
205 {
206 // compare case insensitively
207 for (std::size_t i = 0; i < lhs.layerName.size() && i < lhs.layerName.size();
208 ++i)
209 {
210 auto lhsLow = std::tolower(lhs.layerName[i]);
211 auto rhsLow = std::tolower(rhs.layerName[i]);
212 if (lhsLow < rhsLow)
213 {
214 return true;
215 }
216 else if (lhsLow > rhsLow)
217 {
218 return false;
219 }
220 }
221 // if one is a prefix of the other, the shorter one "smaller"
222 return lhs.layerName.size() < rhs.layerName.size();
223 });
224
225
226 const int numLayers = static_cast<int>(layers.size());
227
228 for (int i = 0; i < numLayers; ++i)
229 {
230 const LayerInformation& layer = layers[static_cast<std::size_t>(i)];
231
232 QString layerName(layer.layerName.c_str());
233
234 if (i < combo->count()) // in range
235 {
236 QString itemData = combo->itemData(i).toString();
237
238 // remove deleted layers
239 while (itemData.size() != 0 && itemData < layerName)
240 {
241 // item layer is smaller than next layer
242 // => item layer was deleted
243 combo->removeItem(i);
244 itemData = i < combo->count() ? combo->itemData(i).toString() : "";
245 }
246
247 // update existing layer
248 if (itemData == layerName)
249 {
250 combo->setItemText(i, makeLayerItemText(layer));
251 }
252 else // (itemData > layerName)
253 {
254 // item layer is further down than current layer
255 // => insert current layer here
256 combo->insertItem(i, makeLayerItemText(layer), layerName);
257 }
258 }
259 else // out of range
260 {
261 combo->insertItem(i, makeLayerItemText(layer), layerName);
262 }
263
264 // check invariant
265 ARMARX_CHECK_EQUAL(combo->itemData(i).toString(), layerName);
266 }
267
268 // remove excessive items
269 while (combo->count() > numLayers)
270 {
271 combo->removeItem(combo->count() - 1);
272 }
273 }
274
275 QString
276 DebugDrawerViewerWidgetController::makeLayerItemText(const LayerInformation& layer)
277 {
278 std::vector<std::string> annotations;
279 if (layer.elementCount == 0)
280 {
281 annotations.push_back("empty");
282 }
283 else
284 {
285 annotations.push_back(std::to_string(layer.elementCount));
286 }
287 if (!layer.visible)
288 {
289 annotations.push_back("hidden");
290 }
291
292 if (annotations.empty())
293 {
294 return {layer.layerName.c_str()};
295 }
296 else
297 {
298 std::stringstream itemText;
299 itemText << layer.layerName << " (" << simox::alg::join(annotations, ", ") << ")";
300 return {itemText.str().c_str()};
301 }
302 }
303} // namespace armarx
uint8_t index
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
std::shared_ptr< std::recursive_mutex > mutex3D
void enableMainWidgetAsync(bool enable)
This function enables/disables the main widget asynchronously (if called from a non qt thread).
static TPtr create(Ice::PropertiesPtr properties=Ice::createProperties(), const std::string &configName="", const std::string &configDomain="ArmarX")
Factory method for a component.
Definition Component.h:116
SoNode * getScene() override
Reimplementing this function and returning a SoNode* will show this SoNode in the 3DViewerWidget,...
std::string getName() const
Retrieve name of object.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Ice::PropertiesPtr getIceProperties() const
Returns the set of Ice properties.
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< ArmarXManager > ArmarXManagerPtr