diff --git a/umbrello/assocrules.cpp b/umbrello/assocrules.cpp index ff62e8e05..b7a3b9c22 100644 --- a/umbrello/assocrules.cpp +++ b/umbrello/assocrules.cpp @@ -1,543 +1,549 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2002-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ // own header #include "assocrules.h" // local includes #include "debug_utils.h" #include "uml.h" #include "umlview.h" #include "umlwidget.h" #include "umlobject.h" #include "associationwidgetlist.h" #include "associationwidget.h" #include "statewidget.h" #include "activitywidget.h" #include "signalwidget.h" #include "forkjoinwidget.h" #include "umlscene.h" #include "umllistview.h" // kde includes #include #include /** * Constructor. */ AssocRules::AssocRules() { } /** * Destructor. */ AssocRules::~AssocRules() { } /** * Returns whether an association is going to be allowed for the given * values. This method is used to test if you can start an association. */ bool AssocRules::allowAssociation(Uml::AssociationType::Enum assocType, UMLWidget * widget) { WidgetBase::WidgetType widgetType = widget->baseType(); bool bValid = false; for (int i = 0; i < m_nNumRules; ++i) { const Assoc_Rule& rule = m_AssocRules[i]; if (!rule.isValid()) continue; if (assocType != rule.assoc_type) continue; if (widgetType == rule.widgetA_type || (widgetType == rule.widgetB_type && rule.bidirectional)) { bValid = true; break; } } if(!bValid) { // Special case: Subsystem realizes interface in component diagram UMLView *view = UMLApp::app()->currentView(); if (view && view->umlScene()->type() == Uml::DiagramType::Component && widgetType == WidgetBase::wt_Package && (assocType == Uml::AssociationType::Generalization || assocType == Uml::AssociationType::Realization)) ; else return false; } AssociationWidgetList list = widget->associationWidgetList(); switch(assocType) { case Uml::AssociationType::Association: case Uml::AssociationType::UniAssociation: case Uml::AssociationType::Dependency: case Uml::AssociationType::Coll_Message_Synchronous: case Uml::AssociationType::Coll_Message_Asynchronous: case Uml::AssociationType::Generalization://can have many sub/super types case Uml::AssociationType::Aggregation: case Uml::AssociationType::Relationship: case Uml::AssociationType::Composition: case Uml::AssociationType::Containment: return true;//doesn't matter whats already connected to widget break; case Uml::AssociationType::Association_Self: return true;// we should really check that connection is to same object break; case Uml::AssociationType::Realization: // one connected to widget only (a or b) foreach (AssociationWidget* assoc, list) { if(assoc->associationType() == Uml::AssociationType::Realization) return false; } return true; break; case Uml::AssociationType::State: { StateWidget *pState = widget->asStateWidget(); return (pState == 0 || pState->stateType() != StateWidget::End); } break; case Uml::AssociationType::Activity: case Uml::AssociationType::Exception: { ActivityWidget *pActivity = widget->asActivityWidget(); return (pActivity == 0 || pActivity->activityType() != ActivityWidget::End); } break; case Uml::AssociationType::Anchor: return true; break; case Uml::AssociationType::Category2Parent: if (widgetType == WidgetBase::wt_Category) return true; break; case Uml::AssociationType::Child2Category: if (widgetType == WidgetBase::wt_Entity) return true; break; default: uWarning() << "allowAssociation() on unknown type"; break; } return false; } /** * Returns whether an association is valid with the given variables. * This method is used to finish an association. * When we know what we are going to connect both ends of the association to, we can * use this method. */ bool AssocRules::allowAssociation(Uml::AssociationType::Enum assocType, UMLWidget * widgetA, UMLWidget * widgetB) { WidgetBase::WidgetType widgetTypeA = widgetA->baseType(); WidgetBase::WidgetType widgetTypeB = widgetB->baseType(); bool bValid = false; if (widgetA->umlObject() && widgetA->umlObject() == widgetB->umlObject()) { return allowSelf(assocType, widgetTypeA); } for (int i = 0; i < m_nNumRules; ++i) { const Assoc_Rule& rule = m_AssocRules[i]; if (!rule.isValid()) continue; if (assocType != rule.assoc_type) continue; if ((widgetTypeA == rule.widgetA_type && widgetTypeB == rule.widgetB_type) || (rule.bidirectional && widgetTypeB == rule.widgetA_type && widgetTypeA == rule.widgetB_type)) { bValid = true; break; } } if (!bValid) { return false; } //Prevent against a package containing its own parent! #packageception. if (assocType == Uml::AssociationType::Containment) { UMLListViewItem* listItemA = UMLApp::app()->listView()->findUMLObject(widgetA->umlObject()); UMLListViewItem* listItemB = UMLApp::app()->listView()->findUMLObject(widgetB->umlObject()); if (listItemA && listItemB) { // Great, we have our listviewitems, now check to make sure that they don't become recursive. if (listItemA->parent() == static_cast(listItemB)) { // The user is trying to make the parent the child and the child the parent. Stop them! return false; } } // This was just a little assertion for safety, don't return yet! } AssociationWidgetList list = widgetB->associationWidgetList(); switch(assocType) { case Uml::AssociationType::Association_Self: if (widgetA->umlObject() == widgetB->umlObject()) return true; break; case Uml::AssociationType::Association: case Uml::AssociationType::UniAssociation: case Uml::AssociationType::Dependency: case Uml::AssociationType::Coll_Message_Synchronous: case Uml::AssociationType::Coll_Message_Asynchronous: case Uml::AssociationType::Aggregation: case Uml::AssociationType::Relationship: return true; // doesn't matter what's already connected to widget break; case Uml::AssociationType::Composition: case Uml::AssociationType::Containment: return true; break; case Uml::AssociationType::Generalization://can have many sub/super types but can't sup/sub each foreach (AssociationWidget * assoc, list) { if((widgetA == assoc->widgetForRole(Uml::RoleType::A) || widgetA == assoc->widgetForRole(Uml::RoleType::B)) && assoc->associationType() == assocType) return false; } return true; break; case Uml::AssociationType::Realization: // can only connect to abstract (interface) classes foreach(AssociationWidget * assoc, list) { if((widgetA == assoc->widgetForRole(Uml::RoleType::A) || widgetA == assoc->widgetForRole(Uml::RoleType::B)) && assoc->associationType() == Uml::AssociationType::Realization) { return false; } } if (widgetB->isClassWidget()) { return widgetB->umlObject()->isAbstract(); } else if (widgetB->isInterfaceWidget() || widgetB->isPackageWidget()) { return true; } break; case Uml::AssociationType::State: { StateWidget *stateA = widgetA->asStateWidget(); StateWidget *stateB = widgetB->asStateWidget(); if (stateA && stateB) { if (stateB->stateType() == StateWidget::Initial) return false; if (stateB->stateType() == StateWidget::End && stateA->stateType() != StateWidget::Normal) return false; } } return true; break; case Uml::AssociationType::Activity: case Uml::AssociationType::Exception: { ActivityWidget *actA = widgetA->asActivityWidget(); ActivityWidget *actB = widgetB->asActivityWidget(); bool isSignal = false; bool isObjectNode = false; if (widgetTypeA == WidgetBase::wt_Signal) isSignal = true; else if (widgetTypeA == WidgetBase::wt_ObjectNode) isObjectNode = true; // no transitions to initial activity allowed if (actB && actB->activityType() == ActivityWidget::Initial) { return false; } // actType -1 here means "not applicable". int actTypeA = -1; if (actA) actTypeA = actA->activityType(); int actTypeB = -1; if (actB) actTypeB = actB->activityType(); // only from a signalwidget a objectnode widget, a normal activity, branch or fork activity, to the end if ((actTypeB == ActivityWidget::End || actTypeB == ActivityWidget::Final) && actTypeA != ActivityWidget::Normal && actTypeA != ActivityWidget::Branch && widgetA->asForkJoinWidget() == 0 && !isSignal &&!isObjectNode) { return false; } // only Forks and Branches can have more than one "outgoing" transition if (actA != 0 && actTypeA != ActivityWidget::Branch) { AssociationWidgetList list = widgetA->associationWidgetList(); foreach (AssociationWidget* assoc, list) { if (assoc->widgetForRole(Uml::RoleType::A) == widgetA) { return false; } } } } return true; break; case Uml::AssociationType::Anchor: return true; break; case Uml::AssociationType::Category2Parent: if (widgetTypeA == WidgetBase::wt_Category && widgetTypeB == WidgetBase::wt_Entity) { return true; } break; case Uml::AssociationType::Child2Category: if (widgetTypeA == WidgetBase::wt_Entity && widgetTypeB == WidgetBase::wt_Category) { return true; } break; default: uWarning() << "allowAssociation() on unknown type"; break; } return false; } /** * Returns whether to allow a role text for the given association type. */ bool AssocRules::allowRole(Uml::AssociationType::Enum assocType) { for(int i = 0; i < m_nNumRules; ++i) { const Assoc_Rule& rule = m_AssocRules[i]; if (!rule.isValid()) continue; if(assocType == rule.assoc_type) return rule.role; } return false; } /** * Returns whether to allow a multiplicity text for the given * association and widget type. */ bool AssocRules::allowMultiplicity(Uml::AssociationType::Enum assocType, WidgetBase::WidgetType widgetType) { for(int i = 0; i < m_nNumRules; ++i) { const Assoc_Rule& rule = m_AssocRules[i]; if (!rule.isValid()) continue; if(assocType == rule.assoc_type) if(widgetType == rule.widgetA_type || widgetType == rule.widgetB_type) return rule.multiplicity; } return false; } /** * Returns whether to allow an association to self for given variables. */ bool AssocRules::allowSelf(Uml::AssociationType::Enum assocType, WidgetBase::WidgetType widgetType) { for(int i = 0; i < m_nNumRules; ++i) { const Assoc_Rule& rule = m_AssocRules[i]; if (!rule.isValid()) continue; if(assocType == rule.assoc_type) if(widgetType == rule.widgetA_type || widgetType == rule.widgetB_type) return rule.self; } return false; } /** * Returns whether an implements association should be a Realisation or * a Generalisation. * as defined in m_AssocRules. */ Uml::AssociationType::Enum AssocRules::isGeneralisationOrRealisation(UMLWidget* widgetA, UMLWidget* widgetB) { WidgetBase::WidgetType widgetTypeA = widgetA->baseType(); WidgetBase::WidgetType widgetTypeB = widgetB->baseType(); for (int i = 0; i < m_nNumRules; ++i) { const Assoc_Rule &rule = m_AssocRules[i]; if (!rule.isValid()) continue; if (rule.assoc_type == Uml::AssociationType::Realization && widgetTypeA == rule.widgetA_type && widgetTypeB == rule.widgetB_type) { return Uml::AssociationType::Realization; } } return Uml::AssociationType::Generalization; } AssocRules::Assoc_Rule AssocRules::m_AssocRules[] = { - // Language Association widgetA widgetB role multi bidir. self - //----+---------------------------------------+--------------------------+---------------------------+-------+-------+-------+-------- - { All, Uml::AssociationType::Association_Self, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, true, true }, - { All, Uml::AssociationType::Association_Self, WidgetBase::wt_Object, WidgetBase::wt_Object, true, true, true, true }, - { All, Uml::AssociationType::Association_Self, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, true, true }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Object, WidgetBase::wt_Object, true, true, true, true }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Instance, WidgetBase::wt_Instance, true, true, true, true }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, true, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, true, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, true, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Actor, WidgetBase::wt_UseCase, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Actor, WidgetBase::wt_Actor, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Actor, WidgetBase::wt_UseCase, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Component, WidgetBase::wt_Interface, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Port, WidgetBase::wt_Interface, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Interface, WidgetBase::wt_Artifact, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false }, - { All, Uml::AssociationType::Association, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false }, - {Java, Uml::AssociationType::Association, WidgetBase::wt_Enum, WidgetBase::wt_Enum, true, false, false, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, true, true }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Object, WidgetBase::wt_Object, true, true, true, true }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, true, true }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, true, true }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, true, true }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Actor, WidgetBase::wt_Actor, true, false, false, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, true, false, false, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_UseCase, WidgetBase::wt_Actor, true, false, false, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Component, WidgetBase::wt_Interface, true, false, false, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Component, WidgetBase::wt_Artifact, true, false, true, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Port, WidgetBase::wt_Interface, true, false, false, false }, - { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_Class, WidgetBase::wt_Datatype, false, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_Class, WidgetBase::wt_Class, false, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_Interface, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_Interface, WidgetBase::wt_Class, false, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, false, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_Actor, WidgetBase::wt_Actor, false, false, false, false }, - { All, Uml::AssociationType::Generalization, WidgetBase::wt_Component, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, false, true }, - { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, false, false }, - { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, false, false }, - { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, false, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Class, true, false, false, true }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, true, false, false, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Actor, WidgetBase::wt_Actor, true, false, false, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Actor, WidgetBase::wt_UseCase, true, false, false, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Package, WidgetBase::wt_Package, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Package, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Interface, WidgetBase::wt_Package, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Interface, WidgetBase::wt_Enum, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Component, true, true, true, true }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Interface, true, true, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Artifact, true, false, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Package, true, false, false, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Port, WidgetBase::wt_Interface, true, false, false, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Package, WidgetBase::wt_Artifact, true, false, true, false }, - { All, Uml::AssociationType::Dependency, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false }, - { All, Uml::AssociationType::Realization, WidgetBase::wt_Class, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Realization, WidgetBase::wt_Interface, WidgetBase::wt_Package, false, false, false, false }, - { All, Uml::AssociationType::Realization, WidgetBase::wt_Interface, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Realization, WidgetBase::wt_Component, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Realization, WidgetBase::wt_Package, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, false, true }, - { All, Uml::AssociationType::Composition, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, false, false }, - { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, false, false }, - { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, false, false }, - { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Datatype, false, false, false, false }, - { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Class, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Class, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Enum, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Datatype, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Package, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Component, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Class, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Enum, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Datatype, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Class, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Interface, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Enum, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Datatype, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Component, WidgetBase::wt_Component, false, false, false, false }, - { All, Uml::AssociationType::Containment, WidgetBase::wt_Component, WidgetBase::wt_Artifact, false, false, false, false }, - { All, Uml::AssociationType::Coll_Message_Synchronous, WidgetBase::wt_Object, WidgetBase::wt_Object, true, false, true, true }, - { All, Uml::AssociationType::Coll_Message_Asynchronous, WidgetBase::wt_Object, WidgetBase::wt_Object, true, false, true, true }, - { All, Uml::AssociationType::State, WidgetBase::wt_State, WidgetBase::wt_State, true, false, true, true }, - { All, Uml::AssociationType::State, WidgetBase::wt_ForkJoin, WidgetBase::wt_State, true, false, true, true }, - { All, Uml::AssociationType::State, WidgetBase::wt_State, WidgetBase::wt_ForkJoin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Signal, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_Signal, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_ObjectNode, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_ObjectNode, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_ForkJoin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Signal, WidgetBase::wt_ForkJoin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_Signal, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_ObjectNode, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_ObjectNode, WidgetBase::wt_ForkJoin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Pin, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Pin, WidgetBase::wt_Pin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_Pin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_Pin, WidgetBase::wt_ForkJoin, true, false, true, true }, - { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_Pin, true, false, true, true }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Activity, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Actor, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Artifact, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Class, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Component, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Datatype, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Entity, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Enum, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Interface, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Message, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Object, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_Package, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_State, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Anchor, WidgetBase::wt_UseCase, WidgetBase::wt_Note, false, false, true, false }, - { All, Uml::AssociationType::Relationship, WidgetBase::wt_Entity, WidgetBase::wt_Entity, true, true, true, true }, - { All, Uml::AssociationType::Exception, WidgetBase::wt_Activity, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Exception, WidgetBase::wt_Activity, WidgetBase::wt_Signal, true, false, true, true }, - { All, Uml::AssociationType::Exception, WidgetBase::wt_Signal, WidgetBase::wt_Activity, true, false, true, true }, - { All, Uml::AssociationType::Exception, WidgetBase::wt_Signal, WidgetBase::wt_Signal, true, false, true, true }, - { All, Uml::AssociationType::Category2Parent, WidgetBase::wt_Category, WidgetBase::wt_Entity, false, false, true, false }, - { All, Uml::AssociationType::Child2Category, WidgetBase::wt_Entity, WidgetBase::wt_Category, false, false, true, false } + // Language Association widgetA widgetB role multi bidir. self level + //----+---------------------------------------+--------------------------+---------------------------+-------+-------+-------+-----+---- + { All, Uml::AssociationType::Association_Self, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, true, true, Any }, + { All, Uml::AssociationType::Association_Self, WidgetBase::wt_Object, WidgetBase::wt_Object, true, true, true, true, Any }, + { All, Uml::AssociationType::Association_Self, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, true, true, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Object, WidgetBase::wt_Object, true, true, true, true, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Instance, WidgetBase::wt_Instance, true, true, true, true, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, true, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, true, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, true, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Actor, WidgetBase::wt_UseCase, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Actor, WidgetBase::wt_Actor, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Actor, WidgetBase::wt_UseCase, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Component, WidgetBase::wt_Interface, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Port, WidgetBase::wt_Interface, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Interface, WidgetBase::wt_Artifact, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Interface, WidgetBase::wt_Component, true, false, false, false, UML2 }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Interface, WidgetBase::wt_Port, true, false, false, false, UML2 }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false, Any }, + { All, Uml::AssociationType::Association, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false, Any }, + {Java, Uml::AssociationType::Association, WidgetBase::wt_Enum, WidgetBase::wt_Enum, true, false, false, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, true, true, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Object, WidgetBase::wt_Object, true, true, true, true, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, true, true, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, true, true, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, true, true, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Actor, WidgetBase::wt_Actor, true, false, false, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, true, false, false, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_UseCase, WidgetBase::wt_Actor, true, false, false, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Component, WidgetBase::wt_Interface, true, false, false, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Component, WidgetBase::wt_Artifact, true, false, true, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Port, WidgetBase::wt_Interface, true, false, false, false, Any }, + { All, Uml::AssociationType::UniAssociation, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_Class, WidgetBase::wt_Datatype, false, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_Class, WidgetBase::wt_Class, false, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_Interface, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_Interface, WidgetBase::wt_Class, false, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, false, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_Actor, WidgetBase::wt_Actor, false, false, false, false, Any }, + { All, Uml::AssociationType::Generalization, WidgetBase::wt_Component, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, false, true, Any }, + { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, false, false, Any }, + { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, false, false, Any }, + { All, Uml::AssociationType::Aggregation, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, false, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Class, true, false, false, true, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_UseCase, WidgetBase::wt_UseCase, true, false, false, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Actor, WidgetBase::wt_Actor, true, false, false, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Actor, WidgetBase::wt_UseCase, true, false, false, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Package, WidgetBase::wt_Package, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Package, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Interface, WidgetBase::wt_Package, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, true, true, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Datatype, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Interface, WidgetBase::wt_Enum, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Component, true, true, true, true, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Interface, true, true, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Artifact, true, false, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Component, WidgetBase::wt_Package, true, false, false, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Port, WidgetBase::wt_Interface, true, false, false, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Package, WidgetBase::wt_Artifact, true, false, true, false, Any }, + { All, Uml::AssociationType::Dependency, WidgetBase::wt_Node, WidgetBase::wt_Node, true, false, false, false, Any }, + { All, Uml::AssociationType::Realization, WidgetBase::wt_Class, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Realization, WidgetBase::wt_Interface, WidgetBase::wt_Package, false, false, false, false, Any }, + { All, Uml::AssociationType::Realization, WidgetBase::wt_Interface, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Realization, WidgetBase::wt_Component, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Realization, WidgetBase::wt_Package, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Class, true, true, false, true, Any }, + { All, Uml::AssociationType::Composition, WidgetBase::wt_Interface, WidgetBase::wt_Interface, true, true, false, false, Any }, + { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Interface, true, true, false, false, Any }, + { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Enum, true, true, false, false, Any }, + { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Datatype, false, false, false, false, Any }, + { All, Uml::AssociationType::Composition, WidgetBase::wt_Class, WidgetBase::wt_Class, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Class, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Enum, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Datatype, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Package, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Package, WidgetBase::wt_Component, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Class, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Enum, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Class, WidgetBase::wt_Datatype, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Class, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Interface, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Enum, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Interface, WidgetBase::wt_Datatype, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Component, WidgetBase::wt_Component, false, false, false, false, Any }, + { All, Uml::AssociationType::Containment, WidgetBase::wt_Component, WidgetBase::wt_Artifact, false, false, false, false, Any }, + { All, Uml::AssociationType::Coll_Message_Synchronous, WidgetBase::wt_Object, WidgetBase::wt_Object, true, false, true, true, Any }, + { All, Uml::AssociationType::Coll_Message_Asynchronous, WidgetBase::wt_Object, WidgetBase::wt_Object, true, false, true, true, Any }, + { All, Uml::AssociationType::State, WidgetBase::wt_State, WidgetBase::wt_State, true, false, true, true, Any }, + { All, Uml::AssociationType::State, WidgetBase::wt_ForkJoin, WidgetBase::wt_State, true, false, true, true, Any }, + { All, Uml::AssociationType::State, WidgetBase::wt_State, WidgetBase::wt_ForkJoin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Signal, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_Signal, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_ObjectNode, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_ObjectNode, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_ForkJoin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Signal, WidgetBase::wt_ForkJoin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_Signal, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_ObjectNode, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_ObjectNode, WidgetBase::wt_ForkJoin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Pin, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Pin, WidgetBase::wt_Pin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Activity, WidgetBase::wt_Pin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_Pin, WidgetBase::wt_ForkJoin, true, false, true, true, Any }, + { All, Uml::AssociationType::Activity, WidgetBase::wt_ForkJoin, WidgetBase::wt_Pin, true, false, true, true, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Activity, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Actor, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Artifact, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Class, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Component, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Datatype, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Entity, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Enum, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Interface, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Message, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Object, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_Package, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_State, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Anchor, WidgetBase::wt_UseCase, WidgetBase::wt_Note, false, false, true, false, Any }, + { All, Uml::AssociationType::Relationship, WidgetBase::wt_Entity, WidgetBase::wt_Entity, true, true, true, true, Any }, + { All, Uml::AssociationType::Exception, WidgetBase::wt_Activity, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Exception, WidgetBase::wt_Activity, WidgetBase::wt_Signal, true, false, true, true, Any }, + { All, Uml::AssociationType::Exception, WidgetBase::wt_Signal, WidgetBase::wt_Activity, true, false, true, true, Any }, + { All, Uml::AssociationType::Exception, WidgetBase::wt_Signal, WidgetBase::wt_Signal, true, false, true, true, Any }, + { All, Uml::AssociationType::Category2Parent, WidgetBase::wt_Category, WidgetBase::wt_Entity, false, false, true, false, Any }, + { All, Uml::AssociationType::Child2Category, WidgetBase::wt_Entity, WidgetBase::wt_Category, false, false, true, false, Any } }; int AssocRules::m_nNumRules = sizeof(m_AssocRules) / sizeof(AssocRules::Assoc_Rule); bool AssocRules::Assoc_Rule::isValid() const { + bool isValidLevel = true; +// (level == Any) || +// (level == UML1 && !Settings::optionState().generalState.uml2) || +// (level == UML2 && Settings::optionState().generalState.uml2); if (language == All) - return true; + return isValidLevel; else if (language == Java && UMLApp::app()->activeLanguage() == Uml::ProgrammingLanguage::Java) - return true; + return isValidLevel; else return false; } diff --git a/umbrello/assocrules.h b/umbrello/assocrules.h index faef8df61..08236e9a1 100644 --- a/umbrello/assocrules.h +++ b/umbrello/assocrules.h @@ -1,64 +1,66 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2002-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ #ifndef ASSOCRULES_H #define ASSOCRULES_H #include "umlobject.h" #include "widgetbase.h" class UMLWidget; /** * Used to determine rules for associations. * * @author Paul Hensgen * Bugs and comments to umbrello-devel@kde.org or http://bugs.kde.org */ class AssocRules { public: AssocRules(); ~AssocRules(); static bool allowAssociation(Uml::AssociationType::Enum assocType, UMLWidget * widget); static bool allowAssociation(Uml::AssociationType::Enum assocType, UMLWidget * widgetA, UMLWidget * widgetB); static bool allowRole(Uml::AssociationType::Enum assocType); static bool allowMultiplicity(Uml::AssociationType::Enum assocType, WidgetBase::WidgetType widgetType); static bool allowSelf(Uml::AssociationType::Enum assocType, WidgetBase::WidgetType widgetType); static Uml::AssociationType::Enum isGeneralisationOrRealisation(UMLWidget* widgetA, UMLWidget* widgetB); typedef enum {All, Java} Language; + typedef enum {Any, UML1, UML2 } Level; private: class Assoc_Rule { ///< Structure to help determine association rules. public: bool isValid() const; Language language; ///< language rule applies to Uml::AssociationType::Enum assoc_type; ///< association type WidgetBase::WidgetType widgetA_type; ///< type of role A widget WidgetBase::WidgetType widgetB_type; ///< type of role B widget bool role; ///< role text bool multiplicity; ///< multipliciy text on association bool bidirectional; ///< can have an association of same type going between widget each way bool self; ///< association to self + Level level; ///< UML level }; static Assoc_Rule m_AssocRules[]; ///< Container that holds all the rules. static int m_nNumRules; ///< The number of rules known about. }; #endif diff --git a/umbrello/icons.qrc b/umbrello/icons.qrc index 086884f69..cb37128a6 100644 --- a/umbrello/icons.qrc +++ b/umbrello/icons.qrc @@ -1,180 +1,182 @@ pics/accept_signal.png pics/accept_time_event.png pics/activity-fork.png pics/actor.png pics/aggregation.png pics/align-horizontal-center.png pics/align-horizontal-left.png pics/align-horizontal-right.png pics/align-vertical-bottom.png pics/align-vertical-center.png pics/align-vertical-top.png pics/anchor.png pics/andline.png pics/arrow.png pics/artifact.png pics/association.png pics/box.png pics/branch.png pics/category2parent.png pics/category.png pics/check_constraint.png pics/child2category.png pics/choice-rhomb.png pics/choice-round.png pics/class-or-package.png pics/class.png pics/combined_fragment.png pics/component.png pics/composition.png pics/containment.png pics/cursor-accept_signal.png pics/cursor-accept_time_event.png pics/cursor-activity-fork.png pics/cursor-actor.png pics/cursor-aggregation.png pics/cursor-anchor.png pics/cursor-andline.png pics/cursor-artifact.png pics/cursor-association.png pics/cursor-box.png pics/cursor-branch.png pics/cursor-category2parent.png pics/cursor-category.png pics/cursor-child2category.png pics/cursor-choice-rhomb.png pics/cursor-choice-round.png pics/cursor-class.png pics/cursor-combined_fragment.png pics/cursor-component.png pics/cursor-composition.png pics/cursor-containment.png pics/cursor-datatype.png pics/cursor-deep-history.png pics/cursor-dependency.png pics/cursor-end_state.png pics/cursor-entity.png pics/cursor-enum.png pics/cursor-exception.png pics/cursor-final_activity.png pics/cursor-generalisation.png pics/cursor-initial_state.png pics/cursor-instance.png pics/cursor-interface.png pics/cursor-join.png pics/cursor-junction.png pics/cursor-node.png pics/cursor-note.png pics/cursor-object_node.png pics/cursor-object.png pics/cursor-package.png pics/cursor-pin.png pics/cursor-precondition.png pics/cursor-PrePostCondition.png pics/cursor-region.png pics/cursor-relationship.png pics/cursor-send_signal.png pics/cursor-shallow-history.png pics/cursor-state-fork.png pics/cursor-text.png pics/cursor-umbr-coll-message-asynchronous.png pics/cursor-umbr-coll-message-synchronous.png pics/cursor-umbr-message-asynchronous.png pics/cursor-umbr-message-found.png pics/cursor-umbr-message-lost.png pics/cursor-umbr-message-synchronous.png pics/cursor-uniassociation.png pics/cursor-usecase.png pics/CVglobal_meth.png pics/CVglobal_var.png pics/CVimplementation_meth.png pics/CVimplementation_signal.png pics/CVimplementation_slot.png pics/CVimplementation_var.png pics/CVprivate_meth.png pics/CVprivate_signal.png pics/CVprivate_slot.png pics/CVprivate_var.png pics/CVprotected_meth.png pics/CVprotected_signal.png pics/CVprotected_slot.png pics/CVprotected_var.png pics/CVpublic_meth.png pics/CVpublic_signal.png pics/CVpublic_slot.png pics/CVpublic_var.png pics/CVstruct.png pics/datatype.png pics/deep-history.png pics/dependency.png pics/distribute-horizontal.png pics/distribute-vertical.png pics/end_state.png pics/entity.png pics/enum.png pics/exception.png pics/final_activity.png pics/foreignkey_constraint.png pics/generalisation.png pics/global/128-apps-umbrello.png pics/global/16-apps-umbrello.png pics/global/16-mimetypes-application-x-uml.png pics/global/22-apps-umbrello.png pics/global/32-apps-umbrello.png pics/global/32-mimetypes-application-x-uml.png pics/global/48-apps-umbrello.png pics/global/64-apps-umbrello.png pics/hi22-actions-umbrello_diagram_activity.png pics/hi22-actions-umbrello_diagram_class.png pics/hi22-actions-umbrello_diagram_collaboration.png pics/hi22-actions-umbrello_diagram_component.png pics/hi22-actions-umbrello_diagram_deployment.png pics/diag_object.png pics/hi22-actions-umbrello_diagram_sequence.png pics/hi22-actions-umbrello_diagram_state.png pics/hi22-actions-umbrello_diagram_usecase.png pics/initial_state.png pics/instance.png pics/interface.png pics/join.png pics/junction.png pics/node.png pics/note.png pics/object_node.png pics/object.png pics/package.png pics/pin.png pics/port.png pics/precondition.png pics/PrePostCondition.png pics/primarykey_constraint.png pics/realization.png pics/refactor.png pics/region.png pics/relationship.png pics/send_signal.png pics/shallow-history.png pics/startlogo.png pics/state-fork.png pics/subsystem.png pics/template.png pics/text.png pics/umbr-coll-message-asynchronous.png pics/umbr-coll-message-synchronous.png pics/umbr-message-asynchronous.png pics/umbr-message-found.png pics/umbr-message-lost.png pics/umbr-message-synchronous.png pics/uniassociation.png pics/unique_constraint.png pics/usecase.png pics/state.png pics/cursor-state.png pics/component1.png pics/cursor-component1.png pics/interface-provider.png + pics/interface-requirement.png pics/cursor-interface-provider.png + pics/cursor-interface-requirement.png diff --git a/umbrello/umlwidgets/classifierwidget.cpp b/umbrello/umlwidgets/classifierwidget.cpp index 3ca61de09..639bb8001 100644 --- a/umbrello/umlwidgets/classifierwidget.cpp +++ b/umbrello/umlwidgets/classifierwidget.cpp @@ -1,1521 +1,1532 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2004-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ // own header #include "classifierwidget.h" // app includes #include "floatingtextwidget.h" #include "associationwidget.h" #include "associationline.h" #include "classifier.h" #include "cmds.h" #include "debug_utils.h" #include "instance.h" #include "listpopupmenu.h" #include "object_factory.h" #include "operation.h" #include "template.h" #include "uml.h" #include "umldoc.h" #include "umlview.h" // qt includes #include DEBUG_REGISTER_DISABLED(ClassifierWidget) const int ClassifierWidget::CIRCLE_SIZE = 30; const int ClassifierWidget::SOCKET_INCREMENT = 10; /** * Constructs a ClassifierWidget. * * @param scene The parent of this ClassifierWidget. * @param c The UMLClassifier to represent. */ ClassifierWidget::ClassifierWidget(UMLScene * scene, UMLClassifier *c) : UMLWidget(scene, WidgetBase::wt_Class, c), m_pAssocWidget(0), m_pInterfaceName(0) { const Settings::OptionState& ops = m_scene->optionState(); setVisualPropertyCmd(ShowVisibility, ops.classState.showVisibility); setVisualPropertyCmd(ShowOperations, ops.classState.showOps); setVisualPropertyCmd(ShowPublicOnly, ops.classState.showPublicOnly); setVisualPropertyCmd(ShowPackage, ops.classState.showPackage); m_attributeSignature = Uml::SignatureType::ShowSig; /*:TODO: setVisualProperty(ShowOperationSignature, ops.classState.showOpSig); Cannot do that because we get "pure virtual method called". Open code: */ if(!ops.classState.showOpSig) { if (visualProperty(ShowVisibility)) m_operationSignature = Uml::SignatureType::NoSig; else m_operationSignature = Uml::SignatureType::NoSigNoVis; } else if (visualProperty(ShowVisibility)) m_operationSignature = Uml::SignatureType::ShowSig; else m_operationSignature = Uml::SignatureType::SigNoVis; setVisualPropertyCmd(ShowAttributes, ops.classState.showAtts); setVisualPropertyCmd(ShowStereotype, ops.classState.showStereoType); setVisualPropertyCmd(DrawAsCircle, false); setShowAttSigs(ops.classState.showAttSig); if (c && c->isInterface()) { setBaseType(WidgetBase::wt_Interface); m_visualProperties = ShowOperations | ShowVisibility | ShowStereotype; setShowStereotype(true); updateSignatureTypes(); } if (c && scene->type() == Uml::DiagramType::Object) { setBaseType(WidgetBase::wt_Instance); m_visualProperties = ShowAttributes; updateSignatureTypes(); } } /** * Constructs a ClassifierWidget. * * @param scene The parent of this ClassifierWidget. * @param o The UMLPackage to represent. */ ClassifierWidget::ClassifierWidget(UMLScene * scene, UMLPackage *o) : UMLWidget(scene, WidgetBase::wt_Package, o), m_pAssocWidget(0), m_pInterfaceName(0) { const Settings::OptionState& ops = m_scene->optionState(); setVisualPropertyCmd(ShowVisibility, ops.classState.showVisibility); setVisualPropertyCmd(ShowOperations, ops.classState.showOps); setVisualPropertyCmd(ShowPublicOnly, ops.classState.showPublicOnly); setVisualPropertyCmd(ShowPackage, ops.classState.showPackage); m_attributeSignature = Uml::SignatureType::ShowSig; if(!ops.classState.showOpSig) { if (visualProperty(ShowVisibility)) m_operationSignature = Uml::SignatureType::NoSig; else m_operationSignature = Uml::SignatureType::NoSigNoVis; } else if (visualProperty(ShowVisibility)) m_operationSignature = Uml::SignatureType::ShowSig; else m_operationSignature = Uml::SignatureType::SigNoVis; setVisualPropertyCmd(ShowAttributes, ops.classState.showAtts); setVisualPropertyCmd(ShowStereotype, ops.classState.showStereoType); setVisualPropertyCmd(DrawAsPackage, true); setShowAttSigs(ops.classState.showAttSig); } /** * Destructor. */ ClassifierWidget::~ClassifierWidget() { if (m_pAssocWidget) m_pAssocWidget->removeAssocClassLine(); if (m_pInterfaceName) { delete m_pInterfaceName; m_pInterfaceName = 0; } } /** * Return the UMLClassifier which this ClassifierWidget * represents. */ UMLClassifier *ClassifierWidget::classifier() const { return m_umlObject->asUMLClassifier(); } /** * @return the visual properties */ ClassifierWidget::VisualProperties ClassifierWidget::visualProperties() const { return m_visualProperties; } /** * Set an OR combination of properties stored in \a properties on this * widget. */ void ClassifierWidget::setVisualProperties(VisualProperties properties) { // Don't do anything if the argument is equal to current status. if (quint32(m_visualProperties) == quint32(properties)) { return; } m_visualProperties = properties; updateSignatureTypes(); } /** * @return The status of the property passed in. * * @note Use @ref attributeSignature() and @ref * operationSignature() to get signature status. This * method only indicates whether signature is visible or not. */ bool ClassifierWidget::visualProperty(VisualProperty property) const { if (property == ShowAttributeSignature) { return (m_attributeSignature == Uml::SignatureType::ShowSig || m_attributeSignature == Uml::SignatureType::SigNoVis); } else if(property == ShowOperationSignature) { return (m_operationSignature == Uml::SignatureType::ShowSig || m_operationSignature == Uml::SignatureType::SigNoVis); } return m_visualProperties.testFlag(property); } /** * A convenient method to set and reset individual VisualProperty * * Undo command. * * @param property The property to be set/reset. * @param enable True/false to set/reset. (default = true) * * @note This method handles ShowAttributeSignature and * ShowOperationSignature specially. */ void ClassifierWidget::setVisualProperty(VisualProperty property, bool enable) { if (visualProperty(property) != enable) { UMLApp::app()->executeCommand(new Uml::CmdChangeVisualProperty(this, property, enable)); } } /** * A convenient method to set and reset individual VisualProperty * * @param property The property to be set/reset. * @param enable True/false to set/reset. (default = true) * * @note This method handles ShowAttributeSignature and * ShowOperationSignature specially. */ void ClassifierWidget::setVisualPropertyCmd(VisualProperty property, bool enable) { // Handle ShowAttributeSignature and ShowOperationSignature // specially. if (property == ShowAttributeSignature) { if (!enable) { m_attributeSignature = visualProperty(ShowVisibility) ? Uml::SignatureType::NoSig : Uml::SignatureType::NoSigNoVis; } else { m_attributeSignature = visualProperty(ShowVisibility) ? Uml::SignatureType::ShowSig : Uml::SignatureType::SigNoVis; } //:TODO: updateTextItemGroups(); updateSignatureTypes(); } else if (property == ShowOperationSignature) { if (!enable) { m_operationSignature = visualProperty(ShowVisibility) ? Uml::SignatureType::NoSig : Uml::SignatureType::NoSigNoVis; } else { m_operationSignature = visualProperty(ShowVisibility) ? Uml::SignatureType::ShowSig : Uml::SignatureType::SigNoVis; } //:TODO: updateTextItemGroups(); updateSignatureTypes(); } else if (property == ShowStereotype) { // Now just update flag and use base method for actual work. if (enable) { m_visualProperties |= property; } else { m_visualProperties &= ~property; } setShowStereotype(enable); } else if (property == DrawAsCircle) { // Don't do anything if the flag status is same. if (visualProperty(property) == enable) return; if (enable) { m_visualProperties |= property; } else { m_visualProperties &= ~property; } setDrawAsCircle(enable); } // Some other flag. else { // Don't do anything if the flag status is same. if (visualProperty(property) == enable) { return; } // Call setVisualProperties appropriately based on enbable. if (enable) { setVisualProperties(visualProperties() | property); } else { setVisualProperties(visualProperties() & ~property); } } } /** * A convenient method to toggle individual VisualProperty of this * widget. * * @param property The property to be toggled. * * @note This method handles ShowAttributeSignature and * ShowOperationSignature specially. */ void ClassifierWidget::toggleVisualProperty(VisualProperty property) { bool oppositeStatus; if (property == ShowOperationSignature) { oppositeStatus = !(m_operationSignature == Uml::SignatureType::ShowSig || m_operationSignature == Uml::SignatureType::SigNoVis); } else if (property == ShowAttributeSignature) { oppositeStatus = !(m_attributeSignature == Uml::SignatureType::ShowSig || m_attributeSignature == Uml::SignatureType::SigNoVis); } else { oppositeStatus = !visualProperty(property); } DEBUG(DBG_SRC) << "VisualProperty: " << property << " to opposite status " << oppositeStatus; setVisualProperty(property, oppositeStatus); } /** * Updates m_operationSignature to match m_showVisibility. */ void ClassifierWidget::updateSignatureTypes() { //turn on scope if (visualProperty(ShowVisibility)) { if (m_operationSignature == Uml::SignatureType::NoSigNoVis) { m_operationSignature = Uml::SignatureType::NoSig; } else if (m_operationSignature == Uml::SignatureType::SigNoVis) { m_operationSignature = Uml::SignatureType::ShowSig; } } //turn off scope else { if (m_operationSignature == Uml::SignatureType::ShowSig) { m_operationSignature = Uml::SignatureType::SigNoVis; } else if (m_operationSignature == Uml::SignatureType::NoSig) { m_operationSignature = Uml::SignatureType::NoSigNoVis; } } if (visualProperty(ShowVisibility)) { if (m_attributeSignature == Uml::SignatureType::NoSigNoVis) m_attributeSignature = Uml::SignatureType::NoSig; else if (m_attributeSignature == Uml::SignatureType::SigNoVis) m_attributeSignature = Uml::SignatureType::ShowSig; } else { if (m_attributeSignature == Uml::SignatureType::ShowSig) m_attributeSignature = Uml::SignatureType::SigNoVis; else if(m_attributeSignature == Uml::SignatureType::NoSig) m_attributeSignature = Uml::SignatureType::NoSigNoVis; } updateGeometry(); update(); } /** * Returns whether to show attribute signatures. * Only applies when m_umlObject->getBaseType() is ot_Class. * * @return Status of how attribute signatures are shown. */ Uml::SignatureType::Enum ClassifierWidget::attributeSignature() const { return m_attributeSignature; } /** * Sets the type of signature to display for an attribute. * Only applies when m_umlObject->getBaseType() is ot_Class. * * @param sig Type of signature to display for an attribute. */ void ClassifierWidget::setAttributeSignature(Uml::SignatureType::Enum sig) { m_attributeSignature = sig; updateSignatureTypes(); updateGeometry(); update(); } /** * @return The Uml::SignatureType::Enum value for the operations. */ Uml::SignatureType::Enum ClassifierWidget::operationSignature() const { return m_operationSignature; } /** * Set the type of signature to display for an Operation * * @param sig Type of signature to display for an operation. */ void ClassifierWidget::setOperationSignature(Uml::SignatureType::Enum sig) { m_operationSignature = sig; updateSignatureTypes(); updateGeometry(); update(); } /** * Sets whether to show attribute signature * Only applies when m_umlObject->getBaseType() is ot_Class. * * @param _status True if attribute signatures shall be shown. */ void ClassifierWidget::setShowAttSigs(bool _status) { if(!_status) { if (visualProperty(ShowVisibility)) m_attributeSignature = Uml::SignatureType::NoSig; else m_attributeSignature = Uml::SignatureType::NoSigNoVis; } else if (visualProperty(ShowVisibility)) m_attributeSignature = Uml::SignatureType::ShowSig; else m_attributeSignature = Uml::SignatureType::SigNoVis; if (UMLApp::app()->document()->loading()) return; updateGeometry(); update(); } /** * Toggles whether to show attribute signatures. * Only applies when m_umlObject->getBaseType() is ot_Class. */ void ClassifierWidget::toggleShowAttSigs() { if (m_attributeSignature == Uml::SignatureType::ShowSig || m_attributeSignature == Uml::SignatureType::SigNoVis) { if (visualProperty(ShowVisibility)) { m_attributeSignature = Uml::SignatureType::NoSig; } else { m_attributeSignature = Uml::SignatureType::NoSigNoVis; } } else if (visualProperty(ShowVisibility)) { m_attributeSignature = Uml::SignatureType::ShowSig; } else { m_attributeSignature = Uml::SignatureType::SigNoVis; } updateGeometry(); update(); } /** * Return the number of displayed members of the given ObjectType. * Takes into consideration m_showPublicOnly but not other settings. */ int ClassifierWidget::displayedMembers(UMLObject::ObjectType ot) const { int count = 0; UMLClassifier *umlc = this->classifier(); if (!umlc) return count; UMLClassifierListItemList list = umlc->getFilteredList(ot); foreach (UMLClassifierListItem *m, list) { if (!(visualProperty(ShowPublicOnly) && m->visibility() != Uml::Visibility::Public)) count++; } return count; } /** * Overrides method from UMLWidget. */ QSizeF ClassifierWidget::minimumSize() const { return calculateSize(); } /** * Calculate content related size of widget. * Overrides method from UMLWidget. */ QSizeF ClassifierWidget::calculateSize(bool withExtensions /* = true */) const { if (!m_umlObject) { return UMLWidget::minimumSize(); } if (m_umlObject->baseType() == UMLObject::ot_Package) { return calculateAsPackageSize(); } UMLClassifier *umlc = this->classifier(); if (!umlc) { uError() << "Internal error - classifier() returns NULL"; return UMLWidget::minimumSize(); } if (umlc->isInterface() && visualProperty(DrawAsCircle)) { return calculateAsCircleSize(); } const bool showNameOnly = !visualProperty(ShowAttributes) && !visualProperty(ShowOperations) && !visualProperty(ShowDocumentation); const QFontMetrics &fm = getFontMetrics(UMLWidget::FT_NORMAL); const int fontHeight = fm.lineSpacing(); // width is the width of the longest 'word' int width = 0, height = 0; // consider stereotype if (visualProperty(ShowStereotype) && !m_umlObject->stereotype().isEmpty()) { height += fontHeight; // ... width const QFontMetrics &bfm = UMLWidget::getFontMetrics(UMLWidget::FT_BOLD); const int stereoWidth = bfm.size(0, m_umlObject->stereotype(true)).width(); if (stereoWidth > width) width = stereoWidth; } else if (showNameOnly) { height += defaultMargin; } // consider name height += fontHeight; // ... width QString name; UMLObject *o; if (m_umlObject && m_umlObject->isUMLInstance() && m_umlObject->asUMLInstance()->classifier()) o = m_umlObject->asUMLInstance()->classifier(); else o = m_umlObject; if (!o) name = m_Text; else if (visualProperty(ShowPackage)) name = o->fullyQualifiedName(); else name = o->name(); QString displayedName; if (m_umlObject->isUMLInstance()) displayedName = m_umlObject->name() + QLatin1String(" : ") + name; else displayedName = name; const UMLWidget::FontType nft = (m_umlObject->isAbstract() ? FT_BOLD_ITALIC : FT_BOLD); const int nameWidth = UMLWidget::getFontMetrics(nft).size(0, displayedName).width(); if (nameWidth > width) width = nameWidth; #ifdef ENABLE_WIDGET_SHOW_DOC // consider documentation if (visualProperty(ShowDocumentation)) { if (!documentation().isEmpty()) { QRect brect = fm.boundingRect(QRect(0, 0, this->width()-2*defaultMargin, this->height()-height), Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, documentation()); height += brect.height(); if (!visualProperty(ShowOperations) && !visualProperty(ShowAttributes)) { if (brect.width() >= width) width = brect.width(); } } else height += fontHeight / 2; } #endif // consider attributes if (visualProperty(ShowAttributes)) { const int numAtts = displayedAttributes(); if (numAtts > 0) { height += fontHeight * numAtts; // calculate width of the attributes UMLClassifierListItemList list = umlc->getFilteredList( m_umlObject->isUMLInstance() ? UMLObject::ot_InstanceAttribute : UMLObject::ot_Attribute); foreach (UMLClassifierListItem *a, list) { if (visualProperty(ShowPublicOnly) && a->visibility() != Uml::Visibility::Public) continue; const int attWidth = fm.size(0, a->toString(m_attributeSignature, visualProperty(ShowStereotype))).width(); if (attWidth > width) width = attWidth; } } else height += fontHeight / 2; } // consider operations if (visualProperty(ShowOperations)) { const int numOps = displayedOperations(); if (numOps > 0) { height += numOps * fontHeight; // ... width UMLOperationList list(umlc->getOpList()); foreach (UMLOperation* op, list) { if (visualProperty(ShowPublicOnly) && op->visibility() != Uml::Visibility::Public) continue; const QString displayedOp = op->toString(m_operationSignature, visualProperty(ShowStereotype)); UMLWidget::FontType oft; oft = (op->isAbstract() ? UMLWidget::FT_ITALIC : UMLWidget::FT_NORMAL); const int w = UMLWidget::getFontMetrics(oft).size(0, displayedOp).width(); if (w > width) width = w; } } else height += fontHeight / 2; } if (withExtensions) { // consider template box _as last_ ! QSize templatesBoxSize = calculateTemplatesBoxSize(); if (templatesBoxSize.width() != 0) { // add width to largest 'word' width += templatesBoxSize.width() / 2; } if (templatesBoxSize.height() != 0) { height += templatesBoxSize.height() - defaultMargin; } } // allow for height margin if (showNameOnly) { height += defaultMargin; } // allow for width margin width += defaultMargin * 2; return QSizeF(width, height); } /** * Calculcates the size of the templates box in the top left * if it exists, returns QSize(0, 0) if it doesn't. * * @return QSize of the templates flap. */ QSize ClassifierWidget::calculateTemplatesBoxSize() const { if (!classifier()) return QSize(0, 0); UMLTemplateList list = classifier()->getTemplateList(); int count = list.count(); if (count == 0) { return QSize(0, 0); } QFont font = UMLWidget::font(); font.setItalic(false); font.setUnderline(false); font.setBold(false); const QFontMetrics fm(font); int width = 0; int height = count * fm.lineSpacing() + (defaultMargin*2); foreach (UMLTemplate *t, list) { int textWidth = fm.size(0, t->toString(Uml::SignatureType::NoSig, visualProperty(ShowStereotype))).width(); if (textWidth > width) width = textWidth; } width += (defaultMargin*2); return QSize(width, height); } /** * Return the number of displayed attributes. */ int ClassifierWidget::displayedAttributes() const { if (!visualProperty(ShowAttributes)) return 0; if(baseType() == WidgetBase::wt_Instance) return displayedMembers(UMLObject::ot_InstanceAttribute); else return displayedMembers(UMLObject::ot_Attribute); } /** * Return the number of displayed operations. */ int ClassifierWidget::displayedOperations() const { if (!visualProperty(ShowOperations)) return 0; return displayedMembers(UMLObject::ot_Operation); } /** * Set the AssociationWidget when this ClassWidget acts as * an association class. */ void ClassifierWidget::setClassAssociationWidget(AssociationWidget *assocwidget) { if (!classifier()) { uError() << "Class association cannot be applied to package"; return; } m_pAssocWidget = assocwidget; UMLAssociation *umlassoc = 0; if (assocwidget) umlassoc = assocwidget->association(); classifier()->setClassAssoc(umlassoc); } /** * Return the AssociationWidget when this classifier acts as * an association class (else return NULL.) */ AssociationWidget *ClassifierWidget::classAssociationWidget() const { return m_pAssocWidget; } /** * Overrides standard method. * Auxiliary to reimplementations in the derived classes. * @note keep fetching attributes in sync with calculateSize() */ void ClassifierWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); setPenFromSettings(painter); if (UMLWidget::useFillColor()) painter->setBrush(UMLWidget::fillColor()); else { painter->setBrush(m_scene->backgroundColor()); } if (m_umlObject->baseType() == UMLObject::ot_Package) { drawAsPackage(painter, option); UMLWidget::paint(painter, option, widget); return; } UMLClassifier *umlc = this->classifier(); if (!umlc) { uError() << "Internal error - classifier() returns NULL"; return; } if (umlc->isInterface() && visualProperty(DrawAsCircle)) { drawAsCircle(painter, option); UMLWidget::paint(painter, option, widget); return; } // Draw the bounding rectangle QSize templatesBoxSize = calculateTemplatesBoxSize(); int bodyOffsetY = 0; if (templatesBoxSize.height() > 0) bodyOffsetY += templatesBoxSize.height() - defaultMargin; int w = width(); if (templatesBoxSize.width() > 0) w -= templatesBoxSize.width() / 2; int h = height(); if (templatesBoxSize.height() > 0) h -= templatesBoxSize.height() - defaultMargin; painter->drawRect(0, bodyOffsetY, w, h); QFont font = UMLWidget::font(); font.setUnderline(false); font.setItalic(false); const QFontMetrics &fm = UMLWidget::getFontMetrics(UMLWidget::FT_NORMAL); const int fontHeight = fm.lineSpacing(); //If there are any templates then draw them UMLTemplateList tlist = umlc->getTemplateList(); if (tlist.count() > 0) { setPenFromSettings(painter); QPen pen = painter->pen(); pen.setStyle(Qt::DotLine); painter->setPen(pen); painter->drawRect(width() - templatesBoxSize.width(), 0, templatesBoxSize.width(), templatesBoxSize.height()); painter->setPen(QPen(textColor())); font.setBold(false); painter->setFont(font); const int x = width() - templatesBoxSize.width() + defaultMargin; int y = defaultMargin; foreach (UMLTemplate *t, tlist) { QString text = t->toString(Uml::SignatureType::NoSig, visualProperty(ShowStereotype)); painter->drawText(x, y, fm.size(0, text).width(), fontHeight, Qt::AlignVCenter, text); y += fontHeight; } } const int textX = defaultMargin; const int textWidth = w - defaultMargin * 2; painter->setPen(QPen(textColor())); // draw stereotype font.setBold(true); const bool showNameOnly = !visualProperty(ShowAttributes) && !visualProperty(ShowOperations) && !visualProperty(ShowDocumentation); int nameHeight = fontHeight; if (visualProperty(ShowStereotype) && !m_umlObject->stereotype().isEmpty()) { painter->setFont(font); painter->drawText(textX, bodyOffsetY, textWidth, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true)); bodyOffsetY += fontHeight; } else if (showNameOnly) { nameHeight = h; } // draw name QString name; UMLObject *o; if (m_umlObject && m_umlObject->isUMLInstance() && m_umlObject->asUMLInstance()->classifier()) o = m_umlObject->asUMLInstance()->classifier(); else o = m_umlObject; if (!o) name = m_Text; else if (visualProperty(ShowPackage)) name = o->fullyQualifiedName(); else name = o->name(); QString displayedName; if (m_umlObject->isUMLInstance()) displayedName = m_umlObject->name() + QLatin1String(" : ") + name; else displayedName = name; font.setItalic(m_umlObject->isAbstract()); painter->setFont(font); painter->drawText(textX, bodyOffsetY, textWidth, nameHeight, Qt::AlignCenter, displayedName); bodyOffsetY += fontHeight; font.setBold(false); font.setItalic(false); painter->setFont(font); #ifdef ENABLE_WIDGET_SHOW_DOC // draw documentation if (visualProperty(ShowDocumentation)) { setPenFromSettings(painter); painter->drawLine(0, bodyOffsetY, w, bodyOffsetY); painter->setPen(textColor()); if (!documentation().isEmpty()) { QRect brect = fm.boundingRect(QRect(0, 0, w-2*defaultMargin, h-bodyOffsetY), Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, documentation()); if (brect.width() > width() + 2*defaultMargin) brect.setWidth(width()-2*defaultMargin); brect.adjust(textX, bodyOffsetY, textX, bodyOffsetY); painter->drawText(brect, Qt::AlignCenter | Qt::TextWordWrap, documentation()); bodyOffsetY += brect.height(); } else bodyOffsetY += fontHeight / 2; } #endif // draw attributes if (visualProperty(ShowAttributes)) { // draw dividing line between doc/name and attributes setPenFromSettings(painter); painter->drawLine(0, bodyOffsetY, w, bodyOffsetY); painter->setPen(textColor()); const int numAtts = displayedAttributes(); if (numAtts > 0) { if (baseType() == WidgetBase::wt_Instance) { drawMembers(painter, UMLObject::ot_InstanceAttribute, m_attributeSignature, textX, bodyOffsetY, fontHeight); } else { drawMembers(painter, UMLObject::ot_Attribute, m_attributeSignature, textX, bodyOffsetY, fontHeight); } bodyOffsetY += fontHeight * numAtts; } else bodyOffsetY += fontHeight / 2; } // draw operations if (visualProperty(ShowOperations)) { // draw dividing line between attributes and operations setPenFromSettings(painter); painter->drawLine(0, bodyOffsetY, w, bodyOffsetY); painter->setPen(QPen(textColor())); const int numOps = displayedOperations(); if (numOps >= 0) { drawMembers(painter, UMLObject::ot_Operation, m_operationSignature, textX, bodyOffsetY, fontHeight); } } UMLWidget::paint(painter, option, widget); } /** * @return The shape of the ClassifierWidget. */ QPainterPath ClassifierWidget::shape() const { QPainterPath path; if (classifier() && classifier()->isInterface() && visualProperty(DrawAsCircle)) { path.addEllipse(QRectF(QPointF(), calculateAsCircleSize())); return path; } QSizeF mainSize = rect().size(); QSize templatesBoxSize = calculateTemplatesBoxSize(); qreal mainY = 0.0; if (templatesBoxSize.height() > 0) { mainY += templatesBoxSize.height() - defaultMargin; path.addRect(QRectF(mainSize.width() - templatesBoxSize.width() / 2, 0.0, templatesBoxSize.width(), templatesBoxSize.height())); } path.addRect(QRectF(0.0, mainY, mainSize.width(), mainSize.height())); return path; } /** * Draws the interface as a circle. * Only applies when m_umlObject->getBaseType() is ot_Interface. */ void ClassifierWidget::drawAsCircle(QPainter *painter, const QStyleOptionGraphicsItem *option) { Q_UNUSED(option); const int w = width(); + bool showProvider = associationWidgetList().size() == 0; + bool showRequired = false; + AssociationWidgetList requiredAssocs; + + foreach (AssociationWidget *aw, associationWidgetList()) { + const Uml::AssociationType::Enum aType = aw->associationType(); + UMLWidget *otherEnd = aw->widgetForRole(Uml::RoleType::A); + UMLWidget *thisEnd = aw->widgetForRole(Uml::RoleType::B); + if (aType == Uml::AssociationType::UniAssociation || + aType == Uml::AssociationType::Association) { + if (otherEnd->baseType() == WidgetBase::wt_Component || + otherEnd->baseType() == WidgetBase::wt_Port) // provider + showProvider = true; + else if (thisEnd->baseType() == WidgetBase::wt_Component || + thisEnd->baseType() == WidgetBase::wt_Port) { + showRequired = true; + requiredAssocs.push_back(aw); + } + } + } - if (associationWidgetList().size() > 1) { + if (showProvider || !showRequired) painter->drawEllipse(w/2 - CIRCLE_SIZE/2, SOCKET_INCREMENT / 2, CIRCLE_SIZE, CIRCLE_SIZE); + + if (showRequired) { // Draw socket for required interface. const qreal angleSpan = 180; // 360.0 / (m_Assocs.size() + 1.0); const int arcDiameter = CIRCLE_SIZE + SOCKET_INCREMENT; QRect requireArc(w/2 - arcDiameter/2, 0, arcDiameter, arcDiameter); const QPointF center(x() + w/2, y() + arcDiameter/2); const qreal cX = center.x(); const qreal cY = center.y(); - foreach (AssociationWidget *aw, associationWidgetList()) { - const Uml::AssociationType::Enum aType = aw->associationType(); - if (aType == Uml::AssociationType::UniAssociation || - aType == Uml::AssociationType::Association) // provider - continue; - UMLWidget *otherEnd = aw->widgetForRole(Uml::RoleType::A); - const WidgetBase::WidgetType oType = otherEnd->baseType(); - if (oType != WidgetBase::wt_Component && oType != WidgetBase::wt_Port) - continue; + foreach (AssociationWidget *aw, requiredAssocs) { AssociationLine *assocLine = aw->associationLine(); const QPointF p(assocLine->endPoint()); const qreal tolerance = 18.0; bool drawArc = true; qreal midAngle; if (p.x() < cX - tolerance) { if (p.y() < cY - tolerance) midAngle = 135; else if (p.y() > cY + tolerance) midAngle = 225; else midAngle = 180; } else if (p.x() > cX + tolerance) { if (p.y() < cY - tolerance) midAngle = 45; else if (p.y() > cY + tolerance) midAngle = 315; else midAngle = 0; } else { if (p.y() < cY - tolerance) midAngle = 90; else if (p.y() > cY + tolerance) midAngle = 270; else drawArc = false; } if (drawArc) { // uDebug() << "number of assocs: " << m_Assocs.size() // << ", p: " << p << ", center: " << center // << ", midAngle: " << midAngle << ", angleSpan: " << angleSpan; painter->drawArc(requireArc, 16 * (midAngle - angleSpan/2), 16 * angleSpan); } else { uError() << "socket: assocLine endPoint " << p << " too close to own center" << center; } } } - else - painter->drawEllipse(w/2 - CIRCLE_SIZE/2, 0, CIRCLE_SIZE, CIRCLE_SIZE); } /** * Calculates the size of the object when drawn as a circle. * Only applies when m_umlObject->getBaseType() is ot_Interface. */ QSize ClassifierWidget::calculateAsCircleSize() const { int circleSize = CIRCLE_SIZE; - if (associationWidgetList().size() > 1) - circleSize += SOCKET_INCREMENT; + circleSize += SOCKET_INCREMENT; return QSize(circleSize, circleSize); } void ClassifierWidget::drawAsPackage(QPainter *painter, const QStyleOptionGraphicsItem *option) { Q_UNUSED(option); int w = width(); int h = height(); QFont font = UMLWidget::font(); font.setBold(true); //FIXME italic is true when a package is first created until you click elsewhere, not sure why font.setItalic(false); const QFontMetrics &fm = getFontMetrics(FT_BOLD); const int fontHeight = fm.lineSpacing(); painter->drawRect(0, 0, 50, fontHeight); if (m_umlObject->stereotype() == QLatin1String("subsystem")) { const int fHalf = fontHeight / 2; const int symY = fHalf; const int symX = 38; painter->drawLine(symX, symY, symX, symY + fHalf - 2); // left leg painter->drawLine(symX + 8, symY, symX + 8, symY + fHalf - 2); // right leg painter->drawLine(symX, symY, symX + 8, symY); // waist painter->drawLine(symX + 4, symY, symX + 4, symY - fHalf + 2); // head } painter->drawRect(0, fontHeight - 1, w, h - fontHeight); painter->setPen(textColor()); painter->setFont(font); int lines = 1; QString stereotype = m_umlObject->stereotype(); if (!stereotype.isEmpty()) { painter->drawText(0, fontHeight + defaultMargin, w, fontHeight, Qt::AlignCenter, m_umlObject->stereotype(true)); lines = 2; } painter->drawText(0, (fontHeight*lines) + defaultMargin, w, fontHeight, Qt::AlignCenter, name()); } QSize ClassifierWidget::calculateAsPackageSize() const { const QFontMetrics &fm = getFontMetrics(FT_BOLD_ITALIC); const int fontHeight = fm.lineSpacing(); int lines = 1; int width = fm.width(m_umlObject->name()); int tempWidth = 0; if (!m_umlObject->stereotype().isEmpty()) { tempWidth = fm.width(m_umlObject->stereotype(true)); lines = 2; } if (tempWidth > width) width = tempWidth; width += defaultMargin * 2; if (width < 70) width = 70; // minumin width of 70 int height = (lines*fontHeight) + fontHeight + (defaultMargin * 2); return QSize(width, height); } /** * Auxiliary method for draw() of child classes: * Draw the attributes or operations. * * @param p QPainter to paint to. * @param ot Object type to draw, either ot_Attribute or ot_Operation. * @param sigType Governs details of the member display. * @param x X coordinate at which to draw the texts. * @param y Y coordinate at which text drawing commences. * @param fontHeight The font height. */ void ClassifierWidget::drawMembers(QPainter * painter, UMLObject::ObjectType ot, Uml::SignatureType::Enum sigType, int x, int y, int fontHeight) { UMLClassifier *umlc = classifier(); if (!umlc) { return; } QFont f = UMLWidget::font(); f.setBold(false); UMLClassifierListItemList list = umlc->getFilteredList(ot); painter->setClipping(true); painter->setClipRect(rect()); foreach (UMLClassifierListItem *obj, list) { if (visualProperty(ShowPublicOnly) && obj->visibility() != Uml::Visibility::Public) continue; QString text = obj->toString(sigType, visualProperty(ShowStereotype)); f.setItalic(obj->isAbstract()); f.setUnderline(obj->isStatic()); painter->setFont(f); QFontMetrics fontMetrics(f); painter->drawText(x, y, fontMetrics.size(0, text).width(), fontHeight, Qt::AlignVCenter, text); f.setItalic(false); f.setUnderline(false); painter->setFont(f); y += fontHeight; } painter->setClipping(false); } /** * Override method from UMLWidget in order to additionally check m_pInterfaceName. * * @param p Point to be checked. * * @return 'this' if UMLWidget::onWidget(p) returns non 0; * m_pInterfaceName if m_pName is non NULL and * m_pInterfaceName->onWidget(p) returns non 0; else NULL. */ UMLWidget* ClassifierWidget::onWidget(const QPointF &p) { if (UMLWidget::onWidget(p) != 0) return this; if (getDrawAsCircle() && m_pInterfaceName) { uDebug() << "floatingtext: " << m_pInterfaceName->text(); return m_pInterfaceName->onWidget(p); } return 0; } /** * Reimplement function from UMLWidget. */ UMLWidget* ClassifierWidget::widgetWithID(Uml::ID::Type id) { if (UMLWidget::widgetWithID(id)) return this; if (getDrawAsCircle() && m_pInterfaceName && m_pInterfaceName->widgetWithID(id)) return m_pInterfaceName; return 0; } void ClassifierWidget::setDocumentation(const QString &doc) { WidgetBase::setDocumentation(doc); updateGeometry(); } /** * Sets whether to draw as circle. * Only applies when m_umlObject->getBaseType() is ot_Interface. * * @param drawAsCircle True if widget shall be drawn as circle. */ void ClassifierWidget::setDrawAsCircle(bool drawAsCircle) { setVisualPropertyCmd(DrawAsCircle, drawAsCircle); const int circleSize = CIRCLE_SIZE + SOCKET_INCREMENT; if (drawAsCircle) { setX(x() + (width()/2 - circleSize/2)); setY(y() + (height()/2 - circleSize/2)); setSize(circleSize, circleSize); if (m_pInterfaceName) { m_pInterfaceName->show(); } else { m_pInterfaceName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, name()); m_pInterfaceName->setParentItem(this); m_pInterfaceName->setText(name()); // to get geometry update m_pInterfaceName->setX(circleSize/2 - m_pInterfaceName->width() / 2); m_pInterfaceName->setY(circleSize + SOCKET_INCREMENT); } m_resizable = false; } else { setSize(ClassifierWidget::minimumSize()); setX(x() - (width()/2 - circleSize/2)); setY(y() - (height()/2 - circleSize/2)); if (m_pInterfaceName) m_pInterfaceName->hide(); m_resizable = true; } setChangesShape(drawAsCircle); updateGeometry(); update(); } /** * Returns whether to draw as circle. * Only applies when m_umlObject->getBaseType() is ot_Interface. * * @return True if widget is drawn as circle. */ bool ClassifierWidget::getDrawAsCircle() const { return visualProperty(DrawAsCircle); } /** * Toggles whether to draw as circle. * Only applies when m_umlObject->getBaseType() is ot_Interface. */ void ClassifierWidget::toggleDrawAsCircle() { toggleVisualProperty(DrawAsCircle); updateSignatureTypes(); updateGeometry(); update(); } /** * Changes this classifier from an interface to a class. * Attributes and stereotype visibility is got from the view OptionState. * This widget is also updated. */ void ClassifierWidget::changeToClass() { setBaseType(WidgetBase::wt_Class); m_umlObject->setBaseType(UMLObject::ot_Class); setVisualPropertyCmd(DrawAsCircle, false); const Settings::OptionState& ops = m_scene->optionState(); setVisualProperty(ShowAttributes, ops.classState.showAtts); setVisualProperty(ShowStereotype, ops.classState.showStereoType); updateGeometry(); update(); } /** * Changes this classifier from a class to an interface. * Attributes are hidden and stereotype is shown. * This widget is also updated. */ void ClassifierWidget::changeToInterface() { setBaseType(WidgetBase::wt_Interface); m_umlObject->setBaseType(UMLObject::ot_Interface); setVisualProperty(ShowAttributes, false); setVisualProperty(ShowStereotype, true); updateGeometry(); update(); } /** * Changes this classifier from an "class-or-package" to a package. * This widget is also updated. */ void ClassifierWidget::changeToPackage() { setBaseType(WidgetBase::wt_Package); m_umlObject->setBaseType(UMLObject::ot_Package); setVisualProperty(ShowAttributes, false); setVisualProperty(ShowStereotype, true); updateGeometry(); update(); } /** * Extends base method to adjust also the association of a class * association. * Executes the base method and then, if file isn't loading and the * classifier acts as a class association, the association position is * updated. * TODO: This is never called. * * param x The x-coordinate. * param y The y-coordinate. */ //void ClassifierWidget::adjustAssociations(int x, int y) //{ // DEBUG(DBG_SRC) << "x=" << x << " / y=" << y; // UMLWidget::adjustAssocs(x, y); // if (m_doc->loading() || m_pAssocWidget == 0) { // return; // } // //:TODO: the following is also called from UMLWidgetr::ajdustAssocs(...) // // and then AssociationWidget::widgetMoved(...) // //m_pAssocWidget->computeAssocClassLine(); //} /** * Loads the "classwidget" or "interfacewidget" XML element. */ bool ClassifierWidget::loadFromXMI1(QDomElement & qElement) { if (!UMLWidget::loadFromXMI1(qElement)) { return false; } bool loadShowAttributes = true; if (umlObject() && (umlObject()->isUMLPackage() || umlObject()->isUMLInstance())) { loadShowAttributes = false; } if (loadShowAttributes) { QString showatts = qElement.attribute(QLatin1String("showattributes"), QLatin1String("0")); QString showops = qElement.attribute(QLatin1String("showoperations"), QLatin1String("1")); QString showpubliconly = qElement.attribute(QLatin1String("showpubliconly"), QLatin1String("0")); QString showattsigs = qElement.attribute(QLatin1String("showattsigs"), QLatin1String("600")); QString showopsigs = qElement.attribute(QLatin1String("showopsigs"), QLatin1String("600")); QString showpackage = qElement.attribute(QLatin1String("showpackage"), QLatin1String("0")); QString showscope = qElement.attribute(QLatin1String("showscope"), QLatin1String("0")); QString drawascircle = qElement.attribute(QLatin1String("drawascircle"), QLatin1String("0")); QString showstereotype = qElement.attribute(QLatin1String("showstereotype"), QLatin1String("1")); setVisualPropertyCmd(ShowAttributes, (bool)showatts.toInt()); setVisualPropertyCmd(ShowOperations, (bool)showops.toInt()); setVisualPropertyCmd(ShowPublicOnly, (bool)showpubliconly.toInt()); setVisualPropertyCmd(ShowPackage, (bool)showpackage.toInt()); setVisualPropertyCmd(ShowVisibility, (bool)showscope.toInt()); setVisualPropertyCmd(DrawAsCircle, (bool)drawascircle.toInt()); setVisualPropertyCmd(ShowStereotype, (bool)showstereotype.toInt()); m_attributeSignature = Uml::SignatureType::fromInt(showattsigs.toInt()); m_operationSignature = Uml::SignatureType::fromInt(showopsigs.toInt()); } #ifdef ENABLE_WIDGET_SHOW_DOC QString showDocumentation = qElement.attribute(QLatin1String("showdocumentation"), QLatin1String("0")); setVisualPropertyCmd(ShowDocumentation, (bool)showDocumentation.toInt()); #endif if (!getDrawAsCircle()) return true; // Optional child element: floatingtext QDomNode node = qElement.firstChild(); QDomElement element = node.toElement(); if (!element.isNull()) { QString tag = element.tagName(); if (tag == QLatin1String("floatingtext")) { if (m_pInterfaceName == 0) { m_pInterfaceName = new FloatingTextWidget(m_scene, Uml::TextRole::Floating, name(), Uml::ID::Reserved); m_pInterfaceName->setParentItem(this); } if (!m_pInterfaceName->loadFromXMI1(element)) { // Most likely cause: The FloatingTextWidget is empty. delete m_pInterfaceName; m_pInterfaceName = 0; } else { m_pInterfaceName->activate(); m_pInterfaceName->update(); } } else { uError() << "unknown tag " << tag; } } return true; } /** * Creates the "classwidget" or "interfacewidget" XML element. */ void ClassifierWidget::saveToXMI1(QDomDocument & qDoc, QDomElement & qElement) { QDomElement conceptElement; bool saveShowAttributes = true; UMLClassifier *umlc = classifier(); if (umlObject() && umlObject()->baseType() == UMLObject::ot_Package) { conceptElement = qDoc.createElement(QLatin1String("packagewidget")); saveShowAttributes = false; } else if(umlObject()->baseType() == UMLObject::ot_Instance) { conceptElement = qDoc.createElement(QLatin1String("instancewidget")); saveShowAttributes = false; } else if (umlc && umlc->isInterface()) { conceptElement = qDoc.createElement(QLatin1String("interfacewidget")); } else { conceptElement = qDoc.createElement(QLatin1String("classwidget")); } UMLWidget::saveToXMI1(qDoc, conceptElement); if (saveShowAttributes) { conceptElement.setAttribute(QLatin1String("showoperations"), visualProperty(ShowOperations)); conceptElement.setAttribute(QLatin1String("showpubliconly"), visualProperty(ShowPublicOnly)); conceptElement.setAttribute(QLatin1String("showopsigs"), m_operationSignature); conceptElement.setAttribute(QLatin1String("showpackage"), visualProperty(ShowPackage)); conceptElement.setAttribute(QLatin1String("showscope"), visualProperty(ShowVisibility)); conceptElement.setAttribute(QLatin1String("showattributes"), visualProperty(ShowAttributes)); conceptElement.setAttribute(QLatin1String("showattsigs"), m_attributeSignature); conceptElement.setAttribute(QLatin1String("showstereotype"), visualProperty(ShowStereotype)); } #ifdef ENABLE_WIDGET_SHOW_DOC conceptElement.setAttribute(QLatin1String("showdocumentation"),visualProperty(ShowDocumentation)); #endif if (umlc && (umlc->isInterface() || umlc->isAbstract())) { conceptElement.setAttribute(QLatin1String("drawascircle"), visualProperty(DrawAsCircle)); if (visualProperty(DrawAsCircle) && m_pInterfaceName) { m_pInterfaceName->saveToXMI1(qDoc, conceptElement); } } qElement.appendChild(conceptElement); } /** * Will be called when a menu selection has been made from the * popup menu. * * @param action The action that has been selected. */ void ClassifierWidget::slotMenuSelection(QAction* action) { ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action); switch (sel) { case ListPopupMenu::mt_Attribute: case ListPopupMenu::mt_Operation: case ListPopupMenu::mt_Template: case ListPopupMenu::mt_InstanceAttribute: { UMLObject::ObjectType ot = ListPopupMenu::convert_MT_OT(sel); UMLClassifier *umlc = classifier(); if (!umlc) { uError() << "Internal error - classifier() returns NULL"; return; } if (Object_Factory::createChildObject(umlc, ot)) { updateGeometry(); update(); UMLApp::app()->document()->setModified(); } break; } case ListPopupMenu::mt_Class: case ListPopupMenu::mt_Datatype: case ListPopupMenu::mt_Enum: case ListPopupMenu::mt_Interface: { UMLObject::ObjectType ot = ListPopupMenu::convert_MT_OT(sel); UMLClassifier *umlc = classifier(); if (!umlc) { uError() << "Internal error - classifier() returns NULL"; return; } umlScene()->setCreateObject(true); if (Object_Factory::createUMLObject(ot, QString(), umlc)) { updateGeometry(); update(); UMLApp::app()->document()->setModified(); } break; } case ListPopupMenu::mt_Show_Operations: toggleVisualProperty(ShowOperations); break; case ListPopupMenu::mt_Show_Attributes: toggleVisualProperty(ShowAttributes); break; case ListPopupMenu::mt_Show_Documentation: toggleVisualProperty(ShowDocumentation); break; case ListPopupMenu::mt_Show_Public_Only: toggleVisualProperty(ShowPublicOnly); break; case ListPopupMenu::mt_Show_Operation_Signature: toggleVisualProperty(ShowOperationSignature); break; case ListPopupMenu::mt_Show_Attribute_Signature: toggleVisualProperty(ShowAttributeSignature); break; case ListPopupMenu::mt_Visibility: toggleVisualProperty(ShowVisibility); break; case ListPopupMenu::mt_Show_Packages: toggleVisualProperty(ShowPackage); break; case ListPopupMenu::mt_Show_Stereotypes: toggleVisualProperty(ShowStereotype); break; case ListPopupMenu::mt_DrawAsCircle: toggleVisualProperty(DrawAsCircle); break; case ListPopupMenu::mt_ChangeToClass: changeToClass(); break; case ListPopupMenu::mt_ChangeToInterface: changeToInterface(); break; case ListPopupMenu::mt_ChangeToPackage: changeToPackage(); break; default: UMLWidget::slotMenuSelection(action); break; } } /** * Slot to show/hide attributes based on \a state. */ void ClassifierWidget::slotShowAttributes(bool state) { setVisualProperty(ShowAttributes, state); } /** * Slot to show/hide operations based on \a state. */ void ClassifierWidget::slotShowOperations(bool state) { setVisualProperty(ShowOperations, state); } /** * Show a properties dialog for a ClassifierWidget */ bool ClassifierWidget::showPropertiesDialog() { if (UMLWidget::showPropertiesDialog()) { if (isInterfaceWidget() && visualProperty(DrawAsCircle)) m_pInterfaceName->setText(name()); return true; } return false; } /** * Overriding the method from WidgetBase because we need to do * something extra in case this ClassifierWidget represents * an interface widget used in component diagrams. */ void ClassifierWidget::setUMLObject(UMLObject *obj) { WidgetBase::setUMLObject(obj); if (isInterfaceWidget() && visualProperty(DrawAsCircle)) m_pInterfaceName->setText(obj->name()); }