1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2002-2021 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 #ifndef UMLSCENE_H
7 #define UMLSCENE_H
8 
9 // local includes
10 #include "associationwidgetlist.h"
11 #include "basictypes.h"
12 #include "classifierwidget.h"
13 #include "messagewidgetlist.h"
14 #include "optionstate.h"
15 #include "umlobject.h"
16 #include "umlobjectlist.h"
17 #include "umlwidgetlist.h"
18 #include "worktoolbar.h"
19 #include "widgetbase.h"
20 
21 // Qt includes
22 #include <QDomDocument>
23 #include <QGraphicsScene>
24 #include <QGraphicsItem>
25 #include <QGraphicsSceneMouseEvent>
26 #include <QGraphicsPolygonItem>
27 #include <QKeyEvent>
28 #include <QMouseEvent>
29 #include <QPixmap>
30 #include <QXmlStreamWriter>
31 
32 // forward declarations
33 class ClassOptionsPage;
34 class IDChangeLog;
35 class LayoutGrid;
36 class FloatingTextWidget;
37 class ObjectWidget;
38 class ToolBarState;
39 class ToolBarStateFactory;
40 class UMLFolder;
41 class UMLDoc;
42 class UMLAttribute;
43 class UMLCanvasObject;
44 class UMLClassifier;
45 class UMLViewImageExporter;
46 class UMLForeignKeyConstraint;
47 class UMLEntity;
48 class UMLView;
49 
50 class QHideEvent;
51 class QMouseEvent;
52 class QPrinter;
53 class QShowEvent;
54 class UMLScenePrivate;
55 
56 // migration wrapper for QGraphicsScene items
57 typedef QList<QGraphicsItem*> UMLSceneItemList;
58 
59 /**
60  * UMLScene instances represent diagrams.
61  * The UMLScene class inherits from QGraphicsScene and it owns the
62  * objects displayed (see m_WidgetList.)
63  */
64 class UMLScene : public QGraphicsScene
65 {
66     Q_OBJECT
67 public:
68     friend class UMLViewImageExporterModel;
69 
70     explicit UMLScene(UMLFolder *parentFolder, UMLView *view = 0);
71     virtual ~UMLScene();
72 
73     UMLView* activeView() const;
74 
75     // Accessors and other methods dealing with loaded/saved data
76 
77     UMLFolder* folder() const;
78     void setFolder(UMLFolder *folder);
79 
80     QString documentation() const;
81     void setDocumentation(const QString &doc);
82 
83     bool autoIncrementSequence() const;
84     void setAutoIncrementSequence(bool state);
85     QString autoIncrementSequenceValue();
86 
87     QString name() const;
88     void setName(const QString &name);
89 
90     Uml::DiagramType::Enum type() const;
91     void setType(Uml::DiagramType::Enum type);
92 
93     Uml::ID::Type ID() const;
94     void setID(Uml::ID::Type id);
95 
96     QPointF pos() const;
97     void setPos(const QPointF &pos);
98 
99     const QColor& fillColor() const;
100     void setFillColor(const QColor &color);
101 
102     const QColor& lineColor() const;
103     void setLineColor(const QColor &color);
104 
105     uint lineWidth() const;
106     void setLineWidth(uint width);
107 
108     const QColor& textColor() const;
109     void setTextColor(const QColor& color);
110 
111     const QColor& gridDotColor() const;
112     void setGridDotColor(const QColor& color);
113 
114     const QColor& backgroundColor() const;
115 
116     bool snapToGrid() const;
117     void setSnapToGrid(bool bSnap);
118 
119     bool snapComponentSizeToGrid() const;
120     void setSnapComponentSizeToGrid(bool bSnap);
121 
122     int snapX() const;
123     int snapY() const;
124     void setSnapSpacing(int x, int y);
125 
126     qreal snappedX(qreal x);
127     qreal snappedY(qreal y);
128 
129     bool isSnapGridVisible() const;
130     void setSnapGridVisible(bool bShow);
131 
132     bool isShowDocumentationIndicator() const;
133     void setShowDocumentationIndicator(bool bShow);
134 
135     bool useFillColor() const;
136     void setUseFillColor(bool ufc);
137 
138     QFont font() const;
139     void setFont(QFont font, bool changeAllWidgets = false);
140 
141     bool showOpSig() const;
142     void setShowOpSig(bool bShowOpSig);
143 
144     Settings::OptionState& optionState();
145     void setOptionState(const Settings::OptionState& options);
146 
147     const AssociationWidgetList associationList() const;
148     const MessageWidgetList messageList() const;
149     const UMLWidgetList widgetList() const;
150     void addWidgetCmd(UMLWidget* widget);
151     void addWidgetCmd(AssociationWidget *widget);
152 
153     bool isOpen() const;
154     void setIsOpen(bool isOpen);
155 
156     // End of accessors and methods that only deal with loaded/saved data
157     ////////////////////////////////////////////////////////////////////////
158 
159     void print(QPrinter *pPrinter, QPainter & pPainter);
160 
161     void hideEvent(QHideEvent *he);
162     void showEvent(QShowEvent *se);
163 
164     void checkMessages(ObjectWidget * w);
165 
166     UMLWidget* findWidget(Uml::ID::Type id);
167 
168     AssociationWidget* findAssocWidget(Uml::ID::Type id);
169     AssociationWidget* findAssocWidget(Uml::AssociationType::Enum at,
170                                        UMLWidget *pWidgetA, UMLWidget *pWidgetB);
171     AssociationWidget* findAssocWidget(UMLWidget *pWidgetA,
172                                        UMLWidget *pWidgetB, const QString& roleNameB);
173 
174     void removeWidget(UMLWidget *o);
175     void removeWidget(AssociationWidget *w);
176     void removeWidgetCmd(UMLWidget *o);
177 private:
178     void removeOwnedWidgets(UMLWidget* o);
179 public:
180 
181     UMLWidgetList selectedWidgets() const;
182     AssociationWidgetList selectedAssociationWidgets() const;
183     UMLWidgetList selectedMessageWidgets() const;
184     void clearSelected();
185 
186     void moveSelectedBy(qreal dX, qreal dY);
187 
188     int selectedCount(bool filterText = false) const;
189 
190     void selectionUseFillColor(bool useFC);
191     void selectionSetFont(const QFont &font);
192     void selectionSetLineColor(const QColor &color);
193     void selectionSetLineWidth(uint width);
194     void selectionSetFillColor(const QColor &color);
195     void selectionSetVisualProperty(ClassifierWidget::VisualProperty property, bool value);
196 
197 private:
198     void unselectChildrenOfSelectedWidgets();
199 public:
200     void deleteSelection();
201     void resizeSelection();
202 
203     void selectAll();
204 
205     UMLWidget* widgetOnDiagram(Uml::ID::Type id);
206     UMLWidget *widgetOnDiagram(WidgetBase::WidgetType type);
207 
208     bool isSavedInSeparateFile();
209 
210     void setMenu(const QPoint& pos);
211 
212     void resetToolbar();
213     void triggerToolbarButton(WorkToolBar::ToolBar_Buttons button);
214 
215     bool getPaste() const;
216     void setPaste(bool paste);
217 
218     void activate();
219 
220     AssociationWidgetList selectedAssocs();
221     UMLWidgetList selectedWidgetsExt(bool filterText = true);
222 
223     void activateAfterLoad(bool bUseLog = false);
224 
225     void endPartialWidgetPaste();
226     void beginPartialWidgetPaste();
227 
228     void removeWidgetCmd(AssociationWidget* pAssoc);
229     void removeAssociations(UMLWidget* pWidget);
230     void selectAssociations(bool bSelect);
231 
232     void getWidgetAssocs(UMLObject* Obj, AssociationWidgetList & Associations);
233 
234     void removeAllAssociations();
235 
236     void removeAllWidgets();
237 
238     void getDiagram(QPixmap & diagram, const QRectF &rect);
239     void getDiagram(QPainter &painter, const QRectF &source, const QRectF &target = QRectF());
240 
241     void copyAsImage(QPixmap*& pix);
242 
243     UMLViewImageExporter* getImageExporter();
244 
245     bool addAssociation(AssociationWidget* pAssoc, bool isPasteOperation = false);
246 
247     void removeAssocInViewAndDoc(AssociationWidget* assoc);
248 
249     void addFloatingTextWidget(FloatingTextWidget* pWidget);
250 
251     QPointF getPastePoint();
252     void resetPastePoint();
253 
254     void setStartedCut();
255 
256     void createAutoAssociations(UMLWidget * widget);
257     void createAutoAttributeAssociations(UMLWidget *widget);
258     void createAutoConstraintAssociations(UMLWidget* widget);
259     void createAutoAttributeAssociations2(UMLWidget *widget);
260 
261     void updateContainment(UMLCanvasObject *self);
262 
263     void setClassWidgetOptions(ClassOptionsPage * page);
264 
265     WidgetBase::WidgetType getUniqueSelectionType();
266 
267     void clearDiagram();
268 
269     void applyLayout(const QString &actionText);
270 
271     void toggleSnapToGrid();
272     void toggleSnapComponentSizeToGrid();
273     void toggleShowGrid();
274 
275     void fileLoaded();
276 
277     void resizeSceneToItems();
278 
279     // Load/Save interface:
280 
281     virtual void saveToXMI1(QXmlStreamWriter& writer);
282     virtual bool loadFromXMI1(QDomElement & qElement);
283 
284     bool loadUISDiagram(QDomElement & qElement);
285     UMLWidget* loadWidgetFromXMI(QDomElement& widgetElement);
286 
287     void addObject(UMLObject *object);
288 
289     void selectWidgets(qreal px, qreal py, qreal qx, qreal qy);
290     void selectWidgets(UMLWidgetList &widgets);
291     void selectWidget(UMLWidget* widget, QRectF* rect = 0);
292     void selectWidgetsOfAssoc(AssociationWidget *a);
293 
294     ObjectWidget * onWidgetLine(const QPointF &point) const;
295     ObjectWidget * onWidgetDestructionBox(const QPointF &point) const;
296 
297     UMLWidget* getFirstMultiSelectedWidget() const;
298 
299     UMLWidget* widgetAt(const QPointF& p);
300     AssociationWidget* associationAt(const QPointF& p);
301     MessageWidget* messageAt(const QPointF& p);
302 
303     void setupNewWidget(UMLWidget *w, bool setPosition=true);
304 
305     bool getCreateObject() const;
306     void setCreateObject(bool bCreate);
307 
308     int generateCollaborationId();
309 
310     UMLSceneItemList collisions(const QPointF &p, int delta = 3);
311 
isClassDiagram()312     bool isClassDiagram()              const { return type() == Uml::DiagramType::Class;  }
isUseCaseDiagram()313     bool isUseCaseDiagram()            const { return type() == Uml::DiagramType::UseCase; }
isSequenceDiagram()314     bool isSequenceDiagram()           const { return type() == Uml::DiagramType::Sequence; }
isCollaborationDiagram()315     bool isCollaborationDiagram()      const { return type() == Uml::DiagramType::Collaboration; }
isStateDiagram()316     bool isStateDiagram()              const { return type() == Uml::DiagramType::State; }
isActivityDiagram()317     bool isActivityDiagram()           const { return type() == Uml::DiagramType::Activity; }
isComponentDiagram()318     bool isComponentDiagram()          const { return type() == Uml::DiagramType::Component; }
isDeploymentDiagram()319     bool isDeploymentDiagram()         const { return type() == Uml::DiagramType::Deployment; }
isEntityRelationshipDiagram()320     bool isEntityRelationshipDiagram() const { return type() == Uml::DiagramType::EntityRelationship; }
isObjectDiagram()321     bool isObjectDiagram()             const { return type() == Uml::DiagramType::Object; }
322 
323     void setWidgetLink(WidgetBase *w);
324     WidgetBase *widgetLink();
325 
326 protected:
327     // Methods and members related to loading/saving
328 
329     bool loadWidgetsFromXMI(QDomElement & qElement);
330     bool loadMessagesFromXMI(QDomElement & qElement);
331     bool loadAssociationsFromXMI(QDomElement & qElement);
332     bool loadUisDiagramPresentation(QDomElement & qElement);
333 
334     /**
335      * Contains the unique ID to allocate to a widget that needs an
336      * ID for the view.  @ref ObjectWidget is an example of this.
337      */
338     Uml::ID::Type          m_nLocalID;
339 
340     Uml::ID::Type          m_nID;      ///< The ID of the view. Allocated by @ref UMLDoc.
341     Uml::DiagramType::Enum m_Type;     ///< The type of diagram to represent.
342     QString                m_Name;     ///< The name of the diagram.
343     QString          m_Documentation;  ///< The documentation of the diagram.
344     Settings::OptionState  m_Options;  ///< Options used by view.
345 
346     bool m_bUseSnapToGrid;  ///< Flag to use snap to grid. The default is off.
347     bool m_bUseSnapComponentSizeToGrid;  ///< Flag to use snap to grid for component size. The default is off.
348     bool m_isOpen;  ///< Flag is set to true when diagram is open, i.e. shown to the user.
349 
350     // End of methods and members related to loading/saving
351     ////////////////////////////////////////////////////////////////////////
352 
353     void dragEnterEvent(QGraphicsSceneDragDropEvent* enterEvent);
354     void dragMoveEvent(QGraphicsSceneDragDropEvent* moveEvent);
355     void dropEvent(QGraphicsSceneDragDropEvent* dropEvent);
356 
357     void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent);
358     void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent);
359     void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* mouseEvent);
360     void mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent);
361     virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
362 
363     QRectF diagramRect();
364 
365     void makeSelected(UMLWidget* uw);
366 
367     void updateComponentSizes();
368 
369     void findMaxBoundingRectangle(const FloatingTextWidget* ft,
370                                   qreal& px, qreal& py, qreal& qx, qreal& qy);
371     void forceUpdateWidgetFontMetrics(QPainter *painter);
372 
373     virtual void drawBackground(QPainter *painter, const QRectF &rect);
374 
375 #if QT_VERSION >= 0x050000
376 #if !(QT_DEPRECATED_SINCE(5, 0))
itemAt(const QPointF & position)377     inline QGraphicsItem *itemAt(const QPointF &position) const {
378         QList<QGraphicsItem *> itemsAtPoint = items(position);
379         return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
380     }
381 #endif
382 #endif
383 
384     int m_nCollaborationId;  ///< Used for creating unique name of collaboration messages.
385     QPointF m_pos;
386     bool m_bCreateObject;
387     bool m_bDrawSelectedOnly;
388     bool m_bPaste;
389     bool m_bStartedCut;  ///< Flag if view/children started cut operation.
390 
391 private:
392     UMLScenePrivate *m_d;
393     static const qreal defaultCanvasSize;  ///< The default size of a diagram in pixels.
394     static bool m_showDocumentationIndicator; ///< Status of documentation indicator
395 
396     UMLView *m_view;   ///< The view to which this scene is related.
397     UMLFolder *m_pFolder;  ///< The folder in which this UMLView is contained.
398 
399     IDChangeLog * m_pIDChangesLog;  ///< LocalID Changes Log for paste actions
400     bool m_isActivated;             ///< True if the view was activated after the serialization(load).
401     bool m_bPopupShowing;           ///< Status of a popupmenu on view. True - a popup is on view.
402     QPointF m_PastePoint;     ///< The offset at which to paste the clipboard.
403     UMLDoc* m_doc;                  ///< Pointer to the UMLDoc.
404     UMLViewImageExporter* m_pImageExporter;  ///< Used to export the view.
405     LayoutGrid*  m_layoutGrid;      ///< layout grid in the background
406     bool m_autoIncrementSequence; ///< state of auto increment sequence
407 
408     void createAutoAttributeAssociation(UMLClassifier *type,
409                                         UMLAttribute *attr,
410                                         UMLWidget *widget);
411     void createAutoConstraintAssociation(UMLEntity* refEntity,
412                                          UMLForeignKeyConstraint* fkConstraint,
413                                          UMLWidget* widget);
414 
415 public slots:
416     void slotToolBarChanged(int c);
417     void slotObjectCreated(UMLObject * o);
418     void slotObjectRemoved(UMLObject * o);
419     void slotMenuSelection(QAction* action);
420     void slotActivate();
421     void slotCutSuccessful();
422     void slotShowView();
423 
424     void alignLeft();
425     void alignRight();
426     void alignTop();
427     void alignBottom();
428     void alignVerticalMiddle();
429     void alignHorizontalMiddle();
430     void alignVerticalDistribute();
431     void alignHorizontalDistribute();
432 
433 signals:
434     void sigResetToolBar();
435 
436     void sigFillColorChanged(Uml::ID::Type);
437     void sigGridColorChanged(Uml::ID::Type);
438     void sigLineColorChanged(Uml::ID::Type);
439     void sigTextColorChanged(Uml::ID::Type);
440     void sigLineWidthChanged(Uml::ID::Type);
441     void sigSnapToGridToggled(bool);
442     void sigSnapComponentSizeToGridToggled(bool);
443     void sigShowGridToggled(bool);
444     void sigAssociationRemoved(AssociationWidget*);
445     void sigWidgetRemoved(UMLWidget*);
446 
447     friend class DiagramProxyWidget;
448 };
449 
450 QDebug operator<<(QDebug dbg, UMLScene *item);
451 
452 #endif // UMLSCENE_H
453