30 #include <QHBoxLayout>
32 #include <QStringList>
49 #include <QMessageBox>
50 #include <QPushButton>
53 #include <QToolButton>
56 #include <QtWidgets/QSlider>
57 #include <QtWidgets/QTableWidgetItem>
59 #include <nlohmann/json.hpp>
61 static const std::string config_key_skilldashboard =
"skilldashboard";
62 static const std::string config_key_start_in =
"start_in";
68 addWidget<SkillDashboardWidget>();
73 DEFAULT_SETTINGS_CUSTOM_TEXT(
"custom text")
79 this->shortcutLayout =
new QVBoxLayout();
81 this->editModeAction =
new QAction(
"Edit Mode",
this);
82 this->editModeAction->setCheckable(
true);
83 this->editModeAction->setToolTip(
"If toggled the shortcut config buttons and the reload, "
84 "add and export button will be shown.");
86 connect(this->editModeAction, SIGNAL(toggled(
bool)),
this, SLOT(editMode(
bool)));
89 ui.addButton, &QPushButton::clicked,
this, [
this]() { openConfigWindow(
"",
"",
""); });
90 connect(
ui.reloadButton, &QPushButton::clicked,
this, &SkillDashboardWidget::loadButtons);
93 connect(
ui.exportButton, &QPushButton::clicked,
this, &SkillDashboardWidget::exportButtons);
98 &SkillDashboardWidget::activateButton);
100 connect(this->dialog,
103 &SkillDashboardWidget::onShortcutNameChanged);
105 this->editMode(
true);
114 if (not dashboardManagerName.empty())
122 if (not this->skillManagerOberserverName.empty())
136 this->connected.store(
true);
137 getProxy(this->dashboardPrx, this->dashboardManagerName);
138 getProxy(this->managerPrx, this->skillManagerOberserverName);
139 this->exampleTask = std::thread([&] { exampleThreadMethod(); });
144 SkillDashboardWidget::activateButton(
const std::string& name)
146 this->shortcutButtons.at(name)->setDisabled(
false);
150 SkillDashboardWidget::exampleThreadMethod()
152 while (this->connected.load())
154 if (not this->runningSkills.empty())
156 for (
auto it = this->runningSkills.cbegin(); it != this->runningSkills.cend();)
158 skills::core::dto::Execution::Status
status =
159 skills::core::dto::Execution::Status::Succeeded;
163 IceUtil::Optional<skills::manager::dto::SkillStatusUpdate>
update =
164 this->managerPrx->getSkillExecutionStatus(it->second);
170 catch (Ice::Exception
const&)
175 if (
status == skills::core::dto::Execution::Status::Succeeded ||
176 status == skills::core::dto::Execution::Status::Failed ||
177 status == skills::core::dto::Execution::Status::Aborted)
180 this->runningSkills.erase(it++);
192 SkillDashboardWidget::onShortcutNameChanged()
195 if ((this->shortcutButtons.find(this->dialog->getShortcutName().toStdString()) !=
196 this->shortcutButtons.end()) and
197 (this->dialog->
getShortcutName().toStdString() != this->currentShortcutName))
200 "A shortcut with this name already exists! The old one will be overwritten.");
202 <<
"A shortcut with this name already exists! The old one will be overwritten!";
211 SkillDashboardWidget::openConfigWindow(
const std::string& name,
212 const std::string&
id,
213 const std::string& args)
221 if (this->dialog->exec() == QDialog::Accepted)
225 SkillShortcut newShortcut{
227 .skillId = this->dialog->
getSkillId().toStdString(),
229 this->dashboardPrx->addNewShortcut(newShortcut);
231 catch (Ice::Exception
const&)
242 auto now = std::chrono::system_clock::now();
243 std::time_t now_c = std::chrono::system_clock::to_time_t(now);
245 localtime_r(&now_c, &local_tm);
246 std::ostringstream oss;
247 oss << std::put_time(&local_tm,
"%Y-%m-%d_%H-%M-%S");
252 SkillDashboardWidget::exportButtons()
254 std::vector<SkillShortcut> shortcuts;
257 shortcuts = this->dashboardPrx->getShortcuts();
259 catch (Ice::Exception
const&)
265 for (
const auto& shortcut : shortcuts)
267 nlohmann::json skillArgs_json = nlohmann::json::parse(shortcut.skillArgs);
269 j[
"shortcuts"].push_back({{
"skill_shortcut_name", shortcut.shortcutName},
270 {
"skill_id", shortcut.skillId},
271 {
"skill_args", skillArgs_json}});
274 std::string packageName =
ui.packageEdit->text().toStdString();
275 std::string folderName =
ui.folderEdit->text().toStdString();
276 std::string fileName =
ui.fileNameEdit->text().toStdString();
278 size_t pos = fileName.find(
"%TIMESTAMP%");
279 if (pos != std::string::npos)
285 std::string absoluteFilename;
287 if (finder.packageFound())
291 std::string packageDataDir = finder.getDataDir();
295 std::filesystem::create_directory(packageDataDir +
"/" + folderName);
297 std::string relativeFilename(folderName);
301 ARMARX_INFO <<
"Located file at:" << absoluteFilename;
302 std::string
filename = fileName +
".json";
303 std::ofstream outFile(absoluteFilename +
"/" +
filename);
304 outFile << std::setw(4) << j << std::endl;
312 SkillDashboardWidget::loadButtons()
314 this->shortcutButtons.clear();
315 this->configButtons.clear();
316 this->deleteButtons.clear();
317 std::vector<SkillShortcut> shortcuts;
320 shortcuts = this->dashboardPrx->getShortcuts();
322 catch (Ice::Exception
const&)
326 clearLayout(this->shortcutLayout);
328 QLayout* existingLayout = container->layout();
330 for (SkillShortcut& shortcut : shortcuts)
332 QPushButton* button =
new QPushButton(QString::fromStdString(shortcut.shortcutName));
333 button->setStyleSheet(
"padding-right: 30px;");
336 QToolButton* configButton =
new QToolButton();
338 getWidget()->style()->standardIcon(QStyle::SP_FileDialogContentsView);
339 configButton->setIcon(iconConfig);
340 configButton->setToolTip(
"Settings");
343 QToolButton* deleteButton =
new QToolButton();
344 QIcon iconDelete =
getWidget()->style()->standardIcon(QStyle::QStyle::SP_TrashIcon);
345 deleteButton->setIcon(iconDelete);
346 deleteButton->setToolTip(
"Delete");
349 QHBoxLayout* buttonLayout =
new QHBoxLayout(button);
350 buttonLayout->setContentsMargins(0, 0, 0, 0);
351 buttonLayout->addStretch();
352 buttonLayout->addWidget(configButton);
353 buttonLayout->addWidget(deleteButton);
356 this->shortcutLayout->addWidget(button);
357 if (QVBoxLayout* hLayout = qobject_cast<QVBoxLayout*>(existingLayout))
359 hLayout->addLayout(this->shortcutLayout);
362 this->shortcutButtons[shortcut.shortcutName] = button;
363 this->deleteButtons[shortcut.shortcutName] = deleteButton;
364 this->configButtons[shortcut.shortcutName] = configButton;
367 &QPushButton::clicked,
369 [
this, name = shortcut.shortcutName]() { executeSkill(name); });
370 connect(configButton,
371 &QToolButton::clicked,
373 [
this, name = shortcut.shortcutName]() { editShortcut(name); });
375 connect(deleteButton,
376 &QToolButton::clicked,
378 [
this, name = shortcut.shortcutName]() { deleteShortcut(name); });
383 SkillDashboardWidget::executeSkill(
const std::string& name)
385 SkillShortcut shortcut;
388 shortcut = this->dashboardPrx->getShortcut(name);
390 catch (Ice::Exception
const&)
395 size_t pos = shortcut.skillId.find(
'/');
396 std::string provider =
"";
397 std::string nameSkill =
"";
398 nlohmann::json json = nlohmann::json::parse(shortcut.skillArgs);
403 if (pos != std::string::npos)
405 provider = shortcut.skillId.substr(0, pos);
406 nameSkill = shortcut.skillId.substr(pos + 1);
407 skills::manager::dto::ProviderID providerId{.providerName = provider};
409 skills::manager::dto::SkillID skillId{.providerId = providerId, .skillName = nameSkill};
411 char hostname[HOST_NAME_MAX];
412 gethostname(hostname, HOST_NAME_MAX);
414 skills::manager::dto::SkillExecutionRequest request{
416 .executorName =
"Skills.Dashboard GUI (hostname: " + std::string(hostname) +
")",
417 .parameters = paramterDto};
421 skills::manager::dto::SkillExecutionID executionId =
422 this->managerPrx->executeSkillAsync(request);
423 this->runningSkills[shortcut.shortcutName] = executionId;
424 this->shortcutButtons.at(shortcut.shortcutName)->setDisabled(
true);
426 catch (Ice::Exception
const&)
438 SkillDashboardWidget::editShortcut(
const std::string& name)
440 this->currentShortcutName = name;
442 SkillShortcut shortcut;
445 shortcut = this->dashboardPrx->getShortcut(name);
447 catch (Ice::Exception
const&)
451 openConfigWindow(shortcut.shortcutName, shortcut.skillId, shortcut.skillArgs);
452 this->currentShortcutName =
"not set";
456 SkillDashboardWidget::deleteShortcut(
const std::string& name)
461 this->dashboardPrx->deleteShortcut(name);
464 catch (Ice::Exception
const&)
472 SkillDashboardWidget::clearLayout(QLayout* layout)
477 while (QLayoutItem* item = layout->takeAt(0))
479 if (QWidget* widget = item->widget())
481 widget->deleteLater();
483 else if (QLayout* subLayout = item->layout())
485 clearLayout(subLayout);
496 if (parent != customToolbar->parent())
498 customToolbar->setParent(parent);
501 return customToolbar.data();
504 customToolbar =
new QToolBar(parent);
505 customToolbar->setIconSize(QSize(16, 16));
506 customToolbar->addAction(editModeAction);
508 return customToolbar.data();
512 SkillDashboardWidget::editMode(
bool edit)
516 for (
const auto& button : this->deleteButtons)
518 button.second->setVisible(
true);
520 for (
const auto& button : this->configButtons)
522 button.second->setVisible(
true);
524 ui.addButton->setVisible(
true);
525 ui.reloadButton->setVisible(
true);
526 ui.exportButton->setVisible(
true);
530 for (
const auto& button : this->deleteButtons)
532 button.second->setVisible(
false);
534 for (
const auto& button : this->configButtons)
536 button.second->setVisible(
false);
538 ui.addButton->setVisible(
false);
539 ui.reloadButton->setVisible(
false);
540 ui.exportButton->setVisible(
false);
547 this->connected.store(
false);
548 this->exampleTask.join();
561 if (not m_config_dialog)
565 {::config_key_skilldashboard,
"SkillDashboard",
"*"});
566 m_config_dialog->addProxyFinder<skills::manager::dti::SkillManagerInterfacePrx>(
567 "SkillMemory",
"",
"SkillMem*");
569 return qobject_cast<QDialog*>(m_config_dialog);
576 dashboardManagerName = settings
577 ->value(QString::fromStdString(::config_key_skilldashboard),
578 "SkillDashboardInterface")
581 this->skillManagerOberserverName =
582 settings->value(
"SkillMemory",
"SkillMemory").toString().toStdString();
589 settings->setValue(QString::fromStdString(::config_key_skilldashboard),
590 QString::fromStdString(dashboardManagerName));
591 settings->setValue(
"SkillMemory", QString::fromStdString(this->skillManagerOberserverName));
600 this->dashboardManagerName = m_config_dialog->getProxyName(::config_key_skilldashboard);
601 this->skillManagerOberserverName = m_config_dialog->getProxyName(
"SkillMemory");