1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2003-2020 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 // own header
7 #include "artifactwidget.h"
8 
9 // app includes
10 #include "artifact.h"
11 #include "debug_utils.h"
12 #include "umlscene.h"
13 #include "umlview.h"
14 
15 // qt includes
16 #include <QXmlStreamWriter>
17 
DEBUG_REGISTER_DISABLED(ArtifactWidget)18 DEBUG_REGISTER_DISABLED(ArtifactWidget)
19 
20 /**
21  * Constructs an ArtifactWidget.
22  *
23  * @param scene     The parent of this ArtifactWidget.
24  * @param a         The Artifact this widget will be representing.
25  */
26 ArtifactWidget::ArtifactWidget(UMLScene *scene, UMLArtifact *a)
27   : UMLWidget(scene, WidgetBase::wt_Artifact, a)
28 {
29     setSize(100, 30);
30 }
31 
32 /**
33  * Destructor.
34  */
~ArtifactWidget()35 ArtifactWidget::~ArtifactWidget()
36 {
37 }
38 
39 /**
40  * Reimplemented to paint the artifact widget. Some part of specific
41  * drawing is delegated to private method like drawAsFile..
42  */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)43 void ArtifactWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
44 {
45     Q_UNUSED(option);
46     Q_UNUSED(widget);
47 
48     UMLWidget::setPenFromSettings(painter);
49     if (UMLWidget::useFillColor()) {
50         painter->setBrush(UMLWidget::fillColor());
51     } else {
52         painter->setBrush(m_scene->backgroundColor());
53     }
54 
55     if (umlObject()) {
56         UMLArtifact *umlart = m_umlObject->asUMLArtifact();
57         UMLArtifact::Draw_Type drawType = umlart->getDrawAsType();
58         switch (drawType) {
59         case UMLArtifact::defaultDraw:
60             paintAsNormal(painter, option);
61             break;
62         case UMLArtifact::file:
63             paintAsFile(painter, option);
64             break;
65         case UMLArtifact::library:
66             paintAsLibrary(painter, option);
67             break;
68         case UMLArtifact::table:
69             paintAsTable(painter, option);
70             break;
71         default:
72             uWarning() << "Artifact drawn as unknown type";
73             break;
74         }
75     }
76     else {
77         uWarning() << "Cannot draw as there is no UMLArtifact for this widget.";
78     }
79 }
80 
81 /**
82  * Reimplemented from WidgetBase::saveToXMI1 to save the widget to
83  * the "artifactwidget" XMI element.
84  */
saveToXMI1(QXmlStreamWriter & writer)85 void ArtifactWidget::saveToXMI1(QXmlStreamWriter& writer)
86 {
87     writer.writeStartElement(QLatin1String("artifactwidget"));
88     UMLWidget::saveToXMI1(writer);
89     writer.writeEndElement();
90 }
91 
92 /**
93  * Overrides method from UMLWidget.
94  */
minimumSize() const95 QSizeF ArtifactWidget::minimumSize() const
96 {
97     if (!m_umlObject) {
98         return UMLWidget::minimumSize();
99     }
100     UMLArtifact *umlart = m_umlObject->asUMLArtifact();
101     if (umlart->getDrawAsType() == UMLArtifact::defaultDraw) {
102         return calculateNormalSize();
103     } else {
104         return calculateIconSize();
105     }
106 }
107 
108 /**
109  * calculates the size when drawing as an icon (it's the same size for all icons)
110  */
calculateIconSize() const111 QSize ArtifactWidget::calculateIconSize() const
112 {
113     const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
114     const int fontHeight  = fm.lineSpacing();
115 
116     int width = fm.width(m_umlObject->name());
117 
118     width = width<50 ? 50 : width;
119 
120     int height = 50 + fontHeight;
121 
122     return QSize(width, height);
123 }
124 
125 /**
126  * calculates the size for drawing as a box
127  */
calculateNormalSize() const128 QSize ArtifactWidget::calculateNormalSize() const
129 {
130     const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC);
131     const int fontHeight  = fm.lineSpacing();
132 
133     int width = fm.width(m_umlObject->name());
134 
135     int tempWidth = 0;
136     if(!m_umlObject->stereotype().isEmpty()) {
137         tempWidth = fm.width(m_umlObject->stereotype(true));
138     }
139     width = tempWidth>width ? tempWidth : width;
140     width += ARTIFACT_MARGIN * 2;
141 
142     int height = (2*fontHeight) + (ARTIFACT_MARGIN * 2);
143 
144     return QSize(width, height);
145 }
146 
147 /**
148  * draw as a file icon
149  */
paintAsFile(QPainter * painter,const QStyleOptionGraphicsItem * option)150 void ArtifactWidget::paintAsFile(QPainter *painter, const QStyleOptionGraphicsItem *option)
151 {
152     const int w = width();
153     const int h = height();
154     QFont font = UMLWidget::font();
155     const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
156     const int fontHeight  = fm.lineSpacing();
157 
158     int startX = (w/2) - 25;
159     int iconHeight = h - fontHeight;
160     QPolygon pointArray(5);
161     pointArray.setPoint(0, startX, 0);
162     pointArray.setPoint(1, startX + 40, 0);
163     pointArray.setPoint(2, startX + 50, 10);
164     pointArray.setPoint(3, startX + 50, iconHeight);
165     pointArray.setPoint(4, startX, iconHeight);
166     painter->drawPolygon(pointArray);
167 
168     painter->drawLine(startX + 40, 0, startX + 40, 10);
169     painter->drawLine(startX + 40, 10, startX + 50, 10);
170     painter->drawLine(startX + 40, 0, startX + 50, 10);
171 
172     painter->setPen(textColor());
173     painter->setFont(font);
174 
175     painter->drawText(0, h - fontHeight,
176                w, fontHeight, Qt::AlignCenter, name());
177 
178     UMLWidget::paint(painter, option);
179 }
180 
181 /**
182  * draw as a library file icon
183  */
paintAsLibrary(QPainter * painter,const QStyleOptionGraphicsItem * option)184 void ArtifactWidget::paintAsLibrary(QPainter *painter, const QStyleOptionGraphicsItem *option)
185 {
186     //FIXME this should have gears on it
187     const int w = width();
188     const int h = height();
189     const QFont font = UMLWidget::font();
190     const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
191     const int fontHeight  = fm.lineSpacing();
192 
193     const int startX = (w/2) - 25;
194     const int iconHeight = h - fontHeight;
195     QPolygon pointArray(5);
196     pointArray.setPoint(0, startX, 0);
197     pointArray.setPoint(1, startX + 40, 0);
198     pointArray.setPoint(2, startX + 50, 10);
199     pointArray.setPoint(3, startX + 50, iconHeight);
200     pointArray.setPoint(4, startX, iconHeight);
201     painter->drawPolygon(pointArray);
202 
203     painter->drawLine(startX + 40, 0, startX + 40, 10);
204     painter->drawLine(startX + 40, 10, startX + 50, 10);
205     painter->drawLine(startX + 40, 0, startX + 50, 10);
206 
207     painter->setPen(textColor());
208     painter->setFont(font);
209 
210     painter->drawText(0, h - fontHeight,
211                w, fontHeight, Qt::AlignCenter, name());
212 
213     UMLWidget::paint(painter, option);
214 }
215 
216 /**
217  * draw as a database table icon
218  */
paintAsTable(QPainter * painter,const QStyleOptionGraphicsItem * option)219 void ArtifactWidget::paintAsTable(QPainter *painter, const QStyleOptionGraphicsItem *option)
220 {
221     const int w = width();
222     const int h = height();
223     const QFont font = UMLWidget::font();
224     const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
225     const int fontHeight  = fm.lineSpacing();
226 
227     const int startX = (w/2) - 25;
228     const int iconHeight = h - fontHeight;
229 
230     painter->drawRect(startX, 0, 50, h - fontHeight + 1);
231     painter->drawLine(startX + 20, 0, startX + 20, iconHeight);
232     painter->drawLine(startX + 30, 0, startX + 30, iconHeight);
233     painter->drawLine(startX + 40, 0, startX + 40, iconHeight);
234     painter->drawLine(startX, (iconHeight/2), startX + 49, (iconHeight/2));
235     painter->drawLine(startX, (iconHeight/2) + (iconHeight/4),
236                startX + 49, (iconHeight/2) + (iconHeight/4));
237 
238     QPen thickerPen = painter->pen();
239     thickerPen.setWidth(2);
240     painter->setPen(thickerPen);
241     painter->drawLine(startX + 10, 0, startX + 10, iconHeight);
242     painter->drawLine(startX, (iconHeight/4), startX + 50, (iconHeight/4));
243 
244     painter->setPen(textColor());
245     painter->setFont(font);
246 
247     painter->drawText(0, h - fontHeight,
248                w, fontHeight, Qt::AlignCenter, name());
249 
250     UMLWidget::paint(painter, option);
251 }
252 
253 /**
254  * draw as a box
255  */
paintAsNormal(QPainter * painter,const QStyleOptionGraphicsItem * option)256 void ArtifactWidget::paintAsNormal(QPainter *painter, const QStyleOptionGraphicsItem *option)
257 {
258     int w = width();
259     int h = height();
260     QFont font = UMLWidget::font();
261     font.setBold(true);
262     const QFontMetrics &fm = getFontMetrics(FT_BOLD);
263     const int fontHeight  = fm.lineSpacing();
264     QString stereotype = m_umlObject->stereotype();
265 
266     painter->drawRect(0, 0, w, h);
267 
268     painter->setPen(textColor());
269     painter->setFont(font);
270 
271     if (!stereotype.isEmpty()) {
272         painter->drawText(ARTIFACT_MARGIN, (h/2) - fontHeight,
273                    w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true));
274     }
275 
276     int lines;
277     if (!stereotype.isEmpty()) {
278         lines = 2;
279     } else {
280         lines = 1;
281     }
282 
283     if (lines == 1) {
284         painter->drawText(0, (h/2) - (fontHeight/2),
285                    w, fontHeight, Qt::AlignCenter, name());
286     } else {
287         painter->drawText(0, (h/2),
288                    w, fontHeight, Qt::AlignCenter, name());
289     }
290 
291     UMLWidget::paint(painter, option);
292 }
293 
294