1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2004-2021 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 #ifndef WIDGETBASE_H
7 #define WIDGETBASE_H
8 
9 #include "basictypes.h"
10 #include "icon_utils.h"
11 
12 #include <QColor>
13 #include <QDomDocument>
14 #include <QFont>
15 #include <QGraphicsObject>
16 #include <QObject>
17 #include <QPainter>
18 #include <QPointer>
19 #include <QXmlStreamWriter>
20 
21 // forward declarations
22 class QAction;
23 class ActivityWidget;
24 class ActorWidget;
25 class ArtifactWidget;
26 class AssociationWidget;
27 class BoxWidget;
28 class CategoryWidget;
29 class ClassifierWidget;
30 class CombinedFragmentWidget;
31 class ComponentWidget;
32 class DatatypeWidget;
33 class EntityWidget;
34 class EnumWidget;
35 class FloatingDashLineWidget;
36 class FloatingTextWidget;
37 class ForkJoinWidget;
38 class IDChangeLog;
39 class InterfaceWidget;
40 class MessageWidget;
41 class NodeWidget;
42 class NoteWidget;
43 class ObjectNodeWidget;
44 class ObjectWidget;
45 class PackageWidget;
46 class PinWidget;
47 class PortWidget;
48 class PinPortBase;
49 class PreconditionWidget;
50 class RegionWidget;
51 class SignalWidget;
52 class StateWidget;
53 //class TextWidget;
54 class UseCaseWidget;
55 class UMLDoc;
56 class UMLObject;
57 class UMLScene;
58 class UMLWidget;   // required by function onWidget()
59 
60 /**
61  * Provides a wrapper that bypasses the restriction that
62  * QGraphicsItem::setSelected() is not virtual
63  *
64  * The selection management of umbrello uses a virtual method
65  * setSelected() for selection to achieve the desired behavior
66  * in the different derivation levels regarding selection and
67  * deselection.
68  *
69  * Within QGraphicsScene, QGraphicsItem::setSelected() is called
70  * to manage the selection state, e.g. with clearSelection(), but
71  * unfortunately cannot be directly overwritten by umbrello because
72  * this method is not virtual (I consider this a design flaw).
73  *
74  * Fortunately there is a workaround for the problem by using
75  * QGraphicsItem::itemChange(), which is overridden in this class
76  * and calls the (now) virtual method setSelected() when the selection
77  * state changes. This calls derived implementations of this method
78  * and realizes the desired behavior.
79  *
80  * Within setSelected() you have to take care that
81  * QGraphicsObject::setSelected() is not called if the call came
82  * from itemChange() to avoid an endless loop.
83  *
84  * @author Ralf Habacker <ralf.habacker@freenet.de>
85  */
86 class QGraphicsObjectWrapper: public QGraphicsObject
87 {
88 public:
89     virtual void setSelected(bool state);
90 protected:
91     bool m_calledFromItemChange{false};
92     QVariant itemChange(GraphicsItemChange change, const QVariant &value);
93 };
94 
95 /**
96  * @short       Common base class for UMLWidget and AssociationWidget
97  * @author      Oliver Kellogg <okellogg@users.sourceforge.net>
98  * Bugs and comments to umbrello-devel@kde.org or https://bugs.kde.org
99  */
100 class WidgetBase : public QGraphicsObjectWrapper
101 {
102     Q_OBJECT
103     Q_ENUMS(WidgetType)
104 
105 public:
106     enum WidgetType
107     {
108         wt_Min = 299,               // lower bounds check value
109         wt_UMLWidget,               // does not have UMLObject representation
110         wt_Actor,                   // has UMLObject representation
111         wt_UseCase,                 // has UMLObject representation
112         wt_Class,                   // has UMLObject representation
113         wt_Interface,               // has UMLObject representation
114         wt_Datatype,                // has UMLObject representation
115         wt_Enum,                    // has UMLObject representation
116         wt_Entity,                  // has UMLObject representation
117         wt_Package,                 // has UMLObject representation
118         wt_Object,                  // has UMLObject representation
119         wt_Note,                    // does not have UMLObject representation
120         wt_Box,                     // does not have UMLObject representation
121         wt_Message,                 // does not have UMLObject representation
122         wt_Text,                    // does not have UMLObject representation
123         wt_State,                   // does not have UMLObject representation
124         wt_Activity,                // does not have UMLObject representation
125         wt_Component,               // has UMLObject representation
126         wt_Artifact,                // has UMLObject representation
127         wt_Node,                    // has UMLObject representation
128         wt_Association,             // has UMLObject representation
129         wt_ForkJoin,                // does not have UMLObject representation
130         wt_Precondition,            // does not have UMLObject representation
131         wt_CombinedFragment,        // does not have UMLObject representation
132         wt_FloatingDashLine,        // does not have UMLObject representation
133         wt_Signal,                  // does not have UMLObject representation
134         wt_Pin,
135         wt_ObjectNode,
136         wt_Region,
137         wt_Category,                // has UMLObject representation
138         wt_Port,                    // has UMLObject representation
139         wt_Instance,                // has UMLObject representation == wt_Object
140         wt_Max                      // upper bounds check value
141     };
142 
143     static QString toString(WidgetType wt);
144     static QString toI18nString(WidgetType wt);
145     static Icon_Utils::IconType toIcon(WidgetType wt);
146 
147     explicit WidgetBase(UMLScene * scene, WidgetType type= wt_UMLWidget, Uml::ID::Type id = Uml::ID::None);
148     virtual ~WidgetBase();
149 
150     UMLObject* umlObject() const;
151     virtual void setUMLObject(UMLObject *obj);
152 
153     Uml::ID::Type id() const;
154     void setID(Uml::ID::Type id);
155 
156     void setLocalID(Uml::ID::Type id);
157     Uml::ID::Type localID() const;
158 
159     virtual UMLWidget *widgetWithID(Uml::ID::Type id);
160 
161     WidgetType baseType() const;
162     void setBaseType(const WidgetType& baseType);
163     QLatin1String baseTypeStr() const;
164     QString baseTypeStrWithoutPrefix() const;
165 
166     virtual void setSelected(bool select);
167 
168     UMLScene* umlScene() const;
169     UMLDoc* umlDoc() const;
170 
171     QString documentation() const;
172     bool hasDocumentation();
173     virtual void setDocumentation(const QString& doc);
174 
175     QString name() const;
176     virtual void setName(const QString &strName);
177 
178     QColor lineColor() const;
179     virtual void setLineColor(const QColor& color);
180 
181     uint lineWidth() const;
182     virtual void setLineWidth(uint width);
183 
184     QColor textColor() const;
185     virtual void setTextColor(const QColor& color);
186 
187     QColor fillColor() const;
188     virtual void setFillColor(const QColor& color);
189 
190     bool usesDiagramLineColor() const;
191     void setUsesDiagramLineColor(bool state);
192 
193     bool usesDiagramLineWidth() const;
194     void setUsesDiagramLineWidth(bool state);
195 
196     bool useFillColor();
197     virtual void setUseFillColor(bool state);
198 
199     bool usesDiagramTextColor() const;
200     void setUsesDiagramTextColor(bool state);
201 
202     bool usesDiagramFillColor() const;
203     void setUsesDiagramFillColor(bool state);
204 
205     bool usesDiagramUseFillColor() const;
206     void setUsesDiagramUseFillColor(bool state);
207 
208     virtual QFont font() const;
209     virtual void setFont(const QFont& font);
210 
211     bool autoResize();
212     void setAutoResize(bool state);
213 
214     bool changesShape();
215     void setChangesShape(bool state);
216 
217     virtual bool showPropertiesDialog();
218 
219     virtual bool loadFromXMI1(QDomElement &qElement);
220     virtual void saveToXMI1(QXmlStreamWriter& writer);
221 
222     virtual void removeAssoc(AssociationWidget* pAssoc);
223     virtual void addAssoc(AssociationWidget* pAssoc);
224 
225     WidgetBase& operator=(const WidgetBase& other);
226 
227     QRectF rect() const;
228     void setRect(const QRectF& rect);
229     void setRect(qreal x, qreal y, qreal width, qreal height);
230 
231     virtual QRectF boundingRect() const;
232 
233     virtual UMLWidget* onWidget(const QPointF &p);
234 
235     virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
236 
isActivityWidget()237     bool isActivityWidget()         const { return baseType() == wt_Activity; }
isActorWidget()238     bool isActorWidget()            const { return baseType() == wt_Actor; }
isArtifactWidget()239     bool isArtifactWidget()         const { return baseType() == wt_Artifact; }
isAssociationWidget()240     bool isAssociationWidget()      const { return baseType() == wt_Association; }
isBoxWidget()241     bool isBoxWidget()              const { return baseType() == wt_Box; }
isCategoryWidget()242     bool isCategoryWidget()         const { return baseType() == wt_Category; }
isClassWidget()243     bool isClassWidget()            const { return baseType() == wt_Class; }
isCombinedFragmentWidget()244     bool isCombinedFragmentWidget() const { return baseType() == wt_CombinedFragment; }
isComponentWidget()245     bool isComponentWidget()        const { return baseType() == wt_Component; }
isDatatypeWidget()246     bool isDatatypeWidget()         const { return baseType() == wt_Datatype; }
isEntityWidget()247     bool isEntityWidget()           const { return baseType() == wt_Entity; }
isEnumWidget()248     bool isEnumWidget()             const { return baseType() == wt_Enum; }
isFloatingDashLineWidget()249     bool isFloatingDashLineWidget() const { return baseType() == wt_FloatingDashLine; }
isForkJoinWidget()250     bool isForkJoinWidget()         const { return baseType() == wt_ForkJoin; }
isInterfaceWidget()251     bool isInterfaceWidget()        const { return baseType() == wt_Interface; }
isMessageWidget()252     bool isMessageWidget()          const { return baseType() == wt_Message; }
isNodeWidget()253     bool isNodeWidget()             const { return baseType() == wt_Node; }
isNoteWidget()254     bool isNoteWidget()             const { return baseType() == wt_Note; }
isObjectNodeWidget()255     bool isObjectNodeWidget()       const { return baseType() == wt_ObjectNode; }
isObjectWidget()256     bool isObjectWidget()           const { return baseType() == wt_Object; }
isPackageWidget()257     bool isPackageWidget()          const { return baseType() == wt_Package; }
isPinWidget()258     bool isPinWidget()              const { return baseType() == wt_Pin; }
isPortWidget()259     bool isPortWidget()             const { return baseType() == wt_Port; }
isPreconditionWidget()260     bool isPreconditionWidget()     const { return baseType() == wt_Precondition; }
isRegionWidget()261     bool isRegionWidget()           const { return baseType() == wt_Region; }
isSignalWidget()262     bool isSignalWidget()           const { return baseType() == wt_Signal; }
isStateWidget()263     bool isStateWidget()            const { return baseType() == wt_State; }
isTextWidget()264     bool isTextWidget()             const { return baseType() == wt_Text; }
isUseCaseWidget()265     bool isUseCaseWidget()          const { return baseType() == wt_UseCase; }
266 
267     ActivityWidget* asActivityWidget();
268     ActorWidget* asActorWidget();
269     ArtifactWidget* asArtifactWidget();
270     AssociationWidget* asAssociationWidget();
271     BoxWidget* asBoxWidget();
272     CategoryWidget* asCategoryWidget();
273     ClassifierWidget* asClassifierWidget();
274     CombinedFragmentWidget* asCombinedFragmentWidget();
275     ComponentWidget* asComponentWidget();
276     DatatypeWidget* asDatatypeWidget();
277     EntityWidget* asEntityWidget();
278     EnumWidget* asEnumWidget();
279     FloatingDashLineWidget* asFloatingDashLineWidget();
280     ForkJoinWidget* asForkJoinWidget();
281     InterfaceWidget* asInterfaceWidget();
282     MessageWidget* asMessageWidget();
283     NodeWidget* asNodeWidget();
284     NoteWidget* asNoteWidget();
285     ObjectNodeWidget* asObjectNodeWidget();
286     ObjectWidget* asObjectWidget();
287     PackageWidget* asPackageWidget();
288     PinWidget* asPinWidget();
289     PinPortBase* asPinPortBase();
290     PortWidget* asPortWidget();
291     PreconditionWidget* asPreconditionWidget();
292     RegionWidget* asRegionWidget();
293     SignalWidget* asSignalWidget();
294     StateWidget* asStateWidget();
295     FloatingTextWidget* asFloatingTextWidget();
296 //    TextWidget* asTextWidget();
297     UseCaseWidget* asUseCaseWidget();
298     UMLWidget* asUMLWidget();
299 
300     static bool widgetHasUMLObject(WidgetBase::WidgetType type);
301     virtual bool activate(IDChangeLog *changeLog = 0);
302 
303 public Q_SLOTS:
304     virtual void slotMenuSelection(QAction *trigger);
305 
306 protected:
307     virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
308 
309 private:
310     WidgetType  m_baseType;  ///< Type of widget.
311 protected:
312     UMLScene   *m_scene;
313     QPointer<UMLObject> m_umlObject;
314     QString     m_Doc;   ///< Only used if m_umlObject is not set.
315     QString     m_Text;
316     QRectF      m_rect;  ///< widget size
317 
318     /**
319      * This ID is only used when the widget does not have a
320      * corresponding UMLObject (i.e. the m_umlObject pointer is NULL.)
321      * For UMLObjects, the ID from the UMLObject is used.
322      */
323     Uml::ID::Type m_nId;
324 
325     /**
326      * This ID is only used when a widget could be added more than once to a diagram
327      */
328     Uml::ID::Type m_nLocalID;
329 
330     QColor m_textColor;  ///< Color of the text of the widget. Is saved to XMI.
331     QColor m_lineColor;  ///< Color of the lines of the widget. Is saved to XMI.
332     QColor m_fillColor;  ///< color of the background of the widget
333     QBrush m_brush;
334     QFont  m_font;
335     uint   m_lineWidth;  ///< Width of the lines of the widget. Is saved to XMI.
336     bool   m_useFillColor;  ///< flag indicates if the UMLWidget uses the Diagram FillColour
337 
338     /**
339      * true by default, false if the colors have
340      * been explicitly set for this widget.
341      * These are saved to XMI.
342      */
343     bool m_usesDiagramFillColor;
344     bool m_usesDiagramLineColor;
345     bool m_usesDiagramLineWidth;
346     bool m_usesDiagramTextColor;
347     bool m_usesDiagramUseFillColor;
348     bool m_autoResize;
349     bool m_changesShape; ///< The widget changes its shape when the number of connections or their positions are changed
350 };
351 
352 #endif
353