14#include <QTreeWidgetItem>
39 ARMARX_INFO <<
"The execution has no parameters to copy.";
44 QApplication::clipboard()->setText(QString::fromStdString(json.dump(2)));
49 SkillExecutionTreeWidget::runContextMenu(
const QPoint& pos)
54 QMenu* menu =
new QMenu();
57 QAction* stopSkillAction =
new QAction(
"Stop execution",
this);
58 const auto& executions =
memory->getExecutions();
59 if (executions.count(selectedExecution.skillExecutionId) == 0)
62 memory->getExecutions().at(selectedExecution.skillExecutionId).status;
67 QAction* rerunSkillAction =
new QAction(
"Re-execute with similar parameters",
this);
68 QAction* copyParametersAction =
new QAction(
"Copy parameters to clipboard",
this);
69 QAction* showDetailsAction =
new QAction(
"Show Execution Details",
this);
70 menu->addAction(stopSkillAction);
71 menu->addAction(rerunSkillAction);
72 menu->addAction(copyParametersAction);
73 menu->addAction(showDetailsAction);
74 connect(stopSkillAction,
77 &SkillExecutionTreeWidget::stopSelectedExecution);
78 connect(rerunSkillAction,
81 &SkillExecutionTreeWidget::rerunSkillWithSimilarParams);
82 connect(copyParametersAction,
85 &SkillExecutionTreeWidget::copyParametersToClipboard);
86 connect(showDetailsAction,
89 &SkillExecutionTreeWidget::showExecutionDetails);
92 menu->popup(this->viewport()->mapToGlobal(pos));
96 SkillExecutionTreeWidget::stopSelectedExecution()
98 if (!selectionValid())
100 memory->stopExecution(this->selectedExecution.skillExecutionId);
104 SkillExecutionTreeWidget::rerunSkillWithSimilarParams()
106 if (!selectionValid())
109 skills::SkillExecutionID currentExecutionId = this->selectedExecution.skillExecutionId;
110 auto executions =
memory->getExecutions();
111 if (executions.empty())
114 if (executions.count(currentExecutionId) == 0)
117 ARMARX_IMPORTANT <<
"The selected execution was not found in memory. The GUI is unable "
118 "to determine the parametrization for this execution.";
121 auto params = executions[currentExecutionId].parameters;
123 ARMARX_INFO <<
"Re-executing the skill " << currentExecutionId.skillId
124 <<
" with previous parameters.";
127 this->
memory->startExecutionWithParams(currentExecutionId.skillId, params);
131 SkillExecutionTreeWidget::copyParametersToClipboard()
133 if (!selectionValid())
136 auto executions =
memory->getExecutions();
137 auto executionIt = executions.find(selectedExecution.skillExecutionId);
138 if (executionIt == executions.end())
140 ARMARX_IMPORTANT <<
"The selected execution was not found in memory. The GUI is unable "
141 "to determine the parametrization for this execution.";
144 copyParametersJsonToClipboard(executionIt->second.parameters);
148 SkillExecutionTreeWidget::showExecutionDetails()
150 if (!selectionValid())
153 skills::SkillExecutionID executionId = this->selectedExecution.skillExecutionId;
154 auto executions =
memory->getExecutions();
155 if (executions.count(executionId) == 0)
157 ARMARX_IMPORTANT <<
"The selected execution was not found in memory. The GUI is unable "
158 "to determine the details for this execution.";
161 const auto&
update = executions.at(executionId);
163 std::string statusStr =
"Unknown";
164 for (
const auto& [
status, name] : EXECUTION_STATUS_TO_STRING)
172 auto* dialog =
new QDialog(
this);
173 dialog->setAttribute(Qt::WA_DeleteOnClose);
174 dialog->setWindowTitle(
"Execution Details");
175 dialog->resize(600, 500);
177 auto* layout =
new QVBoxLayout(dialog);
178 auto* infoLayout =
new QFormLayout();
179 infoLayout->addRow(
"Skill:",
180 new QLabel(QString::fromStdString(executionId.skillId.toString())));
181 infoLayout->addRow(
"Executor:",
182 new QLabel(QString::fromStdString(executionId.executorName)));
185 new QLabel(QString::fromStdString(executionId.executionStartedTime.toDateTimeString())));
186 infoLayout->addRow(
"Status:",
new QLabel(QString::fromStdString(statusStr)));
187 layout->addLayout(infoLayout);
191 std::optional<skills::SkillDescription> description;
192 if (executionId.skillId.providerId.has_value())
194 const auto skillsMap =
memory->getSkills();
195 auto providerIt = skillsMap.find(executionId.skillId.providerId.value());
196 if (providerIt != skillsMap.end())
198 auto skillIt = providerIt->second.find(executionId.skillId);
199 if (skillIt != providerIt->second.end())
201 description = skillIt->second;
208 const auto makeAronTree = [dialog](
const std::string& title,
213 auto* tree =
new QTreeWidget(dialog);
214 tree->setColumnCount(3);
215 tree->setHeaderLabels({
"Key",
"Value",
"Type"});
217 auto* rootItem =
new QTreeWidgetItem(tree);
218 rootItem->setText(0, QString::fromStdString(title));
220 auto* controller =
new AronTreeWidgetController(tree, rootItem, type, data);
226 std::function<void(QTreeWidgetItem*)> showEnumNames = [&](QTreeWidgetItem* item)
232 if (enumType && enumWidget)
234 const std::string text = enumWidget->getText().toStdString();
235 QString display = QString::fromStdString(text);
236 for (
const auto& [name, value] : enumType->getAcceptedValueMap())
238 if (name == text || std::to_string(value) == text)
240 display = QString::fromStdString(name +
" (" +
241 std::to_string(value) +
")");
245 tree->removeItemWidget(item, 1);
246 item->setText(1, display);
249 for (
int i = 0; i < item->childCount(); ++i)
251 showEnumNames(item->child(i));
254 showEnumNames(rootItem);
258 const auto markChanged = [](QTreeWidgetItem* item)
260 const QBrush highlight(QColor(255, 200, 100, 90));
261 QFont font = item->font(0);
263 for (
int column = 0; column < 3; ++column)
265 item->setBackground(column, highlight);
266 item->setToolTip(column,
267 "This value differs from the profile default, i.e. it "
268 "was actively set for this execution.");
270 item->setFont(0, font);
274 const auto markContainsChange = [](QTreeWidgetItem* item)
276 QFont font = item->font(0);
278 item->setFont(0, font);
283 std::function<bool(QTreeWidgetItem*,
286 markDifferences = [&](QTreeWidgetItem* item,
290 if (!value && !defaultValue)
294 if (!value || !defaultValue)
309 bool anyChildChanged =
false;
310 for (
int i = 0; i < item->childCount(); ++i)
312 QTreeWidgetItem* childItem = item->child(i);
313 const std::string key = childItem->text(0).toStdString();
314 const auto childValue =
315 valueDict->hasElement(key) ? valueDict->getElement(key) :
nullptr;
316 const auto childDefault = defaultDict->hasElement(key)
317 ? defaultDict->getElement(key)
319 anyChildChanged |= markDifferences(childItem, childValue, childDefault);
323 markContainsChange(item);
325 return anyChildChanged;
336 const auto valueElements = valueList->getElements();
337 const auto defaultElements = defaultList->getElements();
338 bool anyChildChanged =
false;
339 for (
int i = 0; i < item->childCount(); ++i)
341 QTreeWidgetItem* childItem = item->child(i);
342 const auto childValue =
static_cast<size_t>(i) < valueElements.size()
345 const auto childDefault =
static_cast<size_t>(i) < defaultElements.size()
348 anyChildChanged |= markDifferences(childItem, childValue, childDefault);
350 if (valueElements.size() != defaultElements.size())
354 anyChildChanged =
true;
356 else if (anyChildChanged)
358 markContainsChange(item);
360 return anyChildChanged;
381 if (data && defaults)
383 if (QTreeWidgetItem* objectItem = rootItem->child(0))
385 markDifferences(objectItem, data, defaults);
389 tree->setEditTriggers(QAbstractItemView::NoEditTriggers);
390 std::function<void(QTreeWidgetItem*)> makeReadOnly =
391 [&](QTreeWidgetItem* item)
393 item->setFlags(item->flags() & ~Qt::ItemIsEditable);
394 if (QWidget* itemWidget = tree->itemWidget(item, 1))
396 itemWidget->setEnabled(
false);
398 for (
int i = 0; i < item->childCount(); ++i)
400 makeReadOnly(item->child(i));
403 makeReadOnly(rootItem);
406 tree->resizeColumnToContents(0);
410 if (description.has_value())
412 layout->addWidget(makeAronTree(
"Parameters",
413 description->parametersType,
415 description->rootProfileDefaults));
420 makeAronTree(
"Result", description->resultType,
update.result,
nullptr));
426 new QLabel(
"The skill description is no longer available; the parameters "
427 "cannot be displayed."));
430 auto* copyButton =
new QPushButton(
"Copy parameters to clipboard", dialog);
432 &QPushButton::clicked,
433 [parameters =
update.parameters]() { copyParametersJsonToClipboard(parameters); });
434 layout->addWidget(copyButton);
447 SkillExecutionTreeWidget::setupUi()
449 this->setColumnCount(6);
451 this->setContextMenuPolicy(Qt::CustomContextMenu);
453 QTreeWidgetItem* qtreewidgetitem = this->headerItem();
454 qtreewidgetitem->setText(5,
"");
455 qtreewidgetitem->setText(4,
"");
456 qtreewidgetitem->setText(3,
"Status");
457 qtreewidgetitem->setText(2,
"SkillID");
458 qtreewidgetitem->setText(1,
"Executor");
459 qtreewidgetitem->setText(0,
"Timestamp");
461 this->setColumnWidth(4, 30);
467 SkillExecutionTreeWidget::connectSignals()
470 &QTreeWidget::customContextMenuRequested,
472 &SkillExecutionTreeWidget::runContextMenu);
474 &QTreeWidget::currentItemChanged,
476 &SkillExecutionTreeWidget::executionSelectionChanged);
480 SkillExecutionTreeWidget::selectionValid()
486 SkillExecutionTreeWidget::executionSelectionChanged(QTreeWidgetItem* current,
487 QTreeWidgetItem* previous)
490 SkillExecutionTreeWidgetItem* selected =
491 dynamic_cast<SkillExecutionTreeWidgetItem*
>(current);
501 if (update.statuses.empty())
506 for (
const auto& [k, v] : update.statuses)
512 for (
int i = 0; i < this->topLevelItemCount(); ++i)
536 item->updateItem(statusUpdate.
status);
static nlohmann::json ConvertToNlohmannJSON(const data::VariantPtr &)
static PointerType DynamicCast(const VariantPtr &n)
static DerivedT & DynamicCast(Variant &n)
static const constexpr char * UNKNOWN
std::shared_ptr< SkillManagerWrapper > memory
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
std::shared_ptr< Dict > DictPtr
std::shared_ptr< Variant > VariantPtr
std::shared_ptr< Object > ObjectPtr
std::shared_ptr< Value > value()
bool equal(const std::string &a, const std::string &b)