StateItem.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24#include "StateItem.h"
25
26#include <QGraphicsProxyWidget>
27#include <QGraphicsSceneContextMenuEvent>
28#include <QMenu>
29#include <QMessageBox>
30#include <QPainter>
31#include <QStyleOptionGraphicsItem>
32#include <QtGui>
33
35
37
38#include "../StateScene.h"
39#include "../model/State.h"
41#include "../model/Transition.h"
43#include "TransitionItem.h"
44
45
46#define MAXFONTSIZE 300.0f
47
48namespace armarx
49{
51 RoundRectItem(QRectF(0, 0, state->getClassSize().width(), state->getClassSize().height()),
52 // QColor(Qt::blue).lighter(190),
53 QColor(),
54 parent),
55 MorphingItem(this),
57 // QGraphicsWidget(parent)
58 {
59 // if(state && state->getStateClass())
60 setAcceptDrops(true);
61 // stateScene = dynamic_cast<StateScene*>(scene());
62 setup(parent);
67 setZValue(10000);
69 if (state->getStateClass())
70 {
71 setEditable(state->getStateClass()->isEditable());
72 }
73 }
74
76 {
77 // ARMARX_INFO << state->getInstanceName();
78 }
79
80 void
81 StateItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
82 {
83 StateItem* parentState = qgraphicsitem_cast<StateItem*>(parentItem());
84 LevelOfDetail detail = getLevelOfDetailByParent(painter, parentState);
85
86 if (detail ==
87 eHidden) // only use scale of parent so that all sub elements of parent (states, transitions) are hidden at once and not one after the other
88 {
89 return;
90 }
91
92
93 statechartmodel::StatePtr stateClass = state->getStateClass();
94
95 // Draw state rect
96 RoundRectItem::paint(painter, option, widget);
97
98 // draw substate rect for debug purposes
99 // if(state->getStateClass())
100 // painter->drawRect(QRectF(state->getStateClass()->margin.topLeft(),
101 // QPointF(state->getStateClass()->getSize().width()-state->getStateClass()->margin.width(),
102 // state->getStateClass()->getSize().height()-state->getStateClass()->margin.height())));
103 /*
104 * There are three different cases which must be differentiated:
105 * 1. Class known & substates: Show both names at top
106 * 2. Class known & no substates: Show both names centered (instance label centered, class name below)
107 * 3. Class unknown & no substates: Show class name centered
108 * (Class unknown & substates: Not possible, substates are deduced from state class)
109 */
110
111 bool showSubstates =
112 detail != eNoSubstates && stateClass && !stateClass->getSubstates().empty();
113
114 bool showStateClassName =
115 stateClass && (instanceName != stateClass->getStateName() /*|| !showSubstates*/);
116
117 const int renderFlags = static_cast<uint8_t>(Qt::TextSingleLine) |
118 static_cast<uint8_t>(Qt::AlignTop) |
119 static_cast<uint8_t>(Qt::AlignHCenter);
120
121 QRectF textRect = bounds;
122
123 float instanceNameWidthRelative = showSubstates ? 0.5f : 0.8f;
124
125
126 float instanceNameScaleFactor = textRect.width() * instanceNameWidthRelative /
127 painter->fontMetrics().width(instanceName);
128
129 if (showSubstates)
130 {
131 if (showStateClassName)
132 {
133 textRect.adjust(0, 10, 0, 0);
134 }
135 else
136 {
137 textRect.adjust(0, 20, 0, 0);
138 }
139 }
140 else
141 {
142 textRect.adjust(
143 0,
144 (bounds.height() - painter->fontMetrics().height() * instanceNameScaleFactor) / 2,
145 0,
146 0);
147 }
148
149 qreal lodT =
150 QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform());
151 QFont f = painter->font();
152 QRectF maxFsize(0, 0, 0, MAXFONTSIZE);
153 f.setPointSizeF(
154 std::min<float>(f.pointSizeF() * instanceNameScaleFactor, (maxFsize).height() / lodT));
155 painter->setFont(f);
156 float textHeightScale = 0.8;
157
158
159 if (showSubstates && state->getStateClass() &&
160 painter->fontMetrics().height() > 0.5 * state->getStateClass()->margin.top())
161 {
162 float margin = state->getStateClass()->margin.top();
163 float height = painter->fontMetrics().height();
164 float size = f.pointSizeF();
165 textHeightScale = margin / height;
166 if (showStateClassName)
167 {
168 textHeightScale *= 0.45;
169 }
170 else
171 {
172 textHeightScale *= 0.7;
173 }
174 f.setPointSizeF(size * textHeightScale);
175 painter->setFont(f);
176 // ARMARX_INFO << "Text to high: " << textHeightScale;
177 }
178
179 painter->setFont(f);
180 painter->drawText(textRect, renderFlags, instanceName);
181
182 if (showStateClassName && !stateClass->getStateName().isEmpty())
183 {
184 QString classNameText = "[state: " + stateClass->getStateName() + "]";
185 float instanceNamePointSize = f.pointSizeF();
186 float classNameScaleFactor =
187 textRect.width() * 0.8f / painter->fontMetrics().width(classNameText);
188
189
190 textRect.adjust(0, painter->fontMetrics().height() * 1.0, 0, 0);
191
192 lodT = QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform());
193 QRectF maxFsize(0, 0, 0, MAXFONTSIZE);
194 float classNamePointSize =
195 textHeightScale *
196 std::min<float>(f.pointSizeF() * classNameScaleFactor, (maxFsize).height() / lodT);
197 classNamePointSize = std::min(classNamePointSize,
198 instanceNamePointSize); // never bigger than instance name
199 f.setPointSizeF(classNamePointSize);
200 painter->setFont(f);
201
202 painter->drawText(textRect, renderFlags, classNameText);
203 }
204 }
205
206 void
208 {
210
211 if (signalType == statechartmodel::eChanged)
212 {
214 setRimColor();
215 update();
216 setSize(state->getClassSize());
217 setInstanceName(state->getInstanceName());
218 // ARMARX_WARNING_S << "Resizing " << state->getInstanceName() << VAROUT(state->getClassSize());
219 update(bounds);
220 }
221 }
222
223 void
226 {
227
228 switch (signalType)
229 {
231 {
232 // ARMARX_INFO << "substate added: " << substate->getInstanceName();
233 StateInstanceItemMap::iterator it = subStates.find(substate);
234
235 if (it != subStates.end())
236 {
237 ARMARX_WARNING << "substate already in list";
238 return;
239 }
240
241 StateItem* stateItem = new StateItem(substate, this);
242 subStates.insert(substate, stateItem);
243 connect(stateItem,
244 SIGNAL(stateItemMoved(QPointF)),
245 substate.get(),
246 SLOT(setPosition(QPointF)));
247 connect(stateItem,
248 SIGNAL(stateItemBoundingBoxChanged(float)),
249 substate.get(),
250 SLOT(setBoundingBox(float)));
251 stateItem->setInstanceName(substate->getInstanceName());
252 stateItem->setScale(substate->getScale());
253 // ARMARX_INFO_S << "topleft: " << substate->getTopLeft();
254 stateItem->setPos(substate->getTopLeft());
255 stateItem->setSize(substate->getClassSize());
256
257
258 stateItem->adjustSize();
259 update();
260 // ARMARX_INFO << "Added state " << stateName << " to Scene";
261 }
262 break;
263
265 {
266 // ARMARX_INFO << "substate changed: " << substate->getInstanceName();
267 StateInstanceItemMap::iterator it = subStates.find(substate);
268
269 if (it == subStates.end())
270 {
271 break;
272 }
273
274 StateItem* substateItem = it.value();
275 substateItem->setPos(substate->getTopLeft());
276 substateItem->setSize(substate->getClassSize());
277 substateItem->setScale(substate->getScale());
278 substateItem->setInstanceName(substate->getInstanceName());
279 substateItem->setStateColor();
280 substateItem->setRimColor();
282 }
283 break;
284
286 {
287 }
288 break;
289
291 {
292 // ARMARX_INFO << "Removing state " << substate->getInstanceName() << " from Scene";
293 StateInstanceItemMap::iterator it = subStates.find(substate);
294
295 if (it == subStates.end())
296 {
297 // ARMARX_INFO << "Could not find substate";
298 break;
299 }
300
301 QPointer<StateItem> substateItem = it.value();
302 subStates.remove(substate);
303 if (substateItem)
304 {
305 substateItem->prepareGeometryChange();
306 QObject::disconnect(substateItem);
307 delete substateItem.data();
308 }
309 }
310 break;
311
312 default:
313 // ARMARX_INFO << "Unhandled state changed";
314 break;
315 }
316 }
317
318 void
321 {
322 // ARMARX_INFO << "Transition Changed";
323 switch (signalType)
324 {
326 {
327 TransitionItem* t = new TransitionItem(transition, this);
328 transitions.insert(transition, t);
329 t->recalcPath();
330 connect(t,
331 SIGNAL(transitionEndPlaced(statechartmodel::TransitionCPtr, QPointF)),
332 this,
334 connect(t,
336 statechartmodel::TransitionCPtr, QPoint, QPointF)),
337 this,
339 statechartmodel::TransitionCPtr, QPoint, QPointF)));
340 }
341 break;
342
344 {
345 TransitionMap::iterator it = transitions.find(transition);
346
347 if (it == transitions.end())
348 {
349 break;
350 }
351 TransitionItem* t = it.value();
352 t->updateLabel();
353 t->recalcPath();
354 }
355 break;
356
358 {
359 TransitionMap::iterator it = transitions.find(transition);
360
361 if (it == transitions.end())
362 {
363 break;
364 }
365 // ARMARX_DEBUG << "Removing transition " << transition->eventName;
366 TransitionItem* t = it.value();
367 QObject::disconnect(t);
368 transitions.remove(transition);
369 // t->prepareGeometryChange();
370 delete t;
371 }
372 break;
374 {
375 TransitionMap::iterator it = transitions.find(transition);
376
377 if (it == transitions.end())
378 {
379 break;
380 }
381 int highlightDuration = 10000;
382 TransitionItem* t = it.value();
383 t->highlightAnimation(highlightDuration);
384 }
385 break;
386 default:
387
388 break;
389 }
390 }
391
392 void
395 {
396 TransitionMap::iterator it = transitions.begin();
397
398 for (; it != transitions.end(); it++)
399 {
400 auto t = it.key();
401
402 if (t->sourceState == state || t->destinationState == state)
403 {
404 notifyTransitionChanged(t, signalType);
405 }
406 }
407 }
408
409 void
411 QPoint mouseScreenPos,
412 QPointF mouseItemPos)
413 {
415 transition, state->getStateClass(), mouseScreenPos, mouseItemPos);
416 }
417
418 void
420 {
421 TransitionMap::iterator it = transitions.find(transition);
423
424 StateInstanceItemMap::iterator itState = subStates.begin();
425
426 for (; itState != subStates.end(); itState++)
427 {
428 StateItem* item = itState.value();
429 QPointF dropPointMapped = item->mapFromParent(dropPoint);
430
431 if (item->contains(dropPointMapped))
432 {
433
434 ARMARX_IMPORTANT << "dropped on " << item->getStateInstance()->getInstanceName();
435 QList<QPointF> suppPoint;
436 suppPoint.push_back(dropPoint);
437 state->getStateClass()->updateTransitionDestination(
438 transition, item->getStateInstance(), suppPoint);
439 return;
440 }
441 }
442
443 state->getStateClass()->detachTransitionDestination(transition, dropPoint);
444 }
445
446 void
448 {
449 // ui.substatesView->fitInView( substateScene->sceneRect(), Qt::KeepAspectRatio );
450 }
451
452 void
454 {
455 if (parentItem())
456 {
457 // ARMARX_INFO << "adjusting size";
458 // state->setBoundingBox(100);
459 // bounds.setWidth(parentItem()->boundingRect().width()*0.3);
460 // bounds.setHeight(parentItem()->boundingRect().height()*0.3);
461 }
462 }
463
464 void
465 StateItem::setup(QGraphicsItem* parent)
466 {
467 }
468
469 void
471 {
473
474 if (state->getStateClass())
475 {
476 connect(state->getStateClass().get(),
477 SIGNAL(stateChanged(statechartmodel::SignalType)),
478 this,
480 connect(state->getStateClass().get(),
481 SIGNAL(substateChanged(statechartmodel::StateInstancePtr,
483 this,
486 connect(state->getStateClass().get(),
487 SIGNAL(transitionChanged(statechartmodel::TransitionCPtr,
489 this,
492 connect(this,
493 SIGNAL(stateItemResized(QSizeF)),
494 state->getStateClass().get(),
495 SLOT(setSize(QSizeF)));
496 }
497
498 if (scene())
499 {
500 QVariant v;
501 v.setValue(scene());
502 itemChange(ItemSceneChange, v);
503 }
504 }
505
506 void
508 {
511
512 if (!state->getStateClass())
513 {
514 return;
515 }
516
517 const auto& ts = state->getStateClass()->getTransitions(true);
518
519 for (int i = 0; i < ts.size(); i++)
520 {
522 }
523
524 const auto& sl = state->getStateClass()->getSubstates();
525
526 for (auto i = sl.begin(); i != sl.end(); i++)
527 {
529 }
530 }
531
532 void
534 {
535 if (!state)
536 {
537 return;
538 }
539 int level = getInstanceLevel();
540 switch (state->getType())
541 {
542 case eNormalState:
543 {
544 QColor color(52, 152, 219);
545 if (level % 2 == 0)
546 {
547 color = color.lighter(130);
548 }
549 else
550 {
551 color = color.lighter(110);
552 }
553 setColor(color);
554 }
555 break;
556
557 case eRemoteState:
558 {
559 QColor color(26, 188, 156);
560 if (level % 2 == 0)
561 {
562 color = color.lighter(130);
563 }
564 else
565 {
566 color = color.lighter(110);
567 }
568 setColor(color);
569 }
570 break;
571
572 case eDynamicRemoteState:
573 setColor(QColor(155, 89, 182));
574 break;
575
576 case eFinalState:
577 {
578 QColor color(241, 196, 15);
579 color = color.lighter(120);
580 setColor(color);
581 }
582
583
584 default:
585 break;
586 }
587 }
588
589 void
591 {
592 if ((state && state->isActive()) || active)
593 {
594 setRimPen(QPen(Qt::red, 10));
595 }
596 else
597 {
598 setRimPen(QPen(Qt::black, 2));
599 }
600 update();
601 }
602
603 void
605 {
606 QString tip;
607 if (state)
608 {
609 tip = "StateType: " + statechartmodel::State::StateTypeToString(state->getType());
610 if (state->getStateClass())
611 {
612 auto desc = state->getStateClass()->getDescription();
613 if (!desc.isEmpty())
614 {
615 tip += "\n" + desc;
616 }
617 }
618 }
619 setToolTip(tip);
620 }
621
622 void
624 {
625 auto curScene = scene();
626 if (curScene)
627 {
628 for (auto& t : transitions)
629 {
630 // t->prepareGeometryChange();
631 curScene->removeItem(t);
632 }
633 }
634 for (auto& s : subStates)
635 {
636 s->prepareGeometryChange();
637 s->removeChildren();
638 if (curScene)
639 {
640 curScene->removeItem(s);
641 }
642 }
643 }
644
645 int
647 {
648 int level = 0;
649 const QGraphicsItem* parent = this;
650 while (dynamic_cast<StateItem*>(parent->parentItem()))
651 {
652 parent = parent->parentItem();
653 level++;
654 }
655 return level;
656 }
657
658 QPointF
660 {
661 if (state)
662 {
663 return state->adjustPosition(newPos);
664 }
665 ARMARX_INFO << "state ptr is null";
666 return newPos;
667 }
668
669 int
674
675 void
677 {
678 maxShownSubstateLevel = value;
679 for (auto& substate : subStates)
680 {
681 substate->setMaxShownSubstateLevel(value);
682 }
683 for (auto& item : childItems())
684 {
685 item->update();
686 }
687 }
688
689 void
690 StateItem::setActiveSubstate(const QString& substateName)
691 {
692 auto substates = getSubstateItems();
693 for (auto substate : substates)
694 {
695 bool active = (substate->getInstanceName() == substateName);
696 substate->setActiveState(active);
697 }
698 }
699
700 void
702 {
703 auto substates = getSubstateItems();
704 for (auto substate : substates)
705 {
706 substate->setActiveState(false);
707 }
708 }
709
710 QString
712 {
713 QString path = instanceName;
714 StateItem* parent = qgraphicsitem_cast<StateItem*>(parentItem());
715 while (parent)
716 {
717 path = parent->getInstanceName() + "/" + path;
718 parent = qgraphicsitem_cast<StateItem*>(parent->parentItem());
719 }
720 return path;
721 }
722
723 StateItem*
725 {
726 StateItem* parent = qgraphicsitem_cast<StateItem*>(parentItem());
727 return parent;
728 }
729
730 QVector<StateItem*>
732 {
733 QVector<StateItem*> result;
734 for (QGraphicsItem* item : this->childItems())
735 {
736 StateItem* state = dynamic_cast<StateItem*>(item);
737 if (state)
738 {
739 result.push_back(state);
740 }
741 }
742 return result;
743 }
744
745 QVector<TransitionItem*>
747 {
748 QVector<TransitionItem*> result;
749 for (QGraphicsItem* item : this->childItems())
750 {
751 TransitionItem* transition = dynamic_cast<TransitionItem*>(item);
752 if (transition)
753 {
754 result.push_back(transition);
755 }
756 }
757 return result;
758 }
759
760 QString
762 {
763 return instanceName;
764 }
765
766 void
767 StateItem::setInstanceName(const QString& value)
768 {
769 if (value != instanceName)
770 {
771 instanceName = value;
772 update();
773 }
774 }
775
776 void
778 {
779 this->active = active;
780 setRimColor();
781 }
782
783 bool
784 StateItem::itemResizing(const QRectF& oldSize, QRectF& proposedSize)
785 {
786 if (!state->getStateClass())
787 {
788 return false;
789 }
790
791 return true;
792 }
793
794 void
795 StateItem::itemResized(const QRectF& oldSize, const QRectF& newSize)
796 {
797 if (oldSize != newSize)
798 {
799 emit stateItemResized(newSize.size());
800 }
801 }
802
803 void
804 StateItem::itemMoved(const QPointF& oldPos, const QPointF& newPos)
805 {
806 // ARMARX_INFO << VAROUT(oldPos) << " " << VAROUT(newPos);
807 if (oldPos != newPos)
808 {
809 // ARMARX_INFO << "Changed";
810 emit stateItemMoved(newPos);
811 }
812 }
813
814 void
815 StateItem::itemBoundingBoxChanged(float oldSize, float size)
816 {
817
818 if (oldSize != size)
819 {
820 // ARMARX_INFO << VAROUT(oldSize) << " newBB: " << size;
822 }
823 }
824
825 void
826 StateItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
827 {
828 if (isLevelOfDetailLow(event))
829 {
830 event->ignore();
831 ARMARX_DEBUG << "Ignoring context menu event on " << state->getInstanceName();
832 return;
833 }
834 if (scene())
835 {
836 scene()->clearSelection();
837 }
838
839 this->setSelected(true);
840 emit stateContextMenuRequested(state, event->screenPos(), event->pos());
841 event->accept();
842 }
843
844 QVariant
845 StateItem::itemChange(GraphicsItemChange change, const QVariant& value)
846 {
847 if (change == ItemSelectedHasChanged && value.toBool() == true)
848 {
849 // ARMARX_IMPORTANT << state->getInstanceName() << " was selected with scale " << scale();
850 // setScale(scale()*1.1);
851 }
852 else if (change == ItemSelectedHasChanged && value.toBool() == false)
853 {
854 // ARMARX_IMPORTANT << state->getInstanceName() << " was UNselected";
855 // setScale(scale()*0.9);
856 }
857 else if (change == ItemScaleHasChanged)
858 {
859 emit stateItemBoundingBoxChanged(std::max(bounds.width(), bounds.height()) *
860 value.toFloat());
861 // itemBoundingBoxChanged(std::max(oldRect.width(), oldRect.height()),
862 // std::max(bounds.width(), bounds.height()));
863 // emit stateItemScaled(value.toFloat());
864 }
865 else if (change == ItemSceneChange)
866 {
867 StateScene* oldStateScene = dynamic_cast<StateScene*>(scene());
868
869 if (oldStateScene)
870 {
871 disconnect(this,
873 statechartmodel::StateInstancePtr, QPoint, QPointF)),
874 oldStateScene,
876 statechartmodel::StateInstancePtr, QPoint, QPointF)));
877 disconnect(this,
880 QPoint,
881 QPointF)),
882 oldStateScene,
885 QPoint,
886 QPointF)));
887 }
888
889 StateScene* stateScene = dynamic_cast<StateScene*>(value.value<QGraphicsScene*>());
890
891 if (stateScene)
892 {
893 // ARMARX_INFO_S << "scene OF " << state->getInstanceName() << " has changed - StateScene";
894 connect(this,
896 statechartmodel::StateInstancePtr, QPoint, QPointF)),
899 statechartmodel::StateInstancePtr, QPoint, QPointF)));
900 connect(this,
903 QPoint,
904 QPointF)),
908 QPoint,
909 QPointF)));
910 }
911
912 // else
913 // ARMARX_INFO_S << "scene OF " << state->getInstanceName() << " has changed - noScene";
914 }
915
916 return RoundRectItem::itemChange(change, value);
917 }
918
919 void
920 StateItem::dragEnterEvent(QGraphicsSceneDragDropEvent* event)
921 {
922 // ARMARX_INFO << "Drag Enter event " << state->getInstanceName();
924 qobject_cast<const AbstractStateMimeData*>(event->mimeData());
925
926 if (data && state && state->getStateClass() && data->getState() &&
927 state->getType() == eNormalState)
928 {
929 event->setDropAction(Qt::LinkAction);
930 }
931 else
932 {
933 event->setDropAction(Qt::IgnoreAction);
934 }
935
936 event->accept();
937 }
938
939 void
940 StateItem::dragMoveEvent(QGraphicsSceneDragDropEvent* event)
941 {
942 dragEnterEvent(event);
943 }
944
945 void
946 StateItem::dropEvent(QGraphicsSceneDragDropEvent* event)
947 {
948 // ARMARX_INFO << "drop event " << state->getInstanceName();
949 if (event->proposedAction() == Qt::IgnoreAction)
950 {
951 return;
952 }
953
955 qobject_cast<const AbstractStateMimeData*>(event->mimeData());
956 bool accept = true;
957 if (data && state && state->getStateClass() && data->getState() &&
958 (state->getType() == eNormalState || state->getType() == eRemoteState))
959 {
960 int i = 2;
961 const QString newStateNameBase = data->getState()->getStateName();
962 QString newStateName = newStateNameBase;
963
964 while (state->getStateClass()->getSubstates().find(newStateName) !=
965 state->getStateClass()->getSubstates().end())
966 {
967 newStateName = newStateNameBase + "_" + QString::number(i);
968 i++;
969 }
970
971 if (hasAncestor(data->getState()) ||
972 data->getState()->hasDescendant(state->getStateClass()))
973 {
974 QMessageBox::warning(event->source(),
975 "State drag'n'drop error",
976 "State cycle detected - you must not insert a state which is "
977 "also a parent state of the current state");
978 accept = false;
979 }
980 else if (data->getState()->getType() == eDynamicRemoteState &&
981 !data->isInSameGroup(state->getStateClass()))
982 {
983 QMessageBox::warning(event->source(),
984 "State drag'n'drop error",
985 "Dynamic Remote States can only be added in the same group.");
986 accept = false;
987 }
988 else if (data->isInSameGroup(state->getStateClass()))
989 {
990 if (data->getState()->getType() == eDynamicRemoteState)
991 {
992 state->getStateClass()->addDynamicRemoteSubstate(
993 data->getState(), newStateName, event->pos());
994 }
995 else
996 {
997 state->getStateClass()->addSubstate(
998 data->getState(), newStateName, event->pos());
999 }
1000 }
1001 else if (data->isPublic())
1002 {
1003 state->getStateClass()->addRemoteSubstate(
1004 data->getState(), data->getProxyName(), newStateName, event->pos());
1005 }
1006 else
1007 {
1008 QMessageBox::warning(event->source(),
1009 "State drag'n'drop error",
1010 "Only public states can be added as a Remote State.");
1011 accept = false;
1012 }
1013 }
1014 else
1015 {
1016 accept = false;
1017 }
1018
1019
1020 if (accept)
1021 {
1022 event->setDropAction(Qt::LinkAction);
1023 event->accept();
1024 }
1025 else
1026 {
1027 event->setDropAction(Qt::IgnoreAction);
1028 event->accept();
1029 }
1030 }
1031
1032 bool
1034 {
1035 if (!sC)
1036 {
1037 return false;
1038 }
1039
1040 StateItem* state = qgraphicsitem_cast<StateItem*>(parentItem());
1041 if (!state)
1042 {
1043 return false;
1044 }
1045 if (!state->getStateInstance() || !state->getStateInstance()->getStateClass())
1046 {
1047 return false;
1048 }
1049
1050 if (state->getStateInstance()->getStateClass()->getUUID() == sC->getUUID())
1051 {
1052 return true;
1053 }
1054
1055 return state->hasAncestor(sC);
1056 }
1057
1058 bool
1060 {
1061 if (!sC || !state->getStateClass())
1062 {
1063 return false;
1064 }
1065 return state->getStateClass()->hasDescendant(sC);
1066 }
1067
1069 StateItem::getLevelOfDetail(float levelOfDetail) const
1070 {
1071 if (maxShownSubstateLevel >= 0) // only show X levels of substates
1072 {
1073 int level = getInstanceLevel();
1074 if (level > maxShownSubstateLevel)
1075 {
1076 return eHidden;
1077 }
1078 else if (level >= maxShownSubstateLevel)
1079 {
1080 return eNoSubstates;
1081 }
1082 }
1083 return MorphingItem::getLevelOfDetail(levelOfDetail);
1084 }
1085} // namespace armarx
#define option(type, fn)
#define MAXFONTSIZE
Definition StateItem.cpp:46
bool isLevelOfDetailLow(QGraphicsSceneEvent *event) const
RoundRectItem(const QRectF &bounds, const QColor &color, QGraphicsItem *parent=0)
void setEditable(bool editable)
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0) override
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override
void setColor(QColor newColor)
void setRimPen(QPen newPen)
void setSize(const QSizeF &newSize)
The AbstractStateMimeData class is used to transport state data from the treeview to the stateview an...
MorphingItem(QGraphicsItem *derivedItem)
virtual LevelOfDetail getLevelOfDetail(QPainter *painter) const
virtual LevelOfDetail getLevelOfDetailByParent(QPainter *painter, MorphingItem *parent) const
void stateItemBoundingBoxChanged(float newSquareBoundingBoxSize)
void transitionMoved(statechartmodel::TransitionCPtr transition, QPointF dropPoint)
void notifyStateChanged(statechartmodel::SignalType signalType)
void itemResized(const QRectF &oldSize, const QRectF &newSize) override
void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override
QPointF adjustPosition(QPointF &newPos) override
QString getInstanceName() const
bool hasDescendant(statechartmodel::StatePtr state) const
void setActiveState(bool active)
QString getFullStatePath() const
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
QString instanceName
Definition StateItem.h:133
LevelOfDetail getLevelOfDetail(float levelOfDetail) const override
void notifyTransitionChanged(statechartmodel::TransitionCPtr transition, statechartmodel::SignalType signalType)
void transitionContextMenuRequested(statechartmodel::TransitionCPtr transition, statechartmodel::StatePtr state, QPoint mouseScreenPos, QPointF mouseItemPos)
TransitionMap transitions
Definition StateItem.h:135
bool hasAncestor(statechartmodel::StatePtr state) const
int getMaxShownSubstateLevel() const
void forwardTransitionContextMenuRequested(statechartmodel::TransitionCPtr transition, QPoint mouseScreenPos, QPointF mouseItemPos)
QVector< StateItem * > getSubstateItems() const
statechartmodel::StateInstancePtr getStateInstance() const
Definition StateItem.h:66
QVector< TransitionItem * > getTransitionItems() const
void notifySubstateChanged(statechartmodel::StateInstancePtr substate, statechartmodel::SignalType signalType)
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override
void stateItemResized(QSizeF newSize)
void setInstanceName(const QString &value)
void itemBoundingBoxChanged(float oldSize, float size) override
void itemMoved(const QPointF &oldPos, const QPointF &newPos) override
StateItem * getParentStateItem() const
void setup(QGraphicsItem *parent)
void stateItemMoved(QPointF newPosition)
void clearActiveSubstate()
int getInstanceLevel() const
void stateContextMenuRequested(statechartmodel::StateInstancePtr stateInstace, QPoint mouseScreenPos, QPointF mouseItemPos)
statechartmodel::StateInstancePtr state
Definition StateItem.h:130
void dropEvent(QGraphicsSceneDragDropEvent *event) override
~StateItem() override
Definition StateItem.cpp:75
void setMaxShownSubstateLevel(int value)
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
Definition StateItem.cpp:81
StateItem(statechartmodel::StateInstancePtr state, QGraphicsItem *parent=0)
Definition StateItem.cpp:50
bool itemResizing(const QRectF &oldSize, QRectF &proposedSize) override
StateInstanceItemMap subStates
Definition StateItem.h:132
void notifyTransitionsChanged(statechartmodel::StateInstancePtr transition, statechartmodel::SignalType signalType)
StateScene * stateScene
Definition StateItem.h:129
void setActiveSubstate(const QString &substateName)
void highlightAnimation(int duration=5000)
static QString StateTypeToString(eStateType type)
Definition State.cpp:1294
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
std::shared_ptr< State > StatePtr
Definition State.h:48
std::shared_ptr< StateInstance > StateInstancePtr
std::shared_ptr< const Transition > TransitionCPtr
Definition Transition.h:91
SignalType
The SignalType enum.
Definition SignalType.h:34
This file offers overloads of toIce() and fromIce() functions for STL container types.
@ eNoSubstates