diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp index b8c2237b61294daefd0d73df112be629ba877c67..1b2987142535772f604d2c6d70470e9c585bc856 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp @@ -1081,27 +1081,31 @@ void StateTreeController::onOpenGroup(QString groupFile) loadAndAddGroup(groupFile); } -void StateTreeController::executeGroup(StatechartGroupPtr group, QString startState) + + +void StateTreeController::stopGroupExecution(StatechartGroupPtr group) { - if (processes.find(group->getGroupPath()) == processes.end()) - { - processes[group->getGroupPath()] = new QProcess(this); - } - else + if (processes.find(group->getGroupPath()) != processes.end()) { processes[group->getGroupPath()]->kill(); processes[group->getGroupPath()]->waitForFinished(500); } +} +void StateTreeController::executeGroup(StatechartGroupPtr group, QString startState) +{ + stopGroupExecution(group); + + if (processes.find(group->getGroupPath()) == processes.end()) + { + processes[group->getGroupPath()] = new QProcess(this); + } QProcess* p = processes[group->getGroupPath()]; connect(p, SIGNAL(finished(int)), this, SLOT(onStatechartFinished(int))); CMakePackageFinder core("ArmarXCore"); QStringList args; - // args << QString::fromStdString(core.getBinaryDir()) + "/XMLRemoteStateOffererRun"; - // args << "--Ice.Default.Locator=\\\"IceGrid/Locator:tcp -p 4061 -h localhost\\\"" << "--Ice.ThreadPool.Client.SizeMax=20"; - // args << "--Ice.ThreadPool.Server.SizeMax=20" << "--Ice.PrintStackTraces=1"; if (!startState.isEmpty()) { args << "--ArmarX.XMLStateComponent.StatesToEnter=" + startState; @@ -1131,6 +1135,26 @@ void StateTreeController::executeGroup(StatechartGroupPtr group, QString startSt connect(p, SIGNAL(readyReadStandardError()), this, SLOT(processErrorsReady())); } +void StateTreeController::executeGroupWithDependencies(StatechartGroupPtr group, QString startState) +{ + auto deps = GroupCloner(stateTreeModel, packageTool).getGroupDependencies(group, false); + executeGroup(group, startState); + for (StatechartGroupPtr dep : deps) + { + executeGroup(dep); + } +} + +void StateTreeController::stopGroupExecutionWithDependencies(StatechartGroupPtr group) +{ + auto deps = GroupCloner(stateTreeModel, packageTool).getGroupDependencies(group, false); + stopGroupExecution(group); + for (StatechartGroupPtr dep : deps) + { + stopGroupExecution(dep); + } +} + void StateTreeController::onExecuteGroup() { StateTreeNodePtr node = getSelectedNode(); @@ -1151,7 +1175,7 @@ void StateTreeController::onExecuteGroup() } } bool ok; - auto startState = QInputDialog::getItem(0, "State", "Select the state to start or none", states, 0, false, &ok); + QString startState = QInputDialog::getItem(0, "State", "Select the state to start or none", states, 0, false, &ok); if (!ok) { return; @@ -1160,13 +1184,8 @@ void StateTreeController::onExecuteGroup() { startState = ""; } - - auto deps = GroupCloner(stateTreeModel, packageTool).getGroupDependencies(node->getGroup(), false); - executeGroup(node->getGroup(), startState); - for (StatechartGroupPtr dep : deps) - { - executeGroup(dep); - } + StatechartGroupPtr group = node->getGroup(); + executeGroupWithDependencies(group, startState); // p->start(QString::fromStdString(core.getBinaryDir()) + "/startApplication.sh", args); diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h index a202249d3e04f2af13b1dcd8755f351bb5096c4a..800e689d1618fe29087903ef605fc1b571fb108e 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h @@ -138,6 +138,11 @@ namespace armarx void executeGroup(StatechartGroupPtr group, QString startState = ""); + void stopGroupExecution(StatechartGroupPtr group); + + void executeGroupWithDependencies(StatechartGroupPtr group, QString startState); + + void stopGroupExecutionWithDependencies(StatechartGroupPtr group); public: void openStateCPP(StateTreeNodePtr node); diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.cpp b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.cpp index 65d2fe70be1b5c74545eb8cf0cf297a1399a4c48..26609d90905f34d4f049f089e40ea6c8450564a6 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.cpp +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.cpp @@ -404,6 +404,45 @@ namespace armarx editor->getStateTabWidget()->clear(); } + void StatechartEditorController::executeOpenedState(bool) + { + StatechartView* view = editor->getUI()->stateTabWidget->currentStateview(); + if (!executedOpenedGroup) + { + if (view) + { + auto node = treeController->getNodeByState(view->getStateInstance()->getStateClass()); + if (node) + { + if (node->isPublic()) + { + treeController->executeGroupWithDependencies(node->getGroup(), view->getStateInstance()->getStateClass()->getStateName()); + executedOpenedGroup = node->getGroup(); + editor->getUI()->toolButtonRunState->setIcon(QIcon(":/icons/images/delete.ico")); + } + else + { + 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'."); + } + } + } + else + { + QMessageBox::warning(editor, "Execution not possible", "You need to open a state before executing it with this button."); + } + } + else + { + if (executedOpenedGroup) + { + treeController->stopGroupExecutionWithDependencies(executedOpenedGroup); + executedOpenedGroup.reset(); + } + editor->getUI()->toolButtonRunState->setIcon(QIcon(":/icons/images/run.svg")); + } + + } + QPointer<QWidget> StatechartEditorController::getWidget() { if (!editor) @@ -463,6 +502,8 @@ namespace armarx connect(editor->getUI()->actionNew_Statechart_Group, SIGNAL(triggered()), this, SLOT(showNewStatechartGroupDialog())); connect(editor->getUI()->actionOpenStatechartGroup, SIGNAL(triggered()), treeController.get(), SLOT(onOpenGroup())); connect(editor->getUI()->actionSettings, SIGNAL(triggered()), this, SLOT(showStatechartEditorSettingsDialog())); + connect(editor->getUI()->toolButtonRunState, SIGNAL(clicked(bool)), this, SLOT(executeOpenedState(bool))); + connect(treeController.get(), SIGNAL(closeAllTabsRequested()), this, SLOT(closeAllTabs())); // setup plugin specific shortcuts diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.h b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.h index d7015a758541f018b1b0e5279750e76d7ff038b4..428aa3816ecbe3e8fa25fbfaf841fa2415296f7e 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.h +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StatechartEditorController.h @@ -156,6 +156,7 @@ namespace armarx void showOnExitFunction(); void openSelectedState(); void closeAllTabs(); + void executeOpenedState(bool); public: // inherited from Component void onInitComponent(); @@ -194,7 +195,7 @@ namespace armarx VariantInfoPtr variantInfo; StatechartProfilesPtr profiles; QPointer<StatechartEditorConfigDialog> dialog; - + StatechartGroupPtr executedOpenedGroup; // ArmarXWidgetController interface public: QPointer<QDialog> getConfigDialog(QWidget* parent); diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/view/StatechartEditorMainWindow.ui b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/view/StatechartEditorMainWindow.ui index 4b68e8c0b4ed1ab639a725da73648ace273d2770..2db4e45b6d6648c2912729fe477c3a1b40718e26 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/view/StatechartEditorMainWindow.ui +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/view/StatechartEditorMainWindow.ui @@ -252,7 +252,7 @@ </property> </widget> </item> - <item row="3" column="0" colspan="6"> + <item row="3" column="0" colspan="7"> <widget class="QTextEdit" name="textEditCppCode"> <property name="enabled"> <bool>true</bool> @@ -283,7 +283,7 @@ </property> </widget> </item> - <item row="0" column="5"> + <item row="0" column="6"> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -296,11 +296,39 @@ </property> </spacer> </item> + <item row="0" column="5"> + <widget class="QToolButton" name="toolButtonRunState"> + <property name="toolTip"> + <string>Start/Stop currently opened state</string> + </property> + <property name="text"> + <string>Run State</string> + </property> + <property name="icon"> + <iconset resource="../resources/StatechartEditor.qrc"> + <normaloff>:/icons/images/run.svg</normaloff> + <normalon>:/icons/images/run.svg</normalon>:/icons/images/run.svg</iconset> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> <item row="0" column="4"> - <widget class="QPushButton" name="btnOpenCppCode"> + <widget class="QToolButton" name="btnOpenCppCode"> + <property name="toolTip"> + <string>Open Statechart code in text editor</string> + </property> <property name="text"> <string>Open C++ Code</string> </property> + <property name="icon"> + <iconset resource="../resources/StatechartEditor.qrc"> + <normaloff>:/icons/cpp.svg</normaloff>:/icons/cpp.svg</iconset> + </property> </widget> </item> </layout> @@ -317,7 +345,7 @@ <x>0</x> <y>0</y> <width>1338</width> - <height>33</height> + <height>25</height> </rect> </property> </widget> diff --git a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.cpp b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.cpp index f0e2e49d2dd43ff5fc93e410606592af22b4d241..993aa9cb8e65813a3a6c1243ad7b5bce3bd9cffb 100644 --- a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.cpp +++ b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.cpp @@ -41,8 +41,12 @@ #include <ArmarXCore/core/ArmarXManager.h> #include <ArmarXCore/core/ManagedIceObject.h> +#include <ArmarXGui/gui-plugins/StatechartViewerPlugin/model/stateinstance/DynamicRemoteState.h> +#include <ArmarXGui/gui-plugins/StatechartViewerPlugin/model/stateinstance/RemoteState.h> #include <IceUtil/UUID.h> +#include <queue> +#include <QMenu> #include <QToolBar> namespace armarx @@ -51,6 +55,8 @@ namespace armarx StatechartViewerController::StatechartViewerController() : updateTimer(new QTimer) { + setlocale(LC_ALL, "C"); + ui = new Ui::StatechartViewer(); connect(this, SIGNAL(componentConnected()), this, SLOT(connectToIce())); connect(this, SIGNAL(remoteProxyChanged()), this, SLOT(updateStatechart())); @@ -283,6 +289,8 @@ namespace armarx view->getLayoutController().enableLayouting(); updateStatechart(); + connectToStateTab(ui->tabWidget->currentIndex()); + } void StatechartViewerController::addNewStateView() @@ -341,10 +349,6 @@ namespace armarx } } - - - - QPointer<QWidget> StatechartViewerController::getCustomTitlebarWidget(QWidget* parent) { if (customToolbar) @@ -370,4 +374,90 @@ namespace armarx return qobject_cast<QToolBar*>(customToolbar); } + void StatechartViewerController::connectToStateTab(int index) + { + ARMARX_INFO << "Trying to connect to " << index; + if (index != -1 && ui->tabWidget->currentStateview() && ui->tabWidget->currentStateview()->getScene()) + { + connect(ui->tabWidget->currentStateview()->getScene(), SIGNAL(transitionContextMenuRequested(statechartmodel::TransitionCPtr, statechartmodel::StatePtr, QPoint, QPointF)), + this, SLOT(showTransitionContextMenu(statechartmodel::TransitionCPtr, statechartmodel::StatePtr, QPoint, QPointF)), Qt::UniqueConnection); + } + } + + void StatechartViewerController::showTransitionContextMenu(statechartmodel::TransitionCPtr transition, statechartmodel::StatePtr state, QPoint mouseScreenPos, QPointF mouseItemPos) + { + ARMARX_DEBUG_S << "pos: " << mouseItemPos; + QMenu menu; + QAction* triggerTransition = menu.addAction("Trigger Transition " + transition->eventName); + if (transition->sourceState != state->getActiveSubstate()) + { + triggerTransition->setEnabled(false); + } + + + QAction* result = menu.exec(mouseScreenPos); + + + + + if (result == triggerTransition) + { + ScopedRecursiveLock lock(mutex); + + for (RemoteStateData & data : converters) + { + std::set<std::string> proxyNames; + std::string globalId; + auto states = data.converter->getCompleteStateMap(); + for (auto & statepair : states) + { + proxyNames.insert(data.proxyName.toStdString()); + if (state == statepair.second.first->getStateClass()) + { + globalId = statepair.first; + ARMARX_INFO << "Found state " << statepair.first; + + + } + StateIceBasePtr iceState = statepair.second.second; + RemoteStateIceBasePtr remoteState = RemoteStateIceBasePtr::dynamicCast(iceState); + if (remoteState) + { + proxyNames.insert(remoteState->proxyName); + } + } + if (!globalId.empty()) + { + ARMARX_IMPORTANT << VAROUT(Ice::StringSeq(proxyNames.begin(), proxyNames.end())); + for (auto proxyName : proxyNames) + { + RemoteStateOffererInterfacePrx proxy = getProxy<RemoteStateOffererInterfacePrx>(proxyName, false, "", false); + try + { + if (proxy) + { + if (proxy->isHostOfStateByGlobalIdStr(globalId)) + { + ARMARX_INFO << proxyName << " is the one"; + proxy->begin_issueEventWithGlobalIdStr(globalId, new Event(transition->sourceState->getInstanceName().toStdString(), transition->eventName.toStdString())); + ARMARX_INFO << "Sending event " << transition->eventName << " to " << transition->sourceState->getInstanceName(); + + } + } + else + { + ARMARX_INFO << proxyName << " is NULL"; + } + } + catch (...) + { + getArmarXManager()->getIceManager()->removeProxyFromCache(proxy); + } + } + } + } + } + + } + } diff --git a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.h b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.h index 9be64366e2f0c538251c23f2f78bb1b19ac7b657..4fe72d032906667ee4ea68c43a96fd0b67aa31b1 100644 --- a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.h +++ b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/StatechartViewerController.h @@ -84,6 +84,8 @@ namespace armarx void updateStatechart(); public slots: + void connectToStateTab(int index); + void showTransitionContextMenu(statechartmodel::TransitionCPtr transition, statechartmodel::StatePtr state, QPoint mouseScreenPos, QPointF mouseItemPos); signals: void componentConnected(); void remoteProxyChanged();