25 #include <QGridLayout>
27 #include <QScrollArea>
28 #include <QSpacerItem>
29 #include <QStyledItemDelegate>
42 while ((item = layout->takeAt(0)))
47 delete item->layout();
51 delete item->widget();
60 const char*
const REMOTE_TAB_ID =
"remote.tab_id";
61 const char*
const REMOTE_WIDGET_NAME =
"remote.widget_name";
63 struct InternalUpdateGuard
70 ~InternalUpdateGuard()
82 widget.remoteTabWidget->clear();
84 widget.comboBoxTabGroups->setVisible(
false);
85 widget.comboBoxTabGroups->addItem(groupAll);
86 widget.comboBoxTabGroups->addItem(groupUngrouped);
88 connect(widget.sendRemoteValuesButton,
89 &QPushButton::clicked,
92 connect(widget.checkBoxGroupTabs,
96 connect(widget.comboBoxTabGroups,
97 QOverload<const QString&>::of(&QComboBox::currentIndexChanged),
105 Qt::QueuedConnection);
110 Qt::QueuedConnection);
115 Qt::QueuedConnection);
120 Qt::QueuedConnection);
122 widget.comboBoxTabGroups->setCurrentIndex(0);
135 dialog->addProxyFinder<RemoteGuiInterfacePrx>({
"RemoteGuiProvider",
"",
"RemoteGui*"});
137 return qobject_cast<SimpleConfigDialog*>(dialog);
143 remoteGuiProviderName = dialog->getProxyName(
"RemoteGuiProvider");
149 remoteGuiProviderName =
150 settings->value(
"remoteGuiProviderName",
"RemoteGuiProvider").toString().toStdString();
156 settings->setValue(
"remoteGuiProviderName", QString::fromStdString(remoteGuiProviderName));
168 remoteGuiProvider = getProxy<RemoteGuiInterfacePrx>(remoteGuiProviderName);
172 std::unique_lock<std::mutex> lock(stateMutex);
173 tabs = remoteGuiProvider->getTabs();
174 tabWidgetStates = remoteGuiProvider->getTabStates();
175 tabValueMap = remoteGuiProvider->getValuesForAllTabs();
182 usingTopic(remoteGuiProvider->getTopicName());
189 std::unique_lock<std::mutex> lock(stateMutex);
190 tabs = remoteGuiProvider->getTabs();
191 tabWidgetStates = remoteGuiProvider->getTabStates();
192 tabValueMap = remoteGuiProvider->getValuesForAllTabs();
194 QString qTabId = QString::fromStdString(tab);
203 std::unique_lock<std::mutex> lock(stateMutex);
204 tabs = remoteGuiProvider->getTabs();
205 tabWidgetStates = remoteGuiProvider->getTabStates();
206 tabValueMap = remoteGuiProvider->getValuesForAllTabs();
213 const RemoteGui::WidgetStateMap& widgetState,
217 std::unique_lock<std::mutex> lock(stateMutex);
218 tabWidgetStates[tab] = widgetState;
220 QString qTabId = QString::fromStdString(tab);
230 std::unique_lock<std::mutex> lock(stateMutex);
231 for (
const auto& pair : delta)
233 tabValueMap[tab][pair.first] = pair.second;
234 tabDirtyMap[tab][pair.first] = pair.second;
237 QString qTabId = QString::fromStdString(tab);
247 std::unique_lock<std::mutex> lock(stateMutex);
252 removeObsoleteTabs();
258 std::unique_lock<std::mutex> lock(stateMutex);
261 for (
auto& tabWidget : tabs)
263 QString qid = QString::fromStdString(tabWidget.first);
269 removeObsoleteTabs();
278 std::unique_lock<std::mutex> lock(stateMutex);
299 QWidget* widget = qobject_cast<QWidget*>(sender());
302 ARMARX_WARNING <<
"Expected a widget as sender of onGuiStateChanged()";
306 std::string
id = widget->property(REMOTE_TAB_ID).toString().toStdString();
307 std::string name = widget->property(REMOTE_WIDGET_NAME).toString().toStdString();
309 std::unique_lock<std::mutex> lock(stateMutex);
324 RemoteGui::ValueVariant& currentValue = tabValueMap.at(
id).at(name);
328 RemoteGui::ValueVariant newValue = widgetHandler.
handleGuiChange(*desc, widget);
330 if (newValue != currentValue)
332 currentValue = newValue;
340 const int index = widget.remoteTabWidget->currentIndex();
341 QString currentTabText = widget.remoteTabWidget->tabText(
index);
344 remoteGuiProvider->setValues(tabId, tabValueMap[tabId]);
348 RemoteGuiWidgetController::createTab(std::string
const& tabId)
353 ARMARX_INFO <<
"Updating GUI for tab '" << tabId <<
"'";
356 QString qTabId = QString::fromStdString(tabId);
357 QWidget* tabHolder =
nullptr;
358 for (
const auto& pair : qtTabs)
360 TabData
const&
data = pair.second;
361 if (
data.fullName() == tabId)
367 QGridLayout* layout =
nullptr;
371 QScrollArea* scrollArea = qobject_cast<QScrollArea*>(tabHolder);
372 if (scrollArea && scrollArea->widget())
374 layout = qobject_cast<QGridLayout*>(scrollArea->widget()->layout());
384 QScrollArea* scrollArea =
new QScrollArea(widget.remoteTabWidget);
385 scrollArea->setObjectName(qTabId);
386 scrollArea->setWidgetResizable(
true);
387 layout =
new QGridLayout(scrollArea);
388 layout->setContentsMargins(0, 0, 0, 0);
389 QWidget* scrollAreaWidgetContents =
new QWidget;
390 scrollArea->setWidget(scrollAreaWidgetContents);
391 scrollAreaWidgetContents->setLayout(layout);
392 tabHolder = scrollArea;
395 auto&
data = qtTabs[tabId];
399 const auto fname =
data.fullName();
400 std::size_t idx = fname.find(
'_');
401 while (idx != std::string::npos)
403 data.groups.emplace(fname.substr(0, idx));
404 idx = fname.find(
'_', idx + 1);
408 if (activeGroup == groupAll || (
data.groups.empty() && activeGroup == groupUngrouped))
411 widget.remoteTabWidget->addTab(tabHolder, qTabId);
413 else if (
data.groups.count(activeGroup))
415 widget.remoteTabWidget->addTab(tabHolder,
416 QString::fromStdString(
data.name(activeGroup)));
419 for (
const auto& group :
data.groups)
421 if (tabsPerGroup.count(group))
423 ++tabsPerGroup.at(group);
427 tabsPerGroup[group] = 1;
428 const auto box = widget.comboBoxTabGroups;
429 box->blockSignals(
true);
430 box->addItem(QString::fromStdString(group));
431 box->blockSignals(
false);
438 guiWidgets[tabId].clear();
439 QWidget* newTab = createWidgetFromDescription(tabId, widgetP);
441 newTab->setParent(tabHolder);
442 layout->addWidget(newTab, 0, 0);
443 layout->addItem(
new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding), 1, 1);
444 layout->addItem(
new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 1);
448 RemoteGuiWidgetController::removeObsoleteTabs()
450 for (
auto iter = qtTabs.begin(); iter != qtTabs.end();)
452 std::string
const& tabId = iter->first;
453 TabData
const&
data = iter->second;
455 if (tabs.count(tabId) > 0)
462 QString qTabId = QString::fromStdString(tabId);
464 QWidget* tabHolder =
data.w;
465 tabHolder->deleteLater();
466 QTabWidget* tab = widget.remoteTabWidget;
467 int i =
data.findTabIndex(tab);
473 for (
const std::string& group :
data.groups)
475 std::size_t& tabCount = tabsPerGroup.at(group);
479 tabsPerGroup.erase(group);
480 QComboBox* box = widget.comboBoxTabGroups;
481 int boxIdx = box->findText(QString::fromStdString(group));
485 box->blockSignals(
true);
486 box->setCurrentIndex(0);
487 box->removeItem(boxIdx);
488 box->blockSignals(
false);
491 box->setCurrentIndex(0);
495 iter = qtTabs.erase(iter);
496 guiWidgets.erase(tabId);
503 RemoteGuiWidgetController::updateWidgets(std::string
const& tabId)
506 RemoteGui::WidgetStateMap
const& states = tabWidgetStates.at(tabId);
507 std::map<std::string, QWidget*>
const& widgets = guiWidgets.at(tabId);
509 for (
auto& nameState : states)
511 std::string
const& name = nameState.first;
512 RemoteGui::WidgetState
const& state = nameState.second;
513 QWidget* widget = widgets.at(name);
515 widget->setHidden(state.hidden);
516 widget->setDisabled(state.disabled);
521 RemoteGuiWidgetController::updateState(std::string
const& tabId)
524 std::unique_lock<std::mutex> lock(stateMutex);
527 InternalUpdateGuard guard(&internalUpdate);
530 std::map<std::string, QWidget*>
const& widgets = guiWidgets.at(tabId);
531 RemoteGui::WidgetMap
const& widgetDesc = guiDescriptions.at(tabId);
535 std::string
const& name = pair.first;
536 RemoteGui::ValueVariant
const&
value = pair.second;
538 QWidget* widget = widgets.at(name);
541 widgetHandler.updateGui(*desc, widget,
value);
543 tabDirtyMap.at(tabId).clear();
547 setNameProp(QWidget* w, QString
const& name, QString
const&
id)
549 if (w->property(REMOTE_WIDGET_NAME).toString() ==
"")
551 w->setProperty(REMOTE_WIDGET_NAME, name);
552 w->setProperty(REMOTE_TAB_ID,
id);
553 for (
auto child : w->findChildren<QWidget*>(QString{}, Qt::FindDirectChildrenOnly))
555 setNameProp(child, name,
id);
561 RemoteGuiWidgetController::createWidgetFromDescription(
const std::string& tabId,
565 QWidget* widget =
nullptr;
568 bool useDefaultValue =
values.count(desc->name) == 0;
569 RemoteGui::ValueVariant
const& initialValue =
570 useDefaultValue ? desc->defaultValue :
values[desc->name];
576 return this->createWidgetFromDescription(tabId, desc);
582 InternalUpdateGuard guard(&internalUpdate);
585 widget = widgetHandler.createWidget(
591 setNameProp(widget, QString::fromStdString(desc->name), QString::fromStdString(tabId));
594 if (!desc->name.empty())
597 auto result = guiWidgets[tabId].emplace(desc->name, widget);
598 bool inserted = result.second;
601 guiDescriptions[tabId][desc->name] = desc;
602 values[desc->name] = initialValue;
607 ARMARX_WARNING <<
"Tried to add a widget with duplicate name '" << desc->name
608 <<
"' to remote tab ID '" << tabId <<
"'";
618 widget.widgetTopBar->setVisible(
false);
619 widget.remoteTabWidget->tabBar()->setVisible(
false);
625 widget.widgetTopBar->setVisible(
true);
626 widget.remoteTabWidget->tabBar()->setVisible(
true);
630 RemoteGuiWidgetController::doAutoUpdate(std::string
const&
id)
632 if (widget.autoUpdateCheckBox->checkState() == Qt::Checked)
634 remoteGuiProvider->setValues(
id, tabValueMap[
id]);
641 widget.comboBoxTabGroups->setEnabled(checked);
642 widget.comboBoxTabGroups->setVisible(checked);
643 widget.comboBoxTabGroups->setCurrentIndex(0);
649 activeGroup = group.toStdString();
650 auto tab = widget.remoteTabWidget;
657 for (
const auto& pair : qtTabs)
659 TabData
const&
data = pair.second;
661 if (activeGroup == groupAll || (
data.groups.empty() && activeGroup == groupUngrouped))
664 tab->addTab(
data.w, QString::fromStdString(
data.fullName()));
666 else if (!
data.groups.empty() &&
data.groups.count(activeGroup))
668 tab->addTab(
data.w, QString::fromStdString(
data.name(activeGroup)));
674 RemoteGuiWidgetController::TabData::fullName()
const
676 return w->objectName().toStdString();
680 RemoteGuiWidgetController::TabData::name(
const std::string& pre)
const
682 return fullName().substr(pre.size() + 1);
686 RemoteGuiWidgetController::TabData::findTabIndex(QTabWidget* tab)
const
688 for (
auto idx = 0; idx < tab->count(); ++idx)
690 if (w == tab->widget(idx))