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 // own header
7 #include "model_utils.h"
8
9 // app includes
10 #include "floatingtextwidget.h"
11 #include "debug_utils.h"
12 #include "umlobject.h"
13 #include "umlpackagelist.h"
14 #include "uniqueconstraint.h"
15 #include "package.h"
16 #include "folder.h"
17 #include "classifier.h"
18 #include "enum.h"
19 #include "instance.h"
20 #include "entity.h"
21 #include "template.h"
22 #include "operation.h"
23 #include "attribute.h"
24 #include "association.h"
25 #include "umlrole.h"
26 #include "umldoc.h"
27 #include "uml.h"
28 #include "umllistview.h"
29 #include "umllistviewitem.h"
30 #include "umlscene.h"
31 #include "umlview.h"
32 #include "codegenerator.h"
33
34 // kde includes
35 #include <KLocalizedString>
36
37 // qt includes
38 #include <QRegExp>
39 #include <QStringList>
40
41 namespace Model_Utils {
42
43 /**
44 * Determines whether the given widget type is cloneable.
45 *
46 * @param type The input WidgetType.
47 * @return True if the given type is cloneable.
48 */
isCloneable(WidgetBase::WidgetType type)49 bool isCloneable(WidgetBase::WidgetType type)
50 {
51 switch (type) {
52 case WidgetBase::wt_Actor:
53 case WidgetBase::wt_UseCase:
54 case WidgetBase::wt_Class:
55 case WidgetBase::wt_Interface:
56 case WidgetBase::wt_Enum:
57 case WidgetBase::wt_Datatype:
58 case WidgetBase::wt_Package:
59 case WidgetBase::wt_Component:
60 case WidgetBase::wt_Port:
61 case WidgetBase::wt_Node:
62 case WidgetBase::wt_Artifact:
63 case WidgetBase::wt_Instance:
64 case WidgetBase::wt_Entity:
65 return true;
66 default:
67 return false;
68 }
69 }
70
71 /**
72 * Seek the given id in the given list of objects.
73 * Each list element may itself contain other objects
74 * and the search is done recursively.
75 *
76 * @param id The unique ID to seek.
77 * @param inList The UMLObjectList in which to search.
78 * @return Pointer to the UMLObject that matches the ID (NULL if none matches).
79 */
findObjectInList(Uml::ID::Type id,const UMLObjectList & inList)80 UMLObject* findObjectInList(Uml::ID::Type id, const UMLObjectList& inList)
81 {
82 for (UMLObjectListIt oit(inList); oit.hasNext();) {
83 UMLObject *obj = oit.next();
84 uIgnoreZeroPointer(obj);
85 if (obj->id() == id)
86 return obj;
87 UMLObject *o;
88 UMLObject::ObjectType t = obj->baseType();
89 switch (t) {
90 case UMLObject::ot_Folder:
91 case UMLObject::ot_Package:
92 case UMLObject::ot_Component:
93 o = obj->asUMLPackage()->findObjectById(id);
94 if (o)
95 return o;
96 break;
97 case UMLObject::ot_Interface:
98 case UMLObject::ot_Class:
99 case UMLObject::ot_Enum:
100 o = obj->asUMLClassifier()->findChildObjectById(id);
101 if (o == nullptr &&
102 (t == UMLObject::ot_Interface || t == UMLObject::ot_Class))
103 o = obj->asUMLPackage()->findObjectById(id);
104 if (o)
105 return o;
106 break;
107 case UMLObject::ot_Instance:
108 o = obj->asUMLInstance()->findChildObjectById(id);
109 if (o)
110 return o;
111 break;
112 case UMLObject::ot_Entity:
113 o = obj->asUMLEntity()->findChildObjectById(id);
114 if (o)
115 return o;
116 o = obj->asUMLPackage()->findObjectById(id);
117 if (o)
118 return o;
119 break;
120 case UMLObject::ot_Association:
121 {
122 UMLAssociation *assoc = obj->asUMLAssociation();
123 UMLRole *rA = assoc->getUMLRole(Uml::RoleType::A);
124 if (rA->id() == id)
125 return rA;
126 UMLRole *rB = assoc->getUMLRole(Uml::RoleType::B);
127 if (rB->id() == id)
128 return rB;
129 }
130 break;
131 default:
132 break;
133 }
134 }
135 return 0;
136 }
137
138 /**
139 * Find the UML object of the given type and name in the passed-in list.
140 *
141 * @param inList List in which to seek the object.
142 * @param inName Name of the object to find.
143 * @param type ObjectType of the object to find (optional.)
144 * When the given type is ot_UMLObject the type is
145 * disregarded, i.e. the given name is the only
146 * search criterion.
147 * @param currentObj Object relative to which to search (optional.)
148 * If given then the enclosing scope(s) of this
149 * object are searched before the global scope.
150 * @return Pointer to the UMLObject found, or NULL if not found.
151 */
findUMLObject(const UMLObjectList & inList,const QString & inName,UMLObject::ObjectType type,UMLObject * currentObj)152 UMLObject* findUMLObject(const UMLObjectList& inList,
153 const QString& inName,
154 UMLObject::ObjectType type /* = ot_UMLObject */,
155 UMLObject *currentObj /* = 0 */)
156 {
157 const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
158 QString name = inName;
159 const bool atGlobalScope = name.startsWith(QLatin1String("::"));
160 if (atGlobalScope) {
161 name = name.mid(2);
162 currentObj = 0;
163 }
164 QStringList components;
165 #ifdef TRY_BUGFIX_120682
166 // If we have a pointer or a reference in cpp we need to remove
167 // the asterisks and ampersands in order to find the appropriate object
168 if (UMLApp::app()->getActiveLanguage() == Uml::pl_Cpp) {
169 if (name.endsWith(QLatin1Char('*')))
170 name.remove(QLatin1Char('*'));
171 else if (name.contains(QLatin1Char('&')))
172 name.remove(QLatin1Char('&'));
173 }
174 #endif
175 QString scopeSeparator = UMLApp::app()->activeLanguageScopeSeparator();
176 if (name.contains(scopeSeparator))
177 components = name.split(scopeSeparator);
178 QString nameWithoutFirstPrefix;
179 if (components.size() > 1) {
180 name = components.front();
181 components.pop_front();
182 nameWithoutFirstPrefix = components.join(scopeSeparator);
183 }
184 if (currentObj) {
185 UMLPackage *pkg = 0;
186 if (currentObj->asUMLClassifierListItem()) {
187 currentObj = currentObj->umlParent();
188 }
189 pkg = currentObj->asUMLPackage();
190 if (pkg == 0 || pkg->baseType() == UMLObject::ot_Association)
191 pkg = currentObj->umlPackage();
192 // Remember packages that we've seen - for avoiding cycles.
193 UMLPackageList seenPkgs;
194 for (; pkg; pkg = currentObj->umlPackage()) {
195 if (nameWithoutFirstPrefix.isEmpty()
196 && (type == UMLObject::ot_UMLObject ||
197 type == UMLObject::ot_Folder ||
198 type == UMLObject::ot_Package || type == pkg->baseType())) {
199 if (caseSensitive) {
200 if (pkg->name() == name)
201 return pkg;
202 } else if (pkg->name().toLower() == name.toLower()) {
203 return pkg;
204 }
205 }
206 if (seenPkgs.indexOf(pkg) != -1) {
207 uError() << "findUMLObject(" << name << "): "
208 << "breaking out of cycle involving "
209 << pkg->name();
210 break;
211 }
212 seenPkgs.append(pkg);
213
214 // exclude non package type
215 // pg->asUMLPackage() fails for unknown reason
216 // see https://bugs.kde.org/show_bug.cgi?id=341709
217 UMLObject::ObjectType foundType = pkg->baseType();
218 if (foundType != UMLObject::ot_Package &&
219 foundType != UMLObject::ot_Folder &&
220 foundType != UMLObject::ot_Class &&
221 foundType != UMLObject::ot_Interface &&
222 foundType != UMLObject::ot_Component) {
223 continue;
224 }
225 UMLObjectList objectsInCurrentScope = pkg->containedObjects();
226 for (UMLObjectListIt oit(objectsInCurrentScope); oit.hasNext();) {
227 UMLObject *obj = oit.next();
228 uIgnoreZeroPointer(obj);
229 if (caseSensitive) {
230 if (obj->name() != name)
231 continue;
232 } else if (obj->name().toLower() != name.toLower()) {
233 continue;
234 }
235 UMLObject::ObjectType foundType = obj->baseType();
236 if (nameWithoutFirstPrefix.isEmpty()) {
237 if (type != UMLObject::ot_UMLObject && type != foundType) {
238 uDebug() << "type mismatch for "
239 << name << " (seeking type: "
240 << UMLObject::toString(type) << ", found type: "
241 << UMLObject::toString(foundType) << ")";
242 // Class, Interface, and Datatype are all Classifiers
243 // and are considered equivalent.
244 // The caller must be prepared to handle possible mismatches.
245 if ((type == UMLObject::ot_Class ||
246 type == UMLObject::ot_Interface ||
247 type == UMLObject::ot_Datatype) &&
248 (foundType == UMLObject::ot_Class ||
249 foundType == UMLObject::ot_Interface ||
250 foundType == UMLObject::ot_Datatype)) {
251 return obj;
252 }
253 // Code import may set <<class-or-package>> stereotype
254 if ((type == UMLObject::ot_Package || type == UMLObject::ot_Class)
255 && obj->stereotype() == QLatin1String("class-or-package")) {
256 return obj;
257 }
258 continue;
259 }
260 return obj;
261 }
262 if (foundType != UMLObject::ot_Package &&
263 foundType != UMLObject::ot_Folder &&
264 foundType != UMLObject::ot_Class &&
265 foundType != UMLObject::ot_Interface &&
266 foundType != UMLObject::ot_Component) {
267 uDebug() << "found " << UMLObject::toString(foundType) << name
268 << " is not a package (?)";
269 continue;
270 }
271 UMLPackage *pkg = obj->asUMLPackage();
272 return findUMLObject(pkg->containedObjects(),
273 nameWithoutFirstPrefix, type);
274 }
275 currentObj = pkg;
276 }
277 }
278 for (UMLObjectListIt oit(inList); oit.hasNext();) {
279 UMLObject *obj = oit.next();
280 uIgnoreZeroPointer(obj);
281 if (caseSensitive) {
282 if (obj->name() != name)
283 continue;
284 } else if (obj->name().toLower() != name.toLower()) {
285 continue;
286 }
287 UMLObject::ObjectType foundType = obj->baseType();
288 if (nameWithoutFirstPrefix.isEmpty()) {
289 if (type != UMLObject::ot_UMLObject && type != foundType) {
290 // Code import may set <<class-or-package>> stereotype
291 if ((type == UMLObject::ot_Package || type == UMLObject::ot_Class)
292 && obj->stereotype() == QLatin1String("class-or-package")) {
293 return obj;
294 }
295 uDebug() << "type mismatch for "
296 << name << " (seeking type: "
297 << UMLObject::toString(type) << ", found type: "
298 << UMLObject::toString(foundType) << ")";
299 continue;
300 }
301 return obj;
302 }
303 if (foundType != UMLObject::ot_Package &&
304 foundType != UMLObject::ot_Folder &&
305 foundType != UMLObject::ot_Class &&
306 foundType != UMLObject::ot_Interface &&
307 foundType != UMLObject::ot_Component) {
308 uDebug() << "found " << name << "(" << UMLObject::toString(foundType) << ")"
309 << " is not a package (?)";
310 continue;
311 }
312 UMLPackage *pkg = obj->asUMLPackage();
313 return findUMLObject(pkg->containedObjects(),
314 nameWithoutFirstPrefix, type);
315 }
316 return 0;
317 }
318
319 /**
320 * Find the UML object of the given type and name in the passed-in list.
321 * This method searches for the raw name.
322 *
323 * @param inList List in which to seek the object.
324 * @param name Name of the object to find.
325 * @param type ObjectType of the object to find (optional.)
326 * When the given type is ot_UMLObject the type is
327 * disregarded, i.e. the given name is the only
328 * search criterion.
329 * @param currentObj Object relative to which to search (optional.)
330 * If given then the enclosing scope(s) of this
331 * object are searched before the global scope.
332 * @return Pointer to the UMLObject found, or NULL if not found.
333 */
findUMLObjectRaw(const UMLObjectList & inList,const QString & name,UMLObject::ObjectType type,UMLObject * currentObj)334 UMLObject* findUMLObjectRaw(const UMLObjectList& inList,
335 const QString& name,
336 UMLObject::ObjectType type /* = ot_UMLObject */,
337 UMLObject *currentObj /*= 0*/)
338 {
339 Q_UNUSED(currentObj);
340 for (UMLObjectListIt oit(inList); oit.hasNext();) {
341 UMLObject *obj = oit.next();
342 if (obj->name() == name && type == obj->baseType())
343 return obj;
344 }
345 return 0;
346 }
347
348 /**
349 * Find the UML object of the given type and name in the passed-in list.
350 * This method searches for the raw name.
351 *
352 * @param inList List in which to seek the object.
353 * @param name Name of the object to find.
354 * @param type ObjectType of the object to find (optional.)
355 * When the given type is ot_UMLObject the type is
356 * disregarded, i.e. the given name is the only
357 * search criterion.
358 * @return Pointer to the UMLObject found, or NULL if not found.
359 */
findUMLObjectRecursive(const UMLObjectList & inList,const QString & name,UMLObject::ObjectType type)360 UMLObject* findUMLObjectRecursive(const UMLObjectList& inList,
361 const QString& name,
362 UMLObject::ObjectType type /* = ot_UMLObject */)
363 {
364 foreach(UMLObject *obj, inList) {
365 if (obj->name() == name && type == obj->baseType())
366 return obj;
367 UMLPackage *pkg = obj->asUMLPackage();
368 if (pkg && pkg->containedObjects().size() > 0) {
369 UMLObject *o = findUMLObjectRecursive(pkg->containedObjects(), name, type);
370 if (o)
371 return o;
372 }
373 }
374 return 0;
375 }
376
377 /**
378 * Get the root folder of the given UMLObject.
379 */
rootPackage(UMLObject * obj)380 UMLPackage* rootPackage(UMLObject* obj)
381 {
382 if (obj == 0)
383 return 0;
384 UMLPackage* root = obj->umlPackage();
385 if (root == 0) {
386 root = obj->asUMLPackage();
387 } else {
388 while (root->umlPackage() != 0) {
389 root = root->umlPackage();
390 }
391 }
392 return root;
393 }
394
395 /**
396 * Add the given list of views to the tree view.
397 * @param viewList the list of views to add
398 */
treeViewAddViews(const UMLViewList & viewList)399 void treeViewAddViews(const UMLViewList& viewList)
400 {
401 UMLListView* tree = UMLApp::app()->listView();
402 foreach (UMLView* v, viewList) {
403 if (tree->findItem(v->umlScene()->ID()) != 0) {
404 continue;
405 }
406 tree->createDiagramItem(v);
407 }
408 }
409
410 /**
411 * Change an icon of an object in the tree view.
412 * @param object the object in the treeViewAddViews
413 * @param to the new icon type for the given object
414 */
treeViewChangeIcon(UMLObject * object,Icon_Utils::IconType to)415 void treeViewChangeIcon(UMLObject* object, Icon_Utils::IconType to)
416 {
417 UMLListView* tree = UMLApp::app()->listView();
418 tree->changeIconOf(object, to);
419 }
420
421 /**
422 * Set the given object to the current item in the tree view.
423 * @param object the object which will be the current item
424 */
treeViewSetCurrentItem(UMLObject * object)425 void treeViewSetCurrentItem(UMLObject* object)
426 {
427 UMLListView* tree = UMLApp::app()->listView();
428 UMLListViewItem* item = tree->findUMLObject(object);
429 tree->setCurrentItem(item);
430 }
431
432 /**
433 * Move an object to a new container in the tree view.
434 * @param container the new container for the object
435 * @param object the to be moved object
436 */
treeViewMoveObjectTo(UMLObject * container,UMLObject * object)437 void treeViewMoveObjectTo(UMLObject* container, UMLObject* object)
438 {
439 UMLListView *listView = UMLApp::app()->listView();
440 UMLListViewItem *newParent = listView->findUMLObject(container);
441 listView->moveObject(object->id(),
442 Model_Utils::convert_OT_LVT(object),
443 newParent);
444 }
445
446 /**
447 * Return the current UMLObject from the tree view.
448 * @return the UML object of the current item
449 */
treeViewGetCurrentObject()450 UMLObject* treeViewGetCurrentObject()
451 {
452 UMLListView *listView = UMLApp::app()->listView();
453 UMLListViewItem *current = static_cast<UMLListViewItem*>(listView->currentItem());
454 return current->umlObject();
455 }
456
457 /**
458 * Return the UMLPackage if the current item
459 * in the tree view is a package. Return the
460 * closest package in the tree view or NULL otherwise
461 *
462 * @return the package or NULL
463 */
treeViewGetPackageFromCurrent()464 UMLPackage* treeViewGetPackageFromCurrent()
465 {
466 UMLListView *listView = UMLApp::app()->listView();
467 UMLListViewItem *parentItem = (UMLListViewItem*)listView->currentItem();
468 while (parentItem) {
469 UMLListViewItem::ListViewType lvt = parentItem->type();
470 if (Model_Utils::typeIsContainer(lvt)) {
471 UMLObject *o = parentItem->umlObject();
472 return o->asUMLPackage();
473 }
474
475 // selected item is not a container, try to find the
476 // container higher up in the tree view
477 parentItem = static_cast<UMLListViewItem*>(parentItem->parent());
478 }
479
480 return 0;
481 }
482
483 /**
484 * Build the diagram name from the tree view.
485
486 * The function returns a relative path constructed from the folder hierarchy.
487 * @param id the id of the diaram
488 * @return the constructed diagram name
489 */
treeViewBuildDiagramName(Uml::ID::Type id)490 QString treeViewBuildDiagramName(Uml::ID::Type id)
491 {
492 UMLListView *listView = UMLApp::app()->listView();
493 UMLListViewItem* listViewItem = listView->findItem(id);
494
495 if (listViewItem) {
496 QString name = listViewItem->text(0);
497 listViewItem = static_cast<UMLListViewItem*>(listViewItem->parent());
498
499 // Relies on the tree structure of the UMLListView. There are a base "Views" folder
500 // and five children, one for each view type (Logical, use case, components, deployment
501 // and entity relationship)
502 while (listView->rootView(listViewItem->type()) == 0) {
503 name.insert(0, listViewItem->text(0) + QLatin1Char('/'));
504 listViewItem = static_cast<UMLListViewItem*>(listViewItem->parent());
505 if (listViewItem == 0)
506 break;
507 }
508 return name;
509 }
510 else {
511 uWarning() << "diagram not found - returning empty name!";
512 return QString();
513 }
514 }
515
516 /**
517 * Returns a name for the new object, appended with a number
518 * if the default name is taken e.g. new_actor, new_actor_1
519 * etc.
520 * @param type The object type.
521 * @param parentPkg The package in which to compare the name.
522 * @param prefix The prefix to use (optional)
523 * If no prefix is given then a type related
524 * prefix will be chosen internally.
525 */
uniqObjectName(UMLObject::ObjectType type,UMLPackage * parentPkg,QString prefix)526 QString uniqObjectName(UMLObject::ObjectType type, UMLPackage *parentPkg, QString prefix)
527 {
528 QString currentName = prefix;
529 if (currentName.isEmpty()) {
530 switch(type) {
531 case UMLObject::ot_Actor: currentName = i18n("new_actor"); break;
532 case UMLObject::ot_Artifact: currentName = i18n("new_artifact"); break;
533 case UMLObject::ot_Association: currentName = i18n("new_association"); break;
534 case UMLObject::ot_Attribute: currentName = i18n("new_attribute"); break;
535 case UMLObject::ot_Category: currentName = i18n("new_category"); break;
536 case UMLObject::ot_CheckConstraint: currentName = i18n("new_check_constraint"); break;
537 case UMLObject::ot_Class: currentName = i18n("new_class"); break;
538 case UMLObject::ot_Component: currentName = i18n("new_component"); break;
539 case UMLObject::ot_Datatype: currentName = i18n("new_datatype"); break;
540 case UMLObject::ot_Entity: currentName = i18n("new_entity"); break;
541 case UMLObject::ot_EntityAttribute: currentName = i18n("new_entity_attribute"); break;
542 case UMLObject::ot_EntityConstraint: currentName = i18n("new_entity_constraint"); break;
543 case UMLObject::ot_Enum: currentName = i18n("new_enum"); break;
544 case UMLObject::ot_EnumLiteral: currentName = i18n("new_enum_literal"); break;
545 case UMLObject::ot_Folder: currentName = i18n("new_folder"); break;
546 case UMLObject::ot_ForeignKeyConstraint:currentName = i18n("new_foreign_key_constraint"); break;
547 case UMLObject::ot_Instance: currentName = i18n("new_instance"); break;
548 case UMLObject::ot_InstanceAttribute: currentName = i18n("new_instance_attribute"); break;
549 case UMLObject::ot_Interface: currentName = i18n("new_interface"); break;
550 case UMLObject::ot_Node: currentName = i18n("new_node"); break;
551 case UMLObject::ot_Operation: currentName = i18n("new_operation"); break;
552 case UMLObject::ot_Package: currentName = i18n("new_package"); break;
553 case UMLObject::ot_Port: currentName = i18n("new_port"); break;
554 case UMLObject::ot_Role: currentName = i18n("new_role"); break;
555 case UMLObject::ot_Stereotype: currentName = i18n("new_stereotype"); break;
556 case UMLObject::ot_Template: currentName = i18n("new_template"); break;
557 case UMLObject::ot_UniqueConstraint: currentName = i18n("new_unique_constraint"); break;
558 case UMLObject::ot_UseCase: currentName = i18n("new_use case"); break;
559 default:
560 currentName = i18n("new_object");
561 uWarning() << "model_utils::uniqObjectName unknown object type" << UMLObject::toString(type);
562 }
563 }
564 UMLDoc *doc = UMLApp::app()->document();
565 QString name = currentName;
566 for (int number = 1; !doc->isUnique(name, parentPkg); ++number) {
567 name = currentName + QLatin1Char('_') + QString::number(number);
568 }
569 return name;
570 }
571
572 /**
573 * Returns translated title string used by uml object related dialogs
574 * @param type uml object type
575 * @return translated title string
576 */
newTitle(UMLObject::ObjectType type)577 QString newTitle(UMLObject::ObjectType type)
578 {
579 switch(type) {
580 case UMLObject::ot_Actor: return i18n("New actor");
581 case UMLObject::ot_Artifact: return i18n("New artifact");
582 case UMLObject::ot_Association: return i18n("New association");
583 case UMLObject::ot_Attribute: return i18n("New attribute");
584 case UMLObject::ot_Category: return i18n("New category");
585 case UMLObject::ot_CheckConstraint: return i18n("New check constraint");
586 case UMLObject::ot_Class: return i18n("New class");
587 case UMLObject::ot_Component: return i18n("New component");
588 case UMLObject::ot_Datatype: return i18n("New datatype");
589 case UMLObject::ot_Entity: return i18n("New entity");
590 case UMLObject::ot_EntityAttribute: return i18n("New entity attribute");
591 case UMLObject::ot_EntityConstraint: return i18n("New entity constraint");
592 case UMLObject::ot_Enum: return i18n("New enum");
593 case UMLObject::ot_EnumLiteral: return i18n("New enum literal");
594 case UMLObject::ot_Folder: return i18n("New folder");
595 case UMLObject::ot_ForeignKeyConstraint:return i18n("New foreign key constraint");
596 case UMLObject::ot_Instance: return i18n("New instance");
597 case UMLObject::ot_InstanceAttribute: return i18n("New instance attribute");
598 case UMLObject::ot_Interface: return i18n("New interface");
599 case UMLObject::ot_Node: return i18n("New node");
600 case UMLObject::ot_Operation: return i18n("New operation");
601 case UMLObject::ot_Package: return i18n("New package");
602 case UMLObject::ot_Port: return i18n("New port");
603 case UMLObject::ot_Role: return i18n("New role");
604 case UMLObject::ot_Stereotype: return i18n("New stereotype");
605 case UMLObject::ot_Template: return i18n("New template");
606 case UMLObject::ot_UniqueConstraint: return i18n("New unique constraint");
607 case UMLObject::ot_UseCase: return i18n("New use case");
608 default:
609 uWarning() << "model_utils::newTitle unknown object type" << UMLObject::toString(type);
610 return i18n("New UML object");
611 }
612 }
613
614 /**
615 * Returns translated text string used by uml object related dialogs
616 * @param type uml object type
617 * @return translated text string
618 */
newText(UMLObject::ObjectType type)619 QString newText(UMLObject::ObjectType type)
620 {
621 switch(type) {
622 case UMLObject::ot_Actor: return i18n("Enter the name of the new actor:");
623 case UMLObject::ot_Artifact: return i18n("Enter the name of the new artifact:");
624 case UMLObject::ot_Association: return i18n("Enter the name of the new association:");
625 case UMLObject::ot_Attribute: return i18n("Enter the name of the new attribute:");
626 case UMLObject::ot_Category: return i18n("Enter the name of the new category:");
627 case UMLObject::ot_CheckConstraint: return i18n("Enter the name of the new check constraint:");
628 case UMLObject::ot_Class: return i18n("Enter the name of the new class:");
629 case UMLObject::ot_Component: return i18n("Enter the name of the new component:");
630 case UMLObject::ot_Datatype: return i18n("Enter the name of the new datatype:");
631 case UMLObject::ot_Entity: return i18n("Enter the name of the new entity:");
632 case UMLObject::ot_EntityAttribute: return i18n("Enter the name of the new entity attribute:");
633 case UMLObject::ot_EntityConstraint: return i18n("Enter the name of the new entity constraint:");
634 case UMLObject::ot_Enum: return i18n("Enter the name of the new enum:");
635 case UMLObject::ot_EnumLiteral: return i18n("Enter the name of the new enum literal:");
636 case UMLObject::ot_Folder: return i18n("Enter the name of the new folder:");
637 case UMLObject::ot_ForeignKeyConstraint:return i18n("Enter the name of the new foreign key constraint:");
638 case UMLObject::ot_Instance: return i18n("Enter the name of the new instance:");
639 case UMLObject::ot_InstanceAttribute: return i18n("Enter the name of the new instance attribute:");
640 case UMLObject::ot_Interface: return i18n("Enter the name of the new interface:");
641 case UMLObject::ot_Node: return i18n("Enter the name of the new node:");
642 case UMLObject::ot_Operation: return i18n("Enter the name of the new operation:");
643 case UMLObject::ot_Package: return i18n("Enter the name of the new package:");
644 case UMLObject::ot_Port: return i18n("Enter the name of the new port:");
645 case UMLObject::ot_Role: return i18n("Enter the name of the new role:");
646 case UMLObject::ot_Stereotype: return i18n("Enter the name of the new stereotype:");
647 case UMLObject::ot_Template: return i18n("Enter the name of the new template:");
648 case UMLObject::ot_UniqueConstraint: return i18n("Enter the name of the new unique constraint:");
649 case UMLObject::ot_UseCase: return i18n("Enter the name of the new use case:");
650 default:
651 uWarning() << "model_utils::newText unknown object type" << UMLObject::toString(type);
652 return i18n("Enter the name of the new UML object");
653 }
654 }
655
656 /**
657 * Returns translated title string used by uml object related dialogs
658 * @param type uml object type
659 * @return translated title string
660 */
renameTitle(UMLObject::ObjectType type)661 QString renameTitle(UMLObject::ObjectType type)
662 {
663 switch(type) {
664 case UMLObject::ot_Actor: return i18n("Rename actor");
665 case UMLObject::ot_Artifact: return i18n("Rename artifact");
666 case UMLObject::ot_Association: return i18n("Rename association");
667 case UMLObject::ot_Attribute: return i18n("Rename attribute");
668 case UMLObject::ot_Category: return i18n("Rename category");
669 case UMLObject::ot_CheckConstraint: return i18n("Rename check constraint");
670 case UMLObject::ot_Class: return i18n("Rename class");
671 case UMLObject::ot_Component: return i18n("Rename component");
672 case UMLObject::ot_Datatype: return i18n("Rename datatype");
673 case UMLObject::ot_Entity: return i18n("Rename entity");
674 case UMLObject::ot_EntityAttribute: return i18n("Rename entity attribute");
675 case UMLObject::ot_EntityConstraint: return i18n("Rename entity constraint");
676 case UMLObject::ot_Enum: return i18n("Rename enum");
677 case UMLObject::ot_EnumLiteral: return i18n("Rename enum literal");
678 case UMLObject::ot_Folder: return i18n("Rename folder");
679 case UMLObject::ot_ForeignKeyConstraint:return i18n("Rename foreign key constraint");
680 case UMLObject::ot_Instance: return i18n("Rename instance");
681 case UMLObject::ot_InstanceAttribute: return i18n("Rename instance attribute");
682 case UMLObject::ot_Interface: return i18n("Rename interface");
683 case UMLObject::ot_Node: return i18n("Rename node");
684 case UMLObject::ot_Operation: return i18n("Rename operation");
685 case UMLObject::ot_Package: return i18n("Rename package");
686 case UMLObject::ot_Port: return i18n("Rename port");
687 case UMLObject::ot_Role: return i18n("Rename role");
688 case UMLObject::ot_Stereotype: return i18n("Rename stereotype");
689 case UMLObject::ot_Template: return i18n("Rename template");
690 case UMLObject::ot_UniqueConstraint: return i18n("Rename unique constraint");
691 case UMLObject::ot_UseCase: return i18n("Rename use case");
692 default:
693 uWarning() << "model_utils::renameTitle unknown object type" << UMLObject::toString(type);
694 return i18n("Rename UML object");
695 }
696 }
697
698 /**
699 * Returns translated text string used by uml object related dialogs
700 * @param type uml object type
701 * @return translated text string
702 */
renameText(UMLObject::ObjectType type)703 QString renameText(UMLObject::ObjectType type)
704 {
705 switch(type) {
706 case UMLObject::ot_Actor: return i18n("Enter the new name of the actor:");
707 case UMLObject::ot_Artifact: return i18n("Enter the new name of the artifact:");
708 case UMLObject::ot_Association: return i18n("Enter the new name of the association:");
709 case UMLObject::ot_Attribute: return i18n("Enter the new name of the attribute:");
710 case UMLObject::ot_Category: return i18n("Enter the new name of the category:");
711 case UMLObject::ot_CheckConstraint: return i18n("Enter the new name of the check constraint:");
712 case UMLObject::ot_Class: return i18n("Enter the new name of the class:");
713 case UMLObject::ot_Component: return i18n("Enter the new name of the component:");
714 case UMLObject::ot_Datatype: return i18n("Enter the new name of the datatype:");
715 case UMLObject::ot_Entity: return i18n("Enter the new name of the entity:");
716 case UMLObject::ot_EntityAttribute: return i18n("Enter the new name of the entity attribute:");
717 case UMLObject::ot_EntityConstraint: return i18n("Enter the new name of the entity constraint:");
718 case UMLObject::ot_Enum: return i18n("Enter the new name of the enum:");
719 case UMLObject::ot_EnumLiteral: return i18n("Enter the new name of the enum literal:");
720 case UMLObject::ot_Folder: return i18n("Enter the new name of the folder:");
721 case UMLObject::ot_ForeignKeyConstraint:return i18n("Enter the new name of the foreign key constraint:");
722 case UMLObject::ot_Instance: return i18n("Enter the new name of the instance:");
723 case UMLObject::ot_InstanceAttribute: return i18n("Enter the new name of the instance attribute:");
724 case UMLObject::ot_Interface: return i18n("Enter the new name of the interface:");
725 case UMLObject::ot_Node: return i18n("Enter the new name of the node:");
726 case UMLObject::ot_Operation: return i18n("Enter the new name of the operation:");
727 case UMLObject::ot_Package: return i18n("Enter the new name of the package:");
728 case UMLObject::ot_Port: return i18n("Enter the new name of the port:");
729 case UMLObject::ot_Role: return i18n("Enter the new name of the role:");
730 case UMLObject::ot_Stereotype: return i18n("Enter the new name of the stereotype:");
731 case UMLObject::ot_Template: return i18n("Enter the new name of the template:");
732 case UMLObject::ot_UniqueConstraint: return i18n("Enter the new name of the unique constraint:");
733 case UMLObject::ot_UseCase: return i18n("Enter the new name of the use case:");
734 default:
735 uWarning() << "model_utils::renameText unknown object type" << UMLObject::toString(type);
736 return i18n("Enter the new name of the UML object");
737 }
738 }
739
740 /**
741 * Return the xmi.id (XMI-1) or xmi:id (XMI-2) of a QDomElement.
742 */
getXmiId(QDomElement element)743 QString getXmiId(QDomElement element)
744 {
745 QString idStr = element.attribute(QLatin1String("xmi.id"));
746 if (idStr.isEmpty())
747 idStr = element.attribute(QLatin1String("xmi:id"));
748 return idStr;
749 }
750
751 /**
752 * Return true if the given tag is one of the common XMI
753 * attributes, such as:
754 * "name" | "visibility" | "isRoot" | "isLeaf" | "isAbstract" |
755 * "isActive" | "ownerScope"
756 */
isCommonXMI1Attribute(const QString & tag)757 bool isCommonXMI1Attribute(const QString &tag)
758 {
759 bool retval = (UMLDoc::tagEq(tag, QLatin1String("name")) ||
760 UMLDoc::tagEq(tag, QLatin1String("visibility")) ||
761 UMLDoc::tagEq(tag, QLatin1String("isRoot")) ||
762 UMLDoc::tagEq(tag, QLatin1String("isLeaf")) ||
763 UMLDoc::tagEq(tag, QLatin1String("isAbstract")) ||
764 UMLDoc::tagEq(tag, QLatin1String("isSpecification")) ||
765 UMLDoc::tagEq(tag, QLatin1String("isActive")) ||
766 UMLDoc::tagEq(tag, QLatin1String("namespace")) ||
767 UMLDoc::tagEq(tag, QLatin1String("ownerScope")) ||
768 UMLDoc::tagEq(tag, QLatin1String("ModelElement.stereotype")) ||
769 UMLDoc::tagEq(tag, QLatin1String("GeneralizableElement.generalization")) ||
770 UMLDoc::tagEq(tag, QLatin1String("specialization")) || //NYI
771 UMLDoc::tagEq(tag, QLatin1String("clientDependency")) || //NYI
772 UMLDoc::tagEq(tag, QLatin1String("supplierDependency")) //NYI
773 );
774 return retval;
775 }
776
777 /**
778 * Return true if the given type is common among the majority
779 * of programming languages, such as "bool" or "boolean".
780 * TODO: Make this depend on the active programming language.
781 */
isCommonDataType(QString type)782 bool isCommonDataType(QString type)
783 {
784 CodeGenerator *gen = UMLApp::app()->generator();
785 if (gen == 0)
786 return true; // gen == NULL means we use UMLPrimitiveTypes
787 const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
788 const QStringList dataTypes = gen->defaultDatatypes();
789 QStringList::ConstIterator end(dataTypes.end());
790 for (QStringList::ConstIterator it = dataTypes.begin(); it != end; ++it) {
791 if (caseSensitive) {
792 if (type == *it)
793 return true;
794 } else if (type.toLower() == (*it).toLower()) {
795 return true;
796 }
797 }
798 return false;
799 }
800
801 /**
802 * Return true if the given object type is a classifier list item type.
803 */
isClassifierListitem(UMLObject::ObjectType type)804 bool isClassifierListitem(UMLObject::ObjectType type)
805 {
806 if (type == UMLObject::ot_Attribute ||
807 type == UMLObject::ot_Operation ||
808 type == UMLObject::ot_Template ||
809 type == UMLObject::ot_EntityAttribute ||
810 type == UMLObject::ot_EnumLiteral ||
811 type == UMLObject::ot_UniqueConstraint ||
812 type == UMLObject::ot_ForeignKeyConstraint ||
813 type == UMLObject::ot_CheckConstraint) {
814 // UMLObject::ot_InstanceAttribute needs to be handled separately
815 // because UMLInstanceAttribute is not a UMLClassifierListItem.
816 return true;
817 } else {
818 return false;
819 }
820 }
821
822 /**
823 * Try to guess the correct container folder type of a UMLObject.
824 * Object types that can't be guessed are mapped to Uml::ModelType::Logical.
825 * NOTE: This function exists mainly for handling pre-1.5.5 files
826 * and should not be used for new code.
827 */
guessContainer(UMLObject * o)828 Uml::ModelType::Enum guessContainer(UMLObject *o)
829 {
830 UMLObject::ObjectType ot = o->baseType();
831 if (ot == UMLObject::ot_Package && o->stereotype() == QLatin1String("subsystem"))
832 return Uml::ModelType::Component;
833 Uml::ModelType::Enum mt = Uml::ModelType::N_MODELTYPES;
834 switch (ot) {
835 case UMLObject::ot_Package: // trouble: package can also appear in Component view
836 case UMLObject::ot_Interface:
837 case UMLObject::ot_Datatype:
838 case UMLObject::ot_Enum:
839 case UMLObject::ot_Class:
840 case UMLObject::ot_Attribute:
841 case UMLObject::ot_Operation:
842 case UMLObject::ot_EnumLiteral:
843 case UMLObject::ot_Template:
844 case UMLObject::ot_Instance:
845 case UMLObject::ot_InstanceAttribute:
846 mt = Uml::ModelType::Logical;
847 break;
848 case UMLObject::ot_Actor:
849 case UMLObject::ot_UseCase:
850 mt = Uml::ModelType::UseCase;
851 break;
852 case UMLObject::ot_Component:
853 case UMLObject::ot_Port:
854 case UMLObject::ot_Artifact: // trouble: artifact can also appear at Deployment
855 mt = Uml::ModelType::Component;
856 break;
857 case UMLObject::ot_Node:
858 mt = Uml::ModelType::Deployment;
859 break;
860 case UMLObject::ot_Entity:
861 case UMLObject::ot_EntityAttribute:
862 case UMLObject::ot_UniqueConstraint:
863 case UMLObject::ot_ForeignKeyConstraint:
864 case UMLObject::ot_CheckConstraint:
865 case UMLObject::ot_Category:
866 mt = Uml::ModelType::EntityRelationship;
867 break;
868 case UMLObject::ot_Association:
869 {
870 UMLAssociation *assoc = o->asUMLAssociation();
871 UMLDoc *umldoc = UMLApp::app()->document();
872 for (int r = Uml::RoleType::A; r <= Uml::RoleType::B; ++r) {
873 UMLObject *roleObj = assoc->getObject(Uml::RoleType::fromInt(r));
874 if (roleObj == 0) {
875 // Ouch! we have been called while types are not yet resolved
876 return Uml::ModelType::N_MODELTYPES;
877 }
878 UMLPackage *pkg = roleObj->umlPackage();
879 if (pkg) {
880 while (pkg->umlPackage()) { // wind back to root
881 pkg = pkg->umlPackage();
882 }
883 const Uml::ModelType::Enum m = umldoc->rootFolderType(pkg);
884 if (m != Uml::ModelType::N_MODELTYPES)
885 return m;
886 }
887 mt = guessContainer(roleObj);
888 if (mt != Uml::ModelType::Logical)
889 break;
890 }
891 }
892 break;
893 default:
894 break;
895 }
896 return mt;
897 }
898
899 /**
900 * Parse a direction string into the Uml::ParameterDirection::Enum.
901 *
902 * @param input The string to parse: "in", "out", or "inout"
903 * optionally followed by whitespace.
904 * @param result The corresponding Uml::ParameterDirection::Enum.
905 * @return Length of the string matched, excluding the optional
906 * whitespace.
907 */
stringToDirection(QString input,Uml::ParameterDirection::Enum & result)908 int stringToDirection(QString input, Uml::ParameterDirection::Enum & result)
909 {
910 QRegExp dirx(QLatin1String("^(in|out|inout)"));
911 int pos = dirx.indexIn(input);
912 if (pos == -1)
913 return 0;
914 const QString dirStr = dirx.capturedTexts().first();
915 int dirLen = dirStr.length();
916 if (input.length() > dirLen && !input[dirLen].isSpace())
917 return 0; // no match after all.
918 if (dirStr == QLatin1String("out"))
919 result = Uml::ParameterDirection::Out;
920 else if (dirStr == QLatin1String("inout"))
921 result = Uml::ParameterDirection::InOut;
922 else
923 result = Uml::ParameterDirection::In;
924 return dirLen;
925 }
926
927 /**
928 * Parses a template parameter given in UML syntax.
929 *
930 * @param t Input text of the template parameter.
931 * Example: parname : partype
932 * or just: parname (for class type)
933 * @param nmTp NameAndType returned by this method.
934 * @param owningScope Pointer to the owning scope of the template param.
935 * @return Error status of the parse, PS_OK for success.
936 */
parseTemplate(QString t,NameAndType & nmTp,UMLClassifier * owningScope)937 Parse_Status parseTemplate(QString t, NameAndType& nmTp, UMLClassifier *owningScope)
938 {
939 UMLDoc *pDoc = UMLApp::app()->document();
940
941 t = t.trimmed();
942 if (t.isEmpty())
943 return PS_Empty;
944
945 QStringList nameAndType = t.split(QRegExp(QLatin1String("\\s*:\\s*")));
946 if (nameAndType.count() == 2) {
947 UMLObject *pType = 0;
948 if (nameAndType[1] != QLatin1String("class")) {
949 pType = pDoc->findUMLObject(nameAndType[1], UMLObject::ot_UMLObject, owningScope);
950 if (pType == 0)
951 return PS_Unknown_ArgType;
952 }
953 nmTp = NameAndType(nameAndType[0], pType);
954 } else {
955 nmTp = NameAndType(t, 0);
956 }
957 return PS_OK;
958 }
959
960 /**
961 * Parses an attribute given in UML syntax.
962 *
963 * @param a Input text of the attribute in UML syntax.
964 * Example: argname : argtype
965 * @param nmTp NameAndType returned by this method.
966 * @param owningScope Pointer to the owning scope of the attribute.
967 * @param vis Optional pointer to visibility (return value.)
968 * The visibility may be given at the beginning of the
969 * attribute text in mnemonic form as follows:
970 * "+" stands for public
971 * "#" stands for protected
972 * "-" stands for private
973 * "~" stands for implementation level visibility
974 *
975 * @return Error status of the parse, PS_OK for success.
976 */
parseAttribute(QString a,NameAndType & nmTp,UMLClassifier * owningScope,Uml::Visibility::Enum * vis)977 Parse_Status parseAttribute(QString a, NameAndType& nmTp, UMLClassifier *owningScope,
978 Uml::Visibility::Enum *vis /* = 0 */)
979 {
980 UMLDoc *pDoc = UMLApp::app()->document();
981
982 a = a.simplified();
983 if (a.isEmpty())
984 return PS_Empty;
985
986 int colonPos = a.indexOf(QLatin1Char(':'));
987 if (colonPos < 0) {
988 nmTp = NameAndType(a, 0);
989 return PS_OK;
990 }
991 QString name = a.left(colonPos).trimmed();
992 if (vis) {
993 QRegExp mnemonicVis(QLatin1String("^([\\+\\#\\-\\~] *)"));
994 int pos = mnemonicVis.indexIn(name);
995 if (pos == -1) {
996 *vis = Uml::Visibility::Private; // default value
997 } else {
998 QString caption = mnemonicVis.cap(1);
999 QString strVis = caption.left(1);
1000 if (strVis == QLatin1String("+"))
1001 *vis = Uml::Visibility::Public;
1002 else if (strVis == QLatin1String("#"))
1003 *vis = Uml::Visibility::Protected;
1004 else if (strVis == QLatin1String("-"))
1005 *vis = Uml::Visibility::Private;
1006 else
1007 *vis = Uml::Visibility::Implementation;
1008 }
1009 name.remove(mnemonicVis);
1010 }
1011 Uml::ParameterDirection::Enum pd = Uml::ParameterDirection::In;
1012 if (name.startsWith(QLatin1String(QLatin1String("in ")))) {
1013 pd = Uml::ParameterDirection::In;
1014 name = name.mid(3);
1015 } else if (name.startsWith(QLatin1String(QLatin1String("inout ")))) {
1016 pd = Uml::ParameterDirection::InOut;
1017 name = name.mid(6);
1018 } else if (name.startsWith(QLatin1String(QLatin1String("out ")))) {
1019 pd = Uml::ParameterDirection::Out;
1020 name = name.mid(4);
1021 }
1022 a = a.mid(colonPos + 1).trimmed();
1023 if (a.isEmpty()) {
1024 nmTp = NameAndType(name, 0, pd);
1025 return PS_OK;
1026 }
1027 QStringList typeAndInitialValue = a.split(QRegExp(QLatin1String("\\s*=\\s*")));
1028 const QString &type = typeAndInitialValue[0];
1029 UMLObject *pType = pDoc->findUMLObject(type, UMLObject::ot_UMLObject, owningScope);
1030 if (pType == 0) {
1031 nmTp = NameAndType(name, 0, pd);
1032 return PS_Unknown_ArgType;
1033 }
1034 QString initialValue;
1035 if (typeAndInitialValue.count() == 2) {
1036 initialValue = typeAndInitialValue[1];
1037 }
1038 nmTp = NameAndType(name, pType, pd, initialValue);
1039 return PS_OK;
1040 }
1041
1042 /**
1043 * Parses an operation given in UML syntax.
1044 *
1045 * @param m Input text of the operation in UML syntax.
1046 * Example of a two-argument operation returning "void":
1047 * methodname (arg1name : arg1type, arg2name : arg2type) : void
1048 * @param desc OpDescriptor returned by this method.
1049 * @param owningScope Pointer to the owning scope of the operation.
1050 * @return Error status of the parse, PS_OK for success.
1051 */
parseOperation(QString m,OpDescriptor & desc,UMLClassifier * owningScope)1052 Parse_Status parseOperation(QString m, OpDescriptor& desc, UMLClassifier *owningScope)
1053 {
1054 UMLDoc *pDoc = UMLApp::app()->document();
1055
1056 m = m.simplified();
1057 if (m.isEmpty())
1058 return PS_Empty;
1059 if (m.contains(QRegExp(QLatin1String("operator *()")))) {
1060 // C++ special case: two sets of parentheses
1061 desc.m_name = QLatin1String("operator()");
1062 m.remove(QRegExp(QLatin1String("operator *()")));
1063 } else {
1064 /**
1065 * The search pattern includes everything up to the opening parenthesis
1066 * because UML also permits non programming-language oriented designs
1067 * using narrative names, for example "check water temperature".
1068 */
1069 QRegExp beginningUpToOpenParenth(QLatin1String("^([^\\(]+)"));
1070 int pos = beginningUpToOpenParenth.indexIn(m);
1071 if (pos == -1)
1072 return PS_Illegal_MethodName;
1073 desc.m_name = beginningUpToOpenParenth.cap(1);
1074 }
1075 desc.m_pReturnType = 0;
1076 QRegExp pat = QRegExp(QLatin1String("\\) *:(.*)$"));
1077 int pos = pat.indexIn(m);
1078 if (pos != -1) { // return type is optional
1079 QString retType = pat.cap(1);
1080 retType = retType.trimmed();
1081 if (retType != QLatin1String("void")) {
1082 UMLObject *pRetType = owningScope ? owningScope->findTemplate(retType) : 0;
1083 if (pRetType == 0) {
1084 pRetType = pDoc->findUMLObject(retType, UMLObject::ot_UMLObject, owningScope);
1085 if (pRetType == 0)
1086 return PS_Unknown_ReturnType;
1087 }
1088 desc.m_pReturnType = pRetType;
1089 }
1090 }
1091 // Remove possible empty parentheses ()
1092 m.remove(QRegExp(QLatin1String("\\s*\\(\\s*\\)")));
1093 desc.m_args.clear();
1094 pat = QRegExp(QLatin1String("\\((.*)\\)"));
1095 pos = pat.indexIn(m);
1096 if (pos == -1) // argument list is optional
1097 return PS_OK;
1098 QString arglist = pat.cap(1);
1099 arglist = arglist.trimmed();
1100 if (arglist.isEmpty())
1101 return PS_OK;
1102 const QStringList args = arglist.split(QRegExp(QLatin1String("\\s*, \\s*")));
1103 for (QStringList::ConstIterator lit = args.begin(); lit != args.end(); ++lit) {
1104 NameAndType nmTp;
1105 Parse_Status ps = parseAttribute(*lit, nmTp, owningScope);
1106 if (ps)
1107 return ps;
1108 desc.m_args.append(nmTp);
1109 }
1110 return PS_OK;
1111 }
1112
1113 /**
1114 * Parses a constraint.
1115 *
1116 * @param m Input text of the constraint
1117 *
1118 * @param name The name returned by this method
1119 * @param owningScope Pointer to the owning scope of the constraint
1120 * @return Error status of the parse, PS_OK for success.
1121 */
parseConstraint(QString m,QString & name,UMLEntity * owningScope)1122 Parse_Status parseConstraint(QString m, QString& name, UMLEntity* owningScope)
1123 {
1124 Q_UNUSED(owningScope);
1125 m = m.simplified();
1126 if (m.isEmpty())
1127 return PS_Empty;
1128
1129 int colonPos = m.indexOf(QLatin1Char(':'));
1130 if (colonPos < 0) {
1131 name = m;
1132 return PS_OK;
1133 }
1134
1135 name = m.left(colonPos).trimmed();
1136 return PS_OK;
1137 }
1138
1139 /**
1140 * Returns the Parse_Status as a text.
1141 */
psText(Parse_Status value)1142 QString psText(Parse_Status value)
1143 {
1144 const QString text[] = {
1145 i18n("OK"), i18nc("parse status", "Empty"), i18n("Malformed argument"),
1146 i18n("Unknown argument type"), i18n("Illegal method name"),
1147 i18n("Unknown return type"), i18n("Unspecified error")
1148 };
1149 return text[(unsigned) value];
1150 }
1151
1152 /**
1153 * Return true if the listview type is one of the predefined root views
1154 * (root, logical, usecase, component, deployment, datatype, or entity-
1155 * relationship view.)
1156 */
typeIsRootView(UMLListViewItem::ListViewType type)1157 bool typeIsRootView(UMLListViewItem::ListViewType type)
1158 {
1159 switch (type) {
1160 case UMLListViewItem::lvt_View:
1161 case UMLListViewItem::lvt_Logical_View:
1162 case UMLListViewItem::lvt_UseCase_View:
1163 case UMLListViewItem::lvt_Component_View:
1164 case UMLListViewItem::lvt_Deployment_View:
1165 case UMLListViewItem::lvt_EntityRelationship_Model:
1166 return true;
1167 break;
1168 default:
1169 break;
1170 }
1171 return false;
1172 }
1173
1174 /**
1175 * Return true if the listview type also has a widget representation in diagrams.
1176 */
typeIsCanvasWidget(UMLListViewItem::ListViewType type)1177 bool typeIsCanvasWidget(UMLListViewItem::ListViewType type)
1178 {
1179 switch (type) {
1180 case UMLListViewItem::lvt_Actor:
1181 case UMLListViewItem::lvt_UseCase:
1182 case UMLListViewItem::lvt_Class:
1183 case UMLListViewItem::lvt_Package:
1184 case UMLListViewItem::lvt_Logical_Folder:
1185 case UMLListViewItem::lvt_UseCase_Folder:
1186 case UMLListViewItem::lvt_Component_Folder:
1187 case UMLListViewItem::lvt_Deployment_Folder:
1188 case UMLListViewItem::lvt_EntityRelationship_Folder:
1189 case UMLListViewItem::lvt_Subsystem:
1190 case UMLListViewItem::lvt_Component:
1191 case UMLListViewItem::lvt_Port:
1192 case UMLListViewItem::lvt_Node:
1193 case UMLListViewItem::lvt_Artifact:
1194 case UMLListViewItem::lvt_Interface:
1195 case UMLListViewItem::lvt_Datatype:
1196 case UMLListViewItem::lvt_Enum:
1197 case UMLListViewItem::lvt_Instance:
1198 case UMLListViewItem::lvt_Entity:
1199 case UMLListViewItem::lvt_Category:
1200 return true;
1201 break;
1202 default:
1203 break;
1204 }
1205 return false;
1206 }
1207
1208 /**
1209 * Return true if the listview type is a logical, usecase or component folder.
1210 */
typeIsFolder(UMLListViewItem::ListViewType type)1211 bool typeIsFolder(UMLListViewItem::ListViewType type)
1212 {
1213 if (typeIsRootView(type) ||
1214 type == UMLListViewItem::lvt_Datatype_Folder ||
1215 type == UMLListViewItem::lvt_Logical_Folder ||
1216 type == UMLListViewItem::lvt_UseCase_Folder ||
1217 type == UMLListViewItem::lvt_Component_Folder ||
1218 type == UMLListViewItem::lvt_Deployment_Folder ||
1219 type == UMLListViewItem::lvt_EntityRelationship_Folder) {
1220 return true;
1221 } else {
1222 return false;
1223 }
1224 }
1225
1226 /**
1227 * Return true if the listview type may act as a container for other objects,
1228 * i.e. if it is a folder, package, subsystem, or component.
1229 */
typeIsContainer(UMLListViewItem::ListViewType type)1230 bool typeIsContainer(UMLListViewItem::ListViewType type)
1231 {
1232 if (typeIsFolder(type))
1233 return true;
1234 return (type == UMLListViewItem::lvt_Package ||
1235 type == UMLListViewItem::lvt_Subsystem ||
1236 type == UMLListViewItem::lvt_Component ||
1237 type == UMLListViewItem::lvt_Class ||
1238 type == UMLListViewItem::lvt_Interface);
1239 }
1240
1241 /**
1242 * Return true if the listview type is an attribute, operation, or template.
1243 */
typeIsClassifierList(UMLListViewItem::ListViewType type)1244 bool typeIsClassifierList(UMLListViewItem::ListViewType type)
1245 {
1246 if (type == UMLListViewItem::lvt_Attribute ||
1247 type == UMLListViewItem::lvt_Operation ||
1248 type == UMLListViewItem::lvt_Template ||
1249 type == UMLListViewItem::lvt_EntityAttribute ||
1250 type == UMLListViewItem::lvt_UniqueConstraint ||
1251 type == UMLListViewItem::lvt_ForeignKeyConstraint ||
1252 type == UMLListViewItem::lvt_PrimaryKeyConstraint ||
1253 type == UMLListViewItem::lvt_CheckConstraint ||
1254 type == UMLListViewItem::lvt_EnumLiteral) {
1255 // UMLListViewItem::lvt_InstanceAttribute must be handled separately
1256 // because UMLInstanceAttribute is not a UMLClassifierListItem.
1257 return true;
1258 } else {
1259 return false;
1260 }
1261 }
1262
1263 /**
1264 * Return true if the listview type is a classifier (Class, Entity, Enum)
1265 */
typeIsClassifier(UMLListViewItem::ListViewType type)1266 bool typeIsClassifier(UMLListViewItem::ListViewType type)
1267 {
1268 if (type == UMLListViewItem::lvt_Class ||
1269 type == UMLListViewItem::lvt_Interface ||
1270 type == UMLListViewItem::lvt_Entity ||
1271 type == UMLListViewItem::lvt_Enum) {
1272 return true;
1273 }
1274 return false;
1275 }
1276
1277 /**
1278 * Return true if the listview type is a settings entry.
1279 */
typeIsProperties(UMLListViewItem::ListViewType type)1280 bool typeIsProperties(UMLListViewItem::ListViewType type)
1281 {
1282 switch (type) {
1283 case UMLListViewItem::lvt_Properties:
1284 case UMLListViewItem::lvt_Properties_AutoLayout:
1285 case UMLListViewItem::lvt_Properties_Class:
1286 case UMLListViewItem::lvt_Properties_CodeImport:
1287 case UMLListViewItem::lvt_Properties_CodeGeneration:
1288 case UMLListViewItem::lvt_Properties_CodeViewer:
1289 case UMLListViewItem::lvt_Properties_Font:
1290 case UMLListViewItem::lvt_Properties_General:
1291 case UMLListViewItem::lvt_Properties_UserInterface:
1292 return true;
1293 break;
1294 default:
1295 break;
1296 }
1297 return false;
1298 }
1299
1300 /**
1301 * Check if a listviewitem of type childType is allowed
1302 * as child of type parentType
1303 */
typeIsAllowedInType(UMLListViewItem::ListViewType childType,UMLListViewItem::ListViewType parentType)1304 bool typeIsAllowedInType(UMLListViewItem::ListViewType childType,
1305 UMLListViewItem::ListViewType parentType)
1306 {
1307 switch (childType) {
1308 case UMLListViewItem::lvt_Class:
1309 case UMLListViewItem::lvt_Package:
1310 case UMLListViewItem::lvt_Interface:
1311 case UMLListViewItem::lvt_Enum:
1312 case UMLListViewItem::lvt_Instance:
1313 return parentType == UMLListViewItem::lvt_Logical_View ||
1314 parentType == UMLListViewItem::lvt_Class ||
1315 parentType == UMLListViewItem::lvt_Package ||
1316 parentType == UMLListViewItem::lvt_Logical_Folder;
1317 case UMLListViewItem::lvt_Attribute:
1318 return parentType == UMLListViewItem::lvt_Class;
1319 case UMLListViewItem::lvt_EntityAttribute:
1320 return parentType == UMLListViewItem::lvt_Entity;
1321 case UMLListViewItem::lvt_InstanceAttribute:
1322 return parentType == UMLListViewItem::lvt_Instance;
1323 case UMLListViewItem::lvt_Operation:
1324 return parentType == UMLListViewItem::lvt_Class ||
1325 parentType == UMLListViewItem::lvt_Interface;
1326 case UMLListViewItem::lvt_Datatype:
1327 return parentType == UMLListViewItem::lvt_Logical_Folder ||
1328 parentType == UMLListViewItem::lvt_Datatype_Folder ||
1329 parentType == UMLListViewItem::lvt_Class ||
1330 parentType == UMLListViewItem::lvt_Interface ||
1331 parentType == UMLListViewItem::lvt_Package;
1332 case UMLListViewItem::lvt_Class_Diagram:
1333 case UMLListViewItem::lvt_Collaboration_Diagram:
1334 case UMLListViewItem::lvt_State_Diagram:
1335 case UMLListViewItem::lvt_Activity_Diagram:
1336 case UMLListViewItem::lvt_Sequence_Diagram:
1337 case UMLListViewItem::lvt_Object_Diagram:
1338 return parentType == UMLListViewItem::lvt_Logical_Folder ||
1339 parentType == UMLListViewItem::lvt_Logical_View;
1340 case UMLListViewItem::lvt_Logical_Folder:
1341 return parentType == UMLListViewItem::lvt_Package ||
1342 parentType == UMLListViewItem::lvt_Logical_Folder ||
1343 parentType == UMLListViewItem::lvt_Logical_View;
1344 case UMLListViewItem::lvt_UseCase_Folder:
1345 return parentType == UMLListViewItem::lvt_UseCase_Folder ||
1346 parentType == UMLListViewItem::lvt_UseCase_View;
1347 case UMLListViewItem::lvt_Component_Folder:
1348 return parentType == UMLListViewItem::lvt_Component_Folder ||
1349 parentType == UMLListViewItem::lvt_Component_View;
1350 case UMLListViewItem::lvt_Deployment_Folder:
1351 return parentType == UMLListViewItem::lvt_Deployment_Folder ||
1352 parentType == UMLListViewItem::lvt_Deployment_View;
1353 case UMLListViewItem::lvt_EntityRelationship_Folder:
1354 return parentType == UMLListViewItem::lvt_EntityRelationship_Folder ||
1355 parentType == UMLListViewItem::lvt_EntityRelationship_Model;
1356 case UMLListViewItem::lvt_Actor:
1357 case UMLListViewItem::lvt_UseCase:
1358 case UMLListViewItem::lvt_UseCase_Diagram:
1359 return parentType == UMLListViewItem::lvt_UseCase_Folder ||
1360 parentType == UMLListViewItem::lvt_UseCase_View;
1361 case UMLListViewItem::lvt_Subsystem:
1362 return parentType == UMLListViewItem::lvt_Component_Folder ||
1363 parentType == UMLListViewItem::lvt_Subsystem ||
1364 parentType == UMLListViewItem::lvt_Component_View;
1365 case UMLListViewItem::lvt_Component:
1366 return parentType == UMLListViewItem::lvt_Component_Folder ||
1367 parentType == UMLListViewItem::lvt_Component ||
1368 parentType == UMLListViewItem::lvt_Subsystem ||
1369 parentType == UMLListViewItem::lvt_Component_View;
1370 case UMLListViewItem::lvt_Port:
1371 return parentType == UMLListViewItem::lvt_Component ||
1372 parentType == UMLListViewItem::lvt_Subsystem;
1373 case UMLListViewItem::lvt_Artifact:
1374 case UMLListViewItem::lvt_Component_Diagram:
1375 return parentType == UMLListViewItem::lvt_Component_Folder ||
1376 parentType == UMLListViewItem::lvt_Component_View;
1377 case UMLListViewItem::lvt_Node:
1378 case UMLListViewItem::lvt_Deployment_Diagram:
1379 return parentType == UMLListViewItem::lvt_Deployment_Folder ||
1380 parentType == UMLListViewItem::lvt_Deployment_View;
1381 case UMLListViewItem::lvt_Entity:
1382 case UMLListViewItem::lvt_EntityRelationship_Diagram:
1383 case UMLListViewItem::lvt_Category:
1384 return parentType == UMLListViewItem::lvt_EntityRelationship_Folder ||
1385 parentType == UMLListViewItem::lvt_EntityRelationship_Model;
1386 default:
1387 return false;
1388 }
1389 }
1390
1391 /**
1392 * Return true if the listview type is a diagram.
1393 */
typeIsDiagram(UMLListViewItem::ListViewType type)1394 bool typeIsDiagram(UMLListViewItem::ListViewType type)
1395 {
1396 if (type == UMLListViewItem::lvt_Class_Diagram ||
1397 type == UMLListViewItem::lvt_Collaboration_Diagram ||
1398 type == UMLListViewItem::lvt_State_Diagram ||
1399 type == UMLListViewItem::lvt_Activity_Diagram ||
1400 type == UMLListViewItem::lvt_Sequence_Diagram ||
1401 type == UMLListViewItem::lvt_UseCase_Diagram ||
1402 type == UMLListViewItem::lvt_Component_Diagram ||
1403 type == UMLListViewItem::lvt_Deployment_Diagram ||
1404 type == UMLListViewItem::lvt_EntityRelationship_Diagram ||
1405 type == UMLListViewItem::lvt_Object_Diagram) {
1406 return true;
1407 } else {
1408 return false;
1409 }
1410 }
1411
1412 /**
1413 * Return the Model_Type which corresponds to the given DiagramType.
1414 */
convert_DT_MT(Uml::DiagramType::Enum dt)1415 Uml::ModelType::Enum convert_DT_MT(Uml::DiagramType::Enum dt)
1416 {
1417 Uml::ModelType::Enum mt;
1418 switch (dt) {
1419 case Uml::DiagramType::UseCase:
1420 mt = Uml::ModelType::UseCase;
1421 break;
1422 case Uml::DiagramType::Collaboration:
1423 case Uml::DiagramType::Class:
1424 case Uml::DiagramType::Object:
1425 case Uml::DiagramType::Sequence:
1426 case Uml::DiagramType::State:
1427 case Uml::DiagramType::Activity:
1428 mt = Uml::ModelType::Logical;
1429 break;
1430 case Uml::DiagramType::Component:
1431 mt = Uml::ModelType::Component;
1432 break;
1433 case Uml::DiagramType::Deployment:
1434 mt = Uml::ModelType::Deployment;
1435 break;
1436 case Uml::DiagramType::EntityRelationship:
1437 mt = Uml::ModelType::EntityRelationship;
1438 break;
1439 default:
1440 uError() << "Model_Utils::convert_DT_MT: illegal input value " << dt;
1441 mt = Uml::ModelType::N_MODELTYPES;
1442 break;
1443 }
1444 return mt;
1445 }
1446
1447 /**
1448 * Return the ListViewType which corresponds to the given Model_Type.
1449 */
convert_MT_LVT(Uml::ModelType::Enum mt)1450 UMLListViewItem::ListViewType convert_MT_LVT(Uml::ModelType::Enum mt)
1451 {
1452 UMLListViewItem::ListViewType lvt = UMLListViewItem::lvt_Unknown;
1453 switch (mt) {
1454 case Uml::ModelType::Logical:
1455 lvt = UMLListViewItem::lvt_Logical_View;
1456 break;
1457 case Uml::ModelType::UseCase:
1458 lvt = UMLListViewItem::lvt_UseCase_View;
1459 break;
1460 case Uml::ModelType::Component:
1461 lvt = UMLListViewItem::lvt_Component_View;
1462 break;
1463 case Uml::ModelType::Deployment:
1464 lvt = UMLListViewItem::lvt_Deployment_View;
1465 break;
1466 case Uml::ModelType::EntityRelationship:
1467 lvt = UMLListViewItem::lvt_EntityRelationship_Model;
1468 break;
1469 default:
1470 break;
1471 }
1472 return lvt;
1473 }
1474
1475 /**
1476 * Return the Model_Type which corresponds to the given ListViewType.
1477 * Returns Uml::N_MODELTYPES if the list view type given does not map
1478 * to a Model_Type.
1479 */
convert_LVT_MT(UMLListViewItem::ListViewType lvt)1480 Uml::ModelType::Enum convert_LVT_MT(UMLListViewItem::ListViewType lvt)
1481 {
1482 Uml::ModelType::Enum mt = Uml::ModelType::N_MODELTYPES;
1483 switch (lvt) {
1484 case UMLListViewItem::lvt_Logical_View:
1485 mt = Uml::ModelType::Logical;
1486 break;
1487 case UMLListViewItem::lvt_UseCase_View:
1488 mt = Uml::ModelType::UseCase;
1489 break;
1490 case UMLListViewItem::lvt_Component_View:
1491 mt = Uml::ModelType::Component;
1492 break;
1493 case UMLListViewItem::lvt_Deployment_View:
1494 mt = Uml::ModelType::Deployment;
1495 break;
1496 case UMLListViewItem::lvt_EntityRelationship_Model:
1497 mt = Uml::ModelType::EntityRelationship;
1498 break;
1499 default:
1500 break;
1501 }
1502 return mt;
1503 }
1504
1505 /**
1506 * Convert a diagram type enum to the equivalent list view type.
1507 */
convert_DT_LVT(Uml::DiagramType::Enum dt)1508 UMLListViewItem::ListViewType convert_DT_LVT(Uml::DiagramType::Enum dt)
1509 {
1510 UMLListViewItem::ListViewType type = UMLListViewItem::lvt_Unknown;
1511 switch(dt) {
1512 case Uml::DiagramType::UseCase:
1513 type = UMLListViewItem::lvt_UseCase_Diagram;
1514 break;
1515
1516 case Uml::DiagramType::Class:
1517 type = UMLListViewItem::lvt_Class_Diagram;
1518 break;
1519
1520 case Uml::DiagramType::Object:
1521 type = UMLListViewItem::lvt_Object_Diagram;
1522 break;
1523
1524 case Uml::DiagramType::Sequence:
1525 type = UMLListViewItem::lvt_Sequence_Diagram;
1526 break;
1527
1528 case Uml::DiagramType::Collaboration:
1529 type = UMLListViewItem::lvt_Collaboration_Diagram;
1530 break;
1531
1532 case Uml::DiagramType::State:
1533 type = UMLListViewItem::lvt_State_Diagram;
1534 break;
1535
1536 case Uml::DiagramType::Activity:
1537 type = UMLListViewItem::lvt_Activity_Diagram;
1538 break;
1539
1540 case Uml::DiagramType::Component:
1541 type = UMLListViewItem::lvt_Component_Diagram;
1542 break;
1543
1544 case Uml::DiagramType::Deployment:
1545 type = UMLListViewItem::lvt_Deployment_Diagram;
1546 break;
1547
1548 case Uml::DiagramType::EntityRelationship:
1549 type = UMLListViewItem::lvt_EntityRelationship_Diagram;
1550 break;
1551
1552 default:
1553 uWarning() << "convert_DT_LVT() called on unknown diagram type";
1554 }
1555 return type;
1556 }
1557
1558 /**
1559 * Convert an object's type to the equivalent list view type
1560 *
1561 * @param o Pointer to the UMLObject whose type shall be converted
1562 * to the equivalent ListViewType. We cannot just
1563 * pass in a UMLObject::ObjectType because a UMLFolder is mapped
1564 * to different ListViewType values, depending on its
1565 * location in one of the predefined modelviews (Logical/
1566 * UseCase/etc.)
1567 * @return The equivalent ListViewType.
1568 */
convert_OT_LVT(UMLObject * o)1569 UMLListViewItem::ListViewType convert_OT_LVT(UMLObject *o)
1570 {
1571 UMLObject::ObjectType ot = o->baseType();
1572 UMLListViewItem::ListViewType type = UMLListViewItem::lvt_Unknown;
1573 switch(ot) {
1574 case UMLObject::ot_UseCase:
1575 type = UMLListViewItem::lvt_UseCase;
1576 break;
1577
1578 case UMLObject::ot_Actor:
1579 type = UMLListViewItem::lvt_Actor;
1580 break;
1581
1582 case UMLObject::ot_Class:
1583 type = UMLListViewItem::lvt_Class;
1584 break;
1585
1586 case UMLObject::ot_Package:
1587 if (o->stereotype() == QLatin1String("subsystem"))
1588 type = UMLListViewItem::lvt_Subsystem;
1589 else
1590 type = UMLListViewItem::lvt_Package;
1591 break;
1592
1593 case UMLObject::ot_Folder:
1594 {
1595 UMLDoc *umldoc = UMLApp::app()->document();
1596 UMLPackage *p = o->asUMLPackage();
1597 do {
1598 const Uml::ModelType::Enum mt = umldoc->rootFolderType(p);
1599 if (mt != Uml::ModelType::N_MODELTYPES) {
1600 switch (mt) {
1601 case Uml::ModelType::Logical:
1602 type = UMLListViewItem::lvt_Logical_Folder;
1603 break;
1604 case Uml::ModelType::UseCase:
1605 type = UMLListViewItem::lvt_UseCase_Folder;
1606 break;
1607 case Uml::ModelType::Component:
1608 type = UMLListViewItem::lvt_Component_Folder;
1609 break;
1610 case Uml::ModelType::Deployment:
1611 type = UMLListViewItem::lvt_Deployment_Folder;
1612 break;
1613 case Uml::ModelType::EntityRelationship:
1614 type = UMLListViewItem::lvt_EntityRelationship_Folder;
1615 break;
1616 default:
1617 break;
1618 }
1619 return type;
1620 }
1621 } while ((p = p->umlPackage()) != 0);
1622 uError() << "convert_OT_LVT(" << o->name()
1623 << "): internal error - object is not properly nested in folder";
1624 }
1625 break;
1626
1627 case UMLObject::ot_Component:
1628 type = UMLListViewItem::lvt_Component;
1629 break;
1630
1631 case UMLObject::ot_Port:
1632 type = UMLListViewItem::lvt_Port;
1633 break;
1634
1635 case UMLObject::ot_Node:
1636 type = UMLListViewItem::lvt_Node;
1637 break;
1638
1639 case UMLObject::ot_Artifact:
1640 type = UMLListViewItem::lvt_Artifact;
1641 break;
1642
1643 case UMLObject::ot_Interface:
1644 type = UMLListViewItem::lvt_Interface;
1645 break;
1646
1647 case UMLObject::ot_Datatype:
1648 type = UMLListViewItem::lvt_Datatype;
1649 break;
1650
1651 case UMLObject::ot_Enum:
1652 type = UMLListViewItem::lvt_Enum;
1653 break;
1654
1655 case UMLObject::ot_EnumLiteral:
1656 type = UMLListViewItem::lvt_EnumLiteral;
1657 break;
1658
1659 case UMLObject::ot_Entity:
1660 type = UMLListViewItem::lvt_Entity;
1661 break;
1662
1663 case UMLObject::ot_Category:
1664 type = UMLListViewItem::lvt_Category;
1665 break;
1666
1667 case UMLObject::ot_EntityAttribute:
1668 type = UMLListViewItem::lvt_EntityAttribute;
1669 break;
1670
1671 case UMLObject::ot_UniqueConstraint: {
1672 UMLEntity* ent = o->umlParent()->asUMLEntity();
1673 UMLUniqueConstraint* uc = o->asUMLUniqueConstraint();
1674 if (ent->isPrimaryKey(uc)) {
1675 type = UMLListViewItem::lvt_PrimaryKeyConstraint;
1676 } else {
1677 type = UMLListViewItem::lvt_UniqueConstraint;
1678 }
1679 break;
1680 }
1681
1682 case UMLObject::ot_ForeignKeyConstraint:
1683 type = UMLListViewItem::lvt_ForeignKeyConstraint;
1684 break;
1685
1686 case UMLObject::ot_CheckConstraint:
1687 type = UMLListViewItem::lvt_CheckConstraint;
1688 break;
1689
1690 case UMLObject::ot_Attribute:
1691 type = UMLListViewItem::lvt_Attribute;
1692 break;
1693
1694 case UMLObject::ot_Operation:
1695 type = UMLListViewItem::lvt_Operation;
1696 break;
1697
1698 case UMLObject::ot_Template:
1699 type = UMLListViewItem::lvt_Template;
1700 break;
1701
1702 case UMLObject::ot_Association:
1703 type = UMLListViewItem::lvt_Association;
1704 break;
1705
1706 case UMLObject::ot_Instance:
1707 type = UMLListViewItem::lvt_Instance;
1708 break;
1709
1710 case UMLObject::ot_InstanceAttribute:
1711 type = UMLListViewItem::lvt_InstanceAttribute;
1712 break;
1713
1714 default:
1715 break;
1716 }
1717 return type;
1718 }
1719
1720 /**
1721 * Converts a list view type enum to the equivalent object type.
1722 *
1723 * @param lvt The ListViewType to convert.
1724 * @return The converted ObjectType if the listview type
1725 * has a UMLObject::ObjectType representation, else 0.
1726 */
convert_LVT_OT(UMLListViewItem::ListViewType lvt)1727 UMLObject::ObjectType convert_LVT_OT(UMLListViewItem::ListViewType lvt)
1728 {
1729 UMLObject::ObjectType ot = (UMLObject::ObjectType)0;
1730 switch (lvt) {
1731 case UMLListViewItem::lvt_UseCase:
1732 ot = UMLObject::ot_UseCase;
1733 break;
1734
1735 case UMLListViewItem::lvt_Actor:
1736 ot = UMLObject::ot_Actor;
1737 break;
1738
1739 case UMLListViewItem::lvt_Class:
1740 ot = UMLObject::ot_Class;
1741 break;
1742
1743 case UMLListViewItem::lvt_Package:
1744 case UMLListViewItem::lvt_Subsystem:
1745 ot = UMLObject::ot_Package;
1746 break;
1747
1748 case UMLListViewItem::lvt_Component:
1749 ot = UMLObject::ot_Component;
1750 break;
1751
1752 case UMLListViewItem::lvt_Port:
1753 ot = UMLObject::ot_Port;
1754 break;
1755
1756 case UMLListViewItem::lvt_Node:
1757 ot = UMLObject::ot_Node;
1758 break;
1759
1760 case UMLListViewItem::lvt_Artifact:
1761 ot = UMLObject::ot_Artifact;
1762 break;
1763
1764 case UMLListViewItem::lvt_Interface:
1765 ot = UMLObject::ot_Interface;
1766 break;
1767
1768 case UMLListViewItem::lvt_Datatype:
1769 ot = UMLObject::ot_Datatype;
1770 break;
1771
1772 case UMLListViewItem::lvt_Enum:
1773 ot = UMLObject::ot_Enum;
1774 break;
1775
1776 case UMLListViewItem::lvt_Entity:
1777 ot = UMLObject::ot_Entity;
1778 break;
1779
1780 case UMLListViewItem::lvt_Category:
1781 ot = UMLObject::ot_Category;
1782 break;
1783
1784 case UMLListViewItem::lvt_EntityAttribute:
1785 ot = UMLObject::ot_EntityAttribute;
1786 break;
1787
1788 case UMLListViewItem::lvt_UniqueConstraint:
1789 ot = UMLObject::ot_UniqueConstraint;
1790 break;
1791
1792 case UMLListViewItem::lvt_PrimaryKeyConstraint:
1793 ot = UMLObject::ot_UniqueConstraint;
1794 break;
1795
1796 case UMLListViewItem::lvt_ForeignKeyConstraint:
1797 ot = UMLObject::ot_ForeignKeyConstraint;
1798 break;
1799
1800 case UMLListViewItem::lvt_CheckConstraint:
1801 ot = UMLObject::ot_CheckConstraint;
1802 break;
1803
1804 case UMLListViewItem::lvt_Attribute:
1805 ot = UMLObject::ot_Attribute;
1806 break;
1807
1808 case UMLListViewItem::lvt_Operation:
1809 ot = UMLObject::ot_Operation;
1810 break;
1811
1812 case UMLListViewItem::lvt_Template:
1813 ot = UMLObject::ot_Template;
1814 break;
1815
1816 case UMLListViewItem::lvt_EnumLiteral:
1817 ot = UMLObject::ot_EnumLiteral;
1818 break;
1819
1820 case UMLListViewItem::lvt_Instance:
1821 ot = UMLObject::ot_Instance;
1822 break;
1823
1824 case UMLListViewItem::lvt_InstanceAttribute:
1825 ot = UMLObject::ot_InstanceAttribute;
1826 break;
1827
1828 default:
1829 if (typeIsFolder(lvt))
1830 ot = UMLObject::ot_Folder;
1831 break;
1832 }
1833 return ot;
1834 }
1835
1836 /**
1837 * Return the IconType which corresponds to the given listview type.
1838 *
1839 * @param lvt ListViewType to convert.
1840 * @return The Icon_Utils::IconType corresponding to the lvt.
1841 * Returns it_Home in case no mapping to IconType exists.
1842 */
convert_LVT_IT(UMLListViewItem::ListViewType lvt,UMLObject * o)1843 Icon_Utils::IconType convert_LVT_IT(UMLListViewItem::ListViewType lvt, UMLObject *o)
1844 {
1845 Icon_Utils::IconType icon = Icon_Utils::it_Home;
1846 switch (lvt) {
1847 case UMLListViewItem::lvt_UseCase_View:
1848 case UMLListViewItem::lvt_UseCase_Folder:
1849 icon = Icon_Utils::it_Folder_Grey;
1850 break;
1851 case UMLListViewItem::lvt_Logical_View:
1852 case UMLListViewItem::lvt_Logical_Folder:
1853 icon = Icon_Utils::it_Folder_Green;
1854 break;
1855 case UMLListViewItem::lvt_Datatype_Folder:
1856 icon = Icon_Utils::it_Folder_Orange;
1857 break;
1858 case UMLListViewItem::lvt_Component_View:
1859 case UMLListViewItem::lvt_Component_Folder:
1860 icon = Icon_Utils::it_Folder_Red;
1861 break;
1862 case UMLListViewItem::lvt_Deployment_View:
1863 case UMLListViewItem::lvt_Deployment_Folder:
1864 icon = Icon_Utils::it_Folder_Violet;
1865 break;
1866 case UMLListViewItem::lvt_EntityRelationship_Model:
1867 case UMLListViewItem::lvt_EntityRelationship_Folder:
1868 icon = Icon_Utils::it_Folder_Cyan;
1869 break;
1870 case UMLListViewItem::lvt_Actor:
1871 icon = Icon_Utils::it_Actor;
1872 break;
1873 case UMLListViewItem::lvt_Association:
1874 icon = Icon_Utils::it_Association;
1875 break;
1876 case UMLListViewItem::lvt_UseCase:
1877 icon = Icon_Utils::it_UseCase;
1878 break;
1879 case UMLListViewItem::lvt_Class:
1880 if (o && o->stereotype() == QLatin1String("class-or-package"))
1881 icon = Icon_Utils::it_ClassOrPackage;
1882 else
1883 icon = Icon_Utils::it_Class;
1884 break;
1885 case UMLListViewItem::lvt_Package:
1886 icon = Icon_Utils::it_Package;
1887 break;
1888 case UMLListViewItem::lvt_Subsystem:
1889 icon = Icon_Utils::it_Subsystem;
1890 break;
1891 case UMLListViewItem::lvt_Component:
1892 icon = Icon_Utils::it_Component;
1893 break;
1894 case UMLListViewItem::lvt_Port:
1895 icon = Icon_Utils::it_Port;
1896 break;
1897 case UMLListViewItem::lvt_Node:
1898 icon = Icon_Utils::it_Node;
1899 break;
1900 case UMLListViewItem::lvt_Artifact:
1901 icon = Icon_Utils::it_Artifact;
1902 break;
1903 case UMLListViewItem::lvt_Interface:
1904 icon = Icon_Utils::it_Interface;
1905 break;
1906 case UMLListViewItem::lvt_Datatype:
1907 icon = Icon_Utils::it_Datatype;
1908 break;
1909 case UMLListViewItem::lvt_Enum:
1910 icon = Icon_Utils::it_Enum;
1911 break;
1912 case UMLListViewItem::lvt_Entity:
1913 icon = Icon_Utils::it_Entity;
1914 break;
1915 case UMLListViewItem::lvt_Category:
1916 icon = Icon_Utils::it_Category;
1917 break;
1918 case UMLListViewItem::lvt_Template:
1919 icon = Icon_Utils::it_Template;
1920 break;
1921 case UMLListViewItem::lvt_Attribute:
1922 icon = Icon_Utils::it_Private_Attribute;
1923 break;
1924 case UMLListViewItem::lvt_EntityAttribute:
1925 icon = Icon_Utils::it_Private_Attribute;
1926 break;
1927 case UMLListViewItem::lvt_EnumLiteral:
1928 icon = Icon_Utils::it_Public_Attribute;
1929 break;
1930 case UMLListViewItem::lvt_Operation:
1931 icon = Icon_Utils::it_Public_Method;
1932 break;
1933 case UMLListViewItem::lvt_UniqueConstraint:
1934 icon = Icon_Utils::it_Unique_Constraint;
1935 break;
1936 case UMLListViewItem::lvt_PrimaryKeyConstraint:
1937 icon = Icon_Utils::it_PrimaryKey_Constraint;
1938 break;
1939 case UMLListViewItem::lvt_ForeignKeyConstraint:
1940 icon = Icon_Utils::it_ForeignKey_Constraint;
1941 break;
1942 case UMLListViewItem::lvt_CheckConstraint:
1943 icon = Icon_Utils::it_Check_Constraint;
1944 break;
1945 case UMLListViewItem::lvt_Class_Diagram:
1946 icon = Icon_Utils::it_Diagram_Class;
1947 break;
1948 case UMLListViewItem::lvt_Object_Diagram:
1949 icon = Icon_Utils::it_Diagram_Object;
1950 break;
1951 case UMLListViewItem::lvt_UseCase_Diagram:
1952 icon = Icon_Utils::it_Diagram_Usecase;
1953 break;
1954 case UMLListViewItem::lvt_Sequence_Diagram:
1955 icon = Icon_Utils::it_Diagram_Sequence;
1956 break;
1957 case UMLListViewItem::lvt_Collaboration_Diagram:
1958 icon = Icon_Utils::it_Diagram_Collaboration;
1959 break;
1960 case UMLListViewItem::lvt_State_Diagram:
1961 icon = Icon_Utils::it_Diagram_State;
1962 break;
1963 case UMLListViewItem::lvt_Activity_Diagram:
1964 icon = Icon_Utils::it_Diagram_Activity;
1965 break;
1966 case UMLListViewItem::lvt_Component_Diagram:
1967 icon = Icon_Utils::it_Diagram_Component;
1968 break;
1969 case UMLListViewItem::lvt_Deployment_Diagram:
1970 icon = Icon_Utils::it_Diagram_Deployment;
1971 break;
1972 case UMLListViewItem::lvt_EntityRelationship_Diagram:
1973 icon = Icon_Utils::it_Diagram_EntityRelationship;
1974 break;
1975 case UMLListViewItem::lvt_Properties:
1976 icon = Icon_Utils::it_Properties;
1977 break;
1978 case UMLListViewItem::lvt_Properties_AutoLayout:
1979 icon = Icon_Utils::it_Properties_AutoLayout;
1980 break;
1981 case UMLListViewItem::lvt_Properties_Class:
1982 icon = Icon_Utils::it_Properties_Class;
1983 break;
1984 case UMLListViewItem::lvt_Properties_CodeImport:
1985 icon = Icon_Utils::it_Properties_CodeImport;
1986 break;
1987 case UMLListViewItem::lvt_Properties_CodeGeneration:
1988 icon = Icon_Utils::it_Properties_CodeGeneration;
1989 break;
1990 case UMLListViewItem::lvt_Properties_CodeViewer:
1991 icon = Icon_Utils::it_Properties_CodeViewer;
1992 break;
1993 case UMLListViewItem::lvt_Properties_Font:
1994 icon = Icon_Utils::it_Properties_Font;
1995 break;
1996 case UMLListViewItem::lvt_Properties_General:
1997 icon = Icon_Utils::it_Properties_General;
1998 break;
1999 case UMLListViewItem::lvt_Properties_UserInterface:
2000 icon = Icon_Utils::it_Properties_UserInterface;
2001 break;
2002 case UMLListViewItem::lvt_Instance:
2003 icon = Icon_Utils::it_Instance;
2004 break;
2005 case UMLListViewItem::lvt_InstanceAttribute:
2006 icon = Icon_Utils::it_Private_Attribute;
2007 break;
2008 default:
2009 break;
2010 }
2011 return icon;
2012 }
2013
2014 /**
2015 * Return the DiagramType which corresponds to the given listview type.
2016 *
2017 * @param lvt ListViewType to convert.
2018 * @return The Uml::DiagramType corresponding to the lvt.
2019 * Returns dt_Undefined in case no mapping to DiagramType exists.
2020 */
convert_LVT_DT(UMLListViewItem::ListViewType lvt)2021 Uml::DiagramType::Enum convert_LVT_DT(UMLListViewItem::ListViewType lvt)
2022 {
2023 Uml::DiagramType::Enum dt = Uml::DiagramType::Undefined;
2024 switch (lvt) {
2025 case UMLListViewItem::lvt_Class_Diagram:
2026 dt = Uml::DiagramType::Class;
2027 break;
2028 case UMLListViewItem::lvt_UseCase_Diagram:
2029 dt = Uml::DiagramType::UseCase;
2030 break;
2031 case UMLListViewItem::lvt_Sequence_Diagram:
2032 dt = Uml::DiagramType::Sequence;
2033 break;
2034 case UMLListViewItem::lvt_Collaboration_Diagram:
2035 dt = Uml::DiagramType::Collaboration;
2036 break;
2037 case UMLListViewItem::lvt_State_Diagram:
2038 dt = Uml::DiagramType::State;
2039 break;
2040 case UMLListViewItem::lvt_Activity_Diagram:
2041 dt = Uml::DiagramType::Activity;
2042 break;
2043 case UMLListViewItem::lvt_Component_Diagram:
2044 dt = Uml::DiagramType::Component;
2045 break;
2046 case UMLListViewItem::lvt_Deployment_Diagram:
2047 dt = Uml::DiagramType::Deployment;
2048 break;
2049 case UMLListViewItem::lvt_EntityRelationship_Diagram:
2050 dt = Uml::DiagramType::EntityRelationship;
2051 break;
2052 case UMLListViewItem::lvt_Object_Diagram:
2053 dt = Uml::DiagramType::Object;
2054 break;
2055 default:
2056 break;
2057 }
2058 return dt;
2059 }
2060
2061 /**
2062 * Converts a list view type enum to the equivalent settings dialog type.
2063 *
2064 * @param type The ListViewType to convert.
2065 * @return The converted settings dialog type
2066 */
convert_LVT_PT(UMLListViewItem::ListViewType type)2067 MultiPageDialogBase::PageType convert_LVT_PT(UMLListViewItem::ListViewType type)
2068 {
2069 MultiPageDialogBase::PageType pt = MultiPageDialogBase::GeneralPage;
2070 switch (type) {
2071 case UMLListViewItem::lvt_Properties:
2072 pt = MultiPageDialogBase::GeneralPage;
2073 break;
2074 case UMLListViewItem::lvt_Properties_AutoLayout:
2075 pt = MultiPageDialogBase::AutoLayoutPage;
2076 break;
2077 case UMLListViewItem::lvt_Properties_Class:
2078 pt = MultiPageDialogBase::ClassPage;
2079 break;
2080 case UMLListViewItem::lvt_Properties_CodeImport:
2081 pt = MultiPageDialogBase::CodeImportPage;
2082 break;
2083 case UMLListViewItem::lvt_Properties_CodeGeneration:
2084 pt = MultiPageDialogBase::CodeGenerationPage;
2085 break;
2086 case UMLListViewItem::lvt_Properties_CodeViewer:
2087 pt = MultiPageDialogBase::CodeViewerPage;
2088 break;
2089 case UMLListViewItem::lvt_Properties_Font:
2090 pt = MultiPageDialogBase::FontPage;
2091 break;
2092 case UMLListViewItem::lvt_Properties_General:
2093 pt = MultiPageDialogBase::GeneralPage;
2094 break;
2095 case UMLListViewItem::lvt_Properties_UserInterface:
2096 pt = MultiPageDialogBase::UserInterfacePage;
2097 break;
2098 default:
2099 break;
2100 }
2101 return pt;
2102 }
2103
2104 /**
2105 * Return the Model_Type which corresponds to the given ObjectType.
2106 */
convert_OT_MT(UMLObject::ObjectType ot)2107 Uml::ModelType::Enum convert_OT_MT(UMLObject::ObjectType ot)
2108 {
2109 Uml::ModelType::Enum mt = Uml::ModelType::N_MODELTYPES;
2110 switch (ot) {
2111 case UMLObject::ot_Actor:
2112 case UMLObject::ot_UseCase:
2113 mt = Uml::ModelType::UseCase;
2114 break;
2115 case UMLObject::ot_Component:
2116 case UMLObject::ot_Port:
2117 case UMLObject::ot_Artifact:
2118 case UMLObject::ot_SubSystem:
2119 mt = Uml::ModelType::Component;
2120 break;
2121 case UMLObject::ot_Node:
2122 mt = Uml::ModelType::Deployment;
2123 break;
2124 case UMLObject::ot_Entity:
2125 case UMLObject::ot_EntityAttribute:
2126 case UMLObject::ot_UniqueConstraint:
2127 case UMLObject::ot_ForeignKeyConstraint:
2128 case UMLObject::ot_CheckConstraint:
2129 case UMLObject::ot_Category:
2130 mt = Uml::ModelType::EntityRelationship;
2131 break;
2132 default:
2133 mt = Uml::ModelType::Logical;
2134 break;
2135 }
2136 return mt;
2137 }
2138
2139 /**
2140 * Converts from the UpdateDeleteAction enum to a QString
2141 * @param uda The UpdateDeleteAction enum literal
2142 */
updateDeleteActionToString(UMLForeignKeyConstraint::UpdateDeleteAction uda)2143 QString updateDeleteActionToString(UMLForeignKeyConstraint::UpdateDeleteAction uda)
2144 {
2145 switch(uda) {
2146 case UMLForeignKeyConstraint::uda_NoAction:
2147 return QLatin1String("NO ACTION");
2148 case UMLForeignKeyConstraint::uda_Restrict:
2149 return QLatin1String("RESTRICT");
2150 case UMLForeignKeyConstraint::uda_Cascade:
2151 return QLatin1String("CASCADE");
2152 case UMLForeignKeyConstraint::uda_SetNull:
2153 return QLatin1String("SET NULL");
2154 case UMLForeignKeyConstraint::uda_SetDefault:
2155 return QLatin1String("SET DEFAULT");
2156 default:
2157 return QString();
2158 }
2159 }
2160
2161 /**
2162 * Return true if the object type is allowed in the related diagram
2163 * @param o UML object instance
2164 * @param scene diagram instance
2165 * @return true type is allowed
2166 * @return false type is not allowed
2167 */
typeIsAllowedInDiagram(UMLObject * o,UMLScene * scene)2168 bool typeIsAllowedInDiagram(UMLObject* o, UMLScene *scene)
2169 {
2170 //make sure dragging item onto correct diagram
2171 // concept - class, seq, coll diagram
2172 // actor, usecase - usecase diagram
2173 UMLObject::ObjectType ot = o->baseType();
2174 Uml::ID::Type id = o->id();
2175 Uml::DiagramType::Enum diagramType = scene->type();
2176 bool bAccept = true;
2177
2178 switch (diagramType) {
2179 case Uml::DiagramType::UseCase:
2180 if ((scene->widgetOnDiagram(id) && ot == UMLObject::ot_Actor) ||
2181 (ot != UMLObject::ot_Actor && ot != UMLObject::ot_UseCase))
2182 bAccept = false;
2183 break;
2184 case Uml::DiagramType::Class:
2185 if (scene->widgetOnDiagram(id) ||
2186 (ot != UMLObject::ot_Class &&
2187 ot != UMLObject::ot_Package &&
2188 ot != UMLObject::ot_Interface &&
2189 ot != UMLObject::ot_Enum &&
2190 ot != UMLObject::ot_Datatype &&
2191 ot != UMLObject::ot_Instance)) {
2192 bAccept = false;
2193 }
2194 break;
2195 case Uml::DiagramType::Object:
2196 if (scene->widgetOnDiagram(id) || ot != UMLObject::ot_Instance)
2197 bAccept = false;
2198 break;
2199 case Uml::DiagramType::Sequence:
2200 if (ot != UMLObject::ot_Class &&
2201 ot != UMLObject::ot_Interface &&
2202 ot != UMLObject::ot_Actor)
2203 bAccept = false;
2204 break;
2205 case Uml::DiagramType::Collaboration:
2206 if (ot != UMLObject::ot_Class &&
2207 ot != UMLObject::ot_Interface &&
2208 ot != UMLObject::ot_Instance &&
2209 ot != UMLObject::ot_Actor)
2210 bAccept = false;
2211 break;
2212 case Uml::DiagramType::Deployment:
2213 if (scene->widgetOnDiagram(id))
2214 bAccept = false;
2215 else if (ot != UMLObject::ot_Interface &&
2216 ot != UMLObject::ot_Package &&
2217 ot != UMLObject::ot_Component &&
2218 ot != UMLObject::ot_Class &&
2219 ot != UMLObject::ot_Node)
2220 bAccept = false;
2221 else if (ot == UMLObject::ot_Package &&
2222 o->stereotype() != QLatin1String("subsystem"))
2223 bAccept = false;
2224 break;
2225 case Uml::DiagramType::Component:
2226 if (scene->widgetOnDiagram(id) ||
2227 (ot != UMLObject::ot_Interface &&
2228 ot != UMLObject::ot_Package &&
2229 ot != UMLObject::ot_Component &&
2230 ot != UMLObject::ot_Port &&
2231 ot != UMLObject::ot_Artifact &&
2232 ot != UMLObject::ot_Class))
2233 bAccept = false;
2234 else if (ot == UMLObject::ot_Class && !o->isAbstract())
2235 bAccept = false;
2236 else if (ot == UMLObject::ot_Port) {
2237 const bool componentOnDiagram = scene->widgetOnDiagram(o->umlPackage()->id());
2238 bAccept = componentOnDiagram;
2239 }
2240 break;
2241 case Uml::DiagramType::EntityRelationship:
2242 if (scene->widgetOnDiagram(id) ||
2243 (ot != UMLObject::ot_Entity &&
2244 ot != UMLObject::ot_Category))
2245 bAccept = false;
2246 break;
2247 default:
2248 break;
2249 }
2250 return bAccept;
2251 }
2252
2253 /**
2254 * Return true if the widget type is allowed in the related diagram
2255 * @param w UML widget object
2256 * @param scene diagram instance
2257 * @return true type is allowed
2258 * @return false type is not allowed
2259 */
typeIsAllowedInDiagram(UMLWidget * w,UMLScene * scene)2260 bool typeIsAllowedInDiagram(UMLWidget* w, UMLScene *scene)
2261 {
2262 UMLWidget::WidgetType wt = w->baseType();
2263 Uml::DiagramType::Enum diagramType = scene->type();
2264 bool bAccept = true;
2265
2266 // TODO: check additional widgets
2267 switch (diagramType) {
2268 case Uml::DiagramType::Activity:
2269 case Uml::DiagramType::Class:
2270 case Uml::DiagramType::Object:
2271 case Uml::DiagramType::Collaboration:
2272 case Uml::DiagramType::Component:
2273 case Uml::DiagramType::Deployment:
2274 case Uml::DiagramType::EntityRelationship:
2275 case Uml::DiagramType::Sequence:
2276 case Uml::DiagramType::State:
2277 case Uml::DiagramType::UseCase:
2278 default:
2279 switch(wt) {
2280 case WidgetBase::wt_Note:
2281 break;
2282 case WidgetBase::wt_Text:
2283 {
2284 FloatingTextWidget *ft = w->asFloatingTextWidget();
2285 if (ft && ft->textRole() != Uml::TextRole::Floating) {
2286 bAccept = false;
2287 }
2288 }
2289 break;
2290 default:
2291 bAccept = false;
2292 break;
2293 }
2294 break;
2295 }
2296 return bAccept;
2297 }
2298
2299 /**
2300 * return true if given object type supports associations
2301 * @param type uml object type to check
2302 */
hasAssociations(UMLObject::ObjectType type)2303 bool hasAssociations(UMLObject::ObjectType type)
2304 {
2305 switch (type) {
2306 case UMLObject::ot_Actor:
2307 case UMLObject::ot_UseCase:
2308 case UMLObject::ot_Class:
2309 case UMLObject::ot_Package:
2310 case UMLObject::ot_Component:
2311 case UMLObject::ot_Node:
2312 case UMLObject::ot_Artifact:
2313 case UMLObject::ot_Interface:
2314 case UMLObject::ot_Enum:
2315 case UMLObject::ot_Entity:
2316 case UMLObject::ot_Datatype:
2317 case UMLObject::ot_Category:
2318 case UMLObject::ot_Instance:
2319 return true;
2320 default:
2321 return false;
2322 }
2323 }
2324 } // namespace Model_Utils
2325
2326