36 #include "../StatechartViewerPlugin/view/StatechartView.h"
37 #include "../StatechartViewerPlugin/view/StateItem.h"
40 #include <ArmarXCore/interface/statechart/RemoteStateOffererIce.h>
42 #include <IceUtil/UUID.h>
44 #include <QCoreApplication>
45 #include <QInputDialog>
47 #include <QMessageBox>
50 #include <SimoxUtility/algorithm/string/string_tools.h>
62 setlocale(LC_ALL,
"C");
64 QSettings
s(
"KIT",
"ArmarXStatechartEditor");
80 QSettings
s(
"KIT",
"ArmarXStatechartEditor");
88 if (basePath.isEmpty())
96 for (std::filesystem::recursive_directory_iterator end, dir(basePath.toUtf8().data());
97 dir != end &&
getState() < eManagedIceObjectExiting; ++dir, i++)
99 std::string path(dir->path().c_str());
101 if (dir->path().extension() ==
".scgxml")
104 if (path.find(
"deprecated") != std::string::npos)
106 ARMARX_INFO <<
"Skipping deprecated Statechart Group " << path;
110 result << dir->path().c_str();
116 QCoreApplication::processEvents();
120 catch (std::exception& e)
136 QTimer::singleShot(0,
this, SLOT(initWidget()));
138 getArmarXManager()->addObject(stateWatcher,
"StateWatcher" + IceUtil::generateUUID(),
false);
147 if (executionStatusTask)
149 executionStatusTask->stop();
168 if (settings->contains(
"selectedProfile"))
170 config.
selectedProfile = profiles->getProfileByName(settings->value(
"selectedProfile").toString().toStdString());
215 if (node && node->getState())
217 int index = editor->getStateTabWidget()->getStateTab(node->getState());
218 getTipDialog()->showMessage(
"You can move states by holding the SHIFT + left click button. You can move the scene by holding ALT + move mouse.",
"State Interaction");
222 editor->getStateTabWidget()->addStateTab(node->getState());
226 editor->getStateTabWidget()->setCurrentIndex(index);
234 treeController->saveAll();
239 StatechartView* view = editor->getUI()->stateTabWidget->stateview(index);
243 treeController->selectNodeByState(view->
getStateInstance()->getStateClass());
251 QList<QString> selectedProxies;
255 if (d.exec() == QDialog::Accepted)
266 if (d.exec() == QDialog::Accepted)
285 editor->getUI()->treeViewProgressBar->show();
286 editor->getUI()->treeViewProgressBar->setMaximum(groups.size());
288 foreach (QString groupPath, groups)
290 treeController->onOpenGroup(groupPath);
291 editor->getUI()->treeViewProgressBar->setValue(i);
293 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
295 editor->getUI()->treeViewProgressBar->hide();
300 paths.removeDuplicates();
302 foreach (QString path, paths)
312 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
322 if (stateInstance && stateInstance->getStateClass())
324 StateTreeNodePtr node = treeController->getNodeByState(stateInstance->getStateClass());
328 std::string filePath = node->getBoostCppFilePath().c_str();
337 watcher->removePath(path);
338 std::string fileContent;
340 if (std::filesystem::exists(path.toUtf8().data()))
342 watcher->addPath(path);
347 fileContent =
"<cpp missing>";
350 int line = editor->getUI()->textEditCppCode->textCursor().blockNumber();
351 QTextCursor cursor = editor->getUI()->textEditCppCode->textCursor();
352 cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line);
353 editor->getUI()->textEditCppCode->setText(QString::fromUtf8(fileContent.c_str()));
354 editor->getUI()->textEditCppCode->setTextCursor(cursor);
361 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
362 editor->getUI()->textEditCppCode->find(
"::onEnter()", QTextDocument::FindBackward);
367 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
368 editor->getUI()->textEditCppCode->find(
"::run()", QTextDocument::FindBackward);
374 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
375 editor->getUI()->textEditCppCode->find(
"::onBreak()", QTextDocument::FindBackward);
381 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
382 editor->getUI()->textEditCppCode->find(
"::onExit()", QTextDocument::FindBackward);
390 if (editor->getUI()->stateTabWidget->currentStateview())
393 auto selection = editor->getUI()->stateTabWidget->currentStateview()->getScene()->selectedItems();
395 for (QGraphicsItem* item : selection)
418 auto node = treeController->getNodeByState(state);
420 if (node && node->isState())
422 treeController->openStateCPP(node);
434 editor->getStateTabWidget()->clear();
439 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
440 if (!executedOpenedGroup)
444 auto node = treeController->getNodeByState(view->
getStateInstance()->getStateClass());
447 if (node->isPublic())
449 treeController->executeGroupWithDependencies(node->getGroup(), view->
getStateInstance()->getStateClass()->getStateName());
450 executedOpenedGroup = node->getGroup();
451 editor->getUI()->toolButtonRunState->setIcon(QIcon(
":/icons/delete.ico"));
452 editor->getUI()->toolButtonRunState->setToolTip(
"Stop the Statechart Group");
453 editor->getUI()->toolButtonWatchStateExecution->setEnabled(
false);
454 editor->getUI()->labelExecutionState->setVisible(
true);
455 alreadyWatchingState =
false;
456 executionStatusTask->start();
460 QMessageBox::warning(editor,
"Execution not possible",
"You can only execute public state. Right-click on the state in the tree view on the left and select 'Public State'.");
466 QMessageBox::warning(editor,
"Execution not possible",
"You need to open a state before executing it with this button.");
471 if (executedOpenedGroup)
473 treeController->stopGroupExecutionWithDependencies(executedOpenedGroup);
474 executedOpenedGroup.reset();
475 executionStatusTask->stop();
476 editor->getUI()->labelExecutionState->setVisible(
false);
478 editor->getUI()->toolButtonRunState->setToolTip(
"Start the Statechart Group");
479 editor->getUI()->toolButtonRunState->setIcon(QIcon(
":/icons/run.svg"));
480 editor->getUI()->toolButtonWatchStateExecution->setEnabled(
true);
485 std::function<void(
StateItem* state)> unsubscriptionLamba;
486 unsubscriptionLamba = [&](
StateItem * state)
488 stateWatcher->unsubscribeState(state);
493 unsubscriptionLamba(stateInstance);
502 void StatechartEditorController::updateExecutionButtonStatus()
504 bool changeToWaiting =
false;
505 QString labelText =
"";
506 if (executedOpenedGroup)
508 std::string proxyName = executedOpenedGroup->getName().toStdString() +
"StateComponentAppManager";
509 std::string objName =
config.
selectedProfile->getName() + executedOpenedGroup->getName().toStdString() +
"RemoteStateOfferer";
510 ArmarXManagerInterfacePrx stateComponentProxy = getProxy<ArmarXManagerInterfacePrx>(proxyName,
false,
"",
false);
517 else if (stateComponentProxy)
519 auto state = stateComponentProxy->getObjectState(objName);
520 if (state != eManagedIceObjectStarted)
523 for (
auto elem : stateComponentProxy->getObjectConnectivity(objName).dependencies)
525 ManagedIceObjectDependencyBasePtr dep = elem.second;
526 if (!dep->getResolved())
528 if (deps.size() >= 2)
530 deps.push_back(
"...");
535 deps.push_back(dep->getName());
539 labelText =
"Waiting for dependencies: " + QString::fromStdString(simox::alg::join(deps,
", "));
540 changeToWaiting =
true;
545 labelText =
"Waiting for statechart group to start";
546 changeToWaiting =
true;
549 catch (
const Ice::Exception& e)
551 labelText =
"Waiting for statechart group to start (ice-exception catched)";
552 changeToWaiting =
true;
557 labelText =
"Waiting for statechart group to start (exception catched)";
558 changeToWaiting =
true;
561 if (!changeToWaiting)
563 labelText =
"Statechart group is running";
564 if (editor->getUI()->toolButtonWatchStateExecution->isChecked() && !alreadyWatchingState)
570 QMetaObject::invokeMethod(editor->getUI()->labelExecutionState,
"setText", Qt::QueuedConnection, Q_ARG(QString, labelText));
575 void StatechartEditorController::watchState(
const std::string& objName)
577 RemoteStateOffererInterfacePrx statechartHandler = getProxy<RemoteStateOffererInterfacePrx>(objName,
false,
"",
false);
579 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
582 std::string globalStateName =
"TopLevel->" + view->getStateInstance()->getStateClass()->getStateName().toStdString();
583 QMap<QString, StateInstanceData> instanceData = view->getScene()->getStateInstanceData();
584 auto toplevelPathString = view->getScene()->getTopLevelStateItem()->getFullStatePath();
585 auto asyncResult = statechartHandler->begin_getStatechartInstanceByGlobalIdStr(globalStateName);
586 while (!asyncResult->isCompleted())
588 if (
getState() >= eManagedIceObjectExiting)
595 armarx::StateIceBasePtr stateptr = statechartHandler->end_getStatechartInstanceByGlobalIdStr(asyncResult);
604 std::function<void(StateIceBasePtr iceState, StateItem* state)> subscriptionLamba;
605 subscriptionLamba = [&](StateIceBasePtr iceState, StateItem * state)
607 stateWatcher->subscribeToState(iceState, state);
609 for (
auto stateInstance : state->getSubstateItems())
611 if (stateInstance->getStateInstance()->getStateClass() && iceState->subStateList.size() > i)
613 subscriptionLamba(StateIceBasePtr::dynamicCast(iceState->subStateList.at(i)), stateInstance);
618 subscriptionLamba(stateptr, view->getScene()->getTopLevelStateItem());
620 alreadyWatchingState =
true;
633 return qobject_cast<QWidget*>(editor);
636 void StatechartEditorController::initWidget()
638 getWidget()->setFocusPolicy(Qt::WheelFocus);
649 editor->setVariantInfo(variantInfo);
651 editor->getUI()->toolBarViewControl->addWidget(
new QLabel(QString::fromStdString(
"Selected Profile: " +
config.
selectedProfile->getFullName())));
652 editor->getUI()->toolBarViewControl->insertWidget(editor->getUI()->actionEdit_State_Properties,
new QLabel(
"Active State:"));
654 QList<QVariant> header;
655 header.push_back(QString(
"TEST"));
659 QStringList searchPaths;
664 for (
const auto& includePath : CMakePackageFinder(package).getIncludePathList())
666 std::filesystem::path packageStatechartPath(includePath.c_str());
667 packageStatechartPath /= package;
668 packageStatechartPath /=
"statecharts";
670 if (std::filesystem::exists(packageStatechartPath)
671 && !std::filesystem::exists(packageStatechartPath /
"cmake_install.cmake"))
673 ARMARX_VERBOSE <<
"Adding statechart search path: " << packageStatechartPath.string();
674 searchPaths.push_back(packageStatechartPath.c_str());
685 connect(editor->getUI()->actionNew_State_Definition, SIGNAL(triggered()), treeController.get(), SLOT(onNewStateDefinition()));
686 connect(editor->getUI()->actionDelete_State_Definition, SIGNAL(triggered()), treeController.get(), SLOT(onDeleteNode()));
688 connect(editor->getUI()->actionSave_State, SIGNAL(triggered()), SLOT(
requestSave()));
689 connect(editor->getUI()->stateTabWidget, SIGNAL(currentChanged(
int)), SLOT(
onStateTabChanged(
int)));
691 connect(editor->getUI()->actionOpenStatechartGroup, SIGNAL(triggered()), treeController.get(), SLOT(onOpenGroup()));
693 connect(editor->getUI()->toolButtonRunState, SIGNAL(clicked(
bool)),
this, SLOT(
executeOpenedState(
bool)));
695 connect(treeController.get(), SIGNAL(closeAllTabsRequested()),
this, SLOT(
closeAllTabs()));
698 editor->getUI()->actionOpenStatechartGroup->setShortcutContext(Qt::WidgetWithChildrenShortcut);
699 editor->getUI()->actionOpenStatechartGroup->setShortcut(tr(
"Ctrl+O"));
700 getWidget()->addAction(editor->getUI()->actionOpenStatechartGroup);
705 connect(editor->getUI()->stateTabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(
connectToView(
int)), Qt::UniqueConnection);
706 connect(editor->getUI()->radioOnEnter, SIGNAL(clicked()),
this, SLOT(
showOnEnterFunction()), Qt::UniqueConnection);
707 connect(editor->getUI()->radioOnBreak, SIGNAL(clicked()),
this, SLOT(
showOnBreakFunction()), Qt::UniqueConnection);
708 connect(editor->getUI()->radioRun, SIGNAL(clicked()),
this, SLOT(
showRunFunction()), Qt::UniqueConnection);
709 connect(editor->getUI()->radioOnExit, SIGNAL(clicked()),
this, SLOT(
showOnExitFunction()), Qt::UniqueConnection);
712 connect(editor->getUI()->btnOpenCppCode, SIGNAL(clicked()),
this, SLOT(
openSelectedState()));
714 watcher =
new QFileSystemWatcher(editor);
720 treeController->collapseAll();
721 executionStatusTask =
new PeriodicTask<StatechartEditorController>(
this, &StatechartEditorController::updateExecutionButtonStatus, 300);
749 return qobject_cast<StatechartEditorConfigDialog*>(dialog);