1 /**
2  * UGENE - Integrated Bioinformatics Tools.
3  * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4  * http://ugene.net
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  */
21 
22 #ifndef _U2_WORKFLOW_VIEW_ITEMS_H_
23 #define _U2_WORKFLOW_VIEW_ITEMS_H_
24 
25 #include <QAction>
26 #include <QGraphicsItem>
27 #include <QGraphicsScene>
28 #include <QWidget>
29 
30 #include "U2Lang/LocalDomain.h"
31 #include <U2Lang/ActorModel.h>
32 
33 class QDomElement;
34 
35 namespace U2 {
36 using namespace Workflow;
37 class WorkflowScene;
38 class ItemViewStyle;
39 class WorkflowHighlightItem;
40 
41 typedef QString StyleId;
42 
43 #define GRID_STEP 15
44 #define ANGLE_STEP 10
45 
round(qreal val,int step)46 inline qreal round(qreal val, int step) {
47     int tmp = int(val) + step / 2;
48     tmp -= tmp % step;
49     return qreal(tmp);
50 }
roundUp(qreal val,int step)51 inline qreal roundUp(qreal val, int step) {
52     int tmp = int(val) + step / 2;
53     tmp -= tmp % step;
54     if (tmp < int(val)) {
55         tmp += step;
56     }
57     return qreal(tmp);
58 }
59 
60 class ItemStyles {
61 public:
62     static const StyleId SIMPLE;
63     static const StyleId EXTENDED;
64 };
65 
66 class StyledItem : public QGraphicsItem {
67 public:
68     StyledItem(QGraphicsItem *p = 0)
QGraphicsItem(p)69         : QGraphicsItem(p) {
70     }
71     WorkflowScene *getWorkflowScene() const;
~StyledItem()72     virtual ~StyledItem() {
73     }
setStyle(StyleId)74     virtual void setStyle(StyleId) {
75     }
getStyle()76     virtual StyleId getStyle() const {
77         return ItemStyles::SIMPLE;
78     }
getContextMenuActions()79     virtual QList<QAction *> getContextMenuActions() const {
80         return QList<QAction *>();
81     }
82 };
83 
84 class WorkflowPortItem;
85 class WorkflowBusItem;
86 enum {
87     WorkflowProcessItemType = QGraphicsItem::UserType + 1,
88     WorkflowPortItemType,
89     WorkflowBusItemType
90 };
91 
92 enum InspectionItemOrientationType {
93     InspectionLeft,
94     InspectionRight,
95     InspectionUp,
96     InspectionDown
97 };
98 
99 class WorkflowProcessItem : public QObject, public StyledItem {
100     Q_OBJECT
101 public:
102     WorkflowProcessItem(Actor *process);
103     virtual ~WorkflowProcessItem();
getProcess()104     Actor *getProcess() const {
105         return process;
106     }
107     WorkflowPortItem *getPort(const QString &id) const;
getPortItems()108     QList<WorkflowPortItem *> getPortItems() const {
109         return ports;
110     }
111     QRectF boundingRect(void) const;
112     QRectF portsBoundingRect() const;
113     QPainterPath shape() const;
114 
115     virtual void setStyle(StyleId);
getStyle()116     virtual StyleId getStyle() const {
117         return styles.key(currentStyle);
118     }
119 
120     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
121     enum { Type = WorkflowProcessItemType };
type()122     int type() const {
123         return Type;
124     }
prepareUpdate()125     void prepareUpdate() {
126         prepareGeometryChange();
127     }
128 
129     virtual QList<QAction *> getContextMenuActions() const;
130 
131     void saveState(QDomElement &) const;
132     void loadState(QDomElement &);
133 
134     ItemViewStyle *getStyleByIdSafe(StyleId id) const;
135     ItemViewStyle *getStyleById(const StyleId &id) const;
136     bool containsStyle(const StyleId &id) const;
137     void updatePorts();
138 
139     void toggleBreakpointState();
140     void toggleBreakpoint();
141     bool isBreakpointInserted();
142     bool isBreakpointEnabled();
143     void highlightItem();
144 
145 protected:
146     QVariant itemChange(GraphicsItemChange change, const QVariant &value);
147     virtual bool sceneEvent(QEvent *event);
148     virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
149     virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
150 
151 public slots:
152     void sl_update();
153 
154 private slots:
155     void sl_descriptionChanged();
156 
157 private:
158     void createPorts();
159     QMap<StyleId, ItemViewStyle *> styles;
160     ItemViewStyle *currentStyle;
161     Actor *process;
162     QList<WorkflowPortItem *> ports;
163     QMap<QGraphicsItem *, QPointF> initialPositions;
164     bool hasBreakpoint;
165     bool hasEnabledBreakpoint;
166     WorkflowHighlightItem *highlighting;
167 };
168 
169 class WorkflowPortItem : public QObject, public StyledItem {
170     Q_OBJECT
171 public:
172     WorkflowPortItem(WorkflowProcessItem *owner, Port *port);
173     virtual ~WorkflowPortItem();
getPort()174     Port *getPort() const {
175         return port;
176     }
getOwner()177     WorkflowProcessItem *getOwner() const {
178         return owner;
179     }
getDataFlows()180     QList<WorkflowBusItem *> getDataFlows() const {
181         return flows;
182     }
183     WorkflowBusItem *getDataFlow(const WorkflowPortItem *other) const;
184     WorkflowPortItem *checkBindCandidate(const QGraphicsItem *it) const;
185     WorkflowPortItem *findNearbyBindingCandidate(const QPointF &at) const;
186     void addDataFlow(WorkflowBusItem *flow);
187     void removeDataFlow(WorkflowBusItem *flow);
188     // position of the arrow tip in items coordinates
189     QPointF head(const QGraphicsItem *item) const;
190     // position of the arrow tip in scene coordinates
191     QPointF headToScene() const;
192     // direction of the arrow in items coordinates
193     QLineF arrow(const QGraphicsItem *item) const;
194     QRectF boundingRect(void) const;
195     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
196 
getOrientarion()197     qreal getOrientarion() const {
198         return orientation;
199     }
200     void setOrientation(qreal);
201 
202     virtual void setStyle(StyleId);
getStyle()203     virtual StyleId getStyle() const {
204         return currentStyle;
205     }
206     void adaptOwnerShape();
207 
setHighlight(bool v)208     void setHighlight(bool v) {
209         highlight = v;
210     }
211 
212     enum { Type = WorkflowPortItemType };
type()213     int type() const {
214         return Type;
215     }
216 
217 protected:
218     void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
219     void mousePressEvent(QGraphicsSceneMouseEvent *event);
220     void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
221     void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
222     void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
223     void focusOutEvent(QFocusEvent *event);
224     QVariant itemChange(GraphicsItemChange change, const QVariant &value);
225 public slots:
226     void sl_onVisibleChanged(bool);
227 
228 private:
229     StyleId currentStyle;
230 
231     Port *port;
232     WorkflowProcessItem *owner;
233     qreal orientation;
234     QList<WorkflowBusItem *> flows;
235     bool dragging;
236     bool rotating;
237     bool sticky;
238     bool highlight;
239     bool mouseMoveIsBeingProcessed;  // the field is needed to prevent a recursion during mouse events processing
240     QList<WorkflowPortItem *> bindCandidates;
241     QPointF dragPoint;
242 };
243 
244 class WorkflowBusItem : public QObject, public StyledItem {
245     Q_OBJECT
246     friend class WorkflowPortItem;
247     friend class WorkflowProcessItem;
248 
249 public:
250     WorkflowBusItem(WorkflowPortItem *p1, WorkflowPortItem *p2, Link *link);
251     virtual ~WorkflowBusItem();
getInPort()252     WorkflowPortItem *getInPort() const {
253         return dst;
254     }
getOutPort()255     WorkflowPortItem *getOutPort() const {
256         return src;
257     }
getBus()258     Link *getBus() const {
259         return bus;
260     }
261     QRectF boundingRect(void) const;
262     QPainterPath shape() const;
263     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
264     enum { Type = WorkflowBusItemType };
type()265     int type() const {
266         return Type;
267     }
268     bool validate();
269 
270     void saveState(QDomElement &) const;
271     void loadState(QDomElement &);
272 
getText()273     QGraphicsItem *getText() const {
274         return text;
275     }
276     void updatePos();
277 
278 protected:
279     QVariant itemChange(GraphicsItemChange change, const QVariant &value);
280     // void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
281     // void mousePressEvent ( QGraphicsSceneMouseEvent * event );
282     // void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event );
283     void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
284     void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
285 
286 private slots:
287     void sl_update();
288 
289 private:
290     Link *bus;
291     WorkflowPortItem *dst, *src;
292     QGraphicsItem *text;
293     // bool dragging;
294     // QPointF dragPoint;
295 };
296 
297 class WorkflowHighlightItem : public StyledItem {
298 public:
299     WorkflowHighlightItem(WorkflowProcessItem *owner);
300     QRectF boundingRect() const;
301     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
302 
303     void replay();
304 
305 private:
306     quint8 countOfAnimationStepsLeft;
307 };
308 
309 }  // namespace U2
310 
311 Q_DECLARE_METATYPE(U2::StyleId);
312 
313 #endif
314