diff --git a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.cpp b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.cpp index 49a2c1a9b418f178628a21eea4368012769f5d3d..35393ba88616f3c2fe23093af1509f15dc76e495 100644 --- a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.cpp +++ b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.cpp @@ -1108,6 +1108,39 @@ TransitionPtr statechartmodel::State::findTransition(const QString& eventName, c return TransitionPtr(); } +bool State::hasDescendant(StatePtr sC) const +{ + if (!sC) + { + return false; + } + + for (auto it = substates.begin(); it != substates.end(); it++) + { + statechartmodel::StateInstancePtr state = (it.value()); + if (!state) + { + continue; + } + if (!state->getStateClass()) + { + continue; + } + + if (state->getStateClass()->getUUID() == sC->getUUID()) + { + return true; + } + + if (state->getStateClass()->hasDescendant(sC)) + { + return true; + } + } + return false; + +} + QString statechartmodel::State::StateTypeToString(eStateType type) { switch (type) diff --git a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.h b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.h index eb43413d81600ad36fede88867942675f93cde6f..0f9316b6af0cd7bd6d532dd7543ea0bfc9c42fb0 100644 --- a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.h +++ b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/model/State.h @@ -134,6 +134,7 @@ namespace armarx TransitionCPtr getStartTransition() const; TransitionPtr findTransition(TransitionCPtr t) const; TransitionPtr findTransition(const QString& eventName, const QString& transitionSourceName, const QString& transitionDestinationName) const; + bool hasDescendant(statechartmodel::StatePtr state) const; static QString StateTypeToString(eStateType type); void connectToSubclasses(); diff --git a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.cpp b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.cpp index ed8c6980962ad3d29a88ac0622fb3651cf931edd..a88cff19ca0075bbd11f193f197863243bbd3b68 100644 --- a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.cpp +++ b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.cpp @@ -735,7 +735,6 @@ namespace armarx else { event->setDropAction(Qt::IgnoreAction); - } event->accept(); @@ -757,7 +756,7 @@ namespace armarx } const AbstractStateMimeData* data = qobject_cast<const AbstractStateMimeData*>(event->mimeData()); - + bool accept = true; if (data && state && state->getStateClass() && data->getState() && (state->getType() == eNormalState || state->getType() == eRemoteState)) { @@ -771,9 +770,15 @@ namespace armarx i++; } - if (data->getState()->getType() == eDynamicRemoteState && !data->isInSameGroup(state->getStateClass())) + if (hasAncestor(data->getState()) || data->getState()->hasDescendant(state->getStateClass())) + { + QMessageBox::warning(event->source(), "State drag'n'drop error", "State cycle detected - you must not insert a state which is also a parent state of the current state"); + accept = false; + } + else if (data->getState()->getType() == eDynamicRemoteState && !data->isInSameGroup(state->getStateClass())) { QMessageBox::warning(event->source(), "State drag'n'drop error", "Dynamic Remote States can only be added in the same group."); + accept = false; } else if (data->isInSameGroup(state->getStateClass())) { @@ -793,20 +798,64 @@ namespace armarx else { QMessageBox::warning(event->source(), "State drag'n'drop error", "Only public states can be added as a Remote State."); + accept = false; } + + } + else + { + accept = false; + } + + + if (accept) + { event->setDropAction(Qt::LinkAction); - event->acceptProposedAction(); + event->accept(); } else { event->setDropAction(Qt::IgnoreAction); - event->acceptProposedAction(); + event->accept(); } } + bool StateItem::hasAncestor(statechartmodel::StatePtr sC) const + { + if (!sC) + { + return false; + } + StateItem* state = qgraphicsitem_cast<StateItem*>(parentItem()); + if (!state) + { + return false; + } + if (!state->getStateInstance() || !state->getStateInstance()->getStateClass()) + { + return false; + } + if (state->getStateInstance()->getStateClass()->getUUID() == sC->getUUID()) + { + return true; + } + + return state->hasAncestor(sC); + } + + bool StateItem::hasDescendant(statechartmodel::StatePtr sC) const + { + if (!sC || !state->getStateClass()) + { + return false; + } + return state->getStateClass()->hasDescendant(sC); + + + } } diff --git a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.h b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.h index d63ea34d48be533c90e87d5958baf7c7ec2ca841..2c2b2625e62015139929b4ed28a6f168253e1db8 100644 --- a/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.h +++ b/source/ArmarXGui/gui-plugins/StatechartViewerPlugin/view/StateItem.h @@ -75,6 +75,8 @@ namespace armarx QString getInstanceName() const; + bool hasAncestor(statechartmodel::StatePtr state) const; + bool hasDescendant(statechartmodel::StatePtr state) const; signals: void stateItemResized(QSizeF newSize); void stateItemMoved(QPointF newPosition);