28 #include <QCoreApplication>
29 #include <QInputDialog>
31 #include <QMessageBox>
34 #include <IceUtil/UUID.h>
36 #include <SimoxUtility/algorithm/string/string_tools.h>
40 #include <ArmarXCore/interface/statechart/RemoteStateOffererIce.h>
45 #include "../StatechartViewerPlugin/view/StateItem.h"
46 #include "../StatechartViewerPlugin/view/StatechartView.h"
62 setlocale(LC_ALL,
"C");
64 QSettings
s(
"KIT",
"ArmarXStatechartEditor");
78 QSettings
s(
"KIT",
"ArmarXStatechartEditor");
87 if (basePath.isEmpty())
95 for (std::filesystem::recursive_directory_iterator end, dir(basePath.toUtf8().data());
96 dir != end &&
getState() < eManagedIceObjectExiting;
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)
137 QTimer::singleShot(0,
this, SLOT(initWidget()));
140 stateWatcher,
"StateWatcher" + IceUtil::generateUUID(),
false);
151 if (executionStatusTask)
153 executionStatusTask->stop();
174 if (settings->contains(
"selectedProfile"))
177 settings->value(
"selectedProfile").toString().toStdString());
211 settings->setValue(
"selectedProfile",
223 if (node && node->getState())
225 int index = editor->getStateTabWidget()->getStateTab(node->getState());
227 "You can move states by holding the SHIFT + left click button. You can move the "
228 "scene by holding ALT + move mouse.",
229 "State Interaction");
233 editor->getStateTabWidget()->addStateTab(node->getState());
237 editor->getStateTabWidget()->setCurrentIndex(
index);
245 treeController->saveAll();
255 treeController->selectNodeByState(view->
getStateInstance()->getStateClass());
264 QList<QString> selectedProxies;
274 if (d.exec() == QDialog::Accepted)
292 if (d.exec() == QDialog::Accepted)
312 editor->getUI()->treeViewProgressBar->show();
313 editor->getUI()->treeViewProgressBar->setMaximum(groups.size());
315 foreach (QString groupPath, groups)
317 treeController->onOpenGroup(groupPath);
318 editor->getUI()->treeViewProgressBar->setValue(i);
320 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
322 editor->getUI()->treeViewProgressBar->hide();
328 paths.removeDuplicates();
330 foreach (QString path, paths)
340 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
354 if (stateInstance && stateInstance->getStateClass())
356 StateTreeNodePtr node = treeController->getNodeByState(stateInstance->getStateClass());
360 std::string filePath = node->getBoostCppFilePath().c_str();
369 watcher->removePath(path);
370 std::string fileContent;
372 if (std::filesystem::exists(path.toUtf8().data()))
374 watcher->addPath(path);
379 fileContent =
"<cpp missing>";
382 int line = editor->getUI()->textEditCppCode->textCursor().blockNumber();
383 QTextCursor cursor = editor->getUI()->textEditCppCode->textCursor();
384 cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line);
385 editor->getUI()->textEditCppCode->setText(QString::fromUtf8(fileContent.c_str()));
386 editor->getUI()->textEditCppCode->setTextCursor(cursor);
392 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
393 editor->getUI()->textEditCppCode->find(
"::onEnter()", QTextDocument::FindBackward);
399 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
400 editor->getUI()->textEditCppCode->find(
"::run()", QTextDocument::FindBackward);
406 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
407 editor->getUI()->textEditCppCode->find(
"::onBreak()", QTextDocument::FindBackward);
413 editor->getUI()->textEditCppCode->find(
"::CreateInstance(");
414 editor->getUI()->textEditCppCode->find(
"::onExit()", QTextDocument::FindBackward);
422 if (editor->getUI()->stateTabWidget->currentStateview())
426 editor->getUI()->stateTabWidget->currentStateview()->getScene()->selectedItems();
428 for (QGraphicsItem* item : selection)
449 auto node = treeController->getNodeByState(state);
451 if (node && node->isState())
453 treeController->openStateCPP(node);
465 editor->getStateTabWidget()->clear();
471 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
472 if (!executedOpenedGroup)
480 if (node->isPublic())
482 treeController->executeGroupWithDependencies(
485 executedOpenedGroup = node->getGroup();
486 editor->getUI()->toolButtonRunState->setIcon(QIcon(
":/icons/delete.ico"));
487 editor->getUI()->toolButtonRunState->setToolTip(
488 "Stop the Statechart Group");
489 editor->getUI()->toolButtonWatchStateExecution->setEnabled(
false);
490 editor->getUI()->labelExecutionState->setVisible(
true);
491 alreadyWatchingState =
false;
492 executionStatusTask->start();
496 QMessageBox::warning(
498 "Execution not possible",
499 "You can only execute public state. Right-click on the state in the "
500 "tree view on the left and select 'Public State'.");
506 QMessageBox::warning(
508 "Execution not possible",
509 "You need to open a state before executing it with this button.");
514 if (executedOpenedGroup)
516 treeController->stopGroupExecutionWithDependencies(executedOpenedGroup);
517 executedOpenedGroup.reset();
518 executionStatusTask->stop();
519 editor->getUI()->labelExecutionState->setVisible(
false);
521 editor->getUI()->toolButtonRunState->setToolTip(
"Start the Statechart Group");
522 editor->getUI()->toolButtonRunState->setIcon(QIcon(
":/icons/run.svg"));
523 editor->getUI()->toolButtonWatchStateExecution->setEnabled(
true);
528 std::function<void(
StateItem * state)> unsubscriptionLamba;
529 unsubscriptionLamba = [&](
StateItem* state)
531 stateWatcher->unsubscribeState(state);
536 unsubscriptionLamba(stateInstance);
545 StatechartEditorController::updateExecutionButtonStatus()
547 bool changeToWaiting =
false;
548 QString labelText =
"";
549 if (executedOpenedGroup)
551 std::string proxyName =
552 executedOpenedGroup->getName().toStdString() +
"StateComponentAppManager";
554 executedOpenedGroup->getName().toStdString() +
555 "RemoteStateOfferer";
556 ArmarXManagerInterfacePrx stateComponentProxy =
557 getProxy<ArmarXManagerInterfacePrx>(proxyName,
false,
"",
false);
564 else if (stateComponentProxy)
566 auto state = stateComponentProxy->getObjectState(objName);
567 if (state != eManagedIceObjectStarted)
571 stateComponentProxy->getObjectConnectivity(objName).dependencies)
573 ManagedIceObjectDependencyBasePtr dep = elem.second;
574 if (!dep->getResolved())
576 if (deps.size() >= 2)
578 deps.push_back(
"...");
583 deps.push_back(dep->getName());
587 labelText =
"Waiting for dependencies: " +
588 QString::fromStdString(simox::alg::join(deps,
", "));
589 changeToWaiting =
true;
594 labelText =
"Waiting for statechart group to start";
595 changeToWaiting =
true;
598 catch (
const Ice::Exception& e)
600 labelText =
"Waiting for statechart group to start (ice-exception catched)";
601 changeToWaiting =
true;
606 labelText =
"Waiting for statechart group to start (exception catched)";
607 changeToWaiting =
true;
610 if (!changeToWaiting)
612 labelText =
"Statechart group is running";
613 if (editor->getUI()->toolButtonWatchStateExecution->isChecked() &&
614 !alreadyWatchingState)
620 QMetaObject::invokeMethod(editor->getUI()->labelExecutionState,
622 Qt::QueuedConnection,
623 Q_ARG(QString, labelText));
628 StatechartEditorController::watchState(
const std::string& objName)
630 RemoteStateOffererInterfacePrx statechartHandler =
631 getProxy<RemoteStateOffererInterfacePrx>(objName,
false,
"",
false);
633 StatechartView* view = editor->getUI()->stateTabWidget->currentStateview();
636 std::string globalStateName =
638 view->getStateInstance()->getStateClass()->getStateName().toStdString();
639 QMap<QString, StateInstanceData> instanceData =
640 view->getScene()->getStateInstanceData();
641 auto toplevelPathString = view->getScene()->getTopLevelStateItem()->getFullStatePath();
643 statechartHandler->begin_getStatechartInstanceByGlobalIdStr(globalStateName);
644 while (!asyncResult->isCompleted())
646 if (
getState() >= eManagedIceObjectExiting)
653 armarx::StateIceBasePtr stateptr =
654 statechartHandler->end_getStatechartInstanceByGlobalIdStr(asyncResult);
663 std::function<void(StateIceBasePtr iceState, StateItem * state)> subscriptionLamba;
664 subscriptionLamba = [&](StateIceBasePtr iceState, StateItem* state)
666 stateWatcher->subscribeToState(iceState, state);
668 for (
auto stateInstance : state->getSubstateItems())
670 if (stateInstance->getStateInstance()->getStateClass() &&
671 iceState->subStateList.size() > i)
674 StateIceBasePtr::dynamicCast(iceState->subStateList.at(i)),
680 subscriptionLamba(stateptr, view->getScene()->getTopLevelStateItem());
682 alreadyWatchingState =
true;
696 return qobject_cast<QWidget*>(editor);
700 StatechartEditorController::initWidget()
702 getWidget()->setFocusPolicy(Qt::WheelFocus);
714 eventuallyNamespacedPackage,
"",
true, variantInfo);
717 editor->setVariantInfo(variantInfo);
719 editor->getUI()->toolBarViewControl->addWidget(
new QLabel(
721 editor->getUI()->toolBarViewControl->insertWidget(
722 editor->getUI()->actionEdit_State_Properties,
new QLabel(
"Active State:"));
724 QList<QVariant> header;
725 header.push_back(QString(
"TEST"));
729 editor->getUI()->treeViewGroups,
730 editor->getUI()->lineEditStateSearch,
737 QStringList searchPaths;
746 const std::string cmakePackageName =
747 simox::alg::replace_all(eventuallyNamespacedPackage,
"::",
"_");
749 for (
const auto& includePath :
750 CMakePackageFinder(cmakePackageName).getIncludePathList())
754 if (elements.size() == 1)
756 std::filesystem::path packageStatechartPath(includePath.c_str());
757 packageStatechartPath /= cmakePackageName;
758 packageStatechartPath /=
"statecharts";
760 if (std::filesystem::exists(packageStatechartPath) &&
761 !std::filesystem::exists(
762 packageStatechartPath /
763 "cmake_install.cmake"))
766 << packageStatechartPath.string();
767 searchPaths.push_back(packageStatechartPath.c_str());
771 if (elements.size() == 2)
773 std::filesystem::path packageStatechartPathArmarXPackage(
774 includePath.c_str());
776 packageStatechartPathArmarXPackage /= elements.at(0);
777 packageStatechartPathArmarXPackage /= elements.at(1);
778 packageStatechartPathArmarXPackage /=
"statecharts";
782 if (std::filesystem::exists(packageStatechartPathArmarXPackage) &&
783 !std::filesystem::exists(
784 packageStatechartPathArmarXPackage /
785 "cmake_install.cmake"))
788 << packageStatechartPathArmarXPackage.string();
789 searchPaths.push_back(packageStatechartPathArmarXPackage.c_str());
798 connect(editor->getUI()->actionNew_State_Definition,
800 treeController.get(),
801 SLOT(onNewStateDefinition()));
802 connect(editor->getUI()->actionDelete_State_Definition,
804 treeController.get(),
805 SLOT(onDeleteNode()));
806 connect(editor->getUI()->treeViewGroups,
807 SIGNAL(doubleClicked(QModelIndex)),
809 connect(editor->getUI()->actionSave_State, SIGNAL(triggered()), SLOT(
requestSave()));
810 connect(editor->getUI()->stateTabWidget,
811 SIGNAL(currentChanged(
int)),
813 connect(editor->getUI()->actionNew_Statechart_Group,
817 connect(editor->getUI()->actionOpenStatechartGroup,
819 treeController.get(),
820 SLOT(onOpenGroup()));
821 connect(editor->getUI()->actionSettings,
825 connect(editor->getUI()->toolButtonRunState,
826 SIGNAL(clicked(
bool)),
830 connect(treeController.get(), SIGNAL(closeAllTabsRequested()),
this, SLOT(
closeAllTabs()));
833 editor->getUI()->actionOpenStatechartGroup->setShortcutContext(
834 Qt::WidgetWithChildrenShortcut);
835 editor->getUI()->actionOpenStatechartGroup->setShortcut(tr(
"Ctrl+O"));
836 getWidget()->addAction(editor->getUI()->actionOpenStatechartGroup);
839 stateEditorController.reset(
new StateEditorController(editor,
846 connect(editor->getUI()->stateTabWidget,
847 SIGNAL(currentChanged(
int)),
850 Qt::UniqueConnection);
851 connect(editor->getUI()->radioOnEnter,
855 Qt::UniqueConnection);
856 connect(editor->getUI()->radioOnBreak,
860 Qt::UniqueConnection);
861 connect(editor->getUI()->radioRun,
865 Qt::UniqueConnection);
866 connect(editor->getUI()->radioOnExit,
870 Qt::UniqueConnection);
874 editor->getUI()->btnOpenCppCode, SIGNAL(clicked()),
this, SLOT(
openSelectedState()));
876 watcher =
new QFileSystemWatcher(editor);
882 treeController->collapseAll();
883 executionStatusTask =
new PeriodicTask<StatechartEditorController>(
884 this, &StatechartEditorController::updateExecutionButtonStatus, 300);
916 return qobject_cast<StatechartEditorConfigDialog*>(dialog);