VariantWidget.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 ArmarXGui::ArmarXObjects::VariantWidget
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "VariantWidget.h"
24
25#include <QFormLayout>
26#include <QLabel>
27#include <QTableWidget>
28#include <QVBoxLayout>
29
32#include <ArmarXCore/interface/observers/Complex.h>
33#include <ArmarXCore/interface/observers/Matrix.h>
34#include <ArmarXCore/interface/observers/Timestamp.h>
35#include <ArmarXCore/interface/observers/VariantContainers.h>
36
38{
40 {
41 public:
51
52 BoolVariantDataWidget(const VariantDataPtr& v) : disp{DisplayOption::Boolalpha}
53 {
54 auto l = new QVBoxLayout;
55 l->setContentsMargins(0, 0, 0, 0);
56 setLayout(l);
57 label = new QLabel;
58 l->addWidget(label);
59 update(v);
60 }
61
62 void
63 update(const VariantDataPtr& p) override
64 {
65 BoolVariantDataPtr v = BoolVariantDataPtr::dynamicCast(p);
67 switch (disp)
68 {
70 label->setText(v->b ? "true" : "false");
71 break;
73 label->setText(v->b ? "True" : "False");
74 break;
76 label->setText(v->b ? "TRUE" : "FALSE");
77 break;
79 label->setText(v->b ? "1" : "0");
80 break;
82 label->setText(v->b ? "X" : "O");
83 break;
85 label->setText(v->b ? "X" : " ");
86 break;
87 }
88 }
89
90 private:
91 QLabel* label;
92 DisplayOption disp;
93 };
94
97
99 {
100 public:
101 DoubleVariantDataWidget(const VariantDataPtr& v)
102 {
103 auto l = new QVBoxLayout;
104 l->setContentsMargins(0, 0, 0, 0);
105 setLayout(l);
106 label = new QLabel;
107 l->addWidget(label);
108 update(v);
109 }
110
111 void
112 update(const VariantDataPtr& p) override
113 {
114 DoubleVariantDataPtr v = DoubleVariantDataPtr::dynamicCast(p);
116 label->setText(QString::number(v->d));
117 }
118
119 private:
120 QLabel* label;
121 };
122
125
127 {
128 public:
129 FloatVariantDataWidget(const VariantDataPtr& v)
130 {
131 auto l = new QVBoxLayout;
132 l->setContentsMargins(0, 0, 0, 0);
133 setLayout(l);
134 label = new QLabel;
135 l->addWidget(label);
136 update(v);
137 }
138
139 void
140 update(const VariantDataPtr& p) override
141 {
142 FloatVariantDataPtr v = FloatVariantDataPtr::dynamicCast(p);
144 label->setText(QString::number(v->f));
145 }
146
147 private:
148 QLabel* label;
149 };
150
153
155 {
156 public:
157 IntVariantDataWidget(const VariantDataPtr& v)
158 {
159 auto l = new QVBoxLayout;
160 l->setContentsMargins(0, 0, 0, 0);
161 setLayout(l);
162 label = new QLabel;
163 l->addWidget(label);
164 update(v);
165 }
166
167 void
168 update(const VariantDataPtr& p) override
169 {
170 IntVariantDataPtr v = IntVariantDataPtr::dynamicCast(p);
172 label->setText(QString::number(v->n));
173 }
174
175 private:
176 QLabel* label;
177 };
178
181
183 {
184 public:
185 LongVariantDataWidget(const VariantDataPtr& v)
186 {
187 auto l = new QVBoxLayout;
188 l->setContentsMargins(0, 0, 0, 0);
189 setLayout(l);
190 label = new QLabel;
191 l->addWidget(label);
192 update(v);
193 }
194
195 void
196 update(const VariantDataPtr& p) override
197 {
198 LongVariantDataPtr v = LongVariantDataPtr::dynamicCast(p);
200 label->setText(QString::number(v->n));
201 }
202
203 private:
204 QLabel* label;
205 };
206
209
211 {
212 public:
213 StringVariantDataWidget(const VariantDataPtr& v)
214 {
215 auto l = new QVBoxLayout;
216 l->setContentsMargins(0, 0, 0, 0);
217 setLayout(l);
218 label = new QLabel;
219 l->addWidget(label);
220 update(v);
221 }
222
223 void
224 update(const VariantDataPtr& p) override
225 {
226 StringVariantDataPtr v = StringVariantDataPtr::dynamicCast(p);
228 label->setText(QString::fromStdString(v->s));
229 }
230
231 private:
232 QLabel* label;
233 };
234
237
239 {
240 public:
241 TimestampBaseWidget(const VariantDataPtr& v) : suffix{"us"}
242 {
243 auto l = new QVBoxLayout;
244 l->setContentsMargins(0, 0, 0, 0);
245 setLayout(l);
246 label = new QLabel;
247 l->addWidget(label);
248 update(v);
249 }
250
251 void
252 update(const VariantDataPtr& p) override
253 {
254 TimestampBasePtr v = TimestampBasePtr::dynamicCast(p);
256 label->setText(QString::number(v->timestamp) + suffix);
257 }
258
259 private:
260 QLabel* label;
261 QString suffix;
262 };
263
266
268 {
269 public:
270 ComplexFloatBaseWidget(const VariantDataPtr& v)
271 {
272 auto l = new QFormLayout;
273 l->setContentsMargins(0, 0, 0, 0);
274 setLayout(l);
275 labelR = new QLabel;
276 labelI = new QLabel;
277 l->addRow("Real", labelR);
278 l->addRow("Imag", labelI);
279 update(v);
280 }
281
282 void
283 update(const VariantDataPtr& p) override
284 {
285 ComplexFloatBasePtr v = ComplexFloatBasePtr::dynamicCast(p);
287 labelR->setText(QString::number(v->real));
288 labelI->setText(QString::number(v->imag));
289 }
290
291 private:
292 QLabel* labelR;
293 QLabel* labelI;
294 };
295
298
300 {
301 public:
302 ComplexDoubleBaseWidget(const VariantDataPtr& v)
303 {
304 auto l = new QFormLayout;
305 l->setContentsMargins(0, 0, 0, 0);
306 setLayout(l);
307 labelR = new QLabel;
308 labelI = new QLabel;
309 l->addRow("Real", labelR);
310 l->addRow("Imag", labelI);
311 update(v);
312 }
313
314 void
315 update(const VariantDataPtr& p) override
316 {
317 ComplexDoubleBasePtr v = ComplexDoubleBasePtr::dynamicCast(p);
319 labelR->setText(QString::number(v->real));
320 labelI->setText(QString::number(v->imag));
321 }
322
323 private:
324 QLabel* labelR;
325 QLabel* labelI;
326 };
327
330
332 {
333 public:
334 MatrixDoubleBaseWidget(const VariantDataPtr& v)
335 {
336 auto l = new QVBoxLayout;
337 l->setContentsMargins(0, 0, 0, 0);
338 setLayout(l);
339 table = new QTableWidget;
340 l->addWidget(table);
341 update(v);
342 }
343
344 void
345 update(const VariantDataPtr& p) override
346 {
347 MatrixDoubleBasePtr v = MatrixDoubleBasePtr::dynamicCast(p);
349 table->setRowCount(v->rows);
350 table->setColumnCount(v->cols);
351 for (int row = 0; row < v->rows; ++row)
352 {
353 for (int col = 0; col < v->cols; ++col)
354 {
355 int i = row + col * v->rows;
356 table->setItem(row, col, new QTableWidgetItem{QString::number(v->data.at(i))});
357 }
358 }
359 }
360
361 private:
362 QTableWidget* table;
363 };
364
367
369 {
370 public:
371 MatrixFloatBaseWidget(const VariantDataPtr& v)
372 {
373 auto l = new QVBoxLayout;
374 l->setContentsMargins(0, 0, 0, 0);
375 setLayout(l);
376 table = new QTableWidget;
377 l->addWidget(table);
378 update(v);
379 }
380
381 void
382 update(const VariantDataPtr& p) override
383 {
384 MatrixFloatBasePtr v = MatrixFloatBasePtr::dynamicCast(p);
386 table->setRowCount(v->rows);
387 table->setColumnCount(v->cols);
388 for (int row = 0; row < v->rows; ++row)
389 {
390 for (int col = 0; col < v->cols; ++col)
391 {
392 int i = row + col * v->rows;
393 table->setItem(row, col, new QTableWidgetItem{QString::number(v->data.at(i))});
394 }
395 }
396 }
397
398 private:
399 QTableWidget* table;
400 };
401
404} // namespace armarx::VariantDataWidgets
405
406namespace armarx
407{
408 VariantWidget::VariantWidget(QWidget* parent) : QWidget{parent}
409 {
410 l = new QFormLayout;
411 setLayout(l);
412 reset();
413 }
414
415 void
416 VariantWidget::reset(Mode newMode)
417 {
418 if (mode != Mode::Empty)
419 {
420 //clear layout
421 while (QLayoutItem* item = l->takeAt(0))
422 {
423 QWidget* widget = item->widget();
424 if (widget)
425 {
426 widget->deleteLater();
427 }
428 delete item;
429 }
430 }
431 entries.clear();
432 mode = newMode;
433 if (mode == Mode::Map)
434 {
435 l->setHorizontalSpacing(6);
436 }
437 else
438 {
439 l->setHorizontalSpacing(0);
440 }
441 }
442
443 void
445 {
446 if (mode != Mode::SingleEntry)
447 {
448 reset(Mode::SingleEntry);
449 }
450 updateEntry("SingleEntry", v);
451 }
452
453 void
454 VariantWidget::update(const std::vector<VariantBasePtr>& vec)
455 {
456 if (mode != Mode::Vector)
457 {
458 reset(Mode::Vector);
459 }
460 for (std::size_t i = 0; i < vec.size(); ++i)
461 {
462 updateEntry(to_string(i), vec.at(i));
463 }
464 }
465
466 void
467 VariantWidget::update(const std::map<std::string, VariantBasePtr>& map)
468 {
469 if (mode != Mode::Map)
470 {
471 reset(Mode::Map);
472 }
473 for (const auto& entry : map)
474 {
475 updateEntry(entry.first, entry.second);
476 }
477 }
478
479 void
480 VariantWidget::updateEntry(const std::string& name, const VariantBasePtr& v)
481 {
482 ARMARX_CHECK_EXPRESSION(layout());
483 if (entries.count(name))
484 {
485 //there is an old entry
486 VariantDataWidgetBase* entryOld = entries.at(name);
487 if (!v || !v->data)
488 {
489 //there is no new entry -> delete old entry delete
490 if (mode == Mode::Map)
491 {
492 //remove the label
493 auto label = l->labelForField(entryOld);
494 l->removeWidget(label);
495 label->deleteLater();
496 }
497 l->removeWidget(entryOld);
498 entryOld->deleteLater();
499 entries.erase(name);
500 }
501 else
502 {
503 //update the entry
504 std::string type = v->data->ice_id();
505 if (entryOld->getTypeName() != type)
506 {
507 //other type -> exchange data widget
509 //new data widget
510 int row = getEntryRow(entryOld);
511 ARMARX_CHECK_EXPRESSION(row < l->rowCount());
512 ARMARX_CHECK_EXPRESSION(row >= 0);
513 l->removeWidget(entryOld);
514 entryOld->deleteLater();
515 l->setWidget(row, QFormLayout::FieldRole, entries[name]);
516 }
517 else
518 {
519 //same type -> update data widget
520 entryOld->update(v->data);
521 }
522 }
523 }
524 else
525 {
527 //add to layout
528 if (mode == Mode::Map)
529 {
530 l->addRow(QString::fromStdString(name), entries[name]);
531 }
532 else
533 {
534 l->addRow("", entries[name]);
535 }
536 }
537 }
538
539 int
540 VariantWidget::getEntryRow(VariantWidget::VariantDataWidgetBase* entry) const
541 {
542 //i need to find the correct row.
543 //there is no other way than iterating over the rows and check them
544 for (int row = 0; row < l->rowCount(); ++row)
545 {
546 QLayoutItem* it = l->itemAt(row, QFormLayout::FieldRole);
547 if (it && it->widget() == entry)
548 {
549 return row;
550 }
551 }
552 return -1;
553 }
554
557 {
558 class ErrorMessageWidget : public VariantDataWidgetBase
559 {
560 public:
561 ErrorMessageWidget(const std::string& errorMessage)
562 {
563 setLayout(new QVBoxLayout);
564 setTypeName(".ErrorMessageWidget");
565 layout()->setContentsMargins(0, 0, 0, 0);
566 QLabel* label = new QLabel{QString::fromStdString(errorMessage)};
567 layout()->addWidget(label);
568 label->setStyleSheet("QLabel { background-color : yellow; color : red; }");
569 }
570 };
571
572 if (!p)
573 {
574 return new ErrorMessageWidget{"Null VariantBasePtr"};
575 }
576 if (!p->data)
577 {
578 return new ErrorMessageWidget{"Null VariantBasePtr::data"};
579 }
580 auto type = p->data->ice_id();
582 {
583 try
584 {
586 w->setTypeName(type);
587 return w;
588 }
589 catch (std::exception& e)
590 {
591 return new ErrorMessageWidget{"VariantDataWidgetFactory for " + type +
592 " threw exception\n" + e.what()};
593 }
594 catch (...)
595 {
596 return new ErrorMessageWidget{"VariantDataWidgetFactory for " + type +
597 " threw exception"};
598 }
599 }
600 else
601 {
602 return new ErrorMessageWidget{"No VariantDataWidgetFactory for " + type};
603 }
604 return new ErrorMessageWidget{"makeVariantDataWidget: Unknown error"};
605 }
606} // namespace armarx
static const std::function< VariantDataWidgetBase *(const VariantDataPtr &)> & get(const std::string &key)
Definition Registrar.h:85
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
void update(const VariantDataPtr &p) override
virtual void setTypeName(const std::string &name)
VariantWidget(VariantPtr variant, QWidget *parent=0, Qt::WindowFlags f=0)
void update(const VariantBasePtr &v)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
VariantDataWidgetFactoryRegistration< StringVariantDataWidget > registerStringVariantDataWidget
VariantDataWidgetFactoryRegistration< MatrixFloatBaseWidget > registerMatrixFloatBaseWidget
VariantDataWidgetFactoryRegistration< TimestampBaseWidget > registerTimestampBaseWidget
VariantDataWidgetFactoryRegistration< IntVariantDataWidget > registerIntVariantDataWidget
VariantDataWidgetFactoryRegistration< DoubleVariantDataWidget > registerDoubleVariantDataWidget
VariantDataWidgetBase * makeVariantDataWidget(const VariantBasePtr &p)
VariantDataWidgetFactoryRegistration< MatrixDoubleBaseWidget > registerMatrixDoubleBaseWidget
VariantDataWidgetFactoryRegistration< FloatVariantDataWidget > registerFloatVariantDataWidget
VariantDataWidgetFactoryRegistration< LongVariantDataWidget > registerLongVariantDataWidget
VariantDataWidgetFactoryRegistration< ComplexDoubleBaseWidget > registerComplexDoubleBaseWidget
VariantDataWidgetFactoryRegistration< ComplexFloatBaseWidget > registerComplexFloatBaseWidget
VariantDataWidgetFactoryRegistration< BoolVariantDataWidget > registerBoolVariantDataWidget
double v(double t, double v0, double a0, double j)
Definition CtrlUtil.h:39
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::Handle<::armarx::VariantBase > VariantBasePtr
const std::string & to_string(const std::string &s)