Skip to content
Snippets Groups Projects
Commit af000825 authored by Mirko Wächter's avatar Mirko Wächter
Browse files

working version of statechart viewer in statechart editor

parent f58d526b
No related branches found
No related tags found
No related merge requests found
......@@ -134,7 +134,7 @@ namespace armarx
void StatechartEditorController::onConnectComponent()
{
QTimer::singleShot(0, this, SLOT(initWidget()));
stateWatcher = ManagedIceObject::create<StateWatcher>();
stateWatcher = new StateWatcher();
getArmarXManager()->addObject(stateWatcher, "StateWatcher" + IceUtil::generateUUID(), false);
}
......@@ -450,6 +450,7 @@ namespace armarx
executedOpenedGroup = node->getGroup();
editor->getUI()->toolButtonRunState->setIcon(QIcon(":/icons/images/delete.ico"));
editor->getUI()->toolButtonRunState->setToolTip("Stop the Statechart Group");
editor->getUI()->toolButtonWatchStateExecution->setEnabled(false);
editor->getUI()->labelExecutionState->setVisible(true);
alreadyWatchingState = false;
executionStatusTask->start();
......@@ -476,10 +477,24 @@ namespace armarx
}
editor->getUI()->toolButtonRunState->setToolTip("Start the Statechart Group");
editor->getUI()->toolButtonRunState->setIcon(QIcon(":/icons/images/run.svg"));
editor->getUI()->toolButtonWatchStateExecution->setEnabled(true);
if (view)
{
view->getStateInstance()->getStateClass()->clearActiveSubstates();
view->getScene()->clearActiveSubstates();
}
std::function<void(StateItem* state)> unsubscriptionLamba;
unsubscriptionLamba = [&](StateItem * state)
{
stateWatcher->unsubscribeState(state);
for (auto stateInstance : state->getSubstateItems())
{
if (stateInstance)
{
unsubscriptionLamba(stateInstance);
}
}
};
unsubscriptionLamba(view->getScene()->getTopLevelStateItem());
}
}
......@@ -543,7 +558,7 @@ namespace armarx
if (!changeToWaiting)
{
labelText = "Statechart group is running";
if (!alreadyWatchingState)
if (editor->getUI()->toolButtonWatchStateExecution->isChecked() && !alreadyWatchingState)
{
watchState(objName);
}
......@@ -562,6 +577,8 @@ namespace armarx
if (view)
{
std::string globalStateName = "TopLevel->" + view->getStateInstance()->getStateClass()->getStateName().toStdString();
QMap<QString, StateInstanceData> instanceData = view->getScene()->getStateInstanceData();
auto toplevelPathString = view->getScene()->getTopLevelStateItem()->getFullStatePath();
auto asyncResult = statechartHandler->begin_getStatechartInstanceByGlobalIdStr(globalStateName);
while (!asyncResult->isCompleted())
{
......@@ -579,22 +596,23 @@ namespace armarx
}
else
{
ARMARX_INFO << "subscribing;";
std::function<void(StateIceBasePtr iceState, statechartmodel::StatePtr state)> subscriptionLamba;
subscriptionLamba = [&](StateIceBasePtr iceState, statechartmodel::StatePtr state)
std::function<void(StateIceBasePtr iceState, StateItem* state)> subscriptionLamba;
subscriptionLamba = [&](StateIceBasePtr iceState, StateItem * state)
{
stateWatcher->subscribeToState(iceState, state);
size_t i = 0;
for (statechartmodel::StateInstancePtr stateInstance : state->getSubstates())
for (auto stateInstance : state->getSubstateItems())
{
if (stateInstance->getStateClass() && iceState->subStateList.size() > i)
if (stateInstance->getStateInstance()->getStateClass() && iceState->subStateList.size() > i)
{
subscriptionLamba(iceState->subStateList.at(i), stateInstance->getStateClass());
subscriptionLamba(iceState->subStateList.at(i), stateInstance);
}
i++;
}
};
subscriptionLamba(stateptr, view->getStateInstance()->getStateClass());
subscriptionLamba(stateptr, view->getScene()->getTopLevelStateItem());
alreadyWatchingState = true;
}
......
......@@ -248,20 +248,45 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QRadioButton" name="radioRun">
<item row="0" column="6">
<widget class="QLabel" name="labelExecutionState">
<property name="text">
<string>run()</string>
<string/>
</property>
</widget>
</item>
<item row="3" column="0" colspan="8">
<widget class="QTextEdit" name="textEditCppCode">
<property name="enabled">
<bool>true</bool>
<item row="0" column="5">
<widget class="QToolButton" name="toolButtonRunState">
<property name="toolTip">
<string>Start/Stop currently opened state</string>
</property>
<property name="readOnly">
<bool>true</bool>
<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="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>
......@@ -279,6 +304,16 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="10">
<widget class="QTextEdit" name="textEditCppCode">
<property name="enabled">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="radioOnEnter">
<property name="text">
......@@ -286,7 +321,7 @@
</property>
</widget>
</item>
<item row="0" column="7">
<item row="0" column="9">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
......@@ -299,45 +334,27 @@
</property>
</spacer>
</item>
<item row="0" column="5">
<widget class="QToolButton" name="toolButtonRunState">
<property name="toolTip">
<string>Start/Stop currently opened state</string>
</property>
<item row="0" column="1">
<widget class="QRadioButton" name="radioRun">
<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>
<string>run()</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QToolButton" name="btnOpenCppCode">
<property name="toolTip">
<string>Open Statechart code in text editor</string>
</property>
<item row="0" column="7">
<widget class="QToolButton" name="toolButtonWatchStateExecution">
<property name="text">
<string>Open C++ Code</string>
<string/>
</property>
<property name="icon">
<iconset resource="../resources/StatechartEditor.qrc">
<normaloff>:/icons/cpp.svg</normaloff>:/icons/cpp.svg</iconset>
<iconset resource="../../../libraries/ArmarXGuiBase/armarxicons.qrc">
<normaloff>:/icons/binoculars.svg</normaloff>:/icons/binoculars.svg</iconset>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLabel" name="labelExecutionState">
<property name="text">
<string/>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
......@@ -355,7 +372,7 @@
<x>0</x>
<y>0</y>
<width>1338</width>
<height>27</height>
<height>28</height>
</rect>
</property>
</widget>
......@@ -585,6 +602,7 @@
<resources>
<include location="../../../libraries/ArmarXGuiBase/armarxicons.qrc"/>
<include location="../../../libraries/qtpropertybrowser/src/qtpropertybrowser.qrc"/>
<include location="../../../libraries/qtpropertybrowser/src/qtpropertybrowser.qrc"/>
<include location="../resources/StatechartEditor.qrc"/>
</resources>
<connections>
......
......@@ -70,8 +70,64 @@ namespace armarx
img.save(path);
}
const QMap<QString, StateInstanceData>& StateScene::getStateInstanceData() const
void StateScene::clearActiveSubstates()
{
std::function<void(StateItem*)> clearRecursive;
clearRecursive = [&](StateItem * item)
{
if (!item)
{
return;
}
for (auto substateItem : item->getSubstateItems())
{
clearRecursive(substateItem);
}
item->clearActiveSubstate();
};
if (topLevelStateItem)
{
clearRecursive(topLevelStateItem);
}
}
QMap<QString, StateInstanceData> StateScene::getStateInstanceData() const
{
QMap<QString, StateInstanceData> stateInstanceData;
std::function<QMap<QString, StateInstanceData>(StateItem*)> getChildren;
getChildren = [&](StateItem * stateItem)
{
QMap<QString, StateInstanceData> stateInstanceData;
for (StateItem* substateItem : stateItem->getSubstateItems())
{
auto fullpath = substateItem->getFullStatePath();
StateInstanceData data;
data.active = substateItem->isActive();
data.fullStatePath = fullpath;
data.stateInstance = substateItem->getStateInstance();
stateInstanceData[fullpath] = data;
auto map = getChildren(substateItem);
for (auto& key : map.keys())
{
stateInstanceData[key] = map[key];
}
}
return stateInstanceData;
};
if (topLevelStateItem)
{
stateInstanceData = getChildren(topLevelStateItem);
auto fullpath = topLevelStateItem->getFullStatePath();
StateInstanceData data;
data.active = topLevelStateItem->isActive();
data.fullStatePath = fullpath;
data.stateInstance = topLevelStateItem->getStateInstance();
stateInstanceData[fullpath] = data;
}
return stateInstanceData;
}
......
......@@ -63,7 +63,7 @@ namespace armarx
const QMap<QString, StateInstanceData>& getStateInstanceData() const;
QMap<QString, StateInstanceData> getStateInstanceData() const;
signals:
void stateContextMenuRequested(statechartmodel::StateInstancePtr state, QPoint mouseScreenPos, QPointF mouseItemPos);
......@@ -71,10 +71,10 @@ namespace armarx
public slots:
void setToplevelState(statechartmodel::StatePtr toplevelStateInstance);
void saveSceneToSVG(QString path = "/tmp/statechart.png", int width = 6000);
void clearActiveSubstates();
private:
statechartmodel::StateInstancePtr toplevelStateInstance;
StateItem* topLevelStateItem;
QMap<QString, StateInstanceData> stateInstanceData;
// QMap<QString, StateItem*> subStates;
// QList<QGraphicsLineItem*> transitions;
......
......@@ -22,7 +22,7 @@
* GNU General Public License
*/
#include "StateWatcher.h"
#include "view/TransitionItem.h"
#include <ArmarXCore/observers/condition/Term.h>
#include <iterator>
......@@ -73,7 +73,7 @@ namespace armarx
void StateWatcher::subscriptionFunction()
{
std::vector<std::pair<StateIceBasePtr, statechartmodel::StatePtr> > tempList;
SubscriptionMap tempList;
{
ScopedLock lock(mapMutex);
tempList.swap(subscriptionQueue);
......@@ -82,12 +82,17 @@ namespace armarx
for (auto& elem : tempList)
{
StateIceBasePtr iceState = elem.first;
statechartmodel::StatePtr state = elem.second;
statechartmodel::StatePtr state = elem.second.first;
StateItem* stateItem = elem.second.second;
StateListenerDataMap::iterator it;
{
ScopedLock lock(mapMutex);
it = stateMap.find(iceState->globalStateIdentifier);
if (it != stateMap.end() && it->second.states.count(state) > 0)
if (it != stateMap.end() && state && it->second.states.count(state) > 0)
{
continue;
}
if (it != stateMap.end() && stateItem && it->second.stateItems.count(stateItem) > 0)
{
continue;
}
......@@ -102,7 +107,14 @@ namespace armarx
data = it->second;
}
data.iceState = iceState;
data.states.insert(state);
if (state)
{
data.states.insert(state);
}
if (stateItem)
{
data.stateItems.insert(stateItem);
}
ScopedLock lock(mapMutex);
stateMap[iceState->globalStateIdentifier] = data;
......@@ -129,8 +141,42 @@ namespace armarx
ARMARX_WARNING << "State NULL: " << iceState->globalStateIdentifier;
return false;
}
StateItem* item = nullptr;
subscriptionQueue.push_back(std::make_pair(iceState, std::make_pair(state, item)));
return true;
}
bool StateWatcher::unsubscribeState(StateItem* state)
{
ScopedLock lock(mapMutex);
for (auto& pair : stateMap)
{
for (auto item : pair.second.stateItems)
{
if (item == state)
{
pair.second.stateItems.erase(state);
return true;
}
}
}
return false;
}
subscriptionQueue.push_back(std::make_pair(iceState, state));
bool StateWatcher::subscribeToState(StateIceBasePtr iceState, StateItem* state)
{
ScopedLock lock(mapMutex);
if (!iceState)
{
ARMARX_WARNING << "Ice State NULL";
return false;
}
if (!state)
{
ARMARX_WARNING << "State NULL: " << iceState->globalStateIdentifier;
return false;
}
subscriptionQueue.push_back(std::make_pair(iceState, std::make_pair(statechartmodel::StatePtr(), state)));
return true;
}
......@@ -304,6 +350,12 @@ namespace armarx
QMetaObject::invokeMethod(state.get(), "setActiveSubstate", Q_ARG(StateInstancePtr, StateInstancePtr()));
}
}
for (auto item : data.stateItems)
{
std::string activeSubstateName = ExtractStateName(event.targetStateIdentifier);
QMetaObject::invokeMethod(item, "setActiveSubstate", Q_ARG(QString, QString::fromStdString(activeSubstateName)));
// QMetaObject::invokeMethod(item->getParentStateItem()->setActiveSubstate(QString::fromStdString(activeSubstateName));
}
}
......@@ -346,6 +398,25 @@ namespace armarx
}
}
}
for (auto item : data.stateItems)
{
QString eventName = QString::fromStdString(event.eventName);
QString sourceStateName = QString::fromStdString(ExtractStateName(event.sourceStateIdentifier));
QString destinationStateName = QString::fromStdString(ExtractStateName(event.targetStateIdentifier));
if (item && !eventName.isEmpty() && !destinationStateName.isEmpty())
{
for (auto t : item->getTransitionItems())
{
statechartmodel::StateCPtr stateclass = item->getStateInstance()->getStateClass();
if ((t->getTransition()->eventName == eventName && t->getTransition()->sourceState->getInstanceName() == sourceStateName)
|| (stateclass && t->getTransition() == stateclass->getStartTransition() && eventName == "InitialTransition"))
{
QMetaObject::invokeMethod(t, "highlightAnimation", Q_ARG(int, 10000));
// t->highlightAnimation(10000);
}
}
}
}
}
}
catch (...)
......
......@@ -27,6 +27,7 @@
#include <ArmarXCore/observers/variant/DatafieldRef.h>
#include <ArmarXCore/core/services/tasks/PeriodicTask.h>
#include <ArmarXCore/interface/observers/ProfilerObserverInterface.h>
#include <ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.h>
namespace armarx
{
......@@ -41,6 +42,7 @@ namespace armarx
{
StateIceBasePtr iceState;
std::set<statechartmodel::StatePtr> states;
std::set<StateItem*> stateItems;
std::map<std::string, ::armarx::StateParameterMap> parameters;
......@@ -49,7 +51,9 @@ namespace armarx
typedef std::map<std::string, StateListenerData> StateListenerDataMap;
StateWatcher();
bool subscribeToState(StateIceBasePtr iceState, StateItem* state);
bool subscribeToState(StateIceBasePtr iceState, statechartmodel::StatePtr state);
bool unsubscribeState(StateItem* state);
VariantPtr getStateParameter(statechartmodel::StatePtr state, const std::string paramMapType) const;
StateParameterMap getStateParameterMap(statechartmodel::StatePtr state, const std::string paramMapType) const;
......@@ -69,7 +73,8 @@ namespace armarx
mutable armarx::Mutex mapMutex;
ConditionHandlerInterfacePrx conditionHandler;
ProfilerObserverInterfacePrx profilerObserver;
std::vector<std::pair<StateIceBasePtr, statechartmodel::StatePtr> > subscriptionQueue;
typedef std::vector<std::pair<StateIceBasePtr, std::pair<statechartmodel::StatePtr, StateItem*>> > SubscriptionMap;
SubscriptionMap subscriptionQueue;
PeriodicTask<StateWatcher>::pointer_type subscriptionTask;
......
......@@ -335,11 +335,11 @@ namespace armarx
{
break;
}
// ARMARX_DEBUG << "Removing transition " << transition->eventName;
// ARMARX_DEBUG << "Removing transition " << transition->eventName;
TransitionItem* t = it.value();
QObject::disconnect(t);
transitions.remove(transition);
// t->prepareGeometryChange();
// t->prepareGeometryChange();
delete t;
}
......@@ -548,8 +548,8 @@ namespace armarx
void StateItem::setRimColor()
{
if (state
&& state->isActive())
if ((state
&& state->isActive()) || active)
{
setRimPen(QPen(Qt::red, 10));
}
......@@ -583,13 +583,13 @@ namespace armarx
auto curScene = scene();
if (curScene)
{
for (auto & t : transitions)
for (auto& t : transitions)
{
// t->prepareGeometryChange();
curScene->removeItem(t);
}
}
for (auto & s : subStates)
for (auto& s : subStates)
{
s->prepareGeometryChange();
s->removeChildren();
......@@ -630,16 +630,35 @@ namespace armarx
void StateItem::setMaxShownSubstateLevel(int value)
{
maxShownSubstateLevel = value;
for (auto & substate : subStates)
for (auto& substate : subStates)
{
substate->setMaxShownSubstateLevel(value);
}
for (auto & item : childItems())
for (auto& item : childItems())
{
item->update();
}
}
void StateItem::setActiveSubstate(const QString& substateName)
{
auto substates = getSubstateItems();
for (auto substate : substates)
{
bool active = (substate->getInstanceName() == substateName);
substate->setActiveState(active);
}
}
void StateItem::clearActiveSubstate()
{
auto substates = getSubstateItems();
for (auto substate : substates)
{
substate->setActiveState(false);
}
}
QString StateItem::getFullStatePath() const
{
QString path = instanceName;
......@@ -647,11 +666,45 @@ namespace armarx
while (parent)
{
path = parent->getInstanceName() + "/" + path;
parent = qgraphicsitem_cast<StateItem*>(parentItem());
parent = qgraphicsitem_cast<StateItem*>(parent->parentItem());
}
return path;
}
StateItem* StateItem::getParentStateItem() const
{
StateItem* parent = qgraphicsitem_cast<StateItem*>(parentItem());
return parent;
}
QVector<StateItem*> StateItem::getSubstateItems() const
{
QVector<StateItem*> result;
for (QGraphicsItem* item : this->childItems())
{
StateItem* state = dynamic_cast<StateItem*>(item);
if (state)
{
result.push_back(state);
}
}
return result;
}
QVector<TransitionItem*> StateItem::getTransitionItems() const
{
QVector<TransitionItem*> result;
for (QGraphicsItem* item : this->childItems())
{
TransitionItem* transition = dynamic_cast<TransitionItem*>(item);
if (transition)
{
result.push_back(transition);
}
}
return result;
}
QString StateItem::getInstanceName() const
{
return instanceName;
......
......@@ -53,7 +53,9 @@ namespace armarx
}
class StateItem;
class TransitionItem;
class StateItem :
public RoundRectItem,
public MorphingItem
......@@ -79,7 +81,13 @@ namespace armarx
bool hasDescendant(statechartmodel::StatePtr state) const;
int getMaxShownSubstateLevel() const;
void setMaxShownSubstateLevel(int value);
void clearActiveSubstate();
StateItem* getParentStateItem() const;
QString getFullStatePath() const;
QVector<StateItem*> getSubstateItems() const;
QVector<TransitionItem*> getTransitionItems() const;
signals:
void stateItemResized(QSizeF newSize);
void stateItemMoved(QPointF newPosition);
......@@ -98,6 +106,8 @@ namespace armarx
void adjustSize();
void setInstanceName(const QString& value);
void setActiveState(bool active);
void setActiveSubstate(const QString& substateName);
protected:
void setup(QGraphicsItem* parent);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment