26 #include <QCoreApplication>
27 #include <QInputDialog>
29 #include <QMessageBox>
36 #include <IceUtil/UUID.h>
38 #include <SimoxUtility/algorithm/string/string_tools.h>
42 #include <ArmarXCore/interface/statechart/RemoteStateOffererIce.h>
47 #include "../StatechartViewerPlugin/view/StateItem.h"
48 #include "../StatechartViewerPlugin/view/StatechartView.h"
64 setlocale(LC_ALL,
"C");
66 QSettings
s(
"KIT",
"ArmarXStatechartEditor");
80 QSettings
s(
"KIT",
"ArmarXStatechartEditor");
89 if (basePath.isEmpty())
97 for (std::filesystem::recursive_directory_iterator end, dir(basePath.toUtf8().data());
98 dir != end &&
getState() < eManagedIceObjectExiting;
101 std::string path(dir->path().c_str());
103 if (dir->path().extension() ==
".scgxml")
106 if (path.find(
"deprecated") != std::string::npos)
108 ARMARX_INFO <<
"Skipping deprecated Statechart Group " << path;
112 result << dir->path().c_str();
118 QCoreApplication::processEvents();
122 catch (std::exception& e)
139 QTimer::singleShot(0,
this, SLOT(initWidget()));
142 stateWatcher,
"StateWatcher" + IceUtil::generateUUID(),
false);
153 if (executionStatusTask)
155 executionStatusTask->stop();
176 if (settings->contains(
"selectedProfile"))
179 settings->value(
"selectedProfile").toString().toStdString());
213 settings->setValue(
"selectedProfile",
225 if (node && node->getState())
227 int index = editor->getStateTabWidget()->getStateTab(node->getState());
229 "You can move states by holding the SHIFT + left click button. You can move the "
230 "scene by holding ALT + move mouse.",
231 "State Interaction");
235 editor->getStateTabWidget()->addStateTab(node->getState());
239 editor->getStateTabWidget()->setCurrentIndex(
index);
247 treeController->saveAll();
257 treeController->selectNodeByState(view->
getStateInstance()->getStateClass());
266 QList<QString> selectedProxies;
276 if (d.exec() == QDialog::Accepted)
294 if (d.exec() == QDialog::Accepted)
314 editor->getUI()->treeViewProgressBar->show();
315 editor->getUI()->treeViewProgressBar->setMaximum(groups.size());
317 foreach (QString groupPath, groups)
319 treeController->onOpenGroup(groupPath);
320 editor->getUI()->treeViewProgressBar->setValue(i);
322 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
324 editor->getUI()->treeViewProgressBar->hide();
330 paths.removeDuplicates();
332 foreach (QString path, paths)
342 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
356 if (stateInstance && stateInstance->getStateClass())
358 StateTreeNodePtr node = treeController->getNodeByState(stateInstance->getStateClass());
362 std::string filePath = node->getBoostCppFilePath().c_str();
371 watcher->removePath(path);
372 std::string fileContent;
374 if (std::filesystem::exists(path.toUtf8().data()))
376 watcher->addPath(path);
381 fileContent =
"<cpp missing>";
384 int line = editor->getUI()->textEditCppCode->textCursor().blockNumber();
385 QTextCursor cursor = editor->getUI()->textEditCppCode->textCursor();
386 cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line);
387 editor->getUI()->textEditCppCode->setText(QString::fromUtf8(fileContent.c_str()));
388 editor->getUI()->textEditCppCode->setTextCursor(cursor);
394 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
395 editor->getUI()->textEditCppCode->find(
"::onEnter()", QTextDocument::FindBackward);
401 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
402 editor->getUI()->textEditCppCode->find(
"::run()", QTextDocument::FindBackward);
408 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
409 editor->getUI()->textEditCppCode->find(
"::onBreak()", QTextDocument::FindBackward);
415 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
416 editor->getUI()->textEditCppCode->find(
"::onExit()", QTextDocument::FindBackward);
424 if (editor->getUI()->stateTabWidget->currentStateview())
428 editor->getUI()->stateTabWidget->currentStateview()->getScene()->selectedItems();
430 for (QGraphicsItem* item : selection)
451 auto node = treeController->getNodeByState(state);
453 if (node && node->isState())
455 treeController->openStateCPP(node);
467 editor->getStateTabWidget()->clear();
473 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
474 if (!executedOpenedGroup)
482 if (node->isPublic())
484 treeController->executeGroupWithDependencies(
487 executedOpenedGroup = node->getGroup();
488 editor->getUI()->toolButtonRunState->setIcon(QIcon(
":/icons/delete.ico"));
489 editor->getUI()->toolButtonRunState->setToolTip(
490 "Stop the Statechart Group");
491 editor->getUI()->toolButtonWatchStateExecution->setEnabled(
false);
492 editor->getUI()->labelExecutionState->setVisible(
true);
493 alreadyWatchingState =
false;
494 executionStatusTask->start();
498 QMessageBox::warning(
500 "Execution not possible",
501 "You can only execute public state. Right-click on the state in the "
502 "tree view on the left and select 'Public State'.");
508 QMessageBox::warning(
510 "Execution not possible",
511 "You need to open a state before executing it with this button.");
516 if (executedOpenedGroup)
518 treeController->stopGroupExecutionWithDependencies(executedOpenedGroup);
519 executedOpenedGroup.reset();
520 executionStatusTask->stop();
521 editor->getUI()->labelExecutionState->setVisible(
false);
523 editor->getUI()->toolButtonRunState->setToolTip(
"Start the Statechart Group");
524 editor->getUI()->toolButtonRunState->setIcon(QIcon(
":/icons/run.svg"));
525 editor->getUI()->toolButtonWatchStateExecution->setEnabled(
true);
530 std::function<void(
StateItem * state)> unsubscriptionLamba;
531 unsubscriptionLamba = [&](
StateItem* state)
533 stateWatcher->unsubscribeState(state);
538 unsubscriptionLamba(stateInstance);
547 StatechartEditorController::updateExecutionButtonStatus()
549 bool changeToWaiting =
false;
550 QString labelText =
"";
551 if (executedOpenedGroup)
553 std::string proxyName =
554 executedOpenedGroup->getName().toStdString() +
"StateComponentAppManager";
556 executedOpenedGroup->getName().toStdString() +
557 "RemoteStateOfferer";
558 ArmarXManagerInterfacePrx stateComponentProxy =
559 getProxy<ArmarXManagerInterfacePrx>(proxyName,
false,
"",
false);
566 else if (stateComponentProxy)
568 auto state = stateComponentProxy->getObjectState(objName);
569 if (state != eManagedIceObjectStarted)
573 stateComponentProxy->getObjectConnectivity(objName).dependencies)
575 ManagedIceObjectDependencyBasePtr dep = elem.second;
576 if (!dep->getResolved())
578 if (deps.size() >= 2)
580 deps.push_back(
"...");
585 deps.push_back(dep->getName());
589 labelText =
"Waiting for dependencies: " +
590 QString::fromStdString(simox::alg::join(deps,
", "));
591 changeToWaiting =
true;
596 labelText =
"Waiting for statechart group to start";
597 changeToWaiting =
true;
600 catch (
const Ice::Exception& e)
602 labelText =
"Waiting for statechart group to start (ice-exception catched)";
603 changeToWaiting =
true;
608 labelText =
"Waiting for statechart group to start (exception catched)";
609 changeToWaiting =
true;
612 if (!changeToWaiting)
614 labelText =
"Statechart group is running";
615 if (editor->getUI()->toolButtonWatchStateExecution->isChecked() &&
616 !alreadyWatchingState)
622 QMetaObject::invokeMethod(editor->getUI()->labelExecutionState,
624 Qt::QueuedConnection,
625 Q_ARG(QString, labelText));
630 StatechartEditorController::watchState(
const std::string& objName)
632 RemoteStateOffererInterfacePrx statechartHandler =
633 getProxy<RemoteStateOffererInterfacePrx>(objName,
false,
"",
false);
635 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
638 std::string globalStateName =
640 view->getStateInstance()->getStateClass()->getStateName().toStdString();
641 QMap<QString, StateInstanceData> instanceData =
642 view->getScene()->getStateInstanceData();
643 auto toplevelPathString = view->getScene()->getTopLevelStateItem()->getFullStatePath();
645 statechartHandler->begin_getStatechartInstanceByGlobalIdStr(globalStateName);
646 while (!asyncResult->isCompleted())
648 if (
getState() >= eManagedIceObjectExiting)
655 armarx::StateIceBasePtr stateptr =
656 statechartHandler->end_getStatechartInstanceByGlobalIdStr(asyncResult);
665 std::function<void(StateIceBasePtr iceState, StateItem * state)> subscriptionLamba;
666 subscriptionLamba = [&](StateIceBasePtr iceState, StateItem* state)
668 stateWatcher->subscribeToState(iceState, state);
670 for (
auto stateInstance : state->getSubstateItems())
672 if (stateInstance->getStateInstance()->getStateClass() &&
673 iceState->subStateList.size() > i)
676 StateIceBasePtr::dynamicCast(iceState->subStateList.at(i)),
682 subscriptionLamba(stateptr, view->getScene()->getTopLevelStateItem());
684 alreadyWatchingState =
true;
698 return qobject_cast<QWidget*>(editor);
702 StatechartEditorController::initWidget()
704 getWidget()->setFocusPolicy(Qt::WheelFocus);
716 eventuallyNamespacedPackage,
"",
true, variantInfo);
719 editor->setVariantInfo(variantInfo);
721 editor->getUI()->toolBarViewControl->addWidget(
new QLabel(
723 editor->getUI()->toolBarViewControl->insertWidget(
724 editor->getUI()->actionEdit_State_Properties,
new QLabel(
"Active State:"));
726 QList<QVariant> header;
727 header.push_back(QString(
"TEST"));
731 editor->getUI()->treeViewGroups,
732 editor->getUI()->lineEditStateSearch,
739 QStringList searchPaths;
748 const std::string cmakePackageName =
749 simox::alg::replace_all(eventuallyNamespacedPackage,
"::",
"_");
751 for (
const auto& includePath :
752 CMakePackageFinder(cmakePackageName).getIncludePathList())
756 if (elements.size() == 1)
758 std::filesystem::path packageStatechartPath(includePath.c_str());
759 packageStatechartPath /= cmakePackageName;
760 packageStatechartPath /=
"statecharts";
762 if (std::filesystem::exists(packageStatechartPath) &&
763 !std::filesystem::exists(
764 packageStatechartPath /
765 "cmake_install.cmake"))
768 << packageStatechartPath.string();
769 searchPaths.push_back(packageStatechartPath.c_str());
773 if (elements.size() == 2)
775 std::filesystem::path packageStatechartPathArmarXPackage(
776 includePath.c_str());
778 packageStatechartPathArmarXPackage /= elements.at(0);
779 packageStatechartPathArmarXPackage /= elements.at(1);
780 packageStatechartPathArmarXPackage /=
"statecharts";
784 if (std::filesystem::exists(packageStatechartPathArmarXPackage) &&
785 !std::filesystem::exists(
786 packageStatechartPathArmarXPackage /
787 "cmake_install.cmake"))
790 << packageStatechartPathArmarXPackage.string();
791 searchPaths.push_back(packageStatechartPathArmarXPackage.c_str());
800 connect(editor->getUI()->actionNew_State_Definition,
802 treeController.get(),
803 SLOT(onNewStateDefinition()));
804 connect(editor->getUI()->actionDelete_State_Definition,
806 treeController.get(),
807 SLOT(onDeleteNode()));
808 connect(editor->getUI()->treeViewGroups,
809 SIGNAL(doubleClicked(QModelIndex)),
811 connect(editor->getUI()->actionSave_State, SIGNAL(triggered()), SLOT(
requestSave()));
812 connect(editor->getUI()->stateTabWidget,
813 SIGNAL(currentChanged(
int)),
815 connect(editor->getUI()->actionNew_Statechart_Group,
819 connect(editor->getUI()->actionOpenStatechartGroup,
821 treeController.get(),
822 SLOT(onOpenGroup()));
823 connect(editor->getUI()->actionSettings,
827 connect(editor->getUI()->toolButtonRunState,
828 SIGNAL(clicked(
bool)),
832 connect(treeController.get(), SIGNAL(closeAllTabsRequested()),
this, SLOT(
closeAllTabs()));
835 editor->getUI()->actionOpenStatechartGroup->setShortcutContext(
836 Qt::WidgetWithChildrenShortcut);
837 editor->getUI()->actionOpenStatechartGroup->setShortcut(tr(
"Ctrl+O"));
838 getWidget()->addAction(editor->getUI()->actionOpenStatechartGroup);
841 stateEditorController.reset(
new StateEditorController(editor,
848 connect(editor->getUI()->stateTabWidget,
849 SIGNAL(currentChanged(
int)),
852 Qt::UniqueConnection);
853 connect(editor->getUI()->radioOnEnter,
857 Qt::UniqueConnection);
858 connect(editor->getUI()->radioOnBreak,
862 Qt::UniqueConnection);
863 connect(editor->getUI()->radioRun,
867 Qt::UniqueConnection);
868 connect(editor->getUI()->radioOnExit,
872 Qt::UniqueConnection);
876 editor->getUI()->btnOpenCppCode, SIGNAL(clicked()),
this, SLOT(
openSelectedState()));
878 watcher =
new QFileSystemWatcher(editor);
884 treeController->collapseAll();
885 executionStatusTask =
new PeriodicTask<StatechartEditorController>(
886 this, &StatechartEditorController::updateExecutionButtonStatus, 300);
918 return qobject_cast<StatechartEditorConfigDialog*>(dialog);